@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.
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/build/commands/main.d.ts +7 -0
- package/build/commands/main.d.ts.map +1 -0
- package/build/commands/main.js +7 -0
- package/build/commands/main.js.map +1 -0
- package/build/commands/openfga_import.d.ts +28 -0
- package/build/commands/openfga_import.d.ts.map +1 -0
- package/build/commands/openfga_import.js +74 -0
- package/build/commands/openfga_import.js.map +1 -0
- package/build/commands/openfga_provision.d.ts +27 -0
- package/build/commands/openfga_provision.d.ts.map +1 -0
- package/build/commands/openfga_provision.js +73 -0
- package/build/commands/openfga_provision.js.map +1 -0
- package/build/configure.d.ts +10 -0
- package/build/configure.d.ts.map +1 -0
- package/build/configure.js +43 -0
- package/build/configure.js.map +1 -0
- package/build/index.d.ts +21 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +18 -0
- package/build/index.js.map +1 -0
- package/build/providers/authz_provider.d.ts +17 -0
- package/build/providers/authz_provider.d.ts.map +1 -0
- package/build/providers/authz_provider.js +21 -0
- package/build/providers/authz_provider.js.map +1 -0
- package/build/services/main.d.ts +10 -0
- package/build/services/main.d.ts.map +1 -0
- package/build/services/main.js +13 -0
- package/build/services/main.js.map +1 -0
- package/build/src/catalog.d.ts +3 -0
- package/build/src/catalog.d.ts.map +1 -0
- package/build/src/catalog.js +97 -0
- package/build/src/catalog.js.map +1 -0
- package/build/src/define_config.d.ts +53 -0
- package/build/src/define_config.d.ts.map +1 -0
- package/build/src/define_config.js +4 -0
- package/build/src/define_config.js.map +1 -0
- package/build/src/drivers/database_driver.d.ts +48 -0
- package/build/src/drivers/database_driver.d.ts.map +1 -0
- package/build/src/drivers/database_driver.js +260 -0
- package/build/src/drivers/database_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +107 -0
- package/build/src/drivers/openfga_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_driver.js +450 -0
- package/build/src/drivers/openfga_driver.js.map +1 -0
- package/build/src/manager.d.ts +29 -0
- package/build/src/manager.d.ts.map +1 -0
- package/build/src/manager.js +79 -0
- package/build/src/manager.js.map +1 -0
- package/build/src/middleware/app_access_middleware.d.ts +23 -0
- package/build/src/middleware/app_access_middleware.d.ts.map +1 -0
- package/build/src/middleware/app_access_middleware.js +53 -0
- package/build/src/middleware/app_access_middleware.js.map +1 -0
- package/build/src/models/authz_assignment.d.ts +166 -0
- package/build/src/models/authz_assignment.d.ts.map +1 -0
- package/build/src/models/authz_assignment.js +60 -0
- package/build/src/models/authz_assignment.js.map +1 -0
- package/build/src/models/authz_deny.d.ts +161 -0
- package/build/src/models/authz_deny.d.ts.map +1 -0
- package/build/src/models/authz_deny.js +50 -0
- package/build/src/models/authz_deny.js.map +1 -0
- package/build/src/models/authz_permission.d.ts +159 -0
- package/build/src/models/authz_permission.d.ts.map +1 -0
- package/build/src/models/authz_permission.js +42 -0
- package/build/src/models/authz_permission.js.map +1 -0
- package/build/src/models/authz_role.d.ts +166 -0
- package/build/src/models/authz_role.d.ts.map +1 -0
- package/build/src/models/authz_role.js +66 -0
- package/build/src/models/authz_role.js.map +1 -0
- package/build/src/models/authz_role_permission.d.ts +155 -0
- package/build/src/models/authz_role_permission.d.ts.map +1 -0
- package/build/src/models/authz_role_permission.js +35 -0
- package/build/src/models/authz_role_permission.js.map +1 -0
- package/build/src/testing/contract.d.ts +27 -0
- package/build/src/testing/contract.d.ts.map +1 -0
- package/build/src/testing/contract.js +211 -0
- package/build/src/testing/contract.js.map +1 -0
- package/build/src/testing/main.d.ts +11 -0
- package/build/src/testing/main.d.ts.map +1 -0
- package/build/src/testing/main.js +10 -0
- package/build/src/testing/main.js.map +1 -0
- package/build/src/traits/authz_scopes.d.ts +21 -0
- package/build/src/traits/authz_scopes.d.ts.map +1 -0
- package/build/src/traits/authz_scopes.js +45 -0
- package/build/src/traits/authz_scopes.js.map +1 -0
- package/build/src/traits/has_uuid.d.ts +151 -0
- package/build/src/traits/has_uuid.d.ts.map +1 -0
- package/build/src/traits/has_uuid.js +38 -0
- package/build/src/traits/has_uuid.js.map +1 -0
- package/build/src/types.d.ts +153 -0
- package/build/src/types.d.ts.map +1 -0
- package/build/src/types.js +38 -0
- package/build/src/types.js.map +1 -0
- package/build/stubs/config/app_acl.stub +81 -0
- package/build/stubs/config/authorization.stub +74 -0
- package/build/stubs/main.d.ts +3 -0
- package/build/stubs/main.d.ts.map +1 -0
- package/build/stubs/main.js +3 -0
- package/build/stubs/main.js.map +1 -0
- package/build/stubs/migration.stub +124 -0
- 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
|
+
}
|