diff --git a/apps/sim/lib/core/application/workspace-authorization.test.ts b/apps/sim/lib/core/application/workspace-authorization.test.ts index 0a906477d2e..b5e8fef8035 100644 --- a/apps/sim/lib/core/application/workspace-authorization.test.ts +++ b/apps/sim/lib/core/application/workspace-authorization.test.ts @@ -488,11 +488,11 @@ describe('authorizeWorkspaceOperation personal API key policy', () => { }) /** - * The workspace column keeps its fail-fast: it is a property of the workspace - * rather than of any group, so it is not the organization-configuration - * oracle the group key would be, and three call-site suites pin the ordering. + * The workspace column follows membership too: the context is loaded before + * authorization, so refusing the column first would tell a non-member that the + * workspace, and the resource it named in it, exist. */ - it('keeps refusing the workspace personal-key column before the role lookup', async () => { + it('conceals the workspace before refusing the workspace personal-key column', async () => { mocks.resolvePermission.mockResolvedValue(null) await expect( @@ -500,8 +500,7 @@ describe('authorizeWorkspaceOperation personal API key policy', () => { ...context, allowPersonalApiKeys: false, }) - ).rejects.toBeInstanceOf(PersonalApiKeysDisabledError) - expect(mocks.resolvePermission).not.toHaveBeenCalled() + ).rejects.toBeInstanceOf(NoWorkspaceAccessError) }) }) diff --git a/apps/sim/lib/core/application/workspace-authorization.ts b/apps/sim/lib/core/application/workspace-authorization.ts index 67de9320502..baad11a7c49 100644 --- a/apps/sim/lib/core/application/workspace-authorization.ts +++ b/apps/sim/lib/core/application/workspace-authorization.ts @@ -380,33 +380,32 @@ export async function authorizeWorkspaceOperation workspaceAuthzMock) +import { PersonalApiKeysDisabledError } from '@/lib/core/application' import type { OrchestrationError } from '@/lib/core/orchestration/types' import { authorizeTableOperation } from '@/lib/table/application/authorization' import { tableOperations } from '@/lib/table/application/operations' @@ -65,14 +66,14 @@ describe('table operation authorization', () => { await expectForbidden(createSessionPrincipal()) }) - it('rejects disabled personal keys before permission lookup', async () => { + it("refuses a member's personal key when the workspace disables them", async () => { + resolvePermission.mockResolvedValue('admin') await expect( authorizeTableOperation(createPersonalApiKeyPrincipal(), tableOperations.updateRow, { ...authorizationContext, allowPersonalApiKeys: false, }) - ).rejects.toMatchObject>({ code: 'forbidden' }) - expect(resolvePermission).not.toHaveBeenCalled() + ).rejects.toBeInstanceOf(PersonalApiKeysDisabledError) }) it('allows workspace keys only in their credential workspace', async () => { diff --git a/apps/sim/lib/workspace-files/application/authorization.test.ts b/apps/sim/lib/workspace-files/application/authorization.test.ts index 6e23be54992..a16565bbde2 100644 --- a/apps/sim/lib/workspace-files/application/authorization.test.ts +++ b/apps/sim/lib/workspace-files/application/authorization.test.ts @@ -9,6 +9,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('@sim/platform-authz/workspace', () => workspaceAuthzMock) +import { PersonalApiKeysDisabledError } from '@/lib/core/application' import type { OrchestrationError } from '@/lib/core/orchestration/types' import { authorizeWorkspaceFileAccess } from '@/lib/workspace-files/application/authorization' import { fileOperations } from '@/lib/workspace-files/application/operations' @@ -53,14 +54,14 @@ describe('file operation authorization', () => { }) }) - it('fails a personal key immediately when the workspace disables it', async () => { + it("refuses a member's personal key when the workspace disables them", async () => { + resolvePermission.mockResolvedValue('admin') await expect( authorizeWorkspaceFileAccess(createPersonalApiKeyPrincipal(), fileOperations.rename, { ...authorizationContext, allowPersonalApiKeys: false, }) - ).rejects.toMatchObject>({ code: 'forbidden' }) - expect(resolvePermission).not.toHaveBeenCalled() + ).rejects.toBeInstanceOf(PersonalApiKeysDisabledError) }) it('rejects a disallowed principal kind before principal-specific authorization', async () => {