import { describe, expect, it } from 'vitest'; import type { CallableRequest } from 'firebase-functions/v2/https'; import { callerUid, requireRole } from '../src/core/callable.js'; import { fnAdminSetRole, fnConsentRecord } from '../src/account/account.js'; import { fnAdminWrite } from '../src/admin/admin.js'; /** 에뮬레이터 없이 도는 인증 · 권한 관문 검증. 데이터에 닿기 전에 끊겨야 한다. */ const req = (auth?: { uid: string; token: Record }) => ({ data: {}, auth } as unknown as CallableRequest); describe('인증 관문', () => { it('익명 호출은 E-AUTH-03 으로 끊는다', () => { expect(() => callerUid(req())).toThrow(expect.objectContaining({ details: { code: 'E-AUTH-03' } })); }); it('로그인한 호출은 UID 를 돌려준다', () => { expect(callerUid(req({ uid: 'u1', token: {} }))).toBe('u1'); }); }); describe('운영자 관문', () => { it('허용 목록에 없는 역할은 E-PERM-01 로 끊는다', () => { expect(() => requireRole(req({ uid: 'v', token: { role: 'viewer' } }), ['master', 'ops'])) .toThrow(expect.objectContaining({ details: { code: 'E-PERM-01' } })); }); it('허용된 역할은 그대로 돌려준다', () => { expect(requireRole(req({ uid: 'o', token: { role: 'ops' } }), ['master', 'ops'])).toBe('ops'); }); it('Admin 쓰기 · 권한 부여는 일반 사용자와 조회 운영자를 데이터 접근 전에 거부한다', async () => { for (const fn of [fnAdminWrite, fnAdminSetRole]) { for (const auth of [{ uid: 'user', token: {} }, { uid: 'viewer', token: { role: 'viewer' } }]) { await expect(fn.run(req(auth) as Parameters[0])) .rejects.toMatchObject({ details: { code: 'E-PERM-01' } }); } } }); it('약관 동의 기록은 익명 호출을 거부한다', async () => { await expect(fnConsentRecord.run(req() as Parameters[0])) .rejects.toMatchObject({ details: { code: 'E-AUTH-03' } }); }); });