From 7dc9dd155888e52f9031f61d2f227adac1e7b3d3 Mon Sep 17 00:00:00 2001 From: Laurin <60652077+Flexla54@users.noreply.github.com> Date: Mon, 30 May 2022 12:21:28 +0200 Subject: [PATCH] adding team router/cont and participant router --- src/Controllers/participant.controller.ts | 233 ++++++++++++---------- src/Controllers/team.controller.ts | 0 src/Controllers/user_auth.controller.ts | 28 +-- src/Routes/participant.routes.ts | 30 +++ src/Routes/team.routes.ts | 12 ++ 5 files changed, 186 insertions(+), 117 deletions(-) create mode 100644 src/Controllers/team.controller.ts create mode 100644 src/Routes/participant.routes.ts create mode 100644 src/Routes/team.routes.ts diff --git a/src/Controllers/participant.controller.ts b/src/Controllers/participant.controller.ts index 8a1bb55..cfc6e59 100644 --- a/src/Controllers/participant.controller.ts +++ b/src/Controllers/participant.controller.ts @@ -1,10 +1,17 @@ import prisma from "../lib/prisma"; import { z } from "zod"; import { Request, Response } from "express"; -import { createInsufficientPermissionsError, DataType, generateError, generateInvalidBodyError } from "./common"; +import { + AUTH_ERROR, + createInsufficientPermissionsError, + DataType, + generateError, + generateInvalidBodyError, +} from "./common"; import { Job, Prisma } from "@prisma/client"; import { PrismaClientKnownRequestError } from "@prisma/client/runtime"; import NotFoundError from "../Middleware/error/NotFoundError"; +import { requireResponsibleForGroup } from "../Middleware/auth/auth"; //TODO: add TeamleaderAuthentification @@ -12,127 +19,145 @@ import NotFoundError from "../Middleware/error/NotFoundError"; // an admin the group of whom overlaps with the team AND an elevated admin const ParticipantBody = z.object({ - firstName: z.string(), - lastName: z.string(), - groupId: z.string().uuid(), - //job: z.enum(["TEAMLEADER", "MEMBER"]), + firstName: z.string(), + lastName: z.string(), + groupId: z.string().uuid(), + //job: z.enum(["TEAMLEADER", "MEMBER"]), }); const returnedParticipant = { - pid: true, - firstName: true, - lastName: true, - relevance: true, - team: { select: { - pid: true, - name: true, - } }, - group: { select: { - pid: true, - name: true, - } }, + pid: true, + firstName: true, + lastName: true, + relevance: true, + team: { + select: { + pid: true, + name: true, + }, + }, + group: { + select: { + pid: true, + name: true, + }, + }, } as const; // REVIEW: Location of this endpoints (/groups, /teams, /participants, ...?) -export const createParticipant = async (req: Request<{ pid: string}>, res: Response) => { - //insert TeamleaderAuth +export const createParticipant = async (req: Request<{ pid: string }>, res: Response) => { + const result = ParticipantBody.safeParse(req.body); - const result = ParticipantBody.safeParse(req.body); + if (result.success === false) { + return res.status(400).json( + generateInvalidBodyError( + { + firstname: DataType.STRING, + lastName: DataType.STRING, + groupId: DataType.UUID, + }, + result.error + ) + ); + } + const body = result.data; + const { pid } = req.params; - if(result.success === false){ - return res.status(400).json( - generateInvalidBodyError({ - firstname: DataType.STRING, - lastName: DataType.STRING, - groupId: DataType.UUID, - }, result.error) - ); + /* + if (!req.auth?.isAuthenticated || req.teamleader?.team != pid) { + return res.status(500).json(AUTH_ERROR); + } + if (req.teamleader?.team != pid) { + return res.status(500).json(AUTH_ERROR); + } + requireResponsibleForGroup(req.auth, req.body.groupId); + */ + + try { + const participant = await prisma.participant.create({ + data: { + firstName: body.firstName, + lastName: body.lastName, + relevance: "MEMBER", + group: { connect: { pid: body.groupId } }, + team: { connect: { pid } }, + }, + select: returnedParticipant, + }); + + return res.status(201).json({ + type: "success", + payload: { participant }, + }); + } catch (e) { + if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { + return res + .status(404) + .json(generateError(`Could not link to team with ID '${pid}, or group with ID ${body.groupId}'`)); } - - const body = result.data; - const { pid } = req.params; - - try { - const participant = await prisma.participant.create({ - data: { - firstName: body.firstName, - lastName: body.lastName, - relevance: "MEMBER", - group: { connect: { pid: body.groupId } }, - team: { connect: { pid } }, - }, - select: returnedParticipant, - }); - - return res.status(201).json({ - type: "success", - payload: { participant }, - }); - } catch (e) { - if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { - return res.status(404).json(generateError(`Could not link to team with ID '${pid}, or group with ID ${body.groupId}'`)); - } - throw e; - } -} + throw e; + } +}; export const updateParticipant = async (req: Request<{ pid: string }>, res: Response) => { - //insert TeamleaderAuth + //insert TeamleaderAuth - const result = ParticipantBody.partial().safeParse(req.body); // Should be partial, right? + const result = ParticipantBody.partial().safeParse(req.body); // Should be partial, right? - if(result.success === false){ - return res.status(400).json( - generateInvalidBodyError({ - firstname: DataType.STRING, - lastName: DataType.STRING, - groupId: DataType.UUID, - }, result.error) - ); + if (result.success === false) { + return res.status(400).json( + generateInvalidBodyError( + { + firstname: DataType.STRING, + lastName: DataType.STRING, + groupId: DataType.UUID, + }, + result.error + ) + ); + } + + const body = result.data; + const { pid } = req.params; + + try { + const participant = await prisma.participant.update({ + where: { pid }, + data: { + firstName: body.firstName, + lastName: body.lastName, + group: { connect: { pid: body.groupId } }, + }, + select: returnedParticipant, + }); + + res.status(200).json({ + type: "success", + payload: { participant }, + }); + } catch (e) { + if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { + throw new NotFoundError("participant", pid); } - const body = result.data; - const { pid } = req.params; - - try { - const participant = await prisma.participant.update({ - where: { pid }, - data: { - firstName: body.firstName, - lastName: body.lastName, - group: { connect: { pid: body.groupId, } }, - }, - select: returnedParticipant, - }); - - res.status(200).json({ - type: "success", - payload: { participant }, - }); - - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") { - throw new NotFoundError("participant", pid) - } - - throw e; - } -} + throw e; + } +}; export const deleteParticipant = async (req: Request<{ pid: string }>, res: Response) => { - //insert TeamleaderAuth + //insert TeamleaderAuth - const { pid } = req.params; + const { pid } = req.params; - try { - await prisma.participant.delete({ where: { pid } }); + try { + await prisma.participant.delete({ where: { pid } }); - return res.status(204).end(); - } catch (e) { - if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { - return res.status(404).json(generateError(`The participant with the ID ${pid} could not be found`)); - } - - throw e; + return res.status(204).end(); + } catch (e) { + if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { + return res.status(404).json(generateError(`The participant with the ID ${pid} could not be found`)); } -} + + throw e; + } +}; diff --git a/src/Controllers/team.controller.ts b/src/Controllers/team.controller.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/Controllers/user_auth.controller.ts b/src/Controllers/user_auth.controller.ts index 067addf..405bf97 100644 --- a/src/Controllers/user_auth.controller.ts +++ b/src/Controllers/user_auth.controller.ts @@ -15,7 +15,7 @@ const TeamBody = z.object({ partFirstName: z.string().min(1), partLastName: z.string().min(1), partGroupId: z.string().uuid(), -}) +}); interface CreateTeamBody { teamName: string; @@ -28,19 +28,21 @@ interface CreateTeamBody { // TODO: Some kind of auth (Teamleader probably) export const register = async (req: Request<{}, {}, CreateTeamBody>, res: Response) => { - const result = TeamBody.safeParse(req.body); if (result.success === false) { return res.status(400).json( - generateInvalidBodyError({ - teamName: DataType.STRING, - leaderEmail: DataType.STRING, - disciplineId: DataType.UUID, - partFirstName: DataType.STRING, - partLastName: DataType.STRING, - partGroupId: DataType.UUID, - }, result.error) + generateInvalidBodyError( + { + teamName: DataType.STRING, + leaderEmail: DataType.STRING, + disciplineId: DataType.UUID, + partFirstName: DataType.STRING, + partLastName: DataType.STRING, + partGroupId: DataType.UUID, + }, + result.error + ) ); } @@ -58,8 +60,8 @@ export const register = async (req: Request<{}, {}, CreateTeamBody>, res: Respon lastName: body.partLastName, relevance: "TEAMLEADER", group: { connect: { pid: body.partGroupId } }, - } - } + }, + }, }, select: { pid: true, @@ -68,7 +70,7 @@ export const register = async (req: Request<{}, {}, CreateTeamBody>, res: Respon }, }); - //To do: maybe use returned amount of created use? + //TODO: maybe use returned amount of created use? createRolesForTeam(team.pid); const usid = nanoid(); diff --git a/src/Routes/participant.routes.ts b/src/Routes/participant.routes.ts new file mode 100644 index 0000000..21937a2 --- /dev/null +++ b/src/Routes/participant.routes.ts @@ -0,0 +1,30 @@ +import express from "express"; +import teamRouter from "./team.routes"; +import { createParticipant, deleteParticipant, updateParticipant } from "../Controllers/participant.controller"; +import { requireAuthentication } from "../Middleware/auth/auth"; +import { requireTeamleaderAuthentication } from "../Middleware/auth/teamleaderAuth"; + +const router = express.Router(); + +teamRouter.post<"/:pid/participant/", { pid: string }>( + "/:pid/participant/", + requireAuthentication, + requireTeamleaderAuthentication, + createParticipant +); + +teamRouter.patch<"/:pid/participant/", { pid: string }>( + "/:pid/participant/", + requireAuthentication, + requireTeamleaderAuthentication, + updateParticipant +); + +teamRouter.delete<"/:pid/participant/", { pid: string }>( + "/:pid/participant/", + requireAuthentication, + requireTeamleaderAuthentication, + deleteParticipant +); + +export default router; diff --git a/src/Routes/team.routes.ts b/src/Routes/team.routes.ts new file mode 100644 index 0000000..c05b60c --- /dev/null +++ b/src/Routes/team.routes.ts @@ -0,0 +1,12 @@ +import express from "express"; +import { requireAuthentication } from "../Middleware/auth/auth"; +import { requireTeamleaderAuthentication } from "../Middleware/auth/teamleaderAuth"; +import { register } from "../Controllers/user_auth.controller"; + +const router = express.Router(); + +router.post("/", requireAuthentication, requireTeamleaderAuthentication, register); + +router.delete<"/:pid/", { pid: string }>("/:pid/", requireAuthentication, requireTeamleaderAuthentication, deleteTeam); + +export default router;