mirror of
https://github.com/documenso/documenso.git
synced 2025-11-14 16:51:38 +10:00
Change password in database to new reset password
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
import { Button } from "@documenso/ui";
|
import { Button } from "@documenso/ui";
|
||||||
import Logo from "./logo";
|
import Logo from "./logo";
|
||||||
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
|
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
|
||||||
@ -11,14 +12,50 @@ interface IResetPassword {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ResetPassword(props: any) {
|
export default function ResetPassword(props: any) {
|
||||||
|
const router = useRouter();
|
||||||
|
const { token } = router.query;
|
||||||
|
|
||||||
const methods = useForm<IResetPassword>();
|
const methods = useForm<IResetPassword>();
|
||||||
const { register, formState, watch } = methods;
|
const { register, formState, watch } = methods;
|
||||||
const password = watch("password", "");
|
const password = watch("password", "");
|
||||||
|
|
||||||
const onSubmit = async (values: IResetPassword) => {
|
const onSubmit = async (values: IResetPassword) => {
|
||||||
|
await toast.promise(
|
||||||
|
fetch(`/api/auth/reset-password`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ password: values.password, token }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
loading: "Resetting...",
|
||||||
|
success: `Reset password successful`,
|
||||||
|
error: "Could not reset password :/",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
console.log(values);
|
console.log(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="w-full max-w-md space-y-8">
|
||||||
|
<div>
|
||||||
|
<Logo className="mx-auto h-20 w-auto"></Logo>
|
||||||
|
<h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900">
|
||||||
|
Reset Password
|
||||||
|
</h2>
|
||||||
|
<p className="mt-2 text-center text-sm text-gray-600">
|
||||||
|
The token you provided is invalid. Please try again.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
<div className="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||||
|
|||||||
@ -24,7 +24,6 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const token = crypto.randomBytes(64).toString("hex");
|
const token = crypto.randomBytes(64).toString("hex");
|
||||||
|
|
||||||
const passwordResetToken = await prisma.passwordResetToken.create({
|
const passwordResetToken = await prisma.passwordResetToken.create({
|
||||||
data: {
|
data: {
|
||||||
token,
|
token,
|
||||||
@ -34,7 +33,7 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
|
|
||||||
await sendResetPassword(user, passwordResetToken.token);
|
await sendResetPassword(user, passwordResetToken.token);
|
||||||
|
|
||||||
res.status(201).end();
|
res.status(200).json({ message: "Password reset email sent." });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defaultHandler({
|
export default defaultHandler({
|
||||||
|
|||||||
@ -1,40 +1,53 @@
|
|||||||
import { NextApiRequest, NextApiResponse } from "next";
|
import { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
import { hashPassword } from "@documenso/lib/auth";
|
||||||
import { sendResetPassword } from "@documenso/lib/mail";
|
import { sendResetPassword } from "@documenso/lib/mail";
|
||||||
import { defaultHandler, defaultResponder } from "@documenso/lib/server";
|
import { defaultHandler, defaultResponder } from "@documenso/lib/server";
|
||||||
import prisma from "@documenso/prisma";
|
import prisma from "@documenso/prisma";
|
||||||
import crypto from "crypto";
|
|
||||||
|
|
||||||
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const { email } = req.body;
|
const { token, password } = req.body;
|
||||||
const cleanEmail = email.toLowerCase();
|
|
||||||
|
|
||||||
if (!cleanEmail || !cleanEmail.includes("@")) {
|
if (!token) {
|
||||||
res.status(422).json({ message: "Invalid email" });
|
res.status(422).json({ message: "Invalid token" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await prisma.user.findFirst({
|
const foundToken = await prisma.passwordResetToken.findUnique({
|
||||||
where: {
|
where: {
|
||||||
email: cleanEmail,
|
token,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
User: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!foundToken) {
|
||||||
return res.status(400).json({ message: "No user found with this email." });
|
return res.status(400).json({ message: "Invalid token." });
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = crypto.randomBytes(64).toString("hex");
|
const hashedPassword = await hashPassword(password);
|
||||||
|
|
||||||
const passwordResetToken = await prisma.passwordResetToken.create({
|
const transaction = await prisma.$transaction([
|
||||||
data: {
|
prisma.user.update({
|
||||||
token,
|
where: {
|
||||||
userId: user.id,
|
id: foundToken.userId,
|
||||||
},
|
},
|
||||||
});
|
data: {
|
||||||
|
password: hashedPassword,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
prisma.passwordResetToken.delete({
|
||||||
|
where: {
|
||||||
|
token,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
await sendResetPassword(user, passwordResetToken.token);
|
if (!transaction) {
|
||||||
|
return res.status(500).json({ message: "Error resetting password." });
|
||||||
|
}
|
||||||
|
|
||||||
res.status(201).end();
|
res.status(200).json({ message: "Password reset successful." });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defaultHandler({
|
export default defaultHandler({
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { getUserFromToken } from "@documenso/lib/server";
|
import { getUserFromToken } from "@documenso/lib/server";
|
||||||
import ResetPassword from "../../components/reset-password";
|
import ResetPassword from "../../../components/reset-password";
|
||||||
|
|
||||||
export default function ResetPasswordPage(props: any) {
|
export default function ResetPasswordPage(props: any) {
|
||||||
return (
|
return (
|
||||||
@ -7,10 +7,7 @@ export const sendResetPassword = async (user: User, token: string) => {
|
|||||||
await sendMail(
|
await sendMail(
|
||||||
user.email,
|
user.email,
|
||||||
"Forgot password?",
|
"Forgot password?",
|
||||||
resetPasswordTemplate(
|
resetPasswordTemplate(`${NEXT_PUBLIC_WEBAPP_URL}/auth/reset/${token}`, "Reset Your Password")
|
||||||
`${NEXT_PUBLIC_WEBAPP_URL}/api/auth/reset/${token}`,
|
|
||||||
"Reset Your Password"
|
|
||||||
)
|
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user