@jantstack/adonis-authz 1.0.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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +138 -0
  3. package/build/commands/main.d.ts +7 -0
  4. package/build/commands/main.d.ts.map +1 -0
  5. package/build/commands/main.js +7 -0
  6. package/build/commands/main.js.map +1 -0
  7. package/build/commands/openfga_import.d.ts +28 -0
  8. package/build/commands/openfga_import.d.ts.map +1 -0
  9. package/build/commands/openfga_import.js +74 -0
  10. package/build/commands/openfga_import.js.map +1 -0
  11. package/build/commands/openfga_provision.d.ts +27 -0
  12. package/build/commands/openfga_provision.d.ts.map +1 -0
  13. package/build/commands/openfga_provision.js +73 -0
  14. package/build/commands/openfga_provision.js.map +1 -0
  15. package/build/configure.d.ts +10 -0
  16. package/build/configure.d.ts.map +1 -0
  17. package/build/configure.js +43 -0
  18. package/build/configure.js.map +1 -0
  19. package/build/index.d.ts +21 -0
  20. package/build/index.d.ts.map +1 -0
  21. package/build/index.js +18 -0
  22. package/build/index.js.map +1 -0
  23. package/build/providers/authz_provider.d.ts +17 -0
  24. package/build/providers/authz_provider.d.ts.map +1 -0
  25. package/build/providers/authz_provider.js +21 -0
  26. package/build/providers/authz_provider.js.map +1 -0
  27. package/build/services/main.d.ts +10 -0
  28. package/build/services/main.d.ts.map +1 -0
  29. package/build/services/main.js +13 -0
  30. package/build/services/main.js.map +1 -0
  31. package/build/src/catalog.d.ts +3 -0
  32. package/build/src/catalog.d.ts.map +1 -0
  33. package/build/src/catalog.js +97 -0
  34. package/build/src/catalog.js.map +1 -0
  35. package/build/src/define_config.d.ts +53 -0
  36. package/build/src/define_config.d.ts.map +1 -0
  37. package/build/src/define_config.js +4 -0
  38. package/build/src/define_config.js.map +1 -0
  39. package/build/src/drivers/database_driver.d.ts +48 -0
  40. package/build/src/drivers/database_driver.d.ts.map +1 -0
  41. package/build/src/drivers/database_driver.js +260 -0
  42. package/build/src/drivers/database_driver.js.map +1 -0
  43. package/build/src/drivers/openfga_driver.d.ts +107 -0
  44. package/build/src/drivers/openfga_driver.d.ts.map +1 -0
  45. package/build/src/drivers/openfga_driver.js +450 -0
  46. package/build/src/drivers/openfga_driver.js.map +1 -0
  47. package/build/src/manager.d.ts +29 -0
  48. package/build/src/manager.d.ts.map +1 -0
  49. package/build/src/manager.js +79 -0
  50. package/build/src/manager.js.map +1 -0
  51. package/build/src/middleware/app_access_middleware.d.ts +23 -0
  52. package/build/src/middleware/app_access_middleware.d.ts.map +1 -0
  53. package/build/src/middleware/app_access_middleware.js +53 -0
  54. package/build/src/middleware/app_access_middleware.js.map +1 -0
  55. package/build/src/models/authz_assignment.d.ts +166 -0
  56. package/build/src/models/authz_assignment.d.ts.map +1 -0
  57. package/build/src/models/authz_assignment.js +60 -0
  58. package/build/src/models/authz_assignment.js.map +1 -0
  59. package/build/src/models/authz_deny.d.ts +161 -0
  60. package/build/src/models/authz_deny.d.ts.map +1 -0
  61. package/build/src/models/authz_deny.js +50 -0
  62. package/build/src/models/authz_deny.js.map +1 -0
  63. package/build/src/models/authz_permission.d.ts +159 -0
  64. package/build/src/models/authz_permission.d.ts.map +1 -0
  65. package/build/src/models/authz_permission.js +42 -0
  66. package/build/src/models/authz_permission.js.map +1 -0
  67. package/build/src/models/authz_role.d.ts +166 -0
  68. package/build/src/models/authz_role.d.ts.map +1 -0
  69. package/build/src/models/authz_role.js +66 -0
  70. package/build/src/models/authz_role.js.map +1 -0
  71. package/build/src/models/authz_role_permission.d.ts +155 -0
  72. package/build/src/models/authz_role_permission.d.ts.map +1 -0
  73. package/build/src/models/authz_role_permission.js +35 -0
  74. package/build/src/models/authz_role_permission.js.map +1 -0
  75. package/build/src/testing/contract.d.ts +27 -0
  76. package/build/src/testing/contract.d.ts.map +1 -0
  77. package/build/src/testing/contract.js +211 -0
  78. package/build/src/testing/contract.js.map +1 -0
  79. package/build/src/testing/main.d.ts +11 -0
  80. package/build/src/testing/main.d.ts.map +1 -0
  81. package/build/src/testing/main.js +10 -0
  82. package/build/src/testing/main.js.map +1 -0
  83. package/build/src/traits/authz_scopes.d.ts +21 -0
  84. package/build/src/traits/authz_scopes.d.ts.map +1 -0
  85. package/build/src/traits/authz_scopes.js +45 -0
  86. package/build/src/traits/authz_scopes.js.map +1 -0
  87. package/build/src/traits/has_uuid.d.ts +151 -0
  88. package/build/src/traits/has_uuid.d.ts.map +1 -0
  89. package/build/src/traits/has_uuid.js +38 -0
  90. package/build/src/traits/has_uuid.js.map +1 -0
  91. package/build/src/types.d.ts +153 -0
  92. package/build/src/types.d.ts.map +1 -0
  93. package/build/src/types.js +38 -0
  94. package/build/src/types.js.map +1 -0
  95. package/build/stubs/config/app_acl.stub +81 -0
  96. package/build/stubs/config/authorization.stub +74 -0
  97. package/build/stubs/main.d.ts +3 -0
  98. package/build/stubs/main.d.ts.map +1 -0
  99. package/build/stubs/main.js +3 -0
  100. package/build/stubs/main.js.map +1 -0
  101. package/build/stubs/migration.stub +124 -0
  102. package/package.json +94 -0
@@ -0,0 +1,450 @@
1
+ import { Exception } from '@adonisjs/core/exceptions';
2
+ import db from '@adonisjs/lucid/services/db';
3
+ import { OpenFgaClient, ClientWriteRequestOnDuplicateWrites, ClientWriteRequestOnMissingDeletes, } from '@openfga/sdk';
4
+ import { APP_SCOPE, APP_SCOPE_TYPE } from '../types.js';
5
+ import { APP_SCOPE_DB_UUID } from './database_driver.js';
6
+ /** `:` no es válido en ids de FGA — se encodea (`audit:read` → `audit~read`). */
7
+ function encodeSlug(slug) {
8
+ return slug.replaceAll(':', '~');
9
+ }
10
+ function decodeSlug(encoded) {
11
+ return encoded.replaceAll('~', ':');
12
+ }
13
+ /**
14
+ * Caracteres admitidos en un tipo de scope y en un uuid al construir la clave
15
+ * del binding. `|` es el separador y `~` el escape de los slugs: si alguno
16
+ * apareciera dentro de un componente, dos scopes DISTINTOS podrían producir
17
+ * la misma clave —p. ej. `{org, 'anization|X'}` y `{'org|anization', 'X'}`—
18
+ * y un grant en uno autorizaría en el otro (confusión de privilegios).
19
+ *
20
+ * El driver `database` es inmune por construcción (guarda tipo y uuid en
21
+ * columnas separadas, sin codificar); esta validación protege la única ruta
22
+ * que serializa el scope a un string.
23
+ */
24
+ const SCOPE_COMPONENT_FORMAT = /^[a-zA-Z0-9_.:-]+$/;
25
+ function assertScopeComponent(kind, value) {
26
+ if (!SCOPE_COMPONENT_FORMAT.test(value)) {
27
+ throw new Exception(`${kind} inválido para el driver openfga: '${value}'. ` +
28
+ `Solo se admiten letras, dígitos y . _ - : (ni '|' ni '~').`, { status: 500 });
29
+ }
30
+ }
31
+ /**
32
+ * Clave de scope dentro del id del binding: `app` para la raíz,
33
+ * `<tipo>|<uuid>` para el resto. Genérico: sirve para cualquier nivel que
34
+ * defina el consumidor sin tocar el driver.
35
+ */
36
+ function scopeKey(scope) {
37
+ assertScopeComponent('Tipo de scope', scope.type);
38
+ if (scope.type === APP_SCOPE_TYPE)
39
+ return APP_SCOPE_TYPE;
40
+ assertScopeComponent('UUID de scope', String(scope.uuid ?? ''));
41
+ return `${scope.type}|${scope.uuid}`;
42
+ }
43
+ function parseBindingId(id) {
44
+ const parts = id.split('|');
45
+ if (parts.length === 2 && parts[0] === APP_SCOPE_TYPE) {
46
+ return { scope: { type: APP_SCOPE_TYPE, uuid: null }, slug: decodeSlug(parts[1]) };
47
+ }
48
+ if (parts.length === 3) {
49
+ return { scope: { type: parts[0], uuid: parts[1] }, slug: decodeSlug(parts[2]) };
50
+ }
51
+ return null;
52
+ }
53
+ /** `<tipoFga>:<uuid>` a partir del morph name del holder. */
54
+ function fgaSubjectWith(subject, holderTypes) {
55
+ const fgaType = holderTypes[subject.type];
56
+ if (!fgaType) {
57
+ throw new Exception(`Holder type '${subject.type}' no está en el modelo FGA ` +
58
+ `(declarados: ${Object.keys(holderTypes).join(', ') || 'ninguno'}). ` +
59
+ `Añádelo a holderTypes y regenera el authorization model.`, { status: 500 });
60
+ }
61
+ return `${fgaType}:${subject.uuid}`;
62
+ }
63
+ function checkContext() {
64
+ return { current_time: new Date().toISOString() };
65
+ }
66
+ /**
67
+ * El authorization model en formato JSON del API de FGA, generado a partir
68
+ * de los holders del consumidor. El mismo mapa debe usarse al construir el
69
+ * driver: si difieren, los checks no encuentran las tuplas.
70
+ */
71
+ export function openFgaAuthorizationModel(holderTypeMap) {
72
+ const holderTypes = [...new Set(Object.values(holderTypeMap))];
73
+ const direct = holderTypes.map((type) => ({ type }));
74
+ const directWithExpiry = [
75
+ ...direct,
76
+ ...holderTypes.map((type) => ({ type, condition: 'not_expired' })),
77
+ ];
78
+ return {
79
+ schema_version: '1.1',
80
+ type_definitions: [
81
+ ...holderTypes.map((type) => ({ type, relations: {}, metadata: null })),
82
+ {
83
+ type: 'role_binding',
84
+ relations: { assignee: { this: {} } },
85
+ metadata: {
86
+ relations: { assignee: { directly_related_user_types: directWithExpiry } },
87
+ },
88
+ },
89
+ {
90
+ type: 'deny_binding',
91
+ relations: { denied: { this: {} } },
92
+ metadata: {
93
+ relations: { denied: { directly_related_user_types: direct } },
94
+ },
95
+ },
96
+ ],
97
+ conditions: {
98
+ not_expired: {
99
+ name: 'not_expired',
100
+ expression: 'current_time < valid_until',
101
+ parameters: {
102
+ current_time: { type_name: 'TYPE_NAME_TIMESTAMP' },
103
+ valid_until: { type_name: 'TYPE_NAME_TIMESTAMP' },
104
+ },
105
+ },
106
+ },
107
+ };
108
+ }
109
+ /**
110
+ * Crea un store nuevo + escribe el authorization model derivado de los
111
+ * holders del consumidor. Para bootstrap de un appliance o del harness de
112
+ * tests. El `name` lo decide el caller (el comando openfga:provision
113
+ * resuelve APP_NAME del entorno — el motor no lee env).
114
+ */
115
+ export async function provisionOpenFgaStore(apiUrl, name, holderTypeMap) {
116
+ const client = new OpenFgaClient({ apiUrl });
117
+ const store = await client.createStore({ name });
118
+ const scoped = new OpenFgaClient({ apiUrl, storeId: store.id });
119
+ const model = await scoped.writeAuthorizationModel(openFgaAuthorizationModel(holderTypeMap));
120
+ return { storeId: store.id, modelId: model.authorization_model_id };
121
+ }
122
+ /**
123
+ * Migración de hechos database → openfga: copia las asignaciones vigentes y
124
+ * los denies de las tablas `authz_*` como tuples del store FGA.
125
+ *
126
+ * - COPIA, no mueve: las tablas locales quedan intactas → el rollback es
127
+ * volver a AUTHZ_DRIVER=database (solo se pierde lo escrito mientras se
128
+ * operó con openfga). El catálogo y la jerarquía nunca migran: son
129
+ * metadata local para ambos drivers.
130
+ * - Idempotente: re-ejecutar no duplica (onDuplicateWrites: Ignore).
131
+ * - Las asignaciones ya expiradas se saltan (no tiene sentido copiarlas);
132
+ * las de expiración futura viajan con la condition `not_expired`.
133
+ */
134
+ export async function importAuthzFactsToOpenFga(options) {
135
+ const client = new OpenFgaClient({
136
+ apiUrl: options.apiUrl,
137
+ storeId: options.storeId,
138
+ authorizationModelId: options.modelId,
139
+ });
140
+ const now = new Date();
141
+ const result = {
142
+ assignments: 0,
143
+ denies: 0,
144
+ skippedExpired: 0,
145
+ dryRun: options.dryRun ?? false,
146
+ };
147
+ const tuples = [];
148
+ const assignments = await db
149
+ .from('authz_assignments as a')
150
+ .join('authz_roles as r', 'r.uuid', 'a.role_uuid')
151
+ .select('a.holder_type', 'a.holder_uuid', 'a.scope_type', 'a.scope_uuid', 'a.expires_at')
152
+ .select('r.slug as role_slug');
153
+ const rowScope = (row) => ({
154
+ type: row.scope_type,
155
+ uuid: row.scope_uuid === APP_SCOPE_DB_UUID ? null : row.scope_uuid,
156
+ });
157
+ for (const row of assignments) {
158
+ const expiresAt = row.expires_at ? new Date(row.expires_at) : null;
159
+ if (expiresAt && expiresAt <= now) {
160
+ result.skippedExpired++;
161
+ continue;
162
+ }
163
+ const scope = rowScope(row);
164
+ const key = {
165
+ user: fgaSubjectWith({ type: row.holder_type, uuid: row.holder_uuid }, options.holderTypes),
166
+ relation: 'assignee',
167
+ object: `role_binding:${scopeKey(scope)}|${encodeSlug(row.role_slug)}`,
168
+ };
169
+ tuples.push(expiresAt
170
+ ? {
171
+ ...key,
172
+ condition: { name: 'not_expired', context: { valid_until: expiresAt.toISOString() } },
173
+ }
174
+ : key);
175
+ result.assignments++;
176
+ }
177
+ const denies = await db
178
+ .from('authz_denies as d')
179
+ .join('authz_permissions as p', 'p.uuid', 'd.permission_uuid')
180
+ .select('d.holder_type', 'd.holder_uuid', 'd.scope_type', 'd.scope_uuid')
181
+ .select('p.slug as permission_slug');
182
+ for (const row of denies) {
183
+ const scope = rowScope(row);
184
+ tuples.push({
185
+ user: fgaSubjectWith({ type: row.holder_type, uuid: row.holder_uuid }, options.holderTypes),
186
+ relation: 'denied',
187
+ object: `deny_binding:${scopeKey(scope)}|${encodeSlug(row.permission_slug)}`,
188
+ });
189
+ result.denies++;
190
+ }
191
+ if (!result.dryRun && tuples.length > 0) {
192
+ // Chunks: el write transaccional de FGA tiene límite de tuples por request.
193
+ for (let i = 0; i < tuples.length; i += 50) {
194
+ await client.writeTuples(tuples.slice(i, i + 50), {
195
+ conflict: { onDuplicateWrites: ClientWriteRequestOnDuplicateWrites.Ignore },
196
+ });
197
+ }
198
+ }
199
+ return result;
200
+ }
201
+ export class OpenFgaAuthorizationDriver {
202
+ client;
203
+ resolveAncestors;
204
+ holderTypes;
205
+ constructor(options) {
206
+ this.client = new OpenFgaClient({
207
+ apiUrl: options.apiUrl,
208
+ storeId: options.storeId,
209
+ authorizationModelId: options.modelId,
210
+ });
211
+ this.resolveAncestors =
212
+ options.resolveAncestors ??
213
+ (async (scope) => (scope.type === APP_SCOPE_TYPE ? [] : [APP_SCOPE]));
214
+ this.holderTypes = options.holderTypes;
215
+ }
216
+ async chain(scope) {
217
+ return [scope, ...(await this.resolveAncestors(scope))];
218
+ }
219
+ fgaSubject(subject) {
220
+ return fgaSubjectWith(subject, this.holderTypes);
221
+ }
222
+ /**
223
+ * batchCheck troceado al límite del servidor FGA (50 checks/request) y con
224
+ * verificación de completitud: TODOS los checks deben volver respondidos.
225
+ */
226
+ async batchCheckAll(checks) {
227
+ const results = [];
228
+ for (let i = 0; i < checks.length; i += 50) {
229
+ const slice = checks.slice(i, i + 50);
230
+ const response = await this.client.batchCheck({ checks: slice });
231
+ results.push(...response.result);
232
+ }
233
+ if (results.length !== checks.length) {
234
+ throw new Exception('OpenFGA batchCheck devolvió menos resultados que checks', {
235
+ status: 500,
236
+ });
237
+ }
238
+ return results;
239
+ }
240
+ // ── Catálogo local (compartido entre drivers) ─────────────────────────
241
+ async findPermission(slug) {
242
+ return db.from('authz_permissions').where('slug', slug).select('uuid').first();
243
+ }
244
+ async findRoleOrFail(slug, scopeType) {
245
+ const role = await db
246
+ .from('authz_roles')
247
+ .where('slug', slug)
248
+ .where('scope_type', scopeType)
249
+ .select('uuid')
250
+ .first();
251
+ if (!role) {
252
+ throw new Exception(`Rol '${slug}' no existe en el catálogo para el nivel '${scopeType}'`, {
253
+ status: 422,
254
+ });
255
+ }
256
+ }
257
+ /** Roles del catálogo que conceden el permiso, agrupados por scope_type. */
258
+ async rolesGranting(permissionUuid) {
259
+ const rows = await db
260
+ .from('authz_role_permissions as rp')
261
+ .join('authz_roles as r', 'r.uuid', 'rp.role_uuid')
262
+ .where('rp.permission_uuid', permissionUuid)
263
+ .select('r.slug', 'r.scope_type');
264
+ const byScopeType = new Map();
265
+ for (const row of rows) {
266
+ const list = byScopeType.get(row.scope_type) ?? [];
267
+ list.push(row.slug);
268
+ byScopeType.set(row.scope_type, list);
269
+ }
270
+ return byScopeType;
271
+ }
272
+ // ── Contrato ──────────────────────────────────────────────────────────
273
+ async authorize(subject, permission, scope) {
274
+ const perm = await this.findPermission(permission);
275
+ if (!perm)
276
+ return false;
277
+ const user = this.fgaSubject(subject);
278
+ const chain = await this.chain(scope);
279
+ // 1. Denies en la cadena. FAIL-CLOSED: un check de deny con error se
280
+ // trata como denegado (jamás se ignora un deny por un fallo puntual).
281
+ const denyChecks = chain.map((s) => ({
282
+ user,
283
+ relation: 'denied',
284
+ object: `deny_binding:${scopeKey(s)}|${encodeSlug(permission)}`,
285
+ }));
286
+ const denyResults = await this.batchCheckAll(denyChecks);
287
+ if (denyResults.some((r) => r.allowed || r.error))
288
+ return false;
289
+ // 2. Alguna asignación vigente en la cadena cuyo rol concede el permiso.
290
+ // Aquí un error individual falla cerrado por sí solo (no concede).
291
+ const granting = await this.rolesGranting(perm.uuid);
292
+ const checks = chain.flatMap((s) => (granting.get(s.type) ?? []).map((roleSlug) => ({
293
+ user,
294
+ relation: 'assignee',
295
+ object: `role_binding:${scopeKey(s)}|${encodeSlug(roleSlug)}`,
296
+ context: checkContext(),
297
+ })));
298
+ if (checks.length === 0)
299
+ return false;
300
+ const results = await this.batchCheckAll(checks);
301
+ return results.some((r) => r.allowed && !r.error);
302
+ }
303
+ async grant(subject, role, scope, options = {}) {
304
+ await this.findRoleOrFail(role, scope.type);
305
+ const key = {
306
+ user: this.fgaSubject(subject),
307
+ relation: 'assignee',
308
+ object: `role_binding:${scopeKey(scope)}|${encodeSlug(role)}`,
309
+ };
310
+ const write = options.expiresAt
311
+ ? {
312
+ ...key,
313
+ condition: {
314
+ name: 'not_expired',
315
+ context: { valid_until: options.expiresAt.toISOString() },
316
+ },
317
+ }
318
+ : key;
319
+ // Re-grant refresca la expiración. FGA no admite delete+write de la
320
+ // misma tuple key en una transacción → dos llamadas tolerantes.
321
+ await this.client.deleteTuples([key], {
322
+ conflict: { onMissingDeletes: ClientWriteRequestOnMissingDeletes.Ignore },
323
+ });
324
+ await this.client.writeTuples([write], {
325
+ conflict: { onDuplicateWrites: ClientWriteRequestOnDuplicateWrites.Ignore },
326
+ });
327
+ }
328
+ async revoke(subject, role, scope) {
329
+ await this.client.deleteTuples([
330
+ {
331
+ user: this.fgaSubject(subject),
332
+ relation: 'assignee',
333
+ object: `role_binding:${scopeKey(scope)}|${encodeSlug(role)}`,
334
+ },
335
+ ], { conflict: { onMissingDeletes: ClientWriteRequestOnMissingDeletes.Ignore } });
336
+ }
337
+ async hasRole(subject, role, scope) {
338
+ const user = this.fgaSubject(subject);
339
+ const chain = await this.chain(scope);
340
+ const results = await this.batchCheckAll(chain.map((s) => ({
341
+ user,
342
+ relation: 'assignee',
343
+ object: `role_binding:${scopeKey(s)}|${encodeSlug(role)}`,
344
+ context: checkContext(),
345
+ })));
346
+ return results.some((r) => r.allowed && !r.error);
347
+ }
348
+ async deny(subject, permission, scope) {
349
+ const perm = await this.findPermission(permission);
350
+ if (!perm) {
351
+ throw new Exception(`Permiso '${permission}' no existe en el catálogo`, { status: 422 });
352
+ }
353
+ await this.client.writeTuples([
354
+ {
355
+ user: this.fgaSubject(subject),
356
+ relation: 'denied',
357
+ object: `deny_binding:${scopeKey(scope)}|${encodeSlug(permission)}`,
358
+ },
359
+ ], { conflict: { onDuplicateWrites: ClientWriteRequestOnDuplicateWrites.Ignore } });
360
+ }
361
+ async removeDeny(subject, permission, scope) {
362
+ await this.client.deleteTuples([
363
+ {
364
+ user: this.fgaSubject(subject),
365
+ relation: 'denied',
366
+ object: `deny_binding:${scopeKey(scope)}|${encodeSlug(permission)}`,
367
+ },
368
+ ], { conflict: { onMissingDeletes: ClientWriteRequestOnMissingDeletes.Ignore } });
369
+ }
370
+ async listSubjects(role, scope) {
371
+ // ListUsers exige EXACTAMENTE un user_filter → una consulta por tipo.
372
+ const results = [];
373
+ const fgaToMorph = Object.fromEntries(Object.entries(this.holderTypes).map(([morph, fga]) => [fga, morph]));
374
+ for (const fgaType of [...new Set(Object.values(this.holderTypes))]) {
375
+ const response = await this.client.listUsers({
376
+ object: { type: 'role_binding', id: `${scopeKey(scope)}|${encodeSlug(role)}` },
377
+ relation: 'assignee',
378
+ user_filters: [{ type: fgaType }],
379
+ context: checkContext(),
380
+ });
381
+ for (const u of response.users ?? []) {
382
+ if (u.object) {
383
+ results.push({ type: fgaToMorph[u.object.type] ?? u.object.type, uuid: u.object.id });
384
+ }
385
+ }
386
+ }
387
+ return results;
388
+ }
389
+ /** role_binding ids del subject (asignaciones directas vigentes). */
390
+ async listBindings(subject) {
391
+ const response = await this.client.listObjects({
392
+ user: this.fgaSubject(subject),
393
+ relation: 'assignee',
394
+ type: 'role_binding',
395
+ context: checkContext(),
396
+ });
397
+ return (response.objects ?? []).map((obj) => obj.replace(/^role_binding:/, ''));
398
+ }
399
+ async listRoles(subject, scope) {
400
+ const prefix = scopeKey(scope);
401
+ const roles = new Set();
402
+ for (const id of await this.listBindings(subject)) {
403
+ const parsed = parseBindingId(id);
404
+ if (parsed && scopeKey(parsed.scope) === prefix)
405
+ roles.add(parsed.slug);
406
+ }
407
+ return [...roles];
408
+ }
409
+ async listRoleScopes(subject, scopeType) {
410
+ const seen = new Map();
411
+ for (const id of await this.listBindings(subject)) {
412
+ const parsed = parseBindingId(id);
413
+ if (parsed && parsed.scope.type === scopeType) {
414
+ seen.set(scopeKey(parsed.scope), parsed.scope);
415
+ }
416
+ }
417
+ return [...seen.values()];
418
+ }
419
+ async listScopes(subject, permission) {
420
+ const perm = await this.findPermission(permission);
421
+ if (!perm)
422
+ return [];
423
+ const granting = await this.rolesGranting(perm.uuid);
424
+ // Denies del subject para este permiso (una sola consulta).
425
+ const denyResponse = await this.client.listObjects({
426
+ user: this.fgaSubject(subject),
427
+ relation: 'denied',
428
+ type: 'deny_binding',
429
+ });
430
+ const deniedKeys = new Set((denyResponse.objects ?? [])
431
+ .map((obj) => obj.replace(/^deny_binding:/, ''))
432
+ .map((id) => parseBindingId(id))
433
+ .filter((p) => Boolean(p && p.slug === permission))
434
+ .map((p) => scopeKey(p.scope)));
435
+ const result = new Map();
436
+ for (const id of await this.listBindings(subject)) {
437
+ const parsed = parseBindingId(id);
438
+ if (!parsed)
439
+ continue;
440
+ if (!(granting.get(parsed.scope.type) ?? []).includes(parsed.slug))
441
+ continue;
442
+ const chain = await this.chain(parsed.scope);
443
+ const blocked = chain.some((s) => deniedKeys.has(scopeKey(s)));
444
+ if (!blocked)
445
+ result.set(scopeKey(parsed.scope), parsed.scope);
446
+ }
447
+ return [...result.values()];
448
+ }
449
+ }
450
+ //# sourceMappingURL=openfga_driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openfga_driver.js","sourceRoot":"","sources":["../../../src/drivers/openfga_driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { AuthorizationConfig } from './define_config.js';
2
+ import type { AuthorizationDriver, GrantOptions, ScopeRef, ScopeType, SubjectRef } from './types.js';
3
+ /**
4
+ * Manager de autorización — la fachada que usan middleware, services y
5
+ * seeders. Resuelve el driver activo del config y notifica cada escritura
6
+ * al hook `onWrite` del consumidor (el chasis lo usa para auditar + SSE).
7
+ *
8
+ * Pieza del "paquete" de autorización: NO conoce config files, modelos ni
9
+ * módulos del consumidor — recibe todo por constructor. El singleton de la
10
+ * app vive en `main.ts` (el único archivo de wiring, fuera del paquete).
11
+ */
12
+ export declare class AuthorizationManager {
13
+ #private;
14
+ constructor(config: AuthorizationConfig);
15
+ driver(): Promise<AuthorizationDriver>;
16
+ /** Solo tests: fuerza re-resolución del driver. */
17
+ clearCachedDriver(): void;
18
+ authorize(subject: SubjectRef, permission: string, scope: ScopeRef): Promise<boolean>;
19
+ hasRole(subject: SubjectRef, role: string, scope: ScopeRef): Promise<boolean>;
20
+ listSubjects(role: string, scope: ScopeRef): Promise<SubjectRef[]>;
21
+ listScopes(subject: SubjectRef, permission: string): Promise<ScopeRef[]>;
22
+ listRoles(subject: SubjectRef, scope: ScopeRef): Promise<string[]>;
23
+ listRoleScopes(subject: SubjectRef, scopeType: ScopeType): Promise<ScopeRef[]>;
24
+ grant(subject: SubjectRef, role: string, scope: ScopeRef, options?: GrantOptions): Promise<void>;
25
+ revoke(subject: SubjectRef, role: string, scope: ScopeRef): Promise<void>;
26
+ deny(subject: SubjectRef, permission: string, scope: ScopeRef): Promise<void>;
27
+ removeDeny(subject: SubjectRef, permission: string, scope: ScopeRef): Promise<void>;
28
+ }
29
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EACV,mBAAmB,EAGnB,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,UAAU,EACX,MAAM,YAAY,CAAA;AAEnB;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;;gBAInB,MAAM,EAAE,mBAAmB;IAIjC,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAgB5C,mDAAmD;IACnD,iBAAiB,IAAI,IAAI;IAInB,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrF,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIlE,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIxE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIlE,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAI9E,KAAK,CACT,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,QAAQ,EACf,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC;IAWV,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7E,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1F"}
@@ -0,0 +1,79 @@
1
+ import { Exception } from '@adonisjs/core/exceptions';
2
+ /**
3
+ * Manager de autorización — la fachada que usan middleware, services y
4
+ * seeders. Resuelve el driver activo del config y notifica cada escritura
5
+ * al hook `onWrite` del consumidor (el chasis lo usa para auditar + SSE).
6
+ *
7
+ * Pieza del "paquete" de autorización: NO conoce config files, modelos ni
8
+ * módulos del consumidor — recibe todo por constructor. El singleton de la
9
+ * app vive en `main.ts` (el único archivo de wiring, fuera del paquete).
10
+ */
11
+ export class AuthorizationManager {
12
+ #config;
13
+ #driver = null;
14
+ constructor(config) {
15
+ this.#config = config;
16
+ }
17
+ async driver() {
18
+ if (this.#driver)
19
+ return this.#driver;
20
+ const registry = this.#config.drivers;
21
+ const factory = registry[this.#config.default];
22
+ if (!factory) {
23
+ throw new Exception(`Driver de autorización '${this.#config.default}' no registrado. ` +
24
+ `Registrados: ${Object.keys(this.#config.drivers).join(', ')}`, { status: 500 });
25
+ }
26
+ const driver = await factory();
27
+ this.#driver = driver;
28
+ return driver;
29
+ }
30
+ /** Solo tests: fuerza re-resolución del driver. */
31
+ clearCachedDriver() {
32
+ this.#driver = null;
33
+ }
34
+ async authorize(subject, permission, scope) {
35
+ return (await this.driver()).authorize(subject, permission, scope);
36
+ }
37
+ async hasRole(subject, role, scope) {
38
+ return (await this.driver()).hasRole(subject, role, scope);
39
+ }
40
+ async listSubjects(role, scope) {
41
+ return (await this.driver()).listSubjects(role, scope);
42
+ }
43
+ async listScopes(subject, permission) {
44
+ return (await this.driver()).listScopes(subject, permission);
45
+ }
46
+ async listRoles(subject, scope) {
47
+ return (await this.driver()).listRoles(subject, scope);
48
+ }
49
+ async listRoleScopes(subject, scopeType) {
50
+ return (await this.driver()).listRoleScopes(subject, scopeType);
51
+ }
52
+ async grant(subject, role, scope, options) {
53
+ await (await this.driver()).grant(subject, role, scope, options);
54
+ await this.#notify({
55
+ action: 'granted',
56
+ subject,
57
+ scope,
58
+ role,
59
+ expiresAt: options?.expiresAt ?? null,
60
+ });
61
+ }
62
+ async revoke(subject, role, scope) {
63
+ await (await this.driver()).revoke(subject, role, scope);
64
+ await this.#notify({ action: 'revoked', subject, scope, role });
65
+ }
66
+ async deny(subject, permission, scope) {
67
+ await (await this.driver()).deny(subject, permission, scope);
68
+ await this.#notify({ action: 'denied', subject, scope, permission });
69
+ }
70
+ async removeDeny(subject, permission, scope) {
71
+ await (await this.driver()).removeDeny(subject, permission, scope);
72
+ await this.#notify({ action: 'deny_removed', subject, scope, permission });
73
+ }
74
+ /** El hook es responsabilidad del consumidor; no debe lanzar. */
75
+ async #notify(event) {
76
+ await this.#config.hooks?.onWrite?.(event);
77
+ }
78
+ }
79
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { HttpContext } from '@adonisjs/core/http';
2
+ import type { NextFn } from '@adonisjs/core/types/http';
3
+ /**
4
+ * Enforcement del ACL de NIVEL APP (gemelo de orgAccess para el scope
5
+ * global). Debe ir DESPUÉS de `middleware.auth(...)` — típicamente con el
6
+ * guard `admins`, aunque funciona con cualquier holder con morph name.
7
+ *
8
+ * Reglas:
9
+ * - No autenticado → 401.
10
+ * - Holder sin el rol/permiso requerido a nivel app → 403.
11
+ * - El ACL decide por IDENTIDAD; el scope del token lo acota
12
+ * middleware.ability() aparte (el token nunca amplía, solo restringe).
13
+ *
14
+ * Uso: middleware.appAccess({ permission: 'audit:read' })
15
+ * middleware.appAccess({ role: 'superadmin' })
16
+ */
17
+ export default class AppAccessMiddleware {
18
+ handle(ctx: HttpContext, next: NextFn, options?: {
19
+ permission?: string;
20
+ role?: string;
21
+ }): Promise<any>;
22
+ }
23
+ //# sourceMappingURL=app_access_middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app_access_middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/app_access_middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAKvD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAChC,MAAM,CACV,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO;CA0CvD"}