mirror of
https://github.com/detleph/server.git
synced 2026-09-04 08:36:06 +02:00
patched review suggestions and discovered bugs
This commit is contained in:
@@ -137,12 +137,14 @@ export const addEvent = async (req: Request, res: Response) => {
|
||||
);
|
||||
}
|
||||
|
||||
const body = result.data;
|
||||
|
||||
const event = await prisma.event.create({
|
||||
data: {
|
||||
name: req.body.name,
|
||||
date: req.body.date,
|
||||
briefDescription: req.body.briefDescription,
|
||||
fullDescription: req.body.fullDescription,
|
||||
name: body.name,
|
||||
date: body.date,
|
||||
briefDescription: body.briefDescription,
|
||||
fullDescription: body.fullDescription,
|
||||
},
|
||||
select: basicEvent,
|
||||
});
|
||||
@@ -206,7 +208,7 @@ export const updateEvent = async (req: Request<{ pid: string }>, res: Response)
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError("discipline", pid);
|
||||
throw new NotFoundError("event", pid);
|
||||
}
|
||||
|
||||
throw e;
|
||||
@@ -231,7 +233,7 @@ export const deleteEvent = async (req: Request<DeleteEventQueryParams>, res: Res
|
||||
return res.status(204).end();
|
||||
} catch (e) {
|
||||
if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError("discipline", pid);
|
||||
throw new NotFoundError("event", pid);
|
||||
}
|
||||
|
||||
throw e;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
|
||||
import { generateInvalidBodyError, DataType } from "./common";
|
||||
import { unlink } from "fs/promises";
|
||||
import ForwardableError from "../Middleware/error/ForwardableError";
|
||||
import { table } from "console";
|
||||
|
||||
require("express-async-errors");
|
||||
|
||||
@@ -204,6 +205,7 @@ export const linkMedia = async (req: Request<{ pid: string }, {}, { mediaPid: st
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const updatedRec = await getPrismaUpdateFKT(tableToUpdate[2])({
|
||||
where: { pid },
|
||||
data: {
|
||||
@@ -211,14 +213,18 @@ export const linkMedia = async (req: Request<{ pid: string }, {}, { mediaPid: st
|
||||
},
|
||||
});
|
||||
|
||||
if (!updatedRec) {
|
||||
return res.status(200).json({
|
||||
type: "success",
|
||||
payload: { message: "Linking with the visual was successful" },
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError(tableToUpdate[2], pid);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
type: "success",
|
||||
payload: {},
|
||||
});
|
||||
throw e;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export const unlinkMedia = async (req: Request<{ pid: string; mediaPid: string }>, res: Response) => {
|
||||
|
||||
@@ -28,7 +28,7 @@ const detailedOrganisation = {
|
||||
pid: true,
|
||||
name: true,
|
||||
date: true,
|
||||
description: true,
|
||||
briefDescription: true,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
@@ -191,7 +191,7 @@ export const updateOrganisation = async (
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError("discipline", pid);
|
||||
throw new NotFoundError("organisation", pid);
|
||||
}
|
||||
|
||||
throw e;
|
||||
|
||||
@@ -16,8 +16,6 @@ const InitialParticipant = z.object({
|
||||
groupPid: z.string().min(1).uuid(),
|
||||
});
|
||||
|
||||
const ParticipantBody = InitialParticipant.extend({ teamPid: z.string().uuid() });
|
||||
|
||||
const returnedParticipant = {
|
||||
pid: true,
|
||||
firstName: true,
|
||||
@@ -41,7 +39,7 @@ const returnedParticipant = {
|
||||
export const createParticipant = async (req: Request<{ teamPid: string }>, res: Response) => {
|
||||
const { teamPid } = req.params;
|
||||
|
||||
const result = ParticipantBody.safeParse(req.body);
|
||||
const result = InitialParticipant.safeParse(req.body);
|
||||
|
||||
if (result.success === false) {
|
||||
return res.status(400).json(
|
||||
@@ -59,20 +57,20 @@ export const createParticipant = async (req: Request<{ teamPid: string }>, res:
|
||||
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
await requireLeaderOfTeam(req.teamleader, teamPid);
|
||||
} else {
|
||||
} else if (req.auth?.permission_level == "STANDARD") {
|
||||
requireResponsibleForGroups(req.auth, body.groupPid);
|
||||
}
|
||||
|
||||
try {
|
||||
const discipline = await prisma.team.findUnique({
|
||||
where: { pid: body.teamPid },
|
||||
where: { pid: teamPid },
|
||||
select: { discipline: true }
|
||||
});
|
||||
|
||||
const maxteamsize = discipline?.discipline.maxTeamSize;
|
||||
|
||||
const userCount = await prisma.participant.count({
|
||||
where: { team: { pid: body.teamPid } }
|
||||
where: { team: { pid: teamPid } }
|
||||
});
|
||||
|
||||
if (maxteamsize == userCount) {
|
||||
@@ -85,7 +83,7 @@ export const createParticipant = async (req: Request<{ teamPid: string }>, res:
|
||||
lastName: body.lastName,
|
||||
relevance: "MEMBER",
|
||||
group: { connect: { pid: body.groupPid } },
|
||||
team: { connect: { pid: body.teamPid } },
|
||||
team: { connect: { pid: teamPid } },
|
||||
},
|
||||
select: returnedParticipant,
|
||||
});
|
||||
@@ -95,7 +93,7 @@ export const createParticipant = async (req: Request<{ teamPid: string }>, res:
|
||||
if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
return res
|
||||
.status(404)
|
||||
.json(generateError(`Could not link to team with ID '${body.teamPid}, or group with ID ${body.groupPid}'`));
|
||||
.json(generateError(`Could not link to team with ID '${teamPid}, or group with ID ${body.groupPid}'`));
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
@@ -107,6 +105,8 @@ export const updateParticipant = async (req: Request<{ pid: string }>, res: Resp
|
||||
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
await requireResponsibleForParticipant(req.teamleader, pid);
|
||||
} else if (req.auth?.permission_level == "STANDARD") {
|
||||
requireResponsibleForGroups(req.auth, await getGroupByParticipantPid(pid));
|
||||
}
|
||||
|
||||
const result = InitialParticipant.partial().safeParse(req.body);
|
||||
@@ -143,7 +143,9 @@ export const updateParticipant = async (req: Request<{ pid: string }>, res: Resp
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError("participant", pid);
|
||||
return res
|
||||
.status(404)
|
||||
.json(generateError(`Could not find participant '${pid}, or link to group with ID ${body.groupPid}.'`));
|
||||
}
|
||||
|
||||
throw e;
|
||||
@@ -156,7 +158,7 @@ export const deleteParticipant = async (req: Request<{ pid: string }>, res: Resp
|
||||
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
await requireResponsibleForParticipant(req.teamleader, pid);
|
||||
} else {
|
||||
} else if (req.auth?.permission_level == "STANDARD") {
|
||||
requireResponsibleForGroups(req.auth, await getGroupByParticipantPid(pid));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Request, Response } from "express";
|
||||
import { z } from "zod";
|
||||
import prisma from "../lib/prisma";
|
||||
@@ -61,7 +62,7 @@ export async function getRolesForTeam(req: Request<{ pid: string }>, res: Respon
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
await requireLeaderOfTeam(req.teamleader, pid);
|
||||
} else {
|
||||
await requireResponsibleForGroups(req.auth, await getGroupsByTeamPid(pid));
|
||||
requireResponsibleForGroups(req.auth, await getGroupsByTeamPid(pid));
|
||||
}
|
||||
|
||||
const roles = await prisma.role.findMany({
|
||||
@@ -84,7 +85,6 @@ export async function getRolesForTeam(req: Request<{ pid: string }>, res: Respon
|
||||
|
||||
const AssignParticipantToRoleBody = z.object({
|
||||
participantPid: z.string().uuid(),
|
||||
teamPid: z.string().uuid(),
|
||||
});
|
||||
|
||||
// requires: auth(leader of the team)
|
||||
@@ -102,25 +102,11 @@ export async function assignParticipantToRole(req: Request<{ pid: string }>, res
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
requireResponsibleForParticipant(req.teamleader, participantPid);
|
||||
} else {
|
||||
await requireResponsibleForGroups(req.auth, await getGroupByParticipantPid(participantPid));
|
||||
requireResponsibleForGroups(req.auth, await getGroupByParticipantPid(participantPid));
|
||||
}
|
||||
|
||||
const schema = await prisma.role.findFirst({
|
||||
where: { pid, team: { participants: { some: { pid: participantPid } } } },
|
||||
select: { participant: { select: { pid: true, firstName: true, lastName: true } } },
|
||||
});
|
||||
|
||||
if (!schema) {
|
||||
return res.status(404).json({
|
||||
type: "error",
|
||||
payload: {
|
||||
message: `No role with the ID '${pid}' could be found in the scope of the participant with the ID '${participantPid}'`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// No error handling should be neccesary as the existence of the role and participant have already been checked above
|
||||
await prisma.role.update({ where: { pid }, data: { participant: { connect: { pid: participantPid } } } });
|
||||
try {
|
||||
const schema = await prisma.role.update({ where: { pid }, data: { participant: { connect: { pid: participantPid } } }, select: detailedRole });
|
||||
|
||||
return res.status(200).json({
|
||||
type: "success",
|
||||
@@ -129,4 +115,16 @@ export async function assignParticipantToRole(req: Request<{ pid: string }>, res
|
||||
...(schema.participant ? { unassigned: schema.participant } : {}),
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
return res.status(404).json({
|
||||
type: "error",
|
||||
payload: {
|
||||
message: `No role with the ID '${pid}' could be found in the scope of the participant with the ID '${participantPid}'`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
|
||||
import { Request, Response } from "express";
|
||||
import { z } from "zod";
|
||||
import prisma from "../lib/prisma";
|
||||
import { DurationSchemaT, parseSchema, PointSchemaT } from "../lib/result_schema";
|
||||
import { DurationSchema, parseSchema, PointSchema } from "../lib/result_schema";
|
||||
import NotFoundError from "../Middleware/error/NotFoundError";
|
||||
import SchemaError from "../Middleware/error/SchemaError";
|
||||
import {
|
||||
@@ -19,7 +19,7 @@ require("express-async-errors");
|
||||
|
||||
const RoleSchemaBody = z.object({
|
||||
name: z.string().min(1),
|
||||
schema: z.string(),
|
||||
schema: z.string(PointSchema).or(z.string(DurationSchema)),
|
||||
});
|
||||
|
||||
const UpdateBody = RoleSchemaBody.partial();
|
||||
@@ -138,7 +138,7 @@ export const createRoleSchema = async (
|
||||
|
||||
export const UpdateRoleSchema = async (req: Request<{ pid: string }>, res: Response) => {
|
||||
if (req.auth?.permission_level !== "ELEVATED") {
|
||||
res.status(403).json(createInsufficientPermissionsError());
|
||||
return res.status(403).json(createInsufficientPermissionsError());
|
||||
}
|
||||
|
||||
const { pid } = req.params;
|
||||
@@ -150,7 +150,7 @@ export const UpdateRoleSchema = async (req: Request<{ pid: string }>, res: Respo
|
||||
generateInvalidBodyError(
|
||||
{
|
||||
name: DataType.STRING,
|
||||
schema: DataType.STRING,
|
||||
schema: DataType.RESULT_SCHEMA,
|
||||
},
|
||||
result.error
|
||||
)
|
||||
|
||||
@@ -7,6 +7,8 @@ import { Prisma } from "@prisma/client";
|
||||
import NotFoundError from "../Middleware/error/NotFoundError";
|
||||
import { requireResponsibleForGroups } from "../Middleware/auth/auth";
|
||||
import AuthError from "../Middleware/error/AuthError";
|
||||
import { runInNewContext } from "vm";
|
||||
import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
|
||||
|
||||
require("express-async-errors");
|
||||
|
||||
@@ -31,6 +33,9 @@ export const basicTeam = {
|
||||
};
|
||||
|
||||
export const getTeams = async (req: Request, res: Response) => {
|
||||
if (req.auth?.permission_level == "STANDARD") {
|
||||
throw new AuthError("A STANDARD Admin is not allowed to get all teams!");
|
||||
}
|
||||
const teams = await prisma.team.findMany({ select: basicTeam });
|
||||
|
||||
res.status(200).json({ type: "success", payload: { teams } });
|
||||
@@ -41,8 +46,8 @@ export const getTeam = async (req: Request<{ pid: string }>, res: Response) => {
|
||||
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
await requireLeaderOfTeam(req.teamleader, pid);
|
||||
} else {
|
||||
await requireResponsibleForGroups(req.auth, pid);
|
||||
} else if (req.auth?.permission_level == "STANDARD") {
|
||||
requireResponsibleForGroups(req.auth, await getGroupsByTeamPid(pid));
|
||||
}
|
||||
|
||||
const team = await prisma.team.findUnique({
|
||||
@@ -62,8 +67,8 @@ export const updateTeam = async (req: Request, res: Response) => {
|
||||
|
||||
if (req.teamleader?.isAuthenticated) {
|
||||
await requireLeaderOfTeam(req.teamleader, pid);
|
||||
} else {
|
||||
await requireResponsibleForGroups(req.auth, await getGroupsByTeamPid(pid));
|
||||
} else if (req.auth?.permission_level == "STANDARD") {
|
||||
requireResponsibleForGroups(req.auth, await getGroupsByTeamPid(pid));
|
||||
}
|
||||
|
||||
const result = TeamBody.omit({ partGroupId: true, partFirstName: true, partLastName: true }).safeParse(req.body);
|
||||
@@ -117,9 +122,17 @@ export const deleteTeam = async (req: Request, res: Response) => {
|
||||
throw new AuthError("STANDARD Admins are not allowed to delete Teams!")
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.team.delete({ where: { pid } });
|
||||
|
||||
res.status(204).json({ type: "success", payload: { message: "Sucesfully deleted team" } });
|
||||
} catch (e) {
|
||||
if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError("team", pid);
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
export async function checkTeamExistence(teamPid: string) {
|
||||
|
||||
@@ -7,6 +7,8 @@ import { DataType, generateError, generateInvalidBodyError } from "./common";
|
||||
import { generateTeamleaderJWT } from "../Middleware/auth/teamleaderAuth";
|
||||
import { createRolesForTeam } from "./role.controller";
|
||||
import { z } from "zod";
|
||||
import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
|
||||
import NotFoundError from "../Middleware/error/NotFoundError";
|
||||
|
||||
require("express-async-errors");
|
||||
|
||||
@@ -49,18 +51,7 @@ export const register = async (req: Request<{}, {}, CreateTeamBody>, res: Respon
|
||||
|
||||
const body = result.data;
|
||||
|
||||
const group = prisma.group.findUnique({ where: { pid: body.partGroupId } });
|
||||
|
||||
if (typeof group == null) {
|
||||
return res.status(404).json(generateError("Specified group was not found!"));
|
||||
}
|
||||
|
||||
const discipline = prisma.discipline.findUnique({ where: { pid: body.disciplineId } });
|
||||
|
||||
if (typeof discipline == null) {
|
||||
return res.status(404).json(generateError("Specified discipline was not found!"));
|
||||
}
|
||||
|
||||
try {
|
||||
const team = await prisma.team.create({
|
||||
data: {
|
||||
leaderEmail: body.leaderEmail,
|
||||
@@ -89,10 +80,26 @@ export const register = async (req: Request<{}, {}, CreateTeamBody>, res: Respon
|
||||
|
||||
(await mailClient).set(usid, team.pid);
|
||||
|
||||
// TODO: fix "eventname"
|
||||
verificationMail(req.body.leaderEmail, "eventname", usid);
|
||||
const eventname = await prisma.discipline.findUnique({ where: { pid: body.disciplineId }, select: { event: { select: { name: true, } } } }).event.name;
|
||||
verificationMail(req.body.leaderEmail, eventname, usid);
|
||||
|
||||
return res.status(201).json({ type: "success", payload: { team } });
|
||||
|
||||
} catch (e) {
|
||||
if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
return res.status(404).json({
|
||||
type: "error",
|
||||
payload: {
|
||||
message: `Could not connect to discipline with the ID '${body.disciplineId}' or could not connect participant to group with the ID '${body.partGroupId}'`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
res.status(201).json({ type: "success", payload: { team } });
|
||||
};
|
||||
|
||||
export const requestToken = async (req: Request, res: Response) => {
|
||||
@@ -117,6 +124,7 @@ export const requestToken = async (req: Request, res: Response) => {
|
||||
(await mailClient).set(usid, team.pid);
|
||||
|
||||
// TODO: fix "eventname"
|
||||
// let teamName = await prisma.team.findUnique({ where: { pid: teamId }, select: { discipline: { select: { event: { select: { name: true } } } } } });
|
||||
verificationMail(team.leaderEmail, "eventname", usid);
|
||||
|
||||
res.status(200).json({ type: "sucess", payload: { message: "Email sent!" } });
|
||||
@@ -145,6 +153,7 @@ export const verifyEmail = async (req: Request, res: Response) => {
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const team = await prisma.team.update({
|
||||
where: {
|
||||
pid: acc,
|
||||
@@ -164,4 +173,12 @@ export const verifyEmail = async (req: Request, res: Response) => {
|
||||
});
|
||||
|
||||
res.status(200).json({ type: "succes", payload: { token } });
|
||||
} catch (e) {
|
||||
if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
throw new NotFoundError("discipline", acc);
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -190,7 +190,7 @@ export function requireResponsibleForGroups(auth: AuthJWTPayload | undefined, gr
|
||||
throw new AuthError("The provided authorization is not valid for the requested operation!");
|
||||
});
|
||||
} else {
|
||||
if (auth?.groups.includes(groupPids)) {
|
||||
if (!auth?.groups.includes(groupPids)) {
|
||||
throw new AuthError("The provided authorization is not valid for the requested operation!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const SchemaVersion = z.enum(["1.0"]);
|
||||
|
||||
const TimeUnit = z.enum(["days", "hours", "minutes", "seconds", "milliseconds"]);
|
||||
|
||||
const DurationSchema = z
|
||||
export const DurationSchema = z
|
||||
.object({
|
||||
type: z.literal("duration"),
|
||||
min: z.number().int({ message: "min must be an integer (relative to smallestUnit)" }),
|
||||
@@ -17,7 +17,7 @@ const DurationSchema = z
|
||||
})
|
||||
.refine(({ min, max }) => min < max, { message: "min must be smaller than max" });
|
||||
|
||||
const PointSchema = z
|
||||
export const PointSchema = z
|
||||
.object({
|
||||
type: z.literal("points"),
|
||||
min: z.number(),
|
||||
|
||||
Reference in New Issue
Block a user