UNPKG

@speckle/shared

Version:

Shared code between various Speckle JS packages

366 lines (335 loc) 11.2 kB
import { describe, expect, it } from 'vitest' import { Roles } from '../../../core/constants.js' import { parseFeatureFlags } from '../../../environment/index.js' import { canLoadPolicy } from './canLoad.js' import { ProjectNoAccessError, ProjectNotEnoughPermissionsError, ProjectNotFoundError, ServerNoAccessError, ServerNoSessionError, WorkspaceNoAccessError, WorkspaceSsoSessionNoAccessError } from '../../domain/authErrors.js' import { TIME_MS } from '../../../core/index.js' import { ProjectVisibility } from '../../domain/projects/types.js' import { getWorkspaceFake } from '../../../tests/fakes.js' const buildCanLoadPolicy = (overrides?: Partial<Parameters<typeof canLoadPolicy>[0]>) => canLoadPolicy({ getEnv: async () => parseFeatureFlags({ FF_WORKSPACES_MODULE_ENABLED: 'true' }), getAdminOverrideEnabled: async () => false, getProject: async () => ({ id: 'project-id', workspaceId: null, visibility: ProjectVisibility.Private, allowPublicComments: false }), getProjectRole: async () => Roles.Stream.Owner, getServerRole: async () => Roles.Server.User, getWorkspace: async () => null, getWorkspaceRole: async () => null, getWorkspaceSsoProvider: async () => null, getWorkspaceSsoSession: async () => null, ...overrides }) describe('canLoad', () => { it('returns ok if anyone is trying to load a publicly loadable project', async () => { const canLoad = buildCanLoadPolicy() // this is a deliberate copy pasta, if anyone removes from the baked in list, // the test should fail const publiclyLoadableProjects = ['8be1007be1'] for (const projectId of publiclyLoadableProjects) { const result = await canLoad({ userId: undefined, projectId }) expect(result).toBeAuthOKResult() } }) it('returns error if user is not logged in', async () => { const canLoad = buildCanLoadPolicy() const result = await canLoad({ userId: undefined, projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ServerNoSessionError.code }) }) it('returns error if user is not found', async () => { const canLoad = buildCanLoadPolicy({ getServerRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ServerNoAccessError.code }) }) it('returns error project not found', async () => { const canLoad = buildCanLoadPolicy({ getProject: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ProjectNotFoundError.code }) }) it('returns error if no role at all', async () => { const canLoad = buildCanLoadPolicy({ getProjectRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ProjectNoAccessError.code }) }) it('returns error if not contributor', async () => { const canLoad = buildCanLoadPolicy({ getProjectRole: async () => Roles.Stream.Reviewer }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ProjectNotEnoughPermissionsError.code }) }) it('returns ok if permissible', async () => { const canLoad = buildCanLoadPolicy() const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) describe('with server admin', () => { it('returns ok if admin override enabled even without project role', async () => { const canLoad = buildCanLoadPolicy({ getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => true, getProjectRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) it('returns error if admin override disabled and no project role', async () => { const canLoad = buildCanLoadPolicy({ getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => false, getProjectRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ProjectNoAccessError.code }) }) it('returns ok if admin override disabled but has valid project role', async () => { const canLoad = buildCanLoadPolicy({ getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => false, getProjectRole: async () => Roles.Stream.Contributor }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) }) describe('with workspace project', () => { const overrides = { getProject: async () => ({ id: 'project-id', workspaceId: 'workspace-id', visibility: ProjectVisibility.Workspace, allowPublicComments: false }), getWorkspace: getWorkspaceFake({ id: 'workspace-id', slug: 'workspace-slug' }), getWorkspaceRole: async () => Roles.Workspace.Member, getWorkspaceSsoProvider: async () => ({ providerId: 'provider-id' }), getWorkspaceSsoSession: async () => { const validUntil = new Date() validUntil.setDate(validUntil.getDate() + 7) return { userId: 'user-id', providerId: 'provider-id', validUntil } } } it('returns ok if permissible', async () => { const canLoad = buildCanLoadPolicy(overrides) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) it('returns ok with implicit contributor role', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getWorkspaceRole: async () => Roles.Workspace.Admin, getProjectRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) it('returns error if no workspace role, even w/ valid project role', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getWorkspaceRole: async () => null, getProjectRole: async () => Roles.Stream.Owner }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: WorkspaceNoAccessError.code }) }) it('returns error if invalid workspace and project role', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getWorkspaceRole: async () => Roles.Workspace.Member, getProjectRole: async () => Roles.Stream.Reviewer }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: ProjectNotEnoughPermissionsError.code }) }) it('returns ok if no sso configured', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getWorkspaceSsoProvider: async () => null, getWorkspaceSsoSession: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) it('returns error if no sso session', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getWorkspaceSsoSession: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: WorkspaceSsoSessionNoAccessError.code }) }) it('returns error if sso expired', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getWorkspaceSsoSession: async () => ({ userId: 'user-id', providerId: 'provider-id', validUntil: new Date(new Date().getTime() - TIME_MS.second) }) }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: WorkspaceSsoSessionNoAccessError.code }) }) describe('with server admin', () => { it('returns ok if admin override enabled even without workspace/project role', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => true, getWorkspaceRole: async () => null, getProjectRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) it('returns error if admin override disabled and no workspace role', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => false, getWorkspaceRole: async () => null, getProjectRole: async () => Roles.Stream.Owner }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthErrorResult({ code: WorkspaceNoAccessError.code }) }) it('returns ok if admin override disabled but has valid workspace and project roles', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => false, getWorkspaceRole: async () => Roles.Workspace.Member, getProjectRole: async () => Roles.Stream.Contributor }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) it('returns ok if admin override disabled with implicit contributor role from workspace admin', async () => { const canLoad = buildCanLoadPolicy({ ...overrides, getServerRole: async () => Roles.Server.Admin, getAdminOverrideEnabled: async () => false, getWorkspaceRole: async () => Roles.Workspace.Admin, getProjectRole: async () => null }) const result = await canLoad({ userId: 'user-id', projectId: 'project-id' }) expect(result).toBeAuthOKResult() }) }) }) })