123 lines
4.6 KiB
TypeScript
123 lines
4.6 KiB
TypeScript
process.env.DATABASE_PATH = ':memory:';
|
|
process.env.THEMES_DIR = './themes';
|
|
process.env.FRONTEND_DIST = './frontend/dist';
|
|
process.env.UPLOAD_SIZE_LIMIT = '5mb';
|
|
process.env.NODE_ENV = 'test';
|
|
|
|
import { ApiError } from '../../backend/src/common/errors/api-error';
|
|
import { ERROR_CODES } from '../../backend/src/common/errors/error-codes';
|
|
import type { ArgumentMetadata } from '@nestjs/common';
|
|
import { AdminSystemController } from '../../backend/src/modules/admin/system/admin-system.controller';
|
|
import { ZodValidationPipe } from '../../backend/src/common/pipes/zod-validation.pipe';
|
|
import { AdminRestoreCommitBodySchema } from '../../backend/src/modules/admin/system/dto/admin-system.dto';
|
|
|
|
describe('Job 916: Admin restore commit body passes stagingId through', () => {
|
|
function makeController(opts: {
|
|
commitRestore: jest.Mock;
|
|
consume?: jest.Mock;
|
|
}) {
|
|
const consume = opts.consume ?? jest.fn().mockResolvedValue({ id: 'tok' });
|
|
const reauthenticateAdmin = jest.fn().mockResolvedValue({ id: 'admin-1' });
|
|
const revokeAllRefreshSessions = jest.fn().mockResolvedValue(undefined);
|
|
const issue = jest.fn().mockResolvedValue({ token: 't', expiresAt: 'x', id: 'i' });
|
|
const resetScores = jest.fn();
|
|
const wipeChallenges = jest.fn();
|
|
return {
|
|
controller: new AdminSystemController(
|
|
{ build: jest.fn() } as any,
|
|
{ stageArchive: jest.fn(), commitRestore: opts.commitRestore } as any,
|
|
{ resetScores, wipeChallenges } as any,
|
|
{ consume, issue } as any,
|
|
{ reauthenticateAdmin, revokeAllRefreshSessions } as any,
|
|
),
|
|
consume,
|
|
commitRestore: opts.commitRestore,
|
|
issue,
|
|
reauthenticateAdmin,
|
|
revokeAllRefreshSessions,
|
|
};
|
|
}
|
|
|
|
function adminReq(): any {
|
|
return { user: { sub: 'admin-1', role: 'admin' } };
|
|
}
|
|
|
|
it('forwards stagingId to RestoreService.commitRestore and returns ok', async () => {
|
|
const commitRestore = jest.fn().mockResolvedValue({ restoresPerformed: true, revokeUserId: 'admin-1' });
|
|
const { controller, consume, revokeAllRefreshSessions } = makeController({ commitRestore });
|
|
|
|
const result = await controller.commitRestore(
|
|
adminReq(),
|
|
{ operation: 'restore-backup', token: 'raw-token', stagingId: 'stage-xyz' },
|
|
);
|
|
|
|
expect(result).toEqual({ ok: true, operation: 'restore-backup' });
|
|
expect(consume).toHaveBeenCalledWith({
|
|
userId: 'admin-1',
|
|
operation: 'restore-backup',
|
|
token: 'raw-token',
|
|
stagingId: 'stage-xyz',
|
|
});
|
|
expect(commitRestore).toHaveBeenCalledWith('stage-xyz');
|
|
expect(revokeAllRefreshSessions).toHaveBeenCalledWith('admin-1');
|
|
});
|
|
|
|
it('returns SYSTEM_RESTORE_STAGE_EXPIRED when stagingId is missing', async () => {
|
|
const commitRestore = jest.fn();
|
|
const consume = jest.fn();
|
|
const { controller } = makeController({ commitRestore, consume });
|
|
|
|
await expect(
|
|
controller.commitRestore(
|
|
adminReq(),
|
|
{ operation: 'restore-backup', token: 'raw-token' },
|
|
),
|
|
).rejects.toMatchObject({
|
|
code: ERROR_CODES.SYSTEM_RESTORE_STAGE_EXPIRED,
|
|
});
|
|
expect(consume).not.toHaveBeenCalled();
|
|
expect(commitRestore).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('returns SYSTEM_TOKEN_MISMATCH when operation is not restore-backup', async () => {
|
|
const commitRestore = jest.fn();
|
|
const consume = jest.fn();
|
|
const { controller } = makeController({ commitRestore, consume });
|
|
|
|
await expect(
|
|
controller.commitRestore(
|
|
adminReq(),
|
|
{ operation: 'reset-scores' as any, token: 'raw-token', stagingId: 'stage-xyz' },
|
|
),
|
|
).rejects.toMatchObject({
|
|
code: ERROR_CODES.SYSTEM_TOKEN_MISMATCH,
|
|
});
|
|
expect(consume).not.toHaveBeenCalled();
|
|
expect(commitRestore).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('AdminRestoreCommitBodySchema preserves the stagingId field', () => {
|
|
const pipe = new ZodValidationPipe(AdminRestoreCommitBodySchema);
|
|
const meta: ArgumentMetadata = { type: 'body' };
|
|
const value = pipe.transform({
|
|
operation: 'restore-backup',
|
|
token: 'raw-token',
|
|
stagingId: 'stage-xyz',
|
|
}, meta);
|
|
expect(value).toEqual({
|
|
operation: 'restore-backup',
|
|
token: 'raw-token',
|
|
stagingId: 'stage-xyz',
|
|
});
|
|
});
|
|
|
|
it('AdminRestoreCommitBodySchema keeps optional stagingId absent (not empty-stringed)', () => {
|
|
const pipe = new ZodValidationPipe(AdminRestoreCommitBodySchema);
|
|
const meta: ArgumentMetadata = { type: 'body' };
|
|
const value = pipe.transform({ operation: 'restore-backup', token: 'raw-token' }, meta);
|
|
expect(value).toEqual({ operation: 'restore-backup', token: 'raw-token' });
|
|
expect((value as any).stagingId).toBeUndefined();
|
|
void ApiError;
|
|
});
|
|
});
|