Skip to content

Commit 5b2b80e

Browse files
committed
fix broken build and tests
Signed-off-by: Callum Styan <callumstyan@gmail.com>
1 parent b2e9c6d commit 5b2b80e

File tree

16 files changed

+77
-36
lines changed

16 files changed

+77
-36
lines changed

coderd/apidoc/docs.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ func (s *MethodTestSuite) TestTemplate() {
13481348
Provisioner: "echo",
13491349
OrganizationID: orgID,
13501350
MaxPortSharingLevel: database.AppSharingLevelOwner,
1351+
CorsBehavior: database.CorsBehaviorSimple,
13511352
}).Asserts(rbac.ResourceTemplate.InOrg(orgID), policy.ActionCreate)
13521353
}))
13531354
s.Run("InsertTemplateVersion", s.Subtest(func(db database.Store, check *expects) {
@@ -1468,6 +1469,7 @@ func (s *MethodTestSuite) TestTemplate() {
14681469
check.Args(database.UpdateTemplateMetaByIDParams{
14691470
ID: t1.ID,
14701471
MaxPortSharingLevel: "owner",
1472+
CorsBehavior: database.CorsBehaviorSimple,
14711473
}).Asserts(t1, policy.ActionUpdate)
14721474
}))
14731475
s.Run("UpdateTemplateVersionByID", s.Subtest(func(db database.Store, check *expects) {

coderd/database/migrations/000347_template_level_cors.down.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ CREATE VIEW template_with_names AS
2828
templates.deprecated,
2929
templates.activity_bump,
3030
templates.max_port_sharing_level,
31-
templates.use_classic_parameter_flow,
31+
templates.use_classic_parameter_flow,
3232
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
3333
COALESCE(visible_users.username, ''::text) AS created_by_username,
3434
COALESCE(visible_users.name, ''::text) AS created_by_name,
@@ -42,3 +42,5 @@ CREATE VIEW template_with_names AS
4242
COMMENT ON VIEW template_with_names IS 'Joins in the display name information such as username, avatar, and organization name.';
4343

4444
ALTER TABLE templates DROP COLUMN cors_behavior;
45+
46+
DROP TYPE IF EXISTS cors_behavior;

coderd/prometheusmetrics/prometheusmetrics_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ func insertTemplates(t *testing.T, db database.Store, u database.User, org datab
744744
MaxPortSharingLevel: database.AppSharingLevelAuthenticated,
745745
CreatedBy: u.ID,
746746
OrganizationID: org.ID,
747+
CorsBehavior: database.CorsBehaviorSimple,
747748
}))
748749
pj := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{})
749750

@@ -763,6 +764,7 @@ func insertTemplates(t *testing.T, db database.Store, u database.User, org datab
763764
MaxPortSharingLevel: database.AppSharingLevelAuthenticated,
764765
CreatedBy: u.ID,
765766
OrganizationID: org.ID,
767+
CorsBehavior: database.CorsBehaviorSimple,
766768
}))
767769

768770
require.NoError(t, db.InsertTemplateVersion(context.Background(), database.InsertTemplateVersionParams{

coderd/templates.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -352,12 +352,12 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
352352
}
353353
}
354354

355-
if createTemplate.CORSBehavior != nil {
356-
val := codersdk.CORSBehavior(*createTemplate.CORSBehavior)
355+
if createTemplate.CORSBehavior != nil && *createTemplate.CORSBehavior != "" {
356+
val := createTemplate.CORSBehavior
357357
if err := val.Validate(); err != nil {
358358
validErrs = append(validErrs, codersdk.ValidationError{Field: "cors_behavior", Detail: err.Error()})
359359
} else {
360-
corsBehavior = database.CorsBehavior(val)
360+
corsBehavior = database.CorsBehavior(*val)
361361
}
362362
}
363363

@@ -664,7 +664,6 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
664664
validErrs []codersdk.ValidationError
665665
autostopRequirementDaysOfWeekParsed uint8
666666
autostartRequirementDaysOfWeekParsed uint8
667-
corsBehavior database.CorsBehavior
668667
)
669668
if req.DefaultTTLMillis < 0 {
670669
validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be a positive integer."})
@@ -737,12 +736,13 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
737736
}
738737
}
739738

740-
if req.CORSBehavior != nil {
741-
val := codersdk.CORSBehavior(*req.CORSBehavior)
739+
corsBehavior := template.CorsBehavior
740+
if req.CORSBehavior != nil && *req.CORSBehavior != "" {
741+
val := req.CORSBehavior
742742
if err := val.Validate(); err != nil {
743743
validErrs = append(validErrs, codersdk.ValidationError{Field: "cors_behavior", Detail: err.Error()})
744744
} else {
745-
corsBehavior = database.CorsBehavior(val)
745+
corsBehavior = database.CorsBehavior(*val)
746746
}
747747
}
748748

@@ -1107,7 +1107,7 @@ func (api *API) convertTemplate(
11071107
DeprecationMessage: templateAccessControl.Deprecated,
11081108
MaxPortShareLevel: maxPortShareLevel,
11091109
UseClassicParameterFlow: template.UseClassicParameterFlow,
1110-
CORSBehavior: (*codersdk.CORSBehavior)(&template.CorsBehavior),
1110+
CORSBehavior: codersdk.CORSBehavior(template.CorsBehavior),
11111111
}
11121112
}
11131113

coderd/workspaceapps/db.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ func (p *DBTokenProvider) Issue(ctx context.Context, rw http.ResponseWriter, r *
152152
if dbReq.AppURL != nil {
153153
token.AppURL = dbReq.AppURL.String()
154154
}
155+
token.CORSBehavior = codersdk.CORSBehavior(dbReq.CorsBehavior)
155156

156157
// Verify the user has access to the app.
157158
authed, warnings, err := p.authorizeRequest(r.Context(), authz, dbReq)

coderd/workspaceapps/db_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,12 @@ func Test_ResolveRequest(t *testing.T) {
318318
RegisteredClaims: jwtutils.RegisteredClaims{
319319
Expiry: jwt.NewNumericDate(token.Expiry.Time()),
320320
},
321-
Request: req,
322-
UserID: me.ID,
323-
WorkspaceID: workspace.ID,
324-
AgentID: agentID,
325-
AppURL: appURL,
321+
Request: req,
322+
UserID: me.ID,
323+
WorkspaceID: workspace.ID,
324+
AgentID: agentID,
325+
AppURL: appURL,
326+
CORSBehavior: codersdk.CORSBehaviorSimple,
326327
}, token)
327328
require.NotZero(t, token.Expiry)
328329
require.WithinDuration(t, time.Now().Add(workspaceapps.DefaultTokenExpiry), token.Expiry.Time(), time.Minute)

coderd/workspaceapps/request.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ type databaseRequest struct {
204204
// AppSharingLevel is the sharing level of the app. This is forced to be set
205205
// to AppSharingLevelOwner if the access method is terminal.
206206
AppSharingLevel database.AppSharingLevel
207+
// CorsBehavior is set at the template level for all apps/ports in a workspace, and can
208+
// either be the current CORS middleware 'simple' or bypass the cors middleware with 'passthru'.
209+
CorsBehavior database.CorsBehavior
207210
}
208211

209212
// getDatabase does queries to get the owner user, workspace and agent
@@ -296,14 +299,14 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
296299
// First check if it's a port-based URL with an optional "s" suffix for HTTPS.
297300
potentialPortStr = strings.TrimSuffix(r.AppSlugOrPort, "s")
298301
portUint, portUintErr = strconv.ParseUint(potentialPortStr, 10, 16)
299-
// corsBehavior database.CorsBehavior
302+
corsBehavior database.CorsBehavior
300303
)
301304

302-
// tmpl, err := db.GetTemplateByID(ctx, workspace.TemplateID)
303-
// if err != nil {
304-
// return nil, xerrors.Errorf("get template %q: %w", workspace.TemplateID, err)
305-
// }
306-
// corsBehavior = tmpl.CorsBehavior
305+
tmpl, err := db.GetTemplateByID(ctx, workspace.TemplateID)
306+
if err != nil {
307+
return nil, xerrors.Errorf("get template %q: %w", workspace.TemplateID, err)
308+
}
309+
corsBehavior = tmpl.CorsBehavior
307310
//nolint:nestif
308311
if portUintErr == nil {
309312
protocol := "http"
@@ -424,7 +427,7 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
424427
App: app,
425428
AppURL: appURLParsed,
426429
AppSharingLevel: appSharingLevel,
427-
// CorsBehavior: corsBehavior,
430+
CorsBehavior: corsBehavior,
428431
}, nil
429432
}
430433

coderd/workspaceapps/token.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ type SignedToken struct {
2222
// Request details.
2323
Request `json:"request"`
2424

25-
UserID uuid.UUID `json:"user_id"`
26-
WorkspaceID uuid.UUID `json:"workspace_id"`
27-
AgentID uuid.UUID `json:"agent_id"`
28-
AppURL string `json:"app_url"`
25+
UserID uuid.UUID `json:"user_id"`
26+
WorkspaceID uuid.UUID `json:"workspace_id"`
27+
AgentID uuid.UUID `json:"agent_id"`
28+
AppURL string `json:"app_url"`
29+
CORSBehavior codersdk.CORSBehavior `json:"cors_behavior"`
2930
}
3031

3132
// MatchesRequest returns true if the token matches the request. Any token that

codersdk/cors_behavior.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package codersdk
22

3-
import "golang.org/x/xerrors"
3+
import (
4+
"golang.org/x/xerrors"
5+
)
46

57
type CORSBehavior string
68

79
const (
8-
AppCORSBehaviorSimple CORSBehavior = "simple"
9-
AppCORSBehaviorPassthru CORSBehavior = "passthru"
10+
CORSBehaviorSimple CORSBehavior = "simple"
11+
CORSBehaviorPassthru CORSBehavior = "passthru"
1012
)
1113

1214
func (c CORSBehavior) Validate() error {
13-
if c != AppCORSBehaviorSimple && c != AppCORSBehaviorPassthru {
15+
if c != CORSBehaviorSimple && c != CORSBehaviorPassthru {
1416
return xerrors.New("Invalid CORS behavior.")
1517
}
1618
return nil

codersdk/templates.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ type Template struct {
6161
// template version.
6262
RequireActiveVersion bool `json:"require_active_version"`
6363
MaxPortShareLevel WorkspaceAgentPortShareLevel `json:"max_port_share_level"`
64-
CORSBehavior *CORSBehavior `json:"cors_behavior"`
64+
CORSBehavior CORSBehavior `json:"cors_behavior"`
6565

6666
UseClassicParameterFlow bool `json:"use_classic_parameter_flow"`
6767
}
@@ -253,7 +253,7 @@ type UpdateTemplateMeta struct {
253253
// of the template.
254254
DisableEveryoneGroupAccess bool `json:"disable_everyone_group_access"`
255255
MaxPortShareLevel *WorkspaceAgentPortShareLevel `json:"max_port_share_level,omitempty"`
256-
CORSBehavior *CORSBehavior `json:"cors_behavior"`
256+
CORSBehavior *CORSBehavior `json:"cors_behavior,omitempty"`
257257
// UseClassicParameterFlow is a flag that switches the default behavior to use the classic
258258
// parameter flow when creating a workspace. This only affects deployments with the experiment
259259
// "dynamic-parameters" enabled. This setting will live for a period after the experiment is

site/src/api/typesGenerated.ts

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import FormHelperText from "@mui/material/FormHelperText";
44
import MenuItem from "@mui/material/MenuItem";
55
import TextField from "@mui/material/TextField";
66
import {
7+
CORSBehaviors,
78
type Template,
89
type UpdateTemplateMeta,
910
WorkspaceAppSharingLevels,
@@ -53,6 +54,7 @@ export const validationSchema = Yup.object({
5354
use_classic_parameter_flow: Yup.boolean(),
5455
deprecation_message: Yup.string(),
5556
max_port_sharing_level: Yup.string().oneOf(WorkspaceAppSharingLevels),
57+
cors_behavior: Yup.string().oneOf(Object.values(CORSBehaviors)),
5658
});
5759

5860
export interface TemplateSettingsForm {
@@ -94,6 +96,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
9496
disable_everyone_group_access: false,
9597
max_port_share_level: template.max_port_share_level,
9698
use_classic_parameter_flow: template.use_classic_parameter_flow,
99+
cors_behavior: template.cors_behavior,
97100
},
98101
validationSchema,
99102
onSubmit,
@@ -339,6 +342,28 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
339342
</FormFields>
340343
</FormSection>
341344

345+
<FormSection
346+
title="CORS Behavior"
347+
description="Control how Cross-Origin Resource Sharing (CORS) requests are handled for all shared ports."
348+
>
349+
<FormFields>
350+
<TextField
351+
{...getFieldHelpers("cors_behavior", {
352+
helperText:
353+
"Use Passthru to bypass Coder's built-in CORS protection.",
354+
})}
355+
disabled={isSubmitting}
356+
fullWidth
357+
select
358+
value={form.values.cors_behavior}
359+
label="CORS Behavior"
360+
>
361+
<MenuItem value="simple">Simple</MenuItem>
362+
<MenuItem value="passthru">Passthru</MenuItem>
363+
</TextField>
364+
</FormFields>
365+
</FormSection>
366+
342367
<FormFooter>
343368
<Button onClick={onCancel} variant="outline">
344369
Cancel

site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const validFormValues: FormValues = {
5555
disable_everyone_group_access: false,
5656
max_port_share_level: "owner",
5757
use_classic_parameter_flow: true,
58+
cors_behavior: "simple",
5859
};
5960

6061
const renderTemplateSettingsPage = async () => {

site/src/testHelpers/entities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ export const MockTemplate: TypesGen.Template = {
827827
deprecation_message: "",
828828
max_port_share_level: "public",
829829
use_classic_parameter_flow: true,
830+
cors_behavior: "simple",
830831
};
831832

832833
const MockTemplateVersionFiles: TemplateVersionFiles = {

0 commit comments

Comments
 (0)