import { prisma } from "@/lib/api/db"; import type { NextApiRequest, NextApiResponse } from "next"; import bcrypt from "bcrypt"; import { PostUserSchema } from "@/lib/shared/schemaValidation"; import isAuthenticatedRequest from "../../isAuthenticatedRequest"; import { Subscription, User } from "@prisma/client"; const emailEnabled = process.env.EMAIL_FROM && process.env.EMAIL_SERVER ? true : false; const stripeEnabled = process.env.STRIPE_SECRET_KEY ? true : false; interface Data { response: string | object; status: number; } export default async function postUser( req: NextApiRequest, res: NextApiResponse ): Promise { const parentUser = await isAuthenticatedRequest({ req }); const isAdmin = parentUser && parentUser.id === Number(process.env.NEXT_PUBLIC_ADMIN || 1); const DISABLE_INVITES = process.env.DISABLE_INVITES === "true"; if (process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true" && !isAdmin) { return { response: "Registration is disabled.", status: 400 }; } const dataValidation = PostUserSchema().safeParse(req.body); if (!dataValidation.success) { return { response: `Error: ${ dataValidation.error.issues[0].message } [${dataValidation.error.issues[0].path.join(", ")}]`, status: 400, }; } const { name, email, password, invite } = dataValidation.data; let { username } = dataValidation.data; if (invite && (DISABLE_INVITES || !emailEnabled)) { return { response: "You are not authorized to invite users.", status: 401 }; } else if (invite && !parentUser) { return { response: "You must be logged in to invite users.", status: 401 }; } const autoGeneratedUsername = "user" + Math.round(Math.random() * 1000000000); if (!username) { username = autoGeneratedUsername; } if (!emailEnabled && !password) { return { response: "Password is required.", status: 400, }; } const checkIfUserExists = await prisma.user.findFirst({ where: { OR: [ { email: email ? email.toLowerCase().trim() : undefined, }, { username: username ? username.toLowerCase().trim() : undefined, }, ], }, }); if (!checkIfUserExists) { const autoGeneratedUsername = "user" + Math.round(Math.random() * 1000000000); const saltRounds = 10; const hashedPassword = bcrypt.hashSync(password || "", saltRounds); const user = await prisma.user.create({ data: { name: name, username: emailEnabled ? username || autoGeneratedUsername : username, email: emailEnabled ? email : undefined, emailVerified: isAdmin ? new Date() : undefined, password: password ? hashedPassword : undefined, parentSubscription: parentUser && invite ? { connect: { id: (parentUser.subscriptions as Subscription).id, }, } : undefined, subscriptions: stripeEnabled && isAdmin ? { create: { stripeSubscriptionId: "fake_sub_" + Math.round(Math.random() * 10000000000000), active: true, currentPeriodStart: new Date(), currentPeriodEnd: new Date( new Date().setFullYear(new Date().getFullYear() + 1000) ), // 1000 years from now }, } : undefined, }, select: isAdmin ? { id: true, username: true, email: true, emailVerified: true, password: true, subscriptions: { select: { active: true, }, }, createdAt: true, } : undefined, }); const { password: pass, ...userWithoutPassword } = user as User; return { response: userWithoutPassword, status: 201 }; } else { return { response: "Email or Username already exists.", status: 400 }; } }