Files
fanuzu/app/firebase/functions/test/guard.test.ts
T

47 lines
2.0 KiB
TypeScript

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<string, unknown> }) =>
({ 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<typeof fn.run>[0]))
.rejects.toMatchObject({ details: { code: 'E-PERM-01' } });
}
}
});
it('약관 동의 기록은 익명 호출을 거부한다', async () => {
await expect(fnConsentRecord.run(req() as Parameters<typeof fnConsentRecord.run>[0]))
.rejects.toMatchObject({ details: { code: 'E-AUTH-03' } });
});
});