diff --git a/server/emails/templates/NotifyResetPassword.tsx b/server/emails/templates/NotifyResetPassword.tsx new file mode 100644 index 00000000..05ff1f50 --- /dev/null +++ b/server/emails/templates/NotifyResetPassword.tsx @@ -0,0 +1,70 @@ +import { + Body, + Container, + Head, + Heading, + Html, + Preview, + Section, + Text, + Tailwind +} from "@react-email/components"; +import * as React from "react"; + +interface Props { + email: string; +} + +export const ConfirmPasswordReset = ({ email }: Props) => { + const previewText = `Your password has been reset`; + + return ( + + + {previewText} + + + + + Your password has been successfully reset + + + Hi {email || "there"}, + + + This email confirms that your password has just been + reset. If you made this change, no further action is + required. + +
+ + If you did not request this change, please + contact our support team immediately. + +
+ + Thank you for keeping your account secure. + + + Best regards, +
+ Fossorial +
+
+ +
+ + ); +}; + +export default ConfirmPasswordReset; diff --git a/server/emails/templates/ResetPasswordCode.tsx b/server/emails/templates/ResetPasswordCode.tsx index 60c2f0bb..eb2ec7fb 100644 --- a/server/emails/templates/ResetPasswordCode.tsx +++ b/server/emails/templates/ResetPasswordCode.tsx @@ -48,8 +48,8 @@ export const ResetPasswordCode = ({ email, code, link }: Props) => { click here {" "} - and follow the instructions to reset your - password, or manually enter the following code: + and follow the instructions to reset your password, + or manually enter the following code:
@@ -60,6 +60,11 @@ export const ResetPasswordCode = ({ email, code, link }: Props) => { If you didn’t request this, you can safely ignore this email. + + Best regards, +
+ Fossorial +
diff --git a/server/emails/templates/ResourceOTPCode.tsx b/server/emails/templates/ResourceOTPCode.tsx index 20356160..7744400c 100644 --- a/server/emails/templates/ResourceOTPCode.tsx +++ b/server/emails/templates/ResourceOTPCode.tsx @@ -61,6 +61,12 @@ export const ResourceOTPCode = ({ {otp}
+ + + Best regards, +
+ Fossorial +
diff --git a/server/emails/templates/SendInviteLink.tsx b/server/emails/templates/SendInviteLink.tsx index 9612f5d9..d7a4228d 100644 --- a/server/emails/templates/SendInviteLink.tsx +++ b/server/emails/templates/SendInviteLink.tsx @@ -8,7 +8,7 @@ import { Section, Text, Tailwind, - Button, + Button } from "@react-email/components"; import * as React from "react"; @@ -25,7 +25,7 @@ export const SendInviteLink = ({ inviteLink, orgName, inviterName, - expiresInDays, + expiresInDays }: SendInviteLinkProps) => { const previewText = `${inviterName} invited to join ${orgName}`; @@ -33,15 +33,17 @@ export const SendInviteLink = ({ {previewText} - + }} + > @@ -71,6 +73,12 @@ export const SendInviteLink = ({ Accept invitation to {orgName} + + + Best regards, +
+ Fossorial +
diff --git a/server/emails/templates/VerifyEmailCode.tsx b/server/emails/templates/VerifyEmailCode.tsx index 4a1d07ce..fc8978ed 100644 --- a/server/emails/templates/VerifyEmailCode.tsx +++ b/server/emails/templates/VerifyEmailCode.tsx @@ -63,6 +63,11 @@ export const VerifyEmail = ({ If you didn’t request this, you can safely ignore this email. + + Best regards, +
+ Fossorial +
diff --git a/server/routers/auth/resetPassword.ts b/server/routers/auth/resetPassword.ts index 366d8d26..1c358e39 100644 --- a/server/routers/auth/resetPassword.ts +++ b/server/routers/auth/resetPassword.ts @@ -1,3 +1,4 @@ +import config from "@server/config"; import { Request, Response, NextFunction } from "express"; import createHttpError from "http-errors"; import { z } from "zod"; @@ -15,6 +16,8 @@ import { encodeHex } from "oslo/encoding"; import { isWithinExpirationDate } from "oslo"; import { invalidateAllSessions } from "@server/auth"; import logger from "@server/logger"; +import ConfirmPasswordReset from "@server/emails/templates/NotifyResetPassword"; +import { sendEmail } from "@server/emails"; export const resetPasswordBody = z .object({ @@ -141,7 +144,11 @@ export async function resetPassword( .delete(passwordResetTokens) .where(eq(passwordResetTokens.email, email)); - // TODO: send email to user confirming password reset + await sendEmail(ConfirmPasswordReset({ email }), { + from: config.email?.no_reply, + to: email, + subject: "Password Reset Confirmation" + }) return response(res, { data: null, diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx index 37387b85..d0dddd29 100644 --- a/src/components/LoginForm.tsx +++ b/src/components/LoginForm.tsx @@ -62,7 +62,7 @@ export default function LoginForm({ redirect, onLogin }: LoginFormProps) { const [error, setError] = useState(null); const [loading, setLoading] = useState(false); - const [mfaRequested, setMfaRequested] = useState(true); + const [mfaRequested, setMfaRequested] = useState(false); const form = useForm>({ resolver: zodResolver(formSchema),