fix: audit remediation — SSE user scoping, FK transactional safety, UI error handling
- H4: scoped SSE import progress to exact userId match; non-HTTP events excluded from all subscribers - H2: moved PRAGMA foreign_key_check inside SQLite transaction before COMMIT; violations rollback preserving old tables - M1: removed dead axios-style error branch from extractErrorMessage (interceptor already unwraps) - M2: split handleSave try/catch — save errors vs reload errors shown distinctly - M3: added provider field validation before AI config test request - Added SSE scoping regression tests (import service + controller) - Added FK check failure rollback test (database-migrations.spec) - Updated controller spec expectations for userId parameter Co-authored-by: Code Review <branch-review>
This commit is contained in:
@@ -7,32 +7,59 @@ function permissionsFor(roleCode: string): { groups: string[]; extras: string[]
|
||||
}
|
||||
|
||||
describe('preset role permissions', () => {
|
||||
it('gives teachers explicit workspace permissions without class/schedule delete privileges', () => {
|
||||
it('keeps teachers read-only in scheduling while preserving class attendance access', () => {
|
||||
const teacher = permissionsFor('teacher');
|
||||
|
||||
expect(teacher.groups).toEqual(['notification', 'profile']);
|
||||
expect(teacher.extras).toEqual(
|
||||
expect.arrayContaining([
|
||||
'student:view',
|
||||
'class:view',
|
||||
'teacher-workspace:view',
|
||||
'schedule:view',
|
||||
'attendance:view',
|
||||
'attendance:create',
|
||||
'attendance:export',
|
||||
'attendance:self-edit',
|
||||
]),
|
||||
);
|
||||
expect(teacher.extras).not.toEqual(
|
||||
expect.arrayContaining(['class:delete', 'schedule:delete']),
|
||||
expect(teacher.extras).not.toContain('schedule:create');
|
||||
expect(teacher.extras).not.toContain('schedule:edit');
|
||||
expect(teacher.extras).not.toContain('schedule:delete');
|
||||
expect(teacher.extras).not.toContain('student:view');
|
||||
expect(teacher.extras).not.toContain('class:view');
|
||||
expect(teacher.extras).not.toContain('attendance:export');
|
||||
});
|
||||
|
||||
|
||||
it('gives academic administrators the complete teaching administration workflow', () => {
|
||||
const academic = permissionsFor('academic');
|
||||
expect(academic.groups).toEqual(
|
||||
expect.arrayContaining(['student', 'class', 'schedule', 'attendance', 'classroom']),
|
||||
);
|
||||
expect(academic.extras).toEqual(expect.arrayContaining(['sync:read', 'sync:trigger']));
|
||||
});
|
||||
|
||||
it('combines accommodation, expenses, bills and deposits in one operations role', () => {
|
||||
const accommodation = permissionsFor('accommodation_operations');
|
||||
expect(accommodation.groups).toEqual(
|
||||
expect.arrayContaining(['room', 'occupancy', 'expense', 'bill', 'deposit']),
|
||||
);
|
||||
expect(accommodation.extras).toContain('student:basic-view');
|
||||
});
|
||||
|
||||
it('keeps classroom rental operations separate from accommodation operations', () => {
|
||||
const classroomOperations = permissionsFor('classroom_operations');
|
||||
expect(classroomOperations.groups).toEqual(
|
||||
expect.arrayContaining(['classroom', 'rental', 'organization']),
|
||||
);
|
||||
expect(classroomOperations.groups).not.toEqual(expect.arrayContaining(['room', 'deposit']));
|
||||
});
|
||||
|
||||
it('limits system administrators to accounts, permissions, logs and integrations', () => {
|
||||
const systemAdmin = permissionsFor('system_admin');
|
||||
expect(systemAdmin.groups).toEqual(
|
||||
expect.arrayContaining(['user', 'role', 'log', 'integration', 'sync', 'ai']),
|
||||
);
|
||||
expect(systemAdmin.groups).not.toEqual(
|
||||
expect.arrayContaining(['student', 'schedule', 'attendance', 'expense']),
|
||||
);
|
||||
});
|
||||
|
||||
it('gives institution heads every read permission required by the classroom rental pages', () => {
|
||||
const role = permissionsFor('institution_head');
|
||||
expect(role.groups).toEqual(expect.arrayContaining(['classroom', 'rental', 'organization']));
|
||||
});
|
||||
|
||||
it('keeps roles without dashboard access off the dashboard', () => {
|
||||
expect(permissionsFor('teacher').groups).not.toContain('dashboard');
|
||||
expect(permissionsFor('institution_head').groups).not.toContain('dashboard');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user