builder / app /api /server-generate /__tests__ /desktop-auth.test.ts
Leon4gr45's picture
Upload folder using huggingface_hub
eeb9404 verified
Raw
History Blame Contribute Delete
4.91 kB
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import type { NextRequest } from 'next/server';
/**
* Route-level auth guard for /api/server-generate/*. This locks the behavior that
* regressed once: the desktop app runs in Server Mode but never issues an
* `osw_session` cookie (it only sets `osw_workspace`), so generation and its live
* event stream must authenticate through the desktop-aware `getSession()` (which
* returns a synthetic session when `OSW_DESKTOP=true`). The bug was that each route
* read the cookie directly and 401'd on desktop, breaking all server-side generation.
*
* The meaningful signal is the status code: with a desktop environment and NO cookie
* the route must NOT return 401 (auth passes); without desktop mode and no cookie it
* must return 401.
*/
// The desktop app never sets osw_session. cookies() returns nothing.
vi.mock('next/headers', () => ({
cookies: async () => ({ get: () => undefined }),
}));
// Neutralize the server-generation singletons so importing the routes is
// side-effect-free and post-auth logic has no real infrastructure to touch.
vi.mock('@/lib/server-generate/singleton', () => ({
taskManager: {
getTasksForSession: () => [],
getTask: () => undefined,
createTask: () => 'task-1',
},
eventBus: {
getBuffer: () => [],
replayFrom: () => [],
addListener: vi.fn(),
removeListener: vi.fn(),
},
}));
// Don't actually run a generation when the POST route passes auth.
vi.mock('@/lib/server-generate/server-orchestrator-runner', () => ({
runServerGeneration: vi.fn(),
}));
function makeReq(opts: { body?: unknown; url?: string } = {}): NextRequest {
const controller = new AbortController();
return {
// After the fix routes authenticate via getSession(); request.cookies is unused
// for auth but kept here so nothing throws if a route reads it.
cookies: { get: () => undefined },
headers: new Headers(),
nextUrl: new URL(opts.url ?? 'http://localhost/api/server-generate'),
signal: controller.signal,
json: async () => {
if (opts.body === undefined) throw new Error('no body');
return opts.body;
},
} as unknown as NextRequest;
}
const ORIGINAL_DESKTOP = process.env.OSW_DESKTOP;
beforeEach(() => {
delete process.env.OSW_DESKTOP;
vi.clearAllMocks();
});
afterEach(() => {
if (ORIGINAL_DESKTOP === undefined) delete process.env.OSW_DESKTOP;
else process.env.OSW_DESKTOP = ORIGINAL_DESKTOP;
});
describe('server-generate routes authenticate in desktop mode without a session cookie', () => {
it('POST /api/server-generate: 401 without desktop, not 401 with OSW_DESKTOP', async () => {
const { POST } = await import('../route');
const denied = await POST(makeReq({ body: {} }));
expect(denied.status).toBe(401);
process.env.OSW_DESKTOP = 'true';
const allowed = await POST(makeReq({ body: {} }));
// Passes auth, then fails validation on the empty body (400). The point is: not 401.
expect(allowed.status).not.toBe(401);
});
it('GET /api/server-generate/status: 401 without desktop, 200 with OSW_DESKTOP', async () => {
const { GET } = await import('../status/route');
const denied = await GET(makeReq({ url: 'http://localhost/api/server-generate/status' }));
expect(denied.status).toBe(401);
process.env.OSW_DESKTOP = 'true';
const allowed = await GET(makeReq({ url: 'http://localhost/api/server-generate/status' }));
expect(allowed.status).toBe(200);
});
// The mutation routes all read the body immediately after auth, so an empty body
// yields 400 once auth passes, never 401 in desktop mode.
it.each([
['cancel', () => import('../cancel/route')],
['pause', () => import('../pause/route')],
['resume', () => import('../resume/route')],
['build-result', () => import('../build-result/route')],
])('POST /api/server-generate/%s: 401 without desktop, not 401 with OSW_DESKTOP', async (_name, load) => {
const { POST } = await load();
const denied = await POST(makeReq());
expect(denied.status).toBe(401);
process.env.OSW_DESKTOP = 'true';
const allowed = await POST(makeReq());
expect(allowed.status).not.toBe(401);
});
it('GET /api/server-generate/events: 401 without desktop, streams (200) with OSW_DESKTOP', async () => {
const { GET } = await import('../events/route');
const denied = await GET(makeReq({ url: 'http://localhost/api/server-generate/events' }));
expect(denied.status).toBe(401);
// Fake timers so the stream's keepalive interval does not leak past the test.
vi.useFakeTimers();
try {
process.env.OSW_DESKTOP = 'true';
const allowed = await GET(makeReq({ url: 'http://localhost/api/server-generate/events' }));
expect(allowed.status).toBe(200);
} finally {
vi.clearAllTimers();
vi.useRealTimers();
}
});
});