fix: add verification resend flow
This commit is contained in:
@@ -32,10 +32,18 @@ public class RegisterHandler(
|
|||||||
RegisterRequest request,
|
RegisterRequest request,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
// Check if the user already exists
|
|
||||||
User? existingUser = await userManager.FindByEmailAsync(request.Email);
|
User? existingUser = await userManager.FindByEmailAsync(request.Email);
|
||||||
if (existingUser is not null)
|
if (existingUser is not null)
|
||||||
{
|
{
|
||||||
|
if (!existingUser.EmailConfirmed)
|
||||||
|
{
|
||||||
|
await emailVerificationService.SendVerificationEmailAsync(existingUser);
|
||||||
|
await SendOkAsync(
|
||||||
|
new RegisterResponse("Registration successful! Please check your email to verify your account."),
|
||||||
|
ct);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await SendStringAsync(
|
await SendStringAsync(
|
||||||
"A user with this email already exists",
|
"A user with this email already exists",
|
||||||
400,
|
400,
|
||||||
|
|||||||
@@ -198,7 +198,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resendVerification() {
|
function resendVerification() {
|
||||||
router.push('/verify-email');
|
router.push({
|
||||||
|
path: '/verify-email',
|
||||||
|
query: email.value ? { email: email.value.trim() } : {},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -135,10 +135,12 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useClient } from '@/plugins/api.js';
|
import { useClient } from '@/plugins/api.js';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
import { mdiEye, mdiEyeOff } from '@mdi/js';
|
import { mdiEye, mdiEyeOff } from '@mdi/js';
|
||||||
import { branding } from '@/branding/branding.js';
|
import { branding } from '@/branding/branding.js';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const router = useRouter();
|
||||||
const clientApi = useClient();
|
const clientApi = useClient();
|
||||||
|
|
||||||
const name = ref('');
|
const name = ref('');
|
||||||
@@ -168,9 +170,12 @@
|
|||||||
password: password.value,
|
password: password.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
// On success, show verification message
|
|
||||||
userEmail.value = email.value.trim();
|
userEmail.value = email.value.trim();
|
||||||
registrationSuccess.value = true;
|
registrationSuccess.value = true;
|
||||||
|
await router.push({
|
||||||
|
path: '/verify-email',
|
||||||
|
query: { email: userEmail.value, pending: '1' },
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Registration failed:', error);
|
console.error('Registration failed:', error);
|
||||||
errorMessage.value = error.response?.data?.message || t('registrationFailed');
|
errorMessage.value = error.response?.data?.message || t('registrationFailed');
|
||||||
|
|||||||
@@ -36,28 +36,18 @@
|
|||||||
|
|
||||||
<!-- Error state -->
|
<!-- Error state -->
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else-if="showResendOnly"
|
||||||
class="flex flex-col items-center gap-6"
|
class="flex flex-col items-center gap-6"
|
||||||
>
|
>
|
||||||
<v-icon
|
<v-icon
|
||||||
color="error"
|
color="primary"
|
||||||
icon="mdi-alert-circle"
|
icon="mdi-email-sync"
|
||||||
size="64"
|
size="64"
|
||||||
></v-icon>
|
></v-icon>
|
||||||
<h1 class="text-2xl font-bold text-red-600">{{ t('error.title') }}</h1>
|
<h1 class="text-2xl font-bold">{{ t('pending.title') }}</h1>
|
||||||
<p>{{ errorMessage || t('error.defaultMessage') }}</p>
|
<p>{{ t('pending.message') }}</p>
|
||||||
|
|
||||||
<div class="mt-4 flex flex-col gap-4 w-full">
|
<div class="mt-4 flex flex-col gap-4 w-full">
|
||||||
<v-btn
|
|
||||||
color="primary"
|
|
||||||
@click="goToLogin"
|
|
||||||
>
|
|
||||||
{{ t('error.goToLogin') }}
|
|
||||||
</v-btn>
|
|
||||||
<v-divider class="my-4"></v-divider>
|
|
||||||
|
|
||||||
<!-- Resend verification email section -->
|
|
||||||
<h2 class="text-xl font-medium">{{ t('resend.title') }}</h2>
|
|
||||||
<v-form
|
<v-form
|
||||||
class="w-full"
|
class="w-full"
|
||||||
@submit.prevent="handleResendVerification"
|
@submit.prevent="handleResendVerification"
|
||||||
@@ -99,6 +89,69 @@
|
|||||||
</v-form>
|
</v-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Error state -->
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="flex flex-col items-center gap-6"
|
||||||
|
>
|
||||||
|
<v-icon
|
||||||
|
color="error"
|
||||||
|
icon="mdi-alert-circle"
|
||||||
|
size="64"
|
||||||
|
></v-icon>
|
||||||
|
<h1 class="text-2xl font-bold text-red-600">{{ t('error.title') }}</h1>
|
||||||
|
<p>{{ errorMessage || t('error.defaultMessage') }}</p>
|
||||||
|
|
||||||
|
<div class="mt-4 flex flex-col gap-4 w-full">
|
||||||
|
<v-btn
|
||||||
|
color="primary"
|
||||||
|
@click="goToLogin"
|
||||||
|
>
|
||||||
|
{{ t('error.goToLogin') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-divider class="my-4"></v-divider>
|
||||||
|
|
||||||
|
<h2 class="text-xl font-medium">{{ t('resend.title') }}</h2>
|
||||||
|
<v-form
|
||||||
|
class="w-full"
|
||||||
|
@submit.prevent="handleResendVerification"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<v-text-field
|
||||||
|
v-model="resendEmail"
|
||||||
|
:error-messages="resendEmailError"
|
||||||
|
:label="t('resend.emailLabel')"
|
||||||
|
required
|
||||||
|
type="email"
|
||||||
|
></v-text-field>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
:loading="resendLoading"
|
||||||
|
block
|
||||||
|
color="secondary"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
{{ t('resend.button') }}
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="resendSuccess"
|
||||||
|
class="mt-2 p-3 bg-green-50 border border-green-200 rounded text-green-700 text-sm"
|
||||||
|
>
|
||||||
|
{{ t('resend.success') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="resendError"
|
||||||
|
class="mt-2 p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm"
|
||||||
|
>
|
||||||
|
{{ resendError }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</v-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -118,6 +171,7 @@
|
|||||||
const isLoading = ref(true);
|
const isLoading = ref(true);
|
||||||
const verificationSuccess = ref(false);
|
const verificationSuccess = ref(false);
|
||||||
const errorMessage = ref('');
|
const errorMessage = ref('');
|
||||||
|
const showResendOnly = ref(false);
|
||||||
|
|
||||||
// Resend verification state
|
// Resend verification state
|
||||||
const resendEmail = ref('');
|
const resendEmail = ref('');
|
||||||
@@ -138,7 +192,11 @@
|
|||||||
// Check if we have the required parameters
|
// Check if we have the required parameters
|
||||||
if (!userId || !token) {
|
if (!userId || !token) {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
|
if (route.query.email || route.query.pending) {
|
||||||
|
showResendOnly.value = true;
|
||||||
|
} else {
|
||||||
errorMessage.value = t('error.missingParams');
|
errorMessage.value = t('error.missingParams');
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,8 +260,13 @@
|
|||||||
"missingParams": "Missing required verification parameters.",
|
"missingParams": "Missing required verification parameters.",
|
||||||
"goToLogin": "Go to Login"
|
"goToLogin": "Go to Login"
|
||||||
},
|
},
|
||||||
|
"pending": {
|
||||||
|
"title": "Check your email",
|
||||||
|
"message": "We sent a verification link to your inbox. You can request a new link if it doesn't arrive."
|
||||||
|
},
|
||||||
"resend": {
|
"resend": {
|
||||||
"title": "Resend Verification Email",
|
"title": "Resend Verification Email",
|
||||||
|
"description": "Enter your account email and we'll send a new verification link.",
|
||||||
"emailLabel": "Email",
|
"emailLabel": "Email",
|
||||||
"button": "Resend Verification Email",
|
"button": "Resend Verification Email",
|
||||||
"success": "Verification email sent successfully. Please check your inbox.",
|
"success": "Verification email sent successfully. Please check your inbox.",
|
||||||
@@ -224,8 +287,13 @@
|
|||||||
"missingParams": "Paramètres de vérification requis manquants.",
|
"missingParams": "Paramètres de vérification requis manquants.",
|
||||||
"goToLogin": "Aller à la connexion"
|
"goToLogin": "Aller à la connexion"
|
||||||
},
|
},
|
||||||
|
"pending": {
|
||||||
|
"title": "Vérifiez votre email",
|
||||||
|
"message": "Nous avons envoyé un lien de vérification dans votre boîte de réception. Vous pouvez demander un nouveau lien s'il n'arrive pas."
|
||||||
|
},
|
||||||
"resend": {
|
"resend": {
|
||||||
"title": "Renvoyer l'email de vérification",
|
"title": "Renvoyer l'email de vérification",
|
||||||
|
"description": "Entrez l'email de votre compte et nous enverrons un nouveau lien de vérification.",
|
||||||
"emailLabel": "Email",
|
"emailLabel": "Email",
|
||||||
"button": "Renvoyer l'email de vérification",
|
"button": "Renvoyer l'email de vérification",
|
||||||
"success": "Email de vérification envoyé avec succès. Veuillez vérifier votre boîte de réception.",
|
"success": "Email de vérification envoyé avec succès. Veuillez vérifier votre boîte de réception.",
|
||||||
|
|||||||
Reference in New Issue
Block a user