@nest-boot/row-level-security 7.0.0 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/enums/row-level-security-role.enum.d.ts +7 -0
  2. package/dist/enums/row-level-security-role.enum.js +12 -0
  3. package/dist/enums/row-level-security-role.enum.js.map +1 -0
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.js +3 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.spec.js +6 -14
  8. package/dist/index.spec.js.map +1 -1
  9. package/dist/interfaces/index.d.ts +0 -1
  10. package/dist/interfaces/index.js +0 -1
  11. package/dist/interfaces/index.js.map +1 -1
  12. package/dist/interfaces/policy-options.interface.d.ts +2 -2
  13. package/dist/interfaces/policy-sql-options.interface.d.ts +2 -2
  14. package/dist/row-level-security-driver.d.ts +15 -0
  15. package/dist/row-level-security-driver.js +136 -0
  16. package/dist/row-level-security-driver.js.map +1 -0
  17. package/dist/row-level-security-driver.spec.js +267 -0
  18. package/dist/row-level-security-driver.spec.js.map +1 -0
  19. package/dist/row-level-security-migration-generator.d.ts +1 -0
  20. package/dist/row-level-security-migration-generator.js +39 -8
  21. package/dist/row-level-security-migration-generator.js.map +1 -1
  22. package/dist/row-level-security-migration-generator.spec.js +181 -10
  23. package/dist/row-level-security-migration-generator.spec.js.map +1 -1
  24. package/dist/row-level-security-migration.d.ts +2 -4
  25. package/dist/row-level-security-migration.js +9 -7
  26. package/dist/row-level-security-migration.js.map +1 -1
  27. package/dist/row-level-security-migration.spec.js +7 -16
  28. package/dist/row-level-security-migration.spec.js.map +1 -1
  29. package/dist/row-level-security.d.ts +29 -0
  30. package/dist/row-level-security.js +69 -0
  31. package/dist/row-level-security.js.map +1 -0
  32. package/dist/row-level-security.spec.js +52 -0
  33. package/dist/row-level-security.spec.js.map +1 -0
  34. package/dist/tsconfig.build.tsbuildinfo +1 -1
  35. package/dist/utils/create-policy-bootstrap-sql-statements.d.ts +1 -1
  36. package/dist/utils/create-policy-bootstrap-sql-statements.js +1 -7
  37. package/dist/utils/create-policy-bootstrap-sql-statements.js.map +1 -1
  38. package/dist/utils/create-policy-privilege-down-sql-statements.d.ts +8 -0
  39. package/dist/utils/create-policy-privilege-down-sql-statements.js +93 -0
  40. package/dist/utils/create-policy-privilege-down-sql-statements.js.map +1 -0
  41. package/dist/utils/create-policy-role-sql-statements.d.ts +6 -0
  42. package/dist/utils/create-policy-role-sql-statements.js +48 -0
  43. package/dist/utils/create-policy-role-sql-statements.js.map +1 -0
  44. package/dist/utils/create-policy-up-sql-statements.js +8 -2
  45. package/dist/utils/create-policy-up-sql-statements.js.map +1 -1
  46. package/dist/utils/create-row-level-security-transaction-setup.d.ts +20 -0
  47. package/dist/utils/create-row-level-security-transaction-setup.js +53 -0
  48. package/dist/utils/create-row-level-security-transaction-setup.js.map +1 -0
  49. package/dist/utils/index.d.ts +2 -3
  50. package/dist/utils/index.js +2 -3
  51. package/dist/utils/index.js.map +1 -1
  52. package/dist/utils/policy-migration-sql.spec.js +125 -7
  53. package/dist/utils/policy-migration-sql.spec.js.map +1 -1
  54. package/package.json +4 -4
  55. package/dist/interfaces/row-level-security-options.interface.d.ts +0 -18
  56. package/dist/interfaces/row-level-security-options.interface.js +0 -3
  57. package/dist/interfaces/row-level-security-options.interface.js.map +0 -1
  58. package/dist/row-level-security-context.d.ts +0 -14
  59. package/dist/row-level-security-context.js +0 -38
  60. package/dist/row-level-security-context.js.map +0 -1
  61. package/dist/row-level-security-context.spec.js +0 -29
  62. package/dist/row-level-security-context.spec.js.map +0 -1
  63. package/dist/row-level-security-entity-manager.d.ts +0 -22
  64. package/dist/row-level-security-entity-manager.js +0 -135
  65. package/dist/row-level-security-entity-manager.js.map +0 -1
  66. package/dist/row-level-security-entity-manager.spec.js +0 -200
  67. package/dist/row-level-security-entity-manager.spec.js.map +0 -1
  68. package/dist/tsconfig.tsbuildinfo +0 -1
  69. package/dist/utils/default-row-level-security-options.d.ts +0 -3
  70. package/dist/utils/default-row-level-security-options.js +0 -9
  71. package/dist/utils/default-row-level-security-options.js.map +0 -1
  72. package/dist/utils/get-row-level-security-options.d.ts +0 -8
  73. package/dist/utils/get-row-level-security-options.js +0 -9
  74. package/dist/utils/get-row-level-security-options.js.map +0 -1
  75. package/dist/utils/policy-sql-options.d.ts +0 -12
  76. package/dist/utils/policy-sql-options.js +0 -3
  77. package/dist/utils/policy-sql-options.js.map +0 -1
  78. package/dist/utils/row-level-security-options-state.d.ts +0 -4
  79. package/dist/utils/row-level-security-options-state.js +0 -8
  80. package/dist/utils/row-level-security-options-state.js.map +0 -1
  81. package/dist/utils/set-row-level-security-options.d.ts +0 -3
  82. package/dist/utils/set-row-level-security-options.js +0 -13
  83. package/dist/utils/set-row-level-security-options.js.map +0 -1
  84. /package/dist/{row-level-security-context.spec.d.ts → row-level-security-driver.spec.d.ts} +0 -0
  85. /package/dist/{row-level-security-entity-manager.spec.d.ts → row-level-security.spec.d.ts} +0 -0
@@ -0,0 +1,7 @@
1
+ /** Built-in database roles used by row-level security helpers. */
2
+ export declare enum RowLevelSecurityRole {
3
+ /** Role used for unauthenticated or public RLS access. */
4
+ ANONYMOUS = "anonymous",
5
+ /** Role used for authenticated RLS access. */
6
+ AUTHENTICATED = "authenticated"
7
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowLevelSecurityRole = void 0;
4
+ /** Built-in database roles used by row-level security helpers. */
5
+ var RowLevelSecurityRole;
6
+ (function (RowLevelSecurityRole) {
7
+ /** Role used for unauthenticated or public RLS access. */
8
+ RowLevelSecurityRole["ANONYMOUS"] = "anonymous";
9
+ /** Role used for authenticated RLS access. */
10
+ RowLevelSecurityRole["AUTHENTICATED"] = "authenticated";
11
+ })(RowLevelSecurityRole || (exports.RowLevelSecurityRole = RowLevelSecurityRole = {}));
12
+ //# sourceMappingURL=row-level-security-role.enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security-role.enum.js","sourceRoot":"","sources":["../../src/enums/row-level-security-role.enum.ts"],"names":[],"mappings":";;;AAAA,kEAAkE;AAClE,IAAY,oBAKX;AALD,WAAY,oBAAoB;IAC9B,0DAA0D;IAC1D,+CAAuB,CAAA;IACvB,8CAA8C;IAC9C,uDAA+B,CAAA;AACjC,CAAC,EALW,oBAAoB,oCAApB,oBAAoB,QAK/B"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  export * from "./decorators/policy.decorator";
2
2
  export * from "./enums/policy-command.enum";
3
3
  export * from "./enums/policy-mode.enum";
4
+ export * from "./enums/row-level-security-role.enum";
4
5
  export * from "./interfaces";
5
- export * from "./row-level-security-context";
6
- export * from "./row-level-security-entity-manager";
6
+ export * from "./row-level-security";
7
+ export * from "./row-level-security-driver";
7
8
  export * from "./row-level-security-migration";
8
9
  export * from "./row-level-security-migration-generator";
9
10
  export * from "./utils";
package/dist/index.js CHANGED
@@ -17,9 +17,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./decorators/policy.decorator"), exports);
18
18
  __exportStar(require("./enums/policy-command.enum"), exports);
19
19
  __exportStar(require("./enums/policy-mode.enum"), exports);
20
+ __exportStar(require("./enums/row-level-security-role.enum"), exports);
20
21
  __exportStar(require("./interfaces"), exports);
21
- __exportStar(require("./row-level-security-context"), exports);
22
- __exportStar(require("./row-level-security-entity-manager"), exports);
22
+ __exportStar(require("./row-level-security"), exports);
23
+ __exportStar(require("./row-level-security-driver"), exports);
23
24
  __exportStar(require("./row-level-security-migration"), exports);
24
25
  __exportStar(require("./row-level-security-migration-generator"), exports);
25
26
  __exportStar(require("./utils"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gEAA8C;AAC9C,8DAA4C;AAC5C,2DAAyC;AACzC,+CAA6B;AAC7B,+DAA6C;AAC7C,sEAAoD;AACpD,iEAA+C;AAC/C,2EAAyD;AACzD,0CAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gEAA8C;AAC9C,8DAA4C;AAC5C,2DAAyC;AACzC,uEAAqD;AACrD,+CAA6B;AAC7B,uDAAqC;AACrC,8DAA4C;AAC5C,iEAA+C;AAC/C,2EAAyD;AACzD,0CAAwB"}
@@ -36,35 +36,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const rowLevelSecurity = __importStar(require("."));
37
37
  const rowLevelSecurityUtils = __importStar(require("./utils"));
38
38
  describe("row level security package exports", () => {
39
- afterEach(() => {
40
- rowLevelSecurityUtils.setRowLevelSecurityOptions();
41
- });
42
39
  it("exports the public package API", () => {
43
40
  expect(rowLevelSecurity.Policy).toBeDefined();
44
41
  expect(rowLevelSecurity.PolicyCommand.SELECT).toBe("select");
45
42
  expect(rowLevelSecurity.PolicyMode.PERMISSIVE).toBe("permissive");
46
- expect(rowLevelSecurity.RowLevelSecurityContext).toBeDefined();
47
- expect(rowLevelSecurity.RowLevelSecurityEntityManager).toBeDefined();
43
+ expect(rowLevelSecurity.RowLevelSecurity).toBeDefined();
44
+ expect(rowLevelSecurity.RowLevelSecurityMode.AUTO).toBe("auto");
45
+ expect(rowLevelSecurity.RowLevelSecurityRole.ANONYMOUS).toBe("anonymous");
46
+ expect(rowLevelSecurity.RowLevelSecurityConnection).toBeDefined();
47
+ expect(rowLevelSecurity.RowLevelSecurityDriver).toBeDefined();
48
48
  expect(rowLevelSecurity.RowLevelSecurityMigration).toBeDefined();
49
49
  expect(rowLevelSecurity.RowLevelSecurityMigrationGenerator).toBeDefined();
50
50
  expect(rowLevelSecurity.createPolicyUpSqlStatements).toBeDefined();
51
51
  });
52
52
  it("exports utility helpers", () => {
53
53
  expect(rowLevelSecurityUtils.assertIdentifier("valid_identifier")).toBe("valid_identifier");
54
- expect(rowLevelSecurityUtils.DEFAULT_ROW_LEVEL_SECURITY_OPTIONS).toEqual({
55
- anonymousRole: "anonymous",
56
- authenticatedRole: "authenticated",
57
- });
58
54
  expect(rowLevelSecurityUtils.createPolicyBootstrapSqlStatements()).toEqual(expect.arrayContaining(["create schema if not exists app;"]));
55
+ expect(rowLevelSecurityUtils.createPolicyRoleUpSqlStatements()).toEqual(expect.arrayContaining(["grant anonymous to current_user;"]));
59
56
  });
60
57
  it("exports migration generator types", () => {
61
58
  const diff = { down: [], up: [] };
62
59
  expect(diff).toEqual({ down: [], up: [] });
63
60
  });
64
- it("returns a copy of process-level options", () => {
65
- const options = rowLevelSecurityUtils.getRowLevelSecurityOptions();
66
- options.authenticatedRole = "mutated";
67
- expect(rowLevelSecurityUtils.getRowLevelSecurityOptions().authenticatedRole).toBe("authenticated");
68
- });
69
61
  });
70
62
  //# sourceMappingURL=index.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.spec.js","sourceRoot":"","sources":["../src/index.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oDAAsC;AACtC,+DAAiD;AAEjD,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,SAAS,CAAC,GAAG,EAAE;QACb,qBAAqB,CAAC,0BAA0B,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClE,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/D,MAAM,CAAC,gBAAgB,CAAC,6BAA6B,CAAC,CAAC,WAAW,EAAE,CAAC;QACrE,MAAM,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,WAAW,EAAE,CAAC;QACjE,MAAM,CAAC,gBAAgB,CAAC,kCAAkC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1E,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,CAAC,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CACrE,kBAAkB,CACnB,CAAC;QACF,MAAM,CAAC,qBAAqB,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;YACvE,aAAa,EAAE,WAAW;YAC1B,iBAAiB,EAAE,eAAe;SACnC,CAAC,CAAC;QACH,MAAM,CAAC,qBAAqB,CAAC,kCAAkC,EAAE,CAAC,CAAC,OAAO,CACxE,MAAM,CAAC,eAAe,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,IAAI,GAAkB,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QAEjD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,OAAO,GAAG,qBAAqB,CAAC,0BAA0B,EAAE,CAAC;QAEnE,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;QAEtC,MAAM,CACJ,qBAAqB,CAAC,0BAA0B,EAAE,CAAC,iBAAiB,CACrE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.spec.js","sourceRoot":"","sources":["../src/index.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oDAAsC;AACtC,+DAAiD;AAEjD,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClE,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;QACxD,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChE,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1E,MAAM,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,WAAW,EAAE,CAAC;QAClE,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9D,MAAM,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,WAAW,EAAE,CAAC;QACjE,MAAM,CAAC,gBAAgB,CAAC,kCAAkC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1E,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,CAAC,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CACrE,kBAAkB,CACnB,CAAC;QACF,MAAM,CAAC,qBAAqB,CAAC,kCAAkC,EAAE,CAAC,CAAC,OAAO,CACxE,MAAM,CAAC,eAAe,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAC7D,CAAC;QACF,MAAM,CAAC,qBAAqB,CAAC,+BAA+B,EAAE,CAAC,CAAC,OAAO,CACrE,MAAM,CAAC,eAAe,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,IAAI,GAAkB,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QAEjD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -2,4 +2,3 @@ export * from "./policy-metadata.interface";
2
2
  export * from "./policy-options.interface";
3
3
  export * from "./policy-sql-options.interface";
4
4
  export type { MigrationDiff } from "./row-level-security-migration-generator.interface";
5
- export * from "./row-level-security-options.interface";
@@ -17,5 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./policy-metadata.interface"), exports);
18
18
  __exportStar(require("./policy-options.interface"), exports);
19
19
  __exportStar(require("./policy-sql-options.interface"), exports);
20
- __exportStar(require("./row-level-security-options.interface"), exports);
21
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,6DAA2C;AAC3C,iEAA+C;AAE/C,yEAAuD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,6DAA2C;AAC3C,iEAA+C"}
@@ -12,9 +12,9 @@ export interface PolicyOptions {
12
12
  property?: string;
13
13
  /** Row-level security context key read through `app.get_context`. */
14
14
  context?: string;
15
- /** Explicit `USING` expression. Overrides the generated predicate when provided. */
15
+ /** Explicit `USING` expression. Overrides the generated predicate when provided. Raw expressions are parenthesized in generated SQL. */
16
16
  using?: string;
17
- /** Explicit `WITH CHECK` expression. Overrides the generated predicate when provided. */
17
+ /** Explicit `WITH CHECK` expression. Overrides the generated predicate when provided. Raw expressions are parenthesized in generated SQL. */
18
18
  withCheck?: string;
19
19
  /** Database roles to which the policy applies. Empty or omitted means no role restriction. */
20
20
  roles?: string[];
@@ -12,9 +12,9 @@ export interface PolicySqlOptions {
12
12
  mode?: PolicyMode;
13
13
  /** PostgreSQL command covered by the policy. Defaults to {@link PolicyCommand.ALL}. */
14
14
  command?: PolicyCommand;
15
- /** SQL expression emitted as the policy `USING` predicate. */
15
+ /** SQL expression emitted as the policy `USING` predicate. Raw expressions are parenthesized in generated SQL. */
16
16
  using?: string;
17
- /** SQL expression emitted as the policy `WITH CHECK` predicate. */
17
+ /** SQL expression emitted as the policy `WITH CHECK` predicate. Raw expressions are parenthesized in generated SQL. */
18
18
  withCheck?: string;
19
19
  /** Database roles to which the generated policy applies. */
20
20
  roles?: string[];
@@ -0,0 +1,15 @@
1
+ import type { AnyEntity, Configuration, EntityData, LoggingOptions, QueryResult, Transaction } from "@mikro-orm/core";
2
+ import { AbstractSqlDriver, Knex, PostgreSqlConnection } from "@mikro-orm/postgresql";
3
+ /** PostgreSQL connection that applies RLS role and context at SQL execution time. */
4
+ export declare class RowLevelSecurityConnection extends PostgreSqlConnection {
5
+ /** Applies row level security setup before delegating SQL execution to MikroORM. */
6
+ execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(queryOrKnex: string | Knex.QueryBuilder | Knex.Raw, params?: unknown[], method?: "all" | "get" | "run", ctx?: Transaction, loggerContext?: LoggingOptions): Promise<T>;
7
+ private runInTransactionQueue;
8
+ private configureRowLevelSecurity;
9
+ private clearRowLevelSecurity;
10
+ }
11
+ /** MikroORM PostgreSQL driver that applies row level security per SQL query. */
12
+ export declare class RowLevelSecurityDriver extends AbstractSqlDriver<RowLevelSecurityConnection> {
13
+ /** Creates a PostgreSQL driver using the row level security connection. */
14
+ constructor(config: Configuration);
15
+ }
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowLevelSecurityDriver = exports.RowLevelSecurityConnection = void 0;
4
+ const postgresql_1 = require("@mikro-orm/postgresql");
5
+ const create_row_level_security_transaction_setup_1 = require("./utils/create-row-level-security-transaction-setup");
6
+ const ROW_LEVEL_SECURITY_TRANSACTION_SIGNATURE = Symbol("rowLevelSecurityTransactionSignature");
7
+ const ROW_LEVEL_SECURITY_TRANSACTION_CONTEXT_KEYS = Symbol("rowLevelSecurityTransactionContextKeys");
8
+ const ROW_LEVEL_SECURITY_TRANSACTION_QUEUE = Symbol("rowLevelSecurityTransactionQueue");
9
+ /** PostgreSQL connection that applies RLS role and context at SQL execution time. */
10
+ class RowLevelSecurityConnection extends postgresql_1.PostgreSqlConnection {
11
+ /** Applies row level security setup before delegating SQL execution to MikroORM. */
12
+ async execute(queryOrKnex, params = [], method = "all", ctx, loggerContext) {
13
+ const setup = (0, create_row_level_security_transaction_setup_1.createRowLevelSecurityTransactionSetup)();
14
+ const transactionContext = getTransactionContext(queryOrKnex, ctx);
15
+ if (transactionContext) {
16
+ return await this.runInTransactionQueue(transactionContext.state, async () => {
17
+ await this.configureRowLevelSecurity(transactionContext.state, transactionContext.execution, setup, loggerContext);
18
+ return await super.execute(queryOrKnex, params, method, transactionContext.execution, loggerContext);
19
+ });
20
+ }
21
+ if (!setup || setup.action === "clear") {
22
+ return await super.execute(queryOrKnex, params, method, ctx, loggerContext);
23
+ }
24
+ return await this.transactional(async (trx) => {
25
+ const transactionState = trx;
26
+ return await this.runInTransactionQueue(transactionState, async () => {
27
+ await this.configureRowLevelSecurity(transactionState, trx, setup, loggerContext);
28
+ return await super.execute(queryOrKnex, params, method, trx, loggerContext);
29
+ });
30
+ }, {
31
+ loggerContext,
32
+ });
33
+ }
34
+ async runInTransactionQueue(transactionState, callback) {
35
+ const previous = transactionState[ROW_LEVEL_SECURITY_TRANSACTION_QUEUE];
36
+ let release = () => {
37
+ return;
38
+ };
39
+ const current = new Promise((resolve) => {
40
+ release = resolve;
41
+ });
42
+ const queued = (previous ?? Promise.resolve()).then(() => current, () => current);
43
+ transactionState[ROW_LEVEL_SECURITY_TRANSACTION_QUEUE] = queued;
44
+ await previous?.catch(() => undefined);
45
+ try {
46
+ return await callback();
47
+ }
48
+ finally {
49
+ release();
50
+ if (transactionState[ROW_LEVEL_SECURITY_TRANSACTION_QUEUE] === queued) {
51
+ transactionState[ROW_LEVEL_SECURITY_TRANSACTION_QUEUE] = undefined;
52
+ }
53
+ }
54
+ }
55
+ async configureRowLevelSecurity(transactionState, ctx, setup, loggerContext) {
56
+ if (!setup) {
57
+ await this.clearRowLevelSecurity(transactionState, ctx, loggerContext);
58
+ return;
59
+ }
60
+ if (setup.action === "clear") {
61
+ await this.clearRowLevelSecurity(transactionState, ctx, loggerContext);
62
+ return;
63
+ }
64
+ const staleContextKeys = getStaleContextKeys(transactionState[ROW_LEVEL_SECURITY_TRANSACTION_CONTEXT_KEYS] ?? [], setup.contextKeys);
65
+ const setupSql = [setup.sql, createClearContextSql(staleContextKeys)]
66
+ .filter(Boolean)
67
+ .join("\n");
68
+ if (transactionState[ROW_LEVEL_SECURITY_TRANSACTION_SIGNATURE] ===
69
+ setup.signature &&
70
+ staleContextKeys.length === 0) {
71
+ return;
72
+ }
73
+ await super.execute(setupSql, [], "run", ctx, loggerContext);
74
+ transactionState[ROW_LEVEL_SECURITY_TRANSACTION_SIGNATURE] =
75
+ setup.signature;
76
+ transactionState[ROW_LEVEL_SECURITY_TRANSACTION_CONTEXT_KEYS] = [
77
+ ...setup.contextKeys,
78
+ ];
79
+ }
80
+ async clearRowLevelSecurity(transactionState, ctx, loggerContext) {
81
+ const contextKeys = transactionState[ROW_LEVEL_SECURITY_TRANSACTION_CONTEXT_KEYS] ?? [];
82
+ if (!transactionState[ROW_LEVEL_SECURITY_TRANSACTION_SIGNATURE] &&
83
+ contextKeys.length === 0) {
84
+ return;
85
+ }
86
+ await super.execute([/* SQL */ "SET LOCAL ROLE NONE;", createClearContextSql(contextKeys)]
87
+ .filter(Boolean)
88
+ .join("\n"), [], "run", ctx, loggerContext);
89
+ transactionState[ROW_LEVEL_SECURITY_TRANSACTION_SIGNATURE] = undefined;
90
+ transactionState[ROW_LEVEL_SECURITY_TRANSACTION_CONTEXT_KEYS] = [];
91
+ }
92
+ }
93
+ exports.RowLevelSecurityConnection = RowLevelSecurityConnection;
94
+ /** MikroORM PostgreSQL driver that applies row level security per SQL query. */
95
+ class RowLevelSecurityDriver extends postgresql_1.AbstractSqlDriver {
96
+ /** Creates a PostgreSQL driver using the row level security connection. */
97
+ constructor(config) {
98
+ super(config, new postgresql_1.PostgreSqlPlatform(), RowLevelSecurityConnection, [
99
+ "knex",
100
+ "pg",
101
+ ]);
102
+ }
103
+ }
104
+ exports.RowLevelSecurityDriver = RowLevelSecurityDriver;
105
+ function getTransactionContext(queryOrKnex, ctx) {
106
+ if (ctx) {
107
+ return {
108
+ state: ctx,
109
+ execution: ctx,
110
+ };
111
+ }
112
+ if (typeof queryOrKnex === "string") {
113
+ return undefined;
114
+ }
115
+ const knexQuery = queryOrKnex;
116
+ if (!knexQuery.client?.transacting) {
117
+ return undefined;
118
+ }
119
+ return {
120
+ state: knexQuery.client,
121
+ execution: queryOrKnex,
122
+ };
123
+ }
124
+ function getStaleContextKeys(previousKeys, nextKeys) {
125
+ const nextKeySet = new Set(nextKeys);
126
+ return previousKeys.filter((key) => !nextKeySet.has(key));
127
+ }
128
+ function createClearContextSql(contextKeys) {
129
+ if (contextKeys.length === 0) {
130
+ return "";
131
+ }
132
+ return `SELECT ${contextKeys
133
+ .map((key) => `set_config('app.${key}', '', true)`)
134
+ .join(",")};`;
135
+ }
136
+ //# sourceMappingURL=row-level-security-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security-driver.js","sourceRoot":"","sources":["../src/row-level-security-driver.ts"],"names":[],"mappings":";;;AAQA,sDAK+B;AAE/B,qHAG6D;AAE7D,MAAM,wCAAwC,GAAG,MAAM,CACrD,sCAAsC,CACvC,CAAC;AACF,MAAM,2CAA2C,GAAG,MAAM,CACxD,wCAAwC,CACzC,CAAC;AACF,MAAM,oCAAoC,GAAG,MAAM,CACjD,kCAAkC,CACnC,CAAC;AAaF,qFAAqF;AACrF,MAAa,0BAA2B,SAAQ,iCAAoB;IAClE,oFAAoF;IAC3E,KAAK,CAAC,OAAO,CAIpB,WAAkD,EAClD,SAAoB,EAAE,EACtB,SAAgC,KAAK,EACrC,GAAiB,EACjB,aAA8B;QAE9B,MAAM,KAAK,GAAG,IAAA,oFAAsC,GAAE,CAAC;QACvD,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAEnE,IAAI,kBAAkB,EAAE,CAAC;YACvB,OAAO,MAAM,IAAI,CAAC,qBAAqB,CACrC,kBAAkB,CAAC,KAAK,EACxB,KAAK,IAAI,EAAE;gBACT,MAAM,IAAI,CAAC,yBAAyB,CAClC,kBAAkB,CAAC,KAAK,EACxB,kBAAkB,CAAC,SAAS,EAC5B,KAAK,EACL,aAAa,CACd,CAAC;gBAEF,OAAO,MAAM,KAAK,CAAC,OAAO,CACxB,WAAW,EACX,MAAM,EACN,MAAM,EACN,kBAAkB,CAAC,SAAS,EAC5B,aAAa,CACd,CAAC;YACJ,CAAC,CACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YACvC,OAAO,MAAM,KAAK,CAAC,OAAO,CACxB,WAAW,EACX,MAAM,EACN,MAAM,EACN,GAAG,EACH,aAAa,CACd,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,IAAI,CAAC,aAAa,CAC7B,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,gBAAgB,GAAG,GAAuC,CAAC;YAEjE,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE;gBACnE,MAAM,IAAI,CAAC,yBAAyB,CAClC,gBAAgB,EAChB,GAAG,EACH,KAAK,EACL,aAAa,CACd,CAAC;gBAEF,OAAO,MAAM,KAAK,CAAC,OAAO,CACxB,WAAW,EACX,MAAM,EACN,MAAM,EACN,GAAG,EACH,aAAa,CACd,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,EACD;YACE,aAAa;SACd,CACF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,qBAAqB,CACjC,gBAAkD,EAClD,QAA0B;QAE1B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,oCAAoC,CAAC,CAAC;QACxE,IAAI,OAAO,GAAe,GAAG,EAAE;YAC7B,OAAO;QACT,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5C,OAAO,GAAG,OAAO,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CACjD,GAAG,EAAE,CAAC,OAAO,EACb,GAAG,EAAE,CAAC,OAAO,CACd,CAAC;QAEF,gBAAgB,CAAC,oCAAoC,CAAC,GAAG,MAAM,CAAC;QAChE,MAAM,QAAQ,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAEvC,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,EAAE,CAAC;QAC1B,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;YAEV,IAAI,gBAAgB,CAAC,oCAAoC,CAAC,KAAK,MAAM,EAAE,CAAC;gBACtE,gBAAgB,CAAC,oCAAoC,CAAC,GAAG,SAAS,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,yBAAyB,CACrC,gBAAkD,EAClD,GAAgB,EAChB,KAAmD,EACnD,aAA8B;QAE9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,MAAM,gBAAgB,GAAG,mBAAmB,CAC1C,gBAAgB,CAAC,2CAA2C,CAAC,IAAI,EAAE,EACnE,KAAK,CAAC,WAAW,CAClB,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;aAClE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,IACE,gBAAgB,CAAC,wCAAwC,CAAC;YACxD,KAAK,CAAC,SAAS;YACjB,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAC7B,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;QAC7D,gBAAgB,CAAC,wCAAwC,CAAC;YACxD,KAAK,CAAC,SAAS,CAAC;QAClB,gBAAgB,CAAC,2CAA2C,CAAC,GAAG;YAC9D,GAAG,KAAK,CAAC,WAAW;SACrB,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,qBAAqB,CACjC,gBAAkD,EAClD,GAAgB,EAChB,aAA8B;QAE9B,MAAM,WAAW,GACf,gBAAgB,CAAC,2CAA2C,CAAC,IAAI,EAAE,CAAC;QAEtE,IACE,CAAC,gBAAgB,CAAC,wCAAwC,CAAC;YAC3D,WAAW,CAAC,MAAM,KAAK,CAAC,EACxB,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,KAAK,CAAC,OAAO,CACjB,CAAC,SAAS,CAAC,sBAAsB,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;aACnE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,EACb,EAAE,EACF,KAAK,EACL,GAAG,EACH,aAAa,CACd,CAAC;QACF,gBAAgB,CAAC,wCAAwC,CAAC,GAAG,SAAS,CAAC;QACvE,gBAAgB,CAAC,2CAA2C,CAAC,GAAG,EAAE,CAAC;IACrE,CAAC;CACF;AA3KD,gEA2KC;AAED,gFAAgF;AAChF,MAAa,sBAAuB,SAAQ,8BAA6C;IACvF,2EAA2E;IAC3E,YAAY,MAAqB;QAC/B,KAAK,CAAC,MAAM,EAAE,IAAI,+BAAkB,EAAE,EAAE,0BAA0B,EAAE;YAClE,MAAM;YACN,IAAI;SACL,CAAC,CAAC;IACL,CAAC;CACF;AARD,wDAQC;AAED,SAAS,qBAAqB,CAC5B,WAAoB,EACpB,GAAY;IAEZ,IAAI,GAAG,EAAE,CAAC;QACR,OAAO;YACL,KAAK,EAAE,GAAuC;YAC9C,SAAS,EAAE,GAAkB;SAC9B,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,WAIjB,CAAC;IAEF,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;QACnC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,KAAK,EAAE,SAAS,CAAC,MAA0C;QAC3D,SAAS,EAAE,WAA0B;KACtC,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,YAAsB,EAAE,QAAkB;IACrE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAErC,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,qBAAqB,CAAC,WAAqB;IAClD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,UAAU,WAAW;SACzB,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,GAAG,cAAc,CAAC;SAClD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAClB,CAAC"}
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const postgresql_1 = require("@mikro-orm/postgresql");
4
+ const request_context_1 = require("@nest-boot/request-context");
5
+ const row_level_security_1 = require("./row-level-security");
6
+ const row_level_security_driver_1 = require("./row-level-security-driver");
7
+ describe("RowLevelSecurityDriver", () => {
8
+ afterEach(() => {
9
+ jest.restoreAllMocks();
10
+ });
11
+ it("delegates unchanged outside RequestContext by default", async () => {
12
+ const executeSpy = mockPostgreSqlExecute("query-result");
13
+ const transactional = jest.fn();
14
+ const connection = createConnection({ transactional });
15
+ const result = await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, "select original", [], "all");
16
+ expect(result).toBe("query-result");
17
+ expect(transactional).not.toHaveBeenCalled();
18
+ expect(executeSpy).toHaveBeenCalledTimes(1);
19
+ expect(executeSpy).toHaveBeenCalledWith("select original", [], "all", undefined, undefined);
20
+ });
21
+ it("delegates unchanged inside RequestContext when no row level security context is set", async () => {
22
+ const executeSpy = mockPostgreSqlExecute("query-result");
23
+ const transactional = jest.fn();
24
+ const connection = createConnection({ transactional });
25
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "job" }), async () => {
26
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, "select original", [], "all");
27
+ });
28
+ expect(result).toBe("query-result");
29
+ expect(transactional).not.toHaveBeenCalled();
30
+ expect(executeSpy).toHaveBeenCalledTimes(1);
31
+ expect(executeSpy).toHaveBeenCalledWith("select original", [], "all", undefined, undefined);
32
+ });
33
+ it("delegates unchanged when row level security mode is disabled", async () => {
34
+ const executeSpy = mockPostgreSqlExecute("query-result");
35
+ const transactional = jest.fn();
36
+ const connection = createConnection({ transactional });
37
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "job" }), async () => {
38
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.DISABLED);
39
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
40
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 7);
41
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, "select original", [], "all");
42
+ });
43
+ expect(result).toBe("query-result");
44
+ expect(transactional).not.toHaveBeenCalled();
45
+ expect(executeSpy).toHaveBeenCalledTimes(1);
46
+ expect(executeSpy).toHaveBeenCalledWith("select original", [], "all", undefined, undefined);
47
+ });
48
+ it("clears transaction-local row level security before a disabled query", async () => {
49
+ const transaction = {};
50
+ const executeSpy = mockPostgreSqlExecute("query-result");
51
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
52
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
53
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 7);
54
+ row_level_security_1.RowLevelSecurity.setContext("request_id", "abc");
55
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select scoped", [], "all", transaction);
56
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.DISABLED);
57
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select disabled", [], "all", transaction);
58
+ });
59
+ expect(executeSpy).toHaveBeenNthCalledWith(3, "SET LOCAL ROLE NONE;\nSELECT set_config('app.tenant_id', '', true),set_config('app.request_id', '', true);", [], "run", transaction, undefined);
60
+ expect(executeSpy).toHaveBeenNthCalledWith(4, "select disabled", [], "all", transaction, undefined);
61
+ });
62
+ it("clears transaction-local row level security before a query without RequestContext", async () => {
63
+ const transaction = {};
64
+ const executeSpy = mockPostgreSqlExecute("query-result");
65
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
66
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
67
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 7);
68
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select scoped", [], "all", transaction);
69
+ });
70
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select unscoped", [], "all", transaction);
71
+ expect(executeSpy).toHaveBeenNthCalledWith(3, "SET LOCAL ROLE NONE;\nSELECT set_config('app.tenant_id', '', true);", [], "run", transaction, undefined);
72
+ expect(executeSpy).toHaveBeenNthCalledWith(4, "select unscoped", [], "all", transaction, undefined);
73
+ });
74
+ it("applies anonymous row level security when mode is enabled without context values", async () => {
75
+ const executeSpy = mockPostgreSqlExecute("query-result");
76
+ const transaction = {};
77
+ const transactional = jest.fn(async (cb) => {
78
+ return await cb(transaction);
79
+ });
80
+ const connection = createConnection({ transactional });
81
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), async () => {
82
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.ENABLED);
83
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, "select original", [], "all");
84
+ });
85
+ expect(result).toBe("query-result");
86
+ expect(transactional).toHaveBeenCalledTimes(1);
87
+ expect(executeSpy).toHaveBeenNthCalledWith(1, "SET LOCAL ROLE anonymous;", [], "run", transaction, undefined);
88
+ });
89
+ it("applies row level security on an existing transaction before executing the query", async () => {
90
+ const transaction = {};
91
+ const loggerContext = { label: "test" };
92
+ const executeSpy = mockPostgreSqlExecute("query-result");
93
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
94
+ row_level_security_1.RowLevelSecurity.setRole("app_authenticated");
95
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 42);
96
+ row_level_security_1.RowLevelSecurity.setContext("request_id", "abc");
97
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select original", ["value"], "all", transaction, loggerContext);
98
+ });
99
+ expect(result).toBe("query-result");
100
+ expect(executeSpy).toHaveBeenNthCalledWith(1, "SET LOCAL ROLE app_authenticated;\nSELECT set_config('app.tenant_id', '42', true),set_config('app.request_id', 'abc', true);", [], "run", transaction, loggerContext);
101
+ expect(executeSpy).toHaveBeenNthCalledWith(2, "select original", ["value"], "all", transaction, loggerContext);
102
+ });
103
+ it("opens a short transaction when executing a query outside an existing transaction", async () => {
104
+ const transaction = {};
105
+ const executeSpy = mockPostgreSqlExecute("query-result");
106
+ const transactional = jest.fn(async (cb) => {
107
+ return await cb(transaction);
108
+ });
109
+ const connection = createConnection({ transactional });
110
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
111
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
112
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 7);
113
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, "select original", [], "all");
114
+ });
115
+ expect(result).toBe("query-result");
116
+ expect(transactional).toHaveBeenCalledTimes(1);
117
+ expect(executeSpy).toHaveBeenNthCalledWith(1, "SET LOCAL ROLE authenticated;\nSELECT set_config('app.tenant_id', '7', true);", [], "run", transaction, undefined);
118
+ expect(executeSpy).toHaveBeenNthCalledWith(2, "select original", [], "all", transaction, undefined);
119
+ });
120
+ it("reuses the transaction from a transacting Knex query builder", async () => {
121
+ const queryBuilder = {
122
+ client: {
123
+ transacting: true,
124
+ },
125
+ };
126
+ const executeSpy = mockPostgreSqlExecute("query-result");
127
+ const transactional = jest.fn();
128
+ const connection = createConnection({ transactional });
129
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
130
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
131
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, queryBuilder, [], "all");
132
+ });
133
+ expect(result).toBe("query-result");
134
+ expect(transactional).not.toHaveBeenCalled();
135
+ expect(executeSpy).toHaveBeenNthCalledWith(1, "SET LOCAL ROLE authenticated;", [], "run", queryBuilder, undefined);
136
+ expect(executeSpy).toHaveBeenNthCalledWith(2, queryBuilder, [], "all", queryBuilder, undefined);
137
+ });
138
+ it("tracks row level security state on the shared transaction client for Knex query builders", async () => {
139
+ const transactionClient = {
140
+ transacting: true,
141
+ };
142
+ const scopedQueryBuilder = {
143
+ client: transactionClient,
144
+ };
145
+ const unscopedQueryBuilder = {
146
+ client: transactionClient,
147
+ };
148
+ const executeSpy = mockPostgreSqlExecute("query-result");
149
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
150
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
151
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 7);
152
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), scopedQueryBuilder, [], "all");
153
+ });
154
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), unscopedQueryBuilder, [], "all");
155
+ expect(executeSpy).toHaveBeenNthCalledWith(3, "SET LOCAL ROLE NONE;\nSELECT set_config('app.tenant_id', '', true);", [], "run", unscopedQueryBuilder, undefined);
156
+ });
157
+ it("opens a short transaction for a Knex query builder without a transaction", async () => {
158
+ const queryBuilder = {
159
+ client: {
160
+ transacting: false,
161
+ },
162
+ };
163
+ const transaction = {};
164
+ const executeSpy = mockPostgreSqlExecute("query-result");
165
+ const transactional = jest.fn(async (cb) => {
166
+ return await cb(transaction);
167
+ });
168
+ const connection = createConnection({ transactional });
169
+ const result = await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
170
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
171
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(connection, queryBuilder, [], "all");
172
+ });
173
+ expect(result).toBe("query-result");
174
+ expect(transactional).toHaveBeenCalledTimes(1);
175
+ expect(executeSpy).toHaveBeenNthCalledWith(1, "SET LOCAL ROLE authenticated;", [], "run", transaction, undefined);
176
+ expect(executeSpy).toHaveBeenNthCalledWith(2, queryBuilder, [], "all", transaction, undefined);
177
+ });
178
+ it("reuses row level security setup on the same transaction until the context changes", async () => {
179
+ const transaction = {};
180
+ const executeSpy = mockPostgreSqlExecute("query-result");
181
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
182
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
183
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 1);
184
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select one", [], "all", transaction);
185
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select two", [], "all", transaction);
186
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 2);
187
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select three", [], "all", transaction);
188
+ });
189
+ const rlsQueries = executeSpy.mock.calls.filter(([query]) => typeof query === "string" && query.startsWith("SET LOCAL ROLE"));
190
+ expect(rlsQueries).toHaveLength(2);
191
+ expect(rlsQueries[0]?.[0]).toBe("SET LOCAL ROLE authenticated;\nSELECT set_config('app.tenant_id', '1', true);");
192
+ expect(rlsQueries[1]?.[0]).toBe("SET LOCAL ROLE authenticated;\nSELECT set_config('app.tenant_id', '2', true);");
193
+ });
194
+ it("clears removed context keys before reusing a transaction", async () => {
195
+ const transaction = {};
196
+ const executeSpy = mockPostgreSqlExecute("query-result");
197
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
198
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
199
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 1);
200
+ row_level_security_1.RowLevelSecurity.setContext("request_id", "abc");
201
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select one", [], "all", transaction);
202
+ row_level_security_1.RowLevelSecurity.clear();
203
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
204
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 2);
205
+ await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select two", [], "all", transaction);
206
+ });
207
+ const setupQueries = executeSpy.mock.calls
208
+ .map(([query]) => query)
209
+ .filter((query) => typeof query === "string" && query.startsWith("SET LOCAL"));
210
+ expect(setupQueries).toEqual([
211
+ "SET LOCAL ROLE authenticated;\nSELECT set_config('app.tenant_id', '1', true),set_config('app.request_id', 'abc', true);",
212
+ "SET LOCAL ROLE authenticated;\nSELECT set_config('app.tenant_id', '2', true);\nSELECT set_config('app.request_id', '', true);",
213
+ ]);
214
+ });
215
+ it("serializes setup and query execution on the same transaction", async () => {
216
+ const transaction = {};
217
+ const executionOrder = [];
218
+ let activeTenantId;
219
+ jest
220
+ .spyOn(postgresql_1.PostgreSqlConnection.prototype, "execute")
221
+ .mockImplementation(async (queryOrKnex) => {
222
+ if (typeof queryOrKnex === "string") {
223
+ if (queryOrKnex.startsWith("SET LOCAL ROLE")) {
224
+ activeTenantId = queryOrKnex.includes("'1'") ? 1 : 2;
225
+ executionOrder.push(`setup:${String(activeTenantId)}`);
226
+ return undefined;
227
+ }
228
+ executionOrder.push(`${queryOrKnex}:${String(activeTenantId)}`);
229
+ return activeTenantId;
230
+ }
231
+ return undefined;
232
+ });
233
+ const firstQuery = request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
234
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
235
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 1);
236
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select one", [], "get", transaction);
237
+ });
238
+ const secondQuery = request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "test" }), async () => {
239
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
240
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", 2);
241
+ return await row_level_security_driver_1.RowLevelSecurityConnection.prototype.execute.call(createConnection(), "select two", [], "get", transaction);
242
+ });
243
+ await expect(Promise.all([firstQuery, secondQuery])).resolves.toEqual([
244
+ 1, 2,
245
+ ]);
246
+ expect(executionOrder).toEqual([
247
+ "setup:1",
248
+ "select one:1",
249
+ "setup:2",
250
+ "select two:2",
251
+ ]);
252
+ });
253
+ });
254
+ function mockPostgreSqlExecute(result) {
255
+ return jest
256
+ .spyOn(postgresql_1.PostgreSqlConnection.prototype, "execute")
257
+ .mockImplementation(async (queryOrKnex) => {
258
+ return typeof queryOrKnex === "string" &&
259
+ queryOrKnex.startsWith("SET LOCAL ROLE")
260
+ ? undefined
261
+ : result;
262
+ });
263
+ }
264
+ function createConnection(overrides = {}) {
265
+ return Object.assign(Object.create(row_level_security_driver_1.RowLevelSecurityConnection.prototype), overrides);
266
+ }
267
+ //# sourceMappingURL=row-level-security-driver.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security-driver.spec.js","sourceRoot":"","sources":["../src/row-level-security-driver.spec.ts"],"names":[],"mappings":"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"}