fix: confirm email changes and enforce clean backend build
This commit is contained in:
55
frontend/src/api/schema.d.ts
vendored
55
frontend/src/api/schema.d.ts
vendored
@@ -308,6 +308,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/users/confirm-email-change": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["SocializeApiModulesIdentityHandlersConfirmEmailChangeHandler"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/users/forgot-password": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1262,6 +1278,9 @@ export interface components {
|
||||
/** Format: date-time */
|
||||
birthDate?: string;
|
||||
};
|
||||
SocializeApiModulesIdentityHandlersChangeEmailResponse: {
|
||||
message?: string;
|
||||
};
|
||||
SocializeApiModulesIdentityHandlersChangeEmailRequest: {
|
||||
email?: string | null;
|
||||
};
|
||||
@@ -1279,6 +1298,10 @@ export interface components {
|
||||
/** Format: binary */
|
||||
file: string;
|
||||
};
|
||||
SocializeApiModulesIdentityHandlersConfirmEmailChangeResponse: {
|
||||
message?: string;
|
||||
};
|
||||
SocializeApiModulesIdentityHandlersConfirmEmailChangeRequest: Record<string, never>;
|
||||
SocializeApiModulesIdentityHandlersForgotPasswordRequest: {
|
||||
email?: string;
|
||||
};
|
||||
@@ -2529,12 +2552,14 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description No Content */
|
||||
204: {
|
||||
/** @description Success */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
content: {
|
||||
"application/json": components["schemas"]["SocializeApiModulesIdentityHandlersChangeEmailResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
@@ -2670,6 +2695,30 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
SocializeApiModulesIdentityHandlersConfirmEmailChangeHandler: {
|
||||
parameters: {
|
||||
query: {
|
||||
userId: string;
|
||||
email: string;
|
||||
token: string;
|
||||
};
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Success */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["SocializeApiModulesIdentityHandlersConfirmEmailChangeResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
SocializeApiModulesIdentityHandlersForgotPasswordHandler: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
icon="mdi-check-circle"
|
||||
size="64"
|
||||
></v-icon>
|
||||
<h1 class="text-2xl font-bold text-green-600">{{ t('success.title') }}</h1>
|
||||
<p>{{ t('success.message') }}</p>
|
||||
<h1 class="text-2xl font-bold text-green-600">
|
||||
{{ t(isEmailChange ? 'success.emailChangeTitle' : 'success.title') }}
|
||||
</h1>
|
||||
<p>{{ t(isEmailChange ? 'success.emailChangeMessage' : 'success.message') }}</p>
|
||||
<v-btn
|
||||
color="primary"
|
||||
@click="goToLogin"
|
||||
@@ -172,6 +174,7 @@
|
||||
const verificationSuccess = ref(false);
|
||||
const errorMessage = ref('');
|
||||
const showResendOnly = ref(false);
|
||||
const isEmailChange = ref(false);
|
||||
|
||||
// Resend verification state
|
||||
const resendEmail = ref('');
|
||||
@@ -183,6 +186,8 @@
|
||||
onMounted(async () => {
|
||||
const userId = route.query.userId;
|
||||
const token = route.query.token;
|
||||
const email = route.query.email;
|
||||
isEmailChange.value = route.query.changeEmail === 'true';
|
||||
|
||||
// Populate resend email field if it was in the URL
|
||||
if (route.query.email) {
|
||||
@@ -190,7 +195,7 @@
|
||||
}
|
||||
|
||||
// Check if we have the required parameters
|
||||
if (!userId || !token) {
|
||||
if (!userId || !token || (isEmailChange.value && !email)) {
|
||||
isLoading.value = false;
|
||||
if (route.query.email || route.query.pending) {
|
||||
showResendOnly.value = true;
|
||||
@@ -201,8 +206,10 @@
|
||||
}
|
||||
|
||||
try {
|
||||
// Call the verification endpoint
|
||||
await clientApi.get(`/api/users/verify-email?userId=${userId}&token=${token}`);
|
||||
const endpoint = isEmailChange.value
|
||||
? `/api/users/confirm-email-change?userId=${encodeURIComponent(userId)}&email=${encodeURIComponent(email)}&token=${encodeURIComponent(token)}`
|
||||
: `/api/users/verify-email?userId=${encodeURIComponent(userId)}&token=${encodeURIComponent(token)}`;
|
||||
await clientApi.get(endpoint);
|
||||
verificationSuccess.value = true;
|
||||
} catch (error) {
|
||||
console.error('Email verification failed:', error);
|
||||
@@ -252,6 +259,8 @@
|
||||
"success": {
|
||||
"title": "Email Verified Successfully!",
|
||||
"message": "Your email has been verified. You can now log in to your account.",
|
||||
"emailChangeTitle": "Email Changed Successfully!",
|
||||
"emailChangeMessage": "Your account email address has been updated. Use the new email the next time you log in.",
|
||||
"goToLogin": "Go to Login"
|
||||
},
|
||||
"error": {
|
||||
@@ -279,6 +288,8 @@
|
||||
"success": {
|
||||
"title": "Email vérifié avec succès !",
|
||||
"message": "Votre email a été vérifié. Vous pouvez maintenant vous connecter à votre compte.",
|
||||
"emailChangeTitle": "Email modifié avec succès !",
|
||||
"emailChangeMessage": "L'adresse email de votre compte a été mise à jour. Utilisez le nouvel email lors de votre prochaine connexion.",
|
||||
"goToLogin": "Aller à la connexion"
|
||||
},
|
||||
"error": {
|
||||
|
||||
@@ -155,12 +155,12 @@ export const useUserProfileStore = defineStore(
|
||||
|
||||
try {
|
||||
const client = useClient()
|
||||
await client.post(
|
||||
const response = await client.post(
|
||||
`/api/users/email`,
|
||||
{
|
||||
email: email
|
||||
})
|
||||
value.value.email = email;
|
||||
return response.data;
|
||||
} catch (updateError) {
|
||||
console.error(updateError)
|
||||
error.value = 'Failed to update profile.'
|
||||
|
||||
@@ -69,12 +69,19 @@
|
||||
await userProfileStore.changeAlias(nextAlias || null);
|
||||
}
|
||||
|
||||
let emailChangeRequested = false;
|
||||
if (nextEmail !== (user.email ?? '')) {
|
||||
await userProfileStore.changeEmail(nextEmail);
|
||||
emailChangeRequested = true;
|
||||
}
|
||||
|
||||
settingsStatus.value = t('userSettings.saved');
|
||||
syncFormFromUser(userProfileStore.user);
|
||||
settingsStatus.value = emailChangeRequested
|
||||
? t('userSettings.emailConfirmationSent')
|
||||
: t('userSettings.saved');
|
||||
|
||||
if (!emailChangeRequested) {
|
||||
syncFormFromUser(userProfileStore.user);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to update user settings:', error);
|
||||
settingsError.value = t('userSettings.errors.saveFailed');
|
||||
|
||||
@@ -936,6 +936,7 @@
|
||||
"accountDetailsDescription": "Edit the profile details other workspace members see.",
|
||||
"saveDetails": "Save details",
|
||||
"saved": "Profile details saved",
|
||||
"emailConfirmationSent": "Profile details saved. Check your new email address to confirm the email change.",
|
||||
"portraitSaved": "Portrait saved",
|
||||
"calendarFeed": {
|
||||
"title": "Private calendar feed",
|
||||
|
||||
@@ -936,6 +936,7 @@
|
||||
"accountDetailsDescription": "Modifiez les informations de profil visibles par les autres membres.",
|
||||
"saveDetails": "Enregistrer les détails",
|
||||
"saved": "Informations de profil enregistrées",
|
||||
"emailConfirmationSent": "Informations de profil enregistrées. Consultez votre nouvelle adresse email pour confirmer le changement.",
|
||||
"portraitSaved": "Portrait enregistré",
|
||||
"calendarFeed": {
|
||||
"title": "Flux calendrier privé",
|
||||
|
||||
Reference in New Issue
Block a user