import { hash } from "bcrypt"; import { permissionListEnabled } from "../../libs/permissions.js"; import { generateRandomData } from "../../libs/generateRandom.js"; import type { RouteOptions } from "../../libs/types.js"; export function route(routeOptions: RouteOptions) { const { fastify, prisma, tokens, options } = routeOptions; /** * Creates a new user account to use, only if it is enabled. */ fastify.post( "/api/v1/users/create", { schema: { body: { type: "object", required: ["name", "email", "username", "password"], properties: { name: { type: "string" }, username: { type: "string" }, email: { type: "string" }, password: { type: "string" }, }, }, }, }, async (req, res) => { // @ts-ignore const body: { name: string; email: string; password: string; username: string; } = req.body; if (!options.isSignupEnabled) { return res.status(403).send({ error: "Signing up is not enabled at this time.", }); } const userSearch = await prisma.user.findFirst({ where: { email: body.email, }, }); if (userSearch) { return res.status(400).send({ error: "User already exists", }); } const saltedPassword: string = await hash(body.password, 15); const userData = { name: body.name, email: body.email, password: saltedPassword, username: body.username, permissions: { create: [] as { permission: string; has: boolean; }[], }, }; // TODO: There's probably a faster way to pull this off, but I'm lazy for (const permissionKey of Object.keys(permissionListEnabled)) { if ( options.isSignupAsAdminEnabled || permissionKey.startsWith("routes") || permissionKey == "permissions.see" ) { userData.permissions.create.push({ permission: permissionKey, has: permissionListEnabled[permissionKey], }); } } if (options.allowUnsafeGlobalTokens) { // @ts-ignore userData.rootToken = generateRandomData(); // @ts-ignore userData.isRootServiceAccount = true; } const userCreateResults = await prisma.user.create({ data: userData, }); // FIXME(?): Redundant checks if (options.allowUnsafeGlobalTokens) { return { success: true, token: userCreateResults.rootToken, }; } else { const generatedToken = generateRandomData(); tokens[userCreateResults.id] = []; tokens[userCreateResults.id].push({ createdAt: Date.now(), expiresAt: Date.now() + 30 * 60_000, token: generatedToken, }); return { success: true, token: generatedToken, }; } }, ); }