@contember/bindx-generator 0.1.0 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/bindx-generator",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Schema generator for @contember/bindx with role-based ACL support",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -1,24 +0,0 @@
1
- /**
2
- * Role-aware name schema generator for bindx
3
- * Generates runtime schema names filtered by ACL permissions per role
4
- */
5
- import { Acl, Model } from '@contember/schema';
6
- import { BindxSchemaNames } from './NameSchemaGenerator';
7
- export interface RoleSchemaNames {
8
- readonly [roleName: string]: BindxSchemaNames;
9
- }
10
- export interface RoleNameSchemaGeneratorOptions {
11
- flattenInheritance?: boolean;
12
- allowPredicateAccess?: boolean;
13
- }
14
- export declare class RoleNameSchemaGenerator {
15
- private options;
16
- constructor(options?: RoleNameSchemaGeneratorOptions);
17
- generate(model: Model.Schema, acl: Acl.Schema): RoleSchemaNames;
18
- private generateForRole;
19
- /**
20
- * Generate TypeScript code that exports the role schema names
21
- */
22
- generateCode(model: Model.Schema, acl: Acl.Schema): string;
23
- }
24
- //# sourceMappingURL=RoleNameSchemaGenerator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RoleNameSchemaGenerator.d.ts","sourceRoot":"","sources":["../src/RoleNameSchemaGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAA0B,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAGhF,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAAA;CAC7C;AA2FD,MAAM,WAAW,8BAA8B;IAC9C,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC9B;AAED,qBAAa,uBAAuB;IACnC,OAAO,CAAC,OAAO,CAA0C;gBAE7C,OAAO,GAAE,8BAAmC;IAOxD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,eAAe;IAU/D,OAAO,CAAC,eAAe;IAmFvB;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM;CAqB1D"}
@@ -1,194 +0,0 @@
1
- /**
2
- * Role-aware name schema generator for bindx
3
- * Generates runtime schema names filtered by ACL permissions per role
4
- */
5
- import { Model } from '@contember/schema';
6
- import { acceptEveryFieldVisitor } from '@contember/schema-utils';
7
- import { capitalizeFirstLetter } from './utils';
8
- /**
9
- * Checks if a role has read permission for an entity
10
- */
11
- function hasEntityReadPermission(entityPermissions) {
12
- if (!entityPermissions)
13
- return false;
14
- const readOps = entityPermissions.operations?.read;
15
- return readOps !== undefined && Object.keys(readOps).length > 0;
16
- }
17
- /**
18
- * Checks if a role has read permission for a specific field
19
- */
20
- function hasFieldReadPermission(entityPermissions, fieldName, allowPredicateAccess) {
21
- if (!entityPermissions)
22
- return false;
23
- const readOps = entityPermissions.operations?.read;
24
- if (!readOps)
25
- return false;
26
- const fieldPermission = readOps[fieldName];
27
- if (fieldPermission === undefined)
28
- return false;
29
- if (fieldPermission === false)
30
- return false;
31
- if (fieldPermission === true)
32
- return true;
33
- return allowPredicateAccess;
34
- }
35
- /**
36
- * Get merged permissions for a role, including inherited roles
37
- */
38
- function getMergedPermissions(acl, roleName, visited = new Set()) {
39
- if (visited.has(roleName)) {
40
- return {};
41
- }
42
- visited.add(roleName);
43
- const role = acl.roles[roleName];
44
- if (!role)
45
- return {};
46
- const merged = {};
47
- if (role.inherits) {
48
- for (const inheritedRole of role.inherits) {
49
- const inheritedPermissions = getMergedPermissions(acl, inheritedRole, visited);
50
- for (const [entityName, entityPerms] of Object.entries(inheritedPermissions)) {
51
- if (!merged[entityName]) {
52
- merged[entityName] = { predicates: {}, operations: {} };
53
- }
54
- const existingOps = merged[entityName].operations;
55
- const inheritedOps = entityPerms.operations;
56
- merged[entityName] = {
57
- ...merged[entityName],
58
- operations: {
59
- ...existingOps,
60
- read: { ...existingOps?.read, ...inheritedOps?.read },
61
- },
62
- };
63
- }
64
- }
65
- }
66
- for (const [entityName, entityPerms] of Object.entries(role.entities)) {
67
- if (!merged[entityName]) {
68
- merged[entityName] = entityPerms;
69
- }
70
- else {
71
- const existingOps = merged[entityName].operations;
72
- const roleOps = entityPerms.operations;
73
- merged[entityName] = {
74
- ...merged[entityName],
75
- ...entityPerms,
76
- operations: {
77
- ...existingOps,
78
- ...roleOps,
79
- read: { ...existingOps?.read, ...roleOps?.read },
80
- },
81
- };
82
- }
83
- }
84
- return merged;
85
- }
86
- export class RoleNameSchemaGenerator {
87
- options;
88
- constructor(options = {}) {
89
- this.options = {
90
- flattenInheritance: options.flattenInheritance ?? true,
91
- allowPredicateAccess: options.allowPredicateAccess ?? true,
92
- };
93
- }
94
- generate(model, acl) {
95
- const result = {};
96
- for (const roleName of Object.keys(acl.roles)) {
97
- result[roleName] = this.generateForRole(model, acl, roleName);
98
- }
99
- return result;
100
- }
101
- generateForRole(model, acl, roleName) {
102
- const permissions = this.options.flattenInheritance
103
- ? getMergedPermissions(acl, roleName)
104
- : acl.roles[roleName]?.entities ?? {};
105
- const entities = {};
106
- for (const entity of Object.values(model.entities)) {
107
- const entityPerms = permissions[entity.name];
108
- if (!hasEntityReadPermission(entityPerms)) {
109
- continue;
110
- }
111
- const fields = {};
112
- const scalars = [];
113
- acceptEveryFieldVisitor(model, entity, {
114
- visitHasOne: ctx => {
115
- if (!hasFieldReadPermission(entityPerms, ctx.relation.name, this.options.allowPredicateAccess)) {
116
- return;
117
- }
118
- const targetEntityPerms = permissions[ctx.targetEntity.name];
119
- if (!hasEntityReadPermission(targetEntityPerms)) {
120
- return;
121
- }
122
- fields[ctx.relation.name] = {
123
- type: 'one',
124
- entity: ctx.targetEntity.name,
125
- };
126
- },
127
- visitHasMany: ctx => {
128
- if (!hasFieldReadPermission(entityPerms, ctx.relation.name, this.options.allowPredicateAccess)) {
129
- return;
130
- }
131
- const targetEntityPerms = permissions[ctx.targetEntity.name];
132
- if (!hasEntityReadPermission(targetEntityPerms)) {
133
- return;
134
- }
135
- fields[ctx.relation.name] = {
136
- type: 'many',
137
- entity: ctx.targetEntity.name,
138
- };
139
- },
140
- visitColumn: ctx => {
141
- if (!hasFieldReadPermission(entityPerms, ctx.column.name, this.options.allowPredicateAccess)) {
142
- return;
143
- }
144
- scalars.push(ctx.column.name);
145
- fields[ctx.column.name] = {
146
- type: 'column',
147
- };
148
- },
149
- });
150
- entities[entity.name] = { name: entity.name, fields, scalars };
151
- }
152
- // Filter enums to only include those used by accessible entities
153
- const usedEnums = new Set();
154
- for (const entity of Object.values(model.entities)) {
155
- const entityPerms = permissions[entity.name];
156
- if (!hasEntityReadPermission(entityPerms))
157
- continue;
158
- acceptEveryFieldVisitor(model, entity, {
159
- visitColumn: ctx => {
160
- if (ctx.column.type === Model.ColumnType.Enum) {
161
- if (hasFieldReadPermission(entityPerms, ctx.column.name, this.options.allowPredicateAccess)) {
162
- usedEnums.add(ctx.column.columnType);
163
- }
164
- }
165
- },
166
- visitHasOne: () => { },
167
- visitHasMany: () => { },
168
- });
169
- }
170
- const enums = Object.fromEntries(Object.entries(model.enums).filter(([name]) => usedEnums.has(name)));
171
- return { entities, enums };
172
- }
173
- /**
174
- * Generate TypeScript code that exports the role schema names
175
- */
176
- generateCode(model, acl) {
177
- const schemaNames = this.generate(model, acl);
178
- let code = `import type { BindxSchemaNames } from './types'\n\n`;
179
- // Export individual role schemas
180
- for (const roleName of Object.keys(acl.roles)) {
181
- const roleTypeName = capitalizeFirstLetter(roleName);
182
- code += `export const ${roleTypeName}SchemaNames: BindxSchemaNames = ${JSON.stringify(schemaNames[roleName], null, '\t')}\n\n`;
183
- }
184
- // Export combined role schemas object
185
- code += `export const RoleSchemaNames = {\n`;
186
- for (const roleName of Object.keys(acl.roles)) {
187
- const roleTypeName = capitalizeFirstLetter(roleName);
188
- code += `\t${roleName}: ${roleTypeName}SchemaNames,\n`;
189
- }
190
- code += `} as const\n`;
191
- return code;
192
- }
193
- }
194
- //# sourceMappingURL=RoleNameSchemaGenerator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RoleNameSchemaGenerator.js","sourceRoot":"","sources":["../src/RoleNameSchemaGenerator.ts"],"names":[],"mappings":"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"}