table-privileges.test.ts390 lines · main
1import { afterAll, beforeAll, expect, test } from 'vitest'
2
3import pgMeta from '../src/index'
4import { cleanupRoot, createTestDatabase } from './db/utils'
5
6beforeAll(async () => {
7 // Any global setup if needed
8})
9
10afterAll(async () => {
11 await cleanupRoot()
12})
13
14const withTestDatabase = (
15 name: string,
16 fn: (db: Awaited<ReturnType<typeof createTestDatabase>>) => Promise<void>
17) => {
18 test(name, async () => {
19 const db = await createTestDatabase()
20 try {
21 await fn(db)
22 } finally {
23 await db.cleanup()
24 }
25 })
26}
27
28withTestDatabase('list table privileges', async ({ executeQuery }) => {
29 const { sql, zod } = await pgMeta.tablePrivileges.list()
30 const res = zod.parse(await executeQuery(sql))
31
32 expect(
33 res.find(({ schema, name }) => schema === 'public' && name === 'todos')
34 ).toMatchInlineSnapshot(
35 { relation_id: expect.any(Number) },
36 `
37 {
38 "kind": "table",
39 "name": "todos",
40 "privileges": [
41 {
42 "grantee": "postgres",
43 "grantor": "postgres",
44 "is_grantable": false,
45 "privilege_type": "INSERT",
46 },
47 {
48 "grantee": "postgres",
49 "grantor": "postgres",
50 "is_grantable": false,
51 "privilege_type": "SELECT",
52 },
53 {
54 "grantee": "postgres",
55 "grantor": "postgres",
56 "is_grantable": false,
57 "privilege_type": "UPDATE",
58 },
59 {
60 "grantee": "postgres",
61 "grantor": "postgres",
62 "is_grantable": false,
63 "privilege_type": "DELETE",
64 },
65 {
66 "grantee": "postgres",
67 "grantor": "postgres",
68 "is_grantable": false,
69 "privilege_type": "TRUNCATE",
70 },
71 {
72 "grantee": "postgres",
73 "grantor": "postgres",
74 "is_grantable": false,
75 "privilege_type": "REFERENCES",
76 },
77 {
78 "grantee": "postgres",
79 "grantor": "postgres",
80 "is_grantable": false,
81 "privilege_type": "TRIGGER",
82 },
83 ],
84 "relation_id": Any<Number>,
85 "schema": "public",
86 }
87 `
88 )
89})
90
91withTestDatabase('revoke & grant table privileges', async ({ executeQuery }) => {
92 // Get initial table privileges
93 const { sql: listSql, zod: listZod } = await pgMeta.tablePrivileges.list()
94 const listRes = listZod.parse(await executeQuery(listSql))
95 const { relation_id } = listRes.find(
96 ({ schema, name }) => schema === 'public' && name === 'todos'
97 )!
98
99 // Revoke all privileges
100 const { sql: revokeSql } = pgMeta.tablePrivileges.revoke([
101 {
102 relationId: relation_id,
103 grantee: 'postgres',
104 privilegeType: 'ALL',
105 },
106 ])
107 await executeQuery(revokeSql)
108
109 // Verify privileges were revoked
110 const { sql: retrieveSql, zod: retrieveZod } = await pgMeta.tablePrivileges.retrieve({
111 id: relation_id,
112 })
113 let privs = retrieveZod.parse((await executeQuery(retrieveSql))[0])
114 expect(privs).toMatchInlineSnapshot(
115 { relation_id: expect.any(Number) },
116 `
117 {
118 "kind": "table",
119 "name": "todos",
120 "privileges": [],
121 "relation_id": Any<Number>,
122 "schema": "public",
123 }
124 `
125 )
126
127 // Grant all privileges back
128 const { sql: grantSql } = pgMeta.tablePrivileges.grant([
129 {
130 relationId: relation_id,
131 grantee: 'postgres',
132 privilegeType: 'ALL',
133 },
134 ])
135 await executeQuery(grantSql)
136
137 // Verify privileges were granted
138 const { sql: verifyGrantSql } = await pgMeta.tablePrivileges.retrieve({ id: relation_id })
139 privs = retrieveZod.parse((await executeQuery(verifyGrantSql))[0])
140 expect(privs).toMatchInlineSnapshot(
141 { relation_id: expect.any(Number) },
142 `
143 {
144 "kind": "table",
145 "name": "todos",
146 "privileges": [
147 {
148 "grantee": "postgres",
149 "grantor": "postgres",
150 "is_grantable": false,
151 "privilege_type": "TRIGGER",
152 },
153 {
154 "grantee": "postgres",
155 "grantor": "postgres",
156 "is_grantable": false,
157 "privilege_type": "REFERENCES",
158 },
159 {
160 "grantee": "postgres",
161 "grantor": "postgres",
162 "is_grantable": false,
163 "privilege_type": "TRUNCATE",
164 },
165 {
166 "grantee": "postgres",
167 "grantor": "postgres",
168 "is_grantable": false,
169 "privilege_type": "DELETE",
170 },
171 {
172 "grantee": "postgres",
173 "grantor": "postgres",
174 "is_grantable": false,
175 "privilege_type": "UPDATE",
176 },
177 {
178 "grantee": "postgres",
179 "grantor": "postgres",
180 "is_grantable": false,
181 "privilege_type": "SELECT",
182 },
183 {
184 "grantee": "postgres",
185 "grantor": "postgres",
186 "is_grantable": false,
187 "privilege_type": "INSERT",
188 },
189 ],
190 "relation_id": Any<Number>,
191 "schema": "public",
192 }
193 `
194 )
195})
196
197withTestDatabase(
198 'revoke & grant table privileges w/ quoted table name',
199 async ({ executeQuery }) => {
200 // Create test role and schema
201 await executeQuery(`create role r; create schema "s 1"; create table "s 1"."t 1"();`)
202
203 // Get table privileges
204 const { sql: listSql, zod: listZod } = await pgMeta.tablePrivileges.list()
205 const listRes = listZod.parse(await executeQuery(listSql))
206 const { relation_id } = listRes.find(({ schema, name }) => schema === 's 1' && name === 't 1')!
207
208 // Grant all privileges
209 const { sql: grantSql } = pgMeta.tablePrivileges.grant([
210 {
211 relationId: relation_id,
212 grantee: 'r',
213 privilegeType: 'ALL',
214 },
215 ])
216 await executeQuery(grantSql)
217
218 // Verify privileges were granted
219 const { sql: retrieveSql, zod: retrieveZod } = await pgMeta.tablePrivileges.retrieve({
220 id: relation_id,
221 })
222 let privs = retrieveZod.parse((await executeQuery(retrieveSql))[0])
223 expect(privs).toMatchInlineSnapshot(
224 { relation_id: expect.any(Number) },
225 `
226 {
227 "kind": "table",
228 "name": "t 1",
229 "privileges": [
230 {
231 "grantee": "postgres",
232 "grantor": "postgres",
233 "is_grantable": false,
234 "privilege_type": "TRIGGER",
235 },
236 {
237 "grantee": "postgres",
238 "grantor": "postgres",
239 "is_grantable": false,
240 "privilege_type": "REFERENCES",
241 },
242 {
243 "grantee": "postgres",
244 "grantor": "postgres",
245 "is_grantable": false,
246 "privilege_type": "TRUNCATE",
247 },
248 {
249 "grantee": "postgres",
250 "grantor": "postgres",
251 "is_grantable": false,
252 "privilege_type": "DELETE",
253 },
254 {
255 "grantee": "postgres",
256 "grantor": "postgres",
257 "is_grantable": false,
258 "privilege_type": "UPDATE",
259 },
260 {
261 "grantee": "postgres",
262 "grantor": "postgres",
263 "is_grantable": false,
264 "privilege_type": "SELECT",
265 },
266 {
267 "grantee": "postgres",
268 "grantor": "postgres",
269 "is_grantable": false,
270 "privilege_type": "INSERT",
271 },
272 {
273 "grantee": "r",
274 "grantor": "postgres",
275 "is_grantable": false,
276 "privilege_type": "TRIGGER",
277 },
278 {
279 "grantee": "r",
280 "grantor": "postgres",
281 "is_grantable": false,
282 "privilege_type": "REFERENCES",
283 },
284 {
285 "grantee": "r",
286 "grantor": "postgres",
287 "is_grantable": false,
288 "privilege_type": "TRUNCATE",
289 },
290 {
291 "grantee": "r",
292 "grantor": "postgres",
293 "is_grantable": false,
294 "privilege_type": "DELETE",
295 },
296 {
297 "grantee": "r",
298 "grantor": "postgres",
299 "is_grantable": false,
300 "privilege_type": "UPDATE",
301 },
302 {
303 "grantee": "r",
304 "grantor": "postgres",
305 "is_grantable": false,
306 "privilege_type": "SELECT",
307 },
308 {
309 "grantee": "r",
310 "grantor": "postgres",
311 "is_grantable": false,
312 "privilege_type": "INSERT",
313 },
314 ],
315 "relation_id": Any<Number>,
316 "schema": "s 1",
317 }
318 `
319 )
320
321 // Revoke all privileges
322 const { sql: revokeSql } = pgMeta.tablePrivileges.revoke([
323 {
324 relationId: relation_id,
325 grantee: 'r',
326 privilegeType: 'ALL',
327 },
328 ])
329 await executeQuery(revokeSql)
330
331 // Verify privileges were revoked
332 const { sql: verifyRevokeSql } = await pgMeta.tablePrivileges.retrieve({ id: relation_id })
333 privs = retrieveZod.parse((await executeQuery(verifyRevokeSql))[0])
334 expect(privs).toMatchInlineSnapshot(
335 { relation_id: expect.any(Number) },
336 `
337 {
338 "kind": "table",
339 "name": "t 1",
340 "privileges": [
341 {
342 "grantee": "postgres",
343 "grantor": "postgres",
344 "is_grantable": false,
345 "privilege_type": "TRIGGER",
346 },
347 {
348 "grantee": "postgres",
349 "grantor": "postgres",
350 "is_grantable": false,
351 "privilege_type": "REFERENCES",
352 },
353 {
354 "grantee": "postgres",
355 "grantor": "postgres",
356 "is_grantable": false,
357 "privilege_type": "TRUNCATE",
358 },
359 {
360 "grantee": "postgres",
361 "grantor": "postgres",
362 "is_grantable": false,
363 "privilege_type": "DELETE",
364 },
365 {
366 "grantee": "postgres",
367 "grantor": "postgres",
368 "is_grantable": false,
369 "privilege_type": "UPDATE",
370 },
371 {
372 "grantee": "postgres",
373 "grantor": "postgres",
374 "is_grantable": false,
375 "privilege_type": "SELECT",
376 },
377 {
378 "grantee": "postgres",
379 "grantor": "postgres",
380 "is_grantable": false,
381 "privilege_type": "INSERT",
382 },
383 ],
384 "relation_id": Any<Number>,
385 "schema": "s 1",
386 }
387 `
388 )
389 }
390)