Files
adaptador-planilhas/tests/integration/maintenance-roles.test.ts
Ferraz Fagundes 8c22597420
ci / lint, typecheck, testes e build (push) Canceled after 0s
ci / Postgres e Redis reais (push) Canceled after 0s
ci / imagem Docker Linux (push) Canceled after 0s
fix(db): protege conexoes e migrations de homologacao
2026-10-19 16:32:03 -03:00

63 lines
3.0 KiB
TypeScript

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();
});
});