mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-30 23:28:52 +01:00
🔒 feat: Implement Granular File Storage Strategies and Access Control Middleware
This commit is contained in:
parent
74e029e78f
commit
ff54cbffd9
13 changed files with 269 additions and 210 deletions
|
|
@ -86,6 +86,7 @@ const AppService = async (app) => {
|
|||
const turnstileConfig = loadTurnstileConfig(config, configDefaults);
|
||||
|
||||
const defaultLocals = {
|
||||
config,
|
||||
ocr,
|
||||
paths,
|
||||
memory,
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ describe('AppService', () => {
|
|||
expect(process.env.CDN_PROVIDER).toEqual('testStrategy');
|
||||
|
||||
expect(app.locals).toEqual({
|
||||
config: expect.objectContaining({
|
||||
fileStrategy: 'testStrategy',
|
||||
}),
|
||||
socialLogins: ['testLogin'],
|
||||
fileStrategy: 'testStrategy',
|
||||
interfaceConfig: expect.objectContaining({
|
||||
|
|
@ -775,6 +778,7 @@ describe('AppService updating app.locals and issuing warnings', () => {
|
|||
|
||||
expect(app.locals).toBeDefined();
|
||||
expect(app.locals.paths).toBeDefined();
|
||||
expect(app.locals.config).toEqual({});
|
||||
expect(app.locals.fileStrategy).toEqual(FileSources.local);
|
||||
expect(app.locals.socialLogins).toEqual(defaultSocialLogins);
|
||||
expect(app.locals.balance).toEqual(
|
||||
|
|
@ -807,6 +811,7 @@ describe('AppService updating app.locals and issuing warnings', () => {
|
|||
|
||||
expect(app.locals).toBeDefined();
|
||||
expect(app.locals.paths).toBeDefined();
|
||||
expect(app.locals.config).toEqual(customConfig);
|
||||
expect(app.locals.fileStrategy).toEqual(customConfig.fileStrategy);
|
||||
expect(app.locals.socialLogins).toEqual(customConfig.registration.socialLogins);
|
||||
expect(app.locals.balance).toEqual(customConfig.balance);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ const { loadAuthValues } = require('~/server/services/Tools/credentials');
|
|||
const { checkCapability } = require('~/server/services/Config');
|
||||
const { LB_QueueAsyncCall } = require('~/server/utils/queue');
|
||||
const { getStrategyFunctions } = require('./strategies');
|
||||
const { getFileStrategy } = require('~/server/utils/getFileStrategy');
|
||||
const { determineFileType } = require('~/server/utils');
|
||||
const { logger } = require('~/config');
|
||||
|
||||
|
|
@ -319,7 +320,7 @@ const processFileURL = async ({ fileStrategy, userId, URL, fileName, basePath, c
|
|||
*/
|
||||
const processImageFile = async ({ req, res, metadata, returnFile = false }) => {
|
||||
const { file } = req;
|
||||
const source = req.app.locals.fileStrategy;
|
||||
const source = getFileStrategy(req.app.locals, { isImage: true });
|
||||
const { handleImageUpload } = getStrategyFunctions(source);
|
||||
const { file_id, temp_file_id, endpoint } = metadata;
|
||||
|
||||
|
|
@ -365,7 +366,7 @@ const processImageFile = async ({ req, res, metadata, returnFile = false }) => {
|
|||
* @returns {Promise<{ filepath: string, filename: string, source: string, type: string}>}
|
||||
*/
|
||||
const uploadImageBuffer = async ({ req, context, metadata = {}, resize = true }) => {
|
||||
const source = req.app.locals.fileStrategy;
|
||||
const source = getFileStrategy(req.app.locals, { isImage: true });
|
||||
const { saveBuffer } = getStrategyFunctions(source);
|
||||
let { buffer, width, height, bytes, filename, file_id, type } = metadata;
|
||||
if (resize) {
|
||||
|
|
@ -595,7 +596,8 @@ const processAgentFileUpload = async ({ req, res, metadata }) => {
|
|||
|
||||
// Dual storage pattern for RAG files: Storage + Vector DB
|
||||
let storageResult, embeddingResult;
|
||||
const source = req.app.locals.fileStrategy;
|
||||
const isImageFile = file.mimetype.startsWith('image');
|
||||
const source = getFileStrategy(req.app.locals, { isImage: isImageFile });
|
||||
|
||||
if (tool_resource === EToolResources.file_search) {
|
||||
// FIRST: Upload to Storage for permanent backup (S3/local/etc.)
|
||||
|
|
@ -763,7 +765,7 @@ const processOpenAIImageOutput = async ({ req, buffer, file_id, filename, fileEx
|
|||
type: mime.getType(fileExt),
|
||||
createdAt: formattedDate,
|
||||
updatedAt: formattedDate,
|
||||
source,
|
||||
source: getFileStrategy(req.app.locals, { isImage: true }),
|
||||
context: FileContext.assistants_output,
|
||||
file_id,
|
||||
filename,
|
||||
|
|
@ -904,7 +906,7 @@ async function saveBase64Image(
|
|||
}
|
||||
|
||||
const image = await resizeImageBuffer(inputBuffer, effectiveResolution, endpoint);
|
||||
const source = req.app.locals.fileStrategy;
|
||||
const source = getFileStrategy(req.app.locals, { isImage: true });
|
||||
const { saveBuffer } = getStrategyFunctions(source);
|
||||
const filepath = await saveBuffer({
|
||||
userId: req.user.id,
|
||||
|
|
|
|||
|
|
@ -270,8 +270,12 @@ const getStrategyFunctions = (fileSource) => {
|
|||
return azureMistralOCRStrategy();
|
||||
} else if (fileSource === FileSources.vertexai_mistral_ocr) {
|
||||
return vertexMistralOCRStrategy();
|
||||
} else if (fileSource === FileSources.text) {
|
||||
return localStrategy(); // Text files use local strategy
|
||||
} else {
|
||||
throw new Error('Invalid file source');
|
||||
throw new Error(
|
||||
`Invalid file source: ${fileSource}. Available sources: ${Object.values(FileSources).join(', ')}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue