Admins (with 2FA) can view the site as a non-admin user for up to 30 minutes, with a required reason and a "Viewing as" banner. It is strictly read-only: a guard mounted before every route refuses any write made with an impersonation token, protect/optionalAuth check the session is live, and GET handlers skip the price-refresh writes. Start, end, reason and every page/API call (including blocked attempts) are audited; optional email to the user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CP62L9JxHomA36aYP1ekCe
44 lines
2.1 KiB
JavaScript
44 lines
2.1 KiB
JavaScript
const { allowedWhileImpersonating, impersonationBlocker } = require('../src/utils/impersonation');
|
|
|
|
describe('allowedWhileImpersonating', () => {
|
|
test('reads are allowed', () => {
|
|
expect(allowedWhileImpersonating('GET', '/api/registrations/myregistrations')).toBe(true);
|
|
expect(allowedWhileImpersonating('HEAD', '/api/events')).toBe(true);
|
|
expect(allowedWhileImpersonating('OPTIONS', '/api/payments')).toBe(true);
|
|
});
|
|
|
|
test('every write is refused', () => {
|
|
for (const m of ['POST', 'PUT', 'PATCH', 'DELETE']) {
|
|
expect(allowedWhileImpersonating(m, '/api/registrations')).toBe(false);
|
|
expect(allowedWhileImpersonating(m, '/api/payments/yoco-checkout')).toBe(false);
|
|
expect(allowedWhileImpersonating(m, '/api/users/profile')).toBe(false);
|
|
}
|
|
});
|
|
|
|
test('except ending the session and logging page views', () => {
|
|
expect(allowedWhileImpersonating('POST', '/api/admin/impersonate/end')).toBe(true);
|
|
expect(allowedWhileImpersonating('POST', '/api/admin/impersonate/log?x=1')).toBe(true);
|
|
expect(allowedWhileImpersonating('DELETE', '/api/admin/impersonate/end')).toBe(false);
|
|
expect(allowedWhileImpersonating('POST', '/api/admin/impersonate/end/../../users')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('impersonationBlocker', () => {
|
|
const admin = { id: 'a', role: 'admin', twoFactorEnabled: true };
|
|
const user = { id: 'u', role: 'user', isActive: true };
|
|
|
|
test('an admin with 2FA can view a user', () => {
|
|
expect(impersonationBlocker(admin, user)).toBeNull();
|
|
expect(impersonationBlocker(admin, { ...user, role: 'supervisor' })).toBeNull();
|
|
});
|
|
|
|
test('refusals', () => {
|
|
expect(impersonationBlocker({ ...admin, role: 'supervisor' }, user)).toMatch(/Only admins/);
|
|
expect(impersonationBlocker({ ...admin, twoFactorEnabled: false }, user)).toMatch(/two-factor/);
|
|
expect(impersonationBlocker(admin, { ...user, role: 'admin' })).toMatch(/Admins can't/);
|
|
expect(impersonationBlocker(admin, { ...admin })).toMatch(/yourself/);
|
|
expect(impersonationBlocker(admin, { ...user, isActive: false })).toMatch(/deactivated/);
|
|
expect(impersonationBlocker(admin, null)).toMatch(/not found/);
|
|
});
|
|
});
|