@ooneex/permission 0.0.1 → 0.0.4

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
@@ -1 +1,712 @@
1
1
  # @ooneex/permission
2
+
3
+ A flexible ability-based access control (ABAC) library for TypeScript applications powered by CASL. This package provides fine-grained permission management with support for actions, subjects, and field-level permissions for comprehensive authorization control.
4
+
5
+ ![Browser](https://img.shields.io/badge/Browser-Compatible-green?style=flat-square&logo=googlechrome)
6
+ ![Bun](https://img.shields.io/badge/Bun-Compatible-orange?style=flat-square&logo=bun)
7
+ ![Deno](https://img.shields.io/badge/Deno-Compatible-blue?style=flat-square&logo=deno)
8
+ ![Node.js](https://img.shields.io/badge/Node.js-Compatible-green?style=flat-square&logo=node.js)
9
+ ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue?style=flat-square&logo=typescript)
10
+ ![MIT License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)
11
+
12
+ ## Features
13
+
14
+ ✅ **CASL Integration** - Built on the battle-tested CASL library for ability management
15
+
16
+ ✅ **60+ Permission Actions** - Comprehensive set of actions from CRUD to complex operations
17
+
18
+ ✅ **Subject-Based Permissions** - Define permissions for specific entity types
19
+
20
+ ✅ **Field-Level Control** - Restrict access to specific fields within subjects
21
+
22
+ ✅ **User-Aware Permissions** - Set permissions dynamically based on user context
23
+
24
+ ✅ **Type-Safe** - Full TypeScript support with proper type definitions
25
+
26
+ ✅ **Container Integration** - Works seamlessly with dependency injection
27
+
28
+ ✅ **Framework Integration** - Integrates with Ooneex routing for route-level permissions
29
+
30
+ ## Installation
31
+
32
+ ### Bun
33
+ ```bash
34
+ bun add @ooneex/permission
35
+ ```
36
+
37
+ ### pnpm
38
+ ```bash
39
+ pnpm add @ooneex/permission
40
+ ```
41
+
42
+ ### Yarn
43
+ ```bash
44
+ yarn add @ooneex/permission
45
+ ```
46
+
47
+ ### npm
48
+ ```bash
49
+ npm install @ooneex/permission
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ ### Creating a Permission Class
55
+
56
+ ```typescript
57
+ import { Permission, EPermissionAction, EPermissionSubject } from '@ooneex/permission';
58
+ import type { IUser } from '@ooneex/user';
59
+
60
+ class UserPermission extends Permission {
61
+ private user: IUser | null = null;
62
+
63
+ public allow(): this {
64
+ // Define what actions are allowed
65
+ this.ability.can(EPermissionAction.READ, EPermissionSubject.USER);
66
+ this.ability.can(EPermissionAction.VIEW, EPermissionSubject.USER);
67
+ return this;
68
+ }
69
+
70
+ public forbid(): this {
71
+ // Define what actions are forbidden
72
+ this.ability.cannot(EPermissionAction.DELETE, EPermissionSubject.USER);
73
+ return this;
74
+ }
75
+
76
+ public setUserPermissions(user: IUser | null): this {
77
+ this.user = user;
78
+
79
+ if (user) {
80
+ // Authenticated users can update their own profile
81
+ this.ability.can(EPermissionAction.UPDATE, EPermissionSubject.USER);
82
+ }
83
+
84
+ return this;
85
+ }
86
+
87
+ public async check(): Promise<boolean> {
88
+ return this.user !== null;
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### Using Permissions
94
+
95
+ ```typescript
96
+ import { UserPermission } from './permissions/UserPermission';
97
+ import { EPermissionAction, EPermissionSubject } from '@ooneex/permission';
98
+
99
+ const permission = new UserPermission();
100
+
101
+ // Set up permissions for a user
102
+ permission
103
+ .setUserPermissions(currentUser)
104
+ .allow()
105
+ .forbid()
106
+ .build();
107
+
108
+ // Check if action is allowed
109
+ if (permission.can(EPermissionAction.UPDATE, EPermissionSubject.USER)) {
110
+ console.log('User can update');
111
+ }
112
+
113
+ // Check if action is forbidden
114
+ if (permission.cannot(EPermissionAction.DELETE, EPermissionSubject.USER)) {
115
+ console.log('User cannot delete');
116
+ }
117
+ ```
118
+
119
+ ### Route-Level Permissions
120
+
121
+ ```typescript
122
+ import { Route } from '@ooneex/routing';
123
+ import type { IController, ContextType } from '@ooneex/controller';
124
+ import { UserPermission } from './permissions/UserPermission';
125
+
126
+ @Route.http({
127
+ name: 'api.users.update',
128
+ path: '/api/users/:id',
129
+ method: 'PUT',
130
+ description: 'Update user profile',
131
+ permission: UserPermission
132
+ })
133
+ class UserUpdateController implements IController {
134
+ public async index(context: ContextType): Promise<IResponse> {
135
+ // Permission is automatically checked before reaching this handler
136
+ const { id } = context.params;
137
+ const user = await this.userService.update(id, context.payload);
138
+
139
+ return context.response.json({ user });
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### Field-Level Permissions
145
+
146
+ ```typescript
147
+ import { Permission, EPermissionAction, EPermissionSubject } from '@ooneex/permission';
148
+ import type { IUser } from '@ooneex/user';
149
+
150
+ class UserFieldPermission extends Permission {
151
+ public allow(): this {
152
+ // Allow reading only specific fields
153
+ this.ability.can(EPermissionAction.READ, EPermissionSubject.USER, 'name');
154
+ this.ability.can(EPermissionAction.READ, EPermissionSubject.USER, 'email');
155
+ return this;
156
+ }
157
+
158
+ public forbid(): this {
159
+ // Forbid reading sensitive fields
160
+ this.ability.cannot(EPermissionAction.READ, EPermissionSubject.USER, 'password');
161
+ this.ability.cannot(EPermissionAction.READ, EPermissionSubject.USER, 'secretKey');
162
+ return this;
163
+ }
164
+
165
+ public setUserPermissions(user: IUser | null): this {
166
+ return this;
167
+ }
168
+
169
+ public async check(): Promise<boolean> {
170
+ return true;
171
+ }
172
+ }
173
+
174
+ // Usage
175
+ const permission = new UserFieldPermission();
176
+ permission.allow().forbid().build();
177
+
178
+ permission.can(EPermissionAction.READ, EPermissionSubject.USER, 'name'); // true
179
+ permission.can(EPermissionAction.READ, EPermissionSubject.USER, 'password'); // false
180
+ ```
181
+
182
+ ### Custom Subjects
183
+
184
+ ```typescript
185
+ import { Permission, EPermissionAction } from '@ooneex/permission';
186
+ import type { IUser } from '@ooneex/user';
187
+
188
+ // Define custom subjects for your domain
189
+ type CustomSubjects = 'Article' | 'Comment' | 'Category';
190
+
191
+ class ArticlePermission extends Permission<CustomSubjects> {
192
+ public allow(): this {
193
+ this.ability.can(EPermissionAction.READ, 'Article');
194
+ this.ability.can(EPermissionAction.CREATE, 'Article');
195
+ return this;
196
+ }
197
+
198
+ public forbid(): this {
199
+ this.ability.cannot(EPermissionAction.DELETE, 'Article');
200
+ return this;
201
+ }
202
+
203
+ public setUserPermissions(user: IUser | null): this {
204
+ if (user) {
205
+ this.ability.can(EPermissionAction.UPDATE, 'Article');
206
+ }
207
+ return this;
208
+ }
209
+
210
+ public async check(): Promise<boolean> {
211
+ return true;
212
+ }
213
+ }
214
+ ```
215
+
216
+ ## API Reference
217
+
218
+ ### Classes
219
+
220
+ #### `Permission<S>`
221
+
222
+ Abstract base class for creating permission implementations.
223
+
224
+ **Type Parameter:**
225
+ - `S` - Additional subject types (optional)
226
+
227
+ **Constructor:**
228
+ ```typescript
229
+ new Permission()
230
+ ```
231
+
232
+ **Abstract Methods:**
233
+
234
+ ##### `allow(): this`
235
+
236
+ Define allowed actions for subjects.
237
+
238
+ **Returns:** Self for chaining
239
+
240
+ ##### `forbid(): this`
241
+
242
+ Define forbidden actions for subjects.
243
+
244
+ **Returns:** Self for chaining
245
+
246
+ ##### `setUserPermissions(user: IUser | null): this`
247
+
248
+ Set permissions based on the current user context.
249
+
250
+ **Parameters:**
251
+ - `user` - The current user or null for guests
252
+
253
+ **Returns:** Self for chaining
254
+
255
+ ##### `check(): Promise<boolean>`
256
+
257
+ Perform custom permission validation logic.
258
+
259
+ **Returns:** Promise resolving to true if permission check passes
260
+
261
+ **Concrete Methods:**
262
+
263
+ ##### `build(): this`
264
+
265
+ Build the ability after defining permissions. Must be called before using `can` or `cannot`.
266
+
267
+ **Returns:** Self for chaining
268
+
269
+ **Throws:** None, but `can`/`cannot` will throw if not called
270
+
271
+ ##### `can(action: PermissionActionType, subject: Subjects | S, field?: string): boolean`
272
+
273
+ Check if an action is allowed on a subject.
274
+
275
+ **Parameters:**
276
+ - `action` - The action to check
277
+ - `subject` - The subject to check against
278
+ - `field` - Optional field name for field-level permissions
279
+
280
+ **Returns:** `true` if action is allowed
281
+
282
+ **Throws:** `PermissionException` if `build()` was not called
283
+
284
+ ##### `cannot(action: PermissionActionType, subject: Subjects | S, field?: string): boolean`
285
+
286
+ Check if an action is forbidden on a subject.
287
+
288
+ **Parameters:**
289
+ - `action` - The action to check
290
+ - `subject` - The subject to check against
291
+ - `field` - Optional field name for field-level permissions
292
+
293
+ **Returns:** `true` if action is forbidden
294
+
295
+ **Throws:** `PermissionException` if `build()` was not called
296
+
297
+ ### Enums
298
+
299
+ #### `EPermissionAction`
300
+
301
+ Comprehensive enum of permission actions.
302
+
303
+ **CRUD Operations:**
304
+ | Action | Value | Description |
305
+ |--------|-------|-------------|
306
+ | `CREATE` | `create` | Create new resources |
307
+ | `READ` | `read` | Read/view resources |
308
+ | `UPDATE` | `update` | Update existing resources |
309
+ | `DELETE` | `delete` | Delete resources |
310
+ | `MANAGE` | `manage` | Full management (all actions) |
311
+
312
+ **Content Operations:**
313
+ | Action | Value | Description |
314
+ |--------|-------|-------------|
315
+ | `VIEW` | `view` | View content |
316
+ | `EDIT` | `edit` | Edit content |
317
+ | `PUBLISH` | `publish` | Publish content |
318
+ | `ARCHIVE` | `archive` | Archive content |
319
+ | `APPROVE` | `approve` | Approve content |
320
+ | `REJECT` | `reject` | Reject content |
321
+
322
+ **File Operations:**
323
+ | Action | Value | Description |
324
+ |--------|-------|-------------|
325
+ | `DOWNLOAD` | `download` | Download files |
326
+ | `UPLOAD` | `upload` | Upload files |
327
+ | `COPY` | `copy` | Copy resources |
328
+ | `MOVE` | `move` | Move resources |
329
+ | `EXPORT` | `export` | Export data |
330
+ | `IMPORT` | `import` | Import data |
331
+
332
+ **Social Operations:**
333
+ | Action | Value | Description |
334
+ |--------|-------|-------------|
335
+ | `SHARE` | `share` | Share resources |
336
+ | `COMMENT` | `comment` | Add comments |
337
+ | `RATE` | `rate` | Rate content |
338
+ | `LIKE` | `like` | Like content |
339
+ | `DISLIKE` | `dislike` | Dislike content |
340
+ | `FOLLOW` | `follow` | Follow users/content |
341
+ | `UNFOLLOW` | `unfollow` | Unfollow |
342
+ | `SUBSCRIBE` | `subscribe` | Subscribe |
343
+ | `UNSUBSCRIBE` | `unsubscribe` | Unsubscribe |
344
+ | `BOOKMARK` | `bookmark` | Bookmark content |
345
+
346
+ **User Management:**
347
+ | Action | Value | Description |
348
+ |--------|-------|-------------|
349
+ | `INVITE` | `invite` | Invite users |
350
+ | `ASSIGN` | `assign` | Assign resources |
351
+ | `UNASSIGN` | `unassign` | Unassign resources |
352
+ | `GRANT` | `grant` | Grant permissions |
353
+ | `DENY` | `deny` | Deny permissions |
354
+ | `REVOKE` | `revoke` | Revoke access |
355
+
356
+ **Moderation:**
357
+ | Action | Value | Description |
358
+ |--------|-------|-------------|
359
+ | `BLOCK` | `block` | Block users |
360
+ | `UNBLOCK` | `unblock` | Unblock users |
361
+ | `REPORT` | `report` | Report content |
362
+ | `MODERATE` | `moderate` | Moderate content |
363
+ | `BAN` | `ban` | Ban users |
364
+ | `UNBAN` | `unban` | Unban users |
365
+
366
+ **System Operations:**
367
+ | Action | Value | Description |
368
+ |--------|-------|-------------|
369
+ | `EXECUTE` | `execute` | Execute operations |
370
+ | `RESTORE` | `restore` | Restore deleted |
371
+ | `PURGE` | `purge` | Permanently delete |
372
+ | `BACKUP` | `backup` | Backup data |
373
+ | `SYNC` | `sync` | Synchronize data |
374
+ | `CONFIGURE` | `configure` | Configure settings |
375
+ | `MONITOR` | `monitor` | Monitor system |
376
+ | `AUDIT` | `audit` | Audit actions |
377
+
378
+ **Additional Operations:**
379
+ | Action | Value | Description |
380
+ |--------|-------|-------------|
381
+ | `SEARCH` | `search` | Search resources |
382
+ | `FILTER` | `filter` | Filter resources |
383
+ | `SORT` | `sort` | Sort resources |
384
+ | `TAG` | `tag` | Tag resources |
385
+ | `UNTAG` | `untag` | Remove tags |
386
+ | `LOCK` | `lock` | Lock resources |
387
+ | `UNLOCK` | `unlock` | Unlock resources |
388
+ | `CLONE` | `clone` | Clone resources |
389
+ | `FORK` | `fork` | Fork resources |
390
+ | `MERGE` | `merge` | Merge resources |
391
+ | `SPLIT` | `split` | Split resources |
392
+ | `VALIDATE` | `validate` | Validate data |
393
+ | `VERIFY` | `verify` | Verify data |
394
+ | `CANCEL` | `cancel` | Cancel operations |
395
+ | `PAUSE` | `pause` | Pause operations |
396
+ | `RESUME` | `resume` | Resume operations |
397
+ | `SCHEDULE` | `schedule` | Schedule operations |
398
+ | `UNSCHEDULE` | `unschedule` | Unschedule |
399
+ | `JOIN` | `join` | Join groups |
400
+ | `HIDE` | `hide` | Hide content |
401
+
402
+ #### `EPermissionSubject`
403
+
404
+ Enum of common permission subjects.
405
+
406
+ | Subject | Value | Description |
407
+ |---------|-------|-------------|
408
+ | `USER_ENTITY` | `UserEntity` | User database entity |
409
+ | `AUTH_USER_ENTITY` | `AuthUserEntity` | Auth user entity |
410
+ | `AUTH_USER` | `AuthUser` | Authenticated user |
411
+ | `SYSTEM_ENTITY` | `SystemEntity` | System entity |
412
+ | `SYSTEM` | `System` | System subject |
413
+ | `USER` | `User` | User subject |
414
+ | `ALL` | `all` | All subjects (wildcard) |
415
+
416
+ ### Types
417
+
418
+ #### `PermissionActionType`
419
+
420
+ String literal type for permission actions.
421
+
422
+ ```typescript
423
+ type PermissionActionType = `${EPermissionAction}`;
424
+ // "create" | "read" | "update" | "delete" | "manage" | ...
425
+ ```
426
+
427
+ #### `Subjects`
428
+
429
+ String literal type for permission subjects.
430
+
431
+ ```typescript
432
+ type Subjects = `${EPermissionSubject}`;
433
+ // "UserEntity" | "AuthUserEntity" | "User" | "System" | "all" | ...
434
+ ```
435
+
436
+ #### `PermissionClassType`
437
+
438
+ Type for permission class constructors.
439
+
440
+ ```typescript
441
+ type PermissionClassType = new (...args: any[]) => IPermission;
442
+ ```
443
+
444
+ ### Interfaces
445
+
446
+ #### `IPermission<S>`
447
+
448
+ Interface for permission implementations.
449
+
450
+ ```typescript
451
+ interface IPermission<S extends string = string> {
452
+ allow: () => IPermission<S>;
453
+ forbid: () => IPermission<S>;
454
+ setUserPermissions: (user: IUser | null) => IPermission<S>;
455
+ check: () => Promise<boolean>;
456
+ build: () => IPermission<S>;
457
+ can: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;
458
+ cannot: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;
459
+ }
460
+ ```
461
+
462
+ ### Exceptions
463
+
464
+ #### `PermissionException`
465
+
466
+ Thrown when permission operations fail.
467
+
468
+ ```typescript
469
+ import { Permission, PermissionException } from '@ooneex/permission';
470
+
471
+ try {
472
+ const permission = new MyPermission();
473
+ // Forgot to call build()
474
+ permission.can('read', 'User');
475
+ } catch (error) {
476
+ if (error instanceof PermissionException) {
477
+ console.error('Permission error:', error.message);
478
+ }
479
+ }
480
+ ```
481
+
482
+ ### Decorators
483
+
484
+ #### `@decorator.permission()`
485
+
486
+ Decorator to register permission classes with the DI container.
487
+
488
+ ```typescript
489
+ import { Permission, decorator } from '@ooneex/permission';
490
+
491
+ @decorator.permission()
492
+ class ArticlePermission extends Permission {
493
+ // Implementation
494
+ }
495
+ ```
496
+
497
+ ## Advanced Usage
498
+
499
+ ### Role-Based Permission
500
+
501
+ ```typescript
502
+ import { Permission, EPermissionAction } from '@ooneex/permission';
503
+ import { ERole } from '@ooneex/role';
504
+ import type { IUser } from '@ooneex/user';
505
+
506
+ class AdminPermission extends Permission {
507
+ private user: IUser | null = null;
508
+
509
+ public allow(): this {
510
+ return this;
511
+ }
512
+
513
+ public forbid(): this {
514
+ return this;
515
+ }
516
+
517
+ public setUserPermissions(user: IUser | null): this {
518
+ this.user = user;
519
+
520
+ if (!user) return this;
521
+
522
+ // Set permissions based on role
523
+ switch (user.role) {
524
+ case ERole.SUPER_ADMIN:
525
+ this.ability.can(EPermissionAction.MANAGE, 'all');
526
+ break;
527
+
528
+ case ERole.ADMIN:
529
+ this.ability.can(EPermissionAction.CREATE, 'User');
530
+ this.ability.can(EPermissionAction.READ, 'User');
531
+ this.ability.can(EPermissionAction.UPDATE, 'User');
532
+ this.ability.cannot(EPermissionAction.DELETE, 'User');
533
+ break;
534
+
535
+ case ERole.MODERATOR:
536
+ this.ability.can(EPermissionAction.READ, 'User');
537
+ this.ability.can(EPermissionAction.MODERATE, 'User');
538
+ this.ability.can(EPermissionAction.BAN, 'User');
539
+ break;
540
+
541
+ default:
542
+ this.ability.can(EPermissionAction.READ, 'User');
543
+ }
544
+
545
+ return this;
546
+ }
547
+
548
+ public async check(): Promise<boolean> {
549
+ return this.user !== null;
550
+ }
551
+ }
552
+ ```
553
+
554
+ ### Ownership-Based Permissions
555
+
556
+ ```typescript
557
+ import { Permission, EPermissionAction } from '@ooneex/permission';
558
+ import type { IUser } from '@ooneex/user';
559
+
560
+ class ArticleOwnerPermission extends Permission<'Article'> {
561
+ private user: IUser | null = null;
562
+ private articleOwnerId: string | null = null;
563
+
564
+ public setArticleOwner(ownerId: string): this {
565
+ this.articleOwnerId = ownerId;
566
+ return this;
567
+ }
568
+
569
+ public allow(): this {
570
+ this.ability.can(EPermissionAction.READ, 'Article');
571
+ return this;
572
+ }
573
+
574
+ public forbid(): this {
575
+ return this;
576
+ }
577
+
578
+ public setUserPermissions(user: IUser | null): this {
579
+ this.user = user;
580
+
581
+ if (user && this.articleOwnerId === user.id) {
582
+ // Owner can do everything with their article
583
+ this.ability.can(EPermissionAction.UPDATE, 'Article');
584
+ this.ability.can(EPermissionAction.DELETE, 'Article');
585
+ this.ability.can(EPermissionAction.PUBLISH, 'Article');
586
+ }
587
+
588
+ return this;
589
+ }
590
+
591
+ public async check(): Promise<boolean> {
592
+ return this.user !== null && this.articleOwnerId !== null;
593
+ }
594
+ }
595
+
596
+ // Usage
597
+ const permission = new ArticleOwnerPermission();
598
+ permission
599
+ .setArticleOwner(article.userId)
600
+ .setUserPermissions(currentUser)
601
+ .allow()
602
+ .build();
603
+
604
+ if (permission.can(EPermissionAction.DELETE, 'Article')) {
605
+ await articleService.delete(articleId);
606
+ }
607
+ ```
608
+
609
+ ### Permission Factory
610
+
611
+ ```typescript
612
+ import { Permission, EPermissionAction, type PermissionClassType } from '@ooneex/permission';
613
+ import { container } from '@ooneex/container';
614
+
615
+ function createPermissionFor(resource: string): PermissionClassType {
616
+ return class extends Permission {
617
+ public allow(): this {
618
+ this.ability.can(EPermissionAction.READ, resource);
619
+ return this;
620
+ }
621
+
622
+ public forbid(): this {
623
+ return this;
624
+ }
625
+
626
+ public setUserPermissions(user: IUser | null): this {
627
+ if (user) {
628
+ this.ability.can(EPermissionAction.CREATE, resource);
629
+ this.ability.can(EPermissionAction.UPDATE, resource);
630
+ }
631
+ return this;
632
+ }
633
+
634
+ public async check(): Promise<boolean> {
635
+ return true;
636
+ }
637
+ };
638
+ }
639
+
640
+ // Create permissions dynamically
641
+ const ArticlePermission = createPermissionFor('Article');
642
+ const CommentPermission = createPermissionFor('Comment');
643
+ const CategoryPermission = createPermissionFor('Category');
644
+ ```
645
+
646
+ ### Controller with Permission Check
647
+
648
+ ```typescript
649
+ import { Route } from '@ooneex/routing';
650
+ import { EPermissionAction } from '@ooneex/permission';
651
+ import type { IController, ContextType } from '@ooneex/controller';
652
+ import { ArticlePermission } from './permissions/ArticlePermission';
653
+
654
+ @Route.http({
655
+ name: 'api.articles.delete',
656
+ path: '/api/articles/:id',
657
+ method: 'DELETE',
658
+ description: 'Delete an article',
659
+ permission: ArticlePermission
660
+ })
661
+ class ArticleDeleteController implements IController {
662
+ public async index(context: ContextType): Promise<IResponse> {
663
+ const { id } = context.params;
664
+ const article = await this.articleService.findById(id);
665
+
666
+ // Additional ownership check
667
+ const permission = new ArticlePermission();
668
+ permission
669
+ .setArticleOwner(article.userId)
670
+ .setUserPermissions(context.user)
671
+ .allow()
672
+ .forbid()
673
+ .build();
674
+
675
+ if (permission.cannot(EPermissionAction.DELETE, 'Article')) {
676
+ return context.response.exception('Not authorized to delete this article', {
677
+ status: 403
678
+ });
679
+ }
680
+
681
+ await this.articleService.delete(id);
682
+
683
+ return context.response.json({ deleted: true });
684
+ }
685
+ }
686
+ ```
687
+
688
+ ## License
689
+
690
+ This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
691
+
692
+ ## Contributing
693
+
694
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
695
+
696
+ ### Development Setup
697
+
698
+ 1. Clone the repository
699
+ 2. Install dependencies: `bun install`
700
+ 3. Run tests: `bun run test`
701
+ 4. Build the project: `bun run build`
702
+
703
+ ### Guidelines
704
+
705
+ - Write tests for new features
706
+ - Follow the existing code style
707
+ - Update documentation for API changes
708
+ - Ensure all tests pass before submitting PR
709
+
710
+ ---
711
+
712
+ Made with ❤️ by the Ooneex team
package/dist/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { MongoQuery as MongoQuery2 } from "@casl/ability";
2
- import { IUser as IUser2 } from "@ooneex/user";
3
- import { MongoQuery } from "@casl/ability";
1
+ import { EContainerScope } from "@ooneex/container";
4
2
  import { IUser } from "@ooneex/user";
5
3
  declare enum EPermissionAction {
6
4
  CREATE = "create",
@@ -84,26 +82,32 @@ type PermissionActionType = `${EPermissionAction}`;
84
82
  type Subjects = `${EPermissionSubject}`;
85
83
  type PermissionClassType = new (...args: any[]) => IPermission;
86
84
  interface IPermission<S extends string = string> {
87
- allow: (action: PermissionActionType | PermissionActionType[], subject: (Subjects | S) | (Subjects | S)[], conditions?: MongoQuery<Record<string, unknown>>) => IPermission<S>;
88
- forbid: (action: PermissionActionType | PermissionActionType[], subject: (Subjects | S) | (Subjects | S)[], conditions?: MongoQuery<Record<string, unknown>>) => IPermission<S>;
85
+ allow: () => IPermission<S>;
86
+ forbid: () => IPermission<S>;
87
+ setUserPermissions: (user: IUser | null) => IPermission<S>;
88
+ check: () => Promise<boolean>;
89
89
  build: () => IPermission<S>;
90
90
  can: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;
91
91
  cannot: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;
92
- setCommonPermissions: (user: IUser) => IPermission<S>;
93
92
  }
94
- declare class Permission<S extends string = string> {
95
- private ability;
93
+ declare const decorator: {
94
+ permission: (scope?: EContainerScope) => (target: PermissionClassType) => void;
95
+ };
96
+ import { AbilityBuilder, MongoAbility } from "@casl/ability";
97
+ import { IUser as IUser2 } from "@ooneex/user";
98
+ declare abstract class Permission<S extends string = string> implements IPermission<S> {
99
+ protected ability: AbilityBuilder<MongoAbility>;
96
100
  private builtAbility;
97
101
  constructor();
98
- allow(action: PermissionActionType | PermissionActionType[], subject: (Subjects | S) | (Subjects | S)[], conditions?: MongoQuery2<Record<string, unknown>>): this;
99
- forbid(action: PermissionActionType | PermissionActionType[], subject: (Subjects | S) | (Subjects | S)[], conditions?: MongoQuery2<Record<string, unknown>>): this;
102
+ abstract forbid(): this;
103
+ abstract setUserPermissions(user: IUser2 | null): this;
104
+ abstract check(): Promise<boolean>;
100
105
  build(): this;
101
106
  can(action: PermissionActionType, subject: Subjects | S, field?: string): boolean;
102
107
  cannot(action: PermissionActionType, subject: Subjects | S, field?: string): boolean;
103
- setCommonPermissions(user: IUser2): this;
104
108
  }
105
109
  import { Exception } from "@ooneex/exception";
106
110
  declare class PermissionException extends Exception {
107
111
  constructor(message: string, data?: Record<string, unknown>);
108
112
  }
109
- export { Subjects, PermissionException, PermissionClassType, PermissionActionType, Permission, IPermission, EPermissionSubject, EPermissionAction };
113
+ export { decorator, Subjects, PermissionException, PermissionClassType, PermissionActionType, Permission, IPermission, EPermissionSubject, EPermissionAction };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- import{AbilityBuilder as h,createMongoAbility as q}from"@casl/ability";import{ERole as w}from"@ooneex/role";import{Exception as f}from"@ooneex/exception";import{HttpStatus as g}from"@ooneex/http-status";class H extends f{constructor(x,k={}){super(x,{status:g.Code.InternalServerError,data:k});this.name="PermissionException"}}class I{ability;builtAbility=null;constructor(){this.ability=new h(q)}allow(x,k,v){return this.ability.can(x,k,v),this}forbid(x,k,v){return this.ability.cannot(x,k,v),this}build(){return this.builtAbility=this.ability.build(),this}can(x,k,v){if(!this.builtAbility)throw new H("Permission must be built before checking abilities");return this.builtAbility.can(x,k,v)}cannot(x,k,v){if(!this.builtAbility)throw new H("Permission must be built before checking abilities");return this.builtAbility.cannot(x,k,v)}setCommonPermissions(x){let{roles:k}=x;if(k.includes(w.SYSTEM)||k.includes(w.SUPER_ADMIN)||k.includes(w.ADMIN))return this.allow("manage","all"),this;for(let v of k){if(v===w.USER||v===w.MEMBER)this.allow(["read","update"],["UserEntity","AuthUserEntity","User","AuthUser"],{id:x.id});if(v===w.SUBSCRIBER)this.allow("read",["UserEntity","AuthUserEntity","User","AuthUser"],{id:x.id});if(v===w.TRIAL_USER)this.allow("read",["User","AuthUser"],{id:x.id});if(v===w.SUSPENDED)this.allow("read",["UserEntity","AuthUserEntity","User","AuthUser"],{id:x.id});if(v===w.GUEST)this.allow("read",["UserEntity","AuthUserEntity","User","AuthUser"],{public:!0})}return this}}var z;((p)=>{p.CREATE="create";p.READ="read";p.UPDATE="update";p.DELETE="delete";p.MANAGE="manage";p.VIEW="view";p.EDIT="edit";p.PUBLISH="publish";p.ARCHIVE="archive";p.APPROVE="approve";p.REJECT="reject";p.DOWNLOAD="download";p.UPLOAD="upload";p.SHARE="share";p.COPY="copy";p.MOVE="move";p.EXPORT="export";p.IMPORT="import";p.EXECUTE="execute";p.ASSIGN="assign";p.UNASSIGN="unassign";p.COMMENT="comment";p.RATE="rate";p.LIKE="like";p.DISLIKE="dislike";p.FOLLOW="follow";p.UNFOLLOW="unfollow";p.SUBSCRIBE="subscribe";p.UNSUBSCRIBE="unsubscribe";p.INVITE="invite";p.REVOKE="revoke";p.GRANT="grant";p.DENY="deny";p.BLOCK="block";p.UNBLOCK="unblock";p.REPORT="report";p.MODERATE="moderate";p.BAN="ban";p.UNBAN="unban";p.RESTORE="restore";p.PURGE="purge";p.BACKUP="backup";p.SYNC="sync";p.CONFIGURE="configure";p.MONITOR="monitor";p.AUDIT="audit";p.SEARCH="search";p.FILTER="filter";p.SORT="sort";p.BOOKMARK="bookmark";p.TAG="tag";p.UNTAG="untag";p.LOCK="lock";p.UNLOCK="unlock";p.CLONE="clone";p.FORK="fork";p.MERGE="merge";p.SPLIT="split";p.VALIDATE="validate";p.VERIFY="verify";p.CANCEL="cancel";p.PAUSE="pause";p.RESUME="resume";p.SCHEDULE="schedule";p.UNSCHEDULE="unschedule";p.JOIN="join";p.HIDE="hide"})(z||={});var D;((C)=>{C.USER_ENTITY="UserEntity";C.AUTH_USER_ENTITY="AuthUserEntity";C.AUTH_USER="AuthUser";C.SYSTEM_ENTITY="SystemEntity";C.SYSTEM="System";C.USER="User";C.ALL="all"})(D||={});export{H as PermissionException,I as Permission,D as EPermissionSubject,z as EPermissionAction};
1
+ // @bun
2
+ import{container as r,EContainerScope as h}from"@ooneex/container";var f={permission:(t=h.Singleton)=>{return(p)=>{r.add(p,t)}}};import{AbilityBuilder as e,createMongoAbility as x}from"@casl/ability";import{Exception as g}from"@ooneex/exception";import{HttpStatus as d}from"@ooneex/http-status";class b extends g{constructor(t,p={}){super(t,{status:d.Code.InternalServerError,data:p});this.name="PermissionException"}}class y{ability;builtAbility=null;constructor(){this.ability=new e(x)}build(){return this.builtAbility=this.ability.build(),this}can(t,p,u){if(!this.builtAbility)throw new b("Permission must be built before checking abilities");return this.builtAbility.can(t,p,u)}cannot(t,p,u){if(!this.builtAbility)throw new b("Permission must be built before checking abilities");return this.builtAbility.cannot(t,p,u)}}var w;((l)=>{l.CREATE="create";l.READ="read";l.UPDATE="update";l.DELETE="delete";l.MANAGE="manage";l.VIEW="view";l.EDIT="edit";l.PUBLISH="publish";l.ARCHIVE="archive";l.APPROVE="approve";l.REJECT="reject";l.DOWNLOAD="download";l.UPLOAD="upload";l.SHARE="share";l.COPY="copy";l.MOVE="move";l.EXPORT="export";l.IMPORT="import";l.EXECUTE="execute";l.ASSIGN="assign";l.UNASSIGN="unassign";l.COMMENT="comment";l.RATE="rate";l.LIKE="like";l.DISLIKE="dislike";l.FOLLOW="follow";l.UNFOLLOW="unfollow";l.SUBSCRIBE="subscribe";l.UNSUBSCRIBE="unsubscribe";l.INVITE="invite";l.REVOKE="revoke";l.GRANT="grant";l.DENY="deny";l.BLOCK="block";l.UNBLOCK="unblock";l.REPORT="report";l.MODERATE="moderate";l.BAN="ban";l.UNBAN="unban";l.RESTORE="restore";l.PURGE="purge";l.BACKUP="backup";l.SYNC="sync";l.CONFIGURE="configure";l.MONITOR="monitor";l.AUDIT="audit";l.SEARCH="search";l.FILTER="filter";l.SORT="sort";l.BOOKMARK="bookmark";l.TAG="tag";l.UNTAG="untag";l.LOCK="lock";l.UNLOCK="unlock";l.CLONE="clone";l.FORK="fork";l.MERGE="merge";l.SPLIT="split";l.VALIDATE="validate";l.VERIFY="verify";l.CANCEL="cancel";l.PAUSE="pause";l.RESUME="resume";l.SCHEDULE="schedule";l.UNSCHEDULE="unschedule";l.JOIN="join";l.HIDE="hide"})(w||={});var C;((a)=>{a.USER_ENTITY="UserEntity";a.AUTH_USER_ENTITY="AuthUserEntity";a.AUTH_USER="AuthUser";a.SYSTEM_ENTITY="SystemEntity";a.SYSTEM="System";a.USER="User";a.ALL="all"})(C||={});export{f as decorator,b as PermissionException,y as Permission,C as EPermissionSubject,w as EPermissionAction};
2
3
 
3
- //# debugId=E03E2CB5FC80CB9264756E2164756E21
4
+ //# debugId=2AFA4E169117EE2564756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["src/Permission.ts", "src/PermissionException.ts", "src/types.ts"],
3
+ "sources": ["src/decorators.ts", "src/Permission.ts", "src/PermissionException.ts", "src/types.ts"],
4
4
  "sourcesContent": [
5
- "import { AbilityBuilder, createMongoAbility, type MongoAbility, type MongoQuery } from \"@casl/ability\";\nimport { ERole } from \"@ooneex/role\";\nimport type { IUser } from \"@ooneex/user\";\nimport { PermissionException } from \"./PermissionException\";\nimport type { PermissionActionType, Subjects } from \"./types\";\n\nexport class Permission<S extends string = string> {\n private ability: AbilityBuilder<MongoAbility>;\n private builtAbility: MongoAbility | null = null;\n\n constructor() {\n this.ability = new AbilityBuilder(createMongoAbility);\n }\n\n public allow(\n action: PermissionActionType | PermissionActionType[],\n subject: (Subjects | S) | (Subjects | S)[],\n conditions?: MongoQuery<Record<string, unknown>>,\n ): this {\n this.ability.can(action as string, subject, conditions);\n return this;\n }\n\n public forbid(\n action: PermissionActionType | PermissionActionType[],\n subject: (Subjects | S) | (Subjects | S)[],\n conditions?: MongoQuery<Record<string, unknown>>,\n ): this {\n this.ability.cannot(action as string, subject, conditions);\n return this;\n }\n\n public build(): this {\n this.builtAbility = this.ability.build();\n return this;\n }\n\n public can(action: PermissionActionType, subject: Subjects | S, field?: string): boolean {\n if (!this.builtAbility) {\n throw new PermissionException(\"Permission must be built before checking abilities\");\n }\n return this.builtAbility.can(action as string, subject as string, field);\n }\n\n public cannot(action: PermissionActionType, subject: Subjects | S, field?: string): boolean {\n if (!this.builtAbility) {\n throw new PermissionException(\"Permission must be built before checking abilities\");\n }\n return this.builtAbility.cannot(action as string, subject as string, field);\n }\n\n public setCommonPermissions(user: IUser): this {\n const { roles } = user;\n\n // Check for highest privilege roles first\n if (roles.includes(ERole.SYSTEM) || roles.includes(ERole.SUPER_ADMIN) || roles.includes(ERole.ADMIN)) {\n this.allow(\"manage\", \"all\");\n return this;\n }\n\n // Apply permissions for each role\n for (const role of roles) {\n if (role === ERole.USER || role === ERole.MEMBER) {\n this.allow([\"read\", \"update\"], [\"UserEntity\", \"AuthUserEntity\", \"User\", \"AuthUser\"], { id: user.id });\n }\n\n if (role === ERole.SUBSCRIBER) {\n this.allow(\"read\", [\"UserEntity\", \"AuthUserEntity\", \"User\", \"AuthUser\"], { id: user.id });\n }\n\n if (role === ERole.TRIAL_USER) {\n this.allow(\"read\", [\"User\", \"AuthUser\"], { id: user.id });\n }\n\n if (role === ERole.SUSPENDED) {\n this.allow(\"read\", [\"UserEntity\", \"AuthUserEntity\", \"User\", \"AuthUser\"], { id: user.id });\n }\n\n if (role === ERole.GUEST) {\n this.allow(\"read\", [\"UserEntity\", \"AuthUserEntity\", \"User\", \"AuthUser\"], { public: true });\n }\n }\n\n return this;\n }\n}\n",
5
+ "import { container, EContainerScope } from \"@ooneex/container\";\nimport type { PermissionClassType } from \"./types\";\n\nexport const decorator = {\n permission: (scope: EContainerScope = EContainerScope.Singleton) => {\n return (target: PermissionClassType): void => {\n container.add(target, scope);\n };\n },\n};\n",
6
+ "import { AbilityBuilder, createMongoAbility, type MongoAbility } from \"@casl/ability\";\nimport type { IUser } from \"@ooneex/user\";\nimport { PermissionException } from \"./PermissionException\";\nimport type { IPermission, PermissionActionType, Subjects } from \"./types\";\n\nexport abstract class Permission<S extends string = string> implements IPermission<S> {\n protected ability: AbilityBuilder<MongoAbility>;\n private builtAbility: MongoAbility | null = null;\n\n constructor() {\n this.ability = new AbilityBuilder(createMongoAbility);\n }\n\n public abstract allow(): this;\n\n public abstract forbid(): this;\n\n public abstract setUserPermissions(user: IUser | null): this;\n\n public abstract check(): Promise<boolean>;\n\n public build(): this {\n this.builtAbility = this.ability.build();\n return this;\n }\n\n public can(action: PermissionActionType, subject: Subjects | S, field?: string): boolean {\n if (!this.builtAbility) {\n throw new PermissionException(\"Permission must be built before checking abilities\");\n }\n return this.builtAbility.can(action as string, subject as string, field);\n }\n\n public cannot(action: PermissionActionType, subject: Subjects | S, field?: string): boolean {\n if (!this.builtAbility) {\n throw new PermissionException(\"Permission must be built before checking abilities\");\n }\n return this.builtAbility.cannot(action as string, subject as string, field);\n }\n}\n",
6
7
  "import { Exception } from \"@ooneex/exception\";\nimport { HttpStatus } from \"@ooneex/http-status\";\n\nexport class PermissionException extends Exception {\n constructor(message: string, data: Record<string, unknown> = {}) {\n super(message, {\n status: HttpStatus.Code.InternalServerError,\n data,\n });\n this.name = \"PermissionException\";\n }\n}\n",
7
- "import type { MongoQuery } from \"@casl/ability\";\nimport type { IUser } from \"@ooneex/user\";\n\nexport enum EPermissionAction {\n CREATE = \"create\",\n READ = \"read\",\n UPDATE = \"update\",\n DELETE = \"delete\",\n MANAGE = \"manage\", // Special action that allows everything\n VIEW = \"view\",\n EDIT = \"edit\",\n PUBLISH = \"publish\",\n ARCHIVE = \"archive\",\n APPROVE = \"approve\",\n REJECT = \"reject\",\n DOWNLOAD = \"download\",\n UPLOAD = \"upload\",\n SHARE = \"share\",\n COPY = \"copy\",\n MOVE = \"move\",\n EXPORT = \"export\",\n IMPORT = \"import\",\n EXECUTE = \"execute\",\n ASSIGN = \"assign\",\n UNASSIGN = \"unassign\",\n COMMENT = \"comment\",\n RATE = \"rate\",\n LIKE = \"like\",\n DISLIKE = \"dislike\",\n FOLLOW = \"follow\",\n UNFOLLOW = \"unfollow\",\n SUBSCRIBE = \"subscribe\",\n UNSUBSCRIBE = \"unsubscribe\",\n INVITE = \"invite\",\n REVOKE = \"revoke\",\n GRANT = \"grant\",\n DENY = \"deny\",\n BLOCK = \"block\",\n UNBLOCK = \"unblock\",\n REPORT = \"report\",\n MODERATE = \"moderate\",\n BAN = \"ban\",\n UNBAN = \"unban\",\n RESTORE = \"restore\",\n PURGE = \"purge\",\n BACKUP = \"backup\",\n SYNC = \"sync\",\n CONFIGURE = \"configure\",\n MONITOR = \"monitor\",\n AUDIT = \"audit\",\n SEARCH = \"search\",\n FILTER = \"filter\",\n SORT = \"sort\",\n BOOKMARK = \"bookmark\",\n TAG = \"tag\",\n UNTAG = \"untag\",\n LOCK = \"lock\",\n UNLOCK = \"unlock\",\n CLONE = \"clone\",\n FORK = \"fork\",\n MERGE = \"merge\",\n SPLIT = \"split\",\n VALIDATE = \"validate\",\n VERIFY = \"verify\",\n CANCEL = \"cancel\",\n PAUSE = \"pause\",\n RESUME = \"resume\",\n SCHEDULE = \"schedule\",\n UNSCHEDULE = \"unschedule\",\n JOIN = \"join\",\n HIDE = \"hide\",\n}\n\nexport enum EPermissionSubject {\n USER_ENTITY = \"UserEntity\",\n AUTH_USER_ENTITY = \"AuthUserEntity\",\n AUTH_USER = \"AuthUser\",\n SYSTEM_ENTITY = \"SystemEntity\",\n SYSTEM = \"System\",\n USER = \"User\",\n ALL = \"all\",\n}\n\nexport type PermissionActionType = `${EPermissionAction}`;\nexport type Subjects = `${EPermissionSubject}`;\n\n// biome-ignore lint/suspicious/noExplicitAny: trust me\nexport type PermissionClassType = new (...args: any[]) => IPermission;\n\nexport interface IPermission<S extends string = string> {\n allow: (\n action: PermissionActionType | PermissionActionType[],\n subject: (Subjects | S) | (Subjects | S)[],\n conditions?: MongoQuery<Record<string, unknown>>,\n ) => IPermission<S>;\n forbid: (\n action: PermissionActionType | PermissionActionType[],\n subject: (Subjects | S) | (Subjects | S)[],\n conditions?: MongoQuery<Record<string, unknown>>,\n ) => IPermission<S>;\n build: () => IPermission<S>;\n can: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;\n cannot: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;\n setCommonPermissions: (user: IUser) => IPermission<S>;\n}\n"
8
+ "import type { IUser } from \"@ooneex/user\";\n\nexport enum EPermissionAction {\n CREATE = \"create\",\n READ = \"read\",\n UPDATE = \"update\",\n DELETE = \"delete\",\n MANAGE = \"manage\", // Special action that allows everything\n VIEW = \"view\",\n EDIT = \"edit\",\n PUBLISH = \"publish\",\n ARCHIVE = \"archive\",\n APPROVE = \"approve\",\n REJECT = \"reject\",\n DOWNLOAD = \"download\",\n UPLOAD = \"upload\",\n SHARE = \"share\",\n COPY = \"copy\",\n MOVE = \"move\",\n EXPORT = \"export\",\n IMPORT = \"import\",\n EXECUTE = \"execute\",\n ASSIGN = \"assign\",\n UNASSIGN = \"unassign\",\n COMMENT = \"comment\",\n RATE = \"rate\",\n LIKE = \"like\",\n DISLIKE = \"dislike\",\n FOLLOW = \"follow\",\n UNFOLLOW = \"unfollow\",\n SUBSCRIBE = \"subscribe\",\n UNSUBSCRIBE = \"unsubscribe\",\n INVITE = \"invite\",\n REVOKE = \"revoke\",\n GRANT = \"grant\",\n DENY = \"deny\",\n BLOCK = \"block\",\n UNBLOCK = \"unblock\",\n REPORT = \"report\",\n MODERATE = \"moderate\",\n BAN = \"ban\",\n UNBAN = \"unban\",\n RESTORE = \"restore\",\n PURGE = \"purge\",\n BACKUP = \"backup\",\n SYNC = \"sync\",\n CONFIGURE = \"configure\",\n MONITOR = \"monitor\",\n AUDIT = \"audit\",\n SEARCH = \"search\",\n FILTER = \"filter\",\n SORT = \"sort\",\n BOOKMARK = \"bookmark\",\n TAG = \"tag\",\n UNTAG = \"untag\",\n LOCK = \"lock\",\n UNLOCK = \"unlock\",\n CLONE = \"clone\",\n FORK = \"fork\",\n MERGE = \"merge\",\n SPLIT = \"split\",\n VALIDATE = \"validate\",\n VERIFY = \"verify\",\n CANCEL = \"cancel\",\n PAUSE = \"pause\",\n RESUME = \"resume\",\n SCHEDULE = \"schedule\",\n UNSCHEDULE = \"unschedule\",\n JOIN = \"join\",\n HIDE = \"hide\",\n}\n\nexport enum EPermissionSubject {\n USER_ENTITY = \"UserEntity\",\n AUTH_USER_ENTITY = \"AuthUserEntity\",\n AUTH_USER = \"AuthUser\",\n SYSTEM_ENTITY = \"SystemEntity\",\n SYSTEM = \"System\",\n USER = \"User\",\n ALL = \"all\",\n}\n\nexport type PermissionActionType = `${EPermissionAction}`;\nexport type Subjects = `${EPermissionSubject}`;\n\n// biome-ignore lint/suspicious/noExplicitAny: trust me\nexport type PermissionClassType = new (...args: any[]) => IPermission;\n\nexport interface IPermission<S extends string = string> {\n allow: () => IPermission<S>;\n forbid: () => IPermission<S>;\n setUserPermissions: (user: IUser | null) => IPermission<S>;\n check: () => Promise<boolean>;\n build: () => IPermission<S>;\n can: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;\n cannot: (action: PermissionActionType, subject: Subjects | S, field?: string) => boolean;\n}\n"
8
9
  ],
9
- "mappings": "AAAA,yBAAS,wBAAgB,sBACzB,gBAAS,qBCDT,oBAAS,0BACT,qBAAS,4BAEF,MAAM,UAA4B,CAAU,CACjD,WAAW,CAAC,EAAiB,EAAgC,CAAC,EAAG,CAC/D,MAAM,EAAS,CACb,OAAQ,EAAW,KAAK,oBACxB,MACF,CAAC,EACD,KAAK,KAAO,sBAEhB,CDLO,MAAM,CAAsC,CACzC,QACA,aAAoC,KAE5C,WAAW,EAAG,CACZ,KAAK,QAAU,IAAI,EAAe,CAAkB,EAG/C,KAAK,CACV,EACA,EACA,EACM,CAEN,OADA,KAAK,QAAQ,IAAI,EAAkB,EAAS,CAAU,EAC/C,KAGF,MAAM,CACX,EACA,EACA,EACM,CAEN,OADA,KAAK,QAAQ,OAAO,EAAkB,EAAS,CAAU,EAClD,KAGF,KAAK,EAAS,CAEnB,OADA,KAAK,aAAe,KAAK,QAAQ,MAAM,EAChC,KAGF,GAAG,CAAC,EAA8B,EAAuB,EAAyB,CACvF,GAAI,CAAC,KAAK,aACR,MAAM,IAAI,EAAoB,oDAAoD,EAEpF,OAAO,KAAK,aAAa,IAAI,EAAkB,EAAmB,CAAK,EAGlE,MAAM,CAAC,EAA8B,EAAuB,EAAyB,CAC1F,GAAI,CAAC,KAAK,aACR,MAAM,IAAI,EAAoB,oDAAoD,EAEpF,OAAO,KAAK,aAAa,OAAO,EAAkB,EAAmB,CAAK,EAGrE,oBAAoB,CAAC,EAAmB,CAC7C,IAAQ,SAAU,EAGlB,GAAI,EAAM,SAAS,EAAM,MAAM,GAAK,EAAM,SAAS,EAAM,WAAW,GAAK,EAAM,SAAS,EAAM,KAAK,EAEjG,OADA,KAAK,MAAM,SAAU,KAAK,EACnB,KAIT,QAAW,KAAQ,EAAO,CACxB,GAAI,IAAS,EAAM,MAAQ,IAAS,EAAM,OACxC,KAAK,MAAM,CAAC,OAAQ,QAAQ,EAAG,CAAC,aAAc,iBAAkB,OAAQ,UAAU,EAAG,CAAE,GAAI,EAAK,EAAG,CAAC,EAGtG,GAAI,IAAS,EAAM,WACjB,KAAK,MAAM,OAAQ,CAAC,aAAc,iBAAkB,OAAQ,UAAU,EAAG,CAAE,GAAI,EAAK,EAAG,CAAC,EAG1F,GAAI,IAAS,EAAM,WACjB,KAAK,MAAM,OAAQ,CAAC,OAAQ,UAAU,EAAG,CAAE,GAAI,EAAK,EAAG,CAAC,EAG1D,GAAI,IAAS,EAAM,UACjB,KAAK,MAAM,OAAQ,CAAC,aAAc,iBAAkB,OAAQ,UAAU,EAAG,CAAE,GAAI,EAAK,EAAG,CAAC,EAG1F,GAAI,IAAS,EAAM,MACjB,KAAK,MAAM,OAAQ,CAAC,aAAc,iBAAkB,OAAQ,UAAU,EAAG,CAAE,OAAQ,EAAK,CAAC,EAI7F,OAAO,KAEX,CElFO,IAAK,GAAL,CAAK,IAAL,CACL,SAAS,SACT,OAAO,OACP,SAAS,SACT,SAAS,SACT,SAAS,SACT,OAAO,OACP,OAAO,OACP,UAAU,UACV,UAAU,UACV,UAAU,UACV,SAAS,SACT,WAAW,WACX,SAAS,SACT,QAAQ,QACR,OAAO,OACP,OAAO,OACP,SAAS,SACT,SAAS,SACT,UAAU,UACV,SAAS,SACT,WAAW,WACX,UAAU,UACV,OAAO,OACP,OAAO,OACP,UAAU,UACV,SAAS,SACT,WAAW,WACX,YAAY,YACZ,cAAc,cACd,SAAS,SACT,SAAS,SACT,QAAQ,QACR,OAAO,OACP,QAAQ,QACR,UAAU,UACV,SAAS,SACT,WAAW,WACX,MAAM,MACN,QAAQ,QACR,UAAU,UACV,QAAQ,QACR,SAAS,SACT,OAAO,OACP,YAAY,YACZ,UAAU,UACV,QAAQ,QACR,SAAS,SACT,SAAS,SACT,OAAO,OACP,WAAW,WACX,MAAM,MACN,QAAQ,QACR,OAAO,OACP,SAAS,SACT,QAAQ,QACR,OAAO,OACP,QAAQ,QACR,QAAQ,QACR,WAAW,WACX,SAAS,SACT,SAAS,SACT,QAAQ,QACR,SAAS,SACT,WAAW,WACX,aAAa,aACb,OAAO,OACP,OAAO,SAnEG,QAsEL,IAAK,GAAL,CAAK,IAAL,CACL,cAAc,aACd,mBAAmB,iBACnB,YAAY,WACZ,gBAAgB,eAChB,SAAS,SACT,OAAO,OACP,MAAM,QAPI",
10
- "debugId": "E03E2CB5FC80CB9264756E2164756E21",
10
+ "mappings": ";AAAA,oBAAS,qBAAW,0BAGb,IAAM,EAAY,CACvB,WAAY,CAAC,EAAyB,EAAgB,YAAc,CAClE,MAAO,CAAC,IAAsC,CAC5C,EAAU,IAAI,EAAQ,CAAK,GAGjC,ECTA,yBAAS,wBAAgB,sBCAzB,oBAAS,0BACT,qBAAS,4BAEF,MAAM,UAA4B,CAAU,CACjD,WAAW,CAAC,EAAiB,EAAgC,CAAC,EAAG,CAC/D,MAAM,EAAS,CACb,OAAQ,EAAW,KAAK,oBACxB,MACF,CAAC,EACD,KAAK,KAAO,sBAEhB,CDNO,MAAe,CAAgE,CAC1E,QACF,aAAoC,KAE5C,WAAW,EAAG,CACZ,KAAK,QAAU,IAAI,EAAe,CAAkB,EAW/C,KAAK,EAAS,CAEnB,OADA,KAAK,aAAe,KAAK,QAAQ,MAAM,EAChC,KAGF,GAAG,CAAC,EAA8B,EAAuB,EAAyB,CACvF,GAAI,CAAC,KAAK,aACR,MAAM,IAAI,EAAoB,oDAAoD,EAEpF,OAAO,KAAK,aAAa,IAAI,EAAkB,EAAmB,CAAK,EAGlE,MAAM,CAAC,EAA8B,EAAuB,EAAyB,CAC1F,GAAI,CAAC,KAAK,aACR,MAAM,IAAI,EAAoB,oDAAoD,EAEpF,OAAO,KAAK,aAAa,OAAO,EAAkB,EAAmB,CAAK,EAE9E,CErCO,IAAK,GAAL,CAAK,IAAL,CACL,SAAS,SACT,OAAO,OACP,SAAS,SACT,SAAS,SACT,SAAS,SACT,OAAO,OACP,OAAO,OACP,UAAU,UACV,UAAU,UACV,UAAU,UACV,SAAS,SACT,WAAW,WACX,SAAS,SACT,QAAQ,QACR,OAAO,OACP,OAAO,OACP,SAAS,SACT,SAAS,SACT,UAAU,UACV,SAAS,SACT,WAAW,WACX,UAAU,UACV,OAAO,OACP,OAAO,OACP,UAAU,UACV,SAAS,SACT,WAAW,WACX,YAAY,YACZ,cAAc,cACd,SAAS,SACT,SAAS,SACT,QAAQ,QACR,OAAO,OACP,QAAQ,QACR,UAAU,UACV,SAAS,SACT,WAAW,WACX,MAAM,MACN,QAAQ,QACR,UAAU,UACV,QAAQ,QACR,SAAS,SACT,OAAO,OACP,YAAY,YACZ,UAAU,UACV,QAAQ,QACR,SAAS,SACT,SAAS,SACT,OAAO,OACP,WAAW,WACX,MAAM,MACN,QAAQ,QACR,OAAO,OACP,SAAS,SACT,QAAQ,QACR,OAAO,OACP,QAAQ,QACR,QAAQ,QACR,WAAW,WACX,SAAS,SACT,SAAS,SACT,QAAQ,QACR,SAAS,SACT,WAAW,WACX,aAAa,aACb,OAAO,OACP,OAAO,SAnEG,QAsEL,IAAK,GAAL,CAAK,IAAL,CACL,cAAc,aACd,mBAAmB,iBACnB,YAAY,WACZ,gBAAgB,eAChB,SAAS,SACT,OAAO,OACP,MAAM,QAPI",
11
+ "debugId": "2AFA4E169117EE2564756E2164756E21",
11
12
  "names": []
12
13
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ooneex/permission",
3
- "description": "",
4
- "version": "0.0.1",
3
+ "description": "Ability-based access control using CASL for fine-grained permission management",
4
+ "version": "0.0.4",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -25,18 +25,25 @@
25
25
  "test": "bun test tests",
26
26
  "build": "bunup",
27
27
  "lint": "tsgo --noEmit && bunx biome lint",
28
- "publish:prod": "bun publish --tolerate-republish --access public",
29
- "publish:pack": "bun pm pack --destination ./dist",
30
- "publish:dry": "bun publish --dry-run"
28
+ "publish": "bun publish --access public || true"
31
29
  },
32
30
  "dependencies": {
33
31
  "@casl/ability": "^6.7.3",
32
+ "@ooneex/container": "0.0.2",
34
33
  "@ooneex/exception": "0.0.1",
35
- "@ooneex/http-status": "0.0.1",
36
- "@ooneex/role": "0.0.1"
34
+ "@ooneex/http-status": "0.0.1"
37
35
  },
38
36
  "devDependencies": {
39
37
  "@ooneex/user": "0.0.1"
40
38
  },
41
- "peerDependencies": {}
39
+ "keywords": [
40
+ "authorization",
41
+ "bun",
42
+ "casl",
43
+ "ooneex",
44
+ "permission",
45
+ "permissions",
46
+ "rbac",
47
+ "typescript"
48
+ ]
42
49
  }