mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-07 08:40:19 +01:00
* fix: default ALLOW_SHARED_LINKS_PUBLIC to false for security Shared links were publicly accessible by default when ALLOW_SHARED_LINKS_PUBLIC was not explicitly set, which could lead to unintentional data exposure. Users may assume their authentication settings protect shared links when they do not. This changes the default behavior so shared links require JWT authentication unless ALLOW_SHARED_LINKS_PUBLIC is explicitly set to true. * Document ALLOW_SHARED_LINKS_PUBLIC in .env.example Add comment explaining ALLOW_SHARED_LINKS_PUBLIC setting. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Danny Avila <danacordially@gmail.com>
156 lines
6 KiB
JavaScript
156 lines
6 KiB
JavaScript
const express = require('express');
|
|
const { logger } = require('@librechat/data-schemas');
|
|
const { isEnabled, getBalanceConfig } = require('@librechat/api');
|
|
const { Constants, CacheKeys, defaultSocialLogins } = require('librechat-data-provider');
|
|
const { getLdapConfig } = require('~/server/services/Config/ldap');
|
|
const { getAppConfig } = require('~/server/services/Config/app');
|
|
const { getProjectByName } = require('~/models/Project');
|
|
const { getLogStores } = require('~/cache');
|
|
|
|
const router = express.Router();
|
|
const emailLoginEnabled =
|
|
process.env.ALLOW_EMAIL_LOGIN === undefined || isEnabled(process.env.ALLOW_EMAIL_LOGIN);
|
|
const passwordResetEnabled = isEnabled(process.env.ALLOW_PASSWORD_RESET);
|
|
|
|
const sharedLinksEnabled =
|
|
process.env.ALLOW_SHARED_LINKS === undefined || isEnabled(process.env.ALLOW_SHARED_LINKS);
|
|
|
|
const publicSharedLinksEnabled =
|
|
sharedLinksEnabled && isEnabled(process.env.ALLOW_SHARED_LINKS_PUBLIC);
|
|
|
|
const sharePointFilePickerEnabled = isEnabled(process.env.ENABLE_SHAREPOINT_FILEPICKER);
|
|
const openidReuseTokens = isEnabled(process.env.OPENID_REUSE_TOKENS);
|
|
|
|
router.get('/', async function (req, res) {
|
|
const cache = getLogStores(CacheKeys.CONFIG_STORE);
|
|
|
|
const cachedStartupConfig = await cache.get(CacheKeys.STARTUP_CONFIG);
|
|
if (cachedStartupConfig) {
|
|
res.send(cachedStartupConfig);
|
|
return;
|
|
}
|
|
|
|
const isBirthday = () => {
|
|
const today = new Date();
|
|
return today.getMonth() === 1 && today.getDate() === 11;
|
|
};
|
|
|
|
const instanceProject = await getProjectByName(Constants.GLOBAL_PROJECT_NAME, '_id');
|
|
|
|
const ldap = getLdapConfig();
|
|
|
|
try {
|
|
const appConfig = await getAppConfig({ role: req.user?.role });
|
|
|
|
const isOpenIdEnabled =
|
|
!!process.env.OPENID_CLIENT_ID &&
|
|
!!process.env.OPENID_CLIENT_SECRET &&
|
|
!!process.env.OPENID_ISSUER &&
|
|
!!process.env.OPENID_SESSION_SECRET;
|
|
|
|
const isSamlEnabled =
|
|
!!process.env.SAML_ENTRY_POINT &&
|
|
!!process.env.SAML_ISSUER &&
|
|
!!process.env.SAML_CERT &&
|
|
!!process.env.SAML_SESSION_SECRET;
|
|
|
|
const balanceConfig = getBalanceConfig(appConfig);
|
|
|
|
/** @type {TStartupConfig} */
|
|
const payload = {
|
|
appTitle: process.env.APP_TITLE || 'LibreChat',
|
|
socialLogins: appConfig?.registration?.socialLogins ?? defaultSocialLogins,
|
|
discordLoginEnabled: !!process.env.DISCORD_CLIENT_ID && !!process.env.DISCORD_CLIENT_SECRET,
|
|
facebookLoginEnabled:
|
|
!!process.env.FACEBOOK_CLIENT_ID && !!process.env.FACEBOOK_CLIENT_SECRET,
|
|
githubLoginEnabled: !!process.env.GITHUB_CLIENT_ID && !!process.env.GITHUB_CLIENT_SECRET,
|
|
googleLoginEnabled: !!process.env.GOOGLE_CLIENT_ID && !!process.env.GOOGLE_CLIENT_SECRET,
|
|
appleLoginEnabled:
|
|
!!process.env.APPLE_CLIENT_ID &&
|
|
!!process.env.APPLE_TEAM_ID &&
|
|
!!process.env.APPLE_KEY_ID &&
|
|
!!process.env.APPLE_PRIVATE_KEY_PATH,
|
|
openidLoginEnabled: isOpenIdEnabled,
|
|
openidLabel: process.env.OPENID_BUTTON_LABEL || 'Continue with OpenID',
|
|
openidImageUrl: process.env.OPENID_IMAGE_URL,
|
|
openidAutoRedirect: isEnabled(process.env.OPENID_AUTO_REDIRECT),
|
|
samlLoginEnabled: !isOpenIdEnabled && isSamlEnabled,
|
|
samlLabel: process.env.SAML_BUTTON_LABEL,
|
|
samlImageUrl: process.env.SAML_IMAGE_URL,
|
|
serverDomain: process.env.DOMAIN_SERVER || 'http://localhost:3080',
|
|
emailLoginEnabled,
|
|
registrationEnabled: !ldap?.enabled && isEnabled(process.env.ALLOW_REGISTRATION),
|
|
socialLoginEnabled: isEnabled(process.env.ALLOW_SOCIAL_LOGIN),
|
|
emailEnabled:
|
|
(!!process.env.EMAIL_SERVICE || !!process.env.EMAIL_HOST) &&
|
|
!!process.env.EMAIL_USERNAME &&
|
|
!!process.env.EMAIL_PASSWORD &&
|
|
!!process.env.EMAIL_FROM,
|
|
passwordResetEnabled,
|
|
showBirthdayIcon:
|
|
isBirthday() ||
|
|
isEnabled(process.env.SHOW_BIRTHDAY_ICON) ||
|
|
process.env.SHOW_BIRTHDAY_ICON === '',
|
|
helpAndFaqURL: process.env.HELP_AND_FAQ_URL || 'https://librechat.ai',
|
|
interface: appConfig?.interfaceConfig,
|
|
turnstile: appConfig?.turnstileConfig,
|
|
modelSpecs: appConfig?.modelSpecs,
|
|
balance: balanceConfig,
|
|
sharedLinksEnabled,
|
|
publicSharedLinksEnabled,
|
|
analyticsGtmId: process.env.ANALYTICS_GTM_ID,
|
|
instanceProjectId: instanceProject._id.toString(),
|
|
bundlerURL: process.env.SANDPACK_BUNDLER_URL,
|
|
staticBundlerURL: process.env.SANDPACK_STATIC_BUNDLER_URL,
|
|
sharePointFilePickerEnabled,
|
|
sharePointBaseUrl: process.env.SHAREPOINT_BASE_URL,
|
|
sharePointPickerGraphScope: process.env.SHAREPOINT_PICKER_GRAPH_SCOPE,
|
|
sharePointPickerSharePointScope: process.env.SHAREPOINT_PICKER_SHAREPOINT_SCOPE,
|
|
openidReuseTokens,
|
|
conversationImportMaxFileSize: process.env.CONVERSATION_IMPORT_MAX_FILE_SIZE_BYTES
|
|
? parseInt(process.env.CONVERSATION_IMPORT_MAX_FILE_SIZE_BYTES, 10)
|
|
: 0,
|
|
};
|
|
|
|
const minPasswordLength = parseInt(process.env.MIN_PASSWORD_LENGTH, 10);
|
|
if (minPasswordLength && !isNaN(minPasswordLength)) {
|
|
payload.minPasswordLength = minPasswordLength;
|
|
}
|
|
|
|
const webSearchConfig = appConfig?.webSearch;
|
|
if (
|
|
webSearchConfig != null &&
|
|
(webSearchConfig.searchProvider ||
|
|
webSearchConfig.scraperProvider ||
|
|
webSearchConfig.rerankerType)
|
|
) {
|
|
payload.webSearch = {};
|
|
}
|
|
|
|
if (webSearchConfig?.searchProvider) {
|
|
payload.webSearch.searchProvider = webSearchConfig.searchProvider;
|
|
}
|
|
if (webSearchConfig?.scraperProvider) {
|
|
payload.webSearch.scraperProvider = webSearchConfig.scraperProvider;
|
|
}
|
|
if (webSearchConfig?.rerankerType) {
|
|
payload.webSearch.rerankerType = webSearchConfig.rerankerType;
|
|
}
|
|
|
|
if (ldap) {
|
|
payload.ldap = ldap;
|
|
}
|
|
|
|
if (typeof process.env.CUSTOM_FOOTER === 'string') {
|
|
payload.customFooter = process.env.CUSTOM_FOOTER;
|
|
}
|
|
|
|
await cache.set(CacheKeys.STARTUP_CONFIG, payload);
|
|
return res.status(200).send(payload);
|
|
} catch (err) {
|
|
logger.error('Error in startup config', err);
|
|
return res.status(500).send({ error: err.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|