2024-05-16 14:02:22 -05:00
|
|
|
import { prisma } from "@/lib/api/db";
|
2024-10-21 12:59:05 -05:00
|
|
|
import updateCustomerEmail from "@/lib/api/stripe/updateCustomerEmail";
|
2024-09-14 15:00:19 -05:00
|
|
|
import { VerifyEmailSchema } from "@/lib/shared/schemaValidation";
|
2024-05-16 14:02:22 -05:00
|
|
|
import type { NextApiRequest, NextApiResponse } from "next";
|
|
|
|
|
|
|
|
export default async function verifyEmail(
|
|
|
|
req: NextApiRequest,
|
|
|
|
res: NextApiResponse
|
|
|
|
) {
|
|
|
|
if (req.method === "POST") {
|
2024-07-18 15:29:59 -05:00
|
|
|
if (process.env.NEXT_PUBLIC_DEMO === "true")
|
2024-07-16 19:33:33 -05:00
|
|
|
return res.status(400).json({
|
|
|
|
response:
|
|
|
|
"This action is disabled because this is a read-only demo of Linkwarden.",
|
|
|
|
});
|
|
|
|
|
2024-09-14 15:00:19 -05:00
|
|
|
const dataValidation = VerifyEmailSchema.safeParse(req.query);
|
2024-05-16 14:02:22 -05:00
|
|
|
|
2024-09-14 15:00:19 -05:00
|
|
|
if (!dataValidation.success) {
|
2024-05-16 14:02:22 -05:00
|
|
|
return res.status(400).json({
|
2024-09-14 15:00:19 -05:00
|
|
|
response: `Error: ${
|
|
|
|
dataValidation.error.issues[0].message
|
|
|
|
} [${dataValidation.error.issues[0].path.join(", ")}]`,
|
2024-05-16 14:02:22 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-09-14 15:00:19 -05:00
|
|
|
const { token } = dataValidation.data;
|
|
|
|
|
2024-05-16 14:02:22 -05:00
|
|
|
// Check token in db
|
|
|
|
const verifyToken = await prisma.verificationToken.findFirst({
|
|
|
|
where: {
|
|
|
|
token,
|
|
|
|
expires: {
|
2024-05-18 11:16:00 -05:00
|
|
|
gt: new Date(),
|
2024-05-16 14:02:22 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const oldEmail = verifyToken?.identifier;
|
|
|
|
|
|
|
|
if (!oldEmail) {
|
|
|
|
return res.status(400).json({
|
|
|
|
response: "Invalid token.",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure email isn't in use
|
|
|
|
const findNewEmail = await prisma.user.findFirst({
|
|
|
|
where: {
|
|
|
|
email: oldEmail,
|
|
|
|
},
|
|
|
|
select: {
|
|
|
|
unverifiedNewEmail: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const newEmail = findNewEmail?.unverifiedNewEmail;
|
|
|
|
|
|
|
|
if (!newEmail) {
|
|
|
|
return res.status(400).json({
|
|
|
|
response: "No unverified emails found.",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const emailInUse = await prisma.user.findFirst({
|
|
|
|
where: {
|
|
|
|
email: newEmail,
|
|
|
|
},
|
|
|
|
select: {
|
|
|
|
email: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log(emailInUse);
|
|
|
|
|
|
|
|
if (emailInUse) {
|
|
|
|
return res.status(400).json({
|
|
|
|
response: "Email is already in use.",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove SSO provider
|
|
|
|
await prisma.account.deleteMany({
|
|
|
|
where: {
|
|
|
|
user: {
|
|
|
|
email: oldEmail,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// Update email in db
|
|
|
|
await prisma.user.update({
|
|
|
|
where: {
|
|
|
|
email: oldEmail,
|
|
|
|
},
|
|
|
|
data: {
|
|
|
|
email: newEmail.toLowerCase().trim(),
|
|
|
|
unverifiedNewEmail: null,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// Apply to Stripe
|
|
|
|
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
|
|
|
|
|
|
|
|
if (STRIPE_SECRET_KEY)
|
|
|
|
await updateCustomerEmail(STRIPE_SECRET_KEY, oldEmail, newEmail);
|
|
|
|
|
|
|
|
// Clean up existing tokens
|
|
|
|
await prisma.verificationToken.delete({
|
|
|
|
where: {
|
|
|
|
token,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
await prisma.verificationToken.deleteMany({
|
|
|
|
where: {
|
|
|
|
identifier: oldEmail,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
return res.status(200).json({
|
|
|
|
response: token,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|