style: fix linting issues met Prettier
This commit is contained in:
parent
7f670030a7
commit
0c47546814
30 changed files with 233 additions and 262 deletions
|
@ -2,10 +2,10 @@ import { UnauthorizedException } from '../exceptions/unauthorized-exception.js';
|
||||||
import { getLogger } from '../logging/initalize.js';
|
import { getLogger } from '../logging/initalize.js';
|
||||||
import { AuthenticatedRequest } from '../middleware/auth/authenticated-request.js';
|
import { AuthenticatedRequest } from '../middleware/auth/authenticated-request.js';
|
||||||
import { envVars, getEnvVar } from '../util/envVars.js';
|
import { envVars, getEnvVar } from '../util/envVars.js';
|
||||||
import {createOrUpdateStudent, createStudent} from "../services/students";
|
import { createOrUpdateStudent, createStudent } from '../services/students';
|
||||||
import {AuthenticationInfo} from "../middleware/auth/authentication-info";
|
import { AuthenticationInfo } from '../middleware/auth/authentication-info';
|
||||||
import {Request, Response} from "express";
|
import { Request, Response } from 'express';
|
||||||
import {createOrUpdateTeacher, createTeacher} from "../services/teachers";
|
import { createOrUpdateTeacher, createTeacher } from '../services/teachers';
|
||||||
|
|
||||||
interface FrontendIdpConfig {
|
interface FrontendIdpConfig {
|
||||||
authority: string;
|
authority: string;
|
||||||
|
@ -47,20 +47,26 @@ export function handleGetFrontendAuthConfig(_req: Request, res: Response): void
|
||||||
|
|
||||||
export async function handleHello(req: AuthenticatedRequest): Promise<void> {
|
export async function handleHello(req: AuthenticatedRequest): Promise<void> {
|
||||||
const auth: AuthenticationInfo = req.auth!;
|
const auth: AuthenticationInfo = req.auth!;
|
||||||
if (auth.accountType === "teacher") {
|
if (auth.accountType === 'teacher') {
|
||||||
await createTeacher({
|
await createTeacher(
|
||||||
|
{
|
||||||
id: auth.username,
|
id: auth.username,
|
||||||
username: auth.username,
|
username: auth.username,
|
||||||
firstName: auth.firstName ?? "",
|
firstName: auth.firstName ?? '',
|
||||||
lastName: auth.lastName ?? "",
|
lastName: auth.lastName ?? '',
|
||||||
}, true);
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
await createStudent({
|
await createStudent(
|
||||||
|
{
|
||||||
id: auth.username,
|
id: auth.username,
|
||||||
username: auth.username,
|
username: auth.username,
|
||||||
firstName: auth.firstName ?? "",
|
firstName: auth.firstName ?? '',
|
||||||
lastName: auth.lastName ?? "",
|
lastName: auth.lastName ?? '',
|
||||||
}, true);
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Request, Response } from 'express';
|
||||||
import { requireFields } from './error-helper.js';
|
import { requireFields } from './error-helper.js';
|
||||||
import { createInvitation, deleteInvitation, getAllInvitations, getInvitation, updateInvitation } from '../services/teacher-invitations.js';
|
import { createInvitation, deleteInvitation, getAllInvitations, getInvitation, updateInvitation } from '../services/teacher-invitations.js';
|
||||||
import { TeacherInvitationData } from '@dwengo-1/common/interfaces/teacher-invitation';
|
import { TeacherInvitationData } from '@dwengo-1/common/interfaces/teacher-invitation';
|
||||||
import {ConflictException} from "../exceptions/conflict-exception";
|
import { ConflictException } from '../exceptions/conflict-exception';
|
||||||
|
|
||||||
export async function getAllInvitationsHandler(req: Request, res: Response): Promise<void> {
|
export async function getAllInvitationsHandler(req: Request, res: Response): Promise<void> {
|
||||||
const username = req.params.username;
|
const username = req.params.username;
|
||||||
|
@ -32,7 +32,7 @@ export async function createInvitationHandler(req: Request, res: Response): Prom
|
||||||
requireFields({ sender, receiver, classId });
|
requireFields({ sender, receiver, classId });
|
||||||
|
|
||||||
if (sender === receiver) {
|
if (sender === receiver) {
|
||||||
throw new ConflictException("Cannot send an invitation to yourself");
|
throw new ConflictException('Cannot send an invitation to yourself');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = req.body as TeacherInvitationData;
|
const data = req.body as TeacherInvitationData;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { JwtPayload } from 'jsonwebtoken';
|
import { JwtPayload } from 'jsonwebtoken';
|
||||||
import { AuthenticationInfo } from './authentication-info.js';
|
import { AuthenticationInfo } from './authentication-info.js';
|
||||||
import * as core from "express-serve-static-core";
|
import * as core from 'express-serve-static-core';
|
||||||
|
|
||||||
export interface AuthenticatedRequest<
|
export interface AuthenticatedRequest<
|
||||||
P = core.ParamsDictionary,
|
P = core.ParamsDictionary,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {fetchClass} from "../../../services/classes";
|
import { fetchClass } from '../../../services/classes';
|
||||||
import {fetchAllGroups} from "../../../services/groups";
|
import { fetchAllGroups } from '../../../services/groups';
|
||||||
import {mapToUsername} from "../../../interfaces/user";
|
import { mapToUsername } from '../../../interfaces/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expects the path to contain the path parameters 'classId' and 'id' (meaning the ID of the assignment).
|
* Expects the path to contain the path parameters 'classId' and 'id' (meaning the ID of the assignment).
|
||||||
|
@ -9,15 +9,12 @@ import {mapToUsername} from "../../../interfaces/user";
|
||||||
* - either teachers of the class the assignment was posted in,
|
* - either teachers of the class the assignment was posted in,
|
||||||
* - or students in a group of the assignment.
|
* - or students in a group of the assignment.
|
||||||
*/
|
*/
|
||||||
export const onlyAllowIfHasAccessToAssignment = authorize(
|
export const onlyAllowIfHasAccessToAssignment = authorize(async (auth, req) => {
|
||||||
async (auth, req) => {
|
const { classid: classId, id: assignmentId } = req.params as { classid: string; id: number };
|
||||||
const { classid: classId, id: assignmentId } = req.params as { classid: string, id: number };
|
if (auth.accountType === 'teacher') {
|
||||||
if (auth.accountType === "teacher") {
|
|
||||||
const clazz = await fetchClass(classId);
|
const clazz = await fetchClass(classId);
|
||||||
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
||||||
}
|
}
|
||||||
const groups = await fetchAllGroups(classId, assignmentId);
|
const groups = await fetchAllGroups(classId, assignmentId);
|
||||||
return groups.some(group => group.members.map((member) => member.username).includes(auth.username) );
|
return groups.some((group) => group.members.map((member) => member.username).includes(auth.username));
|
||||||
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import {AuthenticationInfo} from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import {AuthenticatedRequest} from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
import * as express from "express";
|
import * as express from 'express';
|
||||||
import {UnauthorizedException} from "../../../exceptions/unauthorized-exception";
|
import { UnauthorizedException } from '../../../exceptions/unauthorized-exception';
|
||||||
import {ForbiddenException} from "../../../exceptions/forbidden-exception";
|
import { ForbiddenException } from '../../../exceptions/forbidden-exception';
|
||||||
import {RequestHandler} from "express";
|
import { RequestHandler } from 'express';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Middleware which rejects unauthenticated users (with HTTP 401) and authenticated users which do not fulfill
|
* Middleware which rejects unauthenticated users (with HTTP 401) and authenticated users which do not fulfill
|
||||||
|
@ -14,10 +14,14 @@ import {RequestHandler} from "express";
|
||||||
export function authorize<P, ResBody, ReqBody, ReqQuery, Locals extends Record<string, unknown>>(
|
export function authorize<P, ResBody, ReqBody, ReqQuery, Locals extends Record<string, unknown>>(
|
||||||
accessCondition: (auth: AuthenticationInfo, req: AuthenticatedRequest<P, ResBody, ReqBody, ReqQuery, Locals>) => boolean | Promise<boolean>
|
accessCondition: (auth: AuthenticationInfo, req: AuthenticatedRequest<P, ResBody, ReqBody, ReqQuery, Locals>) => boolean | Promise<boolean>
|
||||||
): RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> {
|
): RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> {
|
||||||
return async (req: AuthenticatedRequest<P,ResBody,ReqBody,ReqQuery,Locals>, _res: express.Response, next: express.NextFunction): Promise<void> => {
|
return async (
|
||||||
|
req: AuthenticatedRequest<P, ResBody, ReqBody, ReqQuery, Locals>,
|
||||||
|
_res: express.Response,
|
||||||
|
next: express.NextFunction
|
||||||
|
): Promise<void> => {
|
||||||
if (!req.auth) {
|
if (!req.auth) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
} else if (!await accessCondition(req.auth, req)) {
|
} else if (!(await accessCondition(req.auth, req))) {
|
||||||
throw new ForbiddenException();
|
throw new ForbiddenException();
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {AuthenticationInfo} from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import {AuthenticatedRequest} from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
import {fetchClass} from "../../../services/classes";
|
import { fetchClass } from '../../../services/classes';
|
||||||
import {mapToUsername} from "../../../interfaces/user";
|
import { mapToUsername } from '../../../interfaces/user';
|
||||||
|
|
||||||
async function teaches(teacherUsername: string, classId: string): Promise<boolean> {
|
async function teaches(teacherUsername: string, classId: string): Promise<boolean> {
|
||||||
const clazz = await fetchClass(classId);
|
const clazz = await fetchClass(classId);
|
||||||
|
@ -14,53 +14,45 @@ async function teaches(teacherUsername: string, classId: string): Promise<boolea
|
||||||
* Only allows requests whose username parameter is equal to the username of the user who is logged in and requests
|
* Only allows requests whose username parameter is equal to the username of the user who is logged in and requests
|
||||||
* whose classId parameter references a class the logged-in user is a teacher of.
|
* whose classId parameter references a class the logged-in user is a teacher of.
|
||||||
*/
|
*/
|
||||||
export const onlyAllowStudentHimselfAndTeachersOfClass = authorize(
|
export const onlyAllowStudentHimselfAndTeachersOfClass = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
if (req.params.username === auth.username) {
|
if (req.params.username === auth.username) {
|
||||||
return true;
|
return true;
|
||||||
} else if (auth.accountType === "teacher") {
|
} else if (auth.accountType === 'teacher') {
|
||||||
return teaches(auth.username, req.params.classId);
|
return teaches(auth.username, req.params.classId);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only let the request pass through if its path parameter "username" is the username of the currently logged-in
|
* Only let the request pass through if its path parameter "username" is the username of the currently logged-in
|
||||||
* teacher and the path parameter "classId" refers to a class the teacher teaches.
|
* teacher and the path parameter "classId" refers to a class the teacher teaches.
|
||||||
*/
|
*/
|
||||||
export const onlyAllowTeacherOfClass = authorize(
|
export const onlyAllowTeacherOfClass = authorize(
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) =>
|
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => req.params.username === auth.username && teaches(auth.username, req.params.classId)
|
||||||
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
|
* 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)
|
* or teacher)
|
||||||
*/
|
*/
|
||||||
export const onlyAllowIfInClass = authorize(
|
export const onlyAllowIfInClass = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
const classId = req.params.classId ?? req.params.classid ?? req.params.id;
|
const classId = req.params.classId ?? req.params.classid ?? req.params.id;
|
||||||
const clazz = await fetchClass(classId);
|
const clazz = await fetchClass(classId);
|
||||||
if (auth.accountType === "teacher") {
|
if (auth.accountType === 'teacher') {
|
||||||
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
||||||
}
|
}
|
||||||
return clazz.students.map(mapToUsername).includes(auth.username);
|
return clazz.students.map(mapToUsername).includes(auth.username);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only allows the request to pass if the 'class' property in its body is a class the current user is a member of.
|
* Only allows the request to pass if the 'class' property in its body is a class the current user is a member of.
|
||||||
*/
|
*/
|
||||||
export const onlyAllowOwnClassInBody = authorize(
|
export const onlyAllowOwnClassInBody = authorize(async (auth, req) => {
|
||||||
async (auth, req) => {
|
|
||||||
const classId = (req.body as { class: string })?.class;
|
const classId = (req.body as { class: string })?.class;
|
||||||
const clazz = await fetchClass(classId);
|
const clazz = await fetchClass(classId);
|
||||||
|
|
||||||
if (auth.accountType === "teacher") {
|
if (auth.accountType === 'teacher') {
|
||||||
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
||||||
}
|
}
|
||||||
return clazz.students.map(mapToUsername).includes(auth.username);
|
return clazz.students.map(mapToUsername).includes(auth.username);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {fetchClass} from "../../../services/classes";
|
import { fetchClass } from '../../../services/classes';
|
||||||
import {fetchGroup} from "../../../services/groups";
|
import { fetchGroup } from '../../../services/groups';
|
||||||
import {mapToUsername} from "../../../interfaces/user";
|
import { mapToUsername } from '../../../interfaces/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expects the path to contain the path parameters 'classid', 'assignmentid' and 'groupid'.
|
* Expects the path to contain the path parameters 'classid', 'assignmentid' and 'groupid'.
|
||||||
|
@ -9,17 +9,17 @@ import {mapToUsername} from "../../../interfaces/user";
|
||||||
* - either teachers of the class the assignment for the group was posted in,
|
* - either teachers of the class the assignment for the group was posted in,
|
||||||
* - or students in the group
|
* - or students in the group
|
||||||
*/
|
*/
|
||||||
export const onlyAllowIfHasAccessToGroup = authorize(
|
export const onlyAllowIfHasAccessToGroup = authorize(async (auth, req) => {
|
||||||
async (auth, req) => {
|
const {
|
||||||
const { classid: classId, assignmentid: assignmentId, groupid: groupId } =
|
classid: classId,
|
||||||
req.params as { classid: string, assignmentid: number, groupid: number };
|
assignmentid: assignmentId,
|
||||||
|
groupid: groupId,
|
||||||
|
} = req.params as { classid: string; assignmentid: number; groupid: number };
|
||||||
|
|
||||||
if (auth.accountType === "teacher") {
|
if (auth.accountType === 'teacher') {
|
||||||
const clazz = await fetchClass(classId);
|
const clazz = await fetchClass(classId);
|
||||||
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
return clazz.teachers.map(mapToUsername).includes(auth.username);
|
||||||
} // User is student
|
} // User is student
|
||||||
const group = await fetchGroup(classId, assignmentId, groupId);
|
const group = await fetchGroup(classId, assignmentId, groupId);
|
||||||
return group.members.map(mapToUsername).includes(auth.username);
|
return group.members.map(mapToUsername).includes(auth.username);
|
||||||
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {AuthenticationInfo} from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import {AuthenticatedRequest} from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only allows requests whose learning path personalization query parameters ('forGroup' / 'assignmentNo' / 'classId')
|
* Only allows requests whose learning path personalization query parameters ('forGroup' / 'assignmentNo' / 'classId')
|
||||||
|
@ -9,15 +9,12 @@ import {AuthenticatedRequest} from "../authenticated-request";
|
||||||
* - or set to a group the user is in,
|
* - or set to a group the user is in,
|
||||||
* - or set to anything if the user is a teacher.
|
* - or set to anything if the user is a teacher.
|
||||||
*/
|
*/
|
||||||
export const onlyAllowPersonalizationForOwnGroup = authorize(
|
export const onlyAllowPersonalizationForOwnGroup = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
const { forGroup, assignmentNo, classId } = req.params;
|
const { forGroup, assignmentNo, classId } = req.params;
|
||||||
if (auth.accountType === "student" && forGroup && assignmentNo && classId) {
|
if (auth.accountType === 'student' && forGroup && assignmentNo && classId) {
|
||||||
// TODO: groupNumber?
|
// TODO: groupNumber?
|
||||||
// Const group = await fetchGroup(Number(classId), Number(assignmentNo), )
|
// Const group = await fetchGroup(Number(classId), Number(assignmentNo), )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {AuthenticationInfo} from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import {AuthenticatedRequest} from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
import {requireFields} from "../../../controllers/error-helper";
|
import { requireFields } from '../../../controllers/error-helper';
|
||||||
import {getLearningObjectId, getQuestionId} from "../../../controllers/questions";
|
import { getLearningObjectId, getQuestionId } from '../../../controllers/questions';
|
||||||
import {fetchQuestion} from "../../../services/questions";
|
import { fetchQuestion } from '../../../services/questions';
|
||||||
import {FALLBACK_SEQ_NUM} from "../../../config";
|
import { FALLBACK_SEQ_NUM } from '../../../config';
|
||||||
import {fetchAnswer} from "../../../services/answers";
|
import { fetchAnswer } from '../../../services/answers';
|
||||||
import {mapToUsername} from "../../../interfaces/user";
|
import { mapToUsername } from '../../../interfaces/user';
|
||||||
|
|
||||||
export const onlyAllowAuthor = authorize(
|
export const onlyAllowAuthor = authorize(
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { author: string }).author === auth.username
|
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { author: string }).author === auth.username
|
||||||
);
|
);
|
||||||
|
|
||||||
export const onlyAllowAuthorRequest = authorize(
|
export const onlyAllowAuthorRequest = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
const hruid = req.params.hruid;
|
const hruid = req.params.hruid;
|
||||||
const version = req.params.version;
|
const version = req.params.version;
|
||||||
const language = req.query.lang as string;
|
const language = req.query.lang as string;
|
||||||
|
@ -26,11 +25,9 @@ export const onlyAllowAuthorRequest = authorize(
|
||||||
const question = await fetchQuestion(questionId);
|
const question = await fetchQuestion(questionId);
|
||||||
|
|
||||||
return question.author.username === auth.username;
|
return question.author.username === auth.username;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export const onlyAllowAuthorRequestAnswer = authorize(
|
export const onlyAllowAuthorRequestAnswer = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
const hruid = req.params.hruid;
|
const hruid = req.params.hruid;
|
||||||
const version = req.params.version;
|
const version = req.params.version;
|
||||||
const language = req.query.lang as string;
|
const language = req.query.lang as string;
|
||||||
|
@ -45,11 +42,9 @@ export const onlyAllowAuthorRequestAnswer = authorize(
|
||||||
const answer = await fetchAnswer(questionId, sequenceNumber);
|
const answer = await fetchAnswer(questionId, sequenceNumber);
|
||||||
|
|
||||||
return answer.author.username === auth.username;
|
return answer.author.username === auth.username;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export const onlyAllowIfHasAccessToQuestion = authorize(
|
export const onlyAllowIfHasAccessToQuestion = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
const hruid = req.params.hruid;
|
const hruid = req.params.hruid;
|
||||||
const version = req.params.version;
|
const version = req.params.version;
|
||||||
const language = req.query.lang as string;
|
const language = req.query.lang as string;
|
||||||
|
@ -62,11 +57,9 @@ export const onlyAllowIfHasAccessToQuestion = authorize(
|
||||||
const question = await fetchQuestion(questionId);
|
const question = await fetchQuestion(questionId);
|
||||||
const group = question.inGroup;
|
const group = question.inGroup;
|
||||||
|
|
||||||
if (auth.accountType === "teacher") {
|
if (auth.accountType === 'teacher') {
|
||||||
const cls = group.assignment.within; // TODO check if contains full objects
|
const cls = group.assignment.within; // TODO check if contains full objects
|
||||||
return cls.teachers.map(mapToUsername).includes(auth.username);
|
return cls.teachers.map(mapToUsername).includes(auth.username);
|
||||||
} // User is student
|
} // User is student
|
||||||
return group.members.map(mapToUsername).includes(auth.username);
|
return group.members.map(mapToUsername).includes(auth.username);
|
||||||
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,29 +1,27 @@
|
||||||
import { languageMap } from "dwengo-1-common/util/language";
|
import { languageMap } from 'dwengo-1-common/util/language';
|
||||||
import { LearningObjectIdentifier } from "../../../entities/content/learning-object-identifier";
|
import { LearningObjectIdentifier } from '../../../entities/content/learning-object-identifier';
|
||||||
import { fetchSubmission } from "../../../services/submissions";
|
import { fetchSubmission } from '../../../services/submissions';
|
||||||
import { AuthenticatedRequest } from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
import { AuthenticationInfo } from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import { authorize } from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import { FALLBACK_LANG } from "../../../config";
|
import { FALLBACK_LANG } from '../../../config';
|
||||||
import { mapToUsername } from "../../../interfaces/user";
|
import { mapToUsername } from '../../../interfaces/user';
|
||||||
|
|
||||||
export const onlyAllowSubmitter = authorize(
|
export const onlyAllowSubmitter = authorize(
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { submitter: string }).submitter === auth.username
|
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { submitter: string }).submitter === auth.username
|
||||||
);
|
);
|
||||||
|
|
||||||
export const onlyAllowIfHasAccessToSubmission = authorize(
|
export const onlyAllowIfHasAccessToSubmission = authorize(async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
||||||
async (auth: AuthenticationInfo, req: AuthenticatedRequest) => {
|
|
||||||
const { hruid: lohruid, id: submissionNumber } = req.params;
|
const { hruid: lohruid, id: submissionNumber } = req.params;
|
||||||
const { language: lang, version: version } = req.query;
|
const { language: lang, version: version } = req.query;
|
||||||
|
|
||||||
const loId = new LearningObjectIdentifier(lohruid, languageMap[lang as string] ?? FALLBACK_LANG, Number(version))
|
const loId = new LearningObjectIdentifier(lohruid, languageMap[lang as string] ?? FALLBACK_LANG, Number(version));
|
||||||
const submission = await fetchSubmission(loId, Number(submissionNumber));
|
const submission = await fetchSubmission(loId, Number(submissionNumber));
|
||||||
|
|
||||||
if (auth.accountType === "teacher") {
|
if (auth.accountType === 'teacher') {
|
||||||
// Dit kan niet werken om dat al deze objecten niet gepopulate zijn.
|
// Dit kan niet werken om dat al deze objecten niet gepopulate zijn.
|
||||||
return submission.onBehalfOf.assignment.within.teachers.map(mapToUsername).includes(auth.username);
|
return submission.onBehalfOf.assignment.within.teachers.map(mapToUsername).includes(auth.username);
|
||||||
}
|
}
|
||||||
|
|
||||||
return submission.onBehalfOf.members.map(mapToUsername).includes(auth.username);
|
return submission.onBehalfOf.members.map(mapToUsername).includes(auth.username);
|
||||||
}
|
});
|
||||||
)
|
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {AuthenticationInfo} from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import {AuthenticatedRequest} from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
|
|
||||||
export const onlyAllowSenderOrReceiver = authorize(
|
export const onlyAllowSenderOrReceiver = authorize(
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) =>
|
(auth: AuthenticationInfo, req: AuthenticatedRequest) => req.params.sender === auth.username || req.params.receiver === auth.username
|
||||||
req.params.sender === auth.username || req.params.receiver === auth.username
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const onlyAllowSender = authorize(
|
export const onlyAllowSender = authorize((auth: AuthenticationInfo, req: AuthenticatedRequest) => req.params.sender === auth.username);
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) =>
|
|
||||||
req.params.sender === auth.username
|
|
||||||
);
|
|
||||||
|
|
||||||
export const onlyAllowSenderBody = authorize(
|
export const onlyAllowSenderBody = authorize(
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) =>
|
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { sender: string }).sender === auth.username
|
||||||
(req.body as { sender: string }).sender === auth.username
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const onlyAllowReceiverBody = authorize(
|
export const onlyAllowReceiverBody = authorize(
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) =>
|
(auth: AuthenticationInfo, req: AuthenticatedRequest) => (req.body as { receiver: string }).receiver === auth.username
|
||||||
(req.body as { receiver: string }).receiver === auth.username
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import {authorize} from "./auth-checks";
|
import { authorize } from './auth-checks';
|
||||||
import {AuthenticationInfo} from "../authentication-info";
|
import { AuthenticationInfo } from '../authentication-info';
|
||||||
import {AuthenticatedRequest} from "../authenticated-request";
|
import { AuthenticatedRequest } from '../authenticated-request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only allow the user whose username is in the path parameter "username" to access the endpoint.
|
* Only allow the user whose username is in the path parameter "username" to access the endpoint.
|
||||||
*/
|
*/
|
||||||
export const onlyAllowUserHimself = authorize(
|
export const onlyAllowUserHimself = authorize((auth: AuthenticationInfo, req: AuthenticatedRequest) => req.params.username === auth.username);
|
||||||
(auth: AuthenticationInfo, req: AuthenticatedRequest) => req.params.username === auth.username
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { createAnswerHandler, deleteAnswerHandler, getAnswerHandler, getAllAnswersHandler, updateAnswerHandler } from '../controllers/answers.js';
|
import { createAnswerHandler, deleteAnswerHandler, getAnswerHandler, getAllAnswersHandler, updateAnswerHandler } from '../controllers/answers.js';
|
||||||
import {adminOnly, teachersOnly} from "../middleware/auth/checks/auth-checks";
|
import { adminOnly, teachersOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
import {
|
import { onlyAllowAuthor, onlyAllowAuthorRequestAnswer, onlyAllowIfHasAccessToQuestion } from '../middleware/auth/checks/question-checks';
|
||||||
onlyAllowAuthor,
|
|
||||||
onlyAllowAuthorRequestAnswer,
|
|
||||||
onlyAllowIfHasAccessToQuestion
|
|
||||||
} from "../middleware/auth/checks/question-checks";
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@ import {
|
||||||
putAssignmentHandler,
|
putAssignmentHandler,
|
||||||
} from '../controllers/assignments.js';
|
} from '../controllers/assignments.js';
|
||||||
import groupRouter from './groups.js';
|
import groupRouter from './groups.js';
|
||||||
import {teachersOnly} from "../middleware/auth/checks/auth-checks";
|
import { teachersOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
import {onlyAllowIfInClass} from "../middleware/auth/checks/class-auth-checks";
|
import { onlyAllowIfInClass } from '../middleware/auth/checks/class-auth-checks';
|
||||||
import {onlyAllowIfHasAccessToAssignment} from "../middleware/auth/checks/assignment-auth-checks";
|
import { onlyAllowIfHasAccessToAssignment } from '../middleware/auth/checks/assignment-auth-checks';
|
||||||
|
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ import {
|
||||||
putClassHandler,
|
putClassHandler,
|
||||||
} from '../controllers/classes.js';
|
} from '../controllers/classes.js';
|
||||||
import assignmentRouter from './assignments.js';
|
import assignmentRouter from './assignments.js';
|
||||||
import {adminOnly, teachersOnly} from "../middleware/auth/checks/auth-checks";
|
import { adminOnly, teachersOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
import {onlyAllowIfInClass} from "../middleware/auth/checks/class-auth-checks";
|
import { onlyAllowIfInClass } from '../middleware/auth/checks/class-auth-checks';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import {
|
||||||
getGroupSubmissionsHandler,
|
getGroupSubmissionsHandler,
|
||||||
putGroupHandler,
|
putGroupHandler,
|
||||||
} from '../controllers/groups.js';
|
} from '../controllers/groups.js';
|
||||||
import {onlyAllowIfHasAccessToGroup} from "../middleware/auth/checks/group-auth-checker";
|
import { onlyAllowIfHasAccessToGroup } from '../middleware/auth/checks/group-auth-checker';
|
||||||
import {teachersOnly} from "../middleware/auth/checks/auth-checks";
|
import { teachersOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
import {onlyAllowIfHasAccessToAssignment} from "../middleware/auth/checks/assignment-auth-checks";
|
import { onlyAllowIfHasAccessToAssignment } from '../middleware/auth/checks/assignment-auth-checks';
|
||||||
|
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { getAllLearningObjects, getAttachment, getLearningObject, getLearningObj
|
||||||
|
|
||||||
import submissionRoutes from './submissions.js';
|
import submissionRoutes from './submissions.js';
|
||||||
import questionRoutes from './questions.js';
|
import questionRoutes from './questions.js';
|
||||||
import {authenticatedOnly} from "../middleware/auth/checks/auth-checks";
|
import { authenticatedOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { getLearningPaths } from '../controllers/learning-paths.js';
|
import { getLearningPaths } from '../controllers/learning-paths.js';
|
||||||
import {authenticatedOnly} from "../middleware/auth/checks/auth-checks";
|
import { authenticatedOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { createQuestionHandler, deleteQuestionHandler, getAllQuestionsHandler, getQuestionHandler } from '../controllers/questions.js';
|
import { createQuestionHandler, deleteQuestionHandler, getAllQuestionsHandler, getQuestionHandler } from '../controllers/questions.js';
|
||||||
import answerRoutes from './answers.js';
|
import answerRoutes from './answers.js';
|
||||||
import {adminOnly, studentsOnly} from "../middleware/auth/checks/auth-checks";
|
import { adminOnly, studentsOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
import {updateAnswerHandler} from "../controllers/answers";
|
import { updateAnswerHandler } from '../controllers/answers';
|
||||||
import {
|
import { onlyAllowAuthor, onlyAllowAuthorRequest, onlyAllowIfHasAccessToQuestion } from '../middleware/auth/checks/question-checks';
|
||||||
onlyAllowAuthor,
|
|
||||||
onlyAllowAuthorRequest,
|
|
||||||
onlyAllowIfHasAccessToQuestion
|
|
||||||
} from "../middleware/auth/checks/question-checks";
|
|
||||||
|
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
|
@ -23,7 +19,7 @@ router.get('/:seq', onlyAllowIfHasAccessToQuestion, getQuestionHandler);
|
||||||
|
|
||||||
router.delete('/:seq', studentsOnly, onlyAllowAuthorRequest, deleteQuestionHandler);
|
router.delete('/:seq', studentsOnly, onlyAllowAuthorRequest, deleteQuestionHandler);
|
||||||
|
|
||||||
router.put("/:seq", studentsOnly, onlyAllowAuthorRequest, updateAnswerHandler);
|
router.put('/:seq', studentsOnly, onlyAllowAuthorRequest, updateAnswerHandler);
|
||||||
|
|
||||||
router.use('/:seq/answers', answerRoutes);
|
router.use('/:seq/answers', answerRoutes);
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import {
|
||||||
getStudentRequestHandler,
|
getStudentRequestHandler,
|
||||||
getStudentRequestsHandler,
|
getStudentRequestsHandler,
|
||||||
} from '../controllers/students.js';
|
} from '../controllers/students.js';
|
||||||
import {onlyAllowUserHimself} from "../middleware/auth/checks/user-auth-checks";
|
import { onlyAllowUserHimself } from '../middleware/auth/checks/user-auth-checks';
|
||||||
import {onlyAllowStudentHimselfAndTeachersOfClass} from "../middleware/auth/checks/class-auth-checks";
|
import { onlyAllowStudentHimselfAndTeachersOfClass } from '../middleware/auth/checks/class-auth-checks';
|
||||||
|
|
||||||
// Under /:username/joinRequests/
|
// Under /:username/joinRequests/
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import {
|
||||||
getStudentSubmissionsHandler,
|
getStudentSubmissionsHandler,
|
||||||
} from '../controllers/students.js';
|
} from '../controllers/students.js';
|
||||||
import joinRequestRouter from './student-join-requests.js';
|
import joinRequestRouter from './student-join-requests.js';
|
||||||
import {onlyAllowUserHimself} from "../middleware/auth/checks/user-auth-checks";
|
import { onlyAllowUserHimself } from '../middleware/auth/checks/user-auth-checks';
|
||||||
import {adminOnly} from "../middleware/auth/checks/auth-checks";
|
import { adminOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,13 @@ import {
|
||||||
getInvitationHandler,
|
getInvitationHandler,
|
||||||
updateInvitationHandler,
|
updateInvitationHandler,
|
||||||
} from '../controllers/teacher-invitations';
|
} from '../controllers/teacher-invitations';
|
||||||
import {onlyAllowUserHimself} from "../middleware/auth/checks/user-auth-checks";
|
import { onlyAllowUserHimself } from '../middleware/auth/checks/user-auth-checks';
|
||||||
import {
|
import {
|
||||||
onlyAllowReceiverBody, onlyAllowSender,
|
onlyAllowReceiverBody,
|
||||||
|
onlyAllowSender,
|
||||||
onlyAllowSenderBody,
|
onlyAllowSenderBody,
|
||||||
onlyAllowSenderOrReceiver
|
onlyAllowSenderOrReceiver,
|
||||||
} from "../middleware/auth/checks/teacher-invitation-checks";
|
} from '../middleware/auth/checks/teacher-invitation-checks';
|
||||||
|
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ import {
|
||||||
} from '../controllers/teachers.js';
|
} from '../controllers/teachers.js';
|
||||||
import invitationRouter from './teacher-invitations.js';
|
import invitationRouter from './teacher-invitations.js';
|
||||||
|
|
||||||
import {adminOnly} from "../middleware/auth/checks/auth-checks";
|
import { adminOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
import {onlyAllowUserHimself} from "../middleware/auth/checks/user-auth-checks";
|
import { onlyAllowUserHimself } from '../middleware/auth/checks/user-auth-checks';
|
||||||
import {onlyAllowTeacherOfClass} from "../middleware/auth/checks/class-auth-checks";
|
import { onlyAllowTeacherOfClass } from '../middleware/auth/checks/class-auth-checks';
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
// Root endpoint used to search objects
|
// Root endpoint used to search objects
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { getThemesHandler, getHruidsByThemeHandler } from '../controllers/themes.js';
|
import { getThemesHandler, getHruidsByThemeHandler } from '../controllers/themes.js';
|
||||||
import {authenticatedOnly} from "../middleware/auth/checks/auth-checks";
|
import { authenticatedOnly } from '../middleware/auth/checks/auth-checks';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment';
|
||||||
import { fetchStudent } from './students.js';
|
import { fetchStudent } from './students.js';
|
||||||
import { NotFoundException } from '../exceptions/not-found-exception.js';
|
import { NotFoundException } from '../exceptions/not-found-exception.js';
|
||||||
import { FALLBACK_VERSION_NUM } from '../config.js';
|
import { FALLBACK_VERSION_NUM } from '../config.js';
|
||||||
import {ConflictException} from "../exceptions/conflict-exception";
|
import { ConflictException } from '../exceptions/conflict-exception';
|
||||||
|
|
||||||
export async function getQuestionsAboutLearningObjectInAssignment(
|
export async function getQuestionsAboutLearningObjectInAssignment(
|
||||||
loId: LearningObjectIdentifier,
|
loId: LearningObjectIdentifier,
|
||||||
|
@ -92,11 +92,11 @@ export async function createQuestion(loId: LearningObjectIdentifier, questionDat
|
||||||
const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment, questionData.inGroup.groupNumber);
|
const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment, questionData.inGroup.groupNumber);
|
||||||
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
throw new NotFoundException("Group with id and assignment not found");
|
throw new NotFoundException('Group with id and assignment not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!group.members.contains(author)) {
|
if (!group.members.contains(author)) {
|
||||||
throw new ConflictException("Author is not part of this group");
|
throw new ConflictException('Author is not part of this group');
|
||||||
}
|
}
|
||||||
|
|
||||||
const question = await questionRepository.createQuestion({
|
const question = await questionRepository.createQuestion({
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
|
||||||
import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request';
|
import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request';
|
||||||
import { ConflictException } from '../exceptions/conflict-exception.js';
|
import { ConflictException } from '../exceptions/conflict-exception.js';
|
||||||
import { Submission } from '../entities/assignments/submission.entity';
|
import { Submission } from '../entities/assignments/submission.entity';
|
||||||
import {mapToUsername} from "../interfaces/user";
|
import { mapToUsername } from '../interfaces/user';
|
||||||
|
|
||||||
export async function getAllStudents(full: boolean): Promise<StudentDTO[] | string[]> {
|
export async function getAllStudents(full: boolean): Promise<StudentDTO[] | string[]> {
|
||||||
const studentRepository = getStudentRepository();
|
const studentRepository = getStudentRepository();
|
||||||
|
|
|
@ -30,7 +30,7 @@ import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
|
||||||
import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request';
|
import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request';
|
||||||
import { ClassStatus } from '@dwengo-1/common/util/class-join-request';
|
import { ClassStatus } from '@dwengo-1/common/util/class-join-request';
|
||||||
import { ConflictException } from '../exceptions/conflict-exception.js';
|
import { ConflictException } from '../exceptions/conflict-exception.js';
|
||||||
import {mapToUsername} from "../interfaces/user";
|
import { mapToUsername } from '../interfaces/user';
|
||||||
|
|
||||||
export async function getAllTeachers(full: boolean): Promise<TeacherDTO[] | string[]> {
|
export async function getAllTeachers(full: boolean): Promise<TeacherDTO[] | string[]> {
|
||||||
const teacherRepository: TeacherRepository = getTeacherRepository();
|
const teacherRepository: TeacherRepository = getTeacherRepository();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue