Both PedsHub apps now take admin and moderator from the same two Authentik groups. oidc.admin_groups and oidc.moderator_groups name them; unset means local roles stand. Applied at every sign-in so removal at the SSO demotes here, and never applied to the last admin — a group edit must not be able to lock everyone out of the panel. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
34 lines
2 KiB
JavaScript
34 lines
2 KiB
JavaScript
// Roles come from the SSO's groups on every sign-in, when the admin has said
|
|
// which groups mean what; the last admin is never demoted by a claim.
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const src = fs.readFileSync(path.join(__dirname, '..', 'src/routes/oidc.js'), 'utf8');
|
|
function withSettings(settings) {
|
|
const db = { getSetting: async k => settings[k] || '' };
|
|
const slice = src.slice(src.indexOf('function parseGroupList'), src.indexOf('// ── GET /api/auth/oidc — initiate'));
|
|
return new Function('db', slice + '; return roleFromGroups;')(db);
|
|
}
|
|
|
|
test('groups map to roles: admin beats moderator, neither is a user, off when unset', async () => {
|
|
const on = withSettings({ 'oidc.admin_groups': 'pedshub-admins', 'oidc.moderator_groups': 'pedshub-moderators, editors' });
|
|
assert.equal(await on(['pedshub-members', 'pedshub-admins', 'pedshub-moderators']), 'admin');
|
|
assert.equal(await on(['pedshub-members', 'Editors']), 'moderator', 'case-blind');
|
|
assert.equal(await on(['pedshub-members']), 'user');
|
|
assert.equal(await on('pedshub-members pedshub-moderators'), 'moderator', 'a string claim is a list');
|
|
assert.equal(await on(undefined), null, 'no claim: leave the role alone');
|
|
const off = withSettings({});
|
|
assert.equal(await off(['pedshub-admins']), null, 'unset settings: local roles stand');
|
|
});
|
|
|
|
test('the callback applies the mapping every sign-in and spares the last admin', () => {
|
|
const cb = src.slice(src.indexOf("router.get('/oidc/callback'"));
|
|
assert.match(cb, /var mapped = await roleFromGroups\(claims\.groups\);/);
|
|
assert.match(cb, /if \(mapped && mapped !== user\.role\)/);
|
|
assert.match(cb, /SELECT COUNT\(\*\) AS count FROM users WHERE role = 'admin' AND disabled IS NOT TRUE/);
|
|
assert.match(cb, /not demoting the last admin/);
|
|
assert.match(cb, /UPDATE users SET role = \? WHERE id = \?/);
|
|
assert.match(src, /'oidc\.admin_groups', 'oidc\.moderator_groups'\]/);
|
|
});
|