import { assertEquals, assertExists } from "jsr:@std/assert"; import { stub } from "jsr:@std/testing/mock"; import { app } from "../main.ts"; import { sqlWrapper } from "../db.ts"; import { valkey } from "../valkey.ts"; import { rateLimitWrapper } from "../ratelimit.ts"; const originalSql = sqlWrapper.sql; function setMockSql(mockImpl: () => Promise) { sqlWrapper.sql = mockImpl as any; } function restoreMockSql() { sqlWrapper.sql = originalSql; } rateLimitWrapper.checkRateLimit = () => Promise.resolve(true); Deno.test("Tier 1 & 2: GET /api/forward-auth - Valid session", async () => { const mockUser = { id: "user-id-1", username: "alice", account_status: "active", }; setMockSql(() => Promise.resolve([mockUser])); let queryCount = 0; setMockSql(() => { queryCount++; if (queryCount === 1) return Promise.resolve([mockUser]); // User lookup return Promise.resolve([]); // isGlobalAdmin lookup }); const valkeyStub = stub(valkey, "get", (key: any) => { const k = String(key); if (k.startsWith("auth:app_by_host:")) { return Promise.resolve( JSON.stringify({ id: "app-id-1", name: "test-app" }), ); } if (k.startsWith("auth:grants:")) { return Promise.resolve("viewer"); } return Promise.resolve( JSON.stringify({ uuid: "user-id-1", username: "alice" }), ); }); const req = new Request("http://localhost/api/forward-auth", { headers: { Cookie: "session_id=mock-session-id", "X-Forwarded-Host": "test.app.local", }, }); const res = await app.request(req); assertEquals(res.status, 200); assertEquals(res.headers.get("X-Forwarded-User"), "alice"); assertEquals(res.headers.get("X-Forwarded-User-Id"), "user-id-1"); assertEquals(res.headers.get("X-Forwarded-Scopes"), "viewer"); assertEquals(res.headers.get("X-Forwarded-App-Id"), "app-id-1"); restoreMockSql(); valkeyStub.restore(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Missing session (API request)", async () => { const req = new Request("http://localhost/api/forward-auth", { headers: { "X-Forwarded-Host": "test.app.local" }, }); const valkeyStub = stub(valkey, "get", (key: any) => { const k = String(key); if (k.startsWith("auth:app_by_host:")) { return Promise.resolve( JSON.stringify({ id: "app-id-1", name: "test-app" }), ); } return Promise.resolve(null); }); const res = await app.request(req); assertEquals(res.status, 401); valkeyStub.restore(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Missing session (Browser request with text/html)", async () => { const req = new Request("http://localhost/api/forward-auth", { headers: { "X-Forwarded-Host": "ed-droid.atyg.org", "X-Forwarded-Uri": "/control-panel", "X-Forwarded-Proto": "https", Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", }, }); const valkeyStub = stub(valkey, "get", (key: any) => { const k = String(key); if (k.startsWith("auth:app_by_host:")) { return Promise.resolve( JSON.stringify({ id: "app-id-1", name: "ed-droid" }), ); } return Promise.resolve(null); }); const res = await app.request(req); assertEquals(res.status, 302); const location = res.headers.get("Location"); assertExists(location); assertEquals( location?.includes( "login?redirect=https%3A%2F%2Fed-droid.atyg.org%2Fcontrol-panel", ), true, ); valkeyStub.restore(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Expired session", async () => { const valkeyStub = stub(valkey, "get", (key: any) => { const k = String(key); if (k.startsWith("auth:app_by_host:")) { return Promise.resolve( JSON.stringify({ id: "app-id-1", name: "test-app" }), ); } return Promise.resolve(null); }); const req = new Request("http://localhost/api/forward-auth", { headers: { Cookie: "session_id=expired-session-id", "X-Forwarded-Host": "test.app.local", }, }); const res = await app.request(req); assertEquals(res.status, 401); valkeyStub.restore(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Suspended account", async () => { const mockUser = { id: "user-id-1", username: "alice", account_status: "suspended", }; setMockSql(() => Promise.resolve([mockUser])); const valkeyStub = stub(valkey, "get", (key: any) => { const k = String(key); if (k.startsWith("auth:app_by_host:")) { return Promise.resolve( JSON.stringify({ id: "app-id-1", name: "test-app" }), ); } return Promise.resolve( JSON.stringify({ uuid: "user-id-1", username: "alice" }), ); }); const req = new Request("http://localhost/api/forward-auth", { headers: { Cookie: "session_id=mock-session-id", "X-Forwarded-Host": "test.app.local", }, }); const res = await app.request(req); assertEquals(res.status, 403); assertEquals(await res.text(), "Forbidden: Account inactive"); restoreMockSql(); valkeyStub.restore(); }); Deno.test("Cookie Domain Scoping - getCookieDomain derives wildcard parent domain", async () => { const { getCookieDomain } = await import("../auth-session.ts"); assertEquals(getCookieDomain("auth.atyg.org"), ".atyg.org"); assertEquals(getCookieDomain("ed-droid.atyg.org"), ".atyg.org"); assertEquals(getCookieDomain("atyg.org"), ".atyg.org"); assertEquals(getCookieDomain("localhost"), undefined); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Unregistered domain (API)", async () => { // Override sql to return no app sqlWrapper.sql = (async () => []) as any; const req = new Request("http://localhost/api/forward-auth", { headers: { "X-Forwarded-Host": "unknown.atyg.org", }, }); const res = await app.fetch(req); assertEquals(res.status, 403); const data = await res.json(); assertEquals(data.error, "Application not registered"); restoreMockSql(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Unregistered domain (Browser)", async () => { // Override sql to return no app sqlWrapper.sql = (async () => []) as any; const req = new Request("http://localhost/api/forward-auth", { headers: { "X-Forwarded-Host": "unknown.atyg.org", "Accept": "text/html", }, }); const res = await app.fetch(req); assertEquals(res.status, 302); const location = res.headers.get("Location") || ""; assertEquals( true, location.includes("/errors/unregistered?host=unknown.atyg.org"), ); restoreMockSql(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Dynamic Bypass (is_public)", async () => { // Override sql to return public app sqlWrapper.sql = (async (strings: any) => { if (strings[0].includes("FROM apps")) { return [{ id: "public-app-id", name: "Public App", is_public: true, }]; } return []; }) as any; const req = new Request("http://localhost/api/forward-auth", { headers: { "X-Forwarded-Host": "public.atyg.org", }, }); const res = await app.fetch(req); assertEquals(res.status, 200); assertEquals(res.headers.get("X-Forwarded-App-Id"), "public-app-id"); restoreMockSql(); }); Deno.test("Tier 1 & 2: GET /api/forward-auth - Dynamic Bypass (bypass_paths)", async () => { // Override sql to return app with bypass path sqlWrapper.sql = (async (strings: any) => { if (strings[0].includes("FROM apps")) { return [{ id: "bypass-app-id", name: "Bypass App", bypass_paths: ["/api/public/*"], }]; } return []; }) as any; const req = new Request("http://localhost/api/forward-auth", { headers: { "X-Forwarded-Host": "bypass.atyg.org", "X-Forwarded-Uri": "/api/public/status", }, }); const res = await app.fetch(req); assertEquals(res.status, 200); restoreMockSql(); }); Deno.test("Tier 1 & 2: POST /api/guests/sandbox - Creates guest session", async () => { const { valkey } = await import("../valkey.ts"); // Mock valkey.setex to prevent connection errors during tests valkey.setex = async () => "OK" as any; const req = new Request("http://localhost/api/guests/sandbox", { method: "POST", }); const res = await app.fetch(req); assertEquals(res.status, 200); const data = await res.json(); assertEquals(data.success, true); assertEquals(true, !!data.sessionId); assertEquals(true, !!data.guestUuid); });