mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 01:10:14 +01:00
🛡️ refactor: enhance email verification process (#5485)
This commit is contained in:
parent
12a9a07eb0
commit
e7de9c1576
2 changed files with 36 additions and 29 deletions
|
|
@ -108,31 +108,46 @@ const sendVerificationEmail = async (user) => {
|
||||||
*/
|
*/
|
||||||
const verifyEmail = async (req) => {
|
const verifyEmail = async (req) => {
|
||||||
const { email, token } = req.body;
|
const { email, token } = req.body;
|
||||||
let emailVerificationData = await findToken({ email: decodeURIComponent(email) });
|
const decodedEmail = decodeURIComponent(email);
|
||||||
|
|
||||||
|
const user = await findUser({ email: decodedEmail }, 'email _id emailVerified');
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
logger.warn(`[verifyEmail] [User not found] [Email: ${decodedEmail}]`);
|
||||||
|
return new Error('User not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.emailVerified) {
|
||||||
|
logger.info(`[verifyEmail] Email already verified [Email: ${decodedEmail}]`);
|
||||||
|
return { message: 'Email already verified', status: 'success' };
|
||||||
|
}
|
||||||
|
|
||||||
|
let emailVerificationData = await findToken({ email: decodedEmail });
|
||||||
|
|
||||||
if (!emailVerificationData) {
|
if (!emailVerificationData) {
|
||||||
logger.warn(`[verifyEmail] [No email verification data found] [Email: ${email}]`);
|
logger.warn(`[verifyEmail] [No email verification data found] [Email: ${decodedEmail}]`);
|
||||||
return new Error('Invalid or expired password reset token');
|
return new Error('Invalid or expired password reset token');
|
||||||
}
|
}
|
||||||
|
|
||||||
const isValid = bcrypt.compareSync(token, emailVerificationData.token);
|
const isValid = bcrypt.compareSync(token, emailVerificationData.token);
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
logger.warn(`[verifyEmail] [Invalid or expired email verification token] [Email: ${email}]`);
|
logger.warn(
|
||||||
|
`[verifyEmail] [Invalid or expired email verification token] [Email: ${decodedEmail}]`,
|
||||||
|
);
|
||||||
return new Error('Invalid or expired email verification token');
|
return new Error('Invalid or expired email verification token');
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedUser = await updateUser(emailVerificationData.userId, { emailVerified: true });
|
const updatedUser = await updateUser(emailVerificationData.userId, { emailVerified: true });
|
||||||
if (!updatedUser) {
|
if (!updatedUser) {
|
||||||
logger.warn(`[verifyEmail] [User not found] [Email: ${email}]`);
|
logger.warn(`[verifyEmail] [User update failed] [Email: ${decodedEmail}]`);
|
||||||
return new Error('User not found');
|
return new Error('Failed to update user verification status');
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteTokens({ token: emailVerificationData.token });
|
await deleteTokens({ token: emailVerificationData.token });
|
||||||
logger.info(`[verifyEmail] Email verification successful. [Email: ${email}]`);
|
logger.info(`[verifyEmail] Email verification successful [Email: ${decodedEmail}]`);
|
||||||
return { message: 'Email verification was successful' };
|
return { message: 'Email verification was successful', status: 'success' };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new user.
|
* Register a new user.
|
||||||
* @param {MongoUser} user <email, password, name, username>
|
* @param {MongoUser} user <email, password, name, username>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ function RequestPasswordReset() {
|
||||||
const [headerText, setHeaderText] = useState<string>('');
|
const [headerText, setHeaderText] = useState<string>('');
|
||||||
const [showResendLink, setShowResendLink] = useState<boolean>(false);
|
const [showResendLink, setShowResendLink] = useState<boolean>(false);
|
||||||
const [verificationStatus, setVerificationStatus] = useState<boolean>(false);
|
const [verificationStatus, setVerificationStatus] = useState<boolean>(false);
|
||||||
|
|
||||||
const token = useMemo(() => params.get('token') || '', [params]);
|
const token = useMemo(() => params.get('token') || '', [params]);
|
||||||
const email = useMemo(() => params.get('email') || '', [params]);
|
const email = useMemo(() => params.get('email') || '', [params]);
|
||||||
|
|
||||||
|
|
@ -26,9 +25,8 @@ function RequestPasswordReset() {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
navigate('/c/new', { replace: true });
|
navigate('/c/new', { replace: true });
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
return prevCountdown - 1;
|
|
||||||
}
|
}
|
||||||
|
return prevCountdown - 1;
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
@ -39,11 +37,10 @@ function RequestPasswordReset() {
|
||||||
setVerificationStatus(true);
|
setVerificationStatus(true);
|
||||||
countdownRedirect();
|
countdownRedirect();
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error: unknown) => {
|
||||||
|
setHeaderText(localize('com_auth_email_verification_failed') + ' 😢');
|
||||||
setShowResendLink(true);
|
setShowResendLink(true);
|
||||||
setVerificationStatus(true);
|
setVerificationStatus(true);
|
||||||
setHeaderText(localize('com_auth_email_verification_failed') + ' 😢');
|
|
||||||
setCountdown(0);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -54,7 +51,6 @@ function RequestPasswordReset() {
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
setHeaderText(localize('com_auth_email_resent_failed') + ' 😢');
|
setHeaderText(localize('com_auth_email_resent_failed') + ' 😢');
|
||||||
countdownRedirect();
|
|
||||||
},
|
},
|
||||||
onMutate: () => setShowResendLink(false),
|
onMutate: () => setShowResendLink(false),
|
||||||
});
|
});
|
||||||
|
|
@ -64,26 +60,22 @@ function RequestPasswordReset() {
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (verifyEmailMutation.isLoading || verificationStatus) {
|
if (verificationStatus || verifyEmailMutation.isLoading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token && email) {
|
if (token && email) {
|
||||||
verifyEmailMutation.mutate({
|
verifyEmailMutation.mutate({ email, token });
|
||||||
email,
|
|
||||||
token,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} else if (email) {
|
|
||||||
setHeaderText(localize('com_auth_email_verification_failed_token_missing') + ' 😢');
|
|
||||||
} else {
|
} else {
|
||||||
setHeaderText(localize('com_auth_email_verification_invalid') + ' 🤨');
|
if (email) {
|
||||||
|
setHeaderText(localize('com_auth_email_verification_failed_token_missing') + ' 😢');
|
||||||
|
} else {
|
||||||
|
setHeaderText(localize('com_auth_email_verification_invalid') + ' 🤨');
|
||||||
|
}
|
||||||
|
setShowResendLink(true);
|
||||||
|
setVerificationStatus(true);
|
||||||
}
|
}
|
||||||
|
}, [token, email, verificationStatus, verifyEmailMutation]);
|
||||||
setShowResendLink(true);
|
|
||||||
setVerificationStatus(true);
|
|
||||||
setCountdown(0);
|
|
||||||
}, [localize, token, email, verificationStatus, verifyEmailMutation]);
|
|
||||||
|
|
||||||
const VerificationSuccess = () => (
|
const VerificationSuccess = () => (
|
||||||
<div className="flex flex-col items-center justify-center">
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue