mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00
📧 feat: email verification (#2344)
* feat: verification email * chore: email verification invalid; localize: update * fix: redirect to login when signup: fix: save emailVerified correctly * docs: update ALLOW_UNVERIFIED_EMAIL_LOGIN; fix: don't accept login only when ALLOW_UNVERIFIED_EMAIL_LOGIN = true * fix: user needs to be authenticated * style: update * fix: registration success message and redirect logic * refactor: use `isEnabled` in ALLOW_UNVERIFIED_EMAIL_LOGIN * refactor: move checkEmailConfig to server/utils * refactor: use req as param for verifyEmail function * chore: jsdoc * chore: remove console log * refactor: rename `createNewUser` to `createSocialUser` * refactor: update typing and add expiresAt field to userSchema * refactor: begin use of user methods over direct model access for User * refactor: initial email verification rewrite * chore: typing * refactor: registration flow rewrite * chore: remove help center text * refactor: update getUser to getUserById and add findUser methods. general fixes from recent changes * refactor: Update updateUser method to remove expiresAt field and use $set and $unset operations, createUser now returns Id only * refactor: Update openidStrategy to use optional chaining for avatar check, move saveBuffer init to buffer condition * refactor: logout on deleteUser mutatation * refactor: Update openidStrategy login success message format * refactor: Add emailVerified field to Discord and Facebook profile details * refactor: move limiters to separate middleware dir * refactor: Add limiters for email verification and password reset * refactor: Remove getUserController and update routes and controllers accordingly * refactor: Update getUserById method to exclude password and version fields * refactor: move verification to user route, add resend verification option * refactor: Improve email verification process and resend option * refactor: remove more direct model access of User and remove unused code * refactor: replace user authentication methods and token generation * fix: add user.id to jwt user * refactor: Update AuthContext to include setError function, add resend link to Login Form, make registration redirect shorter * fix(updateUserPluginsService): ensure userPlugins variable is defined * refactor: Delete all shared links for a specific user * fix: remove use of direct User.save() in handleExistingUser * fix(importLibreChatConvo): handle missing createdAt field in messages --------- Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
parent
b7fef6958b
commit
ee673d682e
67 changed files with 1863 additions and 1117 deletions
|
@ -1,42 +1,26 @@
|
|||
const crypto = require('crypto');
|
||||
const cookies = require('cookie');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const { Session, User } = require('~/models');
|
||||
const {
|
||||
registerUser,
|
||||
resetPassword,
|
||||
setAuthTokens,
|
||||
requestPasswordReset,
|
||||
} = require('~/server/services/AuthService');
|
||||
const { Session, getUserById } = require('~/models');
|
||||
const { logger } = require('~/config');
|
||||
|
||||
const registrationController = async (req, res) => {
|
||||
try {
|
||||
const response = await registerUser(req.body);
|
||||
if (response.status === 200) {
|
||||
const { status, user } = response;
|
||||
let newUser = await User.findOne({ _id: user._id });
|
||||
if (!newUser) {
|
||||
newUser = new User(user);
|
||||
await newUser.save();
|
||||
}
|
||||
const token = await setAuthTokens(user._id, res);
|
||||
res.setHeader('Authorization', `Bearer ${token}`);
|
||||
res.status(status).send({ user });
|
||||
} else {
|
||||
const { status, message } = response;
|
||||
res.status(status).send({ message });
|
||||
}
|
||||
const { status, message } = response;
|
||||
res.status(status).send({ message });
|
||||
} catch (err) {
|
||||
logger.error('[registrationController]', err);
|
||||
return res.status(500).json({ message: err.message });
|
||||
}
|
||||
};
|
||||
|
||||
const getUserController = async (req, res) => {
|
||||
return res.status(200).send(req.user);
|
||||
};
|
||||
|
||||
const resetPasswordRequestController = async (req, res) => {
|
||||
try {
|
||||
const resetService = await requestPasswordReset(req);
|
||||
|
@ -77,7 +61,7 @@ const refreshController = async (req, res) => {
|
|||
|
||||
try {
|
||||
const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
|
||||
const user = await User.findOne({ _id: payload.id });
|
||||
const user = await getUserById(payload.id, '-password -__v');
|
||||
if (!user) {
|
||||
return res.status(401).redirect('/login');
|
||||
}
|
||||
|
@ -86,8 +70,7 @@ const refreshController = async (req, res) => {
|
|||
|
||||
if (process.env.NODE_ENV === 'CI') {
|
||||
const token = await setAuthTokens(userId, res);
|
||||
const userObj = user.toJSON();
|
||||
return res.status(200).send({ token, user: userObj });
|
||||
return res.status(200).send({ token, user });
|
||||
}
|
||||
|
||||
// Hash the refresh token
|
||||
|
@ -98,8 +81,7 @@ const refreshController = async (req, res) => {
|
|||
const session = await Session.findOne({ user: userId, refreshTokenHash: hashedToken });
|
||||
if (session && session.expiration > new Date()) {
|
||||
const token = await setAuthTokens(userId, res, session._id);
|
||||
const userObj = user.toJSON();
|
||||
res.status(200).send({ token, user: userObj });
|
||||
res.status(200).send({ token, user });
|
||||
} else if (req?.query?.retry) {
|
||||
// Retrying from a refresh token request that failed (401)
|
||||
res.status(403).send('No session found');
|
||||
|
@ -115,7 +97,6 @@ const refreshController = async (req, res) => {
|
|||
};
|
||||
|
||||
module.exports = {
|
||||
getUserController,
|
||||
refreshController,
|
||||
registrationController,
|
||||
resetPasswordController,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue