diff --git a/src/app/api/plugins/execute/route.js b/src/app/api/plugins/execute/route.js index 5ebc773..ef05061 100644 --- a/src/app/api/plugins/execute/route.js +++ b/src/app/api/plugins/execute/route.js @@ -15,7 +15,14 @@ export async function POST(request, { params } = {}) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } - const { message, context = {} } = await request.json(); + let body; + try { + body = await request.json(); + } catch { + return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 }); + } + + const { message, context = {} } = body; if (!message) { return NextResponse.json({ error: 'Message is required' }, { status: 400 }); diff --git a/src/app/api/plugins/execute/route.test.js b/src/app/api/plugins/execute/route.test.js new file mode 100644 index 0000000..c911c47 --- /dev/null +++ b/src/app/api/plugins/execute/route.test.js @@ -0,0 +1,48 @@ +import { describe, expect, it, vi } from 'vitest'; + +const mocks = vi.hoisted(() => ({ + mockGetUser: vi.fn(), + mockInitialize: vi.fn(), + mockProcessCommand: vi.fn(), + mockGetAvailableCommands: vi.fn(), + mockGetHelpText: vi.fn() +})); + +vi.mock('@/lib/supabase.js', () => ({ + createSupabaseServerClient: vi.fn(() => ({ + auth: { + getUser: mocks.mockGetUser + } + })) +})); + +vi.mock('@/lib/plugins/PluginManager.js', () => ({ + pluginManager: { + initialized: false, + initialize: mocks.mockInitialize, + processCommand: mocks.mockProcessCommand, + getAvailableCommands: mocks.mockGetAvailableCommands, + getHelpText: mocks.mockGetHelpText, + plugins: new Map() + } +})); + +describe('POST /api/plugins/execute validation', () => { + it('returns 400 for malformed JSON instead of a generic 500', async () => { + mocks.mockGetUser.mockResolvedValue({ + data: { user: { id: 'auth-user-id' } }, + error: null + }); + + const { POST } = await import('./route.js'); + const response = await POST({ + json: vi.fn().mockRejectedValue(new SyntaxError('Unexpected token')) + }); + const body = await response.json(); + + expect(response.status).toBe(400); + expect(body.error).toBe('Invalid JSON body'); + expect(mocks.mockInitialize).not.toHaveBeenCalled(); + expect(mocks.mockProcessCommand).not.toHaveBeenCalled(); + }); +});