mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-22 11:20:15 +01:00
refactor: update domain validation to use appConfig for allowed domains
This commit is contained in:
parent
677481dde6
commit
50bd6d3a02
8 changed files with 43 additions and 61 deletions
|
|
@ -1,5 +1,6 @@
|
|||
const { logger } = require('@librechat/data-schemas');
|
||||
const { isEmailDomainAllowed } = require('~/server/services/domains');
|
||||
const { logger } = require('~/config');
|
||||
const { getAppConfig } = require('~/server/services/Config');
|
||||
|
||||
/**
|
||||
* Checks the domain's social login is allowed
|
||||
|
|
@ -14,7 +15,10 @@ const { logger } = require('~/config');
|
|||
*/
|
||||
const checkDomainAllowed = async (req, res, next = () => {}) => {
|
||||
const email = req?.user?.email;
|
||||
if (email && !(await isEmailDomainAllowed(email))) {
|
||||
const appConfig = getAppConfig({
|
||||
role: req?.user?.role,
|
||||
});
|
||||
if (email && !(await isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains))) {
|
||||
logger.error(`[Social Login] [Social Login not allowed] [Email: ${email}]`);
|
||||
return res.redirect('/login');
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const { getAgent, updateAgent, getListAgentsByAccess } = require('~/models/Agent
|
|||
const { updateAction, getActions, deleteAction } = require('~/models/Action');
|
||||
const { isActionDomainAllowed } = require('~/server/services/domains');
|
||||
const { canAccessAgentResource } = require('~/server/middleware');
|
||||
const { getAppConfig } = require('~/server/services/Config/app');
|
||||
const { getRoleByName } = require('~/models/Role');
|
||||
|
||||
const router = express.Router();
|
||||
|
|
@ -83,7 +84,11 @@ router.post(
|
|||
}
|
||||
|
||||
let metadata = await encryptMetadata(removeNullishValues(_metadata, true));
|
||||
const isDomainAllowed = await isActionDomainAllowed(metadata.domain);
|
||||
const appConfig = await getAppConfig({ role: req.user.role });
|
||||
const isDomainAllowed = await isActionDomainAllowed(
|
||||
metadata.domain,
|
||||
appConfig?.registration?.allowedDomains,
|
||||
);
|
||||
if (!isDomainAllowed) {
|
||||
return res.status(400).json({ message: 'Domain not allowed' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ const router = express.Router();
|
|||
* @returns {Object} 200 - success response - application/json
|
||||
*/
|
||||
router.post('/:assistant_id', async (req, res) => {
|
||||
const appConfig = await getAppConfig({ role: req.user?.role });
|
||||
try {
|
||||
const appConfig = await getAppConfig({ role: req.user?.role });
|
||||
const { assistant_id } = req.params;
|
||||
|
||||
/** @type {{ functions: FunctionTool[], action_id: string, metadata: ActionMetadata }} */
|
||||
|
|
@ -32,7 +32,10 @@ router.post('/:assistant_id', async (req, res) => {
|
|||
}
|
||||
|
||||
let metadata = await encryptMetadata(removeNullishValues(_metadata, true));
|
||||
const isDomainAllowed = await isActionDomainAllowed(metadata.domain);
|
||||
const isDomainAllowed = await isActionDomainAllowed(
|
||||
metadata.domain,
|
||||
appConfig?.registration?.allowedDomains,
|
||||
);
|
||||
if (!isDomainAllowed) {
|
||||
return res.status(400).json({ message: 'Domain not allowed' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,33 +84,32 @@ const AppService = async () => {
|
|||
// Store MCP config for later initialization
|
||||
const mcpConfig = config.mcpServers || null;
|
||||
|
||||
const socialLogins =
|
||||
config?.registration?.socialLogins ?? configDefaults?.registration?.socialLogins;
|
||||
const registration = config.registration ?? configDefaults.registration;
|
||||
const interfaceConfig = await loadDefaultInterface(config, configDefaults);
|
||||
const turnstileConfig = loadTurnstileConfig(config, configDefaults);
|
||||
|
||||
const defaultLocals = {
|
||||
config,
|
||||
const defaultConfig = {
|
||||
ocr,
|
||||
paths,
|
||||
config,
|
||||
memory,
|
||||
balance,
|
||||
mcpConfig,
|
||||
webSearch,
|
||||
fileStrategy,
|
||||
socialLogins,
|
||||
registration,
|
||||
filteredTools,
|
||||
includedTools,
|
||||
imageOutputType,
|
||||
interfaceConfig,
|
||||
turnstileConfig,
|
||||
balance,
|
||||
mcpConfig,
|
||||
};
|
||||
|
||||
const agentsDefaults = agentsConfigSetup(config);
|
||||
|
||||
if (!Object.keys(config).length) {
|
||||
const appConfig = {
|
||||
...defaultLocals,
|
||||
...defaultConfig,
|
||||
[EModelEndpoint.agents]: agentsDefaults,
|
||||
};
|
||||
await setAppConfig(appConfig);
|
||||
|
|
@ -169,7 +168,7 @@ const AppService = async () => {
|
|||
}
|
||||
|
||||
const appConfig = {
|
||||
...defaultLocals,
|
||||
...defaultConfig,
|
||||
fileConfig: config?.fileConfig,
|
||||
secureImageLinks: config?.secureImageLinks,
|
||||
modelSpecs: processModelSpecs(endpoints, config.modelSpecs, interfaceConfig),
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ const {
|
|||
deleteUserById,
|
||||
generateRefreshToken,
|
||||
} = require('~/models');
|
||||
const { getBalanceConfig, getAppConfig } = require('~/server/services/Config');
|
||||
const { isEmailDomainAllowed } = require('~/server/services/domains');
|
||||
const { checkEmailConfig, sendEmail } = require('~/server/utils');
|
||||
const { getBalanceConfig } = require('~/server/services/Config');
|
||||
const { registerSchema } = require('~/strategies/validators');
|
||||
|
||||
const domains = {
|
||||
|
|
@ -195,7 +195,8 @@ const registerUser = async (user, additionalData = {}) => {
|
|||
return { status: 200, message: genericVerificationMessage };
|
||||
}
|
||||
|
||||
if (!(await isEmailDomainAllowed(email))) {
|
||||
const appConfig = await getAppConfig({ role: user.role });
|
||||
if (!(await isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains))) {
|
||||
const errorMessage =
|
||||
'The email address provided cannot be used. Please use a different email address.';
|
||||
logger.error(`[registerUser] [Registration not allowed] [Email: ${user.email}]`);
|
||||
|
|
|
|||
|
|
@ -2,37 +2,6 @@ const { logger } = require('@librechat/data-schemas');
|
|||
const { CacheKeys } = require('librechat-data-provider');
|
||||
const getLogStores = require('~/cache/getLogStores');
|
||||
|
||||
/**
|
||||
* @typedef {Object} AppConfig
|
||||
* @property {import('librechat-data-provider').TCustomConfig} config - The main custom configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['ocr']} ocr - OCR configuration
|
||||
* @property {Object} paths - File paths configuration
|
||||
* @property {import('librechat-data-provider').TMemoryConfig | undefined} memory - Memory configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['webSearch']} webSearch - Web search configuration
|
||||
* @property {string} fileStrategy - File storage strategy ('local', 's3', 'firebase', 'azure_blob')
|
||||
* @property {Array} socialLogins - Social login configurations
|
||||
* @property {string[]} [filteredTools] - Admin-filtered tools
|
||||
* @property {string[]} [includedTools] - Admin-included tools
|
||||
* @property {string} imageOutputType - Image output type configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['interface']} interfaceConfig - Interface configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['registration']} turnstileConfig - Turnstile configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['balance']} balance - Balance configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['mcpServers'] | null} mcpConfig - MCP server configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['fileConfig']} [fileConfig] - File configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['secureImageLinks']} [secureImageLinks] - Secure image links configuration
|
||||
* @property {import('librechat-data-provider').TCustomConfig['modelSpecs'] | undefined} [modelSpecs] - Processed model specifications
|
||||
* @property {import('librechat-data-provider').TEndpoint} [openAI] - OpenAI endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [google] - Google endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [bedrock] - Bedrock endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [anthropic] - Anthropic endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [gptPlugins] - GPT plugins endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [azureOpenAI] - Azure OpenAI endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [assistants] - Assistants endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [azureAssistants] - Azure assistants endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [agents] - Agents endpoint configuration
|
||||
* @property {import('librechat-data-provider').TEndpoint} [all] - Global endpoint configuration
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the app configuration based on user context
|
||||
* @param {Object} [options]
|
||||
|
|
|
|||
|
|
@ -364,8 +364,10 @@ async function processRequiredActions(client, requiredActions) {
|
|||
const domain = await domainParser(action.metadata.domain, true);
|
||||
domainMap.set(domain, action);
|
||||
|
||||
// Check if domain is allowed
|
||||
const isDomainAllowed = await isActionDomainAllowed(action.metadata.domain);
|
||||
const isDomainAllowed = await isActionDomainAllowed(
|
||||
action.metadata.domain,
|
||||
appConfig?.registration?.allowedDomains,
|
||||
);
|
||||
if (!isDomainAllowed) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -631,7 +633,10 @@ async function loadAgentTools({ req, res, agent, tool_resources, openAIApiKey })
|
|||
domainMap.set(domain, action);
|
||||
|
||||
// Check if domain is allowed (do this once per action set)
|
||||
const isDomainAllowed = await isActionDomainAllowed(action.metadata.domain);
|
||||
const isDomainAllowed = await isActionDomainAllowed(
|
||||
action.metadata.domain,
|
||||
appConfig?.registration?.allowedDomains,
|
||||
);
|
||||
if (!isDomainAllowed) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
const { getCustomConfig } = require('~/server/services/Config');
|
||||
|
||||
/**
|
||||
* @param {string} email
|
||||
* @param {string[]} [allowedDomains]
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function isEmailDomainAllowed(email) {
|
||||
async function isEmailDomainAllowed(email, allowedDomains) {
|
||||
if (!email) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -15,14 +14,13 @@ async function isEmailDomainAllowed(email) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const customConfig = await getCustomConfig();
|
||||
if (!customConfig) {
|
||||
if (!allowedDomains) {
|
||||
return true;
|
||||
} else if (!customConfig?.registration?.allowedDomains) {
|
||||
} else if (!Array.isArray(allowedDomains) || !allowedDomains.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return customConfig.registration.allowedDomains.includes(domain);
|
||||
return allowedDomains.includes(domain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -65,16 +63,14 @@ function normalizeDomain(domain) {
|
|||
/**
|
||||
* Checks if the given domain is allowed. If no restrictions are set, allows all domains.
|
||||
* @param {string} [domain]
|
||||
* @param {string[]} [allowedDomains]
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function isActionDomainAllowed(domain) {
|
||||
async function isActionDomainAllowed(domain, allowedDomains) {
|
||||
if (!domain || typeof domain !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const customConfig = await getCustomConfig();
|
||||
const allowedDomains = customConfig?.actions?.allowedDomains;
|
||||
|
||||
if (!Array.isArray(allowedDomains) || !allowedDomains.length) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue