diff --git a/packages/shared-auth-ui/src/pages/RegisterPage.svelte b/packages/shared-auth-ui/src/pages/RegisterPage.svelte
index 8213e0772..67d502118 100644
--- a/packages/shared-auth-ui/src/pages/RegisterPage.svelte
+++ b/packages/shared-auth-ui/src/pages/RegisterPage.svelte
@@ -33,6 +33,9 @@
resendingVerification?: string;
verificationEmailSent?: string;
checkYourEmail?: string;
+ emailAlreadyRegistered?: string;
+ emailAlreadyRegisteredMessage?: string;
+ goToLogin?: string;
}
/** Default English translations */
@@ -63,6 +66,10 @@
resendingVerification: 'Sending...',
verificationEmailSent: 'Verification email sent! Please check your inbox.',
checkYourEmail: 'Check your email',
+ emailAlreadyRegistered: 'Email already registered',
+ emailAlreadyRegisteredMessage:
+ "An account with this email already exists. If you haven't verified your email yet, resend the verification email.",
+ goToLogin: 'Sign in instead',
};
interface Props {
@@ -124,6 +131,7 @@
let showConfirmPassword = $state(false);
let resendingVerification = $state(false);
let verificationEmailSent = $state(false);
+ let emailAlreadyRegistered = $state(false);
// Theme state - can be toggled manually, defaults to system preference
let userThemePreference = $state<'light' | 'dark' | null>(null);
@@ -217,6 +225,12 @@
} else {
goto(successRedirect);
}
+ } else if (result.error === 'EMAIL_ALREADY_REGISTERED') {
+ emailAlreadyRegistered = true;
+ needsVerification = true;
+ success = true;
+ password = '';
+ confirmPassword = '';
} else {
error = result.error || t.registrationFailed;
}
@@ -322,54 +336,88 @@
{/if}
-
+
{#if success && needsVerification}
-
+
-
-
-
+ {#if emailAlreadyRegistered}
+
+
+
+ {:else}
+
+
+
+ {/if}
- {t.checkYourEmail || 'Check your email'}
+ {emailAlreadyRegistered
+ ? t.emailAlreadyRegistered || 'Email already registered'
+ : t.checkYourEmail || 'Check your email'}
- {t.accountCreated}
+ {emailAlreadyRegistered
+ ? t.emailAlreadyRegisteredMessage ||
+ "An account with this email already exists. If you haven't verified your email yet, resend the verification email."
+ : t.accountCreated}
- {#if onResendVerification}
-
-
- Didn't receive the email?
-
+
+ {#if onResendVerification}
-
- {/if}
+ {/if}
+ {#if emailAlreadyRegistered}
+
goto(loginPath)}
+ class="w-full flex items-center justify-center h-11 rounded-lg font-medium transition-opacity hover:opacity-80 border-[1.5px]"
+ style:border-color={isDark ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.2)'}
+ style:color={isDark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.7)'}
+ style:background-color="transparent"
+ >
+ {t.goToLogin || 'Sign in instead'}
+
+ {/if}
+
{/if}
diff --git a/packages/shared-auth/src/core/authService.ts b/packages/shared-auth/src/core/authService.ts
index 44ec31cd2..4f4c21a52 100644
--- a/packages/shared-auth/src/core/authService.ts
+++ b/packages/shared-auth/src/core/authService.ts
@@ -161,7 +161,13 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
const errorData = await response.json();
if (response.status === 409) {
- return { success: false, error: 'Email already in use' };
+ return {
+ success: false,
+ error:
+ errorData.code === 'EMAIL_ALREADY_REGISTERED'
+ ? 'EMAIL_ALREADY_REGISTERED'
+ : 'Email already in use',
+ };
} else if (response.status === 400) {
return { success: false, error: errorData.message || 'Invalid email or password' };
}
diff --git a/packages/shared-i18n/src/translations/auth/de.json b/packages/shared-i18n/src/translations/auth/de.json
index 0b3bc330f..bde838b37 100644
--- a/packages/shared-i18n/src/translations/auth/de.json
+++ b/packages/shared-i18n/src/translations/auth/de.json
@@ -49,7 +49,10 @@
"resendVerification": "Bestätigungs-E-Mail erneut senden",
"resendingVerification": "Wird gesendet...",
"verificationEmailSent": "Bestätigungs-E-Mail wurde gesendet! Bitte überprüfe deinen Posteingang.",
- "checkYourEmail": "Überprüfe deine E-Mails"
+ "checkYourEmail": "Überprüfe deine E-Mails",
+ "emailAlreadyRegistered": "E-Mail bereits registriert",
+ "emailAlreadyRegisteredMessage": "Ein Konto mit dieser E-Mail-Adresse existiert bereits. Falls du deine E-Mail noch nicht bestätigt hast, sende die Bestätigungs-E-Mail erneut.",
+ "goToLogin": "Stattdessen anmelden"
},
"forgotPassword": {
"titleForm": "Passwort zurücksetzen",
diff --git a/packages/shared-i18n/src/translations/auth/en.json b/packages/shared-i18n/src/translations/auth/en.json
index fd73cbcf5..85a8b2f1a 100644
--- a/packages/shared-i18n/src/translations/auth/en.json
+++ b/packages/shared-i18n/src/translations/auth/en.json
@@ -49,7 +49,10 @@
"resendVerification": "Resend verification email",
"resendingVerification": "Sending...",
"verificationEmailSent": "Verification email sent! Please check your inbox.",
- "checkYourEmail": "Check your email"
+ "checkYourEmail": "Check your email",
+ "emailAlreadyRegistered": "Email already registered",
+ "emailAlreadyRegisteredMessage": "An account with this email already exists. If you haven't verified your email yet, resend the verification email.",
+ "goToLogin": "Sign in instead"
},
"forgotPassword": {
"titleForm": "Reset Password",
diff --git a/packages/shared-i18n/src/translations/auth/index.ts b/packages/shared-i18n/src/translations/auth/index.ts
index b88c64001..6faa66286 100644
--- a/packages/shared-i18n/src/translations/auth/index.ts
+++ b/packages/shared-i18n/src/translations/auth/index.ts
@@ -65,6 +65,9 @@ export interface AuthTranslations {
resendingVerification?: string;
verificationEmailSent?: string;
checkYourEmail?: string;
+ emailAlreadyRegistered?: string;
+ emailAlreadyRegisteredMessage?: string;
+ goToLogin?: string;
};
forgotPassword: {
titleForm: string;
diff --git a/services/mana-auth/src/routes/auth.ts b/services/mana-auth/src/routes/auth.ts
index 561b0b6fe..0689282f5 100644
--- a/services/mana-auth/src/routes/auth.ts
+++ b/services/mana-auth/src/routes/auth.ts
@@ -53,14 +53,25 @@ export function createAuthRoutes(
sourceAppStore.set(body.email, body.sourceAppUrl);
}
- const response = await auth.api.signUpEmail({
- body: {
- email: body.email,
- password: body.password,
- name: body.name || body.email.split('@')[0],
- },
- headers: c.req.raw.headers,
- });
+ let response;
+ try {
+ response = await auth.api.signUpEmail({
+ body: {
+ email: body.email,
+ password: body.password,
+ name: body.name || body.email.split('@')[0],
+ },
+ headers: c.req.raw.headers,
+ });
+ } catch (error) {
+ const isUserExists =
+ (error as any)?.body?.code === 'USER_ALREADY_EXISTS' ||
+ (error as any)?.status === 'UNPROCESSABLE_ENTITY';
+ if (isUserExists) {
+ return c.json({ error: 'Email already registered', code: 'EMAIL_ALREADY_REGISTERED' }, 409);
+ }
+ throw error;
+ }
if (response?.user?.id) {
security.logEvent({ userId: response.user.id, eventType: 'REGISTER' });