From bff9dcc5f890c5bd070b088a9c13704b70418acf Mon Sep 17 00:00:00 2001 From: Stephan <57194608+stephan418@users.noreply.github.com> Date: Tue, 26 Apr 2022 14:46:23 +0200 Subject: [PATCH] Extract function to create an object by name + Add route to create groups --- src/Controllers/common.ts | 90 +++++++++++++++++++++- src/Controllers/group.controllers.ts | 13 +++- src/Controllers/organisation.controller.ts | 62 ++------------- src/Routes/group.routes.ts | 4 +- 4 files changed, 111 insertions(+), 58 deletions(-) diff --git a/src/Controllers/common.ts b/src/Controllers/common.ts index 994ae79..1658ef5 100644 --- a/src/Controllers/common.ts +++ b/src/Controllers/common.ts @@ -1,4 +1,7 @@ -import { AdminLevel } from "@prisma/client"; +import { AdminLevel, Prisma } from "@prisma/client"; +import { PrismaClientKnownRequestError, PrismaClientUnknownRequestError } from "@prisma/client/runtime"; +import { Request, Response } from "express"; +import prisma from "../lib/prisma"; export enum DataType { STRING = "string", @@ -60,3 +63,88 @@ export const genericError = { message: "There was an error processing your request, please try again later", }, }; + +export function validateName(name: string) { + return name.length > 0; +} + +type Organisation = Partial; +type Group = Partial; + +export async function handleCreateByName( + create: { type: "oragnisation"; data: Organisation }, + link: { type: "event"; id: string }, + req: Request, + res: Response +): Promise; +export async function handleCreateByName( + create: { type: "group"; data: Group }, + link: { type: "oragnisation"; id: string }, + req: Request, + res: Response +): Promise; +export async function handleCreateByName( + create: { type: "oragnisation" | "group"; data: Organisation | Group }, + link: { type: "event" | "oragnisation"; id: string }, + req: Request, + res: Response +) { + if (!req.auth?.isAuthenticated) { + return res.status(500).json(AUTH_ERROR); + } + + if (req.auth.permission_level !== "ELEVATED") { + return res.status(403).json(createInsufficientPermissionsError()); + } + + const { name } = create.data; + + if (typeof name !== "string") { + return res + .status(400) + .json(generateInvalidBodyError({ name: DataType.STRING, [link.type + "Pid"]: DataType.STRING })); + } + + if (!validateName(name)) { + return res.status(400).json({ + type: "error", + payload: { + message: "The name has to be at least 1 character long", + }, + }); + } + + // Check if link object exsits + + try { + // @ts-ignore + const linked = await prisma[link.type].findUnique({ where: { pid: link.id }, select: { id: true } }); + + if (!linked) { + return res.status(404).json({ + type: "error", + payload: { + message: `Could not link to ${link.type} with ID '${link.id}'`, + }, + }); + } + } catch (e) { + // REVIEW: Check for valid UUID + if (e instanceof PrismaClientUnknownRequestError) { + return res.status(400).json({ + type: "error", + payload: { + message: "Unknown error occured. This could be due to malformed IDs", + }, + }); + } + } + + // @ts-ignore + const object = await prisma[create.type].create({ + data: { ...create.data, [link.type]: { connect: { pid: link.id } } }, + select: { pid: true, name: true }, + }); + + res.status(201).json({ type: "success", payload: { [create.type]: object } }); +} diff --git a/src/Controllers/group.controllers.ts b/src/Controllers/group.controllers.ts index ec95ada..54ab975 100644 --- a/src/Controllers/group.controllers.ts +++ b/src/Controllers/group.controllers.ts @@ -2,7 +2,7 @@ import { Admin } from "@prisma/client"; import { PrismaClientUnknownRequestError } from "@prisma/client/runtime"; import { Request, Response } from "express"; import prisma from "../lib/prisma"; -import { generateError, genericError } from "./common"; +import { generateError, genericError, handleCreateByName } from "./common"; const basicGroup = { pid: true, @@ -103,3 +103,14 @@ export const getGroup = async (req: Request, res: Response) return res.status(500).json(genericError); }; + +// at: POST /api/organisations/:eventPid/groups +// requires: auth(ELEVATED) +export const createGroup = async (req: Request<{ organisationPid: string }, {}, { name?: string }>, res: Response) => { + return handleCreateByName( + { type: "group", data: { name: req.body.name, level: 1 } }, + { type: "oragnisation", id: req.params.organisationPid }, + req, + res + ); +}; diff --git a/src/Controllers/organisation.controller.ts b/src/Controllers/organisation.controller.ts index d18cf56..8a22d64 100644 --- a/src/Controllers/organisation.controller.ts +++ b/src/Controllers/organisation.controller.ts @@ -8,6 +8,7 @@ import { generateError, generateInvalidBodyError, genericError, + handleCreateByName, } from "./common"; import { PrismaClientKnownRequestError } from "@prisma/client/runtime"; import { Prisma } from "@prisma/client"; @@ -123,61 +124,12 @@ export const createOrganisation = async ( req: Request, res: Response ) => { - if (!req.auth?.isAuthenticated) { - return res.status(500).json(AUTH_ERROR); - } - - if (req.auth.permission_level !== "ELEVATED") { - return res.status(403).json(createInsufficientPermissionsError()); - } - - const { name } = req.body || {}; - const { eventPid } = req.params; - - if (typeof name !== "string") { - return res.status(400).json(generateInvalidBodyError({ name: DataType.STRING, eventId: DataType.UUID })); - } - - if (!validateOranisationName(name)) { - return res.status(400).json({ - type: "error", - payload: { - message: "The name has to be at least 1 character long", - }, - }); - } - - // Check if event exists - - try { - const event = await prisma.event.findUnique({ where: { pid: eventPid }, select: { id: true } }); - - if (!event) { - return res.status(404).json({ - type: "error", - payload: { - message: `The event with the ID ${eventPid} could not be found`, - }, - }); - } - } catch (e) { - // REVIEW: Check for valid UUID - if (e instanceof PrismaClientUnknownRequestError) { - return res.status(400).send({ - type: "error", - payload: { - message: "Unknown error occured. This could be to malformed IDs", - }, - }); - } - } - - const organisation = await prisma.organisation.create({ - data: { name, event: { connect: { pid: eventPid } } }, - select: detailedOrganisation, - }); - - res.status(201).json({ type: "success", payload: { organisation } }); + return handleCreateByName( + { type: "oragnisation", data: { name: req.body.name } }, + { type: "event", id: req.params.eventPid }, + req, + res + ); }; interface UpdateOrganisationQueryParams { diff --git a/src/Routes/group.routes.ts b/src/Routes/group.routes.ts index 54e43a0..12ae59d 100644 --- a/src/Routes/group.routes.ts +++ b/src/Routes/group.routes.ts @@ -1,5 +1,6 @@ import express from "express"; -import { getAllGroups, getAllGroupsWithParam, getGroup } from "../Controllers/group.controllers"; +import { createGroup, getAllGroups, getAllGroupsWithParam, getGroup } from "../Controllers/group.controllers"; +import { requireAuthentication } from "../Middleware/auth/auth"; import organisationRouter from "./organisation.routes"; const router = express.Router(); @@ -8,5 +9,6 @@ router.get("/", getAllGroups); router.get("/:pid", getGroup); organisationRouter.get("/:organisationPid/groups", getAllGroupsWithParam); +organisationRouter.post("/:organisationPid/groups", requireAuthentication, createGroup); export default router;