mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00
Feat email password reset (#730)
* change name of auth.service to AuthService * Add emailEnabled to config api * Setup email * update nodemailer version * add translations * update .env.example * clean up console.log's) * refactor RequestPasswordReset component * chore: rebuild package-lock.json --------- Co-authored-by: Daniel Avila <messagedaniel@protonmail.com>
This commit is contained in:
parent
2faeebfae2
commit
30a49ae611
15 changed files with 221 additions and 171 deletions
10
.env.example
10
.env.example
|
@ -261,3 +261,13 @@ DISCORD_CALLBACK_URL=/oauth/discord/callback # this should be the same for every
|
|||
|
||||
DOMAIN_CLIENT=http://localhost:3080
|
||||
DOMAIN_SERVER=http://localhost:3080
|
||||
|
||||
###########################
|
||||
# Email
|
||||
###########################
|
||||
|
||||
# Email is used for password reset. Note that all 4 values must be set for email to work.
|
||||
EMAIL_SERVICE= # eg. gmail
|
||||
EMAIL_USERNAME= # eg. your email address if using gmail
|
||||
EMAIL_PASSWORD= # eg. this is the "app password" if using gmail
|
||||
EMAIL_FROM= # eg. email address for from field like noreply@librechat.ai
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"meilisearch": "^0.33.0",
|
||||
"mongoose": "^7.1.1",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nodemailer": "^6.9.4",
|
||||
"openai": "^3.2.1",
|
||||
"openid-client": "^5.4.2",
|
||||
"passport": "^0.6.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { registerUser, requestPasswordReset, resetPassword } = require('../services/auth.service');
|
||||
const { registerUser, requestPasswordReset, resetPassword } = require('../services/AuthService');
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
|
@ -32,10 +32,10 @@ const getUserController = async (req, res) => {
|
|||
const resetPasswordRequestController = async (req, res) => {
|
||||
try {
|
||||
const resetService = await requestPasswordReset(req.body.email);
|
||||
if (resetService.link) {
|
||||
return res.status(200).json(resetService);
|
||||
} else {
|
||||
if (resetService instanceof Error) {
|
||||
return res.status(400).json(resetService);
|
||||
} else {
|
||||
return res.status(200).json(resetService);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { logoutUser } = require('../../services/auth.service');
|
||||
const { logoutUser } = require('../../services/AuthService');
|
||||
|
||||
const logoutController = async (req, res) => {
|
||||
const { signedCookies = {} } = req;
|
||||
|
|
|
@ -18,6 +18,11 @@ router.get('/', async function (req, res) {
|
|||
const serverDomain = process.env.DOMAIN_SERVER || 'http://localhost:3080';
|
||||
const registrationEnabled = process.env.ALLOW_REGISTRATION === 'true';
|
||||
const socialLoginEnabled = process.env.ALLOW_SOCIAL_LOGIN === 'true';
|
||||
const emailEnabled =
|
||||
!!process.env.EMAIL_SERVICE &&
|
||||
!!process.env.EMAIL_USERNAME &&
|
||||
!!process.env.EMAIL_PASSWORD &&
|
||||
!!process.env.EMAIL_FROM;
|
||||
|
||||
return res.status(200).send({
|
||||
appTitle,
|
||||
|
@ -30,6 +35,7 @@ router.get('/', async function (req, res) {
|
|||
serverDomain,
|
||||
registrationEnabled,
|
||||
socialLoginEnabled,
|
||||
emailEnabled,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
|
|
@ -125,6 +125,13 @@ const requestPasswordReset = async (email) => {
|
|||
|
||||
const link = `${domains.client}/reset-password?token=${resetToken}&userId=${user._id}`;
|
||||
|
||||
const emailEnabled =
|
||||
!!process.env.EMAIL_SERVICE &&
|
||||
!!process.env.EMAIL_USERNAME &&
|
||||
!!process.env.EMAIL_PASSWORD &&
|
||||
!!process.env.EMAIL_FROM;
|
||||
|
||||
if (emailEnabled) {
|
||||
sendEmail(
|
||||
user.email,
|
||||
'Password Reset Request',
|
||||
|
@ -132,9 +139,12 @@ const requestPasswordReset = async (email) => {
|
|||
name: user.name,
|
||||
link: link,
|
||||
},
|
||||
'./template/requestResetPassword.handlebars',
|
||||
'requestPasswordReset.handlebars',
|
||||
);
|
||||
return { link: '' };
|
||||
} else {
|
||||
return { link };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -170,7 +180,7 @@ const resetPassword = async (userId, token, password) => {
|
|||
{
|
||||
name: user.name,
|
||||
},
|
||||
'./template/resetPassword.handlebars',
|
||||
'resetPassword.handlebars',
|
||||
);
|
||||
|
||||
await passwordResetToken.deleteOne();
|
|
@ -1,5 +1,3 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
/* eslint-disable no-undef */
|
||||
const nodemailer = require('nodemailer');
|
||||
const handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
|
@ -7,21 +5,19 @@ const path = require('path');
|
|||
|
||||
const sendEmail = async (email, subject, payload, template) => {
|
||||
try {
|
||||
// create reusable transporter object using the default SMTP transport
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: 465,
|
||||
service: process.env.EMAIL_SERVICE,
|
||||
auth: {
|
||||
user: process.env.EMAIL_USERNAME,
|
||||
pass: process.env.EMAIL_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
const source = fs.readFileSync(path.join(__dirname, template), 'utf8');
|
||||
const source = fs.readFileSync(path.join(__dirname, 'emails', template), 'utf8');
|
||||
const compiledTemplate = handlebars.compile(source);
|
||||
const options = () => {
|
||||
return {
|
||||
from: process.env.FROM_EMAIL,
|
||||
from: process.env.EMAIL_FROM,
|
||||
to: email,
|
||||
subject: subject,
|
||||
html: compiledTemplate(payload),
|
||||
|
@ -31,26 +27,17 @@ const sendEmail = async (email, subject, payload, template) => {
|
|||
// Send email
|
||||
transporter.sendMail(options(), (error, info) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
return error;
|
||||
} else {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
});
|
||||
console.log(info);
|
||||
return info;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Example:
|
||||
sendEmail(
|
||||
"youremail@gmail.com,
|
||||
"Email subject",
|
||||
{ name: "Eze" },
|
||||
"./templates/layouts/main.handlebars"
|
||||
);
|
||||
*/
|
||||
|
||||
module.exports = sendEmail;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import store from '~/store';
|
||||
import { localize } from '~/localization/Translation';
|
||||
import {
|
||||
useRequestPasswordResetMutation,
|
||||
useGetStartupConfig,
|
||||
TRequestPasswordReset,
|
||||
TRequestPasswordResetResponse,
|
||||
} from 'librechat-data-provider';
|
||||
|
@ -17,15 +18,19 @@ function RequestPasswordReset() {
|
|||
formState: { errors },
|
||||
} = useForm<TRequestPasswordReset>();
|
||||
const requestPasswordReset = useRequestPasswordResetMutation();
|
||||
const [success, setSuccess] = useState<boolean>(false);
|
||||
const config = useGetStartupConfig();
|
||||
const [requestError, setRequestError] = useState<boolean>(false);
|
||||
const [resetLink, setResetLink] = useState<string>('');
|
||||
const [resetLink, setResetLink] = useState<string | undefined>(undefined);
|
||||
const [headerText, setHeaderText] = useState<string>('');
|
||||
const [bodyText, setBodyText] = useState<React.ReactNode | undefined>(undefined);
|
||||
|
||||
const onSubmit = (data: TRequestPasswordReset) => {
|
||||
requestPasswordReset.mutate(data, {
|
||||
onSuccess: (data: TRequestPasswordResetResponse) => {
|
||||
setSuccess(true);
|
||||
console.log('emailEnabled: ', config.data?.emailEnabled);
|
||||
if (!config.data?.emailEnabled) {
|
||||
setResetLink(data.link);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
setRequestError(true);
|
||||
|
@ -36,25 +41,33 @@ function RequestPasswordReset() {
|
|||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col items-center justify-center bg-white pt-6 sm:pt-0">
|
||||
<div className="mt-6 w-96 overflow-hidden bg-white px-6 py-4 sm:max-w-md sm:rounded-lg">
|
||||
<h1 className="mb-4 text-center text-3xl font-semibold">
|
||||
{localize(lang, 'com_auth_reset_password')}
|
||||
</h1>
|
||||
{success && (
|
||||
<div
|
||||
className="relative mt-4 rounded border border-green-400 bg-green-100 px-4 py-3 text-green-700"
|
||||
role="alert"
|
||||
>
|
||||
useEffect(() => {
|
||||
if (requestPasswordReset.isSuccess) {
|
||||
if (config.data?.emailEnabled) {
|
||||
setHeaderText(localize(lang, 'com_auth_reset_password_link_sent'));
|
||||
setBodyText(localize(lang, 'com_auth_reset_password_email_sent'));
|
||||
} else {
|
||||
setHeaderText(localize(lang, 'com_auth_reset_password'));
|
||||
setBodyText(
|
||||
<span>
|
||||
{localize(lang, 'com_auth_click')}{' '}
|
||||
<a className="text-green-600 hover:underline" href={resetLink}>
|
||||
{localize(lang, 'com_auth_here')}
|
||||
</a>{' '}
|
||||
{localize(lang, 'com_auth_to_reset_your_password')}
|
||||
{/* An email has been sent with instructions on how to reset your password. */}
|
||||
</div>
|
||||
)}
|
||||
</span>,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setHeaderText(localize(lang, 'com_auth_reset_password'));
|
||||
setBodyText(undefined);
|
||||
}
|
||||
}, [requestPasswordReset.isSuccess, config.data?.emailEnabled, resetLink, lang]);
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col items-center justify-center bg-white pt-6 sm:pt-0">
|
||||
<div className="mt-6 w-96 overflow-hidden bg-white px-6 py-4 sm:max-w-md sm:rounded-lg">
|
||||
<h1 className="mb-4 text-center text-3xl font-semibold">{headerText}</h1>
|
||||
{requestError && (
|
||||
<div
|
||||
className="relative mt-4 rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700"
|
||||
|
@ -63,6 +76,14 @@ function RequestPasswordReset() {
|
|||
{localize(lang, 'com_auth_error_reset_password')}
|
||||
</div>
|
||||
)}
|
||||
{bodyText ? (
|
||||
<div
|
||||
className="relative mt-4 rounded border border-green-400 bg-green-100 px-4 py-3 text-green-700"
|
||||
role="alert"
|
||||
>
|
||||
{bodyText}
|
||||
</div>
|
||||
) : (
|
||||
<form
|
||||
className="mt-6"
|
||||
aria-label="Password reset form"
|
||||
|
@ -119,6 +140,7 @@ function RequestPasswordReset() {
|
|||
</button>
|
||||
</div>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -52,6 +52,9 @@ export default {
|
|||
com_auth_password_forgot: 'Esqueceu a senha?',
|
||||
com_auth_password_confirm: 'Confirmar senha',
|
||||
com_auth_password_not_match: 'As senhas não correspondem',
|
||||
com_auth_reset_password_link_sent: 'Link para redefinir a senha enviado',
|
||||
com_auth_reset_password_email_sent:
|
||||
'Um email foi enviado para com instruções para redefinir sua senha.',
|
||||
com_auth_continue: 'Continuar',
|
||||
com_auth_create_account: 'Crie sua conta',
|
||||
com_auth_error_create:
|
||||
|
|
|
@ -69,6 +69,9 @@ export default {
|
|||
com_auth_click: 'Click',
|
||||
com_auth_here: 'HERE',
|
||||
com_auth_to_reset_your_password: 'to reset your password.',
|
||||
com_auth_reset_password_link_sent: 'Email Sent',
|
||||
com_auth_reset_password_email_sent:
|
||||
'An email has been sent to you with further instructions to reset your password.',
|
||||
com_auth_error_reset_password:
|
||||
'There was a problem resetting your password. There was no user found with the email address provided. Please try again.',
|
||||
com_auth_reset_password_success: 'Password Reset Success',
|
||||
|
|
|
@ -46,6 +46,8 @@ export default {
|
|||
com_auth_email_max_length: 'El email no debe tener más de 120 caracteres',
|
||||
com_auth_email_pattern: 'Debes ingresar una dirección de email válida',
|
||||
com_auth_email_address: 'Dirección de email',
|
||||
com_auth_reset_password_link_sent: 'Enlace para restablecer la contraseña enviado',
|
||||
com_auth_reset_password_email_sent: 'Se ha enviado un correo electrónico con instrucciones.',
|
||||
com_auth_password: 'Contraseña',
|
||||
com_auth_password_required: 'Se requiere la contraseña',
|
||||
com_auth_password_min_length: 'La contraseña debe tener al menos 8 caracteres',
|
||||
|
|
|
@ -52,6 +52,9 @@ export default {
|
|||
com_auth_password_forgot: 'Password dimenticata?',
|
||||
com_auth_password_confirm: 'Conferma password',
|
||||
com_auth_password_not_match: 'Le password non corrispondono',
|
||||
com_auth_reset_password_link_sent: 'Link per reimpostare la password inviato',
|
||||
com_auth_reset_password_email_sent:
|
||||
'Ti abbiamo inviato un\'email con un link per reimpostare la password.',
|
||||
com_auth_continue: 'Continua',
|
||||
com_auth_create_account: 'Crea il tuo account',
|
||||
com_auth_error_create:
|
||||
|
|
|
@ -52,6 +52,8 @@ export default {
|
|||
com_auth_continue: '继续',
|
||||
com_auth_create_account: '创建账号',
|
||||
com_auth_error_create: '注册账户过程中出现错误,请重试。',
|
||||
com_auth_reset_password_link_sent: '重置密码链接已发送至邮箱',
|
||||
com_auth_reset_password_email_sent: '重置密码邮件已发送至邮箱',
|
||||
com_auth_full_name: '姓名',
|
||||
com_auth_name_required: '姓名为必填项',
|
||||
com_auth_name_min_length: '姓名至少3个字符',
|
||||
|
|
118
package-lock.json
generated
118
package-lock.json
generated
|
@ -72,7 +72,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"meilisearch": "^0.33.0",
|
||||
"mongoose": "^7.1.1",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nodemailer": "^6.9.4",
|
||||
"openai": "^3.2.1",
|
||||
"openid-client": "^5.4.2",
|
||||
"passport": "^0.6.0",
|
||||
|
@ -243,9 +243,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/sdk": {
|
||||
"version": "0.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.5.8.tgz",
|
||||
"integrity": "sha512-iHenjcE2Q/az6VZiP1DueOSvKNRmxsly6Rx2yjJBoy7OBYVFGVjEdgs2mPQHtTX0ibKAR7tPq6F6MQbKDPWcKg==",
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.5.9.tgz",
|
||||
"integrity": "sha512-9/TYca4qSe0xG40LLNf5vemybw5JAKF5OE6Eiyc+O+h3+VGGPeOKo+1SHaWBP5zS7bGX2o3Ne6EonPWyh9oNqA==",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/node-fetch": "^2.6.4",
|
||||
|
@ -7472,9 +7472,9 @@
|
|||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.17.tgz",
|
||||
"integrity": "sha512-u+e7OlgPPh+aryjOm5UJMX32OvB2E3QASOAqVMY6Ahs90djagxwv2ya0IctglNbNTexC12qCSMZG47KPfy1hAA==",
|
||||
"version": "18.2.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
|
||||
"integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
|
@ -7761,12 +7761,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.3.tgz",
|
||||
"integrity": "sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz",
|
||||
"integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.22.5",
|
||||
"@babel/core": "^7.22.9",
|
||||
"@babel/plugin-transform-react-jsx-self": "^7.22.5",
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.22.5",
|
||||
"react-refresh": "^0.14.0"
|
||||
|
@ -9485,9 +9485,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.9",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
|
||||
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
|
||||
"version": "4.21.10",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
|
||||
"integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -9504,9 +9504,9 @@
|
|||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001503",
|
||||
"electron-to-chromium": "^1.4.431",
|
||||
"node-releases": "^2.0.12",
|
||||
"caniuse-lite": "^1.0.30001517",
|
||||
"electron-to-chromium": "^1.4.477",
|
||||
"node-releases": "^2.0.13",
|
||||
"update-browserslist-db": "^1.0.11"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -9704,9 +9704,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001517",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz",
|
||||
"integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==",
|
||||
"version": "1.0.30001518",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz",
|
||||
"integrity": "sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -10776,9 +10776,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.3.0.tgz",
|
||||
"integrity": "sha512-7glNLfvdsMzZm3FpRY1CHuI2lbYDR+71YmrhmTZjYFD5pfT0ACgnGRdrrC9Mk2uICnzkcdelCx5at787UDGOvg==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
||||
"integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"babel-plugin-macros": "^3.1.0"
|
||||
|
@ -11177,9 +11177,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.477",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.477.tgz",
|
||||
"integrity": "sha512-shUVy6Eawp33dFBFIoYbIwLHrX0IZ857AlH9ug2o4rvbWmpaCUdBpQ5Zw39HRrfzAFm4APJE9V+E2A/WB0YqJw==",
|
||||
"version": "1.4.478",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.478.tgz",
|
||||
"integrity": "sha512-qjTA8djMXd+ruoODDFGnRCRBpID+AAfYWCyGtYTNhsuwxI19s8q19gbjKTwRS5z/LyVf5wICaIiPQGLekmbJbA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/elliptic": {
|
||||
|
@ -17274,9 +17274,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/langsmith": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.0.15.tgz",
|
||||
"integrity": "sha512-SVLJEm94aK9mmqE3z2wlpzLjPNodnPJHp1MZdmXG2ysUWSFsRVuGkd6A/GTzlEZ6OofyJSOg6tcNFJSFOi13QQ==",
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.0.16.tgz",
|
||||
"integrity": "sha512-HD97KJaSpCcuixbjfRhpSFdo5rWz28OJiUVs5uBRZDKUN2Amg4PWd0NFzGO3xC8osnjPPRvgH9by6Ige79hjxQ==",
|
||||
"dependencies": {
|
||||
"@types/uuid": "^9.0.1",
|
||||
"commander": "^10.0.1",
|
||||
|
@ -26550,7 +26550,7 @@
|
|||
},
|
||||
"packages/data-provider": {
|
||||
"name": "librechat-data-provider",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^4.28.0",
|
||||
|
@ -26666,9 +26666,9 @@
|
|||
}
|
||||
},
|
||||
"@anthropic-ai/sdk": {
|
||||
"version": "0.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.5.8.tgz",
|
||||
"integrity": "sha512-iHenjcE2Q/az6VZiP1DueOSvKNRmxsly6Rx2yjJBoy7OBYVFGVjEdgs2mPQHtTX0ibKAR7tPq6F6MQbKDPWcKg==",
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.5.9.tgz",
|
||||
"integrity": "sha512-9/TYca4qSe0xG40LLNf5vemybw5JAKF5OE6Eiyc+O+h3+VGGPeOKo+1SHaWBP5zS7bGX2o3Ne6EonPWyh9oNqA==",
|
||||
"requires": {
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/node-fetch": "^2.6.4",
|
||||
|
@ -30080,7 +30080,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"meilisearch": "^0.33.0",
|
||||
"mongoose": "^7.1.1",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nodemailer": "^6.9.4",
|
||||
"nodemon": "^2.0.20",
|
||||
"openai": "^3.2.1",
|
||||
"openid-client": "^5.4.2",
|
||||
|
@ -31735,9 +31735,9 @@
|
|||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "18.2.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.17.tgz",
|
||||
"integrity": "sha512-u+e7OlgPPh+aryjOm5UJMX32OvB2E3QASOAqVMY6Ahs90djagxwv2ya0IctglNbNTexC12qCSMZG47KPfy1hAA==",
|
||||
"version": "18.2.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
|
||||
"integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==",
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
|
@ -31935,12 +31935,12 @@
|
|||
}
|
||||
},
|
||||
"@vitejs/plugin-react": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.3.tgz",
|
||||
"integrity": "sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz",
|
||||
"integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/core": "^7.22.5",
|
||||
"@babel/core": "^7.22.9",
|
||||
"@babel/plugin-transform-react-jsx-self": "^7.22.5",
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.22.5",
|
||||
"react-refresh": "^0.14.0"
|
||||
|
@ -33302,14 +33302,14 @@
|
|||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.21.9",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
|
||||
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
|
||||
"version": "4.21.10",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
|
||||
"integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001503",
|
||||
"electron-to-chromium": "^1.4.431",
|
||||
"node-releases": "^2.0.12",
|
||||
"caniuse-lite": "^1.0.30001517",
|
||||
"electron-to-chromium": "^1.4.477",
|
||||
"node-releases": "^2.0.13",
|
||||
"update-browserslist-db": "^1.0.11"
|
||||
}
|
||||
},
|
||||
|
@ -33441,9 +33441,9 @@
|
|||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001517",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz",
|
||||
"integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==",
|
||||
"version": "1.0.30001518",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz",
|
||||
"integrity": "sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==",
|
||||
"dev": true
|
||||
},
|
||||
"ccount": {
|
||||
|
@ -34230,9 +34230,9 @@
|
|||
}
|
||||
},
|
||||
"dedent": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.3.0.tgz",
|
||||
"integrity": "sha512-7glNLfvdsMzZm3FpRY1CHuI2lbYDR+71YmrhmTZjYFD5pfT0ACgnGRdrrC9Mk2uICnzkcdelCx5at787UDGOvg==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
||||
"integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
@ -34538,9 +34538,9 @@
|
|||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.477",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.477.tgz",
|
||||
"integrity": "sha512-shUVy6Eawp33dFBFIoYbIwLHrX0IZ857AlH9ug2o4rvbWmpaCUdBpQ5Zw39HRrfzAFm4APJE9V+E2A/WB0YqJw==",
|
||||
"version": "1.4.478",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.478.tgz",
|
||||
"integrity": "sha512-qjTA8djMXd+ruoODDFGnRCRBpID+AAfYWCyGtYTNhsuwxI19s8q19gbjKTwRS5z/LyVf5wICaIiPQGLekmbJbA==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
|
@ -38876,9 +38876,9 @@
|
|||
}
|
||||
},
|
||||
"langsmith": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.0.15.tgz",
|
||||
"integrity": "sha512-SVLJEm94aK9mmqE3z2wlpzLjPNodnPJHp1MZdmXG2ysUWSFsRVuGkd6A/GTzlEZ6OofyJSOg6tcNFJSFOi13QQ==",
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.0.16.tgz",
|
||||
"integrity": "sha512-HD97KJaSpCcuixbjfRhpSFdo5rWz28OJiUVs5uBRZDKUN2Amg4PWd0NFzGO3xC8osnjPPRvgH9by6Ige79hjxQ==",
|
||||
"requires": {
|
||||
"@types/uuid": "^9.0.1",
|
||||
"commander": "^10.0.1",
|
||||
|
|
|
@ -257,6 +257,7 @@ export type TStartupConfig = {
|
|||
serverDomain: string;
|
||||
registrationEnabled: boolean;
|
||||
socialLoginEnabled: boolean;
|
||||
emailEnabled: boolean;
|
||||
};
|
||||
|
||||
export type TRefreshTokenResponse = {
|
||||
|
@ -265,7 +266,8 @@ export type TRefreshTokenResponse = {
|
|||
};
|
||||
|
||||
export type TRequestPasswordResetResponse = {
|
||||
link: string;
|
||||
link?: string;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
export type File = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue