Files
Void-Homelab/tests/auth/capability.test.js

56 lines
1.8 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { canAct } from '../../lib/auth/capability.js';
const ownerActor = { kind: 'user', id: null };
const readAgent = {
kind: 'agent', id: 'a1',
capabilities: { read: true, suggest: true, write: false },
scopes: {}
};
const writeAgent = {
kind: 'agent', id: 'a2',
capabilities: { read: true, suggest: true, write: true },
scopes: { page: true }
};
describe('canAct', () => {
it('owner can do anything', () => {
expect(canAct(ownerActor, 'create', 'page')).toBe('allow');
expect(canAct(ownerActor, 'delete', 'resource')).toBe('allow');
});
it('read-only agent can read', () => {
expect(canAct(readAgent, 'read', 'page')).toBe('allow');
});
it('default agent on create returns "suggest"', () => {
expect(canAct(readAgent, 'create', 'page')).toBe('suggest');
});
it('write-scoped agent can write to its scope', () => {
expect(canAct(writeAgent, 'create', 'page')).toBe('allow');
});
it('write-capable agent without scope still suggests outside it', () => {
expect(canAct(writeAgent, 'create', 'resource')).toBe('suggest');
});
it('agent with no capabilities is deny on mutations', () => {
expect(canAct({ kind: 'agent', id: 'x', capabilities: {} }, 'create', 'page')).toBe('deny');
});
it('agent with no read capability is deny on read', () => {
expect(canAct({ kind: 'agent', id: 'x', capabilities: {} }, 'read', 'page')).toBe('deny');
});
it('null actor is deny', () => {
expect(canAct(null, 'read', 'page')).toBe('deny');
});
it('cron/worker/system get allow', () => {
expect(canAct({ kind: 'cron', id: null }, 'create', 'page')).toBe('allow');
expect(canAct({ kind: 'worker', id: null }, 'update', 'page')).toBe('allow');
expect(canAct({ kind: 'system', id: null }, 'delete', 'page')).toBe('allow');
});
});