Spaces:
Sleeping
Sleeping
| import { describe, it, expect, vi } from 'vitest'; | |
| // Mutable rows array so individual tests can inject DB rows | |
| const dbRows: { key: string; value: string }[] = []; | |
| // Mock database β permissions module queries app_settings at runtime | |
| vi.mock('../../../src/db/database', () => ({ | |
| db: { | |
| prepare: () => ({ | |
| all: () => dbRows, // no custom permissions β fall back to defaults | |
| run: vi.fn(), | |
| get: vi.fn(), | |
| }), | |
| transaction: (fn: () => void) => fn, | |
| }, | |
| })); | |
| import { checkPermission, getPermissionLevel, savePermissions, invalidatePermissionsCache, PERMISSION_ACTIONS } from '../../../src/services/permissions'; | |
| describe('permissions', () => { | |
| describe('checkPermission β admin bypass', () => { | |
| it('admin always passes regardless of permission level', () => { | |
| for (const action of PERMISSION_ACTIONS) { | |
| expect(checkPermission(action.key, 'admin', 1, 1, false)).toBe(true); | |
| expect(checkPermission(action.key, 'admin', 99, 1, false)).toBe(true); | |
| } | |
| }); | |
| }); | |
| describe('checkPermission β everybody level', () => { | |
| it('trip_create (everybody) allows any authenticated user', () => { | |
| expect(checkPermission('trip_create', 'user', null, 42, false)).toBe(true); | |
| }); | |
| }); | |
| describe('checkPermission β trip_owner level', () => { | |
| const ownerId = 10; | |
| const memberId = 20; | |
| it('trip owner passes trip_owner check', () => { | |
| expect(checkPermission('trip_delete', 'user', ownerId, ownerId, false)).toBe(true); | |
| }); | |
| it('member fails trip_owner check', () => { | |
| expect(checkPermission('trip_delete', 'user', ownerId, memberId, true)).toBe(false); | |
| }); | |
| it('non-member non-owner fails trip_owner check', () => { | |
| expect(checkPermission('trip_delete', 'user', ownerId, memberId, false)).toBe(false); | |
| }); | |
| }); | |
| describe('checkPermission β trip_member level', () => { | |
| const ownerId = 10; | |
| const memberId = 20; | |
| const outsiderId = 30; | |
| it('trip owner passes trip_member check', () => { | |
| expect(checkPermission('day_edit', 'user', ownerId, ownerId, false)).toBe(true); | |
| }); | |
| it('trip member passes trip_member check', () => { | |
| expect(checkPermission('day_edit', 'user', ownerId, memberId, true)).toBe(true); | |
| }); | |
| it('outsider fails trip_member check', () => { | |
| expect(checkPermission('day_edit', 'user', ownerId, outsiderId, false)).toBe(false); | |
| }); | |
| }); | |
| describe('getPermissionLevel β defaults', () => { | |
| it('returns default level for known actions (no DB overrides)', () => { | |
| const defaults: Record<string, string> = { | |
| trip_create: 'everybody', | |
| trip_delete: 'trip_owner', | |
| day_edit: 'trip_member', | |
| budget_edit: 'trip_member', | |
| }; | |
| for (const [key, expected] of Object.entries(defaults)) { | |
| expect(getPermissionLevel(key)).toBe(expected); | |
| } | |
| }); | |
| it('returns trip_owner for unknown action key', () => { | |
| expect(getPermissionLevel('nonexistent_action')).toBe('trip_owner'); | |
| }); | |
| }); | |
| describe('savePermissions β invalid action key is skipped', () => { | |
| it('returns skipped array containing invalid action key', () => { | |
| const result = savePermissions({ nonexistent_action: 'trip_member' }); | |
| expect(result.skipped).toContain('nonexistent_action'); | |
| }); | |
| it('returns skipped array when level is not in allowedLevels for the action', () => { | |
| // trip_delete only allows ['admin', 'trip_owner'], so 'trip_member' is invalid | |
| const result = savePermissions({ trip_delete: 'trip_member' }); | |
| expect(result.skipped).toContain('trip_delete'); | |
| }); | |
| }); | |
| describe('checkPermission β default case', () => { | |
| it('returns false when permission level is an unrecognized value', () => { | |
| // Inject a DB row with an unknown level for trip_edit, then invalidate cache | |
| dbRows.push({ key: 'perm_trip_edit', value: 'unknown_level' }); | |
| invalidatePermissionsCache(); | |
| const result = checkPermission('trip_edit', 'user', 10, 10, false); | |
| // Clean up for subsequent tests | |
| dbRows.length = 0; | |
| invalidatePermissionsCache(); | |
| expect(result).toBe(false); | |
| }); | |
| }); | |
| }); | |