63 lines
3.0 KiB
TypeScript
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();
|
|
});
|
|
});
|