62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import type { CommandDef, SlashCommandPayload } from '@mosaicstack/types';
|
|
import { CommandAuthorizationService } from './command-authorization.service.js';
|
|
|
|
const adminCommand: CommandDef = {
|
|
name: 'gc',
|
|
description: 'GC',
|
|
aliases: [],
|
|
scope: 'admin',
|
|
execution: 'socket',
|
|
available: true,
|
|
};
|
|
const payload: SlashCommandPayload = { command: 'gc', conversationId: 'conversation-1' };
|
|
|
|
function createService(role: string): CommandAuthorizationService {
|
|
const entries = new Map<string, string>();
|
|
const db = {
|
|
select: () => ({ from: () => ({ where: () => ({ limit: async () => [{ role }] }) }) }),
|
|
};
|
|
const redis = {
|
|
get: async (key: string) => entries.get(key) ?? null,
|
|
set: async (key: string, value: string) => {
|
|
entries.set(key, value);
|
|
},
|
|
del: async (key: string) => Number(entries.delete(key)),
|
|
};
|
|
return new CommandAuthorizationService(db as never, redis);
|
|
}
|
|
|
|
describe('CommandAuthorizationService', () => {
|
|
it('consumes one exact actor-bound approval once', async (): Promise<void> => {
|
|
const service = createService('admin');
|
|
const approval = await service.createApproval(adminCommand, payload, 'admin-1');
|
|
expect(approval).not.toBeNull();
|
|
expect(
|
|
(await service.authorize(adminCommand, payload, 'admin-1', approval!.approvalId)).allowed,
|
|
).toBe(true);
|
|
expect(
|
|
(await service.authorize(adminCommand, payload, 'admin-1', approval!.approvalId)).allowed,
|
|
).toBe(false);
|
|
});
|
|
|
|
it('rejects an approval when the structured action is mutated', async (): Promise<void> => {
|
|
const service = createService('admin');
|
|
const approval = await service.createApproval(adminCommand, payload, 'admin-1');
|
|
const mutated = { ...payload, conversationId: 'other-conversation' };
|
|
expect(approval).not.toBeNull();
|
|
expect(
|
|
(await service.authorize(adminCommand, mutated, 'admin-1', approval!.approvalId)).allowed,
|
|
).toBe(false);
|
|
});
|
|
|
|
it('denies an admin command to a member before approval is considered', async (): Promise<void> => {
|
|
const service = createService('member');
|
|
const approval = await service.createApproval(adminCommand, payload, 'member-1');
|
|
expect(approval).toBeNull();
|
|
expect(
|
|
(await service.authorize(adminCommand, payload, 'member-1', 'forged-approval-id')).allowed,
|
|
).toBe(false);
|
|
});
|
|
});
|