mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00

* feat(sharepoint): integrate SharePoint file picker and download workflow Introduces end‑to‑end SharePoint import support: * Token exchange with Microsoft Graph and scope management (`useSharePointToken`) * Re‑usable hooks: `useSharePointPicker`, `useSharePointDownload`, `useSharePointFileHandling` * FileSearch dropdown now offers **From Local Machine** / **From SharePoint** sources and gracefully falls back when SharePoint is disabled * Agent upload model, `AttachFileMenu`, and `DropdownPopup` extended for SharePoint files and sub‑menus * Blurry overlay with progress indicator and `maxSelectionCount` limit during downloads * Cache‑flush utility (`config/flush-cache.js`) supporting Redis & filesystem, with dry‑run and npm script * Updated `SharePointIcon` (uses `currentColor`) and new i18n keys * Bug fixes: placeholder syntax in progress message, picker event‑listener cleanup * Misc style and performance optimizations * Fix ESLint warnings --------- Co-authored-by: Atef Bellaaj <slalom.bellaaj@external.daimlertruck.com>
165 lines
6.2 KiB
JavaScript
165 lines
6.2 KiB
JavaScript
const express = require('express');
|
|
const { isEnabled } = require('@librechat/api');
|
|
const { logger } = require('@librechat/data-schemas');
|
|
const { CacheKeys, defaultSocialLogins, Constants } = require('librechat-data-provider');
|
|
const { getCustomConfig } = require('~/server/services/Config/getCustomConfig');
|
|
const { getLdapConfig } = require('~/server/services/Config/ldap');
|
|
const { getProjectByName } = require('~/models/Project');
|
|
const { getMCPManager } = require('~/config');
|
|
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 &&
|
|
(process.env.ALLOW_SHARED_LINKS_PUBLIC === undefined ||
|
|
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 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;
|
|
|
|
/** @type {TStartupConfig} */
|
|
const payload = {
|
|
appTitle: process.env.APP_TITLE || 'LibreChat',
|
|
socialLogins: req.app.locals.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: req.app.locals.interfaceConfig,
|
|
turnstile: req.app.locals.turnstileConfig,
|
|
modelSpecs: req.app.locals.modelSpecs,
|
|
balance: req.app.locals.balance,
|
|
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,
|
|
};
|
|
|
|
payload.mcpServers = {};
|
|
const config = await getCustomConfig();
|
|
if (config?.mcpServers != null) {
|
|
const mcpManager = getMCPManager();
|
|
const oauthServers = mcpManager.getOAuthServers();
|
|
|
|
for (const serverName in config.mcpServers) {
|
|
const serverConfig = config.mcpServers[serverName];
|
|
payload.mcpServers[serverName] = {
|
|
customUserVars: serverConfig?.customUserVars || {},
|
|
chatMenu: serverConfig?.chatMenu,
|
|
isOAuth: oauthServers.has(serverName),
|
|
startup: serverConfig?.startup,
|
|
};
|
|
}
|
|
}
|
|
|
|
/** @type {TCustomConfig['webSearch']} */
|
|
const webSearchConfig = req.app.locals.webSearch;
|
|
if (
|
|
webSearchConfig != null &&
|
|
(webSearchConfig.searchProvider ||
|
|
webSearchConfig.scraperType ||
|
|
webSearchConfig.rerankerType)
|
|
) {
|
|
payload.webSearch = {};
|
|
}
|
|
|
|
if (webSearchConfig?.searchProvider) {
|
|
payload.webSearch.searchProvider = webSearchConfig.searchProvider;
|
|
}
|
|
if (webSearchConfig?.scraperType) {
|
|
payload.webSearch.scraperType = webSearchConfig.scraperType;
|
|
}
|
|
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;
|