From 4d553ca9a60c5f4f28db07484c732360e98ad574 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Mon, 6 Apr 2026 10:53:35 -0700 Subject: [PATCH 1/4] fix(signup): show multiple signup errors at once --- .../reset-password/reset-password-form.tsx | 26 +++++++++---------- apps/sim/app/(auth)/signup/signup-form.tsx | 9 +++---- apps/sim/app/api/auth/reset-password/route.ts | 3 +-- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx index 0ff43b0561a..1f71afcb6ec 100644 --- a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx +++ b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx @@ -104,38 +104,38 @@ export function SetNewPasswordForm({ const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() + const errors: string[] = [] + if (password.length < 8) { - setValidationMessage('Password must be at least 8 characters long') - return + errors.push('Password must be at least 8 characters long') } if (password.length > 100) { - setValidationMessage('Password must not exceed 100 characters') - return + errors.push('Password must not exceed 100 characters') } if (!/[A-Z]/.test(password)) { - setValidationMessage('Password must contain at least one uppercase letter') - return + errors.push('Password must contain at least one uppercase letter') } if (!/[a-z]/.test(password)) { - setValidationMessage('Password must contain at least one lowercase letter') - return + errors.push('Password must contain at least one lowercase letter') } if (!/[0-9]/.test(password)) { - setValidationMessage('Password must contain at least one number') - return + errors.push('Password must contain at least one number') } if (!/[^A-Za-z0-9]/.test(password)) { - setValidationMessage('Password must contain at least one special character') - return + errors.push('Password must contain at least one special character') } if (password !== confirmPassword) { - setValidationMessage('Passwords do not match') + errors.push('Passwords do not match') + } + + if (errors.length > 0) { + setValidationMessage(errors.join(' ')) return } diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index 1b0bd50c05b..bd3dbb595fc 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -229,15 +229,12 @@ function SignupFormContent({ errors.length > 0 ) { if (nameValidationErrors.length > 0) { - setNameErrors([nameValidationErrors[0]]) setShowNameValidationError(true) } if (emailValidationErrors.length > 0) { - setEmailErrors([emailValidationErrors[0]]) setShowEmailValidationError(true) } if (errors.length > 0) { - setPasswordErrors([errors[0]]) setShowValidationError(true) } setIsLoading(false) @@ -400,7 +397,7 @@ function SignupFormContent({ />
0 ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]' @@ -438,7 +435,7 @@ function SignupFormContent({ />
0) || (emailError && !showEmailValidationError) ? 'grid-rows-[1fr]' @@ -497,7 +494,7 @@ function SignupFormContent({
0 ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]' diff --git a/apps/sim/app/api/auth/reset-password/route.ts b/apps/sim/app/api/auth/reset-password/route.ts index 1d47be10354..0ec277543c4 100644 --- a/apps/sim/app/api/auth/reset-password/route.ts +++ b/apps/sim/app/api/auth/reset-password/route.ts @@ -26,8 +26,7 @@ export async function POST(request: NextRequest) { const validationResult = resetPasswordSchema.safeParse(body) if (!validationResult.success) { - const firstError = validationResult.error.errors[0] - const errorMessage = firstError?.message || 'Invalid request data' + const errorMessage = validationResult.error.errors.map((e) => e.message).join(' ') logger.warn('Invalid password reset request data', { errors: validationResult.error.format(), From 8097cfaab549544c628018e8586e7863c8aa197a Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Mon, 6 Apr 2026 13:52:47 -0700 Subject: [PATCH 2/4] Fix reset password error formatting --- .../reset-password/reset-password-form.tsx | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx index 1f71afcb6ec..08ec08b65fc 100644 --- a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx +++ b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx @@ -97,7 +97,7 @@ export function SetNewPasswordForm({ }: SetNewPasswordFormProps) { const [password, setPassword] = useState('') const [confirmPassword, setConfirmPassword] = useState('') - const [validationMessage, setValidationMessage] = useState('') + const [validationMessages, setValidationMessages] = useState([]) const [showPassword, setShowPassword] = useState(false) const [showConfirmPassword, setShowConfirmPassword] = useState(false) @@ -135,11 +135,11 @@ export function SetNewPasswordForm({ } if (errors.length > 0) { - setValidationMessage(errors.join(' ')) + setValidationMessages(errors) return } - setValidationMessage('') + setValidationMessages([]) onSubmit(password) } @@ -162,7 +162,10 @@ export function SetNewPasswordForm({ onChange={(e) => setPassword(e.target.value)} required placeholder='Enter new password' - className={cn('pr-10', validationMessage && 'border-red-500 focus:border-red-500')} + className={cn( + 'pr-10', + validationMessages.length > 0 && 'border-red-500 focus:border-red-500' + )} />
- {validationMessage && ( + {validationMessages.length > 0 && (
-

{validationMessage}

+ {validationMessages.map((error, index) => ( +

{error}

+ ))}
)} From 3ce7320d2527644df10f7171c8c9ac82c92401d8 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Mon, 6 Apr 2026 14:00:23 -0700 Subject: [PATCH 3/4] Remove dead code --- apps/sim/app/(auth)/signup/signup-form.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index bd3dbb595fc..6e33921c6ff 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -228,15 +228,6 @@ function SignupFormContent({ emailValidationErrors.length > 0 || errors.length > 0 ) { - if (nameValidationErrors.length > 0) { - setShowNameValidationError(true) - } - if (emailValidationErrors.length > 0) { - setShowEmailValidationError(true) - } - if (errors.length > 0) { - setShowValidationError(true) - } setIsLoading(false) return } From 51735fccdf51142bdc51eba08685ed410c08dce9 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Mon, 6 Apr 2026 14:18:25 -0700 Subject: [PATCH 4/4] Fix unit tests --- apps/sim/app/api/auth/reset-password/route.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/sim/app/api/auth/reset-password/route.test.ts b/apps/sim/app/api/auth/reset-password/route.test.ts index ee969fe9067..5a8bd79f5e0 100644 --- a/apps/sim/app/api/auth/reset-password/route.test.ts +++ b/apps/sim/app/api/auth/reset-password/route.test.ts @@ -68,7 +68,7 @@ describe('Reset Password API Route', () => { it('should handle missing token', async () => { const req = createMockRequest('POST', { - newPassword: 'newSecurePassword123', + newPassword: 'newSecurePassword123!', }) const response = await POST(req) @@ -97,7 +97,7 @@ describe('Reset Password API Route', () => { it('should handle empty token', async () => { const req = createMockRequest('POST', { token: '', - newPassword: 'newSecurePassword123', + newPassword: 'newSecurePassword123!', }) const response = await POST(req) @@ -119,7 +119,11 @@ describe('Reset Password API Route', () => { const data = await response.json() expect(response.status).toBe(400) - expect(data.message).toBe('Password must be at least 8 characters long') + expect(data.message).toContain('Password must be at least 8 characters long') + expect(data.message).toContain('Password must contain at least one uppercase letter') + expect(data.message).toContain('Password must contain at least one lowercase letter') + expect(data.message).toContain('Password must contain at least one number') + expect(data.message).toContain('Password must contain at least one special character') expect(mockResetPassword).not.toHaveBeenCalled() })