import { describe, expect, it } from "vitest"; import { createReadyDb } from "../helpers/world"; describe("papéis de manutenção", () => { it("cria web e worker sem superuser, sem bypass e sem herança", async () => { const db = await createReadyDb(); const rows = await db.withService((query) => query.query<{ rolname: string; rolsuper: boolean; rolbypassrls: boolean; rolinherit: boolean; rolcanlogin: boolean }>( `select rolname, rolsuper, rolbypassrls, rolinherit, rolcanlogin from pg_roles where rolname in ('adaptador_web', 'adaptador_worker', 'app_user') order by rolname`, ), ); expect(rows.map((row) => row.rolname)).toEqual(["adaptador_web", "adaptador_worker", "app_user"]); for (const row of rows) { expect(row.rolsuper, row.rolname).toBe(false); expect(row.rolbypassrls, row.rolname).toBe(false); expect(row.rolcanlogin, row.rolname).toBe(false); } expect(rows.find((row) => row.rolname === "adaptador_web")?.rolinherit).toBe(false); expect(rows.find((row) => row.rolname === "adaptador_worker")?.rolinherit).toBe(false); await db.close(); }); it("impede a web e o app_user de varrer a fila, e deixa o worker só nas funções", async () => { const db = await createReadyDb(); const denied = [ `begin; set local role adaptador_web; select * from public.spreadsheet_jobs; commit;`, `begin; set local role app_user; select * from public.adapter_list_queued_job_ids(); commit;`, `begin; set local role adaptador_web; select * from public.adapter_worker_context('aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', '11111111-1111-4111-8111-111111111111'); commit;`, ]; for (const statement of denied) { await expect(db.exec(statement)).rejects.toThrow(/permission denied/i); await db.exec("rollback"); } await expect( db.exec(`begin; set local role adaptador_worker; select * from public.adapter_list_queued_job_ids(); commit;`), ).resolves.toBeUndefined(); const signature = await db.withService((query) => query.query<{ result: string; prosecdef: boolean; proconfig: string[] | null }>( `select pg_get_function_result(p.oid) as result, p.prosecdef, p.proconfig from pg_proc p join pg_namespace n on n.oid = p.pronamespace where n.nspname = 'public' and p.proname = 'adapter_read_queued_job'`, ), ); expect(signature[0]?.prosecdef).toBe(true); expect(signature[0]?.proconfig?.join(" ")).toContain("search_path=pg_catalog"); expect(signature[0]?.result).not.toMatch(/content|cells|columns_schema|storage_key/i); await db.close(); }); it("mantém SET LOCAL ROLE dentro da transação do usuário", async () => { const db = await createReadyDb(); const rows = await db.withUser("aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", (query) => query.query<{ current_user: string }>(`select current_user`), ); expect(rows[0]?.current_user).toBe("app_user"); await db.close(); }); });