fix: lists decide every org through the permission system; no system-org shortcut

This commit is contained in:
2026-11-02 10:43:29 +01:00
parent 12964793cf
commit 0f7db7e99e
12 changed files with 98 additions and 31 deletions
+40
View File
@@ -0,0 +1,40 @@
import { test, beforeEach } from 'node:test';
import assert from 'node:assert/strict';
import { addPermissionHook, listScope } from '../dist/index.js';
const ROOT = '00000000-0000-0000-0000-000000000000';
const A = '00000000-0000-4000-8000-00000000000a';
const B = '00000000-0000-4000-8000-00000000000b';
const TREE = { [ROOT]: [ROOT, A, B], [A]: [A], [B]: [B] };
function fakeDb(allowed) {
return {
async query(sql, params) {
if (sql.includes('get_org_scope')) return { rows: [...new Set(params[0].flatMap((o) => TREE[o]))].map((id) => ({ id })) };
if (sql.includes('FROM morbac.orgs')) return { rows: Object.keys(TREE).map((id) => ({ id })) };
if (sql.includes('morbac.is_allowed')) return { rows: params[1].filter((o) => allowed.has(o)).map((o) => ({ o })) };
throw new Error(`unexpected query ${sql}`);
},
};
}
const req = { user: { id: 'u' } };
let removers = [];
beforeEach(() => { removers.forEach((r) => r()); removers = []; });
test('the root org stands for its subtree, decided org by org', async () => {
const { expr, params } = await listScope(fakeDb(new Set([ROOT, A])), req, [ROOT], 'read', 'users', 'x.org_id');
assert.equal(expr, 'x.org_id = ANY($1::UUID[])');
assert.deepEqual(params[0].sort(), [ROOT, A].sort());
});
test('an org the hooks refuse is left out of every list', async () => {
removers.push(addPermissionHook('pre', (c) => c.orgId !== B));
const { params } = await listScope(fakeDb(new Set([ROOT, A, B])), req, [], 'read', 'users', 'x.org_id');
assert.deepEqual(params[0].sort(), [ROOT, A].sort());
});
test('an unpinned list also shows rows with no org', async () => {
const { expr } = await listScope(fakeDb(new Set([A])), req, [], 'read', 'roles', 'r.org_id', 2);
assert.equal(expr, '(r.org_id = ANY($3::UUID[]) OR r.org_id IS NULL)');
});