@rhino-dev/rhino-nestjs 4.2.0 → 4.3.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.
- package/dist/blueprint/blueprint-runner.js +32 -1
- package/dist/blueprint/blueprint-runner.js.map +1 -1
- package/dist/blueprint/blueprint-sorter.d.ts +54 -0
- package/dist/blueprint/blueprint-sorter.js +107 -0
- package/dist/blueprint/blueprint-sorter.js.map +1 -0
- package/dist/cli/commands/permissions-migrate.command.d.ts +13 -0
- package/dist/cli/commands/permissions-migrate.command.js +51 -0
- package/dist/cli/commands/permissions-migrate.command.js.map +1 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/permissions-migrator.d.ts +28 -0
- package/dist/cli/permissions-migrator.js +75 -0
- package/dist/cli/permissions-migrator.js.map +1 -0
- package/dist/guards/group-membership.guard.js +4 -1
- package/dist/guards/group-membership.guard.js.map +1 -1
- package/dist/guards/jwt-auth.guard.js +16 -1
- package/dist/guards/jwt-auth.guard.js.map +1 -1
- package/dist/services/membership.service.d.ts +9 -1
- package/dist/services/membership.service.js +17 -2
- package/dist/services/membership.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/permission-matcher.d.ts +16 -4
- package/dist/utils/permission-matcher.js +106 -15
- package/dist/utils/permission-matcher.js.map +1 -1
- package/package.json +1 -1
|
@@ -39,6 +39,7 @@ const fs = __importStar(require("fs"));
|
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
40
|
const blueprint_parser_1 = require("./blueprint-parser");
|
|
41
41
|
const blueprint_validator_1 = require("./blueprint-validator");
|
|
42
|
+
const blueprint_sorter_1 = require("./blueprint-sorter");
|
|
42
43
|
const manifest_manager_1 = require("./manifest-manager");
|
|
43
44
|
const prisma_schema_generator_1 = require("./generators/prisma-schema-generator");
|
|
44
45
|
const resource_definition_generator_1 = require("./generators/resource-definition-generator");
|
|
@@ -95,7 +96,37 @@ class BlueprintRunner {
|
|
|
95
96
|
return result;
|
|
96
97
|
}
|
|
97
98
|
const manifest = new manifest_manager_1.ManifestManager(manifestDir);
|
|
98
|
-
|
|
99
|
+
// Order so a referenced model is processed before any model that
|
|
100
|
+
// foreign-keys to it (parents before children) — keeps order-sensitive
|
|
101
|
+
// output (e.g. seeders) runnable and matches the Laravel/Rails stacks, where
|
|
102
|
+
// migration timestamps follow this order.
|
|
103
|
+
const sorter = new blueprint_sorter_1.BlueprintSorter();
|
|
104
|
+
const parsedForOrder = [];
|
|
105
|
+
const unparseable = [];
|
|
106
|
+
for (const f of yamlFiles) {
|
|
107
|
+
try {
|
|
108
|
+
parsedForOrder.push({ file: f, blueprint: this.parser.parseModel(path.join(blueprintsDir, f)) });
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
unparseable.push(f);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const orderedBlueprints = sorter.sort(parsedForOrder.map((p) => p.blueprint));
|
|
115
|
+
const fileByModel = new Map();
|
|
116
|
+
for (const p of parsedForOrder) {
|
|
117
|
+
if (!fileByModel.has(p.blueprint.model)) {
|
|
118
|
+
fileByModel.set(p.blueprint.model, p.file);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const orderedYamlFiles = [
|
|
122
|
+
...orderedBlueprints.map((bp) => fileByModel.get(bp.model)).filter(Boolean),
|
|
123
|
+
...unparseable,
|
|
124
|
+
];
|
|
125
|
+
if (sorter.cycles.length > 0) {
|
|
126
|
+
this.log(` ⚠ Circular foreign-key dependency among: ${sorter.cycles.join(', ')}. ` +
|
|
127
|
+
'Order is best-effort — make one side nullable or add the FK in a later step.', options);
|
|
128
|
+
}
|
|
129
|
+
for (const filename of orderedYamlFiles) {
|
|
99
130
|
const filePath = path.join(blueprintsDir, filename);
|
|
100
131
|
try {
|
|
101
132
|
// Parse
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-runner.js","sourceRoot":"","sources":["../../src/blueprint/blueprint-runner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"blueprint-runner.js","sourceRoot":"","sources":["../../src/blueprint/blueprint-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orders blueprints so that a referenced model is processed before any model
|
|
3
|
+
* whose foreign keys point at it (parents before children).
|
|
4
|
+
*
|
|
5
|
+
* Foreign keys are taken from `foreignId` columns that carry a `foreignModel`
|
|
6
|
+
* mapping to another model in the same generation set. References that impose no
|
|
7
|
+
* ordering are ignored:
|
|
8
|
+
* - self-references (a model's FK to its own table),
|
|
9
|
+
* - references to models NOT in this set (e.g. `Organization`/`User`, created
|
|
10
|
+
* by `rhino install`, not the blueprint run).
|
|
11
|
+
*
|
|
12
|
+
* Prisma resolves relations regardless of model declaration order, but the
|
|
13
|
+
* processing order still matters for order-sensitive output (notably seeders: a
|
|
14
|
+
* child row referencing a parent must be inserted after it) and for parity with
|
|
15
|
+
* the Laravel/Rails stacks, where migration timestamps follow this order.
|
|
16
|
+
*
|
|
17
|
+
* Uses Kahn's algorithm with a stable tie-break: among models with no remaining
|
|
18
|
+
* unmet dependency, the one earliest in the input order wins. The input is
|
|
19
|
+
* already alphabetical, so the output stays alphabetical wherever relationships
|
|
20
|
+
* don't force a reorder.
|
|
21
|
+
*
|
|
22
|
+
* A circular FK dependency (A → B → A) has no linear order; such models are
|
|
23
|
+
* emitted in a deterministic best-effort order and reported via {@link cycles}
|
|
24
|
+
* so the caller can warn (one side should be a nullable / deferred FK).
|
|
25
|
+
*/
|
|
26
|
+
export interface SortableColumn {
|
|
27
|
+
type?: string;
|
|
28
|
+
foreignModel?: string | null;
|
|
29
|
+
}
|
|
30
|
+
export interface SortableBlueprint {
|
|
31
|
+
model: string;
|
|
32
|
+
columns?: SortableColumn[];
|
|
33
|
+
}
|
|
34
|
+
export declare class BlueprintSorter {
|
|
35
|
+
private _cycles;
|
|
36
|
+
/**
|
|
37
|
+
* Model names involved in a circular foreign-key dependency during the last
|
|
38
|
+
* {@link sort} (empty when the dependency graph is acyclic).
|
|
39
|
+
*/
|
|
40
|
+
get cycles(): string[];
|
|
41
|
+
/** Re-order blueprints into a valid sequence (parents first). */
|
|
42
|
+
sort<T extends SortableBlueprint>(blueprints: T[]): T[];
|
|
43
|
+
/**
|
|
44
|
+
* Whether `start` can reach itself by following dependency edges — i.e. it
|
|
45
|
+
* participates in a circular foreign-key dependency. `adj` maps a model to the
|
|
46
|
+
* models that reference it (its dependents).
|
|
47
|
+
*/
|
|
48
|
+
private reachableFromSelf;
|
|
49
|
+
/**
|
|
50
|
+
* The model names this blueprint's foreign keys point at, taken from its
|
|
51
|
+
* `foreignId` columns that carry a `foreignModel`.
|
|
52
|
+
*/
|
|
53
|
+
private dependencyModels;
|
|
54
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlueprintSorter = void 0;
|
|
4
|
+
class BlueprintSorter {
|
|
5
|
+
_cycles = [];
|
|
6
|
+
/**
|
|
7
|
+
* Model names involved in a circular foreign-key dependency during the last
|
|
8
|
+
* {@link sort} (empty when the dependency graph is acyclic).
|
|
9
|
+
*/
|
|
10
|
+
get cycles() {
|
|
11
|
+
return this._cycles;
|
|
12
|
+
}
|
|
13
|
+
/** Re-order blueprints into a valid sequence (parents first). */
|
|
14
|
+
sort(blueprints) {
|
|
15
|
+
this._cycles = [];
|
|
16
|
+
if (blueprints.length < 2) {
|
|
17
|
+
return [...blueprints];
|
|
18
|
+
}
|
|
19
|
+
const byModel = new Map();
|
|
20
|
+
for (const bp of blueprints) {
|
|
21
|
+
if (bp.model && !byModel.has(bp.model)) {
|
|
22
|
+
byModel.set(bp.model, bp);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const dependents = new Map();
|
|
26
|
+
const indegree = new Map();
|
|
27
|
+
for (const m of byModel.keys()) {
|
|
28
|
+
dependents.set(m, []);
|
|
29
|
+
indegree.set(m, 0);
|
|
30
|
+
}
|
|
31
|
+
for (const [model, bp] of byModel) {
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
for (const ref of this.dependencyModels(bp)) {
|
|
34
|
+
if (ref === model || !byModel.has(ref) || seen.has(ref)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
seen.add(ref);
|
|
38
|
+
dependents.get(ref).push(model);
|
|
39
|
+
indegree.set(model, (indegree.get(model) ?? 0) + 1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const inputOrder = [...byModel.keys()];
|
|
43
|
+
// Record the models that actually participate in a cycle (reachable from
|
|
44
|
+
// themselves), in input order, so the caller can warn about the full cycle.
|
|
45
|
+
for (const model of inputOrder) {
|
|
46
|
+
if (this.reachableFromSelf(model, dependents)) {
|
|
47
|
+
this._cycles.push(model);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const ordered = [];
|
|
51
|
+
const resolved = new Set();
|
|
52
|
+
while (ordered.length < byModel.size) {
|
|
53
|
+
// Earliest-input model with all dependencies already emitted...
|
|
54
|
+
let pick = inputOrder.find((m) => !resolved.has(m) && indegree.get(m) === 0);
|
|
55
|
+
// ...or, when a cycle blocks the graph, the earliest unresolved model
|
|
56
|
+
// (deterministic cycle-break; the cycle itself is reported via cycles).
|
|
57
|
+
if (pick === undefined) {
|
|
58
|
+
pick = inputOrder.find((m) => !resolved.has(m));
|
|
59
|
+
}
|
|
60
|
+
const picked = pick;
|
|
61
|
+
ordered.push(byModel.get(picked));
|
|
62
|
+
resolved.add(picked);
|
|
63
|
+
for (const child of dependents.get(picked)) {
|
|
64
|
+
indegree.set(child, (indegree.get(child) ?? 0) - 1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return ordered;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Whether `start` can reach itself by following dependency edges — i.e. it
|
|
71
|
+
* participates in a circular foreign-key dependency. `adj` maps a model to the
|
|
72
|
+
* models that reference it (its dependents).
|
|
73
|
+
*/
|
|
74
|
+
reachableFromSelf(start, adj) {
|
|
75
|
+
const stack = [...(adj.get(start) ?? [])];
|
|
76
|
+
const visited = new Set();
|
|
77
|
+
while (stack.length > 0) {
|
|
78
|
+
const node = stack.pop();
|
|
79
|
+
if (node === start) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (visited.has(node)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
visited.add(node);
|
|
86
|
+
for (const next of adj.get(node) ?? []) {
|
|
87
|
+
stack.push(next);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The model names this blueprint's foreign keys point at, taken from its
|
|
94
|
+
* `foreignId` columns that carry a `foreignModel`.
|
|
95
|
+
*/
|
|
96
|
+
dependencyModels(bp) {
|
|
97
|
+
const refs = [];
|
|
98
|
+
for (const col of bp.columns ?? []) {
|
|
99
|
+
if (col.type === 'foreignId' && col.foreignModel) {
|
|
100
|
+
refs.push(col.foreignModel);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return refs;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.BlueprintSorter = BlueprintSorter;
|
|
107
|
+
//# sourceMappingURL=blueprint-sorter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-sorter.js","sourceRoot":"","sources":["../../src/blueprint/blueprint-sorter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npx rhino permissions-migrate [--apply]`
|
|
3
|
+
*
|
|
4
|
+
* Lifts per-user `userRoles.permissions` into the shared `orgRolePermission`
|
|
5
|
+
* role layer, reducing each user row to its delta. Dry-run unless `--apply`.
|
|
6
|
+
*
|
|
7
|
+
* Loads the consumer app's PrismaClient at runtime (the lib has no DB of its
|
|
8
|
+
* own). A custom client can be injected for testing.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runPermissionsMigrate(flags: Record<string, string | true>, deps?: {
|
|
11
|
+
loadPrisma?: () => any;
|
|
12
|
+
log?: (msg: string) => void;
|
|
13
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPermissionsMigrate = runPermissionsMigrate;
|
|
4
|
+
const permissions_migrator_1 = require("../permissions-migrator");
|
|
5
|
+
/**
|
|
6
|
+
* `npx rhino permissions-migrate [--apply]`
|
|
7
|
+
*
|
|
8
|
+
* Lifts per-user `userRoles.permissions` into the shared `orgRolePermission`
|
|
9
|
+
* role layer, reducing each user row to its delta. Dry-run unless `--apply`.
|
|
10
|
+
*
|
|
11
|
+
* Loads the consumer app's PrismaClient at runtime (the lib has no DB of its
|
|
12
|
+
* own). A custom client can be injected for testing.
|
|
13
|
+
*/
|
|
14
|
+
async function runPermissionsMigrate(flags, deps = {}) {
|
|
15
|
+
const apply = flags.apply === true || flags.apply === 'true';
|
|
16
|
+
const log = deps.log ?? ((m) => console.log(m));
|
|
17
|
+
let prisma;
|
|
18
|
+
try {
|
|
19
|
+
const load = deps.loadPrisma ??
|
|
20
|
+
(() => {
|
|
21
|
+
// Resolved from the consumer app's installed @prisma/client.
|
|
22
|
+
const { PrismaClient } = require('@prisma/client');
|
|
23
|
+
return new PrismaClient();
|
|
24
|
+
});
|
|
25
|
+
prisma = load();
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
log('Could not load @prisma/client. Run this from your application root where Prisma is installed.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const result = await (0, permissions_migrator_1.migratePermissions)(prisma, { apply });
|
|
33
|
+
for (const line of result.lines)
|
|
34
|
+
log(line);
|
|
35
|
+
const verb = apply ? 'Migrated' : 'Would migrate';
|
|
36
|
+
let summary = `${verb} ${result.groupsMigrated} (org, role) group(s); ${result.rowsReduced} user row(s) reduced to deltas.`;
|
|
37
|
+
if (result.skippedExisting > 0) {
|
|
38
|
+
summary += ` Skipped ${result.skippedExisting} group(s) with an existing role layer.`;
|
|
39
|
+
}
|
|
40
|
+
log(summary);
|
|
41
|
+
if (!apply && result.groupsMigrated > 0) {
|
|
42
|
+
log('Dry-run only. Re-run with --apply to write these changes.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
if (typeof prisma.$disconnect === 'function') {
|
|
47
|
+
await prisma.$disconnect().catch(() => undefined);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=permissions-migrate.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions-migrate.command.js","sourceRoot":"","sources":["../../../src/cli/commands/permissions-migrate.command.ts"],"names":[],"mappings":";;AAWA,sDAyCC;AApDD,kEAA6D;AAE7D;;;;;;;;GAQG;AACI,KAAK,UAAU,qBAAqB,CACzC,KAAoC,EACpC,OAAgE,EAAE;IAElE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAExD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,IAAI,GACR,IAAI,CAAC,UAAU;YACf,CAAC,GAAG,EAAE;gBACJ,6DAA6D;gBAC7D,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;gBACnD,OAAO,IAAI,YAAY,EAAE,CAAC;YAC5B,CAAC,CAAC,CAAC;QACL,MAAM,GAAG,IAAI,EAAE,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,+FAA+F,CAAC,CAAC;QACrG,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,yCAAkB,EAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAE3C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC;QAClD,IAAI,OAAO,GAAG,GAAG,IAAI,IAAI,MAAM,CAAC,cAAc,0BAA0B,MAAM,CAAC,WAAW,iCAAiC,CAAC;QAC5H,IAAI,MAAM,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,YAAY,MAAM,CAAC,eAAe,wCAAwC,CAAC;QACxF,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,CAAC;QAEb,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;YACxC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YAC7C,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -20,6 +20,7 @@ const generate_command_1 = require("./commands/generate.command");
|
|
|
20
20
|
const blueprint_command_1 = require("./commands/blueprint.command");
|
|
21
21
|
const export_postman_command_1 = require("./commands/export-postman.command");
|
|
22
22
|
const export_types_command_1 = require("./commands/export-types.command");
|
|
23
|
+
const permissions_migrate_command_1 = require("./commands/permissions-migrate.command");
|
|
23
24
|
// -----------------------------------------------------------------------
|
|
24
25
|
// Flag parsing helpers
|
|
25
26
|
// -----------------------------------------------------------------------
|
|
@@ -57,6 +58,7 @@ function printHelp() {
|
|
|
57
58
|
blueprint Generate code from YAML blueprints
|
|
58
59
|
export-postman Export a Postman collection
|
|
59
60
|
export-types Export TypeScript type definitions
|
|
61
|
+
permissions-migrate Lift per-user permissions into the org role layer (--apply)
|
|
60
62
|
|
|
61
63
|
Options (by command):
|
|
62
64
|
blueprint
|
|
@@ -103,6 +105,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
103
105
|
output: typeof flags['output'] === 'string' ? flags['output'] : undefined,
|
|
104
106
|
});
|
|
105
107
|
break;
|
|
108
|
+
case 'permissions-migrate':
|
|
109
|
+
await (0, permissions_migrate_command_1.runPermissionsMigrate)(flags);
|
|
110
|
+
break;
|
|
106
111
|
default:
|
|
107
112
|
printHelp();
|
|
108
113
|
if (command !== undefined) {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;AACA;;;;;;;;;GASG;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lift per-user permissions into the shared org role layer.
|
|
3
|
+
*
|
|
4
|
+
* For each (organization, role) group, the literal intersection of every user's
|
|
5
|
+
* `userRoles.permissions` becomes the `orgRolePermission` row (the shared role
|
|
6
|
+
* layer). Each user's row is then reduced to only its delta
|
|
7
|
+
* (`grantedPermissions = permissions − roleLayer`) and its legacy `permissions`
|
|
8
|
+
* is cleared. Effective permissions are preserved exactly (the intersection is a
|
|
9
|
+
* subset of every user's set, so nothing is gained or lost).
|
|
10
|
+
*
|
|
11
|
+
* Safe & idempotent:
|
|
12
|
+
* - Dry-run by default; pass { apply: true } to write.
|
|
13
|
+
* - Groups that already have an orgRolePermission row are skipped.
|
|
14
|
+
* - After a run the legacy permissions are empty, so a second run is a no-op.
|
|
15
|
+
* - Non-tenant (null organization) rows are left untouched.
|
|
16
|
+
*
|
|
17
|
+
* The `prisma` argument is any object exposing the `userRole` and
|
|
18
|
+
* `orgRolePermission` delegates (a real PrismaClient, or a fake in tests).
|
|
19
|
+
*/
|
|
20
|
+
export interface MigratePermissionsResult {
|
|
21
|
+
groupsMigrated: number;
|
|
22
|
+
rowsReduced: number;
|
|
23
|
+
skippedExisting: number;
|
|
24
|
+
lines: string[];
|
|
25
|
+
}
|
|
26
|
+
export declare function migratePermissions(prisma: any, { apply }?: {
|
|
27
|
+
apply?: boolean;
|
|
28
|
+
}): Promise<MigratePermissionsResult>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.migratePermissions = migratePermissions;
|
|
4
|
+
function decode(value) {
|
|
5
|
+
if (Array.isArray(value))
|
|
6
|
+
return value.filter((v) => typeof v === 'string');
|
|
7
|
+
if (typeof value === 'string' && value.trim() !== '') {
|
|
8
|
+
try {
|
|
9
|
+
const parsed = JSON.parse(value);
|
|
10
|
+
return Array.isArray(parsed) ? parsed.filter((v) => typeof v === 'string') : [];
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
function readOrgId(r) {
|
|
19
|
+
return r.organizationId ?? r.organization_id;
|
|
20
|
+
}
|
|
21
|
+
function readRoleId(r) {
|
|
22
|
+
return r.roleId ?? r.role_id;
|
|
23
|
+
}
|
|
24
|
+
async function migratePermissions(prisma, { apply = false } = {}) {
|
|
25
|
+
const userRoles = await prisma.userRole.findMany();
|
|
26
|
+
const relevant = userRoles.filter((r) => readOrgId(r) != null && readRoleId(r) != null);
|
|
27
|
+
const groups = new Map();
|
|
28
|
+
for (const r of relevant) {
|
|
29
|
+
const key = `${readOrgId(r)}::${readRoleId(r)}`;
|
|
30
|
+
const bucket = groups.get(key);
|
|
31
|
+
if (bucket)
|
|
32
|
+
bucket.push(r);
|
|
33
|
+
else
|
|
34
|
+
groups.set(key, [r]);
|
|
35
|
+
}
|
|
36
|
+
let groupsMigrated = 0;
|
|
37
|
+
let rowsReduced = 0;
|
|
38
|
+
let skippedExisting = 0;
|
|
39
|
+
const lines = [];
|
|
40
|
+
for (const rows of groups.values()) {
|
|
41
|
+
const withLegacy = rows.filter((r) => decode(r.permissions).length > 0);
|
|
42
|
+
if (withLegacy.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
const orgId = readOrgId(rows[0]);
|
|
45
|
+
const roleId = readRoleId(rows[0]);
|
|
46
|
+
const existing = await prisma.orgRolePermission.findFirst({
|
|
47
|
+
where: { organizationId: orgId, roleId: roleId },
|
|
48
|
+
});
|
|
49
|
+
if (existing) {
|
|
50
|
+
skippedExisting++;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const sets = withLegacy.map((r) => decode(r.permissions));
|
|
54
|
+
const roleLayer = sets.reduce((acc, set) => acc.filter((p) => set.includes(p)));
|
|
55
|
+
lines.push(`org=${orgId} role=${roleId} → role layer [${roleLayer.join(', ')}] (${withLegacy.length} user rows)`);
|
|
56
|
+
if (apply) {
|
|
57
|
+
await prisma.orgRolePermission.create({
|
|
58
|
+
data: { organizationId: orgId, roleId: roleId, permissions: roleLayer },
|
|
59
|
+
});
|
|
60
|
+
for (const r of withLegacy) {
|
|
61
|
+
const legacy = decode(r.permissions);
|
|
62
|
+
const grants = decode(r.grantedPermissions ?? r.granted_permissions);
|
|
63
|
+
const delta = Array.from(new Set([...legacy.filter((p) => !roleLayer.includes(p)), ...grants]));
|
|
64
|
+
await prisma.userRole.update({
|
|
65
|
+
where: { id: r.id },
|
|
66
|
+
data: { permissions: [], grantedPermissions: delta },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
groupsMigrated++;
|
|
71
|
+
rowsReduced += withLegacy.length;
|
|
72
|
+
}
|
|
73
|
+
return { groupsMigrated, rowsReduced, skippedExisting, lines };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=permissions-migrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions-migrator.js","sourceRoot":"","sources":["../../src/cli/permissions-migrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,8 +56,11 @@ let GroupMembershipGuard = class GroupMembershipGuard {
|
|
|
56
56
|
if (rows.length === 0) {
|
|
57
57
|
throw rhino_exception_1.RhinoException.membershipDenied();
|
|
58
58
|
}
|
|
59
|
-
// Switch the permission source to the matched membership row(s).
|
|
59
|
+
// Switch the permission source to the matched membership row(s). Both the
|
|
60
|
+
// allow set (legacy ∪ granted ∪ role layer) and the deny set come from the
|
|
61
|
+
// matched rows only; deny wins downstream in `userHasPermission`.
|
|
60
62
|
user.__membershipPermissions = this.membership.permissionsFromRows(rows);
|
|
63
|
+
user.__membershipDeniedPermissions = this.membership.deniedFromRows(rows);
|
|
61
64
|
return true;
|
|
62
65
|
}
|
|
63
66
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-membership.guard.js","sourceRoot":"","sources":["../../src/guards/group-membership.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAIwB;AACxB,kDAAqD;AACrD,uEAAmE;AACnE,+DAA2D;AAG3D;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAEZ;IACA;IAFnB,YACmB,MAA0B,EAC1B,UAA6B;QAD7B,WAAM,GAAN,MAAM,CAAoB;QAC1B,eAAU,GAAV,UAAU,CAAmB;IAC7C,CAAC;IAEJ,WAAW,CAAC,OAAyB;QACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;YAAE,OAAO,IAAI,CAAC;QAE5C,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAgB,CAAC;QAC9D,IAAI,GAAG,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC,CAAC,iDAAiD;QAEzE,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC;QAC5C,0DAA0D;QAC1D,IAAI,UAAU,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEzC,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,gCAAc,CAAC,gBAAgB,EAAE,CAAC;QAC1C,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"group-membership.guard.js","sourceRoot":"","sources":["../../src/guards/group-membership.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAIwB;AACxB,kDAAqD;AACrD,uEAAmE;AACnE,+DAA2D;AAG3D;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAEZ;IACA;IAFnB,YACmB,MAA0B,EAC1B,UAA6B;QAD7B,WAAM,GAAN,MAAM,CAAoB;QAC1B,eAAU,GAAV,UAAU,CAAmB;IAC7C,CAAC;IAEJ,WAAW,CAAC,OAAyB;QACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;YAAE,OAAO,IAAI,CAAC;QAE5C,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAgB,CAAC;QAC9D,IAAI,GAAG,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC,CAAC,iDAAiD;QAEzE,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC;QAC5C,0DAA0D;QAC1D,IAAI,UAAU,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEzC,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,gCAAc,CAAC,gBAAgB,EAAE,CAAC;QAC1C,CAAC;QAED,0EAA0E;QAC1E,2EAA2E;QAC3E,kEAAkE;QACjE,IAAY,CAAC,uBAAuB,GAAG,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACjF,IAAY,CAAC,6BAA6B,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAjCY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;qCAGgB,iCAAkB;QACd,sCAAiB;GAHrC,oBAAoB,CAiChC"}
|
|
@@ -52,12 +52,27 @@ let JwtAuthGuard = class JwtAuthGuard {
|
|
|
52
52
|
// behavior is byte-for-byte unchanged.
|
|
53
53
|
let user = null;
|
|
54
54
|
if (this.config.multiTenantEnabled()) {
|
|
55
|
+
// Preferred: also eager-load the org role layer (org_role_permissions) so
|
|
56
|
+
// layered permission resolution has the role-level grants. Apps that have
|
|
57
|
+
// not added the OrgRolePermission relation will throw on this include —
|
|
58
|
+
// fall back to the role-only include (grant/deny columns are scalars and
|
|
59
|
+
// still load there), then to a plain lookup. Existing behavior is unchanged.
|
|
55
60
|
user = await delegate
|
|
56
61
|
.findUnique({
|
|
57
62
|
where: { id: payload.sub },
|
|
58
|
-
include: {
|
|
63
|
+
include: {
|
|
64
|
+
userRoles: { include: { role: { include: { orgRolePermissions: true } } } },
|
|
65
|
+
},
|
|
59
66
|
})
|
|
60
67
|
.catch(() => null);
|
|
68
|
+
if (!user) {
|
|
69
|
+
user = await delegate
|
|
70
|
+
.findUnique({
|
|
71
|
+
where: { id: payload.sub },
|
|
72
|
+
include: { userRoles: { include: { role: true } } },
|
|
73
|
+
})
|
|
74
|
+
.catch(() => null);
|
|
75
|
+
}
|
|
61
76
|
}
|
|
62
77
|
if (!user) {
|
|
63
78
|
user = await delegate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../src/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAIwB;AACxB,2DAAuD;AACvD,6DAAyD;AACzD,kDAAqD;AACrD,+DAA2D;AAG3D;;;;GAIG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEJ;IACA;IACA;IAHnB,YACmB,IAAiB,EACjB,MAAqB,EACrB,MAA0B;QAF1B,SAAI,GAAJ,IAAI,CAAa;QACjB,WAAM,GAAN,MAAM,CAAe;QACrB,WAAM,GAAN,MAAM,CAAoB;IAC1C,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAgB,CAAC;QAC9D,IAAI,GAAG,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,gCAAc,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,MAAM,gCAAc,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9C,gEAAgE;QAChE,4EAA4E;QAC5E,yEAAyE;QACzE,wEAAwE;QACxE,6EAA6E;QAC7E,uCAAuC;QACvC,IAAI,IAAI,GAAQ,IAAI,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,CAAC;YACrC,IAAI,GAAG,MAAM,QAAQ;iBAClB,UAAU,CAAC;gBACV,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE;gBAC1B,OAAO,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../src/guards/jwt-auth.guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ export interface MembershipRow {
|
|
|
8
8
|
routeGroup: string | null;
|
|
9
9
|
organizationId: number | string | null;
|
|
10
10
|
permissions: unknown;
|
|
11
|
+
grantedPermissions?: unknown;
|
|
12
|
+
deniedPermissions?: unknown;
|
|
11
13
|
role?: any;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
@@ -49,8 +51,14 @@ export declare class MembershipService {
|
|
|
49
51
|
id: number | string;
|
|
50
52
|
} | null | undefined, isTenant: boolean): boolean;
|
|
51
53
|
/**
|
|
52
|
-
*
|
|
54
|
+
* ALLOW permissions resolved from the matched membership rows only
|
|
53
55
|
* (design §6: "permissions then resolve from that matching membership row").
|
|
56
|
+
* Layered: each row contributes legacy ∪ granted ∪ org role layer.
|
|
54
57
|
*/
|
|
55
58
|
permissionsFromRows(rows: MembershipRow[]): string[];
|
|
59
|
+
/**
|
|
60
|
+
* DENY permissions resolved from the matched membership rows. Deny always
|
|
61
|
+
* wins over the allow set ({@link permissionsFromRows}).
|
|
62
|
+
*/
|
|
63
|
+
deniedFromRows(rows: MembershipRow[]): string[];
|
|
56
64
|
}
|
|
@@ -80,6 +80,8 @@ let MembershipService = class MembershipService {
|
|
|
80
80
|
routeGroup: rowGroup,
|
|
81
81
|
organizationId: rowOrg,
|
|
82
82
|
permissions: ur.permissions,
|
|
83
|
+
grantedPermissions: ur.grantedPermissions ?? ur.granted_permissions,
|
|
84
|
+
deniedPermissions: ur.deniedPermissions ?? ur.denied_permissions,
|
|
83
85
|
role: ur.role,
|
|
84
86
|
});
|
|
85
87
|
}
|
|
@@ -93,13 +95,26 @@ let MembershipService = class MembershipService {
|
|
|
93
95
|
return this.matchingRows(user, routeGroup, organization, isTenant).length > 0;
|
|
94
96
|
}
|
|
95
97
|
/**
|
|
96
|
-
*
|
|
98
|
+
* ALLOW permissions resolved from the matched membership rows only
|
|
97
99
|
* (design §6: "permissions then resolve from that matching membership row").
|
|
100
|
+
* Layered: each row contributes legacy ∪ granted ∪ org role layer.
|
|
98
101
|
*/
|
|
99
102
|
permissionsFromRows(rows) {
|
|
100
103
|
const out = [];
|
|
101
104
|
for (const r of rows) {
|
|
102
|
-
for (const p of (0, permission_matcher_1.
|
|
105
|
+
for (const p of (0, permission_matcher_1.rowAllowPermissions)(r))
|
|
106
|
+
out.push(p);
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* DENY permissions resolved from the matched membership rows. Deny always
|
|
112
|
+
* wins over the allow set ({@link permissionsFromRows}).
|
|
113
|
+
*/
|
|
114
|
+
deniedFromRows(rows) {
|
|
115
|
+
const out = [];
|
|
116
|
+
for (const r of rows) {
|
|
117
|
+
for (const p of (0, permission_matcher_1.rowDeniedPermissions)(r))
|
|
103
118
|
out.push(p);
|
|
104
119
|
}
|
|
105
120
|
return out;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"membership.service.js","sourceRoot":"","sources":["../../src/services/membership.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,kDAAqD;AACrD,
|
|
1
|
+
{"version":3,"file":"membership.service.js","sourceRoot":"","sources":["../../src/services/membership.service.ts"],"names":[],"mappings":"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"}
|