fix: remove excess calls to prepareSQLFilter for workspace and template endpoints (#27248)

This commit is contained in:
Callum Styan
2026-07-15 14:23:44 -07:00
committed by GitHub
parent 4d4cbd07e6
commit 15da504cf9
5 changed files with 130 additions and 26 deletions
+44
View File
@@ -54,6 +54,50 @@ import (
"github.com/coder/terraform-provider-coder/v2/provider"
)
// TestWorkspacesListSingleAuthorizePrepare guards against reintroducing the
// redundant OPA partial evaluation the GET /api/v2/workspaces handler used to
// perform. The handler called AuthorizeSQLFilter to build a prepared
// ResourceWorkspace authorizer, but the dbauthz GetAuthorizedWorkspaces wrapper
// ignored it and re-prepared inside GetWorkspaces, so every request ran partial
// evaluation twice. Partial-evaluation cost scales with the number of
// organization-scoped roles the subject carries (see #21890), so the duplicate
// prepare doubled an already expensive operation. A single list request must
// prepare the ResourceWorkspace authorizer exactly once.
func TestWorkspacesListSingleAuthorizePrepare(t *testing.T) {
t.Parallel()
authz := &coderdtest.RecordingAuthorizer{Wrapped: rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())}
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
Authorizer: authz,
})
owner := coderdtest.CreateFirstUser(t, client)
// Seed one workspace directly in the database. The authorization path the
// handler takes does not depend on how the workspace was built, so dbfake
// avoids the cost of a provisioner and real build.
dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID,
}).Do()
ctx := testutil.Context(t, testutil.WaitLong)
// Reset immediately before the measured request so setup prepares are
// excluded. Counts are keyed by subject ID, so background work under system
// subjects is ignored.
authz.Reset()
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{})
require.NoError(t, err)
require.Len(t, res.Workspaces, 1)
// The exact count of 1 relies on this being the only request issued under the
// owner subject between the reset and this assertion, which holds because the
// test makes a single serial call.
count := authz.PrepareCount(owner.UserID.String(), policy.ActionRead, rbac.ResourceWorkspace.Type)
require.Equal(t, 1, count,
"GET /workspaces must prepare the ResourceWorkspace authorizer exactly once; a higher count means a redundant partial evaluation was reintroduced")
}
func TestWorkspace(t *testing.T) {
t.Parallel()