mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 23:46:35 +00:00
refactor(auth): auth, passkey, profile, token and admin services refuse with DomainError instead of returning error envelopes
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { DomainError } from '../../../src/nest/common/domain-error';
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { HttpException, NotFoundException } from '@nestjs/common';
|
||||
import type { Request } from 'express';
|
||||
@@ -88,7 +89,7 @@ afterEach(() => { delete process.env.NODE_ENV; });
|
||||
describe('AdminController users', () => {
|
||||
it('lists, creates (201 + audit), maps an error', async () => {
|
||||
expect(await adminCtl(svc({ listUsers: vi.fn().mockReturnValue([{ id: 1 }]) } as Partial<AdminService>)).listUsers()).toEqual({ users: [{ id: 1 }] });
|
||||
expect(await thrown(() => adminCtl(svc({ createUser: vi.fn().mockReturnValue({ error: 'Email taken', status: 409 }) } as Partial<AdminService>)).createUser(user, {}, req))).toEqual({ status: 409, body: { error: 'Email taken' } });
|
||||
expect(await thrown(() => adminCtl(svc({ createUser: vi.fn().mockRejectedValue(new DomainError(409, 'Email taken')) } as Partial<AdminService>)).createUser(user, {}, req))).toEqual({ status: 409, body: { error: 'Email taken' } });
|
||||
const c = adminCtl(svc({ createUser: vi.fn().mockReturnValue({ user: { id: 2 }, insertedId: 2, auditDetails: {} }) } as Partial<AdminService>));
|
||||
expect(await c.createUser(user, { email: 'a@b.c' }, req)).toEqual({ user: { id: 2 } });
|
||||
expect(writeAudit).toHaveBeenCalledWith(expect.objectContaining({ action: 'admin.user_create' }));
|
||||
@@ -96,7 +97,7 @@ describe('AdminController users', () => {
|
||||
|
||||
it('update + delete audit and map errors', async () => {
|
||||
expect(await adminCtl(svc({ updateUser: vi.fn().mockReturnValue({ user: { id: 2 }, previousEmail: 'a@b.c', changed: ['role'] }) } as Partial<AdminService>)).updateUser(user, '2', {}, req)).toEqual({ user: { id: 2 } });
|
||||
expect(await thrown(() => adminCtl(svc({ deleteUser: vi.fn().mockReturnValue({ error: 'Cannot delete self', status: 400 }) } as Partial<AdminService>)).deleteUser(user, '1', req))).toEqual({ status: 400, body: { error: 'Cannot delete self' } });
|
||||
expect(await thrown(() => adminCtl(svc({ deleteUser: vi.fn().mockRejectedValue(new DomainError(400, 'Cannot delete self')) } as Partial<AdminService>)).deleteUser(user, '1', req))).toEqual({ status: 400, body: { error: 'Cannot delete self' } });
|
||||
expect(await adminCtl(svc({ deleteUser: vi.fn().mockReturnValue({ email: 'a@b.c' }) } as Partial<AdminService>)).deleteUser(user, '2', req)).toEqual({ success: true });
|
||||
});
|
||||
});
|
||||
@@ -114,7 +115,7 @@ describe('AdminController permissions + oidc + misc', () => {
|
||||
|
||||
|
||||
it('save-demo-baseline maps error, else returns message', async () => {
|
||||
expect(await thrown(() => adminCtl(svc({ saveDemoBaseline: vi.fn().mockReturnValue({ error: 'not demo', status: 400 }) } as Partial<AdminService>)).saveDemoBaseline(user, req))).toEqual({ status: 400, body: { error: 'not demo' } });
|
||||
expect(await thrown(() => adminCtl(svc({ saveDemoBaseline: vi.fn().mockRejectedValue(new DomainError(400, 'not demo')) } as Partial<AdminService>)).saveDemoBaseline(user, req))).toEqual({ status: 400, body: { error: 'not demo' } });
|
||||
expect(await adminCtl(svc({ saveDemoBaseline: vi.fn().mockReturnValue({ message: 'saved' }) } as Partial<AdminService>)).saveDemoBaseline(user, req)).toEqual({ success: true, message: 'saved' });
|
||||
});
|
||||
});
|
||||
@@ -127,7 +128,7 @@ describe('AdminController invites', () => {
|
||||
const c = adminCtl(svc(), undefined, undefined, {}, { createInvite: vi.fn().mockReturnValue({ invite: { id: 5 }, inviteId: 5, uses: 1, expiresInDays: 7 }) });
|
||||
expect(await c.createInvite(user, {}, req)).toEqual({ invite: { id: 5 } });
|
||||
expect(writeAudit).toHaveBeenCalledWith(expect.objectContaining({ action: 'admin.invite_create' }));
|
||||
expect(await thrown(() => adminCtl(svc(), undefined, undefined, {}, { deleteInvite: vi.fn().mockReturnValue({ error: 'not found', status: 404 }) }).deleteInvite(user, '5', req))).toEqual({ status: 404, body: { error: 'not found' } });
|
||||
expect(await thrown(() => adminCtl(svc(), undefined, undefined, {}, { deleteInvite: vi.fn().mockRejectedValue(new DomainError(404, 'not found')) }).deleteInvite(user, '5', req))).toEqual({ status: 404, body: { error: 'not found' } });
|
||||
});
|
||||
|
||||
|
||||
@@ -157,7 +158,7 @@ describe('AdminController addons + sessions + jwt + defaults', () => {
|
||||
});
|
||||
|
||||
it('addon update maps the journey-dependency refusal to its status, before any audit', async () => {
|
||||
const c = adminCtl(svc({ updateAddon: vi.fn().mockReturnValue({ error: 'Enable the Journey addon first', status: 409 }) } as Partial<AdminService>));
|
||||
const c = adminCtl(svc({ updateAddon: vi.fn().mockRejectedValue(new DomainError(409, 'Enable the Journey addon first')) } as Partial<AdminService>));
|
||||
const err = await c.updateAddon(user, 'immich', { enabled: true }, req).then(
|
||||
() => null,
|
||||
(e: unknown) => e as HttpException,
|
||||
@@ -170,20 +171,12 @@ describe('AdminController addons + sessions + jwt + defaults', () => {
|
||||
|
||||
it('oauth-sessions revoke audits; rotate-jwt maps error', async () => {
|
||||
expect(await adminCtl(svc(), undefined, undefined, {}, {}, { adminRevokeOAuthSession: vi.fn().mockReturnValue({}) }).revokeOAuthSession(user, '3', req)).toEqual({ success: true });
|
||||
expect(await thrown(() => adminCtl(svc({ rotateJwtSecret: vi.fn().mockReturnValue({ error: 'locked', status: 409 }) } as Partial<AdminService>)).rotateJwtSecret(user, req))).toEqual({ status: 409, body: { error: 'locked' } });
|
||||
expect(await thrown(() => adminCtl(svc({ rotateJwtSecret: vi.fn(() => { throw new DomainError(409, 'locked'); }) } as Partial<AdminService>)).rotateJwtSecret(user, req))).toEqual({ status: 409, body: { error: 'locked' } });
|
||||
expect(await adminCtl(svc({ rotateJwtSecret: vi.fn().mockReturnValue({}) } as Partial<AdminService>)).rotateJwtSecret(user, req)).toEqual({ success: true });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('AdminController error envelope fallbacks', () => {
|
||||
it('ok() defaults to 400 when the error envelope omits a status', async () => {
|
||||
expect(await thrown(() => adminCtl(svc({ createUser: vi.fn().mockReturnValue({ error: 'boom' }) } as Partial<AdminService>)).createUser(user, {}, req))).toEqual({ status: 400, body: { error: 'boom' } });
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe('AdminController read-only getters', () => {
|
||||
it('return service values verbatim', async () => {
|
||||
expect(await adminCtl(svc({ resetUserPasskeys: vi.fn().mockReturnValue({ email: 'a@b.c', deleted: 2 }) } as Partial<AdminService>)).resetUserPasskeys(user, '4', req)).toEqual({ success: true, deleted: 2 });
|
||||
@@ -213,8 +206,8 @@ describe('AdminController read-only getters', () => {
|
||||
describe('AdminController tokens + sessions', () => {
|
||||
it('mcp token + oauth session deletes return success and map errors', async () => {
|
||||
expect(await adminCtl(svc(), undefined, undefined, { adminDeleteMcpToken: vi.fn().mockReturnValue({}) }).deleteMcpToken(user, '2', req)).toEqual({ success: true });
|
||||
expect(await thrown(() => adminCtl(svc(), undefined, undefined, { adminDeleteMcpToken: vi.fn().mockReturnValue({ error: 'no token', status: 404 }) }).deleteMcpToken(user, '9', req))).toEqual({ status: 404, body: { error: 'no token' } });
|
||||
expect(await thrown(() => adminCtl(svc(), undefined, undefined, {}, {}, { adminRevokeOAuthSession: vi.fn().mockReturnValue({ error: 'no session', status: 404 }) }).revokeOAuthSession(user, '9', req))).toEqual({ status: 404, body: { error: 'no session' } });
|
||||
expect(await thrown(() => adminCtl(svc(), undefined, undefined, { adminDeleteMcpToken: vi.fn().mockRejectedValue(new DomainError(404, 'no token')) }).deleteMcpToken(user, '9', req))).toEqual({ status: 404, body: { error: 'no token' } });
|
||||
expect(await thrown(() => adminCtl(svc(), undefined, undefined, {}, {}, { adminRevokeOAuthSession: vi.fn().mockRejectedValue(new DomainError(404, 'no session')) }).revokeOAuthSession(user, '9', req))).toEqual({ status: 404, body: { error: 'no session' } });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user