@holoyan/adonisjs-permissions 0.6.4 → 0.6.8
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 +27 -10
- package/build/src/services/helper.js +3 -3
- package/build/src/services/model_has_role_permissions.d.ts +1 -0
- package/build/src/services/model_has_role_permissions.js +4 -1
- package/build/src/services/permissions/empty_permission.d.ts +3 -2
- package/build/src/services/permissions/empty_permission.js +10 -2
- package/build/src/services/roles/empty_roles.d.ts +3 -2
- package/build/src/services/roles/empty_roles.js +10 -2
- package/build/src/services/roles/roles_service.js +6 -1
- package/build/stubs/migrations/create_db.stub +23 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- [Basic Usage](#basic-usage)
|
|
20
20
|
- [Creating roles and permissions](#creating-roles-and-permissions)
|
|
21
21
|
- [Assigning permissions to the roles (Globally)](#assigning-permissions-to-the-roles-globally)
|
|
22
|
+
- [Creating permission on a fly](#creating-permission-on-a-fly)
|
|
22
23
|
- [Assigning permissions and roles to the users (models)](#assigning-permissions-and-roles-to-the-users-models)
|
|
23
24
|
- [Multi-model support](#multi-model-support)
|
|
24
25
|
- [Getting all roles for a user](#getting-all-roles-for-a-user)
|
|
@@ -39,7 +40,8 @@
|
|
|
39
40
|
- [containsPermission v hasPermission](#containspermission-v-haspermission)
|
|
40
41
|
- [Scopes or Multi-tenancy](#scopes-or-multi-tenancy)
|
|
41
42
|
- [The Scope middleware](#the-scope-middleware)
|
|
42
|
-
- [Default Scope](#default-scope-tenant)
|
|
43
|
+
- [Default Scope](#default-scope-tenant)
|
|
44
|
+
- [Cheat sheet](#cheat-sheet)
|
|
43
45
|
- [Todo](#todo)
|
|
44
46
|
- [Test](#test)
|
|
45
47
|
- [License](#license)
|
|
@@ -172,10 +174,15 @@ On this section, we will explore basic role permission methods.
|
|
|
172
174
|
|
|
173
175
|
Let's manually create `create,update,read,delete` permissions, as well as `admin,manager` roles
|
|
174
176
|
|
|
177
|
+
> Look also [Creating permissions on a fly](#creating-permissions-on-a-fly) section
|
|
178
|
+
|
|
175
179
|
```typescript
|
|
176
180
|
|
|
177
181
|
import { Permission } from '@holoyan/adonisjs-permissions'
|
|
178
182
|
import { Role } from '@holoyan/adonisjs-permissions'
|
|
183
|
+
import {Acl} from "@holoyan/adonisjs-permissions";
|
|
184
|
+
|
|
185
|
+
|
|
179
186
|
|
|
180
187
|
|
|
181
188
|
// create permissions
|
|
@@ -188,12 +195,14 @@ const update = await Permission.create({
|
|
|
188
195
|
slug:'update',
|
|
189
196
|
})
|
|
190
197
|
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
// or create using Acl (recomended way)
|
|
199
|
+
const read = await Acl.permission().create({
|
|
200
|
+
slug: 'read',
|
|
193
201
|
})
|
|
194
202
|
|
|
195
|
-
|
|
196
|
-
|
|
203
|
+
|
|
204
|
+
const delete = await Acl.permission().create({
|
|
205
|
+
slug: 'delete',
|
|
197
206
|
})
|
|
198
207
|
|
|
199
208
|
// create roles
|
|
@@ -202,8 +211,9 @@ const admin = await Role.create({
|
|
|
202
211
|
title:'Cool title for Admin', // optional
|
|
203
212
|
})
|
|
204
213
|
|
|
205
|
-
|
|
206
|
-
|
|
214
|
+
// or create using Acl (recomended way)
|
|
215
|
+
const manager = await Acl.role().create({
|
|
216
|
+
slug: 'manager',
|
|
207
217
|
})
|
|
208
218
|
|
|
209
219
|
```
|
|
@@ -228,13 +238,15 @@ await Acl.role(admin).giveAll(['read', 'delete'])
|
|
|
228
238
|
|
|
229
239
|
```
|
|
230
240
|
|
|
241
|
+
### Creating permissions on a fly
|
|
242
|
+
|
|
231
243
|
In case you are assigning a permission that is not already available, `Acl` will create new permission behind the scenes and assign them.
|
|
232
244
|
|
|
233
245
|
```typescript
|
|
234
246
|
|
|
235
|
-
// uploadFile
|
|
247
|
+
// uploadFile permission not available
|
|
236
248
|
await Acl.role(admin).allow('uploadFile')
|
|
237
|
-
// uploadFile permission created and assigned
|
|
249
|
+
// 'uploadFile' permission created and assigned
|
|
238
250
|
|
|
239
251
|
```
|
|
240
252
|
|
|
@@ -265,7 +277,7 @@ import {Acl} from "@holoyan/adonisjs-permissions";
|
|
|
265
277
|
|
|
266
278
|
// create and assign a new permission
|
|
267
279
|
Acl.model(user1).assignDirectPermission('upload-file-slug')
|
|
268
|
-
// or use allow method
|
|
280
|
+
// or use allow() method
|
|
269
281
|
Acl.model(user1).allow('permissionSlug')
|
|
270
282
|
```
|
|
271
283
|
|
|
@@ -922,6 +934,11 @@ export default class PostController {
|
|
|
922
934
|
> Default Scope value is equal to 0 (zero)
|
|
923
935
|
|
|
924
936
|
|
|
937
|
+
## Cheat sheet
|
|
938
|
+
|
|
939
|
+
Coming soon
|
|
940
|
+
|
|
941
|
+
|
|
925
942
|
## TODO
|
|
926
943
|
|
|
927
944
|
- [X] Scopes (Multitenancy)
|
|
@@ -10,7 +10,7 @@ export function formatList(models) {
|
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
12
|
// @ts-ignore
|
|
13
|
-
ids.push(model.id);
|
|
13
|
+
ids.push(+model.id);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
return { slugs, ids };
|
|
@@ -24,7 +24,7 @@ export function formatListStringNumbers(models) {
|
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
26
|
// @ts-ignore
|
|
27
|
-
ids.push(model);
|
|
27
|
+
ids.push(+model);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
return { slugs, ids };
|
|
@@ -41,7 +41,7 @@ export function formatStringNumbers(models) {
|
|
|
41
41
|
ids.push(model);
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
-
ids.push(model.id);
|
|
44
|
+
ids.push(+model.id);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
return { slugs, ids };
|
|
@@ -46,6 +46,7 @@ export declare class ModelHasRolePermissions {
|
|
|
46
46
|
assignDirectPermission(permission: string, target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
47
47
|
assignDirectAllPermissions(permissions: string[], target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
48
48
|
allow(permission: string, target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
49
|
+
allowAll(permission: string[], target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
49
50
|
revokePermission(permission: string, target?: AclModel | Function): Promise<any[]>;
|
|
50
51
|
revoke(permission: string, target?: AclModel | Function): Promise<any[]>;
|
|
51
52
|
revokeAll(permissions: string[], target?: AclModel | Function): Promise<any[]>;
|
|
@@ -140,7 +140,10 @@ export class ModelHasRolePermissions {
|
|
|
140
140
|
return this.permissionsService.giveAll(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId, true);
|
|
141
141
|
}
|
|
142
142
|
allow(permission, target) {
|
|
143
|
-
return this.
|
|
143
|
+
return this.allowAll([permission], target);
|
|
144
|
+
}
|
|
145
|
+
allowAll(permission, target) {
|
|
146
|
+
return this.assignDirectAllPermissions(permission, target);
|
|
144
147
|
}
|
|
145
148
|
async revokePermission(permission, target) {
|
|
146
149
|
return this.revokeAllPermissions([permission], target);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
-
import { ScopeInterface } from '../../types.js';
|
|
2
|
+
import { PermissionInterface, PermissionModel, ScopeInterface } from '../../types.js';
|
|
3
3
|
export default class EmptyPermission {
|
|
4
4
|
private permissionClassName;
|
|
5
5
|
private scope;
|
|
@@ -8,5 +8,6 @@ export default class EmptyPermission {
|
|
|
8
8
|
on(scope: number): this;
|
|
9
9
|
getScope(): number;
|
|
10
10
|
delete(permission: string): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, any>;
|
|
11
|
-
|
|
11
|
+
create(values: Partial<PermissionInterface>): Promise<PermissionModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
12
|
+
query(): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, PermissionModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
12
13
|
}
|
|
@@ -16,10 +16,18 @@ export default class EmptyPermission {
|
|
|
16
16
|
return this.scope.get();
|
|
17
17
|
}
|
|
18
18
|
delete(permission) {
|
|
19
|
-
// get all permissions by slug
|
|
20
|
-
// if there is permission with allowed false then check if it has `links`
|
|
21
19
|
return this.permissionQuery.where('slug', permission).delete();
|
|
22
20
|
}
|
|
21
|
+
async create(values) {
|
|
22
|
+
if (!values.slug) {
|
|
23
|
+
throw new Error('The attribute slug is required');
|
|
24
|
+
}
|
|
25
|
+
const search = {
|
|
26
|
+
slug: values.slug,
|
|
27
|
+
scope: values.scope || this.getScope(),
|
|
28
|
+
};
|
|
29
|
+
return (await this.permissionClassName.updateOrCreate(search, values));
|
|
30
|
+
}
|
|
23
31
|
query() {
|
|
24
32
|
return this.permissionQuery;
|
|
25
33
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
-
import { ScopeInterface } from '../../types.js';
|
|
2
|
+
import { RoleInterface, RoleModel, ScopeInterface } from '../../types.js';
|
|
3
3
|
export default class EmptyRoles {
|
|
4
4
|
private roleClassName;
|
|
5
5
|
private scope;
|
|
@@ -8,5 +8,6 @@ export default class EmptyRoles {
|
|
|
8
8
|
on(scope: number): this;
|
|
9
9
|
getScope(): number;
|
|
10
10
|
delete(role: string): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, any>;
|
|
11
|
-
|
|
11
|
+
create(values: Partial<RoleInterface>): Promise<RoleModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
12
|
+
query(): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, RoleModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
12
13
|
}
|
|
@@ -16,10 +16,18 @@ export default class EmptyRoles {
|
|
|
16
16
|
return this.scope.get();
|
|
17
17
|
}
|
|
18
18
|
delete(role) {
|
|
19
|
-
// get all permissions by slug
|
|
20
|
-
// if there is permission with allowed false then check if it has `links`
|
|
21
19
|
return this.roleQuery.where('slug', role).delete();
|
|
22
20
|
}
|
|
21
|
+
async create(values) {
|
|
22
|
+
if (!values.slug) {
|
|
23
|
+
throw new Error('The attribute slug is required');
|
|
24
|
+
}
|
|
25
|
+
const search = {
|
|
26
|
+
slug: values.slug,
|
|
27
|
+
scope: values.scope || this.getScope(),
|
|
28
|
+
};
|
|
29
|
+
return (await this.roleClassName.updateOrCreate(search, values));
|
|
30
|
+
}
|
|
23
31
|
query() {
|
|
24
32
|
return this.roleQuery;
|
|
25
33
|
}
|
|
@@ -120,7 +120,12 @@ export default class RolesService extends BaseService {
|
|
|
120
120
|
.where('model_type', this.map.getAlias(model))
|
|
121
121
|
.where('model_id', model.getModelId())
|
|
122
122
|
.where((query) => {
|
|
123
|
-
|
|
123
|
+
if (slugs.length) {
|
|
124
|
+
query.orWhereIn('r.slug', slugs);
|
|
125
|
+
}
|
|
126
|
+
if (ids.length) {
|
|
127
|
+
query.orWhereIn('r.id', ids);
|
|
128
|
+
}
|
|
124
129
|
});
|
|
125
130
|
this.applyModelRoleScopes(q, 'r', this.currentScope);
|
|
126
131
|
await q.delete();
|
|
@@ -3,17 +3,16 @@
|
|
|
3
3
|
to: app.makePath('database', 'migrations', prefix + '_create_role_permissions_table.ts')
|
|
4
4
|
})
|
|
5
5
|
}}}
|
|
6
|
-
|
|
7
6
|
import { BaseSchema } from '@adonisjs/lucid/schema'
|
|
8
7
|
import config from "@adonisjs/core/services/config";
|
|
9
8
|
|
|
10
9
|
export default class extends BaseSchema {
|
|
11
10
|
|
|
12
11
|
async up() {
|
|
13
|
-
this.schema.createTable(config.get('permissions.permissionsConfig.tables.
|
|
14
|
-
table.
|
|
12
|
+
this.schema.createTable(config.get('permissions.permissionsConfig.tables.permissions'), (table) => {
|
|
13
|
+
table.bigIncrements('id')
|
|
15
14
|
|
|
16
|
-
table.string('slug')
|
|
15
|
+
table.string('slug')
|
|
17
16
|
table.string('title').nullable()
|
|
18
17
|
table.string('entity_type').defaultTo('*')
|
|
19
18
|
table.bigint('entity_id').unsigned().nullable()
|
|
@@ -26,16 +25,19 @@ export default class extends BaseSchema {
|
|
|
26
25
|
table.timestamp('created_at', { useTz: true })
|
|
27
26
|
table.timestamp('updated_at', { useTz: true })
|
|
28
27
|
|
|
29
|
-
table.
|
|
28
|
+
table.index(['slug', 'scope'])
|
|
30
29
|
table.index(['entity_type', 'entity_id'])
|
|
31
30
|
})
|
|
32
31
|
|
|
33
|
-
this.schema.createTable(config.get('permissions.permissionsConfig.tables.
|
|
34
|
-
table.
|
|
32
|
+
this.schema.createTable(config.get('permissions.permissionsConfig.tables.roles'), (table) => {
|
|
33
|
+
table.bigIncrements('id')
|
|
35
34
|
|
|
36
|
-
table.string('
|
|
37
|
-
table.
|
|
38
|
-
table.
|
|
35
|
+
table.string('slug')
|
|
36
|
+
table.string('title').nullable()
|
|
37
|
+
table.string('entity_type').defaultTo('*')
|
|
38
|
+
table.bigint('entity_id').unsigned().nullable()
|
|
39
|
+
table.integer('scope').unsigned().defaultTo(0)
|
|
40
|
+
table.boolean('allowed').defaultTo(true)
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* Uses timestamptz for PostgreSQL and DATETIME2 for MSSQL
|
|
@@ -43,20 +45,16 @@ export default class extends BaseSchema {
|
|
|
43
45
|
table.timestamp('created_at', { useTz: true })
|
|
44
46
|
table.timestamp('updated_at', { useTz: true })
|
|
45
47
|
|
|
46
|
-
table.index(['
|
|
47
|
-
|
|
48
|
-
table.foreign('role_id').references('roles.id').onDelete('CASCADE')
|
|
48
|
+
table.index(['slug', 'scope'])
|
|
49
|
+
table.index(['entity_type', 'entity_id'])
|
|
49
50
|
})
|
|
50
51
|
|
|
51
|
-
this.schema.createTable(config.get('permissions.permissionsConfig.tables.
|
|
52
|
-
table.
|
|
52
|
+
this.schema.createTable(config.get('permissions.permissionsConfig.tables.modelRoles'), (table) => {
|
|
53
|
+
table.bigIncrements('id')
|
|
53
54
|
|
|
54
|
-
table.string('
|
|
55
|
-
table.
|
|
56
|
-
table.
|
|
57
|
-
table.bigint('entity_id').unsigned().nullable()
|
|
58
|
-
table.integer('scope').unsigned().defaultTo('*')
|
|
59
|
-
table.boolean('allowed').defaultTo(true)
|
|
55
|
+
table.string('model_type')
|
|
56
|
+
table.bigint('model_id').unsigned()
|
|
57
|
+
table.bigInteger('role_id').unsigned()
|
|
60
58
|
|
|
61
59
|
/**
|
|
62
60
|
* Uses timestamptz for PostgreSQL and DATETIME2 for MSSQL
|
|
@@ -64,12 +62,13 @@ export default class extends BaseSchema {
|
|
|
64
62
|
table.timestamp('created_at', { useTz: true })
|
|
65
63
|
table.timestamp('updated_at', { useTz: true })
|
|
66
64
|
|
|
67
|
-
table.
|
|
68
|
-
|
|
65
|
+
table.index(['model_type', 'model_id'])
|
|
66
|
+
|
|
67
|
+
table.foreign('role_id').references('roles.id').onDelete('CASCADE')
|
|
69
68
|
})
|
|
70
69
|
|
|
71
70
|
this.schema.createTable(config.get('permissions.permissionsConfig.tables.modelPermissions'), (table) => {
|
|
72
|
-
table.
|
|
71
|
+
table.bigIncrements('id')
|
|
73
72
|
|
|
74
73
|
table.string('model_type')
|
|
75
74
|
table.bigint('model_id').unsigned()
|