add team invitation functionality [WIP]

This commit is contained in:
daniel31x13
2024-10-21 13:59:05 -04:00
parent d146ec296c
commit cffc74caa4
32 changed files with 1083 additions and 98 deletions
+61 -48
View File
@@ -1,8 +1,9 @@
import { prisma } from "@/lib/api/db";
import type { NextApiRequest, NextApiResponse } from "next";
import bcrypt from "bcrypt";
import isServerAdmin from "../../isServerAdmin";
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;
@@ -17,7 +18,11 @@ export default async function postUser(
req: NextApiRequest,
res: NextApiResponse
): Promise<Data> {
let isAdmin = await isServerAdmin({ req });
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 };
@@ -34,15 +39,28 @@ export default async function postUser(
};
}
const { name, email, password } = dataValidation.data;
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: [
@@ -62,62 +80,57 @@ export default async function postUser(
const saltRounds = 10;
const hashedPassword = bcrypt.hashSync(password, saltRounds);
const hashedPassword = bcrypt.hashSync(password || "", saltRounds);
// Subscription dates
const currentPeriodStart = new Date();
const currentPeriodEnd = new Date();
currentPeriodEnd.setFullYear(currentPeriodEnd.getFullYear() + 1000); // end date is in 1000 years...
if (isAdmin) {
const user = await prisma.user.create({
data: {
name: name,
username: emailEnabled
? (username as string) || autoGeneratedUsername
: (username as string),
email: emailEnabled ? email : undefined,
password: hashedPassword,
emailVerified: new Date(),
subscriptions: stripeEnabled
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,
currentPeriodEnd,
currentPeriodStart: new Date(),
currentPeriodEnd: new Date(
new Date().setFullYear(new Date().getFullYear() + 1000)
), // 1000 years from now
},
}
: undefined,
},
select: {
id: true,
username: true,
email: true,
emailVerified: true,
subscriptions: {
select: {
active: true,
},
select: isAdmin
? {
id: true,
username: true,
email: true,
emailVerified: true,
password: true,
subscriptions: {
select: {
active: true,
},
},
},
createdAt: true,
},
});
createdAt: true,
}
: undefined,
});
return { response: user, status: 201 };
} else {
await prisma.user.create({
data: {
name: name,
username: emailEnabled ? autoGeneratedUsername : (username as string),
email: emailEnabled ? email : undefined,
password: hashedPassword,
},
});
return { response: "User successfully created.", status: 201 };
}
const { password: pass, ...userWithoutPassword } = user as User;
return { response: userWithoutPassword, status: 201 };
} else {
return { response: "Email or Username already exists.", status: 400 };
}