table-privileges.test.ts 10.0 KB

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