136 lines
3.9 KiB
TypeScript
136 lines
3.9 KiB
TypeScript
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<Data> {
|
|
const parentUser = await isAuthenticatedRequest({ req });
|
|
const isAdmin =
|
|
parentUser && parentUser.id === Number(process.env.NEXT_PUBLIC_ADMIN || 1);
|
|
|
|
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 && (!stripeEnabled || !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 };
|
|
}
|
|
}
|