fix: list routes answer for permitted orgs only; org lists go through the hooks
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { test, beforeEach } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { addPermissionHook, permittedScope } from '../dist/index.js';
|
||||
|
||||
const A = '00000000-0000-4000-8000-00000000000a';
|
||||
const B = '00000000-0000-4000-8000-00000000000b';
|
||||
|
||||
function fakeDb(allowed) {
|
||||
return {
|
||||
async query(sql, params) {
|
||||
if (sql.includes('unnest')) return { rows: params[1].filter((o) => allowed.has(o)).map((o) => ({ o })) };
|
||||
if (sql.includes('morbac.is_allowed')) return { rows: [{ allowed: allowed.has(params[1]) }] };
|
||||
throw new Error(`unexpected query ${sql}`);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function fakeReply() {
|
||||
return { status: 200, code(c) { this.status = c; return this; }, send() { return this; } };
|
||||
}
|
||||
|
||||
const req = { user: { id: 'u' } };
|
||||
let removers = [];
|
||||
beforeEach(() => { removers.forEach((r) => r()); removers = []; });
|
||||
|
||||
test('a pinned list keeps only the orgs the caller may read', async () => {
|
||||
const reply = fakeReply();
|
||||
assert.deepEqual(await permittedScope(fakeDb(new Set([B])), req, reply, [A, B], 'read', 'users'), [B]);
|
||||
assert.equal(reply.status, 200);
|
||||
});
|
||||
|
||||
test('a refused first org no longer fails the list', async () => {
|
||||
removers.push(addPermissionHook('pre', (c) => c.orgId !== A));
|
||||
assert.deepEqual(await permittedScope(fakeDb(new Set([A, B])), req, fakeReply(), [A, B], 'read', 'users'), [B]);
|
||||
});
|
||||
|
||||
test('a list with no permitted org is refused', async () => {
|
||||
const reply = fakeReply();
|
||||
assert.equal(await permittedScope(fakeDb(new Set()), req, reply, [A, B], 'read', 'users'), null);
|
||||
assert.equal(reply.status, 403);
|
||||
});
|
||||
|
||||
test('an unpinned list is decided on the no-org perimeter', async () => {
|
||||
assert.deepEqual(await permittedScope(fakeDb(new Set([null])), req, fakeReply(), [], 'read', 'users'), []);
|
||||
const reply = fakeReply();
|
||||
assert.equal(await permittedScope(fakeDb(new Set()), req, reply, [], 'read', 'users'), null);
|
||||
assert.equal(reply.status, 403);
|
||||
});
|
||||
|
||||
test('an API key outside its scope gets nothing', async () => {
|
||||
const reply = fakeReply();
|
||||
const keyed = { ...req, apiKeyScope: [{ activity: 'read', view: 'roles' }] };
|
||||
assert.equal(await permittedScope(fakeDb(new Set([A])), keyed, reply, [A], 'read', 'users'), null);
|
||||
assert.equal(reply.status, 403);
|
||||
});
|
||||
Reference in New Issue
Block a user