@nest-boot/row-level-security 7.1.0 → 7.2.1

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 (84) 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 +4 -2
  5. package/dist/index.js +4 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.spec.js +7 -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 +4 -0
  20. package/dist/row-level-security-migration-generator.js +54 -9
  21. package/dist/row-level-security-migration-generator.js.map +1 -1
  22. package/dist/row-level-security-migration-generator.spec.js +355 -12
  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-migrator.d.ts +13 -0
  30. package/dist/row-level-security-migrator.js +60 -0
  31. package/dist/row-level-security-migrator.js.map +1 -0
  32. package/dist/row-level-security.d.ts +29 -0
  33. package/dist/row-level-security.js +69 -0
  34. package/dist/row-level-security.js.map +1 -0
  35. package/dist/row-level-security.spec.js +52 -0
  36. package/dist/row-level-security.spec.js.map +1 -0
  37. package/dist/tsconfig.build.tsbuildinfo +1 -1
  38. package/dist/utils/create-policy-bootstrap-sql-statements.d.ts +1 -1
  39. package/dist/utils/create-policy-bootstrap-sql-statements.js +1 -7
  40. package/dist/utils/create-policy-bootstrap-sql-statements.js.map +1 -1
  41. package/dist/utils/create-policy-privilege-down-sql-statements.d.ts +8 -0
  42. package/dist/utils/create-policy-privilege-down-sql-statements.js +93 -0
  43. package/dist/utils/create-policy-privilege-down-sql-statements.js.map +1 -0
  44. package/dist/utils/create-policy-role-sql-statements.d.ts +6 -0
  45. package/dist/utils/create-policy-role-sql-statements.js +48 -0
  46. package/dist/utils/create-policy-role-sql-statements.js.map +1 -0
  47. package/dist/utils/create-policy-up-sql-statements.js +8 -2
  48. package/dist/utils/create-policy-up-sql-statements.js.map +1 -1
  49. package/dist/utils/create-row-level-security-transaction-setup.d.ts +20 -0
  50. package/dist/utils/create-row-level-security-transaction-setup.js +53 -0
  51. package/dist/utils/create-row-level-security-transaction-setup.js.map +1 -0
  52. package/dist/utils/index.d.ts +2 -3
  53. package/dist/utils/index.js +2 -3
  54. package/dist/utils/index.js.map +1 -1
  55. package/dist/utils/policy-migration-sql.spec.js +125 -7
  56. package/dist/utils/policy-migration-sql.spec.js.map +1 -1
  57. package/package.json +4 -4
  58. package/dist/interfaces/row-level-security-options.interface.d.ts +0 -18
  59. package/dist/interfaces/row-level-security-options.interface.js +0 -3
  60. package/dist/interfaces/row-level-security-options.interface.js.map +0 -1
  61. package/dist/row-level-security-context.d.ts +0 -14
  62. package/dist/row-level-security-context.js +0 -38
  63. package/dist/row-level-security-context.js.map +0 -1
  64. package/dist/row-level-security-context.spec.js +0 -29
  65. package/dist/row-level-security-context.spec.js.map +0 -1
  66. package/dist/row-level-security-entity-manager.d.ts +0 -22
  67. package/dist/row-level-security-entity-manager.js +0 -135
  68. package/dist/row-level-security-entity-manager.js.map +0 -1
  69. package/dist/row-level-security-entity-manager.spec.js +0 -200
  70. package/dist/row-level-security-entity-manager.spec.js.map +0 -1
  71. package/dist/utils/default-row-level-security-options.d.ts +0 -3
  72. package/dist/utils/default-row-level-security-options.js +0 -9
  73. package/dist/utils/default-row-level-security-options.js.map +0 -1
  74. package/dist/utils/get-row-level-security-options.d.ts +0 -8
  75. package/dist/utils/get-row-level-security-options.js +0 -9
  76. package/dist/utils/get-row-level-security-options.js.map +0 -1
  77. package/dist/utils/row-level-security-options-state.d.ts +0 -4
  78. package/dist/utils/row-level-security-options-state.js +0 -8
  79. package/dist/utils/row-level-security-options-state.js.map +0 -1
  80. package/dist/utils/set-row-level-security-options.d.ts +0 -3
  81. package/dist/utils/set-row-level-security-options.js +0 -13
  82. package/dist/utils/set-row-level-security-options.js.map +0 -1
  83. /package/dist/{row-level-security-context.spec.d.ts → row-level-security-driver.spec.d.ts} +0 -0
  84. /package/dist/{row-level-security-entity-manager.spec.d.ts → row-level-security.spec.d.ts} +0 -0
@@ -12,11 +12,6 @@ class TestRowLevelSecurityMigration extends row_level_security_migration_1.RowLe
12
12
  command: policy_command_enum_1.PolicyCommand.SELECT,
13
13
  using: `((select app.get_context('user_id', null::bigint)) = "user_id")`,
14
14
  });
15
- this.addDropPolicySql({
16
- schemaName: "public",
17
- tableName: "workspace_member",
18
- policyName: "workspace_member_user_select_policy",
19
- });
20
15
  }
21
16
  }
22
17
  describe("RowLevelSecurityMigration", () => {
@@ -24,17 +19,13 @@ describe("RowLevelSecurityMigration", () => {
24
19
  const migration = new TestRowLevelSecurityMigration({}, {});
25
20
  migration.up();
26
21
  const queries = migration.getQueries();
27
- expect(migration.getQueries()).toHaveLength(12);
28
- expect(queries[0]).toContain("create role authenticated nologin");
29
- expect(queries[1]).toContain("create role anonymous nologin");
30
- expect(queries[2]).toContain("grant authenticated to current_user");
31
- expect(queries[3]).toContain("grant anonymous to current_user");
32
- expect(queries[4]).toContain("create schema if not exists app");
33
- expect(queries[7]).toContain("create or replace function app.get_context");
34
- expect(queries[8]).toContain('alter table "public"."workspace_member" enable row level security;');
35
- expect(queries[9]).toContain('drop policy if exists workspace_member_user_select_policy on "public"."workspace_member";');
36
- expect(queries[10]).toContain("create policy workspace_member_user_select_policy");
37
- expect(queries[11]).toContain("drop policy if exists workspace_member_user_select_policy");
22
+ expect(queries).toContainEqual(expect.stringContaining("create role anonymous nologin"));
23
+ expect(queries).toContainEqual(expect.stringContaining("grant anonymous to current_user"));
24
+ expect(queries).toContainEqual(expect.stringContaining("create schema if not exists app"));
25
+ expect(queries).toContainEqual(expect.stringContaining("create or replace function app.get_context"));
26
+ expect(queries).toContainEqual('alter table "public"."workspace_member" enable row level security;');
27
+ expect(queries).toContainEqual('drop policy if exists workspace_member_user_select_policy on "public"."workspace_member";');
28
+ expect(queries).toContainEqual(expect.stringContaining("create policy workspace_member_user_select_policy"));
38
29
  });
39
30
  });
40
31
  //# sourceMappingURL=row-level-security-migration.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"row-level-security-migration.spec.js","sourceRoot":"","sources":["../src/row-level-security-migration.spec.ts"],"names":[],"mappings":";;AAAA,qEAA4D;AAC5D,iFAA2E;AAE3E,MAAM,6BAA8B,SAAQ,wDAAyB;IAC1D,EAAE;QACT,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACvC,IAAI,CAAC,YAAY,CAAC;YAChB,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,kBAAkB;YAC7B,UAAU,EAAE,qCAAqC;YACjD,OAAO,EAAE,mCAAa,CAAC,MAAM;YAC7B,KAAK,EAAE,iEAAiE;SACzE,CAAC,CAAC;QACH,IAAI,CAAC,gBAAgB,CAAC;YACpB,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,kBAAkB;YAC7B,UAAU,EAAE,qCAAqC;SAClD,CAAC,CAAC;IACL,CAAC;CACF;AAED,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,SAAS,GAAG,IAAI,6BAA6B,CACjD,EAAW,EACX,EAAW,CACZ,CAAC;QAEF,SAAS,CAAC,EAAE,EAAE,CAAC;QAEf,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAc,CAAC;QAEnD,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAC9D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,4CAA4C,CAAC,CAAC;QAC3E,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAC1B,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAC1B,2FAA2F,CAC5F,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAC3B,mDAAmD,CACpD,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAC3B,2DAA2D,CAC5D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"row-level-security-migration.spec.js","sourceRoot":"","sources":["../src/row-level-security-migration.spec.ts"],"names":[],"mappings":";;AAAA,qEAA4D;AAC5D,iFAA2E;AAE3E,MAAM,6BAA8B,SAAQ,wDAAyB;IAC1D,EAAE;QACT,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACvC,IAAI,CAAC,YAAY,CAAC;YAChB,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,kBAAkB;YAC7B,UAAU,EAAE,qCAAqC;YACjD,OAAO,EAAE,mCAAa,CAAC,MAAM;YAC7B,KAAK,EAAE,iEAAiE;SACzE,CAAC,CAAC;IACL,CAAC;CACF;AAED,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,SAAS,GAAG,IAAI,6BAA6B,CACjD,EAAW,EACX,EAAW,CACZ,CAAC;QAEF,SAAS,CAAC,EAAE,EAAE,CAAC;QAEf,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,EAAc,CAAC;QAEnD,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,MAAM,CAAC,gBAAgB,CAAC,+BAA+B,CAAC,CACzD,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,MAAM,CAAC,gBAAgB,CAAC,iCAAiC,CAAC,CAC3D,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,MAAM,CAAC,gBAAgB,CAAC,iCAAiC,CAAC,CAC3D,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,MAAM,CAAC,gBAAgB,CAAC,4CAA4C,CAAC,CACtE,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,2FAA2F,CAC5F,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAC5B,MAAM,CAAC,gBAAgB,CACrB,mDAAmD,CACpD,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { MigrationResult, MikroORM } from "@mikro-orm/core";
2
+ import { Migrator } from "@mikro-orm/migrations";
3
+ /** MikroORM migrator that also creates migrations for policy-only RLS changes. */
4
+ export declare class RowLevelSecurityMigrator extends Migrator {
5
+ /** Registers the RLS-aware migrator extension with a MikroORM instance. */
6
+ static register(orm: MikroORM): void;
7
+ createMigration(path?: string, blank?: boolean, initial?: boolean, name?: string): Promise<MigrationResult>;
8
+ /** Checks whether schema or RLS policy changes require a new migration. */
9
+ checkMigrationNeeded(): Promise<boolean>;
10
+ private hasPendingPolicyChanges;
11
+ private getRowLevelSecurityGenerator;
12
+ private getInternals;
13
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowLevelSecurityMigrator = void 0;
4
+ const migrations_1 = require("@mikro-orm/migrations");
5
+ const row_level_security_migration_generator_1 = require("./row-level-security-migration-generator");
6
+ /** MikroORM migrator that also creates migrations for policy-only RLS changes. */
7
+ class RowLevelSecurityMigrator extends migrations_1.Migrator {
8
+ /** Registers the RLS-aware migrator extension with a MikroORM instance. */
9
+ static register(orm) {
10
+ orm.config.registerExtension("@mikro-orm/migrator", () => new RowLevelSecurityMigrator(orm.em));
11
+ }
12
+ async createMigration(path, blank = false, initial = false, name) {
13
+ if (initial) {
14
+ return await super.createMigration(path, blank, initial, name);
15
+ }
16
+ const internals = this.getInternals();
17
+ await internals.ensureMigrationsDirExists();
18
+ const diff = await internals.getSchemaDiff(blank, initial);
19
+ if (diff.up.length === 0) {
20
+ const hasPolicyChanges = await this.hasPendingPolicyChanges(diff);
21
+ if (!hasPolicyChanges) {
22
+ return { fileName: "", code: "", diff };
23
+ }
24
+ }
25
+ const migration = await internals.generator.generate(diff, path, name);
26
+ await internals.storeCurrentSchema();
27
+ return {
28
+ fileName: migration[1],
29
+ code: migration[0],
30
+ diff,
31
+ };
32
+ }
33
+ /** Checks whether schema or RLS policy changes require a new migration. */
34
+ async checkMigrationNeeded() {
35
+ const internals = this.getInternals();
36
+ await internals.ensureMigrationsDirExists();
37
+ const diff = await internals.getSchemaDiff(false, false);
38
+ if (diff.up.length > 0) {
39
+ return true;
40
+ }
41
+ return await this.hasPendingPolicyChanges(diff);
42
+ }
43
+ async hasPendingPolicyChanges(diff) {
44
+ const generator = this.getRowLevelSecurityGenerator();
45
+ // TODO: Support MikroORM snapshot mode by comparing generated policy state
46
+ // instead of only live database policies.
47
+ return generator ? await generator.hasPendingPolicyChanges(diff) : false;
48
+ }
49
+ getRowLevelSecurityGenerator() {
50
+ const generator = this.getInternals().generator;
51
+ return generator instanceof row_level_security_migration_generator_1.RowLevelSecurityMigrationGenerator
52
+ ? generator
53
+ : undefined;
54
+ }
55
+ getInternals() {
56
+ return this;
57
+ }
58
+ }
59
+ exports.RowLevelSecurityMigrator = RowLevelSecurityMigrator;
60
+ //# sourceMappingURL=row-level-security-migrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security-migrator.js","sourceRoot":"","sources":["../src/row-level-security-migrator.ts"],"names":[],"mappings":";;;AACA,sDAAiD;AAEjD,qGAA8F;AAiB9F,kFAAkF;AAClF,MAAa,wBAAyB,SAAQ,qBAAQ;IACpD,2EAA2E;IAC3E,MAAM,CAAU,QAAQ,CAAC,GAAa;QACpC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAC1B,qBAAqB,EACrB,GAAG,EAAE,CAAC,IAAI,wBAAwB,CAAC,GAAG,CAAC,EAAW,CAAC,CACpD,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,eAAe,CAC5B,IAAa,EACb,KAAK,GAAG,KAAK,EACb,OAAO,GAAG,KAAK,EACf,IAAa;QAEb,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,MAAM,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAEtC,MAAM,SAAS,CAAC,yBAAyB,EAAE,CAAC;QAE5C,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAE3D,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;YAElE,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAEvE,MAAM,SAAS,CAAC,kBAAkB,EAAE,CAAC;QAErC,OAAO;YACL,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;YACtB,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;YAClB,IAAI;SACL,CAAC;IACJ,CAAC;IAED,2EAA2E;IAClE,KAAK,CAAC,oBAAoB;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAEtC,MAAM,SAAS,CAAC,yBAAyB,EAAE,CAAC;QAE5C,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAEzD,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,IAAmB;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,4BAA4B,EAAE,CAAC;QAEtD,2EAA2E;QAC3E,0CAA0C;QAC1C,OAAO,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,CAAC;IAEO,4BAA4B;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,SAAS,CAAC;QAEhD,OAAO,SAAS,YAAY,2EAAkC;YAC5D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAEO,YAAY;QAClB,OAAO,IAAoC,CAAC;IAC9C,CAAC;CACF;AA9ED,4DA8EC"}
@@ -0,0 +1,29 @@
1
+ import { RowLevelSecurityContextValue, SnakeCase } from "./utils/row-level-security-context-builder.types";
2
+ /** Request-scoped row-level security execution mode. */
3
+ export declare enum RowLevelSecurityMode {
4
+ /** Apply RLS only when a role or context value is present. */
5
+ AUTO = "auto",
6
+ /** Always apply RLS while request context is active. */
7
+ ENABLED = "enabled",
8
+ /** Never apply RLS, even when role or context values are present. */
9
+ DISABLED = "disabled"
10
+ }
11
+ /** Request-scoped row-level security mode, role, and context helpers. */
12
+ export declare class RowLevelSecurity {
13
+ /** Stores the row-level security mode for the current request context. */
14
+ static setMode(mode: RowLevelSecurityMode): void;
15
+ /** Reads the request-scoped row-level security mode. */
16
+ static getMode(): RowLevelSecurityMode;
17
+ /** Stores the database role that should be applied to the next RLS query. */
18
+ static setRole(role: string): void;
19
+ /** Reads the request-scoped database role, if one is active. */
20
+ static getRole(): string | undefined;
21
+ /** Stores a context value that will be converted to a PostgreSQL setting. */
22
+ static setContext<S extends string>(key: SnakeCase<S>, value: RowLevelSecurityContextValue): void;
23
+ /** Reads a request-scoped context value by key. */
24
+ static getContext<S extends string>(key: SnakeCase<S>): RowLevelSecurityContextValue;
25
+ /** Returns all request-scoped context entries for RLS transaction setup. */
26
+ static entries(): [string, RowLevelSecurityContextValue][];
27
+ /** Clears request-scoped RLS mode, role, and context values. */
28
+ static clear(): void;
29
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowLevelSecurity = exports.RowLevelSecurityMode = void 0;
4
+ const request_context_1 = require("@nest-boot/request-context");
5
+ const ROW_LEVEL_SECURITY_CONTEXT = Symbol("ROW_LEVEL_SECURITY_CONTEXT");
6
+ const ROW_LEVEL_SECURITY_MODE = Symbol("ROW_LEVEL_SECURITY_MODE");
7
+ const ROW_LEVEL_SECURITY_ROLE = Symbol("ROW_LEVEL_SECURITY_ROLE");
8
+ /** Request-scoped row-level security execution mode. */
9
+ var RowLevelSecurityMode;
10
+ (function (RowLevelSecurityMode) {
11
+ /** Apply RLS only when a role or context value is present. */
12
+ RowLevelSecurityMode["AUTO"] = "auto";
13
+ /** Always apply RLS while request context is active. */
14
+ RowLevelSecurityMode["ENABLED"] = "enabled";
15
+ /** Never apply RLS, even when role or context values are present. */
16
+ RowLevelSecurityMode["DISABLED"] = "disabled";
17
+ })(RowLevelSecurityMode || (exports.RowLevelSecurityMode = RowLevelSecurityMode = {}));
18
+ /** Request-scoped row-level security mode, role, and context helpers. */
19
+ class RowLevelSecurity {
20
+ /** Stores the row-level security mode for the current request context. */
21
+ static setMode(mode) {
22
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_MODE, mode);
23
+ }
24
+ /** Reads the request-scoped row-level security mode. */
25
+ static getMode() {
26
+ return request_context_1.RequestContext.isActive()
27
+ ? (request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_MODE) ??
28
+ RowLevelSecurityMode.AUTO)
29
+ : RowLevelSecurityMode.AUTO;
30
+ }
31
+ /** Stores the database role that should be applied to the next RLS query. */
32
+ static setRole(role) {
33
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_ROLE, role);
34
+ }
35
+ /** Reads the request-scoped database role, if one is active. */
36
+ static getRole() {
37
+ return request_context_1.RequestContext.isActive()
38
+ ? request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_ROLE)
39
+ : undefined;
40
+ }
41
+ /** Stores a context value that will be converted to a PostgreSQL setting. */
42
+ static setContext(key, value) {
43
+ const context = request_context_1.RequestContext.getOrSet(ROW_LEVEL_SECURITY_CONTEXT, new Map());
44
+ context.set(key, value);
45
+ }
46
+ /** Reads a request-scoped context value by key. */
47
+ static getContext(key) {
48
+ return request_context_1.RequestContext.isActive()
49
+ ? request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_CONTEXT)?.get(key)
50
+ : undefined;
51
+ }
52
+ /** Returns all request-scoped context entries for RLS transaction setup. */
53
+ static entries() {
54
+ return request_context_1.RequestContext.isActive()
55
+ ? Array.from(request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_CONTEXT) ?? [])
56
+ : [];
57
+ }
58
+ /** Clears request-scoped RLS mode, role, and context values. */
59
+ static clear() {
60
+ if (!request_context_1.RequestContext.isActive()) {
61
+ return;
62
+ }
63
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_MODE, RowLevelSecurityMode.AUTO);
64
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_ROLE, undefined);
65
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_CONTEXT, new Map());
66
+ }
67
+ }
68
+ exports.RowLevelSecurity = RowLevelSecurity;
69
+ //# sourceMappingURL=row-level-security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security.js","sourceRoot":"","sources":["../src/row-level-security.ts"],"names":[],"mappings":";;;AAAA,gEAA4D;AAS5D,MAAM,0BAA0B,GAAG,MAAM,CAAC,4BAA4B,CAAC,CAAC;AACxE,MAAM,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAClE,MAAM,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAElE,wDAAwD;AACxD,IAAY,oBAOX;AAPD,WAAY,oBAAoB;IAC9B,8DAA8D;IAC9D,qCAAa,CAAA;IACb,wDAAwD;IACxD,2CAAmB,CAAA;IACnB,qEAAqE;IACrE,6CAAqB,CAAA;AACvB,CAAC,EAPW,oBAAoB,oCAApB,oBAAoB,QAO/B;AAED,yEAAyE;AACzE,MAAa,gBAAgB;IAC3B,0EAA0E;IAC1E,MAAM,CAAC,OAAO,CAAC,IAA0B;QACvC,gCAAc,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,wDAAwD;IACxD,MAAM,CAAC,OAAO;QACZ,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,CAAC,gCAAc,CAAC,GAAG,CAAuB,uBAAuB,CAAC;gBAChE,oBAAoB,CAAC,IAAI,CAAC;YAC9B,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC;IAChC,CAAC;IAED,6EAA6E;IAC7E,MAAM,CAAC,OAAO,CAAC,IAAY;QACzB,gCAAc,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,OAAO;QACZ,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,gCAAc,CAAC,GAAG,CAAS,uBAAuB,CAAC;YACrD,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,6EAA6E;IAC7E,MAAM,CAAC,UAAU,CACf,GAAiB,EACjB,KAAmC;QAEnC,MAAM,OAAO,GAAG,gCAAc,CAAC,QAAQ,CACrC,0BAA0B,EAC1B,IAAI,GAAG,EAAE,CACV,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,mDAAmD;IACnD,MAAM,CAAC,UAAU,CACf,GAAiB;QAEjB,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,gCAAc,CAAC,GAAG,CAChB,0BAA0B,CAC3B,EAAE,GAAG,CAAC,GAAG,CAAC;YACb,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,OAAO;QACZ,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,KAAK,CAAC,IAAI,CACR,gCAAc,CAAC,GAAG,CAChB,0BAA0B,CAC3B,IAAI,EAAE,CACR;YACH,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,KAAK;QACV,IAAI,CAAC,gCAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,gCAAc,CAAC,GAAG,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACvE,gCAAc,CAAC,GAAG,CAAqB,uBAAuB,EAAE,SAAS,CAAC,CAAC;QAC3E,gCAAc,CAAC,GAAG,CAChB,0BAA0B,EAC1B,IAAI,GAAG,EAAE,CACV,CAAC;IACJ,CAAC;CACF;AA1ED,4CA0EC"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const request_context_1 = require("@nest-boot/request-context");
4
+ const row_level_security_1 = require("./row-level-security");
5
+ describe("RowLevelSecurity", () => {
6
+ it("stores the database role in RequestContext", async () => {
7
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
8
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
9
+ expect(row_level_security_1.RowLevelSecurity.getRole()).toBe("authenticated");
10
+ });
11
+ });
12
+ it("stores policy context values in RequestContext", async () => {
13
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
14
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", "42");
15
+ row_level_security_1.RowLevelSecurity.setContext("user_id", 7);
16
+ expect(row_level_security_1.RowLevelSecurity.getContext("tenant_id")).toBe("42");
17
+ expect(row_level_security_1.RowLevelSecurity.entries()).toEqual([
18
+ ["tenant_id", "42"],
19
+ ["user_id", 7],
20
+ ]);
21
+ });
22
+ });
23
+ it("defaults to auto mode and stores mode in RequestContext", async () => {
24
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
25
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
26
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
27
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.DISABLED);
28
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.DISABLED);
29
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.ENABLED);
30
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.ENABLED);
31
+ });
32
+ });
33
+ it("clears mode, role, and context values", async () => {
34
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
35
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.ENABLED);
36
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
37
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", "42");
38
+ row_level_security_1.RowLevelSecurity.clear();
39
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
40
+ expect(row_level_security_1.RowLevelSecurity.getRole()).toBeUndefined();
41
+ expect(row_level_security_1.RowLevelSecurity.getContext("tenant_id")).toBeUndefined();
42
+ expect(row_level_security_1.RowLevelSecurity.entries()).toEqual([]);
43
+ });
44
+ });
45
+ it("returns empty values when RequestContext is inactive", () => {
46
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
47
+ expect(row_level_security_1.RowLevelSecurity.getRole()).toBeUndefined();
48
+ expect(row_level_security_1.RowLevelSecurity.getContext("tenant_id")).toBeUndefined();
49
+ expect(row_level_security_1.RowLevelSecurity.entries()).toEqual([]);
50
+ });
51
+ });
52
+ //# sourceMappingURL=row-level-security.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security.spec.js","sourceRoot":"","sources":["../src/row-level-security.spec.ts"],"names":[],"mappings":"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"}