import { describe, expect, it, beforeEach, afterEach } from "vitest"; import { assertUnderRoot, resolveDataFile } from "@/lib/safe-path"; import { assertSafeCcApiBase } from "@/lib/cc-api-base"; import { createOAuthState, parseOAuthState } from "@/services/oauth/providers"; import { resetEnvCache } from "@/lib/env"; import path from "path"; describe("safe-path", () => { it("allows descendant under base", () => { const base = path.resolve("data"); const target = path.join(base, "mails", "1", "a.pdf"); expect(assertUnderRoot(base, target)).toBe(path.resolve(target)); }); it("rejects sibling prefix bypass", () => { const base = path.resolve("data"); const evil = path.resolve("data-evil", "secret"); expect(() => assertUnderRoot(base, evil)).toThrow("PATH_TRAVERSAL"); }); it("rejects absolute path outside data via resolveDataFile", () => { expect(() => resolveDataFile("/etc/passwd")).toThrow("PATH_TRAVERSAL"); }); }); describe("cc-api-base", () => { it("allows official carriercentral host", () => { const u = assertSafeCcApiBase( "https://test.saas.carriercentral.vip/api/", ); expect(u).toContain("carriercentral.vip"); }); it("rejects private IP", () => { expect(() => assertSafeCcApiBase("http://192.168.1.1/api")).toThrow( /PRIVATE|HOST|PROTOCOL|ALLOWED/, ); }); it("rejects metadata host", () => { expect(() => assertSafeCcApiBase("http://169.254.169.254/latest/meta-data"), ).toThrow(); }); }); describe("oauth state", () => { const prevSecret = process.env.SESSION_SECRET; beforeEach(() => { process.env.SESSION_SECRET = "unit-test-session-secret-at-least-32-chars!!"; process.env.DATABASE_URL = process.env.DATABASE_URL || "mysql://u:p@localhost:3306/t"; resetEnvCache(); }); afterEach(() => { if (prevSecret === undefined) delete process.env.SESSION_SECRET; else process.env.SESSION_SECRET = prevSecret; resetEnvCache(); }); it("roundtrips with actor", () => { const state = createOAuthState({ provider: "gmail", actor: "admin", name: "Gmail", }); const parsed = parseOAuthState(state); expect(parsed?.provider).toBe("gmail"); expect(parsed?.actor).toBe("admin"); expect(parsed?.exp).toBeTruthy(); }); it("rejects tampered sig", () => { const state = createOAuthState({ provider: "gmail", actor: "admin" }); const parts = state.split("."); parts[2] = "x".repeat(parts[2].length); expect(parseOAuthState(parts.join("."))).toBeNull(); }); });