mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-09-01 03:27:01 +00:00
🪜 fix: Strip Caller-Supplied Priority from Assign-Only Config Upserts (#13911)
* fix: prevent assign-only config priority changes * fix: preserve assign-only config priority atomically * style: format config priority guard * fix: type preserve priority upsert option
This commit is contained in:
parent
edc0aebdb9
commit
725a14e409
4 changed files with 100 additions and 9 deletions
|
|
@ -994,7 +994,45 @@ describe('createAdminConfigHandlers', () => {
|
|||
await handlers.upsertConfigOverrides(req, res);
|
||||
|
||||
expect(res.statusCode).toBe(201);
|
||||
expect(deps.upsertConfig).toHaveBeenCalled();
|
||||
expect(deps.upsertConfig).toHaveBeenCalledWith(
|
||||
'role',
|
||||
'admin',
|
||||
expect.anything(),
|
||||
{},
|
||||
10,
|
||||
undefined,
|
||||
{ expectEmpty: true, preservePriority: true },
|
||||
);
|
||||
});
|
||||
|
||||
it('requests atomic priority preservation for ASSIGN_CONFIGS-only empty-overrides upsert', async () => {
|
||||
const findConfigByPrincipal = jest
|
||||
.fn()
|
||||
.mockResolvedValue({ _id: 'c1', priority: 7, overrides: {} });
|
||||
const { handlers, deps } = createHandlers({
|
||||
hasConfigCapability: jest.fn().mockResolvedValue(false),
|
||||
hasCapability: jest.fn().mockResolvedValue(true),
|
||||
findConfigByPrincipal,
|
||||
});
|
||||
const req = mockReq({
|
||||
params: { principalType: 'role', principalId: 'admin' },
|
||||
body: { overrides: {}, priority: 999 },
|
||||
});
|
||||
const res = mockRes();
|
||||
|
||||
await handlers.upsertConfigOverrides(req, res);
|
||||
|
||||
expect(res.statusCode).toBe(201);
|
||||
expect(deps.upsertConfig).toHaveBeenCalledWith(
|
||||
'role',
|
||||
'admin',
|
||||
expect.anything(),
|
||||
{},
|
||||
10,
|
||||
undefined,
|
||||
{ expectEmpty: true, preservePriority: true },
|
||||
);
|
||||
expect(findConfigByPrincipal).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects non-empty overrides for ASSIGN_CONFIGS-only caller', async () => {
|
||||
|
|
@ -1113,7 +1151,15 @@ describe('createAdminConfigHandlers', () => {
|
|||
await handlers.upsertConfigOverrides(req, res);
|
||||
|
||||
expect(res.statusCode).toBe(201);
|
||||
expect(deps.upsertConfig).toHaveBeenCalled();
|
||||
expect(deps.upsertConfig).toHaveBeenCalledWith(
|
||||
'role',
|
||||
'admin',
|
||||
expect.anything(),
|
||||
{},
|
||||
10,
|
||||
undefined,
|
||||
{ expectEmpty: true, preservePriority: true },
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects upsert when parameterized grant targets a different principalType', async () => {
|
||||
|
|
@ -1245,7 +1291,7 @@ describe('createAdminConfigHandlers', () => {
|
|||
expect.anything(),
|
||||
expect.anything(),
|
||||
undefined,
|
||||
{ expectEmpty: true },
|
||||
{ expectEmpty: true, preservePriority: true },
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export interface AdminConfigDeps {
|
|||
overrides: Partial<TCustomConfig>,
|
||||
priority: number,
|
||||
session?: ClientSession,
|
||||
options?: { expectEmpty?: boolean },
|
||||
options?: { expectEmpty?: boolean; preservePriority?: boolean },
|
||||
) => Promise<IConfig | null>;
|
||||
patchConfigFields: (
|
||||
principalType: PrincipalType,
|
||||
|
|
@ -393,14 +393,25 @@ export function createAdminConfigHandlers(deps: AdminConfigDeps): {
|
|||
return res.status(403).json({ error: 'Insufficient permissions' });
|
||||
}
|
||||
|
||||
if (priority != null && !hasBroadManage) {
|
||||
logger.warn(
|
||||
`[adminConfig] Ignoring caller-supplied priority on assign-only scope lifecycle upsert to ${principalType}/${principalId}: only broad manage:configs may modify document priority`,
|
||||
);
|
||||
}
|
||||
|
||||
const requestedPriority = hasBroadManage ? (priority ?? DEFAULT_PRIORITY) : DEFAULT_PRIORITY;
|
||||
const upsertOptions = hasBroadManage
|
||||
? { expectEmpty: false }
|
||||
: { expectEmpty: true, preservePriority: true };
|
||||
|
||||
const config = await upsertConfig(
|
||||
principalType,
|
||||
principalId,
|
||||
principalModel(principalType),
|
||||
filteredOverrides,
|
||||
priority ?? DEFAULT_PRIORITY,
|
||||
requestedPriority,
|
||||
undefined,
|
||||
{ expectEmpty: !hasBroadManage },
|
||||
upsertOptions,
|
||||
);
|
||||
if (!config && !hasBroadManage) {
|
||||
return res.status(403).json({ error: 'Insufficient permissions' });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue