mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
feat: allow bypassing current CORS magic based on template config (#18706)
Solves https://github.com/coder/coder/issues/15096 This is a slight rework/refactor of the earlier PRs from @dannykopping and @Emyrk: - https://github.com/coder/coder/pull/15669 - https://github.com/coder/coder/pull/15684 - https://github.com/coder/coder/pull/17596 Rather than having a per-app CORS behaviour setting and additionally a template level setting for ports, this PR adds a single template level CORS behaviour setting that is then used by all apps/ports for workspaces created from that template. The main changes are in `proxy.go` and `request.go` to: a) get the CORS behaviour setting from the template b) have `HandleSubdomain` bypass the CORS middleware handler if the selected behaviour is `passthru` c) in `proxyWorkspaceApp`, do not modify the response if the selected behaviour is `passthru` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for configuring CORS behavior ("simple" or "passthru") at the template level for all shared ports. * Introduced a new "CORS Behavior" setting in the template creation and settings forms. * API endpoints and responses now include the optional `cors_behavior` property for templates. * Workspace apps and proxy now honor the specified CORS behavior, enabling conditional CORS middleware application. * Enhanced workspace app tests with comprehensive scenarios covering CORS behaviors and authentication states. * **Bug Fixes** * None. * **Documentation** * Updated API and admin documentation to describe the new `cors_behavior` property and its usage. * Added examples and schema references for CORS behavior in relevant API docs. * **Tests** * Extended automated tests to cover different CORS behavior scenarios for templates and workspace apps. * **Chores** * Updated audit logging to track changes to the `cors_behavior` field on templates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Callum Styan <callumstyan@gmail.com>
This commit is contained in:
@@ -1462,6 +1462,7 @@ func (s *MethodTestSuite) TestTemplate() {
|
||||
Provisioner: "echo",
|
||||
OrganizationID: orgID,
|
||||
MaxPortSharingLevel: database.AppSharingLevelOwner,
|
||||
CorsBehavior: database.CorsBehaviorSimple,
|
||||
}).Asserts(rbac.ResourceTemplate.InOrg(orgID), policy.ActionCreate)
|
||||
}))
|
||||
s.Run("InsertTemplateVersion", s.Subtest(func(db database.Store, check *expects) {
|
||||
@@ -1582,6 +1583,7 @@ func (s *MethodTestSuite) TestTemplate() {
|
||||
check.Args(database.UpdateTemplateMetaByIDParams{
|
||||
ID: t1.ID,
|
||||
MaxPortSharingLevel: "owner",
|
||||
CorsBehavior: database.CorsBehaviorSimple,
|
||||
}).Asserts(t1, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("UpdateTemplateVersionByID", s.Subtest(func(db database.Store, check *expects) {
|
||||
|
||||
@@ -148,6 +148,7 @@ func Template(t testing.TB, db database.Store, seed database.Template) database.
|
||||
AllowUserCancelWorkspaceJobs: seed.AllowUserCancelWorkspaceJobs,
|
||||
MaxPortSharingLevel: takeFirst(seed.MaxPortSharingLevel, database.AppSharingLevelOwner),
|
||||
UseClassicParameterFlow: takeFirst(seed.UseClassicParameterFlow, false),
|
||||
CorsBehavior: takeFirst(seed.CorsBehavior, database.CorsBehaviorSimple),
|
||||
})
|
||||
require.NoError(t, err, "insert template")
|
||||
|
||||
|
||||
Generated
+8
-1
@@ -73,6 +73,11 @@ CREATE TYPE connection_type AS ENUM (
|
||||
'port_forwarding'
|
||||
);
|
||||
|
||||
CREATE TYPE cors_behavior AS ENUM (
|
||||
'simple',
|
||||
'passthru'
|
||||
);
|
||||
|
||||
CREATE TYPE crypto_key_feature AS ENUM (
|
||||
'workspace_apps_token',
|
||||
'workspace_apps_api_key',
|
||||
@@ -1750,7 +1755,8 @@ CREATE TABLE templates (
|
||||
deprecated text DEFAULT ''::text NOT NULL,
|
||||
activity_bump bigint DEFAULT '3600000000000'::bigint NOT NULL,
|
||||
max_port_sharing_level app_sharing_level DEFAULT 'owner'::app_sharing_level NOT NULL,
|
||||
use_classic_parameter_flow boolean DEFAULT false NOT NULL
|
||||
use_classic_parameter_flow boolean DEFAULT false NOT NULL,
|
||||
cors_behavior cors_behavior DEFAULT 'simple'::cors_behavior NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.';
|
||||
@@ -1803,6 +1809,7 @@ CREATE VIEW template_with_names AS
|
||||
templates.activity_bump,
|
||||
templates.max_port_sharing_level,
|
||||
templates.use_classic_parameter_flow,
|
||||
templates.cors_behavior,
|
||||
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
|
||||
COALESCE(visible_users.username, ''::text) AS created_by_username,
|
||||
COALESCE(visible_users.name, ''::text) AS created_by_name,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
DROP VIEW IF EXISTS template_with_names;
|
||||
CREATE VIEW template_with_names AS
|
||||
SELECT templates.id,
|
||||
templates.created_at,
|
||||
templates.updated_at,
|
||||
templates.organization_id,
|
||||
templates.deleted,
|
||||
templates.name,
|
||||
templates.provisioner,
|
||||
templates.active_version_id,
|
||||
templates.description,
|
||||
templates.default_ttl,
|
||||
templates.created_by,
|
||||
templates.icon,
|
||||
templates.user_acl,
|
||||
templates.group_acl,
|
||||
templates.display_name,
|
||||
templates.allow_user_cancel_workspace_jobs,
|
||||
templates.allow_user_autostart,
|
||||
templates.allow_user_autostop,
|
||||
templates.failure_ttl,
|
||||
templates.time_til_dormant,
|
||||
templates.time_til_dormant_autodelete,
|
||||
templates.autostop_requirement_days_of_week,
|
||||
templates.autostop_requirement_weeks,
|
||||
templates.autostart_block_days_of_week,
|
||||
templates.require_active_version,
|
||||
templates.deprecated,
|
||||
templates.activity_bump,
|
||||
templates.max_port_sharing_level,
|
||||
templates.use_classic_parameter_flow,
|
||||
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
|
||||
COALESCE(visible_users.username, ''::text) AS created_by_username,
|
||||
COALESCE(visible_users.name, ''::text) AS created_by_name,
|
||||
COALESCE(organizations.name, ''::text) AS organization_name,
|
||||
COALESCE(organizations.display_name, ''::text) AS organization_display_name,
|
||||
COALESCE(organizations.icon, ''::text) AS organization_icon
|
||||
FROM ((templates
|
||||
LEFT JOIN visible_users ON ((templates.created_by = visible_users.id)))
|
||||
LEFT JOIN organizations ON ((templates.organization_id = organizations.id)));
|
||||
|
||||
COMMENT ON VIEW template_with_names IS 'Joins in the display name information such as username, avatar, and organization name.';
|
||||
|
||||
ALTER TABLE templates DROP COLUMN cors_behavior;
|
||||
|
||||
DROP TYPE IF EXISTS cors_behavior;
|
||||
@@ -0,0 +1,52 @@
|
||||
CREATE TYPE cors_behavior AS ENUM (
|
||||
'simple',
|
||||
'passthru'
|
||||
);
|
||||
|
||||
ALTER TABLE templates
|
||||
ADD COLUMN cors_behavior cors_behavior NOT NULL DEFAULT 'simple'::cors_behavior;
|
||||
|
||||
-- Update the template_with_users view by recreating it.
|
||||
DROP VIEW IF EXISTS template_with_names;
|
||||
CREATE VIEW template_with_names AS
|
||||
SELECT templates.id,
|
||||
templates.created_at,
|
||||
templates.updated_at,
|
||||
templates.organization_id,
|
||||
templates.deleted,
|
||||
templates.name,
|
||||
templates.provisioner,
|
||||
templates.active_version_id,
|
||||
templates.description,
|
||||
templates.default_ttl,
|
||||
templates.created_by,
|
||||
templates.icon,
|
||||
templates.user_acl,
|
||||
templates.group_acl,
|
||||
templates.display_name,
|
||||
templates.allow_user_cancel_workspace_jobs,
|
||||
templates.allow_user_autostart,
|
||||
templates.allow_user_autostop,
|
||||
templates.failure_ttl,
|
||||
templates.time_til_dormant,
|
||||
templates.time_til_dormant_autodelete,
|
||||
templates.autostop_requirement_days_of_week,
|
||||
templates.autostop_requirement_weeks,
|
||||
templates.autostart_block_days_of_week,
|
||||
templates.require_active_version,
|
||||
templates.deprecated,
|
||||
templates.activity_bump,
|
||||
templates.max_port_sharing_level,
|
||||
templates.use_classic_parameter_flow,
|
||||
templates.cors_behavior, -- <--- adding this column
|
||||
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
|
||||
COALESCE(visible_users.username, ''::text) AS created_by_username,
|
||||
COALESCE(visible_users.name, ''::text) AS created_by_name,
|
||||
COALESCE(organizations.name, ''::text) AS organization_name,
|
||||
COALESCE(organizations.display_name, ''::text) AS organization_display_name,
|
||||
COALESCE(organizations.icon, ''::text) AS organization_icon
|
||||
FROM ((templates
|
||||
LEFT JOIN visible_users ON ((templates.created_by = visible_users.id)))
|
||||
LEFT JOIN organizations ON ((templates.organization_id = organizations.id)));
|
||||
|
||||
COMMENT ON VIEW template_with_names IS 'Joins in the display name information such as username, avatar, and organization name.';
|
||||
@@ -120,6 +120,7 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate
|
||||
&i.ActivityBump,
|
||||
&i.MaxPortSharingLevel,
|
||||
&i.UseClassicParameterFlow,
|
||||
&i.CorsBehavior,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
&i.CreatedByName,
|
||||
|
||||
@@ -559,6 +559,64 @@ func AllConnectionTypeValues() []ConnectionType {
|
||||
}
|
||||
}
|
||||
|
||||
type CorsBehavior string
|
||||
|
||||
const (
|
||||
CorsBehaviorSimple CorsBehavior = "simple"
|
||||
CorsBehaviorPassthru CorsBehavior = "passthru"
|
||||
)
|
||||
|
||||
func (e *CorsBehavior) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = CorsBehavior(s)
|
||||
case string:
|
||||
*e = CorsBehavior(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for CorsBehavior: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullCorsBehavior struct {
|
||||
CorsBehavior CorsBehavior `json:"cors_behavior"`
|
||||
Valid bool `json:"valid"` // Valid is true if CorsBehavior is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullCorsBehavior) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.CorsBehavior, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.CorsBehavior.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullCorsBehavior) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.CorsBehavior), nil
|
||||
}
|
||||
|
||||
func (e CorsBehavior) Valid() bool {
|
||||
switch e {
|
||||
case CorsBehaviorSimple,
|
||||
CorsBehaviorPassthru:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AllCorsBehaviorValues() []CorsBehavior {
|
||||
return []CorsBehavior{
|
||||
CorsBehaviorSimple,
|
||||
CorsBehaviorPassthru,
|
||||
}
|
||||
}
|
||||
|
||||
type CryptoKeyFeature string
|
||||
|
||||
const (
|
||||
@@ -3474,6 +3532,7 @@ type Template struct {
|
||||
ActivityBump int64 `db:"activity_bump" json:"activity_bump"`
|
||||
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
|
||||
CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"`
|
||||
CreatedByUsername string `db:"created_by_username" json:"created_by_username"`
|
||||
CreatedByName string `db:"created_by_name" json:"created_by_name"`
|
||||
@@ -3521,7 +3580,8 @@ type TemplateTable struct {
|
||||
ActivityBump int64 `db:"activity_bump" json:"activity_bump"`
|
||||
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
|
||||
// Determines whether to default to the dynamic parameter creation flow for this template or continue using the legacy classic parameter creation flow.This is a template wide setting, the template admin can revert to the classic flow if there are any issues. An escape hatch is required, as workspace creation is a core workflow and cannot break. This column will be removed when the dynamic parameter creation flow is stable.
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
|
||||
}
|
||||
|
||||
// Records aggregated usage statistics for templates/users. All usage is rounded up to the nearest minute.
|
||||
|
||||
@@ -11768,7 +11768,7 @@ func (q *sqlQuerier) GetTemplateAverageBuildTime(ctx context.Context, arg GetTem
|
||||
|
||||
const getTemplateByID = `-- name: GetTemplateByID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, created_by_avatar_url, created_by_username, created_by_name, organization_name, organization_display_name, organization_icon
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, cors_behavior, created_by_avatar_url, created_by_username, created_by_name, organization_name, organization_display_name, organization_icon
|
||||
FROM
|
||||
template_with_names
|
||||
WHERE
|
||||
@@ -11810,6 +11810,7 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat
|
||||
&i.ActivityBump,
|
||||
&i.MaxPortSharingLevel,
|
||||
&i.UseClassicParameterFlow,
|
||||
&i.CorsBehavior,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
&i.CreatedByName,
|
||||
@@ -11822,7 +11823,7 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat
|
||||
|
||||
const getTemplateByOrganizationAndName = `-- name: GetTemplateByOrganizationAndName :one
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, created_by_avatar_url, created_by_username, created_by_name, organization_name, organization_display_name, organization_icon
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, cors_behavior, created_by_avatar_url, created_by_username, created_by_name, organization_name, organization_display_name, organization_icon
|
||||
FROM
|
||||
template_with_names AS templates
|
||||
WHERE
|
||||
@@ -11872,6 +11873,7 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G
|
||||
&i.ActivityBump,
|
||||
&i.MaxPortSharingLevel,
|
||||
&i.UseClassicParameterFlow,
|
||||
&i.CorsBehavior,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
&i.CreatedByName,
|
||||
@@ -11883,7 +11885,7 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G
|
||||
}
|
||||
|
||||
const getTemplates = `-- name: GetTemplates :many
|
||||
SELECT id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, created_by_avatar_url, created_by_username, created_by_name, organization_name, organization_display_name, organization_icon FROM template_with_names AS templates
|
||||
SELECT id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, cors_behavior, created_by_avatar_url, created_by_username, created_by_name, organization_name, organization_display_name, organization_icon FROM template_with_names AS templates
|
||||
ORDER BY (name, id) ASC
|
||||
`
|
||||
|
||||
@@ -11926,6 +11928,7 @@ func (q *sqlQuerier) GetTemplates(ctx context.Context) ([]Template, error) {
|
||||
&i.ActivityBump,
|
||||
&i.MaxPortSharingLevel,
|
||||
&i.UseClassicParameterFlow,
|
||||
&i.CorsBehavior,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
&i.CreatedByName,
|
||||
@@ -11948,7 +11951,7 @@ func (q *sqlQuerier) GetTemplates(ctx context.Context) ([]Template, error) {
|
||||
|
||||
const getTemplatesWithFilter = `-- name: GetTemplatesWithFilter :many
|
||||
SELECT
|
||||
t.id, t.created_at, t.updated_at, t.organization_id, t.deleted, t.name, t.provisioner, t.active_version_id, t.description, t.default_ttl, t.created_by, t.icon, t.user_acl, t.group_acl, t.display_name, t.allow_user_cancel_workspace_jobs, t.allow_user_autostart, t.allow_user_autostop, t.failure_ttl, t.time_til_dormant, t.time_til_dormant_autodelete, t.autostop_requirement_days_of_week, t.autostop_requirement_weeks, t.autostart_block_days_of_week, t.require_active_version, t.deprecated, t.activity_bump, t.max_port_sharing_level, t.use_classic_parameter_flow, t.created_by_avatar_url, t.created_by_username, t.created_by_name, t.organization_name, t.organization_display_name, t.organization_icon
|
||||
t.id, t.created_at, t.updated_at, t.organization_id, t.deleted, t.name, t.provisioner, t.active_version_id, t.description, t.default_ttl, t.created_by, t.icon, t.user_acl, t.group_acl, t.display_name, t.allow_user_cancel_workspace_jobs, t.allow_user_autostart, t.allow_user_autostop, t.failure_ttl, t.time_til_dormant, t.time_til_dormant_autodelete, t.autostop_requirement_days_of_week, t.autostop_requirement_weeks, t.autostart_block_days_of_week, t.require_active_version, t.deprecated, t.activity_bump, t.max_port_sharing_level, t.use_classic_parameter_flow, t.cors_behavior, t.created_by_avatar_url, t.created_by_username, t.created_by_name, t.organization_name, t.organization_display_name, t.organization_icon
|
||||
FROM
|
||||
template_with_names AS t
|
||||
LEFT JOIN
|
||||
@@ -12059,6 +12062,7 @@ func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplate
|
||||
&i.ActivityBump,
|
||||
&i.MaxPortSharingLevel,
|
||||
&i.UseClassicParameterFlow,
|
||||
&i.CorsBehavior,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
&i.CreatedByName,
|
||||
@@ -12097,10 +12101,11 @@ INSERT INTO
|
||||
display_name,
|
||||
allow_user_cancel_workspace_jobs,
|
||||
max_port_sharing_level,
|
||||
use_classic_parameter_flow
|
||||
use_classic_parameter_flow,
|
||||
cors_behavior
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
|
||||
`
|
||||
|
||||
type InsertTemplateParams struct {
|
||||
@@ -12120,6 +12125,7 @@ type InsertTemplateParams struct {
|
||||
AllowUserCancelWorkspaceJobs bool `db:"allow_user_cancel_workspace_jobs" json:"allow_user_cancel_workspace_jobs"`
|
||||
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParams) error {
|
||||
@@ -12140,6 +12146,7 @@ func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParam
|
||||
arg.AllowUserCancelWorkspaceJobs,
|
||||
arg.MaxPortSharingLevel,
|
||||
arg.UseClassicParameterFlow,
|
||||
arg.CorsBehavior,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -12240,7 +12247,8 @@ SET
|
||||
allow_user_cancel_workspace_jobs = $7,
|
||||
group_acl = $8,
|
||||
max_port_sharing_level = $9,
|
||||
use_classic_parameter_flow = $10
|
||||
use_classic_parameter_flow = $10,
|
||||
cors_behavior = $11
|
||||
WHERE
|
||||
id = $1
|
||||
`
|
||||
@@ -12256,6 +12264,7 @@ type UpdateTemplateMetaByIDParams struct {
|
||||
GroupACL TemplateACL `db:"group_acl" json:"group_acl"`
|
||||
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateTemplateMetaByID(ctx context.Context, arg UpdateTemplateMetaByIDParams) error {
|
||||
@@ -12270,6 +12279,7 @@ func (q *sqlQuerier) UpdateTemplateMetaByID(ctx context.Context, arg UpdateTempl
|
||||
arg.GroupACL,
|
||||
arg.MaxPortSharingLevel,
|
||||
arg.UseClassicParameterFlow,
|
||||
arg.CorsBehavior,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -19911,7 +19921,7 @@ LEFT JOIN LATERAL (
|
||||
) latest_build ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, allow_user_autostart, allow_user_autostop, failure_ttl, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, autostart_block_days_of_week, require_active_version, deprecated, activity_bump, max_port_sharing_level, use_classic_parameter_flow, cors_behavior
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
|
||||
@@ -99,10 +99,11 @@ INSERT INTO
|
||||
display_name,
|
||||
allow_user_cancel_workspace_jobs,
|
||||
max_port_sharing_level,
|
||||
use_classic_parameter_flow
|
||||
use_classic_parameter_flow,
|
||||
cors_behavior
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17);
|
||||
|
||||
-- name: UpdateTemplateActiveVersionByID :exec
|
||||
UPDATE
|
||||
@@ -134,7 +135,8 @@ SET
|
||||
allow_user_cancel_workspace_jobs = $7,
|
||||
group_acl = $8,
|
||||
max_port_sharing_level = $9,
|
||||
use_classic_parameter_flow = $10
|
||||
use_classic_parameter_flow = $10,
|
||||
cors_behavior = $11
|
||||
WHERE
|
||||
id = $1
|
||||
;
|
||||
|
||||
@@ -150,6 +150,7 @@ sql:
|
||||
has_ai_task: HasAITask
|
||||
ai_task_sidebar_app_id: AITaskSidebarAppID
|
||||
latest_build_has_ai_task: LatestBuildHasAITask
|
||||
cors_behavior: CorsBehavior
|
||||
rules:
|
||||
- name: do-not-use-public-schema-in-queries
|
||||
message: "do not use public schema in queries"
|
||||
|
||||
Reference in New Issue
Block a user