// 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'\]/); });