@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,124 @@
1
+ {{{
2
+ exports({ to: app.migrationsPath(migration.folder ?? '', migration.fileName) })
3
+ }}}
4
+ import { BaseSchema } from '@adonisjs/lucid/schema'
5
+
6
+ /**
7
+ * Tablas del motor de autorización propio (driver `database`).
8
+ *
9
+ * Esquema jerárquico desde el día uno: scope_type/scope_uuid preparan los
10
+ * niveles organization (T2) y unit (T3) aunque en T1 solo opere `app`
11
+ * (scope_uuid null). Todo es SQL estándar del schema builder — sin features
12
+ * específicas de un motor (regla M6 del chasis).
13
+ *
14
+ * El catálogo (roles/permissions/role_permissions) es metadata compartida
15
+ * entre drivers; los HECHOS (assignments/denies) son lo único que otro
16
+ * driver (p.ej. openfga) materializaría fuera.
17
+ */
18
+ export default class extends BaseSchema {
19
+ public async up() {
20
+ this.schema.createTable('authz_roles', (table) => {
21
+ table.uuid('uuid').primary().notNullable()
22
+ table.string('slug', 100).notNullable()
23
+ table.string('name', 100).notNullable()
24
+ table.string('description', 500).nullable()
25
+ // Nivel al que el rol es asignable: 'app' | 'organization' | 'unit'.
26
+ table.string('scope_type', 20).notNullable()
27
+ // Rango de privilegio (mayor = más poder). Lo consume la policy de
28
+ // asignación (role_assignment_policy): nadie otorga/quita por encima
29
+ // de su propio rango.
30
+ table.integer('rank').notNullable().defaultTo(0)
31
+ table.timestamp('created_at').notNullable()
32
+ table.timestamp('updated_at').notNullable()
33
+
34
+ table.unique(['slug', 'scope_type'], 'authz_roles_slug_scope_uq')
35
+ })
36
+
37
+ this.schema.createTable('authz_permissions', (table) => {
38
+ table.uuid('uuid').primary().notNullable()
39
+ // Formato `recurso:accion` (la misma gramática que las abilities M3).
40
+ table.string('slug', 100).notNullable().unique()
41
+ table.string('description', 500).nullable()
42
+ table.timestamp('created_at').notNullable()
43
+ table.timestamp('updated_at').notNullable()
44
+ })
45
+
46
+ this.schema.createTable('authz_role_permissions', (table) => {
47
+ table.uuid('uuid').primary().notNullable()
48
+ table
49
+ .uuid('role_uuid')
50
+ .notNullable()
51
+ .references('uuid')
52
+ .inTable('authz_roles')
53
+ .onDelete('CASCADE')
54
+ table
55
+ .uuid('permission_uuid')
56
+ .notNullable()
57
+ .references('uuid')
58
+ .inTable('authz_permissions')
59
+ .onDelete('CASCADE')
60
+ table.timestamp('created_at').notNullable()
61
+
62
+ table.unique(['role_uuid', 'permission_uuid'], 'authz_role_perms_uq')
63
+ })
64
+
65
+ this.schema.createTable('authz_assignments', (table) => {
66
+ table.uuid('uuid').primary().notNullable()
67
+ // Holder polimórfico: morph name (users/admins/integrations/...).
68
+ table.string('holder_type', 50).notNullable()
69
+ table.uuid('holder_uuid').notNullable()
70
+ table
71
+ .uuid('role_uuid')
72
+ .notNullable()
73
+ .references('uuid')
74
+ .inTable('authz_roles')
75
+ .onDelete('RESTRICT')
76
+ table.string('scope_type', 20).notNullable()
77
+ // Sin FK: el scope es polimórfico. El nivel 'app' usa el uuid CENTINELA
78
+ // 00000000-... (no NULL): los motores SQL tratan cada NULL como
79
+ // distinto y el unique no aplicaría — con centinela la idempotencia
80
+ // del grant la respalda la constraint en TODOS los niveles (sin
81
+ // features específicas de un motor, regla M6).
82
+ table.uuid('scope_uuid').notNullable()
83
+ table.timestamp('expires_at').nullable()
84
+ table.timestamp('created_at').notNullable()
85
+
86
+ table.unique(
87
+ ['holder_type', 'holder_uuid', 'role_uuid', 'scope_type', 'scope_uuid'],
88
+ 'authz_asg_holder_role_scope_uq'
89
+ )
90
+ table.index(['holder_type', 'holder_uuid'], 'authz_asg_holder_idx')
91
+ table.index(['scope_type', 'scope_uuid'], 'authz_asg_scope_idx')
92
+ })
93
+
94
+ this.schema.createTable('authz_denies', (table) => {
95
+ table.uuid('uuid').primary().notNullable()
96
+ table.string('holder_type', 50).notNullable()
97
+ table.uuid('holder_uuid').notNullable()
98
+ table
99
+ .uuid('permission_uuid')
100
+ .notNullable()
101
+ .references('uuid')
102
+ .inTable('authz_permissions')
103
+ .onDelete('CASCADE')
104
+ table.string('scope_type', 20).notNullable()
105
+ // Centinela 00000000-... para 'app' (ver nota en authz_assignments).
106
+ table.uuid('scope_uuid').notNullable()
107
+ table.timestamp('created_at').notNullable()
108
+
109
+ table.unique(
110
+ ['holder_type', 'holder_uuid', 'permission_uuid', 'scope_type', 'scope_uuid'],
111
+ 'authz_deny_holder_perm_scope_uq'
112
+ )
113
+ table.index(['holder_type', 'holder_uuid'], 'authz_deny_holder_idx')
114
+ })
115
+ }
116
+
117
+ public async down() {
118
+ this.schema.dropTable('authz_denies')
119
+ this.schema.dropTable('authz_assignments')
120
+ this.schema.dropTable('authz_role_permissions')
121
+ this.schema.dropTable('authz_permissions')
122
+ this.schema.dropTable('authz_roles')
123
+ }
124
+ }
package/package.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "@jantstack/adonis-authz",
3
+ "version": "1.0.0",
4
+ "description": "Driver-based authorization engine for AdonisJS + Lucid: hierarchical scopes with downward inheritance, explicit denies, expiring assignments and polymorphic holders. Ships a self-contained database driver and an OpenFGA driver, both judged by the same executable contract suite.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Jose Tenorio",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/JantStack/adonis-authz.git"
11
+ },
12
+ "homepage": "https://github.com/JantStack/adonis-authz#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/JantStack/adonis-authz/issues"
15
+ },
16
+ "keywords": [
17
+ "adonisjs",
18
+ "adonis",
19
+ "adonisjs-7",
20
+ "adonisjs-package",
21
+ "lucid",
22
+ "lucid-orm",
23
+ "authorization",
24
+ "authz",
25
+ "rbac",
26
+ "acl",
27
+ "permissions",
28
+ "roles",
29
+ "openfga",
30
+ "zanzibar",
31
+ "multi-tenancy",
32
+ "typescript",
33
+ "esm",
34
+ "postgresql",
35
+ "mysql",
36
+ "sqlite",
37
+ "backend"
38
+ ],
39
+ "engines": {
40
+ "node": ">=20.6.0"
41
+ },
42
+ "main": "./build/index.js",
43
+ "types": "./build/index.d.ts",
44
+ "exports": {
45
+ ".": "./build/index.js",
46
+ "./authz_provider": "./build/providers/authz_provider.js",
47
+ "./services/main": "./build/services/main.js",
48
+ "./app_access_middleware": "./build/src/middleware/app_access_middleware.js",
49
+ "./commands": "./build/commands/main.js",
50
+ "./commands/*": "./build/commands/*.js",
51
+ "./testing": "./build/src/testing/main.js",
52
+ "./types": "./build/src/types.js"
53
+ },
54
+ "files": [
55
+ "build",
56
+ "README.md"
57
+ ],
58
+ "scripts": {
59
+ "build": "npm run check:purity && rm -rf build && tsc && npm run copy:stubs",
60
+ "typecheck": "tsc --noEmit",
61
+ "prepublishOnly": "npm run build",
62
+ "copy:stubs": "mkdir -p build/stubs/config && cp stubs/*.stub build/stubs/ && cp stubs/config/*.stub build/stubs/config/",
63
+ "check:purity": "node scripts/check_purity.mjs"
64
+ },
65
+ "peerDependencies": {
66
+ "@adonisjs/core": "^7.0.0",
67
+ "@adonisjs/lucid": "^22.0.0"
68
+ },
69
+ "peerDependenciesMeta": {
70
+ "@openfga/sdk": {
71
+ "optional": true
72
+ }
73
+ },
74
+ "dependencies": {
75
+ "uuid": "^14.0.0"
76
+ },
77
+ "devDependencies": {
78
+ "@adonisjs/core": "^7.3.1",
79
+ "@adonisjs/lucid": "^22.4.2",
80
+ "@japa/assert": "^4.2.0",
81
+ "@japa/runner": "^5.3.0",
82
+ "@openfga/sdk": "^0.9.6",
83
+ "@types/luxon": "^3.7.2",
84
+ "@types/node": "^22.19.1",
85
+ "luxon": "^3.7.2",
86
+ "typescript": "~5.9.3"
87
+ },
88
+ "publishConfig": {
89
+ "access": "public"
90
+ },
91
+ "overrides": {
92
+ "axios": "^1.18.1"
93
+ }
94
+ }