@holoyan/adonisjs-permissions 1.3.0 → 1.3.1
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 +17 -2
- package/build/src/mixins/has_permissions.d.ts +6 -0
- package/build/src/mixins/has_permissions.js +8 -0
- package/build/src/services/helper.d.ts +5 -0
- package/build/src/services/helper.js +7 -0
- package/build/src/services/models/model_has_role_permissions.d.ts +18 -0
- package/build/src/services/models/model_has_role_permissions.js +25 -0
- package/build/src/services/permissions/permissions_service.d.ts +5 -0
- package/build/src/services/permissions/permissions_service.js +25 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,8 +14,8 @@ Checkout other AdonisJS packages
|
|
|
14
14
|
|
|
15
15
|
## Release Notes
|
|
16
16
|
|
|
17
|
-
Version: >= v1.3.
|
|
18
|
-
* Added [
|
|
17
|
+
Version: >= v1.3.1
|
|
18
|
+
* Added [canPartially](#checking-partial-permissions) method
|
|
19
19
|
|
|
20
20
|
## Table of Contents
|
|
21
21
|
|
|
@@ -504,6 +504,21 @@ await Acl.role(role).hasAnyPermission(['update', 'read'])
|
|
|
504
504
|
|
|
505
505
|
```
|
|
506
506
|
|
|
507
|
+
### Checking partial permissions
|
|
508
|
+
|
|
509
|
+
Sometimes you might want to check if a user has a specific permission on any instance of a model class, rather than checking for global permissions or permissions on a specific instance. For this purpose, you can use the `canPartially` method:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
|
|
513
|
+
const postWithId = await Post.find(id)
|
|
514
|
+
await Acl.model(user).allow('create', postWithId) // allow 'create' on post instance
|
|
515
|
+
|
|
516
|
+
// This is useful when you want to know if a user has permission on at least one instance
|
|
517
|
+
Acl.model(user).can('create') // will return false
|
|
518
|
+
Acl.model(user).can('create', Post) // will return false
|
|
519
|
+
Acl.model(user).canPartially('create', Post) // will return true because user has a 'create' permission on postWithId instance
|
|
520
|
+
```
|
|
521
|
+
|
|
507
522
|
### Middleware
|
|
508
523
|
|
|
509
524
|
You are free to do your check anywhere, for example we can create [named](https://docs.adonisjs.com/guides/middleware#named-middleware-collection) middleware and do checking
|
|
@@ -142,6 +142,12 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
|
|
|
142
142
|
*/
|
|
143
143
|
canAll(permissions: string[], target?: AclModel | Function): Promise<boolean>;
|
|
144
144
|
canAny(permissions: string[], target?: AclModel | Function): Promise<boolean>;
|
|
145
|
+
/**
|
|
146
|
+
* Check if a model has permission on any instance of a model class
|
|
147
|
+
* @param permission
|
|
148
|
+
* @param targetClass
|
|
149
|
+
*/
|
|
150
|
+
canPartially(permission: string, targetClass: Function): Promise<boolean>;
|
|
145
151
|
/**
|
|
146
152
|
* Check if model has any permission
|
|
147
153
|
* @param permission
|
|
@@ -204,6 +204,14 @@ export function hasPermissions() {
|
|
|
204
204
|
canAny(permissions, target) {
|
|
205
205
|
return Acl.model(this).canAny(permissions, target);
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Check if a model has permission on any instance of a model class
|
|
209
|
+
* @param permission
|
|
210
|
+
* @param targetClass
|
|
211
|
+
*/
|
|
212
|
+
canPartially(permission, targetClass) {
|
|
213
|
+
return Acl.model(this).canPartially(permission, targetClass);
|
|
214
|
+
}
|
|
207
215
|
/**
|
|
208
216
|
* Check if model has any permission
|
|
209
217
|
* @param permission
|
|
@@ -22,3 +22,8 @@ export declare function destructTarget(map: MorphInterface, target?: AclModel |
|
|
|
22
22
|
targetId: ModelIdType | null;
|
|
23
23
|
};
|
|
24
24
|
export declare function applyTargetRestriction(table: string, q: ManyToManySubQueryBuilderContract<typeof Permission> | ModelQueryBuilderContract<typeof Permission, PermissionInterface> | RelationSubQueryBuilderContract<typeof ModelRole>, entityType: string | null, entityId: ModelIdType | null): void;
|
|
25
|
+
/**
|
|
26
|
+
* Apply target restriction for partial permission checks
|
|
27
|
+
* This function doesn't check entity_id when only entityType is provided
|
|
28
|
+
*/
|
|
29
|
+
export declare function applyPartialTargetRestriction(table: string, q: ManyToManySubQueryBuilderContract<typeof Permission> | ModelQueryBuilderContract<typeof Permission, PermissionInterface> | RelationSubQueryBuilderContract<typeof ModelRole>, entityType: string): void;
|
|
@@ -80,3 +80,10 @@ export function applyTargetRestriction(table, q, entityType, entityId) {
|
|
|
80
80
|
q.where(table + '.entity_type', '*').whereNull(table + '.entity_id');
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Apply target restriction for partial permission checks
|
|
85
|
+
* This function doesn't check entity_id when only entityType is provided
|
|
86
|
+
*/
|
|
87
|
+
export function applyPartialTargetRestriction(table, q, entityType) {
|
|
88
|
+
q.where(table + '.entity_type', entityType).whereNotNull(table + '.entity_id');
|
|
89
|
+
}
|
|
@@ -102,6 +102,24 @@ export declare class ModelHasRolePermissions extends BaseAdapter {
|
|
|
102
102
|
can(permission: string, target?: AclModel | Function): Promise<boolean>;
|
|
103
103
|
canAll(permissions: string[], target?: AclModel | Function): Promise<boolean>;
|
|
104
104
|
canAny(permissions: string[], target?: AclModel | Function): Promise<boolean>;
|
|
105
|
+
/**
|
|
106
|
+
* Check if model has permission on any instance of a model class
|
|
107
|
+
* @param permission
|
|
108
|
+
* @param targetClass
|
|
109
|
+
*/
|
|
110
|
+
hasPartialPermission(permission: string, targetClass: Function): Promise<boolean>;
|
|
111
|
+
/**
|
|
112
|
+
* Check if model has any of the permissions on any instance of a model class
|
|
113
|
+
* @param permissions
|
|
114
|
+
* @param targetClass
|
|
115
|
+
*/
|
|
116
|
+
hasAnyPartialPermission(permissions: string[], targetClass: Function): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Check if a model has permission on any instance of a model class
|
|
119
|
+
* @param permission
|
|
120
|
+
* @param targetClass
|
|
121
|
+
*/
|
|
122
|
+
canPartially(permission: string, targetClass: Function): Promise<boolean>;
|
|
105
123
|
/**
|
|
106
124
|
* calls assignDirectAllPermissions()
|
|
107
125
|
* @param permission
|
|
@@ -213,6 +213,31 @@ export class ModelHasRolePermissions extends BaseAdapter {
|
|
|
213
213
|
canAny(permissions, target) {
|
|
214
214
|
return this.hasAnyPermission(permissions, target);
|
|
215
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Check if model has permission on any instance of a model class
|
|
218
|
+
* @param permission
|
|
219
|
+
* @param targetClass
|
|
220
|
+
*/
|
|
221
|
+
async hasPartialPermission(permission, targetClass) {
|
|
222
|
+
return this.hasAnyPartialPermission([permission], targetClass);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check if model has any of the permissions on any instance of a model class
|
|
226
|
+
* @param permissions
|
|
227
|
+
* @param targetClass
|
|
228
|
+
*/
|
|
229
|
+
async hasAnyPartialPermission(permissions, targetClass) {
|
|
230
|
+
const entityType = this.map.getAlias(targetClass);
|
|
231
|
+
return await this.permissionService.hasAnyPartial(this.map.getAlias(this.model), this.model.getModelId(), permissions, entityType);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Check if a model has permission on any instance of a model class
|
|
235
|
+
* @param permission
|
|
236
|
+
* @param targetClass
|
|
237
|
+
*/
|
|
238
|
+
canPartially(permission, targetClass) {
|
|
239
|
+
return this.hasPartialPermission(permission, targetClass);
|
|
240
|
+
}
|
|
216
241
|
/**
|
|
217
242
|
* calls assignDirectAllPermissions()
|
|
218
243
|
* @param permission
|
|
@@ -57,6 +57,10 @@ export default class PermissionsService extends BaseService {
|
|
|
57
57
|
* has any of permissions
|
|
58
58
|
*/
|
|
59
59
|
hasAny(modelType: string, modelId: ModelIdType, permission: string[], entityType: string | null, entityId: ModelIdType | null): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* has any of permissions on any instance of a model class
|
|
62
|
+
*/
|
|
63
|
+
hasAnyPartial(modelType: string, modelId: ModelIdType, permissions: string[], entityType: string): Promise<boolean>;
|
|
60
64
|
/**
|
|
61
65
|
* has all permissions
|
|
62
66
|
*/
|
|
@@ -109,6 +113,7 @@ export default class PermissionsService extends BaseService {
|
|
|
109
113
|
reverseModelPermissionQuery(conditions: Partial<ModelPermissionsQuery>): ModelQueryBuilderContract<typeof import("../../models/model_permission.js").default, import("../../models/model_permission.js").default>;
|
|
110
114
|
findAssignableEntity(permission: string[], entityClass: string | null, entityId: ModelIdType | null, allowed: boolean): ModelQueryBuilderContract<typeof Permission, Permission>;
|
|
111
115
|
private applyTargetRestriction;
|
|
116
|
+
private applyPartialTargetRestriction;
|
|
112
117
|
private applyScopes;
|
|
113
118
|
private applyModelPermissionScopes;
|
|
114
119
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import BaseService from '../base_service.js';
|
|
2
|
-
import { applyTargetRestriction } from '../helper.js';
|
|
2
|
+
import { applyTargetRestriction, applyPartialTargetRestriction } from '../helper.js';
|
|
3
3
|
export default class PermissionsService extends BaseService {
|
|
4
4
|
options;
|
|
5
5
|
scope;
|
|
@@ -204,6 +204,27 @@ export default class PermissionsService extends BaseService {
|
|
|
204
204
|
const r = await q.distinct(this.permissionTable + '.id').select(this.permissionTable + '.id');
|
|
205
205
|
return r.length > 0;
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* has any of permissions on any instance of a model class
|
|
209
|
+
*/
|
|
210
|
+
async hasAnyPartial(modelType, modelId, permissions, entityType) {
|
|
211
|
+
const { slugs, ids } = this.formatList(permissions);
|
|
212
|
+
const q = this.modelPermissionQueryWithForbiddenCheck({
|
|
213
|
+
modelType,
|
|
214
|
+
modelId,
|
|
215
|
+
directPermissions: this.map.getAlias(this.roleClassName) === modelType,
|
|
216
|
+
permissionSlugs: slugs,
|
|
217
|
+
permissionIds: ids,
|
|
218
|
+
entity: {
|
|
219
|
+
type: entityType,
|
|
220
|
+
id: null,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
// We use applyPartialTargetRestriction which doesn't check entity_id when only entityType is provided
|
|
224
|
+
this.applyPartialTargetRestriction(this.permissionTable, q, entityType);
|
|
225
|
+
const r = await q.distinct(this.permissionTable + '.id').select(this.permissionTable + '.id');
|
|
226
|
+
return r.length > 0;
|
|
227
|
+
}
|
|
207
228
|
/**
|
|
208
229
|
* has all permissions
|
|
209
230
|
*/
|
|
@@ -496,6 +517,9 @@ export default class PermissionsService extends BaseService {
|
|
|
496
517
|
applyTargetRestriction(table, q, entityType, entityId) {
|
|
497
518
|
applyTargetRestriction(table, q, entityType, entityId);
|
|
498
519
|
}
|
|
520
|
+
applyPartialTargetRestriction(table, q, entityType) {
|
|
521
|
+
applyPartialTargetRestriction(table, q, entityType);
|
|
522
|
+
}
|
|
499
523
|
applyScopes(q) {
|
|
500
524
|
q.where(this.permissionTable + '.scope', this.scope.get());
|
|
501
525
|
}
|