fix permissions and teacher attendance workflows

This commit is contained in:
2026-07-10 20:40:52 +08:00
parent 247879f276
commit 8ed1682b90
95 changed files with 4745 additions and 1237 deletions

View File

@@ -0,0 +1,64 @@
import { ForbiddenException } from '@nestjs/common';
import { ClassesService } from './classes.service';
describe('ClassesService — teacher data scope', () => {
const classRepo = { find: jest.fn() };
const classStudentRepo = { createQueryBuilder: jest.fn() };
const classTeacherRepo = { find: jest.fn(), findOne: jest.fn() };
const service = new ClassesService(
classRepo as never,
classStudentRepo as never,
classTeacherRepo as never,
{} as never,
{} as never,
{} as never,
{} as never,
);
beforeEach(() => jest.clearAllMocks());
it('returns only class ids assigned to a teacher', async () => {
classTeacherRepo.find.mockResolvedValue([{ classId: 3 }, { classId: 5 }, { classId: 3 }]);
await expect(service.getAccessibleClassIds(21, false)).resolves.toEqual([3, 5]);
});
it('rejects access to a class outside the teacher assignments', async () => {
classTeacherRepo.findOne.mockResolvedValue(null);
await expect(service.assertClassAccess(21, 9, false)).rejects.toBeInstanceOf(
ForbiddenException,
);
});
it('allows class managers to access any class', async () => {
await expect(service.assertClassAccess(21, 9, true)).resolves.toBeUndefined();
expect(classTeacherRepo.findOne).not.toHaveBeenCalled();
});
});
it('clears denormalized teacher ids when the last teacher for that role is removed', async () => {
const classRepo = { update: jest.fn() };
const classTeacherRepo = {
find: jest.fn().mockResolvedValue([]),
delete: jest.fn().mockResolvedValue({ affected: 1 }),
};
const service = new ClassesService(
classRepo as never,
{} as never,
classTeacherRepo as never,
{} as never,
{} as never,
{} as never,
{} as never,
);
await service.removeTeacher(8, 21);
expect(classRepo.update).toHaveBeenCalledWith(8, {
headTeacherId: null,
lifeTeacherId: null,
academicTeacherId: null,
});
});