Skip to content

Commit 18fa312

Browse files
committed
add some tests
1 parent 0d84246 commit 18fa312

File tree

5 files changed

+89
-4
lines changed

5 files changed

+89
-4
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1961,7 +1961,7 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
19611961
action = rbac.ActionDelete
19621962
}
19631963

1964-
if err = q.authorizeContext(ctx, action, w.WorkspaceBuildRBAC()); err != nil {
1964+
if err = q.authorizeContext(ctx, action, w.WorkspaceBuildRBAC(arg.Transition)); err != nil {
19651965
return database.WorkspaceBuild{}, err
19661966
}
19671967

coderd/database/modelmethods.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,13 @@ func (w Workspace) ApplicationConnectRBAC() rbac.Object {
168168
WithOwner(w.OwnerID.String())
169169
}
170170

171-
func (w Workspace) WorkspaceBuildRBAC() rbac.Object {
171+
func (w Workspace) WorkspaceBuildRBAC(transition WorkspaceTransition) rbac.Object {
172172
// If a workspace is locked it cannot be built.
173-
if w.LockedAt.Valid {
173+
// However we need to allow stopping a workspace by a caller once a workspace
174+
// is locked (e.g. for autobuild). Additionally, if a user wants to delete
175+
// a locked workspace, they shouldn't have to have it unlocked first.
176+
if w.LockedAt.Valid && transition != WorkspaceTransitionStop &&
177+
transition != WorkspaceTransitionDelete {
174178
return w.LockedRBAC()
175179
}
176180

coderd/workspacebuilds.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,11 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
350350
)
351351
var buildErr wsbuilder.BuildError
352352
if xerrors.As(err, &buildErr) {
353+
var authErr dbauthz.NotAuthorizedError
354+
if xerrors.As(err, &authErr) {
355+
buildErr.Status = http.StatusUnauthorized
356+
}
357+
353358
if buildErr.Status == http.StatusInternalServerError {
354359
api.Logger.Error(ctx, "workspace build error", slog.Error(buildErr.Wrapped))
355360
}

coderd/workspaces_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,3 +2375,79 @@ func TestWorkspaceWithOptionalRichParameters(t *testing.T) {
23752375
}
23762376
require.ElementsMatch(t, expectedBuildParameters, workspaceBuildParameters)
23772377
}
2378+
2379+
func TestWorkspaceLock(t *testing.T) {
2380+
t.Parallel()
2381+
2382+
t.Run("OK", func(t *testing.T) {
2383+
t.Parallel()
2384+
var (
2385+
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
2386+
user = coderdtest.CreateFirstUser(t, client)
2387+
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
2388+
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
2389+
template = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
2390+
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
2391+
_ = coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
2392+
)
2393+
2394+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
2395+
defer cancel()
2396+
2397+
err := client.UpdateWorkspaceLock(ctx, workspace.ID, codersdk.UpdateWorkspaceLock{
2398+
Lock: true,
2399+
})
2400+
require.NoError(t, err)
2401+
2402+
workspace, err = client.Workspace(ctx, workspace.ID)
2403+
require.NoError(t, err, "fetch provisioned workspace")
2404+
require.NotNil(t, workspace.LockedAt)
2405+
require.WithinRange(t, *workspace.LockedAt, time.Now().Add(-time.Second*10), time.Now())
2406+
2407+
err = client.UpdateWorkspaceLock(ctx, workspace.ID, codersdk.UpdateWorkspaceLock{
2408+
Lock: false,
2409+
})
2410+
require.NoError(t, err)
2411+
2412+
workspace, err = client.Workspace(ctx, workspace.ID)
2413+
require.NoError(t, err, "fetch provisioned workspace")
2414+
require.Nil(t, workspace.LockedAt)
2415+
})
2416+
2417+
t.Run("CannotStart", func(t *testing.T) {
2418+
t.Parallel()
2419+
var (
2420+
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
2421+
user = coderdtest.CreateFirstUser(t, client)
2422+
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
2423+
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
2424+
template = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
2425+
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
2426+
_ = coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
2427+
)
2428+
2429+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
2430+
defer cancel()
2431+
2432+
err := client.UpdateWorkspaceLock(ctx, workspace.ID, codersdk.UpdateWorkspaceLock{
2433+
Lock: true,
2434+
})
2435+
require.NoError(t, err)
2436+
2437+
// Should be able to stop a workspace while it is locked.
2438+
coderdtest.MustTransitionWorkspace(t, client, workspace.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)
2439+
2440+
// Should not be able to start a workspace while it is locked.
2441+
_, err = client.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{
2442+
TemplateVersionID: template.ActiveVersionID,
2443+
Transition: codersdk.WorkspaceTransition(database.WorkspaceTransitionStart),
2444+
})
2445+
require.Error(t, err)
2446+
2447+
err = client.UpdateWorkspaceLock(ctx, workspace.ID, codersdk.UpdateWorkspaceLock{
2448+
Lock: false,
2449+
})
2450+
require.NoError(t, err)
2451+
coderdtest.MustTransitionWorkspace(t, client, workspace.ID, database.WorkspaceTransitionStop, database.WorkspaceTransitionStart)
2452+
})
2453+
}

codersdk/workspaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ type UpdateWorkspaceLock struct {
287287
}
288288

289289
// UpdateWorkspaceLock locks or unlocks a workspace.
290-
func (c *Client) UpdateWorkspaceLock(ctx context.Context, id uuid.UUID, req PutExtendWorkspaceRequest) error {
290+
func (c *Client) UpdateWorkspaceLock(ctx context.Context, id uuid.UUID, req UpdateWorkspaceLock) error {
291291
path := fmt.Sprintf("/api/v2/workspaces/%s/lock", id.String())
292292
res, err := c.Request(ctx, http.MethodPut, path, req)
293293
if err != nil {

0 commit comments

Comments
 (0)