mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-28 04:37:37 +00:00
🛑 fix: Separate Agent Event Backpressure From User Bans (#15200)
* 🛑 fix: Separate Agent Event Backpressure From User Bans
* fix: Address Agent Event Review Findings
* fix: Mirror Case-Insensitive Agent Control Routing
This commit is contained in:
parent
e9dec7749a
commit
d9e6250d05
4 changed files with 199 additions and 13 deletions
|
|
@ -53,11 +53,15 @@ jest.mock('ua-parser-js', () => jest.fn(() => ({ browser: { name: 'Chrome' } }))
|
|||
|
||||
const checkBan = require('~/server/middleware/checkBan');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { ViolationTypes } = require('librechat-data-provider');
|
||||
const { findUser } = require('~/models');
|
||||
const denyRequest = require('~/server/middleware/denyRequest');
|
||||
const uap = require('ua-parser-js');
|
||||
|
||||
const createReq = (overrides = {}) => ({
|
||||
ip: '192.168.1.1',
|
||||
user: { id: 'user123' },
|
||||
method: 'GET',
|
||||
headers: { 'user-agent': 'Mozilla/5.0' },
|
||||
body: {},
|
||||
baseUrl: '/api',
|
||||
|
|
@ -170,6 +174,110 @@ describe('checkBan middleware', () => {
|
|||
|
||||
expect(mockBanLogsGet).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(['/api/agents/chat/stream/stream-123', '/api/agents/chat/status/conversation-1'])(
|
||||
'returns JSON for a banned browser GET without a request body: %s',
|
||||
async (originalUrl) => {
|
||||
mockBanCacheGet.mockResolvedValueOnce({ expiresAt: Date.now() + 60000 });
|
||||
const req = createReq({
|
||||
body: undefined,
|
||||
baseUrl: '/api/agents',
|
||||
originalUrl,
|
||||
});
|
||||
const res = createRes();
|
||||
|
||||
await checkBan(req, res, jest.fn());
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(403);
|
||||
expect(res.json).toHaveBeenCalledWith({
|
||||
message: 'Your account has been temporarily banned due to violations of our service.',
|
||||
});
|
||||
expect(denyRequest).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
|
||||
it('preserves SSE denial for a banned browser interactive chat request', async () => {
|
||||
mockBanCacheGet.mockResolvedValueOnce({ expiresAt: Date.now() + 60000 });
|
||||
const req = createReq({
|
||||
method: 'POST',
|
||||
baseUrl: '/api/agents',
|
||||
originalUrl: '/api/agents/chat/agents',
|
||||
});
|
||||
const res = createRes();
|
||||
|
||||
await checkBan(req, res, jest.fn());
|
||||
|
||||
expect(denyRequest).toHaveBeenCalledWith(req, res, { type: ViolationTypes.BAN });
|
||||
expect(res.status).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(['active', 'status', 'stream'])(
|
||||
'preserves SSE denial when a custom endpoint uses the POST-only name %s',
|
||||
async (endpoint) => {
|
||||
mockBanCacheGet.mockResolvedValueOnce({ expiresAt: Date.now() + 60000 });
|
||||
const req = createReq({
|
||||
method: 'POST',
|
||||
baseUrl: '/api/agents',
|
||||
originalUrl: `/api/agents/chat/${endpoint}`,
|
||||
});
|
||||
const res = createRes();
|
||||
|
||||
await checkBan(req, res, jest.fn());
|
||||
|
||||
expect(denyRequest).toHaveBeenCalledWith(req, res, { type: ViolationTypes.BAN });
|
||||
expect(res.status).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
|
||||
it('returns JSON for a bodyless browser POST to an interactive chat path', async () => {
|
||||
mockBanCacheGet.mockResolvedValueOnce({ expiresAt: Date.now() + 60000 });
|
||||
const req = createReq({
|
||||
body: undefined,
|
||||
method: 'POST',
|
||||
baseUrl: '/api/agents',
|
||||
originalUrl: '/api/agents/chat/agents',
|
||||
});
|
||||
const res = createRes();
|
||||
|
||||
await checkBan(req, res, jest.fn());
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(403);
|
||||
expect(denyRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(['abort', 'Abort', 'STEER', 'sTeEr'])(
|
||||
'returns JSON for a banned browser agent control request: %s',
|
||||
async (route) => {
|
||||
mockBanCacheGet.mockResolvedValueOnce({ expiresAt: Date.now() + 60000 });
|
||||
const req = createReq({
|
||||
method: 'POST',
|
||||
baseUrl: '/api/agents',
|
||||
originalUrl: `/api/agents/chat/${route}`,
|
||||
});
|
||||
const res = createRes();
|
||||
|
||||
await checkBan(req, res, jest.fn());
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(403);
|
||||
expect(denyRequest).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
|
||||
it('keeps non-browser agent chat denial as JSON', async () => {
|
||||
uap.mockReturnValueOnce({ browser: {} });
|
||||
mockBanCacheGet.mockResolvedValueOnce({ expiresAt: Date.now() + 60000 });
|
||||
const req = createReq({
|
||||
method: 'POST',
|
||||
baseUrl: '/api/agents',
|
||||
originalUrl: '/api/agents/chat/agents',
|
||||
});
|
||||
const res = createRes();
|
||||
|
||||
await checkBan(req, res, jest.fn());
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(403);
|
||||
expect(denyRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('active ban (positive timeLeft)', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue