@holoyan/adonisjs-permissions 0.5.2 → 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 +294 -97
- package/build/configure.js +9 -0
- package/build/index.d.ts +2 -1
- package/build/index.js +2 -1
- package/build/providers/role_permission_provider.js +5 -3
- package/build/src/acl.d.ts +14 -6
- package/build/src/acl.js +33 -12
- package/build/src/mixins/has_permissions.d.ts +1 -2
- package/build/src/mixins/has_permissions.js +0 -3
- package/build/src/model_manager.d.ts +3 -3
- package/build/src/scope.d.ts +7 -0
- package/build/src/scope.js +14 -0
- package/build/src/services/helper.js +3 -3
- package/build/src/services/model_has_role_permissions.d.ts +13 -3
- package/build/src/services/model_has_role_permissions.js +33 -3
- package/build/src/services/permissions/empty_permission.d.ts +7 -2
- package/build/src/services/permissions/empty_permission.js +20 -3
- package/build/src/services/permissions/permission_has_model_roles.d.ts +5 -2
- package/build/src/services/permissions/permission_has_model_roles.js +10 -1
- package/build/src/services/permissions/permissions_service.d.ts +11 -3
- package/build/src/services/permissions/permissions_service.js +48 -13
- package/build/src/services/query_helper.d.ts +4 -4
- package/build/src/services/query_helper.js +8 -8
- package/build/src/services/roles/empty_roles.d.ts +7 -2
- package/build/src/services/roles/empty_roles.js +20 -3
- package/build/src/services/roles/role_has_model_permissions.d.ts +7 -6
- package/build/src/services/roles/role_has_model_permissions.js +16 -6
- package/build/src/services/roles/roles_service.d.ts +10 -5
- package/build/src/services/roles/roles_service.js +22 -5
- package/build/src/types.d.ts +22 -1
- package/build/stubs/middlewares/acl_middleware.stub +26 -0
- package/build/stubs/migrations/create_db.stub +23 -24
- package/package.json +1 -1
|
@@ -6,7 +6,8 @@ export default class PermissionsService extends BaseService {
|
|
|
6
6
|
modelPermissionClassName;
|
|
7
7
|
modelRoleClassName;
|
|
8
8
|
map;
|
|
9
|
-
|
|
9
|
+
scope;
|
|
10
|
+
// private permissionQuery
|
|
10
11
|
permissionTable;
|
|
11
12
|
// private roleQuery
|
|
12
13
|
// private readonly roleTable
|
|
@@ -14,14 +15,15 @@ export default class PermissionsService extends BaseService {
|
|
|
14
15
|
modelPermissionTable;
|
|
15
16
|
// private modelRoleQuery
|
|
16
17
|
modelRoleTable;
|
|
17
|
-
constructor(permissionClassName, roleClassName, modelPermissionClassName, modelRoleClassName, map) {
|
|
18
|
+
constructor(permissionClassName, roleClassName, modelPermissionClassName, modelRoleClassName, map, scope) {
|
|
18
19
|
super();
|
|
19
20
|
this.permissionClassName = permissionClassName;
|
|
20
21
|
this.roleClassName = roleClassName;
|
|
21
22
|
this.modelPermissionClassName = modelPermissionClassName;
|
|
22
23
|
this.modelRoleClassName = modelRoleClassName;
|
|
23
24
|
this.map = map;
|
|
24
|
-
this.
|
|
25
|
+
this.scope = scope;
|
|
26
|
+
// this.permissionQuery = getPermissionModelQuery(this.permissionClassName)
|
|
25
27
|
this.permissionTable = this.permissionClassName.table;
|
|
26
28
|
// this.roleQuery = getRoleModelQuery(this.roleClassName)
|
|
27
29
|
// this.roleTable = this.roleClassName.table
|
|
@@ -30,6 +32,11 @@ export default class PermissionsService extends BaseService {
|
|
|
30
32
|
// this.modelRoleQuery = getModelRoleModelQuery(this.modelRoleClassName)
|
|
31
33
|
this.modelRoleTable = this.modelRoleClassName.table;
|
|
32
34
|
}
|
|
35
|
+
get permissionQuery() {
|
|
36
|
+
const q = getPermissionModelQuery(this.permissionClassName);
|
|
37
|
+
this.applyScopes(q);
|
|
38
|
+
return q;
|
|
39
|
+
}
|
|
33
40
|
/**
|
|
34
41
|
* return all permissions, including forbidden
|
|
35
42
|
*/
|
|
@@ -85,6 +92,16 @@ export default class PermissionsService extends BaseService {
|
|
|
85
92
|
.distinct(this.permissionTable + '.id')
|
|
86
93
|
.select(this.permissionTable + '.*');
|
|
87
94
|
}
|
|
95
|
+
async throughRoles(modelType, modelId, includeForbiddings = false) {
|
|
96
|
+
return this.modelPermissionQueryBuilder({
|
|
97
|
+
modelType,
|
|
98
|
+
modelId,
|
|
99
|
+
includeForbiddings,
|
|
100
|
+
throughRoles: true,
|
|
101
|
+
})
|
|
102
|
+
.distinct(this.permissionTable + '.id')
|
|
103
|
+
.select(this.permissionTable + '.*');
|
|
104
|
+
}
|
|
88
105
|
directGlobal(modelType, modelId, includeForbiddings = false) {
|
|
89
106
|
return this.modelPermissionQueryBuilder({
|
|
90
107
|
modelType,
|
|
@@ -106,7 +123,7 @@ export default class PermissionsService extends BaseService {
|
|
|
106
123
|
directPermissions: true,
|
|
107
124
|
includeForbiddings,
|
|
108
125
|
})
|
|
109
|
-
.
|
|
126
|
+
.where(this.permissionTable + '.entity_type', '!=', '*')
|
|
110
127
|
.distinct(this.permissionTable + '.id')
|
|
111
128
|
.select(this.permissionTable + '.*');
|
|
112
129
|
}
|
|
@@ -312,6 +329,7 @@ export default class PermissionsService extends BaseService {
|
|
|
312
329
|
.where('p.allowed', true)
|
|
313
330
|
.where(this.modelPermissionTable + '.model_type', modelType)
|
|
314
331
|
.where(this.modelPermissionTable + '.model_id', modelId);
|
|
332
|
+
this.applyModelPermissionScopes(q, 'p');
|
|
315
333
|
if (entityType) {
|
|
316
334
|
q.where('p.entity_type', entityType);
|
|
317
335
|
if (entityId) {
|
|
@@ -352,13 +370,13 @@ export default class PermissionsService extends BaseService {
|
|
|
352
370
|
* to remove forbidden permission on model
|
|
353
371
|
*/
|
|
354
372
|
async unforbidAll(modelType, modelId, permissionsSlug, entityType, entityId) {
|
|
355
|
-
// todo replace using reverseModelPermissionQuery() method
|
|
356
373
|
const q = this.modelPermissionQuery
|
|
357
374
|
.leftJoin(this.permissionTable + ' as p', 'p.id', '=', this.modelPermissionTable + '.permission_id')
|
|
358
375
|
.where('model_type', modelType)
|
|
359
376
|
.where('model_id', modelId)
|
|
360
377
|
.whereIn('p.slug', permissionsSlug)
|
|
361
378
|
.where('p.allowed', false);
|
|
379
|
+
this.applyModelPermissionScopes(q, 'p');
|
|
362
380
|
if (entityType) {
|
|
363
381
|
q.where('p.entity_type', entityType);
|
|
364
382
|
if (entityId) {
|
|
@@ -384,15 +402,21 @@ export default class PermissionsService extends BaseService {
|
|
|
384
402
|
else {
|
|
385
403
|
q.leftJoin(this.modelRoleTable + ' as mr', (joinQuery) => {
|
|
386
404
|
joinQuery.onVal('mr.model_type', modelType).onVal('mr.model_id', modelId);
|
|
387
|
-
}).where((subQuery) => {
|
|
388
|
-
subQuery
|
|
389
|
-
.where((query) => {
|
|
390
|
-
query.where('mp.model_type', modelType).where('mp.model_id', modelId);
|
|
391
|
-
})
|
|
392
|
-
.orWhere((query) => {
|
|
393
|
-
query.whereRaw('mr.role_id=mp.model_id').where('mp.model_type', 'roles');
|
|
394
|
-
});
|
|
395
405
|
});
|
|
406
|
+
if (conditions.throughRoles) {
|
|
407
|
+
q.whereRaw('mr.role_id=mp.model_id').where('mp.model_type', 'roles');
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
q.where((subQuery) => {
|
|
411
|
+
subQuery
|
|
412
|
+
.where((query) => {
|
|
413
|
+
query.where('mp.model_type', modelType).where('mp.model_id', modelId);
|
|
414
|
+
})
|
|
415
|
+
.orWhere((query) => {
|
|
416
|
+
query.whereRaw('mr.role_id=mp.model_id').where('mp.model_type', 'roles');
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
}
|
|
396
420
|
}
|
|
397
421
|
}
|
|
398
422
|
if (!includeForbiddings) {
|
|
@@ -402,6 +426,7 @@ export default class PermissionsService extends BaseService {
|
|
|
402
426
|
.leftJoin(this.modelPermissionTable + ' as mp2', 'mp2.permission_id', '=', 'p2.id')
|
|
403
427
|
.where('p2.allowed', false)
|
|
404
428
|
.whereRaw('p2.slug=' + this.permissionTable + '.slug')
|
|
429
|
+
.whereRaw('p2.scope=' + this.permissionTable + '.scope')
|
|
405
430
|
.select('p2.slug')
|
|
406
431
|
.groupBy('p2.slug');
|
|
407
432
|
if (conditions.entity) {
|
|
@@ -414,6 +439,10 @@ export default class PermissionsService extends BaseService {
|
|
|
414
439
|
}
|
|
415
440
|
return q;
|
|
416
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* @deprecated
|
|
444
|
+
* @param conditions
|
|
445
|
+
*/
|
|
417
446
|
reverseModelPermissionQuery(conditions) {
|
|
418
447
|
const { modelId, modelType, permissionSlugs, directPermissions } = conditions;
|
|
419
448
|
const q = this.modelPermissionQuery.leftJoin(this.permissionTable + ' as p', 'p.id', '=', this.modelPermissionTable + '.permission_id');
|
|
@@ -478,4 +507,10 @@ export default class PermissionsService extends BaseService {
|
|
|
478
507
|
q.where(table + '.entity_type', '*').whereNull(table + '.entity_id');
|
|
479
508
|
}
|
|
480
509
|
}
|
|
510
|
+
applyScopes(q) {
|
|
511
|
+
q.where(this.permissionTable + '.scope', this.scope.get());
|
|
512
|
+
}
|
|
513
|
+
applyModelPermissionScopes(q, table) {
|
|
514
|
+
q.where(table + '.scope', this.scope.get());
|
|
515
|
+
}
|
|
481
516
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LucidModel, ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
|
|
2
2
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
3
3
|
import { ModelPermissionModel, ModelRoleModel, PermissionModel, RoleModel } from '../types.js';
|
|
4
|
-
export declare function getPermissionModelQuery<T extends LucidModel>(
|
|
5
|
-
export declare function getRoleModelQuery<T extends LucidModel>(
|
|
6
|
-
export declare function getModelPermissionModelQuery<T extends LucidModel>(
|
|
7
|
-
export declare function getModelRoleModelQuery<T extends LucidModel>(
|
|
4
|
+
export declare function getPermissionModelQuery<T extends LucidModel>(className: typeof BaseModel): ModelQueryBuilderContract<T, PermissionModel<T>>;
|
|
5
|
+
export declare function getRoleModelQuery<T extends LucidModel>(className: typeof BaseModel): ModelQueryBuilderContract<T, RoleModel<T>>;
|
|
6
|
+
export declare function getModelPermissionModelQuery<T extends LucidModel>(className: typeof BaseModel): ModelQueryBuilderContract<T, ModelPermissionModel<T>>;
|
|
7
|
+
export declare function getModelRoleModelQuery<T extends LucidModel>(className: typeof BaseModel): ModelQueryBuilderContract<T, ModelRoleModel<T>>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export function getPermissionModelQuery(
|
|
2
|
-
return
|
|
1
|
+
export function getPermissionModelQuery(className) {
|
|
2
|
+
return className.query();
|
|
3
3
|
}
|
|
4
|
-
export function getRoleModelQuery(
|
|
5
|
-
return
|
|
4
|
+
export function getRoleModelQuery(className) {
|
|
5
|
+
return className.query();
|
|
6
6
|
}
|
|
7
|
-
export function getModelPermissionModelQuery(
|
|
8
|
-
return
|
|
7
|
+
export function getModelPermissionModelQuery(className) {
|
|
8
|
+
return className.query();
|
|
9
9
|
}
|
|
10
|
-
export function getModelRoleModelQuery(
|
|
11
|
-
return
|
|
10
|
+
export function getModelRoleModelQuery(className) {
|
|
11
|
+
return className.query();
|
|
12
12
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
+
import { RoleInterface, RoleModel, ScopeInterface } from '../../types.js';
|
|
2
3
|
export default class EmptyRoles {
|
|
3
4
|
private roleClassName;
|
|
5
|
+
private scope;
|
|
4
6
|
private roleQuery;
|
|
5
|
-
constructor(roleClassName: typeof BaseModel);
|
|
7
|
+
constructor(roleClassName: typeof BaseModel, scope: ScopeInterface);
|
|
8
|
+
on(scope: number): this;
|
|
9
|
+
getScope(): number;
|
|
6
10
|
delete(role: string): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, any>;
|
|
7
|
-
|
|
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>>;
|
|
8
13
|
}
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
import { getRoleModelQuery } from '../query_helper.js';
|
|
2
2
|
export default class EmptyRoles {
|
|
3
3
|
roleClassName;
|
|
4
|
+
scope;
|
|
4
5
|
roleQuery;
|
|
5
|
-
constructor(roleClassName) {
|
|
6
|
+
constructor(roleClassName, scope) {
|
|
6
7
|
this.roleClassName = roleClassName;
|
|
8
|
+
this.scope = scope;
|
|
7
9
|
this.roleQuery = getRoleModelQuery(this.roleClassName);
|
|
8
10
|
}
|
|
11
|
+
on(scope) {
|
|
12
|
+
this.scope.set(scope);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
getScope() {
|
|
16
|
+
return this.scope.get();
|
|
17
|
+
}
|
|
9
18
|
delete(role) {
|
|
10
|
-
// get all permissions by slug
|
|
11
|
-
// if there is permission with allowed false then check if it has `links`
|
|
12
19
|
return this.roleQuery.where('slug', role).delete();
|
|
13
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
|
+
}
|
|
14
31
|
query() {
|
|
15
32
|
return this.roleQuery;
|
|
16
33
|
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import ModelService from '../model_service.js';
|
|
2
2
|
import PermissionsService from '../permissions/permissions_service.js';
|
|
3
|
-
import { AclModel, MorphInterface, PermissionInterface, RoleInterface } from '../../types.js';
|
|
3
|
+
import { AclModel, MorphInterface, PermissionInterface, RoleInterface, ScopeInterface } from '../../types.js';
|
|
4
4
|
export declare class RoleHasModelPermissions {
|
|
5
5
|
private role;
|
|
6
6
|
private permissionService;
|
|
7
7
|
private modelService;
|
|
8
8
|
private map;
|
|
9
|
-
|
|
9
|
+
private scope;
|
|
10
|
+
constructor(role: RoleInterface, permissionService: PermissionsService, modelService: ModelService, map: MorphInterface, scope: ScopeInterface);
|
|
11
|
+
on(scope: number): this;
|
|
12
|
+
getScope(): number;
|
|
10
13
|
models(): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, import("../../types.js").ModelRoleModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
11
14
|
modelsFor(modelType: string): Promise<any>;
|
|
12
|
-
/**
|
|
13
|
-
* todo
|
|
14
|
-
* @param model
|
|
15
|
-
*/
|
|
16
15
|
permissions(): Promise<import("../../types.js").PermissionModel<import("@adonisjs/lucid/types/model").LucidModel>[]>;
|
|
17
16
|
globalPermissions(): Promise<import("../../types.js").PermissionModel<import("@adonisjs/lucid/types/model").LucidModel>[]>;
|
|
18
17
|
onResourcePermissions(): Promise<import("../../types.js").PermissionModel<import("@adonisjs/lucid/types/model").LucidModel>[]>;
|
|
@@ -52,9 +51,11 @@ export declare class RoleHasModelPermissions {
|
|
|
52
51
|
canAny(permissions: (string | PermissionInterface)[]): Promise<boolean>;
|
|
53
52
|
forbidden(permission: string | PermissionInterface, target?: AclModel | Function): Promise<boolean>;
|
|
54
53
|
assign(permission: string, target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
54
|
+
allow(permission: string, target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
55
55
|
give(permission: string, target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
56
56
|
giveAll(permissions: string[], target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
57
57
|
assingAll(permissions: string[], target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
58
|
+
allowAll(permissions: string[], target?: AclModel | Function): Promise<import("@adonisjs/lucid/types/model").LucidRow[]>;
|
|
58
59
|
revokePermission(permission: string): Promise<any[]>;
|
|
59
60
|
revoke(permission: string): Promise<any[]>;
|
|
60
61
|
revokeAll(permissions: string[], target?: AclModel | Function): Promise<any[]>;
|
|
@@ -4,11 +4,20 @@ export class RoleHasModelPermissions {
|
|
|
4
4
|
permissionService;
|
|
5
5
|
modelService;
|
|
6
6
|
map;
|
|
7
|
-
|
|
7
|
+
scope;
|
|
8
|
+
constructor(role, permissionService, modelService, map, scope) {
|
|
8
9
|
this.role = role;
|
|
9
10
|
this.permissionService = permissionService;
|
|
10
11
|
this.modelService = modelService;
|
|
11
12
|
this.map = map;
|
|
13
|
+
this.scope = scope;
|
|
14
|
+
}
|
|
15
|
+
on(scope) {
|
|
16
|
+
this.scope.set(scope);
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
getScope() {
|
|
20
|
+
return this.scope.get();
|
|
12
21
|
}
|
|
13
22
|
models() {
|
|
14
23
|
return this.modelService.all(this.role.getModelId());
|
|
@@ -16,11 +25,6 @@ export class RoleHasModelPermissions {
|
|
|
16
25
|
modelsFor(modelType) {
|
|
17
26
|
return this.modelService.allFor(modelType, this.role.getModelId());
|
|
18
27
|
}
|
|
19
|
-
/**
|
|
20
|
-
* todo
|
|
21
|
-
* @param model
|
|
22
|
-
*/
|
|
23
|
-
// attachTo(model: LucidModel) {}
|
|
24
28
|
// permissions related BEGIN
|
|
25
29
|
async permissions() {
|
|
26
30
|
// for roles direct and all permissions are same
|
|
@@ -100,6 +104,9 @@ export class RoleHasModelPermissions {
|
|
|
100
104
|
assign(permission, target) {
|
|
101
105
|
return this.give(permission, target);
|
|
102
106
|
}
|
|
107
|
+
allow(permission, target) {
|
|
108
|
+
return this.give(permission, target);
|
|
109
|
+
}
|
|
103
110
|
async give(permission, target) {
|
|
104
111
|
const entity = await destructTarget(this.map, target);
|
|
105
112
|
return this.permissionService.giveAll(this.map.getAlias(this.role), this.role.getModelId(), [permission], entity.targetClass, entity.targetId, true);
|
|
@@ -111,6 +118,9 @@ export class RoleHasModelPermissions {
|
|
|
111
118
|
assingAll(permissions, target) {
|
|
112
119
|
return this.giveAll(permissions, target);
|
|
113
120
|
}
|
|
121
|
+
allowAll(permissions, target) {
|
|
122
|
+
return this.giveAll(permissions, target);
|
|
123
|
+
}
|
|
114
124
|
async revokePermission(permission) {
|
|
115
125
|
return this.revoke(permission);
|
|
116
126
|
}
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { AclModel, MorphInterface, RoleInterface } from '../../types.js';
|
|
1
|
+
import { AclModel, MorphInterface, RoleInterface, ScopeInterface } from '../../types.js';
|
|
2
2
|
import BaseService from '../base_service.js';
|
|
3
3
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
4
|
+
import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
|
|
4
5
|
export default class RolesService extends BaseService {
|
|
5
6
|
private roleClassName;
|
|
6
7
|
private modelPermissionClassName;
|
|
7
8
|
private modelRoleClassName;
|
|
8
9
|
private map;
|
|
10
|
+
private scope;
|
|
9
11
|
private roleQuery;
|
|
10
12
|
private readonly roleTable;
|
|
11
13
|
private readonly modelPermissionTable;
|
|
12
14
|
private modelRoleQuery;
|
|
13
15
|
private readonly modelRoleTable;
|
|
14
|
-
|
|
16
|
+
private currentScope;
|
|
17
|
+
constructor(roleClassName: typeof BaseModel, modelPermissionClassName: typeof BaseModel, modelRoleClassName: typeof BaseModel, map: MorphInterface, scope: ScopeInterface);
|
|
15
18
|
private modelRolesQuery;
|
|
16
|
-
all(modelType: string, modelId: number):
|
|
19
|
+
all(modelType: string, modelId: number): ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, import("../../types.js").RoleModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
17
20
|
has(modelType: string, modelId: number, role: string | RoleInterface): Promise<boolean>;
|
|
18
21
|
hasAll(modelType: string, modelId: number, roles: (string | RoleInterface)[]): Promise<boolean>;
|
|
19
22
|
hasAny(modelType: string, modelId: number, roles: (string | RoleInterface)[]): Promise<boolean>;
|
|
@@ -22,6 +25,8 @@ export default class RolesService extends BaseService {
|
|
|
22
25
|
revoke(role: string | number, model: AclModel): Promise<boolean>;
|
|
23
26
|
revokeAll(roles: (string | number)[], model: AclModel): Promise<boolean>;
|
|
24
27
|
private extractRoleModel;
|
|
25
|
-
roleModelPermissionQuery(modelType: string):
|
|
26
|
-
flush(modelType: string, modelId: number):
|
|
28
|
+
roleModelPermissionQuery(modelType: string): ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, import("../../types.js").RoleModel<import("@adonisjs/lucid/types/model").LucidModel>>;
|
|
29
|
+
flush(modelType: string, modelId: number): ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, any>;
|
|
30
|
+
private applyScopes;
|
|
31
|
+
private applyModelRoleScopes;
|
|
27
32
|
}
|
|
@@ -9,6 +9,7 @@ export default class RolesService extends BaseService {
|
|
|
9
9
|
modelPermissionClassName;
|
|
10
10
|
modelRoleClassName;
|
|
11
11
|
map;
|
|
12
|
+
scope;
|
|
12
13
|
// private permissionQuery
|
|
13
14
|
// private readonly permissionTable
|
|
14
15
|
roleQuery;
|
|
@@ -17,18 +18,22 @@ export default class RolesService extends BaseService {
|
|
|
17
18
|
modelPermissionTable;
|
|
18
19
|
modelRoleQuery;
|
|
19
20
|
modelRoleTable;
|
|
21
|
+
currentScope;
|
|
20
22
|
constructor(roleClassName,
|
|
21
23
|
// private permissionClassName: typeof BaseModel,
|
|
22
|
-
modelPermissionClassName, modelRoleClassName, map) {
|
|
24
|
+
modelPermissionClassName, modelRoleClassName, map, scope) {
|
|
23
25
|
super();
|
|
24
26
|
this.roleClassName = roleClassName;
|
|
25
27
|
this.modelPermissionClassName = modelPermissionClassName;
|
|
26
28
|
this.modelRoleClassName = modelRoleClassName;
|
|
27
29
|
this.map = map;
|
|
30
|
+
this.scope = scope;
|
|
28
31
|
// this.permissionQuery = getPermissionModelQuery(this.permissionClassName)
|
|
29
32
|
// this.permissionTable = this.permissionClassName.table
|
|
33
|
+
this.currentScope = this.scope.get();
|
|
30
34
|
this.roleQuery = getRoleModelQuery(this.roleClassName);
|
|
31
35
|
this.roleTable = this.roleClassName.table;
|
|
36
|
+
this.applyScopes(this.roleQuery, this.currentScope);
|
|
32
37
|
// this.modelPermissionQuery = getModelPermissionModelQuery(this.modelPermissionClassName)
|
|
33
38
|
this.modelPermissionTable = this.modelPermissionClassName.table;
|
|
34
39
|
this.modelRoleQuery = getModelRoleModelQuery(this.modelRoleClassName);
|
|
@@ -110,14 +115,20 @@ export default class RolesService extends BaseService {
|
|
|
110
115
|
}
|
|
111
116
|
async revokeAll(roles, model) {
|
|
112
117
|
const { slugs, ids } = this.formatListStringNumbers(roles);
|
|
113
|
-
|
|
118
|
+
const q = this.modelRoleQuery
|
|
114
119
|
.leftJoin(this.roleTable + ' as r', 'r.id', '=', this.modelRoleTable + '.role_id')
|
|
115
120
|
.where('model_type', this.map.getAlias(model))
|
|
116
121
|
.where('model_id', model.getModelId())
|
|
117
122
|
.where((query) => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
if (slugs.length) {
|
|
124
|
+
query.orWhereIn('r.slug', slugs);
|
|
125
|
+
}
|
|
126
|
+
if (ids.length) {
|
|
127
|
+
query.orWhereIn('r.id', ids);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
this.applyModelRoleScopes(q, 'r', this.currentScope);
|
|
131
|
+
await q.delete();
|
|
121
132
|
return true;
|
|
122
133
|
}
|
|
123
134
|
async extractRoleModel(roles) {
|
|
@@ -142,4 +153,10 @@ export default class RolesService extends BaseService {
|
|
|
142
153
|
flush(modelType, modelId) {
|
|
143
154
|
return this.modelRoleQuery.where('model_type', modelType).where('model_id', modelId).delete();
|
|
144
155
|
}
|
|
156
|
+
applyScopes(q, scope) {
|
|
157
|
+
q.where(this.roleTable + '.scope', scope);
|
|
158
|
+
}
|
|
159
|
+
applyModelRoleScopes(q, table, scope) {
|
|
160
|
+
q.where(table + '.scope', scope);
|
|
161
|
+
}
|
|
145
162
|
}
|
package/build/src/types.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { LucidModel } from '@adonisjs/lucid/types/model';
|
|
2
2
|
import { DateTime } from 'luxon';
|
|
3
|
+
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
4
|
+
import { Scope } from './scope.js';
|
|
3
5
|
export interface AclModelInterface {
|
|
4
6
|
getModelId(): number;
|
|
5
7
|
}
|
|
@@ -60,6 +62,7 @@ export interface ModelPermissionsQuery extends AclModelQuery {
|
|
|
60
62
|
directPermissions: boolean;
|
|
61
63
|
includeForbiddings: boolean;
|
|
62
64
|
entity: Entity;
|
|
65
|
+
throughRoles: boolean;
|
|
63
66
|
}
|
|
64
67
|
export interface MorphMapInterface {
|
|
65
68
|
[key: string]: any;
|
|
@@ -72,10 +75,28 @@ export interface MorphInterface {
|
|
|
72
75
|
getAlias(target: any): string;
|
|
73
76
|
}
|
|
74
77
|
export interface ModelManagerInterface {
|
|
75
|
-
[key: string]:
|
|
78
|
+
[key: string]: any;
|
|
76
79
|
}
|
|
77
80
|
export interface Permissions {
|
|
78
81
|
tables: Object;
|
|
79
82
|
morphMaps: Object;
|
|
80
83
|
}
|
|
84
|
+
export interface ScopeInterface {
|
|
85
|
+
set(scope: number): ScopeInterface;
|
|
86
|
+
get(): number;
|
|
87
|
+
default(): number;
|
|
88
|
+
}
|
|
89
|
+
export interface ModelManagerBindings {
|
|
90
|
+
scope: typeof Scope;
|
|
91
|
+
role: typeof BaseModel;
|
|
92
|
+
permission: typeof BaseModel;
|
|
93
|
+
modelRole: typeof BaseModel;
|
|
94
|
+
modelPermission: typeof BaseModel;
|
|
95
|
+
}
|
|
96
|
+
export interface AclMiddlewareOptions {
|
|
97
|
+
role: string;
|
|
98
|
+
permission: string;
|
|
99
|
+
scope: number;
|
|
100
|
+
method: string;
|
|
101
|
+
}
|
|
81
102
|
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{{{
|
|
2
|
+
exports({ to: app.middlewarePath('', 'acl_middleware.ts') })
|
|
3
|
+
}}}
|
|
4
|
+
import type { HttpContext } from '@adonisjs/core/http'
|
|
5
|
+
import type { NextFn } from '@adonisjs/core/types/http'
|
|
6
|
+
import { AclManager, Scope } from '@holoyan/adonisjs-permissions'
|
|
7
|
+
|
|
8
|
+
declare module '@adonisjs/core/http' {
|
|
9
|
+
export interface HttpContext {
|
|
10
|
+
acl: AclManager
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default class UserScopeMiddleware {
|
|
15
|
+
//@ts-ignore
|
|
16
|
+
async handle(ctx: HttpContext, next: NextFn) {
|
|
17
|
+
const scope = new Scope()
|
|
18
|
+
ctx.acl = new AclManager().scope(scope)
|
|
19
|
+
/**
|
|
20
|
+
* Call next method in the pipeline and return its output
|
|
21
|
+
*/
|
|
22
|
+
const output = await next()
|
|
23
|
+
return output
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -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()
|