diff --git a/src/Controllers/admin.controller.ts b/src/Controllers/admin.controller.ts index 083d3c9..526d80f 100644 --- a/src/Controllers/admin.controller.ts +++ b/src/Controllers/admin.controller.ts @@ -1,6 +1,7 @@ import prisma from "../lib/prisma"; import { Request, Response } from "express"; import { AdminLevel } from "@prisma/client"; +import argon2 from "argon2"; const AUTH_ERROR = { type: "failure", @@ -44,3 +45,58 @@ export const getAllAdmins = async (req: Request, res: Response) => { }, }); }; + +interface CreateAdminBody { + name?: string; + password: string; + permission_level: string; + // TODO: Add groups or events +} + +const PERMISSION_LEVELS: readonly AdminLevel[] = ["ELEVATED", "STANDARD"]; // TODO: Enforce completeness + +const isPermissionLevel = (level: string): level is AdminLevel => PERMISSION_LEVELS.includes(level as any); + +// requires: auth(elevated) +export const createAdmin = async (req: Request<{}, {}, CreateAdminBody>, 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, password, permission_level } = req.body || {}; + + if (!(typeof name === "string" && typeof password == "string" && isPermissionLevel(permission_level))) { + return res.status(400).json({ + type: "error", + payload: { + message: "The body of your request did not conform to the requirements", + schema: { + body: { + name: "string", + password_level: "string", + permission_level: "'STANDARD' | 'ELEVATED'", + }, + }, + }, + }); + } + + const password_hash = await argon2.hash(password, { type: argon2.argon2id }); + + // TODO: Check for uniqueness of the name + const user = await prisma.admin.create({ + data: { name, password: password_hash, permission_level }, + select: { pid: true, name: true, permission_level: true }, + }); + + res.status(201).json({ + type: "success", + payload: { + user, + }, + }); +};