Pārlūkot izejas kodu

enhance(auth): add password policy validation and tips in multiple languages

charlie 3 dienas atpakaļ
vecāks
revīzija
5a50191139

+ 16 - 0
packages/ui/src/amplify/lang.ts

@@ -4,12 +4,20 @@ export default {
     'reset-password': 'Reset Password',
     'confirm-code': 'Confirm Code',
     'CODE_ON_THE_WAY_TIP': 'Your code is on the way. To log in, enter the code we sent you. It may take a minute to arrive.',
+    'PW_POLICY_TIP': '1. at least 8 characters.\n' +
+      '2. must have lowercase characters.\n' +
+      '3. must have uppercase characters.\n' +
+      '4. must have symbol characters.',
   },
   'zh-cn': {
     'login': '登录',
     'signup': '注册',
     'reset-password': '重置密码',
     'confirm-code': '确认验证码',
+    'PW_POLICY_TIP': '1. 密码长度至少8个字符\n' +
+      '2. 密码必须包含小写字母\n' +
+      '3. 密码必须包含大写字母\n' +
+      '4. 密码必须包含特殊字符',
     'CODE_ON_THE_WAY_TIP': '验证码已发送。请输入我们发送给您的验证码以登录。可能需要一分钟才能收到。',
     'Sign in to your account': '登录到您的账户',
     'Email': '电子邮箱',
@@ -41,6 +49,10 @@ export default {
     'reset-password': '重置密碼',
     'confirm-code': '確認驗證碼',
     'CODE_ON_THE_WAY_TIP': '驗證碼已發送。請輸入我們發送給您的驗證碼以登入。可能需要一分鐘才能收到。',
+    'PW_POLICY_TIP': '1. 密碼長度至少8個字符\n' +
+      '2. 密碼必須包含小寫字母\n' +
+      '3. 密碼必須包含大寫字母\n' +
+      '4. 密碼必須包含特殊字符',
     'Sign in to your account': '登入到您的帳戶',
     'Email': '電子郵箱',
     'Password': '密碼',
@@ -71,6 +83,10 @@ export default {
     'reset-password': 'パスワードをリセットする',
     'confirm-code': 'コードを確認する',
     'CODE_ON_THE_WAY_TIP': 'コードが送信されました。ログインするには、送信したコードを入力してください。届くまでに1分ほどかかる場合があります。',
+    'PW_POLICY_TIP': '1. パスワードは8文字以上であること。\n' +
+      '2. パスワードには小文字を含める必要があります。\n' +
+      '3. パスワードには大文字を含める必要があります。\n' +
+      '4. パスワードには記号を含める必要があります。',
     'Sign in to your account': 'アカウントにサインイン',
     'Email': 'メール',
     'Password': 'パスワード',

+ 27 - 5
packages/ui/src/amplify/ui.tsx

@@ -25,7 +25,10 @@ function ErrorTip({ error, removeError }: {
       {error.title && <AlertTitle>{error.title}</AlertTitle>}
       <AlertDescription>
         <p>
-          {typeof error.message === 'string' ? error.message : JSON.stringify(error.message)}
+          {(typeof error.message === 'string' ? error.message : JSON.stringify(error.message))?.split('\n')
+            .map((line: string, idx: number) => {
+              return <span key={idx}>{line}<br/></span>
+            })}
         </p>
       </AlertDescription>
       <a className={'close absolute right-0 top-0 opacity-50 hover:opacity-80 p-2'}
@@ -37,7 +40,7 @@ function ErrorTip({ error, removeError }: {
 }
 
 function InputRow(
-  props: InputProps & { label: string }
+  props: InputProps & { label: string | React.ReactNode },
 ) {
   const { errors, setErrors } = useAuthFormState()
   const { label, type, ...rest } = props
@@ -55,7 +58,9 @@ function InputRow(
 
   return (
     <div className={'relative w-full flex flex-col gap-3 pb-1'}>
-      <Label htmlFor={props.id}>{label}</Label>
+      <Label htmlFor={props.id}>
+        {label}
+      </Label>
       <Input type={localType} {...rest as any} />
 
       {isPassword && (
@@ -88,6 +93,21 @@ function FormGroup(props: FormHTMLAttributes<any>) {
   )
 }
 
+// 1. Password must be at least 8 characters
+// 2. Password must have lowercase characters
+// 3. Password must have uppercase characters
+// 4. Password must have symbol characters
+function validatePasswordPolicy(password: string) {
+  if (!password ||
+    password.length < 8 ||
+    !/[a-z]/.test(password) ||
+    !/[A-Z]/.test(password) ||
+    !/[!@#$%^&*(),.?":{}|<>]/.test(password)
+  ) {
+    throw new Error(t('PW_POLICY_TIP'))
+  }
+}
+
 function useCountDown() {
   const [countDownNum, setCountDownNum] = useState<number>(0)
   const startCountDown = () => {
@@ -258,10 +278,12 @@ export function SignupForm() {
         const formData = new FormData(e.target as HTMLFormElement)
         const data = Object.fromEntries(formData.entries()) as any
 
-        if (data.password.length < 8) {
+        try {
+          validatePasswordPolicy(data.password)
+        } catch (e) {
           setErrors({
             password: {
-              message: t('Password must be at least 8 characters.'),
+              message: (e as Error).message,
               title: t('Invalid Password')
             }
           })

+ 4 - 0
src/main/frontend/components/user/login.css

@@ -6,6 +6,10 @@
   p {
     @apply text-[inherit];
   }
+
+  .ui__alert-description {
+    @apply -mb-3;
+  }
 }
 
 .ui__dialog-content[label=user-login] {