refactor: enum voor account types

This commit is contained in:
Gabriellvl 2025-05-15 20:54:43 +02:00
parent f9fc19d8a6
commit fc0d3b5c84
20 changed files with 77 additions and 5870 deletions

View file

@ -5,6 +5,7 @@ import { envVars, getEnvVar } from '../util/envVars.js';
import { createOrUpdateStudent } from '../services/students.js';
import { Request, Response } from 'express';
import { createOrUpdateTeacher } from '../services/teachers.js';
import {AccountType} from "@dwengo-1/common/util/account-types";
interface FrontendIdpConfig {
authority: string;
@ -55,7 +56,7 @@ export async function postHelloHandler(req: AuthenticatedRequest, res: Response)
firstName: auth.firstName ?? '',
lastName: auth.lastName ?? '',
};
if (auth.accountType === 'student') {
if (auth.accountType === AccountType.Student) {
await createOrUpdateStudent(userData);
logger.debug(`Synchronized student ${userData.username} with IDP`);
} else {

View file

@ -2,6 +2,7 @@ import { authorize } from './auth-checks.js';
import { fetchClass } from '../../../services/classes.js';
import { fetchAllGroups } from '../../../services/groups.js';
import { mapToUsername } from '../../../interfaces/user.js';
import {AccountType} from "@dwengo-1/common/util/account-types";
/**
* Expects the path to contain the path parameters 'classId' and 'id' (meaning the ID of the assignment).
@ -11,7 +12,7 @@ import { mapToUsername } from '../../../interfaces/user.js';
*/
export const onlyAllowIfHasAccessToAssignment = authorize(async (auth, req) => {
const { classid: classId, id: assignmentId } = req.params as { classid: string; id: number };
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
const clazz = await fetchClass(classId);
return clazz.teachers.map(mapToUsername).includes(auth.username);
}

View file

@ -4,6 +4,7 @@ import * as express from 'express';
import { RequestHandler } from 'express';
import { UnauthorizedException } from '../../../exceptions/unauthorized-exception.js';
import { ForbiddenException } from '../../../exceptions/forbidden-exception.js';
import {AccountType} from "@dwengo-1/common/util/account-types";
/**
* Middleware which rejects unauthenticated users (with HTTP 401) and authenticated users which do not fulfill
@ -36,11 +37,11 @@ export const authenticatedOnly = authorize((_) => true);
/**
* Middleware which rejects requests from unauthenticated users or users that aren't students.
*/
export const studentsOnly = authorize((auth) => auth.accountType === 'student');
export const studentsOnly = authorize((auth) => auth.accountType === AccountType.Student);
/**
* Middleware which rejects requests from unauthenticated users or users that aren't teachers.
*/
export const teachersOnly = authorize((auth) => auth.accountType === 'teacher');
export const teachersOnly = authorize((auth) => auth.accountType === AccountType.Teacher);
/**
* Middleware which is to be used on requests no normal user should be able to execute.
* Since there is no concept of administrator accounts yet, currently, those requests will always be blocked.

View file

@ -4,6 +4,7 @@ import { AuthenticatedRequest } from '../authenticated-request.js';
import { fetchClass } from '../../../services/classes.js';
import { mapToUsername } from '../../../interfaces/user.js';
import {getAllInvitations} from "../../../services/teacher-invitations";
import {AccountType} from "@dwengo-1/common/util/account-types";
async function teaches(teacherUsername: string, classId: string): Promise<boolean> {
const clazz = await fetchClass(classId);
@ -18,7 +19,7 @@ async function teaches(teacherUsername: string, classId: string): Promise<boolea
export const onlyAllowStudentHimselfAndTeachersOfClass = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
if (req.params.username === auth.username) {
return true;
} else if (auth.accountType === 'teacher') {
} else if (auth.accountType === AccountType.Teacher) {
return teaches(auth.username, req.params.classId);
}
return false;
@ -39,7 +40,7 @@ export const onlyAllowTeacherOfClass = authorize(
export const onlyAllowIfInClass = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
const classId = req.params.classId ?? req.params.classid ?? req.params.id;
const clazz = await fetchClass(classId);
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
return clazz.teachers.map(mapToUsername).includes(auth.username);
}
return clazz.students.map(mapToUsername).includes(auth.username);
@ -48,7 +49,7 @@ export const onlyAllowIfInClass = authorize(async (auth: AuthenticationInfo, req
export const onlyAllowIfInClassOrInvited = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
const classId = req.params.classId ?? req.params.classid ?? req.params.id;
const clazz = await fetchClass(classId);
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
const invitations = await getAllInvitations(auth.username, false);
return clazz.teachers.map(mapToUsername).includes(auth.username) || invitations.some(invitation => invitation.classId === classId);
}
@ -62,7 +63,7 @@ export const onlyAllowOwnClassInBody = authorize(async (auth, req) => {
const classId = (req.body as { class: string })?.class;
const clazz = await fetchClass(classId);
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
return clazz.teachers.map(mapToUsername).includes(auth.username);
}
return clazz.students.map(mapToUsername).includes(auth.username);

View file

@ -2,6 +2,7 @@ import { authorize } from './auth-checks.js';
import { fetchClass } from '../../../services/classes.js';
import { fetchGroup } from '../../../services/groups.js';
import { mapToUsername } from '../../../interfaces/user.js';
import {AccountType} from "@dwengo-1/common/util/account-types";
/**
* Expects the path to contain the path parameters 'classid', 'assignmentid' and 'groupid'.
@ -16,7 +17,7 @@ export const onlyAllowIfHasAccessToGroup = authorize(async (auth, req) => {
groupid: groupId,
} = req.params as { classid: string; assignmentid: number; groupid: number };
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
const clazz = await fetchClass(classId);
return clazz.teachers.map(mapToUsername).includes(auth.username);
} // User is student

View file

@ -1,6 +1,7 @@
import { authorize } from './auth-checks';
import { AuthenticationInfo } from '../authentication-info';
import { AuthenticatedRequest } from '../authenticated-request';
import {AccountType} from "@dwengo-1/common/util/account-types";
/**
* Only allows requests whose learning path personalization query parameters ('forGroup' / 'assignmentNo' / 'classId')
@ -11,7 +12,7 @@ import { AuthenticatedRequest } from '../authenticated-request';
*/
export const onlyAllowPersonalizationForOwnGroup = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
const { forGroup, assignmentNo, classId } = req.params;
if (auth.accountType === 'student' && forGroup && assignmentNo && classId) {
if (auth.accountType === AccountType.Student && forGroup && assignmentNo && classId) {
// TODO: groupNumber?
// Const group = await fetchGroup(Number(classId), Number(assignmentNo), )
return false;

View file

@ -7,6 +7,7 @@ import { fetchQuestion } from '../../../services/questions.js';
import { FALLBACK_SEQ_NUM } from '../../../config.js';
import { fetchAnswer } from '../../../services/answers.js';
import { mapToUsername } from '../../../interfaces/user.js';
import {AccountType} from "@dwengo-1/common/util/account-types";
export const onlyAllowAuthor = authorize(
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { author: string }).author === auth.username
@ -57,7 +58,7 @@ export const onlyAllowIfHasAccessToQuestion = authorize(async (auth: Authenticat
const question = await fetchQuestion(questionId);
const group = question.inGroup;
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
const cls = group.assignment.within; // TODO check if contains full objects
return cls.teachers.map(mapToUsername).includes(auth.username);
} // User is student

View file

@ -6,6 +6,7 @@ import { AuthenticationInfo } from '../authentication-info.js';
import { authorize } from './auth-checks.js';
import { FALLBACK_LANG } from '../../../config.js';
import { mapToUsername } from '../../../interfaces/user.js';
import {AccountType} from "@dwengo-1/common/util/account-types";
export const onlyAllowSubmitter = authorize(
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { submitter: string }).submitter === auth.username
@ -18,7 +19,7 @@ export const onlyAllowIfHasAccessToSubmission = authorize(async (auth: Authentic
const loId = new LearningObjectIdentifier(lohruid, languageMap[lang as string] ?? FALLBACK_LANG, Number(version));
const submission = await fetchSubmission(loId, Number(submissionNumber));
if (auth.accountType === 'teacher') {
if (auth.accountType === AccountType.Teacher) {
// Dit kan niet werken om dat al deze objecten niet gepopulate zijn.
return submission.onBehalfOf.assignment.within.teachers.map(mapToUsername).includes(auth.username);
}