feat(api): server-side album role permission checks

Task 14 (A02 foundation): PermissionsService with fresh-DB-per-call
canViewAlbum/canManageAlbum/canUploadToAlbum/canManagePhoto over the
album_members @@unique([albumId,userId]) compound key; admin bypass,
owner/collaborator matrix per requirements doc section 2, removed
members lose access on the very next call (no caching). Boolean-only
returns; callers map 404/403. AlbumsModule shell wired into app module
(controllers arrive in Task 15). jest maxWorkers=1: DB-backed specs
share one MySQL database and reset it via TRUNCATE, so parallel spec
files wipe each other's seed data.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-17 21:34:22 +08:00
parent 39cae26106
commit 2d9b9f9fad
5 changed files with 349 additions and 2 deletions
+9 -2
View File
@@ -12,6 +12,12 @@
import type { Config } from 'jest';
const config: Config = {
// 单进程串行:test/ 下的 DB 型 spec(seed.spec.ts、permissions.spec.ts)
// 共享同一 MySQL 库且在 beforeAll 以 reset.ts TRUNCATE 全库重置,jest 默认
// 按文件并行会在 spec 间互相清掉对方刚种的数据(seed.spec 断言全库用户数);
// 串行后纯函数 spec 一并排队,代价可忽略。e2e 配置继承本文件同样受益
// (此前多个 e2e spec 并行 reset 仅靠启动时序侥幸不冲突)。
maxWorkers: 1,
testEnvironment: 'node',
rootDir: '.',
setupFiles: ['./test/load-env.ts'],
@@ -23,8 +29,9 @@ const config: Config = {
'^@photo/db-cn$': '<rootDir>/../../packages/db-cn/src/index.ts',
'^(\\.{1,2}/.*)\\.js$': '$1',
},
// test/ 下的 *.spec.ts 为直连真实 DB 的集成型单测(seed.spec.ts,经 reset.ts
// 隔离);纯 HTTP e2e 仍由 jest.e2e.config.ts 的 testMatch 接管。
// test/ 下的 *.spec.ts 为直连真实 DB 的集成型单测(seed.spec.ts、
// permissions.spec.ts,各自经 reset.ts 隔离);纯 HTTP e2e 仍由
// jest.e2e.config.ts 的 testMatch 接管。
testMatch: ['<rootDir>/src/**/*.spec.ts', '<rootDir>/test/**/*.spec.ts'],
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
};