From 1cb41911347050bff78e856db664bf46ccf89c8a Mon Sep 17 00:00:00 2001 From: chaitanyakole Date: Wed, 5 Mar 2025 12:03:41 +0530 Subject: [PATCH] Bug #236457 [admin portal] Password validations are missing while reseting the password by tenant admin and cohort admin. --- public/locales/en/common.json | 22 ++++-- src/components/ResetPassword.tsx | 117 +++++++++++++++++++++++++++---- 2 files changed, 120 insertions(+), 19 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 952118f..1e16469 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -151,11 +151,25 @@ "RESET_PASSWORD": "Reset Password", "NEW_PASSWORD": "New Password", "CONFIRM_PASSWORD": "Confirm Password", - "PASSWORD_RESET_SUCCESSFUL": "Password Reset Successful!", - "PASSWORD_RESET_FAILED": "Password Reset Failed. Please try again.", "ENTER_VALID_PASSWORD": "Enter Valid Password", - "ADD_SINGLE_USER":"Add Single user", - "ADD_MULTIPLE_USERS":"Add Multiple users" + "ADD_SINGLE_USER": "Add Single user", + "ADD_MULTIPLE_USERS": "Add Multiple users", + "PASSWORD_RESET_SUCCESSFUL": "Password has been reset successfully.", + "PASSWORD_RESET_FAILED": "Failed to reset password. Please try again.", + "UNEXPECTED_ERROR": "An unexpected error occurred. Please try again later.", + "RESET_PASSWORD_FOR_USER": "Reset password for user:", + "PASSWORDS_DO_NOT_MATCH": "Passwords do not match.", + "PASSWORD_LENGTH_ERROR": "Password must be at least 8 characters long.", + "PASSWORD_UPPERCASE_ERROR": "Password must contain at least one uppercase letter.", + "PASSWORD_LOWERCASE_ERROR": "Password must contain at least one lowercase letter.", + "PASSWORD_NUMBER_ERROR": "Password must contain at least one number.", + "PASSWORD_SPECIAL_CHAR_ERROR": "Password must contain at least one special character.", + "PASSWORD_COMPLEXITY_REQUIREMENTS": "Password must: \n- Be at least 8 characters long\n- Contain uppercase and lowercase letters\n- Include a number\n- Include a special character" + }, + "HINT": { + "PASSWORD_STRENGTH": { + "GENERAL": "Tip: Create a strong, unique password to protect your account." + } }, "LOGIN_PAGE": { "USERNAME": "Username", diff --git a/src/components/ResetPassword.tsx b/src/components/ResetPassword.tsx index 11e7845..26bd317 100644 --- a/src/components/ResetPassword.tsx +++ b/src/components/ResetPassword.tsx @@ -13,11 +13,16 @@ import { import { useTranslation } from "next-i18next"; import { resetPassword } from "@/services/LoginService"; import { showToastMessage } from "./Toastify"; +import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; interface ResetPasswordModalProps { open: boolean; onClose: () => void; - userData: any; + userData: { + tenantId?: string; + username?: string; + name?: string; + }; } export const ResetPasswordModal: React.FC = ({ @@ -42,15 +47,46 @@ export const ResetPasswordModal: React.FC = ({ onClose(); }; - const validatePasswords = () => { - if (newPassword.length < 8) { - setError("Password must be at least 8 characters long"); + const validatePasswords = (): boolean => { + // Check if passwords match + if (newPassword !== confirmPassword) { + setError(t("COMMON.PASSWORDS_DO_NOT_MATCH")); return false; } - if (newPassword !== confirmPassword) { - setError("Passwords do not match"); + + // Validate password strength + const hasUpperCase = /[A-Z]/.test(newPassword); + const hasLowerCase = /[a-z]/.test(newPassword); + const hasNumber = /\d/.test(newPassword); + const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(newPassword); + const isValidLength = newPassword.length >= 8; + + if (!isValidLength) { + setError(t("COMMON.PASSWORD_LENGTH_ERROR")); + return false; + } + + if (!hasUpperCase) { + setError(t("COMMON.PASSWORD_UPPERCASE_ERROR")); + return false; + } + + if (!hasLowerCase) { + setError(t("COMMON.PASSWORD_LOWERCASE_ERROR")); return false; } + + if (!hasNumber) { + setError(t("COMMON.PASSWORD_NUMBER_ERROR")); + return false; + } + + if (!hasSpecialChar) { + setError(t("COMMON.PASSWORD_SPECIAL_CHAR_ERROR")); + return false; + } + + setError(""); return true; }; @@ -59,34 +95,50 @@ export const ResetPasswordModal: React.FC = ({ setIsLoading(true); setError(""); - const tenantid = userData?.tenantId; + const userObj = { userName: userData?.username, newPassword: newPassword, }; try { - const response = await resetPassword(userObj, tenantid); + const response = await resetPassword(userObj, userData?.tenantId); if (response?.responseCode !== 200) { - throw new Error("Failed to reset password"); + throw new Error(t("COMMON.PASSWORD_RESET_FAILED")); } + showToastMessage(t("COMMON.PASSWORD_RESET_SUCCESSFUL"), "success"); handleClose(); } catch (err) { - setError(err instanceof Error ? err.message : "An error occurred"); - showToastMessage(t("COMMON.PASSWORD_RESET_FAILED"), "error"); + const errorMessage = + err instanceof Error ? err.message : t("COMMON.UNEXPECTED_ERROR"); + + setError(errorMessage); + showToastMessage(errorMessage, "error"); } finally { setIsLoading(false); } }; return ( - + {t("COMMON.RESET_PASSWORD")} - Reset password for user: {userData?.name} + {t("COMMON.RESET_PASSWORD_FOR_USER")}{" "} + {userData?.name} = ({ onChange={(e) => setNewPassword(e.target.value)} margin="normal" error={!!error} + helperText={error && newPassword ? error : ""} + aria-describedby="password-requirements" + InputProps={{ + sx: { + "& input": { + WebkitTextSecurity: "disc", + }, + }, + }} /> = ({ onChange={(e) => setConfirmPassword(e.target.value)} margin="normal" error={!!error} - helperText={error} + helperText={error && confirmPassword ? error : ""} + aria-describedby="password-requirements" + InputProps={{ + sx: { + "& input": { + WebkitTextSecurity: "disc", + }, + }, + }} /> + + + + + {t("COMMON.PASSWORD_COMPLEXITY_REQUIREMENTS")} + + @@ -118,7 +205,7 @@ export const ResetPasswordModal: React.FC = ({