diff --git a/backend/src/controllers/auth.ts b/backend/src/controllers/auth.ts index e30a412e..4df138c1 100644 --- a/backend/src/controllers/auth.ts +++ b/backend/src/controllers/auth.ts @@ -41,7 +41,7 @@ export function handleGetFrontendAuthConfig(_req: Request, res: Response): void res.json(getFrontendAuthConfig()); } -export async function handleHello(req: AuthenticatedRequest) { +export async function handleHello(req: AuthenticatedRequest): Promise { const auth: AuthenticationInfo = req.auth!; if (auth.accountType === "teacher") { await createTeacher({ diff --git a/backend/src/middleware/auth/checks/class-auth-checks.ts b/backend/src/middleware/auth/checks/class-auth-checks.ts index 13adf4a8..f51cf740 100644 --- a/backend/src/middleware/auth/checks/class-auth-checks.ts +++ b/backend/src/middleware/auth/checks/class-auth-checks.ts @@ -33,3 +33,26 @@ export const onlyAllowTeacherOfClass = authorize( async (auth: AuthenticationInfo, req: AuthenticatedRequest) => req.params.username === auth.username && teaches(auth.username, req.params.classId), ); + +/** + * Only let the request pass through if the class id in it refers to a class the current user is in (as a student + * or teacher) + */ +function createOnlyAllowIfInClass(onlyTeacher: boolean) { + return authorize( + async (auth: AuthenticationInfo, req: AuthenticatedRequest) => { + const classId = req.params.classId ?? req.params.classid ?? req.params.id; + const clazz = await getClass(classId); + if (clazz == null) { + return false; + } else if (onlyTeacher || auth.accountType === "teacher") { + return auth.username in clazz.teachers; + } else { + return auth.username in clazz.students; + } + } + ); +} + +export const onlyAllowIfInClass = createOnlyAllowIfInClass(false); +export const onlyAllowIfTeacherInClass = createOnlyAllowIfInClass(true); diff --git a/backend/src/routes/classes.ts b/backend/src/routes/classes.ts index e0972988..f2dd7686 100644 --- a/backend/src/routes/classes.ts +++ b/backend/src/routes/classes.ts @@ -7,20 +7,22 @@ import { getTeacherInvitationsHandler, } from '../controllers/classes.js'; import assignmentRouter from './assignments.js'; +import {adminOnly, teachersOnly} from "../middleware/auth/checks/auth-checks"; +import {onlyAllowIfInClass, onlyAllowIfTeacherInClass} from "../middleware/auth/checks/class-auth-checks"; const router = express.Router(); // Root endpoint used to search objects -router.get('/', getAllClassesHandler); +router.get('/', adminOnly, getAllClassesHandler); -router.post('/', createClassHandler); +router.post('/', teachersOnly, createClassHandler); // Information about an class with id 'id' -router.get('/:id', getClassHandler); +router.get('/:id', onlyAllowIfInClass, getClassHandler); -router.get('/:id/teacher-invitations', getTeacherInvitationsHandler); +router.get('/:id/teacher-invitations', onlyAllowIfTeacherInClass, getTeacherInvitationsHandler); -router.get('/:id/students', getClassStudentsHandler); +router.get('/:id/students', onlyAllowIfInClass, getClassStudentsHandler); router.use('/:classid/assignments', assignmentRouter);