@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 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
- const read = await Permission.create({
192
- slug:'read',
198
+ // or create using Acl (recomended way)
199
+ const read = await Acl.permission().create({
200
+ slug: 'read',
193
201
  })
194
202
 
195
- const delete = await Permission.create({
196
- slug:'delete',
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
- const manager = await Role.create({
206
- slug:'manager',
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 permissions not available
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.assignDirectPermission(permission, target);
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
- query(): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, import("../../types.js").PermissionModel<import("@adonisjs/lucid/types/model").LucidModel>>;
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
- query(): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel, import("../../types.js").RoleModel<import("@adonisjs/lucid/types/model").LucidModel>>;
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
- query.whereIn('r.id', ids).orWhereIn('r.slug', slugs);
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.roles'), (table) => {
14
- table.increments('id')
12
+ this.schema.createTable(config.get('permissions.permissionsConfig.tables.permissions'), (table) => {
13
+ table.bigIncrements('id')
15
14
 
16
- table.string('slug').index()
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.unique(['slug', 'scope'])
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.modelRoles'), (table) => {
34
- table.increments('id')
32
+ this.schema.createTable(config.get('permissions.permissionsConfig.tables.roles'), (table) => {
33
+ table.bigIncrements('id')
35
34
 
36
- table.string('model_type')
37
- table.bigint('model_id').unsigned()
38
- table.bigInteger('role_id').unsigned()
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(['model_type', 'model_id'])
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.permissions'), (table) => {
52
- table.increments('id')
52
+ this.schema.createTable(config.get('permissions.permissionsConfig.tables.modelRoles'), (table) => {
53
+ table.bigIncrements('id')
53
54
 
54
- table.string('slug').index()
55
- table.string('title').nullable()
56
- table.string('entity_type').defaultTo('*')
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.unique(['slug', 'scope'])
68
- table.index(['entity_type', 'entity_id'])
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.increments('id')
71
+ table.bigIncrements('id')
73
72
 
74
73
  table.string('model_type')
75
74
  table.bigint('model_id').unsigned()
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@holoyan/adonisjs-permissions",
3
3
  "description": "Adonisjs roles and permissions system",
4
- "version": "0.6.4",
4
+ "version": "0.6.8",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },