@jantstack/adonis-authz 2.0.0-alpha.1 → 2.4.0-alpha.10
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/README.md +934 -40
- package/build/commands/authz_catalog_diff.d.ts.map +1 -1
- package/build/commands/authz_catalog_diff.js +1 -2
- package/build/commands/authz_catalog_diff.js.map +1 -1
- package/build/commands/authz_catalog_prune_orphans.d.ts +78 -0
- package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -0
- package/build/commands/authz_catalog_prune_orphans.js +135 -0
- package/build/commands/authz_catalog_prune_orphans.js.map +1 -0
- package/build/commands/authz_catalog_sync.d.ts +17 -0
- package/build/commands/authz_catalog_sync.d.ts.map +1 -1
- package/build/commands/authz_catalog_sync.js +27 -4
- package/build/commands/authz_catalog_sync.js.map +1 -1
- package/build/commands/authz_freeze.d.ts +44 -0
- package/build/commands/authz_freeze.d.ts.map +1 -0
- package/build/commands/authz_freeze.js +94 -0
- package/build/commands/authz_freeze.js.map +1 -0
- package/build/commands/authz_reconcile.d.ts +111 -0
- package/build/commands/authz_reconcile.d.ts.map +1 -0
- package/build/commands/authz_reconcile.js +417 -0
- package/build/commands/authz_reconcile.js.map +1 -0
- package/build/commands/authz_relations_reconcile.d.ts +144 -0
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
- package/build/commands/authz_relations_reconcile.js +438 -0
- package/build/commands/authz_relations_reconcile.js.map +1 -0
- package/build/commands/authz_scopes_relay.d.ts +97 -0
- package/build/commands/authz_scopes_relay.d.ts.map +1 -0
- package/build/commands/authz_scopes_relay.js +344 -0
- package/build/commands/authz_scopes_relay.js.map +1 -0
- package/build/commands/authz_scopes_requeue.d.ts +80 -0
- package/build/commands/authz_scopes_requeue.d.ts.map +1 -0
- package/build/commands/authz_scopes_requeue.js +230 -0
- package/build/commands/authz_scopes_requeue.js.map +1 -0
- package/build/commands/authz_unfreeze.d.ts +45 -0
- package/build/commands/authz_unfreeze.d.ts.map +1 -0
- package/build/commands/authz_unfreeze.js +157 -0
- package/build/commands/authz_unfreeze.js.map +1 -0
- package/build/commands/main.d.ts +16 -8
- package/build/commands/main.d.ts.map +1 -1
- package/build/commands/main.js +59 -6
- package/build/commands/main.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +92 -4
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +155 -7
- package/build/commands/openfga_provision.js.map +1 -1
- package/build/configure.d.ts +11 -0
- package/build/configure.d.ts.map +1 -1
- package/build/configure.js +37 -1
- package/build/configure.js.map +1 -1
- package/build/index.d.ts +50 -11
- package/build/index.d.ts.map +1 -1
- package/build/index.js +49 -7
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts +31 -2
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +65 -2
- package/build/providers/authz_provider.js.map +1 -1
- package/build/services/relations.d.ts +14 -0
- package/build/services/relations.d.ts.map +1 -0
- package/build/services/relations.js +17 -0
- package/build/services/relations.js.map +1 -0
- package/build/src/{catalog.d.ts → catalog/catalog.d.ts} +41 -2
- package/build/src/catalog/catalog.d.ts.map +1 -0
- package/build/src/{catalog.js → catalog/catalog.js} +120 -14
- package/build/src/catalog/catalog.js.map +1 -0
- package/build/src/{catalog_cache.d.ts → catalog/catalog_cache.d.ts} +46 -22
- package/build/src/catalog/catalog_cache.d.ts.map +1 -0
- package/build/src/{catalog_cache.js → catalog/catalog_cache.js} +53 -43
- package/build/src/catalog/catalog_cache.js.map +1 -0
- package/build/src/define_config.d.ts +206 -3
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js +11 -0
- package/build/src/define_config.js.map +1 -1
- package/build/src/drivers/database_driver.d.ts +128 -7
- package/build/src/drivers/database_driver.d.ts.map +1 -1
- package/build/src/drivers/database_driver.js +510 -24
- package/build/src/drivers/database_driver.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +140 -0
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/database_relations_driver.js +748 -0
- package/build/src/drivers/database_relations_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +777 -122
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +2228 -477
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +384 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -0
- package/build/src/drivers/openfga_facts.js +836 -0
- package/build/src/drivers/openfga_facts.js.map +1 -0
- package/build/src/drivers/openfga_relations_driver.d.ts +186 -0
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_relations_driver.js +724 -0
- package/build/src/drivers/openfga_relations_driver.js.map +1 -0
- package/build/src/errors.d.ts +430 -6
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +453 -6
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +200 -0
- package/build/src/freeze.d.ts.map +1 -0
- package/build/src/freeze.js +306 -0
- package/build/src/freeze.js.map +1 -0
- package/build/src/http/app_access_middleware.d.ts.map +1 -0
- package/build/src/http/app_access_middleware.js.map +1 -0
- package/build/src/http/resource_access_middleware.d.ts +105 -0
- package/build/src/http/resource_access_middleware.d.ts.map +1 -0
- package/build/src/http/resource_access_middleware.js +81 -0
- package/build/src/http/resource_access_middleware.js.map +1 -0
- package/build/src/identity.d.ts +74 -1
- package/build/src/identity.d.ts.map +1 -1
- package/build/src/identity.js +100 -2
- package/build/src/identity.js.map +1 -1
- package/build/src/manager.d.ts +549 -6
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +2243 -193
- package/build/src/manager.js.map +1 -1
- package/build/src/models/authz_assignment.d.ts +7 -7
- package/build/src/models/authz_assignment.d.ts.map +1 -1
- package/build/src/models/authz_deny.d.ts +7 -7
- package/build/src/models/authz_deny.d.ts.map +1 -1
- package/build/src/models/authz_permission.d.ts +7 -7
- package/build/src/models/authz_permission.d.ts.map +1 -1
- package/build/src/models/authz_role.d.ts +7 -7
- package/build/src/models/authz_role.d.ts.map +1 -1
- package/build/src/models/authz_role_permission.d.ts +7 -7
- package/build/src/models/authz_role_permission.d.ts.map +1 -1
- package/build/src/openfga.d.ts +18 -2
- package/build/src/openfga.d.ts.map +1 -1
- package/build/src/openfga.js +15 -1
- package/build/src/openfga.js.map +1 -1
- package/build/src/reconcile.d.ts +37 -0
- package/build/src/reconcile.d.ts.map +1 -0
- package/build/src/reconcile.js +69 -0
- package/build/src/reconcile.js.map +1 -0
- package/build/src/relation_partition_trigger.d.ts +8 -0
- package/build/src/relation_partition_trigger.d.ts.map +1 -0
- package/build/src/relation_partition_trigger.js +93 -0
- package/build/src/relation_partition_trigger.js.map +1 -0
- package/build/src/relations/define_relations_config.d.ts +109 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -0
- package/build/src/relations/define_relations_config.js +211 -0
- package/build/src/relations/define_relations_config.js.map +1 -0
- package/build/src/relations/manager.d.ts +138 -0
- package/build/src/relations/manager.d.ts.map +1 -0
- package/build/src/relations/manager.js +494 -0
- package/build/src/relations/manager.js.map +1 -0
- package/build/src/relations/reconcile.d.ts +137 -0
- package/build/src/relations/reconcile.d.ts.map +1 -0
- package/build/src/relations/reconcile.js +294 -0
- package/build/src/relations/reconcile.js.map +1 -0
- package/build/src/relations_config_store.d.ts +22 -0
- package/build/src/relations_config_store.d.ts.map +1 -0
- package/build/src/relations_config_store.js +74 -0
- package/build/src/relations_config_store.js.map +1 -0
- package/build/src/scope_outbox.d.ts +123 -0
- package/build/src/scope_outbox.d.ts.map +1 -0
- package/build/src/scope_outbox.js +532 -0
- package/build/src/scope_outbox.js.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.d.ts +42 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.js +78 -1
- package/build/src/shared/backend_guard.js.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.d.ts +2 -0
- package/build/src/shared/sql_expiry.d.ts.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.js +4 -0
- package/build/src/shared/sql_expiry.js.map +1 -0
- package/build/src/shared/transaction_guard.d.ts +53 -0
- package/build/src/shared/transaction_guard.d.ts.map +1 -0
- package/build/src/shared/transaction_guard.js +74 -0
- package/build/src/shared/transaction_guard.js.map +1 -0
- package/build/src/sql_descendants.d.ts +55 -1
- package/build/src/sql_descendants.d.ts.map +1 -1
- package/build/src/sql_descendants.js +75 -1
- package/build/src/sql_descendants.js.map +1 -1
- package/build/src/testing/contract.d.ts +129 -4
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +915 -177
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +10 -2
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +5 -1
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/migration_contract.d.ts +293 -0
- package/build/src/testing/migration_contract.d.ts.map +1 -0
- package/build/src/testing/migration_contract.js +589 -0
- package/build/src/testing/migration_contract.js.map +1 -0
- package/build/src/testing/relations_contract.d.ts +73 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -0
- package/build/src/testing/relations_contract.js +1238 -0
- package/build/src/testing/relations_contract.js.map +1 -0
- package/build/src/testing/relations_reconcile_contract.d.ts +24 -0
- package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -0
- package/build/src/testing/relations_reconcile_contract.js +220 -0
- package/build/src/testing/relations_reconcile_contract.js.map +1 -0
- package/build/src/testing/scope_outbox_contract.d.ts +98 -0
- package/build/src/testing/scope_outbox_contract.d.ts.map +1 -0
- package/build/src/testing/scope_outbox_contract.js +677 -0
- package/build/src/testing/scope_outbox_contract.js.map +1 -0
- package/build/src/traits/authz_scopes.js +1 -1
- package/build/src/traits/authz_scopes.js.map +1 -1
- package/build/src/traits/has_uuid.d.ts +8 -8
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +1537 -84
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +65 -0
- package/build/src/types.js.map +1 -1
- package/build/stubs/config/authorization.stub +149 -5
- package/build/stubs/migration.stub +136 -0
- package/build/stubs/scopes_outbox_migration.stub +57 -0
- package/package.json +4 -2
- package/build/commands/openfga_import.d.ts +0 -34
- package/build/commands/openfga_import.d.ts.map +0 -1
- package/build/commands/openfga_import.js +0 -97
- package/build/commands/openfga_import.js.map +0 -1
- package/build/src/catalog.d.ts.map +0 -1
- package/build/src/catalog.js.map +0 -1
- package/build/src/catalog_cache.d.ts.map +0 -1
- package/build/src/catalog_cache.js.map +0 -1
- package/build/src/drivers/backend_guard.d.ts.map +0 -1
- package/build/src/drivers/backend_guard.js.map +0 -1
- package/build/src/drivers/sql_expiry.d.ts.map +0 -1
- package/build/src/drivers/sql_expiry.js.map +0 -1
- package/build/src/middleware/app_access_middleware.d.ts.map +0 -1
- package/build/src/middleware/app_access_middleware.js.map +0 -1
- /package/build/src/{middleware → http}/app_access_middleware.d.ts +0 -0
- /package/build/src/{middleware → http}/app_access_middleware.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AuthorizationBackendError, AuthorizationBackendTimeoutError, NoScopeResolverError, ScopeResolverError, UnknownScopeError, } from '../errors.js';
|
|
2
2
|
import { APP_SCOPE, APP_SCOPE_TYPE } from '../types.js';
|
|
3
|
-
import { assertScope } from '../identity.js';
|
|
3
|
+
import { assertScope, scopeSpellings } from '../identity.js';
|
|
4
4
|
/**
|
|
5
5
|
* Clasificación de fallos de dependencias, compartida por ambos drivers.
|
|
6
6
|
*
|
|
@@ -40,6 +40,58 @@ export function isSqlDriverError(error) {
|
|
|
40
40
|
return true;
|
|
41
41
|
return false;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* ¿El error (o alguna de sus causas) es un choque del UNIQUE? Por la forma de
|
|
45
|
+
* cada cliente: PostgreSQL SQLSTATE `23505`, MySQL `errno` 1062
|
|
46
|
+
* (`ER_DUP_ENTRY`), SQLite `SQLITE_CONSTRAINT_UNIQUE` (o el `SQLITE_CONSTRAINT`
|
|
47
|
+
* genérico con «UNIQUE» en el mensaje). Se mira la cadena entera de causas:
|
|
48
|
+
* `guardSql` ya lo habrá envuelto en un `AuthorizationBackendError`.
|
|
49
|
+
*
|
|
50
|
+
* Lo usa el driver `database` DENTRO de una transacción del llamante (L-3):
|
|
51
|
+
* fuera de ella un choque se absorbe releyendo (K4), dentro no se puede —en
|
|
52
|
+
* PostgreSQL la transacción ya está abortada y en REPEATABLE READ la relectura
|
|
53
|
+
* no vería al ganador— y sale como 409 `E_AUTHZ_WRITE_CONFLICT`.
|
|
54
|
+
*/
|
|
55
|
+
export function isUniqueViolation(error) {
|
|
56
|
+
let current = error;
|
|
57
|
+
for (let depth = 0; current && depth < 6; depth++) {
|
|
58
|
+
if (current.code === '23505')
|
|
59
|
+
return true;
|
|
60
|
+
if (current.errno === 1062)
|
|
61
|
+
return true;
|
|
62
|
+
if (typeof current.code === 'string' && /^SQLITE_CONSTRAINT/.test(current.code)) {
|
|
63
|
+
if (current.code === 'SQLITE_CONSTRAINT_UNIQUE' || /UNIQUE/i.test(String(current.message ?? '')))
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
current = current.cause;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* ¿El error (o alguna de sus causas) es un DEADLOCK que el motor resolvió
|
|
72
|
+
* eligiendo esta transacción como víctima? PostgreSQL SQLSTATE `40P01`
|
|
73
|
+
* (`deadlock_detected`; y `40001`, `serialization_failure`, la misma familia
|
|
74
|
+
* de «reintenta»), MySQL `errno` 1213 (`ER_LOCK_DEADLOCK`: InnoDB deshace la
|
|
75
|
+
* transacción ENTERA de la víctima). SQLite no tiene deadlocks entre
|
|
76
|
+
* escritores: el segundo recibe `SQLITE_BUSY` (503), no un deadlock.
|
|
77
|
+
*
|
|
78
|
+
* Lo usa el driver `database` de relaciones DENTRO de una transacción del
|
|
79
|
+
* llamante (L-4, 🟡 12 del auditor): dos transacciones que escriben dos
|
|
80
|
+
* relaciones en orden cruzado ⇒ el perdedor sale con **409
|
|
81
|
+
* `E_AUTHZ_WRITE_CONFLICT`** («haz rollback y reintenta»), jamás un error
|
|
82
|
+
* crudo del motor ni un 503 disfrazado de indeterminado.
|
|
83
|
+
*/
|
|
84
|
+
export function isDeadlock(error) {
|
|
85
|
+
let current = error;
|
|
86
|
+
for (let depth = 0; current && depth < 6; depth++) {
|
|
87
|
+
if (current.code === '40P01' || current.code === '40001')
|
|
88
|
+
return true;
|
|
89
|
+
if (current.errno === 1213)
|
|
90
|
+
return true;
|
|
91
|
+
current = current.cause;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
43
95
|
/**
|
|
44
96
|
* ¿El error viene de un deadline vencido? knex lanza `KnexTimeoutError` (o, si
|
|
45
97
|
* además falló la cancelación, el error de cancelación con `timeout` puesto);
|
|
@@ -209,6 +261,31 @@ export async function canonicalScope(resolver, scope, operation) {
|
|
|
209
261
|
throw error;
|
|
210
262
|
}
|
|
211
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* **Los scopes destino de un DELETE que no exige que el scope exista**
|
|
266
|
+
* (`revoke`/`removeDeny`; 3b-8 · A4, mismo cierre que 3b-2h · 🟠 3 dio a
|
|
267
|
+
* `scopes.detached`). Con la fila viva es exactamente UNO, el canónico
|
|
268
|
+
* (`chain[0]`). Sin cadena con la que canonizar —la fila ya borrada, o sin
|
|
269
|
+
* resolutor— la ortografía del llamante a secas hacía del delete un no-op
|
|
270
|
+
* SILENCIOSO cuando llegaba un alias del uuid (el mismo uuid sin guiones,
|
|
271
|
+
* que el tipo `uuid` de PG o una collation `*_ci` funden con la fila real):
|
|
272
|
+
* el hecho canónico seguía escrito y volvía a conceder si el scope se
|
|
273
|
+
* restauraba. Se reusa el fan-out de `scopeSpellings`: la ortografía del
|
|
274
|
+
* llamante Y la canónica de la que puede ser alias. Quitar nunca concede,
|
|
275
|
+
* así que borrar de más no existe aquí.
|
|
276
|
+
*/
|
|
277
|
+
export async function canonicalScopeTargets(resolver, scope, operation) {
|
|
278
|
+
try {
|
|
279
|
+
const chain = await resolveChain(resolver, scope, operation);
|
|
280
|
+
if (chain)
|
|
281
|
+
return [chain[0]];
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
if (!(error instanceof NoScopeResolverError))
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
287
|
+
return scopeSpellings(scope);
|
|
288
|
+
}
|
|
212
289
|
/** La cadena canónica, o 422 `E_AUTHZ_UNKNOWN_SCOPE` si el scope no existe (para escrituras). */
|
|
213
290
|
export async function assertKnownScope(resolver, scope, operation) {
|
|
214
291
|
const chain = await resolveChain(resolver, scope, operation);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_guard.js","sourceRoot":"","sources":["../../../src/shared/backend_guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,8 @@ export interface ExpiryCodec {
|
|
|
29
29
|
/** Lo que devuelve el SELECT de `select(...)` → `Date | null`. */
|
|
30
30
|
fromDb(value: unknown): Date | null;
|
|
31
31
|
}
|
|
32
|
+
/** ¿Es MySQL? (el mismo conjunto que decide el codec). */
|
|
33
|
+
export declare function isMysqlDialect(connection: any): boolean;
|
|
32
34
|
/** Nombre del dialecto de una conexión de Lucid (`dialect.name`; fallback: el driver de knex). */
|
|
33
35
|
export declare function dialectOf(connection: any): string;
|
|
34
36
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql_expiry.d.ts","sourceRoot":"","sources":["../../../src/shared/sql_expiry.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAA;IACrC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,EAAE,IAAI,GAAG,OAAO,CAAA;IACvB,yGAAyG;IACzG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC/C,kEAAkE;IAClE,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAAA;CACpC;AAID,0DAA0D;AAC1D,wBAAgB,cAAc,CAAC,UAAU,EAAE,GAAG,GAAG,OAAO,CAEvD;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,UAAU,EAAE,GAAG,GAAG,MAAM,CAEjD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,GAAG,GAAG,OAAO,CAGxD;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,IAAI,GAAG,MAAM,CAElD;AAED,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAM3D;AA6BD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,GAAE,GAAqB,GAAG,WAAW,CAE7E"}
|
|
@@ -2,6 +2,10 @@ import db from '@adonisjs/lucid/services/db';
|
|
|
2
2
|
import { AuthorizationInternalError } from '../errors.js';
|
|
3
3
|
import { toExpiryDate } from '../expiry.js';
|
|
4
4
|
const MYSQL_DIALECTS = new Set(['mysql', 'mysql2']);
|
|
5
|
+
/** ¿Es MySQL? (el mismo conjunto que decide el codec). */
|
|
6
|
+
export function isMysqlDialect(connection) {
|
|
7
|
+
return MYSQL_DIALECTS.has(dialectOf(connection));
|
|
8
|
+
}
|
|
5
9
|
/** Nombre del dialecto de una conexión de Lucid (`dialect.name`; fallback: el driver de knex). */
|
|
6
10
|
export function dialectOf(connection) {
|
|
7
11
|
return connection?.dialect?.name ?? connection?.client?.driverName ?? 'desconocido';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql_expiry.js","sourceRoot":"","sources":["../../../src/shared/sql_expiry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **¿De quién es esta transacción?** (L-1 · 🟠 9, auditor del panel `{trx}`;
|
|
3
|
+
* ascendido por el juez a REGLA del puerto `{trx}` de L-3/L-4.)
|
|
4
|
+
*
|
|
5
|
+
* Una escritura que se inscribe en la transacción del llamante solo cumple
|
|
6
|
+
* «los dos o ninguno» si esa transacción es de la MISMA conexión que usa
|
|
7
|
+
* quien escribe. `sqlScopeOutbox` lo daba por hecho: con un `trx` devolvía el
|
|
8
|
+
* `trx` tal cual e ignoraba `connection` en silencio, así que el encolado
|
|
9
|
+
* caía en la base del llamante — donde, si existe la tabla, ningún relay
|
|
10
|
+
* lee y la fila ni siquiera sale en `dead()`. Y `db` entero pasaba el
|
|
11
|
+
* duck-check (`.from`/`.table`) y escribía FUERA de toda transacción, sin un
|
|
12
|
+
* solo aviso: la mitigación entera apagada.
|
|
13
|
+
*
|
|
14
|
+
* Esta es la ÚNICA comprobación, para que la outbox de hoy y el
|
|
15
|
+
* `{ transaction }` de `grant`/`relate` de mañana no puedan desincronizarse:
|
|
16
|
+
*
|
|
17
|
+
* 1. tiene que ser un cliente de Lucid (`.from()`/`.table()`);
|
|
18
|
+
* 2. tiene que ser una TRANSACCIÓN ABIERTA (`isTransaction === true`): el
|
|
19
|
+
* `db` de Lucid y un `QueryClient` (`db.connection()`) no lo son;
|
|
20
|
+
* 3. tiene que pertenecer a la conexión de quien escribe (`connectionName`),
|
|
21
|
+
* cuando se conoce cuál es;
|
|
22
|
+
* 4. tiene que seguir ABIERTA (`isCompleted !== true`, 2.4.0-alpha.8): una
|
|
23
|
+
* trx ya confirmada o revertida conserva `isTransaction === true` y hasta
|
|
24
|
+
* alpha.7 pasaba, para reventar dentro de knex como 503.
|
|
25
|
+
*
|
|
26
|
+
* Cualquiera de las cuatro ⇒ 500 `E_AUTHZ_CONFIG` nombrando la operación y las
|
|
27
|
+
* dos conexiones. Es un error de cableado del consumidor, no del backend ni de
|
|
28
|
+
* la petición; y va ANTES de tocar la base (cero sentencias por la
|
|
29
|
+
* transacción ajena).
|
|
30
|
+
*/
|
|
31
|
+
/** Lo mínimo que se exige de la transacción del llamante (un `TransactionClientContract` de Lucid). */
|
|
32
|
+
export interface CallerTransaction {
|
|
33
|
+
from(table: string): any;
|
|
34
|
+
table(table: string): any;
|
|
35
|
+
readonly isTransaction: true;
|
|
36
|
+
readonly connectionName: string;
|
|
37
|
+
}
|
|
38
|
+
export interface CallerTransactionOwner {
|
|
39
|
+
/**
|
|
40
|
+
* La conexión de quien ESCRIBE: la declarada (`connection` de la outbox o
|
|
41
|
+
* del driver) o la primaria del `db` de Lucid. `undefined` solo cuando no
|
|
42
|
+
* se puede saber (un `db` doble sin `primaryConnectionName`): entonces se
|
|
43
|
+
* exige que sea una transacción, pero no se juzga su conexión.
|
|
44
|
+
*/
|
|
45
|
+
connection: string | undefined;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Valida que `transaction` sea la transacción ABIERTA del llamante sobre la
|
|
49
|
+
* conexión de `owner`, y la devuelve tipada. `undefined`/`null` ⇒ `undefined`
|
|
50
|
+
* (no llegó ninguna; el llamante decide qué hacer).
|
|
51
|
+
*/
|
|
52
|
+
export declare function assertCallerTransaction(operation: string, transaction: unknown, owner: CallerTransactionOwner): CallerTransaction | undefined;
|
|
53
|
+
//# sourceMappingURL=transaction_guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction_guard.d.ts","sourceRoot":"","sources":["../../../src/shared/transaction_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,uGAAuG;AACvG,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;IACxB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,KAAK,EAAE,sBAAsB,GAC5B,iBAAiB,GAAG,SAAS,CA6C/B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **¿De quién es esta transacción?** (L-1 · 🟠 9, auditor del panel `{trx}`;
|
|
3
|
+
* ascendido por el juez a REGLA del puerto `{trx}` de L-3/L-4.)
|
|
4
|
+
*
|
|
5
|
+
* Una escritura que se inscribe en la transacción del llamante solo cumple
|
|
6
|
+
* «los dos o ninguno» si esa transacción es de la MISMA conexión que usa
|
|
7
|
+
* quien escribe. `sqlScopeOutbox` lo daba por hecho: con un `trx` devolvía el
|
|
8
|
+
* `trx` tal cual e ignoraba `connection` en silencio, así que el encolado
|
|
9
|
+
* caía en la base del llamante — donde, si existe la tabla, ningún relay
|
|
10
|
+
* lee y la fila ni siquiera sale en `dead()`. Y `db` entero pasaba el
|
|
11
|
+
* duck-check (`.from`/`.table`) y escribía FUERA de toda transacción, sin un
|
|
12
|
+
* solo aviso: la mitigación entera apagada.
|
|
13
|
+
*
|
|
14
|
+
* Esta es la ÚNICA comprobación, para que la outbox de hoy y el
|
|
15
|
+
* `{ transaction }` de `grant`/`relate` de mañana no puedan desincronizarse:
|
|
16
|
+
*
|
|
17
|
+
* 1. tiene que ser un cliente de Lucid (`.from()`/`.table()`);
|
|
18
|
+
* 2. tiene que ser una TRANSACCIÓN ABIERTA (`isTransaction === true`): el
|
|
19
|
+
* `db` de Lucid y un `QueryClient` (`db.connection()`) no lo son;
|
|
20
|
+
* 3. tiene que pertenecer a la conexión de quien escribe (`connectionName`),
|
|
21
|
+
* cuando se conoce cuál es;
|
|
22
|
+
* 4. tiene que seguir ABIERTA (`isCompleted !== true`, 2.4.0-alpha.8): una
|
|
23
|
+
* trx ya confirmada o revertida conserva `isTransaction === true` y hasta
|
|
24
|
+
* alpha.7 pasaba, para reventar dentro de knex como 503.
|
|
25
|
+
*
|
|
26
|
+
* Cualquiera de las cuatro ⇒ 500 `E_AUTHZ_CONFIG` nombrando la operación y las
|
|
27
|
+
* dos conexiones. Es un error de cableado del consumidor, no del backend ni de
|
|
28
|
+
* la petición; y va ANTES de tocar la base (cero sentencias por la
|
|
29
|
+
* transacción ajena).
|
|
30
|
+
*/
|
|
31
|
+
import { AuthorizationConfigError } from '../errors.js';
|
|
32
|
+
/**
|
|
33
|
+
* Valida que `transaction` sea la transacción ABIERTA del llamante sobre la
|
|
34
|
+
* conexión de `owner`, y la devuelve tipada. `undefined`/`null` ⇒ `undefined`
|
|
35
|
+
* (no llegó ninguna; el llamante decide qué hacer).
|
|
36
|
+
*/
|
|
37
|
+
export function assertCallerTransaction(operation, transaction, owner) {
|
|
38
|
+
if (transaction === undefined || transaction === null)
|
|
39
|
+
return undefined;
|
|
40
|
+
const trx = transaction;
|
|
41
|
+
if (typeof trx.from !== 'function' || typeof trx.table !== 'function') {
|
|
42
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' no parece un cliente de Lucid (le faltan .from()/.table()). ` +
|
|
43
|
+
'Pasa el `trx` de db.transaction(); si usas otra cosa, implementa el puerto a mano.');
|
|
44
|
+
}
|
|
45
|
+
// El `db` de Lucid entero (`connection()`/`manager`/`primaryConnectionName`)
|
|
46
|
+
// tiene `.from()`/`.table()` y pasaba: escribía fuera de toda transacción.
|
|
47
|
+
if (typeof trx.connection === 'function' || typeof trx.primaryConnectionName === 'string') {
|
|
48
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' es el servicio \`db\` entero, no una transacción abierta: la escritura se ` +
|
|
49
|
+
'confirmaría sola, FUERA de tu transacción, y la mitigación no existiría. Pasa el `trx` de db.transaction().');
|
|
50
|
+
}
|
|
51
|
+
if (trx.isTransaction !== true) {
|
|
52
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' no es una transacción ABIERTA de Lucid (isTransaction !== true` +
|
|
53
|
+
`${typeof trx.connectionName === 'string' ? `, conexión '${trx.connectionName}'` : ''}): ` +
|
|
54
|
+
'un cliente de consulta confirma cada sentencia por su cuenta. Pasa el `trx` de db.transaction().');
|
|
55
|
+
}
|
|
56
|
+
// (4) Una transacción YA CERRADA (2.4.0-alpha.8; panel relay 2, cuestión
|
|
57
|
+
// 7.2): Lucid deja `isTransaction === true` tras el commit/rollback y
|
|
58
|
+
// publica `isCompleted` (medido). Sin esto la sentencia reventaba dentro de
|
|
59
|
+
// knex y salía como 503 «el backend no respondió», que es mentira: es el
|
|
60
|
+
// cableado del consumidor (un `trx` reutilizado tras `await trx.commit()`).
|
|
61
|
+
if (trx.isCompleted === true) {
|
|
62
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' ya está CERRADA (confirmada o revertida: isCompleted === true` +
|
|
63
|
+
`${typeof trx.connectionName === 'string' ? `, conexión '${trx.connectionName}'` : ''}): no se puede inscribir ` +
|
|
64
|
+
'una escritura en una transacción que ya terminó. Pasa el `trx` de db.transaction() ANTES de confirmarlo o revertirlo. ' +
|
|
65
|
+
'No se ha ejecutado ninguna sentencia.');
|
|
66
|
+
}
|
|
67
|
+
if (owner.connection !== undefined && trx.connectionName !== owner.connection) {
|
|
68
|
+
throw new AuthorizationConfigError(`${operation}: la transacción es de la conexión '${String(trx.connectionName)}' y la escritura va por la ` +
|
|
69
|
+
`conexión '${owner.connection}': no puede inscribirse en ella («los dos o ninguno» sería falso). ` +
|
|
70
|
+
`Abre la transacción con db.connection('${owner.connection}').transaction(), o declara esa conexión aquí.`);
|
|
71
|
+
}
|
|
72
|
+
return trx;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=transaction_guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction_guard.js","sourceRoot":"","sources":["../../../src/shared/transaction_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAoBvD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,SAAiB,EACjB,WAAoB,EACpB,KAA6B;IAE7B,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACvE,MAAM,GAAG,GAAQ,WAAW,CAAA;IAC5B,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,8EAA8E;YACxF,oFAAoF,CACvF,CAAA;IACH,CAAC;IACD,6EAA6E;IAC7E,2EAA2E;IAC3E,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,qBAAqB,KAAK,QAAQ,EAAE,CAAC;QAC1F,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,4FAA4F;YACtG,6GAA6G,CAChH,CAAA;IACH,CAAC;IACD,IAAI,GAAG,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,gFAAgF;YAC1F,GAAG,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK;YAC1F,kGAAkG,CACrG,CAAA;IACH,CAAC;IACD,yEAAyE;IACzE,sEAAsE;IACtE,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAC5E,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,+EAA+E;YACzF,GAAG,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,EAAE,2BAA2B;YAChH,wHAAwH;YACxH,uCAAuC,CAC1C,CAAA;IACH,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,cAAc,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;QAC9E,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,uCAAuC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,6BAA6B;YACxG,aAAa,KAAK,CAAC,UAAU,qEAAqE;YAClG,0CAA0C,KAAK,CAAC,UAAU,gDAAgD,CAC7G,CAAA;IACH,CAAC;IACD,OAAO,GAAwB,CAAA;AACjC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScopeDescendantsResolver } from './types.js';
|
|
1
|
+
import type { ScopeDescendantsResolver, ScopeEdgesEnumerator } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* `descendantsOf` opt-in sobre una tabla del consumidor con columna padre
|
|
4
4
|
* (2.1, B2). Genera UNA CTE recursiva (`WITH RECURSIVE`), la misma para
|
|
@@ -47,5 +47,59 @@ interface DatabaseLike {
|
|
|
47
47
|
connection(name?: string): any;
|
|
48
48
|
}
|
|
49
49
|
export declare function sqlDescendantsOf(options: SqlDescendantsOptions, database?: DatabaseLike): ScopeDescendantsResolver;
|
|
50
|
+
/**
|
|
51
|
+
* `scopes.enumerateEdges` sobre la MISMA tabla que `sqlDescendantsOf`
|
|
52
|
+
* (3b-3a): una página de aristas `hijo → padre` por llamada, ordenadas por la
|
|
53
|
+
* clave primaria y continuadas con un cursor.
|
|
54
|
+
*
|
|
55
|
+
* scopes: {
|
|
56
|
+
* resolveChain,
|
|
57
|
+
* enumerateEdges: sqlScopeEdges({
|
|
58
|
+
* table: 'organization_nodes', uuidColumn: 'uuid',
|
|
59
|
+
* parentColumn: 'parent_uuid', typeColumn: 'kind',
|
|
60
|
+
* }),
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* Lo usa `authz:reconcile --to=openfga` para reconstruir el árbol del store
|
|
64
|
+
* (y para borrar las aristas que la tabla ya no respalda).
|
|
65
|
+
*
|
|
66
|
+
* Decisiones que hay que conocer:
|
|
67
|
+
* - **el cursor es el uuid de la última fila**, y el orden es `ORDER BY
|
|
68
|
+
* uuid` (clave primaria: orden total y estable). Una pasada reanudada no
|
|
69
|
+
* se salta nodos aunque el árbol cambie entre páginas; lo que cambie por
|
|
70
|
+
* debajo del cursor entra en la siguiente pasada, que es idempotente.
|
|
71
|
+
* - **una fila cuyo padre NO existe no produce arista** (LEFT JOIN sin
|
|
72
|
+
* pareja). Es coherente con `resolveChain`, que devuelve `null` para ese
|
|
73
|
+
* nodo: no está en el árbol. No es silencioso: el destino conserva la
|
|
74
|
+
* arista vieja, `authz:reconcile` la cuenta como sobrante y sus hechos
|
|
75
|
+
* salen en `skipped` con el motivo.
|
|
76
|
+
* - `parentColumn IS NULL` es la raíz (`APP_SCOPE`).
|
|
77
|
+
*
|
|
78
|
+
* Mismos dialectos que `sqlDescendantsOf` (PG, MySQL 8, SQLite) y el mismo
|
|
79
|
+
* 500 `E_AUTHZ_UNSUPPORTED_DIALECT` para cualquier otro.
|
|
80
|
+
*
|
|
81
|
+
* **Una tabla con el padre EN LA MISMA tabla** (2.4.0-alpha.4): el `LEFT
|
|
82
|
+
* JOIN` es contra sí misma, y una fila cuyo padre no tiene pareja ahí se
|
|
83
|
+
* SALTA sin aviso (no distingue «huérfano» de «el padre vive en otra
|
|
84
|
+
* tabla»). Si el árbol está repartido en varias tablas, concatenar varios
|
|
85
|
+
* `sqlScopeEdges` no emite las aristas entre tablas y `authz:reconcile
|
|
86
|
+
* --prune` las borraría del store (subárbol entero denegando): escribe tu
|
|
87
|
+
* `enumerateEdges` (UNION ALL). Está en el README de `authz:reconcile`.
|
|
88
|
+
*/
|
|
89
|
+
export interface SqlScopeEdgesOptions {
|
|
90
|
+
table: string;
|
|
91
|
+
uuidColumn: string;
|
|
92
|
+
/** Columna con el uuid del padre; `NULL` = el nodo cuelga de `app`. */
|
|
93
|
+
parentColumn: string;
|
|
94
|
+
/** Columna con el `ScopeRef.type` de cada fila. Excluyente con `scopeType`. */
|
|
95
|
+
typeColumn?: string;
|
|
96
|
+
/** Tipo fijo de todos los nodos de la tabla (sin columna de tipo). Excluyente con `typeColumn`. */
|
|
97
|
+
scopeType?: string;
|
|
98
|
+
/** Nombre de la conexión Lucid (default: la primaria). */
|
|
99
|
+
connection?: string;
|
|
100
|
+
/** Deadline de cada consulta en ms (default 5000): vencido ⇒ 503. */
|
|
101
|
+
timeoutMs?: number;
|
|
102
|
+
}
|
|
103
|
+
export declare function sqlScopeEdges(options: SqlScopeEdgesOptions, database?: DatabaseLike): ScopeEdgesEnumerator;
|
|
50
104
|
export {};
|
|
51
105
|
//# sourceMappingURL=sql_descendants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql_descendants.d.ts","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sql_descendants.d.ts","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAa,oBAAoB,EAAY,MAAM,YAAY,CAAA;AAErG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAuBD,0FAA0F;AAC1F,UAAU,YAAY;IACpB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;CAC/B;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,GAAE,YAAiB,GAC1B,wBAAwB,CAiH1B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,GAAE,YAAiB,GAC1B,oBAAoB,CA+EtB"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import db from '@adonisjs/lucid/services/db';
|
|
2
2
|
import { AuthorizationConfigError, TooManyScopesError, UnsupportedDialectError } from './errors.js';
|
|
3
3
|
import { assertScope, assertScopeType } from './identity.js';
|
|
4
|
-
import { guardSql } from './
|
|
4
|
+
import { guardSql } from './shared/backend_guard.js';
|
|
5
5
|
import { APP_SCOPE_TYPE } from './types.js';
|
|
6
|
+
import { APP_SCOPE } from './types.js';
|
|
6
7
|
const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
7
8
|
/** Dialecto → carácter con el que cita identificadores (MySQL: backtick; el resto: comilla doble ANSI). */
|
|
8
9
|
const QUOTE_BY_DIALECT = {
|
|
@@ -126,4 +127,77 @@ export function sqlDescendantsOf(options, database = db) {
|
|
|
126
127
|
return rows.map((row) => ({ type: typeCol ? row.type : fixedType, uuid: row.uuid }));
|
|
127
128
|
};
|
|
128
129
|
}
|
|
130
|
+
export function sqlScopeEdges(options, database = db) {
|
|
131
|
+
const table = identifier('table', options.table);
|
|
132
|
+
const uuidCol = identifier('uuidColumn', options.uuidColumn);
|
|
133
|
+
const parentCol = identifier('parentColumn', options.parentColumn);
|
|
134
|
+
if ((options.typeColumn === undefined) === (options.scopeType === undefined)) {
|
|
135
|
+
throw new AuthorizationConfigError('sqlScopeEdges: declara exactamente uno de typeColumn (el tipo viene de la fila) o scopeType (tipo fijo).');
|
|
136
|
+
}
|
|
137
|
+
const typeCol = options.typeColumn === undefined ? null : identifier('typeColumn', options.typeColumn);
|
|
138
|
+
const fixedType = options.scopeType ?? null;
|
|
139
|
+
if (fixedType !== null) {
|
|
140
|
+
try {
|
|
141
|
+
assertScopeType(fixedType);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
throw new AuthorizationConfigError(`sqlScopeEdges: scopeType inválido: ${error.message}`);
|
|
145
|
+
}
|
|
146
|
+
if (fixedType === APP_SCOPE_TYPE) {
|
|
147
|
+
throw new AuthorizationConfigError("sqlScopeEdges: scopeType no puede ser 'app' (la raíz no tiene fila)");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
151
|
+
const connectionName = options.connection;
|
|
152
|
+
return async ({ limit, after }) => {
|
|
153
|
+
if (!Number.isInteger(limit) || limit < 1) {
|
|
154
|
+
throw new AuthorizationConfigError(`sqlScopeEdges: limit debe ser un entero >= 1 (llegó ${String(limit)})`);
|
|
155
|
+
}
|
|
156
|
+
const connection = database.connection(connectionName);
|
|
157
|
+
const dialect = connection?.dialect?.name ?? connection?.client?.driverName ?? 'desconocido';
|
|
158
|
+
const quote = QUOTE_BY_DIALECT[dialect];
|
|
159
|
+
if (!quote) {
|
|
160
|
+
throw new UnsupportedDialectError(`sqlScopeEdges: dialecto '${dialect}' sin observación en la suite (hoy: PostgreSQL, MySQL 8 y SQLite). ` +
|
|
161
|
+
`Implementa scopes.enumerateEdges a mano para este motor.`);
|
|
162
|
+
}
|
|
163
|
+
const q = (name) => `${quote}${name}${quote}`;
|
|
164
|
+
const childType = typeCol ? `t.${q(typeCol)}` : 'NULL';
|
|
165
|
+
const parentType = typeCol ? `p.${q(typeCol)}` : 'NULL';
|
|
166
|
+
const text = `SELECT t.${q(uuidCol)} AS ${q('child_uuid')}, ${childType} AS ${q('child_type')},` +
|
|
167
|
+
` t.${q(parentCol)} AS ${q('parent_uuid')}, ${parentType} AS ${q('parent_type')},` +
|
|
168
|
+
` p.${q(uuidCol)} AS ${q('parent_row')}` +
|
|
169
|
+
` FROM ${q(table)} t LEFT JOIN ${q(table)} p ON t.${q(parentCol)} = p.${q(uuidCol)}` +
|
|
170
|
+
(after === undefined ? '' : ` WHERE t.${q(uuidCol)} > ?`) +
|
|
171
|
+
` ORDER BY t.${q(uuidCol)} LIMIT ?`;
|
|
172
|
+
const bindings = after === undefined ? [limit] : [after, limit];
|
|
173
|
+
const result = await guardSql('sqlScopeEdges', 'enumerateEdges', timeoutMs, () => connection.rawQuery(text, bindings));
|
|
174
|
+
const rows = Array.isArray(result)
|
|
175
|
+
? result.length === 2 && Array.isArray(result[0]) && Array.isArray(result[1])
|
|
176
|
+
? result[0]
|
|
177
|
+
: result
|
|
178
|
+
: (result?.rows ?? []);
|
|
179
|
+
const edges = [];
|
|
180
|
+
for (const row of rows) {
|
|
181
|
+
const child = { type: typeCol ? row.child_type : fixedType, uuid: String(row.child_uuid) };
|
|
182
|
+
if (row.parent_uuid === null || row.parent_uuid === undefined) {
|
|
183
|
+
edges.push({ child, parent: APP_SCOPE });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
// Padre declarado que no tiene fila: el nodo NO está en el árbol
|
|
187
|
+
// (`resolveChain` devuelve `null` ahí). No se inventa la arista.
|
|
188
|
+
if (row.parent_row === null || row.parent_row === undefined)
|
|
189
|
+
continue;
|
|
190
|
+
edges.push({
|
|
191
|
+
child,
|
|
192
|
+
parent: { type: typeCol ? row.parent_type : fixedType, uuid: String(row.parent_uuid) },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// El cursor es la ÚLTIMA FILA LEÍDA, no la última arista emitida: si no,
|
|
196
|
+
// una fila con el padre colgando pararía la paginación en seco.
|
|
197
|
+
const last = rows[rows.length - 1];
|
|
198
|
+
return rows.length < limit
|
|
199
|
+
? { edges }
|
|
200
|
+
: { edges, cursor: String(last.child_uuid) };
|
|
201
|
+
};
|
|
202
|
+
}
|
|
129
203
|
//# sourceMappingURL=sql_descendants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql_descendants.js","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC5C,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sql_descendants.js","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"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"}
|