@holoyan/adonisjs-permissions 1.2.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 CHANGED
@@ -14,8 +14,8 @@ Checkout other AdonisJS packages
14
14
 
15
15
  ## Release Notes
16
16
 
17
- Version: >= v1.2.0
18
- * Added [Morph Map](https://github.com/holoyan/morph-map-js) as a dependency to handle polymorphic relations - fixed [#20](https://github.com/holoyan/adonisjs-permissions/issues/20)
17
+ Version: >= v1.3.1
18
+ * Added [canPartially](#checking-partial-permissions) method
19
19
 
20
20
  ## Table of Contents
21
21
 
@@ -25,6 +25,8 @@ Version: >= v1.2.0
25
25
  - [Installation](#installation)
26
26
  - [Configuration](#configuration)
27
27
  - [Mixins](#mixins)
28
+ - [hasPermissions](#haspermissions-mixin)
29
+ - [permissionQueryHelpers](#permissionqueryhelpers-mixin)
28
30
  - [Support](#support)
29
31
  - [Database support](#database-support)
30
32
  - [UUID support](#uuid-support)
@@ -143,6 +145,8 @@ export default class Post extends BaseModel implements AclModelInterface {
143
145
 
144
146
  ## Mixins
145
147
 
148
+ ### hasPermissions mixin
149
+
146
150
  If you want to be able to call `Acl` methods on a `User` model then consider using `hasPermissions` mixin
147
151
 
148
152
  ```typescript
@@ -172,6 +176,61 @@ await user.allow('edit') // give edit permission
172
176
 
173
177
  ```
174
178
 
179
+
180
+ ### permissionQueryHelpers mixin
181
+
182
+ Sometimes you might want to get all users who have a specific permission, for that you can use `permissionQueryHelpers` mixin
183
+
184
+ ```typescript
185
+
186
+ import { permissionQueryHelpers } from '@holoyan/adonisjs-permissions'
187
+
188
+
189
+ @MorphMap('users')
190
+ export default class User extends compose(BaseModel, permissionQueryHelpers()) implements AclModelInterface {
191
+ getModelId(): number {
192
+ return this.id
193
+ }
194
+ // other code goes here
195
+
196
+ // name your scopes whatever you want, make sure to call query helper methods inside the scope
197
+ static whereRoles = scope((query, ...roles: string[]) => {
198
+ // all users who have roles
199
+ new User()._whereRoles(query, User, ...roles)
200
+ })
201
+
202
+ static whereDirectPermissions = scope(
203
+ (query, permissions: string[], target?: AclModel | Function) => {
204
+ // all users who have direct assigned permissions
205
+ new User()._whereDirectPermissions(query, User, permissions, target)
206
+ }
207
+ )
208
+
209
+ static whereRolePermissions = scope(
210
+ (query, permissions: string[], target?: AclModel | Function) => {
211
+ // all users who have permissions assigned through the role
212
+ new User()._whereRolePermissions(query, User, permissions, target)
213
+ }
214
+ )
215
+
216
+ static wherePermissions = scope((query, permissions: string[], target?: AclModel | Function) => {
217
+ // all users who have permissions assigned directly or through the role
218
+ new User()._wherePermissions(query, User, permissions, target)
219
+ })
220
+ }
221
+
222
+ ```
223
+
224
+ And to get all users who have `edit` permission, you can do that like this
225
+
226
+ ```typescript
227
+
228
+ const users = await User.query().withScopes((scopes) => {
229
+ scopes.wherePermissions(['edit'])
230
+ })
231
+
232
+ ```
233
+
175
234
  ## Support
176
235
 
177
236
  ### Database Support
@@ -445,6 +504,21 @@ await Acl.role(role).hasAnyPermission(['update', 'read'])
445
504
 
446
505
  ```
447
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
+
448
522
  ### Middleware
449
523
 
450
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
@@ -1273,6 +1347,7 @@ await Acl.permission(myPermission).detachFromRole(role_slug)
1273
1347
  - [X] Scopes (Multitenancy)
1274
1348
  - [X] UUID support
1275
1349
  - [X] Events
1350
+ - [X] Query helpers
1276
1351
  - [ ] More test coverage
1277
1352
  - [ ] Caching
1278
1353
  - [ ] Integration with AdonisJs Bouncer
package/build/index.d.ts CHANGED
@@ -10,5 +10,5 @@ export { configure } from './configure.js';
10
10
  export { stubsRoot } from './stubs/main.js';
11
11
  export { AclManager, Acl } from './src/acl.js';
12
12
  export { MorphMap, getClassPath } from './src/decorators.js';
13
- export { hasPermissions } from './src/mixins/has_permissions.js';
13
+ export { hasPermissions, permissionQueryHelpers } from './src/mixins/has_permissions.js';
14
14
  export { Scope } from './src/scope.js';
package/build/index.js CHANGED
@@ -18,5 +18,5 @@ export { configure } from './configure.js';
18
18
  export { stubsRoot } from './stubs/main.js';
19
19
  export { AclManager, Acl } from './src/acl.js';
20
20
  export { MorphMap, getClassPath } from './src/decorators.js';
21
- export { hasPermissions } from './src/mixins/has_permissions.js';
21
+ export { hasPermissions, permissionQueryHelpers } from './src/mixins/has_permissions.js';
22
22
  export { Scope } from './src/scope.js';
@@ -1,13 +1,18 @@
1
1
  import type { NormalizeConstructor } from '@adonisjs/core/types/helpers';
2
2
  import { BaseModel } from '@adonisjs/lucid/orm';
3
3
  import { AclModel, ModelIdType } from '../types.js';
4
+ import type { ManyToMany, HasMany } from '@adonisjs/lucid/types/relations';
5
+ import Role from '../models/role.js';
6
+ import { LucidModel, LucidRow, ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
7
+ import { ModelRole, Permission } from '../../index.js';
8
+ import ModelPermission from '../models/model_permission.js';
4
9
  export declare function hasPermissions(): <Model extends NormalizeConstructor<typeof BaseModel>>(superclass: Model) => {
5
10
  new (...args: any[]): {
6
11
  getModelId(): ModelIdType;
7
12
  /**
8
13
  * returns list of roles assigned to the model
9
14
  */
10
- roles(): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<typeof import("../models/role.js").default, import("../models/role.js").default>;
15
+ roles(): ModelQueryBuilderContract<typeof Role, Role>;
11
16
  /**
12
17
  * Check if model has role
13
18
  * @param role
@@ -137,18 +142,24 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
137
142
  */
138
143
  canAll(permissions: string[], target?: AclModel | Function): Promise<boolean>;
139
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>;
140
151
  /**
141
152
  * Check if model has any permission
142
153
  * @param permission
143
154
  * @param target
144
155
  */
145
- assignDirectPermission(permission: string, target?: AclModel | Function): Promise<import("../models/model_permission.js").default[]>;
156
+ assignDirectPermission(permission: string, target?: AclModel | Function): Promise<ModelPermission[]>;
146
157
  /**
147
158
  * Allow permission for model
148
159
  * @param permission
149
160
  * @param target
150
161
  */
151
- allow(permission: string, target?: AclModel | Function): Promise<import("../models/model_permission.js").default[]>;
162
+ allow(permission: string, target?: AclModel | Function): Promise<ModelPermission[]>;
152
163
  /**
153
164
  * Revoke permission from model
154
165
  * @param permission
@@ -185,7 +196,7 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
185
196
  * @param permissions
186
197
  * @param target
187
198
  */
188
- syncPermissions(permissions: string[], target?: AclModel | Function): Promise<import("../models/model_permission.js").default[]>;
199
+ syncPermissions(permissions: string[], target?: AclModel | Function): Promise<ModelPermission[]>;
189
200
  /**
190
201
  * Forbid permission for model
191
202
  * @param permission
@@ -214,7 +225,152 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
214
225
  $extras: import("@adonisjs/lucid/types/model").ModelObject;
215
226
  $original: import("@adonisjs/lucid/types/model").ModelObject;
216
227
  $preloaded: {
217
- [relation: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
228
+ [relation: string]: LucidRow | LucidRow[];
229
+ };
230
+ $columns: undefined;
231
+ $sideloaded: import("@adonisjs/lucid/types/model").ModelObject;
232
+ $primaryKeyValue?: number | string;
233
+ $isPersisted: boolean;
234
+ $isNew: boolean;
235
+ $isLocal: boolean;
236
+ $dirty: import("@adonisjs/lucid/types/model").ModelObject;
237
+ $isDirty: boolean;
238
+ $isDeleted: boolean;
239
+ $options?: import("@adonisjs/lucid/types/model").ModelOptions;
240
+ $trx?: import("@adonisjs/lucid/types/database").TransactionClientContract;
241
+ $setOptionsAndTrx(options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): void;
242
+ useTransaction(trx: import("@adonisjs/lucid/types/database").TransactionClientContract): /*elided*/ any;
243
+ useConnection(connection: string): /*elided*/ any;
244
+ $getQueryFor(action: "insert", client: import("@adonisjs/lucid/types/database").QueryClientContract): ReturnType<import("@adonisjs/lucid/types/database").QueryClientContract["insertQuery"]>;
245
+ $getQueryFor(action: "update" | "delete" | "refresh", client: import("@adonisjs/lucid/types/database").QueryClientContract): ModelQueryBuilderContract<LucidModel>;
246
+ $setAttribute(key: string, value: any): void;
247
+ $getAttribute(key: string): any;
248
+ $getAttributeFromCache(key: string, callback: import("@adonisjs/lucid/types/model").CacheNode["getter"]): any;
249
+ $hasRelated(key: string): boolean;
250
+ $setRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<LucidRow> | null): void;
251
+ $pushRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<LucidRow> | null): void;
252
+ $getRelated(key: string, defaultValue?: any): import("@adonisjs/lucid/types/querybuilder").OneOrMany<LucidRow> | undefined | null;
253
+ $consumeAdapterResult(adapterResult: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject): void;
254
+ $hydrateOriginals(): void;
255
+ fill(value: Partial<{}>, allowExtraProperties?: boolean): /*elided*/ any;
256
+ merge(value: Partial<{}>, allowExtraProperties?: boolean): /*elided*/ any;
257
+ isDirty(fields?: undefined[] | undefined): boolean;
258
+ enableForceUpdate(): /*elided*/ any;
259
+ save(): Promise</*elided*/ any>;
260
+ saveQuietly(): Promise</*elided*/ any>;
261
+ lockForUpdate<T>(callback: (user: /*elided*/ any) => T | Promise<T>): Promise<T>;
262
+ delete(): Promise<void>;
263
+ deleteQuietly(): Promise<void>;
264
+ refresh(): Promise</*elided*/ any>;
265
+ load: import("@adonisjs/lucid/types/model").LucidRowPreload</*elided*/ any>;
266
+ loadOnce: import("@adonisjs/lucid/types/model").LucidRowPreloadOnce</*elided*/ any>;
267
+ preload: import("@adonisjs/lucid/types/model").LucidRowPreload</*elided*/ any>;
268
+ loadAggregate: <Self extends /*elided*/ any, Name extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? Self[Name]["subQuery"] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
269
+ loadCount: <Self extends /*elided*/ any, Name_1 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder_1 = Self[Name_1] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? Self[Name_1]["subQuery"] : never>(name: Name_1, callback?: ((builder: RelatedBuilder_1) => void) | undefined) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
270
+ serializeAttributes(fields?: import("@adonisjs/lucid/types/model").CherryPickFields, raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
271
+ serializeComputed(fields?: import("@adonisjs/lucid/types/model").CherryPickFields): import("@adonisjs/lucid/types/model").ModelObject;
272
+ serializeRelations(fields: undefined, raw: true): {
273
+ [key: string]: LucidRow | LucidRow[];
274
+ };
275
+ serializeRelations(cherryPick: import("@adonisjs/lucid/types/model").CherryPick["relations"] | undefined, raw: false | undefined): import("@adonisjs/lucid/types/model").ModelObject;
276
+ serializeRelations(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick["relations"], raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
277
+ serialize(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick): import("@adonisjs/lucid/types/model").ModelObject;
278
+ toObject(): import("@adonisjs/lucid/types/model").ModelObject;
279
+ toJSON(): import("@adonisjs/lucid/types/model").ModelObject;
280
+ related<Name_2 extends undefined>(relation: Name_2): /*elided*/ any[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? /*elided*/ any[Name_2]["client"] : never;
281
+ };
282
+ find: <T extends LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
283
+ all: <T extends LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
284
+ namingStrategy: import("@adonisjs/lucid/types/model").NamingStrategyContract;
285
+ connection?: string | undefined;
286
+ readonly booted: boolean;
287
+ $columnsDefinitions: Map<string, import("@adonisjs/lucid/types/model").ModelColumnOptions>;
288
+ $relationsDefinitions: Map<string, import("@adonisjs/lucid/types/relations").RelationshipsContract>;
289
+ $computedDefinitions: Map<string, import("@adonisjs/lucid/types/model").ComputedOptions>;
290
+ primaryKey: string;
291
+ table: string;
292
+ selfAssignPrimaryKey: boolean;
293
+ $adapter: import("@adonisjs/lucid/types/model").AdapterContract;
294
+ useAdapter: (adapter: import("@adonisjs/lucid/types/model").AdapterContract) => void;
295
+ $hooks: import("@poppinss/hooks").default<any>;
296
+ $keys: {
297
+ attributesToColumns: import("@adonisjs/lucid/types/model").ModelKeysContract;
298
+ attributesToSerialized: import("@adonisjs/lucid/types/model").ModelKeysContract;
299
+ columnsToAttributes: import("@adonisjs/lucid/types/model").ModelKeysContract;
300
+ columnsToSerialized: import("@adonisjs/lucid/types/model").ModelKeysContract;
301
+ serializedToColumns: import("@adonisjs/lucid/types/model").ModelKeysContract;
302
+ serializedToAttributes: import("@adonisjs/lucid/types/model").ModelKeysContract;
303
+ };
304
+ $createFromAdapterResult: <T extends LucidModel>(this: T, result?: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => null | InstanceType<T>;
305
+ $createMultipleFromAdapterResult: <T extends LucidModel>(this: T, results: import("@adonisjs/lucid/types/model").ModelObject[], sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => InstanceType<T>[];
306
+ $addColumn: (name: string, options: Partial<import("@adonisjs/lucid/types/model").ColumnOptions>) => import("@adonisjs/lucid/types/model").ColumnOptions;
307
+ $hasColumn: (name: string) => boolean;
308
+ $getColumn: (name: string) => import("@adonisjs/lucid/types/model").ModelColumnOptions | undefined;
309
+ $addComputed: (name: string, options: Partial<import("@adonisjs/lucid/types/model").ComputedOptions>) => import("@adonisjs/lucid/types/model").ComputedOptions;
310
+ $hasComputed: (name: string) => boolean;
311
+ $getComputed: (name: string) => import("@adonisjs/lucid/types/model").ComputedOptions | undefined;
312
+ $addRelation: (name: string, type: import("@adonisjs/lucid/types/relations").ModelRelationTypes["__opaque_type"], relatedModel: () => LucidModel, options: import("@adonisjs/lucid/types/model").ModelRelationOptions) => void;
313
+ $hasRelation: (name: string) => boolean;
314
+ $getRelation: {
315
+ <Model_1 extends LucidModel, Name_2 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<InstanceType<Model_1>>>(this: Model_1, name: Name_2): InstanceType<Model_1>[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? InstanceType<Model_1>[Name_2]["client"]["relation"] : import("@adonisjs/lucid/types/relations").RelationshipsContract;
316
+ <Model_1 extends LucidModel>(this: Model_1, name: string): import("@adonisjs/lucid/types/relations").RelationshipsContract;
317
+ };
318
+ $defineProperty: <Model_1 extends LucidModel, Prop extends keyof Model_1>(this: Model_1, propertyName: Prop, defaultValue: Model_1[Prop], strategy: "inherit" | "define" | ((value: Model_1[Prop]) => Model_1[Prop])) => void;
319
+ boot: () => void;
320
+ before: {
321
+ <Model_1 extends LucidModel, Event extends "find" | "fetch">(this: Model_1, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<ModelQueryBuilderContract<Model_1>, Event>): void;
322
+ <Model_1 extends LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<[ModelQueryBuilderContract<Model_1>, ModelQueryBuilderContract<Model_1>], "paginate">): void;
323
+ <Model_1 extends LucidModel, Event_1 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_1, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_1>): void;
324
+ };
325
+ after: {
326
+ <Model_1 extends LucidModel>(this: Model_1, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>[], "fetch">): void;
327
+ <Model_1 extends LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelPaginatorContract<InstanceType<Model_1>>, "paginate">): void;
328
+ <Model_1 extends LucidModel, Event_2 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_2, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_2>): void;
329
+ };
330
+ create: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
331
+ createQuietly: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
332
+ createMany: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
333
+ createManyQuietly: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
334
+ findOrFail: <T extends LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
335
+ findBy: {
336
+ <T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
337
+ <T extends LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
338
+ };
339
+ findByOrFail: {
340
+ <T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
341
+ <T extends LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
342
+ };
343
+ findManyBy: {
344
+ <T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
345
+ <T extends LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
346
+ };
347
+ first: <T extends LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
348
+ firstOrFail: <T extends LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
349
+ findMany: <T extends LucidModel>(this: T, value: any[], options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
350
+ firstOrNew: <T extends LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
351
+ firstOrCreate: <T extends LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
352
+ updateOrCreate: <T extends LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, updatePayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
353
+ fetchOrNewUpMany: <T extends LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
354
+ fetchOrCreateMany: <T extends LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
355
+ updateOrCreateMany: <T extends LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
356
+ query: <Model_1 extends LucidModel, Result = InstanceType<Model_1>>(this: Model_1, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => ModelQueryBuilderContract<Model_1, Result>;
357
+ transaction: import("@adonisjs/lucid/types/database").TransactionFn;
358
+ truncate: (cascade?: boolean) => Promise<void>;
359
+ } & Model;
360
+ export declare function permissionQueryHelpers(): <Model extends NormalizeConstructor<typeof BaseModel>>(superclass: Model) => {
361
+ new (...args: any[]): {
362
+ _roles: ManyToMany<typeof Role>;
363
+ _whereRoles<TargetClass extends Model>(query: ModelQueryBuilderContract<LucidModel, LucidRow>, targetClass: TargetClass, ...roles: string[]): ModelQueryBuilderContract<LucidModel, LucidRow>;
364
+ _permissions: ManyToMany<typeof Permission>;
365
+ _whereDirectPermissions<TargetClass extends Model>(query: ModelQueryBuilderContract<LucidModel, LucidRow>, targetClass: TargetClass, permissions: string[], target?: AclModel | Function): ModelQueryBuilderContract<LucidModel, LucidRow>;
366
+ _model_roles: HasMany<typeof ModelRole>;
367
+ _whereRolePermissions<TargetClass extends Model>(query: ModelQueryBuilderContract<LucidModel, LucidRow>, targetClass: TargetClass, permissions: string[], target?: AclModel | Function): ModelQueryBuilderContract<LucidModel, LucidRow>;
368
+ _wherePermissions<TargetClass extends Model>(query: ModelQueryBuilderContract<LucidModel, LucidRow>, targetClass: TargetClass, permissions: string[], target?: AclModel | Function): void;
369
+ $attributes: import("@adonisjs/lucid/types/model").ModelObject;
370
+ $extras: import("@adonisjs/lucid/types/model").ModelObject;
371
+ $original: import("@adonisjs/lucid/types/model").ModelObject;
372
+ $preloaded: {
373
+ [relation: string]: LucidRow | LucidRow[];
218
374
  };
219
375
  $columns: undefined;
220
376
  $sideloaded: import("@adonisjs/lucid/types/model").ModelObject;
@@ -231,14 +387,14 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
231
387
  useTransaction(trx: import("@adonisjs/lucid/types/database").TransactionClientContract): /*elided*/ any;
232
388
  useConnection(connection: string): /*elided*/ any;
233
389
  $getQueryFor(action: "insert", client: import("@adonisjs/lucid/types/database").QueryClientContract): ReturnType<import("@adonisjs/lucid/types/database").QueryClientContract["insertQuery"]>;
234
- $getQueryFor(action: "update" | "delete" | "refresh", client: import("@adonisjs/lucid/types/database").QueryClientContract): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel>;
390
+ $getQueryFor(action: "update" | "delete" | "refresh", client: import("@adonisjs/lucid/types/database").QueryClientContract): ModelQueryBuilderContract<LucidModel>;
235
391
  $setAttribute(key: string, value: any): void;
236
392
  $getAttribute(key: string): any;
237
393
  $getAttributeFromCache(key: string, callback: import("@adonisjs/lucid/types/model").CacheNode["getter"]): any;
238
394
  $hasRelated(key: string): boolean;
239
- $setRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
240
- $pushRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
241
- $getRelated(key: string, defaultValue?: any): import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | undefined | null;
395
+ $setRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<LucidRow> | null): void;
396
+ $pushRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<LucidRow> | null): void;
397
+ $getRelated(key: string, defaultValue?: any): import("@adonisjs/lucid/types/querybuilder").OneOrMany<LucidRow> | undefined | null;
242
398
  $consumeAdapterResult(adapterResult: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject): void;
243
399
  $hydrateOriginals(): void;
244
400
  fill(value: Partial<{}>, allowExtraProperties?: boolean): /*elided*/ any;
@@ -254,22 +410,22 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
254
410
  load: import("@adonisjs/lucid/types/model").LucidRowPreload</*elided*/ any>;
255
411
  loadOnce: import("@adonisjs/lucid/types/model").LucidRowPreloadOnce</*elided*/ any>;
256
412
  preload: import("@adonisjs/lucid/types/model").LucidRowPreload</*elided*/ any>;
257
- loadAggregate: <Self extends /*elided*/ any, Name extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? Self[Name]["subQuery"] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
258
- loadCount: <Self extends /*elided*/ any, Name_1 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder_1 = Self[Name_1] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? Self[Name_1]["subQuery"] : never>(name: Name_1, callback?: ((builder: RelatedBuilder_1) => void) | undefined) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
413
+ loadAggregate: <Self extends /*elided*/ any, Name extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder = Self[Name] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? Self[Name]["subQuery"] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
414
+ loadCount: <Self extends /*elided*/ any, Name_1 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder_1 = Self[Name_1] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? Self[Name_1]["subQuery"] : never>(name: Name_1, callback?: ((builder: RelatedBuilder_1) => void) | undefined) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
259
415
  serializeAttributes(fields?: import("@adonisjs/lucid/types/model").CherryPickFields, raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
260
416
  serializeComputed(fields?: import("@adonisjs/lucid/types/model").CherryPickFields): import("@adonisjs/lucid/types/model").ModelObject;
261
417
  serializeRelations(fields: undefined, raw: true): {
262
- [key: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
418
+ [key: string]: LucidRow | LucidRow[];
263
419
  };
264
420
  serializeRelations(cherryPick: import("@adonisjs/lucid/types/model").CherryPick["relations"] | undefined, raw: false | undefined): import("@adonisjs/lucid/types/model").ModelObject;
265
421
  serializeRelations(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick["relations"], raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
266
422
  serialize(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick): import("@adonisjs/lucid/types/model").ModelObject;
267
423
  toObject(): import("@adonisjs/lucid/types/model").ModelObject;
268
424
  toJSON(): import("@adonisjs/lucid/types/model").ModelObject;
269
- related<Name_2 extends undefined>(relation: Name_2): /*elided*/ any[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? /*elided*/ any[Name_2]["client"] : never;
425
+ related<Name_2 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations</*elided*/ any>>(relation: Name_2): /*elided*/ any[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? /*elided*/ any[Name_2]["client"] : never;
270
426
  };
271
- find: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
272
- all: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
427
+ find: <T extends LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
428
+ all: <T extends LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
273
429
  namingStrategy: import("@adonisjs/lucid/types/model").NamingStrategyContract;
274
430
  connection?: string | undefined;
275
431
  readonly booted: boolean;
@@ -290,59 +446,59 @@ export declare function hasPermissions(): <Model extends NormalizeConstructor<ty
290
446
  serializedToColumns: import("@adonisjs/lucid/types/model").ModelKeysContract;
291
447
  serializedToAttributes: import("@adonisjs/lucid/types/model").ModelKeysContract;
292
448
  };
293
- $createFromAdapterResult: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, result?: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => null | InstanceType<T>;
294
- $createMultipleFromAdapterResult: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, results: import("@adonisjs/lucid/types/model").ModelObject[], sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => InstanceType<T>[];
449
+ $createFromAdapterResult: <T extends LucidModel>(this: T, result?: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => null | InstanceType<T>;
450
+ $createMultipleFromAdapterResult: <T extends LucidModel>(this: T, results: import("@adonisjs/lucid/types/model").ModelObject[], sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => InstanceType<T>[];
295
451
  $addColumn: (name: string, options: Partial<import("@adonisjs/lucid/types/model").ColumnOptions>) => import("@adonisjs/lucid/types/model").ColumnOptions;
296
452
  $hasColumn: (name: string) => boolean;
297
453
  $getColumn: (name: string) => import("@adonisjs/lucid/types/model").ModelColumnOptions | undefined;
298
454
  $addComputed: (name: string, options: Partial<import("@adonisjs/lucid/types/model").ComputedOptions>) => import("@adonisjs/lucid/types/model").ComputedOptions;
299
455
  $hasComputed: (name: string) => boolean;
300
456
  $getComputed: (name: string) => import("@adonisjs/lucid/types/model").ComputedOptions | undefined;
301
- $addRelation: (name: string, type: import("@adonisjs/lucid/types/relations").ModelRelationTypes["__opaque_type"], relatedModel: () => import("@adonisjs/lucid/types/model").LucidModel, options: import("@adonisjs/lucid/types/model").ModelRelationOptions) => void;
457
+ $addRelation: (name: string, type: import("@adonisjs/lucid/types/relations").ModelRelationTypes["__opaque_type"], relatedModel: () => LucidModel, options: import("@adonisjs/lucid/types/model").ModelRelationOptions) => void;
302
458
  $hasRelation: (name: string) => boolean;
303
459
  $getRelation: {
304
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Name_2 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<InstanceType<Model_1>>>(this: Model_1, name: Name_2): InstanceType<Model_1>[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? InstanceType<Model_1>[Name_2]["client"]["relation"] : import("@adonisjs/lucid/types/relations").RelationshipsContract;
305
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, name: string): import("@adonisjs/lucid/types/relations").RelationshipsContract;
460
+ <Model_1 extends LucidModel, Name_2 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<InstanceType<Model_1>>>(this: Model_1, name: Name_2): InstanceType<Model_1>[Name_2] extends import("@adonisjs/lucid/types/relations").ModelRelations<LucidModel, LucidModel> ? InstanceType<Model_1>[Name_2]["client"]["relation"] : import("@adonisjs/lucid/types/relations").RelationshipsContract;
461
+ <Model_1 extends LucidModel>(this: Model_1, name: string): import("@adonisjs/lucid/types/relations").RelationshipsContract;
306
462
  };
307
- $defineProperty: <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Prop extends keyof Model_1>(this: Model_1, propertyName: Prop, defaultValue: Model_1[Prop], strategy: "inherit" | "define" | ((value: Model_1[Prop]) => Model_1[Prop])) => void;
463
+ $defineProperty: <Model_1 extends LucidModel, Prop extends keyof Model_1>(this: Model_1, propertyName: Prop, defaultValue: Model_1[Prop], strategy: "inherit" | "define" | ((value: Model_1[Prop]) => Model_1[Prop])) => void;
308
464
  boot: () => void;
309
465
  before: {
310
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Event extends "find" | "fetch">(this: Model_1, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1>, Event>): void;
311
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<[import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1>, import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1>], "paginate">): void;
312
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Event_1 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_1, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_1>): void;
466
+ <Model_1 extends LucidModel, Event extends "find" | "fetch">(this: Model_1, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<ModelQueryBuilderContract<Model_1>, Event>): void;
467
+ <Model_1 extends LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<[ModelQueryBuilderContract<Model_1>, ModelQueryBuilderContract<Model_1>], "paginate">): void;
468
+ <Model_1 extends LucidModel, Event_1 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_1, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_1>): void;
313
469
  };
314
470
  after: {
315
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>[], "fetch">): void;
316
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelPaginatorContract<InstanceType<Model_1>>, "paginate">): void;
317
- <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Event_2 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_2, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_2>): void;
471
+ <Model_1 extends LucidModel>(this: Model_1, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>[], "fetch">): void;
472
+ <Model_1 extends LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelPaginatorContract<InstanceType<Model_1>>, "paginate">): void;
473
+ <Model_1 extends LucidModel, Event_2 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_2, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_2>): void;
318
474
  };
319
- create: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
320
- createQuietly: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
321
- createMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
322
- createManyQuietly: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
323
- findOrFail: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
475
+ create: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
476
+ createQuietly: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
477
+ createMany: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
478
+ createManyQuietly: <T extends LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
479
+ findOrFail: <T extends LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
324
480
  findBy: {
325
- <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
326
- <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
481
+ <T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
482
+ <T extends LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
327
483
  };
328
484
  findByOrFail: {
329
- <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
330
- <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
485
+ <T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
486
+ <T extends LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
331
487
  };
332
488
  findManyBy: {
333
- <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
334
- <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
489
+ <T extends LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
490
+ <T extends LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
335
491
  };
336
- first: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
337
- firstOrFail: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
338
- findMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any[], options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
339
- firstOrNew: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
340
- firstOrCreate: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
341
- updateOrCreate: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, updatePayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
342
- fetchOrNewUpMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
343
- fetchOrCreateMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
344
- updateOrCreateMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
345
- query: <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Result = InstanceType<Model_1>>(this: Model_1, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1, Result>;
492
+ first: <T extends LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
493
+ firstOrFail: <T extends LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
494
+ findMany: <T extends LucidModel>(this: T, value: any[], options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
495
+ firstOrNew: <T extends LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
496
+ firstOrCreate: <T extends LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
497
+ updateOrCreate: <T extends LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, updatePayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
498
+ fetchOrNewUpMany: <T extends LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
499
+ fetchOrCreateMany: <T extends LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
500
+ updateOrCreateMany: <T extends LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
501
+ query: <Model_1 extends LucidModel, Result = InstanceType<Model_1>>(this: Model_1, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => ModelQueryBuilderContract<Model_1, Result>;
346
502
  transaction: import("@adonisjs/lucid/types/database").TransactionFn;
347
503
  truncate: (cascade?: boolean) => Promise<void>;
348
504
  } & Model;
@@ -1,4 +1,16 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { manyToMany, hasMany } from '@adonisjs/lucid/orm';
1
8
  import { Acl } from '../acl.js';
9
+ import Role from '../models/role.js';
10
+ import { ModelRole, Permission } from '../../index.js';
11
+ import ModelPermission from '../models/model_permission.js';
12
+ import { morphMap } from '@holoyan/morph-map-js';
13
+ import { applyTargetRestriction, destructTarget } from '../services/helper.js';
2
14
  export function hasPermissions() {
3
15
  return (superclass) => {
4
16
  class HasPermissionsMixin extends superclass {
@@ -192,6 +204,14 @@ export function hasPermissions() {
192
204
  canAny(permissions, target) {
193
205
  return Acl.model(this).canAny(permissions, target);
194
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
+ }
195
215
  /**
196
216
  * Check if model has any permission
197
217
  * @param permission
@@ -295,3 +315,102 @@ export function hasPermissions() {
295
315
  return HasPermissionsMixin;
296
316
  };
297
317
  }
318
+ export function permissionQueryHelpers() {
319
+ return (superclass) => {
320
+ class QueryHelpersMixin extends superclass {
321
+ _whereRoles(query, targetClass, ...roles) {
322
+ return query.whereHas(
323
+ // @ts-ignore
324
+ '_roles', (rolesQuery) => {
325
+ rolesQuery.whereIn('slug', roles).where('model_type', morphMap.getAlias(targetClass));
326
+ });
327
+ }
328
+ _whereDirectPermissions(query, targetClass, permissions, target) {
329
+ return query.whereHas(
330
+ // @ts-ignore
331
+ '_permissions', (permissionsQuery) => {
332
+ const entity = destructTarget(morphMap, target);
333
+ permissionsQuery
334
+ .whereIn('slug', permissions)
335
+ .where('model_type', morphMap.getAlias(targetClass))
336
+ .whereNotExists((subQuery) => {
337
+ subQuery
338
+ .from(Permission.table + ' as p2')
339
+ .leftJoin(ModelPermission.table + ' as mp2', 'mp2.permission_id', '=', 'p2.id')
340
+ .where('p2.allowed', false)
341
+ .whereRaw('p2.slug=' + Permission.table + '.slug')
342
+ .whereRaw('p2.scope=' + Permission.table + '.scope')
343
+ .whereColumn('mp2.model_id', targetClass.table + '.id')
344
+ .where('mp2.model_type', morphMap.getAlias(targetClass))
345
+ .select('p2.slug')
346
+ .groupBy('p2.slug');
347
+ });
348
+ applyTargetRestriction(Permission.table, permissionsQuery, entity.targetClass, entity.targetId);
349
+ });
350
+ }
351
+ _whereRolePermissions(query, targetClass, permissions, target) {
352
+ return query.whereHas(
353
+ // @ts-ignore
354
+ '_model_roles', (rolesQuery) => {
355
+ const entity = destructTarget(morphMap, target);
356
+ rolesQuery
357
+ .where(ModelRole.table + '.model_type', morphMap.getAlias(targetClass))
358
+ .join(ModelPermission.table + ' as mp', 'mp.model_id', '=', ModelRole.table + '.role_id')
359
+ .where('mp.model_type', 'roles')
360
+ .join(Permission.table + ' as p', 'p.id', '=', 'mp.permission_id')
361
+ .whereIn('p.slug', permissions)
362
+ .whereNotExists((subQuery) => {
363
+ subQuery
364
+ .from(Permission.table + ' as p2')
365
+ .leftJoin(ModelPermission.table + ' as mp2', 'mp2.permission_id', '=', 'p2.id')
366
+ .where('p2.allowed', false)
367
+ .whereRaw('p2.slug=' + 'p.slug')
368
+ .whereRaw('p2.scope=' + 'p.scope')
369
+ .whereColumn('mp2.model_id', targetClass.table + '.id')
370
+ .where('mp2.model_type', morphMap.getAlias(targetClass))
371
+ .select('p2.slug')
372
+ .groupBy('p2.slug');
373
+ });
374
+ applyTargetRestriction('p', rolesQuery, entity.targetClass, entity.targetId);
375
+ });
376
+ }
377
+ _wherePermissions(query, targetClass, permissions, target) {
378
+ query
379
+ .where((subQuery) => {
380
+ this._whereDirectPermissions(subQuery, targetClass, permissions, target);
381
+ })
382
+ .orWhere((subQuery) => {
383
+ this._whereRolePermissions(subQuery, targetClass, permissions, target);
384
+ });
385
+ }
386
+ }
387
+ __decorate([
388
+ manyToMany(() => Role, {
389
+ localKey: 'id',
390
+ relatedKey: 'id',
391
+ pivotForeignKey: 'model_id',
392
+ pivotRelatedForeignKey: 'role_id',
393
+ pivotTable: 'model_roles',
394
+ pivotColumns: ['model_type'],
395
+ pivotTimestamps: true,
396
+ })
397
+ ], QueryHelpersMixin.prototype, "_roles", void 0);
398
+ __decorate([
399
+ manyToMany(() => Permission, {
400
+ localKey: 'id',
401
+ relatedKey: 'id',
402
+ pivotForeignKey: 'model_id',
403
+ pivotRelatedForeignKey: 'permission_id',
404
+ pivotTable: 'model_permissions',
405
+ pivotColumns: ['model_type'],
406
+ pivotTimestamps: true,
407
+ })
408
+ ], QueryHelpersMixin.prototype, "_permissions", void 0);
409
+ __decorate([
410
+ hasMany(() => ModelRole, {
411
+ foreignKey: 'modelId',
412
+ })
413
+ ], QueryHelpersMixin.prototype, "_model_roles", void 0);
414
+ return QueryHelpersMixin;
415
+ };
416
+ }
@@ -1,4 +1,7 @@
1
- import { AclModel, MorphInterface } from '../types.js';
1
+ import { AclModel, ModelIdType, MorphInterface, PermissionInterface } from '../types.js';
2
+ import type { ManyToManySubQueryBuilderContract, RelationSubQueryBuilderContract } from '@adonisjs/lucid/types/relations';
3
+ import { ModelRole, Permission } from '../../index.js';
4
+ import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
2
5
  export declare function formatList(models: (string | number | any)[]): {
3
6
  slugs: string[];
4
7
  ids: number[];
@@ -11,10 +14,16 @@ export declare function formatStringNumbers(models: string | number | any): {
11
14
  slugs: string[];
12
15
  ids: number[];
13
16
  };
14
- export declare function destructTarget(map: MorphInterface, target?: AclModel | Function): Promise<{
17
+ export declare function destructTarget(map: MorphInterface, target?: AclModel | Function): {
15
18
  targetClass: null;
16
19
  targetId: null;
17
20
  } | {
18
21
  targetClass: string;
19
- targetId: import("../types.js").ModelIdType | null;
20
- }>;
22
+ targetId: ModelIdType | null;
23
+ };
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;
@@ -47,7 +47,7 @@ export function formatStringNumbers(models) {
47
47
  }
48
48
  return { slugs, ids };
49
49
  }
50
- export async function destructTarget(map, target) {
50
+ export function destructTarget(map, target) {
51
51
  if (!target) {
52
52
  return {
53
53
  targetClass: null,
@@ -62,3 +62,28 @@ export async function destructTarget(map, target) {
62
62
  function isAclModelInterface(obj) {
63
63
  return typeof obj === 'object' && typeof obj.getModelId === 'function';
64
64
  }
65
+ export function applyTargetRestriction(table, q, entityType, entityId) {
66
+ if (entityType) {
67
+ q.where((query) => {
68
+ query.where(table + '.entity_type', entityType).orWhere(table + '.entity_type', '*');
69
+ });
70
+ if (entityId) {
71
+ q.where((query) => {
72
+ query.where(table + '.entity_id', entityId).orWhereNull(table + '.entity_id');
73
+ });
74
+ }
75
+ else {
76
+ q.whereNull(table + '.entity_id');
77
+ }
78
+ }
79
+ else {
80
+ q.where(table + '.entity_type', '*').whereNull(table + '.entity_id');
81
+ }
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
@@ -186,22 +186,22 @@ export class ModelHasRolePermissions extends BaseAdapter {
186
186
  * @param target
187
187
  */
188
188
  async hasAllPermissions(permissions, target) {
189
- const entity = await destructTarget(this.map, target);
189
+ const entity = destructTarget(this.map, target);
190
190
  return await this.permissionService.hasAll(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
191
191
  }
192
192
  async hasAnyPermission(permissions, target) {
193
- const entity = await destructTarget(this.map, target);
193
+ const entity = destructTarget(this.map, target);
194
194
  return await this.permissionService.hasAny(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
195
195
  }
196
196
  async hasAnyDirectPermission(permissions, target) {
197
- const entity = await destructTarget(this.map, target);
197
+ const entity = destructTarget(this.map, target);
198
198
  return await this.permissionService.hasAnyDirect(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
199
199
  }
200
200
  async hasDirectPermission(permission, target) {
201
201
  return this.hasAnyDirectPermission([permission], target);
202
202
  }
203
203
  async hasAllPermissionsDirect(permissions, target) {
204
- const entity = await destructTarget(this.map, target);
204
+ const entity = destructTarget(this.map, target);
205
205
  return await this.permissionService.hasAllDirect(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
206
206
  }
207
207
  can(permission, target) {
@@ -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
@@ -227,7 +252,7 @@ export class ModelHasRolePermissions extends BaseAdapter {
227
252
  * @param target
228
253
  */
229
254
  async assignDirectAllPermissions(permissions, target) {
230
- const entity = await destructTarget(this.map, target);
255
+ const entity = destructTarget(this.map, target);
231
256
  const assigned = await this.permissionService.giveAll(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId, true);
232
257
  this.fire(PermissionsAttachedToModelEvent, assigned.map((item) => item.permissionId), this.model);
233
258
  return assigned;
@@ -282,7 +307,7 @@ export class ModelHasRolePermissions extends BaseAdapter {
282
307
  * @param target
283
308
  */
284
309
  async revokeAllPermissions(permissions, target) {
285
- const entity = await destructTarget(this.map, target);
310
+ const entity = destructTarget(this.map, target);
286
311
  const revoked = this.permissionService.revokeAll(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
287
312
  this.fire(PermissionsDetachedFromModelEvent, permissions, this.model);
288
313
  return revoked;
@@ -320,7 +345,7 @@ export class ModelHasRolePermissions extends BaseAdapter {
320
345
  * @param target
321
346
  */
322
347
  async forbidAll(permissions, target) {
323
- const entity = await destructTarget(this.map, target);
348
+ const entity = destructTarget(this.map, target);
324
349
  const forbade = await this.permissionService.forbidAll(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
325
350
  this.fire(PermissionsForbadeEvent, forbade.map((item) => item.permissionId), this.model);
326
351
  }
@@ -329,7 +354,7 @@ export class ModelHasRolePermissions extends BaseAdapter {
329
354
  * @param target
330
355
  */
331
356
  async unforbidAll(permissions, target) {
332
- const entity = await destructTarget(this.map, target);
357
+ const entity = destructTarget(this.map, target);
333
358
  const unforbade = await this.permissionService.unforbidAll(this.map.getAlias(this.model), this.model.getModelId(), permissions, entity.targetClass, entity.targetId);
334
359
  if (unforbade.length) {
335
360
  this.fire(PermissionsUnForbadeEvent, unforbade.map((item) => item.permissionId), this.model);
@@ -84,7 +84,7 @@ export default class PermissionHasModelRoles extends BaseAdapter {
84
84
  }
85
85
  role = String(r.id);
86
86
  }
87
- const entity = await destructTarget(this.map, target);
87
+ const entity = destructTarget(this.map, target);
88
88
  const attached = await this.permissionService.giveAll(this.map.getAlias(this.roleClassName), role, [this.permission.slug], entity.targetClass, entity.targetId, true);
89
89
  if (attached.length > 0) {
90
90
  this.fire(PermissionsAttachedToRoleEvent, attached.map((item) => item.permissionId), role);
@@ -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,4 +1,5 @@
1
1
  import BaseService from '../base_service.js';
2
+ import { applyTargetRestriction, applyPartialTargetRestriction } from '../helper.js';
2
3
  export default class PermissionsService extends BaseService {
3
4
  options;
4
5
  scope;
@@ -203,6 +204,27 @@ export default class PermissionsService extends BaseService {
203
204
  const r = await q.distinct(this.permissionTable + '.id').select(this.permissionTable + '.id');
204
205
  return r.length > 0;
205
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
+ }
206
228
  /**
207
229
  * has all permissions
208
230
  */
@@ -229,6 +251,7 @@ export default class PermissionsService extends BaseService {
229
251
  directPermissions: this.map.getAlias(this.roleClassName) === modelType,
230
252
  permissionSlugs: slugs,
231
253
  permissionIds: ids,
254
+ includeForbiddings: true,
232
255
  }).distinct(this.permissionTable + '.id');
233
256
  const r = await q.select(this.permissionTable + '.id');
234
257
  // @ts-ignore
@@ -245,6 +268,7 @@ export default class PermissionsService extends BaseService {
245
268
  directPermissions: true,
246
269
  permissionSlugs: slugs,
247
270
  permissionIds: ids,
271
+ includeForbiddings: true,
248
272
  }).distinct(this.permissionTable + '.id');
249
273
  const r = await q.select(this.permissionTable + '.id');
250
274
  return r.length >= permission.length;
@@ -260,6 +284,7 @@ export default class PermissionsService extends BaseService {
260
284
  directPermissions: true,
261
285
  permissionSlugs: slugs,
262
286
  permissionIds: ids,
287
+ includeForbiddings: true,
263
288
  }).distinct(this.permissionTable + '.id');
264
289
  const r = await q.select(this.permissionTable + '.id');
265
290
  // @ts-ignore
@@ -393,16 +418,20 @@ export default class PermissionsService extends BaseService {
393
418
  const q = this.permissionQuery.leftJoin(this.modelPermissionTable + ' as mp', 'mp.permission_id', '=', this.permissionTable + '.id');
394
419
  if (modelId && modelType) {
395
420
  if (directPermissions) {
421
+ // check direct-assigned permissions
396
422
  q.where('mp.model_type', modelType).where('mp.model_id', modelId);
397
423
  }
398
424
  else {
425
+ //
399
426
  q.leftJoin(this.modelRoleTable + ' as mr', (joinQuery) => {
400
427
  joinQuery.onVal('mr.model_type', modelType).onVal('mr.model_id', modelId);
401
428
  });
402
429
  if (conditions.throughRoles) {
430
+ // only through roles
403
431
  q.whereRaw('mr.role_id=mp.model_id').where('mp.model_type', 'roles');
404
432
  }
405
433
  else {
434
+ // check direct-assigned permissions and through roles
406
435
  q.where((subQuery) => {
407
436
  subQuery
408
437
  .where((query) => {
@@ -410,9 +439,6 @@ export default class PermissionsService extends BaseService {
410
439
  })
411
440
  .orWhere((query) => {
412
441
  query.whereRaw('mr.role_id=mp.model_id').where('mp.model_type', 'roles');
413
- // query
414
- // .whereRaw('CAST(mr.role_id AS CHAR)=mp.model_id')
415
- // .where('mp.model_type', 'roles')
416
442
  });
417
443
  });
418
444
  }
@@ -489,22 +515,10 @@ export default class PermissionsService extends BaseService {
489
515
  return q;
490
516
  }
491
517
  applyTargetRestriction(table, q, entityType, entityId) {
492
- if (entityType) {
493
- q.where((query) => {
494
- query.where(table + '.entity_type', entityType).orWhere(table + '.entity_type', '*');
495
- });
496
- if (entityId) {
497
- q.where((query) => {
498
- query.where(table + '.entity_id', entityId).orWhereNull(table + '.entity_id');
499
- });
500
- }
501
- else {
502
- q.whereNull(table + '.entity_id');
503
- }
504
- }
505
- else {
506
- q.where(table + '.entity_type', '*').whereNull(table + '.entity_id');
507
- }
518
+ applyTargetRestriction(table, q, entityType, entityId);
519
+ }
520
+ applyPartialTargetRestriction(table, q, entityType) {
521
+ applyPartialTargetRestriction(table, q, entityType);
508
522
  }
509
523
  applyScopes(q) {
510
524
  q.where(this.permissionTable + '.scope', this.scope.get());
@@ -71,7 +71,7 @@ export class RoleHasModelPermissions extends BaseAdapter {
71
71
  return result;
72
72
  }
73
73
  async hasPermission(permission, target) {
74
- const entity = await destructTarget(this.map, target);
74
+ const entity = destructTarget(this.map, target);
75
75
  const result = await this.permissionService.hasAny(this.map.getAlias(this.role), this.role.getModelId(), [permission], entity.targetClass, entity.targetId);
76
76
  return result;
77
77
  }
@@ -82,7 +82,7 @@ export class RoleHasModelPermissions extends BaseAdapter {
82
82
  * @returns
83
83
  */
84
84
  async hasAllPermissions(permissions, target) {
85
- const entity = await destructTarget(this.map, target);
85
+ const entity = destructTarget(this.map, target);
86
86
  const result = await this.permissionService.hasAll(this.map.getAlias(this.role), this.role.getModelId(), permissions, entity.targetClass, entity.targetId);
87
87
  return result;
88
88
  }
@@ -93,7 +93,7 @@ export class RoleHasModelPermissions extends BaseAdapter {
93
93
  * @returns
94
94
  */
95
95
  async hasAnyPermissions(permissions, target) {
96
- const entity = await destructTarget(this.map, target);
96
+ const entity = destructTarget(this.map, target);
97
97
  const result = await this.permissionService.hasAny(this.map.getAlias(this.role), this.role.getModelId(), permissions, entity.targetClass, entity.targetId);
98
98
  return result;
99
99
  }
@@ -112,7 +112,7 @@ export class RoleHasModelPermissions extends BaseAdapter {
112
112
  return this.hasAnyPermissions(permissions);
113
113
  }
114
114
  async forbidden(permission, target) {
115
- const entity = await destructTarget(this.map, target);
115
+ const entity = destructTarget(this.map, target);
116
116
  return this.permissionService.forbidden(this.map.getAlias(this.role), this.role.getModelId(), permission, entity.targetClass, entity.targetId);
117
117
  }
118
118
  /**
@@ -144,7 +144,7 @@ export class RoleHasModelPermissions extends BaseAdapter {
144
144
  * @param target
145
145
  */
146
146
  async giveAll(permissions, target) {
147
- const entity = await destructTarget(this.map, target);
147
+ const entity = destructTarget(this.map, target);
148
148
  const attached = await this.permissionService.giveAll(this.map.getAlias(this.role), this.role.getModelId(), permissions, entity.targetClass, entity.targetId, true);
149
149
  if (attached.length > 0) {
150
150
  this.fire(PermissionsAttachedToRoleEvent, attached.map((item) => item.permissionId), this.role.getModelId());
@@ -182,7 +182,7 @@ export class RoleHasModelPermissions extends BaseAdapter {
182
182
  return this.revokeAll([permission]);
183
183
  }
184
184
  async revokeAll(permissions, target) {
185
- const entity = await destructTarget(this.map, target);
185
+ const entity = destructTarget(this.map, target);
186
186
  const revoked = await this.permissionService.revokeAll(this.map.getAlias(this.role), this.role.getModelId(), permissions, entity.targetClass, entity.targetId);
187
187
  if (revoked.length > 0) {
188
188
  this.fire(PermissionsDetachedFromRoleEvent, permissions, this.role.getModelId());
@@ -211,11 +211,11 @@ export class RoleHasModelPermissions extends BaseAdapter {
211
211
  return this.giveAll(permissions, target);
212
212
  }
213
213
  async forbid(permission, target) {
214
- const entity = await destructTarget(this.map, target);
214
+ const entity = destructTarget(this.map, target);
215
215
  return this.permissionService.forbid(this.map.getAlias(this.role), this.role.getModelId(), permission, entity.targetClass, entity.targetId);
216
216
  }
217
217
  async unforbid(permission, target) {
218
- const entity = await destructTarget(this.map, target);
218
+ const entity = destructTarget(this.map, target);
219
219
  return this.permissionService.unforbidAll(this.map.getAlias(this.role), this.role.getModelId(), [permission], entity.targetClass, entity.targetId);
220
220
  }
221
221
  }
@@ -69,9 +69,6 @@ export interface ModelPermissionsQuery extends AclModelQuery {
69
69
  entity: Entity;
70
70
  throughRoles: boolean;
71
71
  }
72
- export interface MorphMapInterface {
73
- [key: string]: any;
74
- }
75
72
  export interface MorphInterface {
76
73
  set(alias: string, target: any): void;
77
74
  get(alias: string): any;
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": "1.2.0",
4
+ "version": "1.3.1",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },