diff --git a/messages/en-US.json b/messages/en-US.json index 9fa8e16c..bdecc6e8 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -1766,8 +1766,13 @@ "maxSessionLengthDisabledDescription": "This feature requires a valid license (Enterprise) or active subscription (SaaS)", "selectSessionLength": "Select session length", "passwordExpiryDays": "Password Expiry", - "passwordExpiryDescription": "Set the number of days before users are required to change their password.", + "editPasswordExpiryDescription": "Set the number of days before users are required to change their password.", "selectPasswordExpiry": "Select password expiry", + "30Days": "30 days", + "60Days": "60 days", + "90Days": "90 days", + "180Days": "180 days", + "1Year": "1 year", "subscriptionBadge": "Subscription Required", "authPageErrorUpdateMessage": "An error occurred while updating the auth page settings", "authPageUpdated": "Auth page updated successfully", diff --git a/server/routers/auth/changePassword.ts b/server/routers/auth/changePassword.ts index 6c9d0d7c..0164316e 100644 --- a/server/routers/auth/changePassword.ts +++ b/server/routers/auth/changePassword.ts @@ -18,6 +18,9 @@ import { sessions, resourceSessions } from "@server/db"; import { and, eq, ne, inArray } from "drizzle-orm"; import { passwordSchema } from "@server/auth/passwordSchema"; import { UserType } from "@server/types/UserTypes"; +import { sendEmail } from "@server/emails"; +import ConfirmPasswordReset from "@server/emails/templates/NotifyResetPassword"; +import config from "@server/lib/config"; export const changePasswordBody = z .object({ @@ -158,7 +161,16 @@ export async function changePassword( // Invalidate all sessions except the current one await invalidateAllSessionsExceptCurrent(user.userId, req.session.sessionId); - // TODO: send email to user confirming password change + try { + const email = user.email!; + await sendEmail(ConfirmPasswordReset({ email }), { + from: config.getNoReplyEmail(), + to: email, + subject: "Password Reset Confirmation" + }); + } catch (e) { + logger.error("Failed to send password reset confirmation email", e); + } return response(res, { data: null, diff --git a/src/app/[orgId]/settings/general/page.tsx b/src/app/[orgId]/settings/general/page.tsx index e15a98ac..a210364f 100644 --- a/src/app/[orgId]/settings/general/page.tsx +++ b/src/app/[orgId]/settings/general/page.tsx @@ -65,14 +65,14 @@ const SESSION_LENGTH_OPTIONS = [ { value: 4320, label: "180 days" } // 180 * 24 = 4320 hours ]; -// Password expiry options in days +// Password expiry options in days - will be translated in component const PASSWORD_EXPIRY_OPTIONS = [ - { value: null, label: "Never Expire" }, - { value: 30, label: "30 days" }, - { value: 60, label: "60 days" }, - { value: 90, label: "90 days" }, - { value: 180, label: "180 days" }, - { value: 365, label: "1 year" } + { value: null, labelKey: "neverExpire" }, + { value: 30, labelKey: "30Days" }, + { value: 60, labelKey: "60Days" }, + { value: 90, labelKey: "90Days" }, + { value: 180, labelKey: "180Days" }, + { value: 365, labelKey: "1Year" } ]; // Schema for general organization settings @@ -511,9 +511,7 @@ export default function GeneralPage() { : option.value.toString() } > - { - option.label - } + {t(option.labelKey)} ) )} @@ -523,7 +521,7 @@ export default function GeneralPage() { {t( - "passwordExpiryDescription" + "editPasswordExpiryDescription" )}