@moostjs/arbac 0.5.27

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 moostjs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # @moostjs/arbac
2
+
3
+ Advanced Role-Based Access Control (ARBAC) integration for MoostJS, enabling seamless authorization management with `@prostojs/arbac` while leveraging Moost's dependency injection and metadata-driven event processing capabilities.
4
+
5
+ ## Features
6
+
7
+ - **MoostJS Integration** – Provides decorators and utilities for enforcing access control.
8
+ - **Role & Scope-Based Authorization** – Supports fine-grained access control based on user roles and attributes.
9
+ - **Dependency Injection Support** – Utilizes MoostJS's DI system for injecting ARBAC services.
10
+ - **Easy Decorators** – Define resource-based access rules with simple decorators.
11
+
12
+ ## Installation
13
+
14
+ ```sh
15
+ npm install @moostjs/arbac
16
+ ```
17
+
18
+ or using pnpm:
19
+
20
+ ```sh
21
+ pnpm i @moostjs/arbac
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### Setup `MoostArbac`
27
+
28
+ To integrate ARBAC into your MoostJS application, define an instance of `MoostArbac`, register roles, and provide it as a dependency.
29
+
30
+ ```typescript
31
+ import { createProvideRegistry } from 'moost'
32
+ import { MoostArbac } from '@moostjs/arbac'
33
+ import * as roles from './roles'
34
+ import type { TRoleScope, TUserAttrs } from './types'
35
+
36
+ export const ArbacProvideRegistry = createProvideRegistry([
37
+ MoostArbac,
38
+ () => {
39
+ const instance = new MoostArbac<TUserAttrs, TRoleScope>()
40
+ for (const role of roles) {
41
+ instance.registerRole(role)
42
+ }
43
+ return instance
44
+ },
45
+ ])
46
+ ```
47
+
48
+ ### Define a Custom User Provider
49
+
50
+ To integrate user attributes and roles dynamically, replace the generic `ArbacUserProvider` with an application-specific implementation.
51
+
52
+ ```typescript
53
+ import { createReplaceRegistry } from 'moost'
54
+ import { ArbacUserProvider } from '@moostjs/arbac'
55
+ import { CustomUserProvider } from './custom-user-provider'
56
+
57
+ export const ArbacReplaceRegistry = createReplaceRegistry([ArbacUserProvider, CustomUserProvider])
58
+ ```
59
+
60
+ ### Register ARBAC in Moost Application
61
+
62
+ ```typescript
63
+ import { App } from 'moost'
64
+ import { ArbacProvideRegistry, ArbacReplaceRegistry } from './arbac-setup'
65
+
66
+ const app = new App()
67
+ app.setProvideRegistry(ArbacProvideRegistry)
68
+ app.setReplaceRegistry(ArbacReplaceRegistry)
69
+ ```
70
+
71
+ ### Protect Routes with `@Authorized()`
72
+
73
+ ```typescript
74
+ import { Authorized, Public } from '@moostjs/arbac'
75
+ import { Controller, Get } from 'moost'
76
+
77
+ @Controller('/data')
78
+ @ArbacAuthorized()
79
+ export class DataController {
80
+ @Get()
81
+ getProtectedData() {
82
+ return { data: 'secured' }
83
+ }
84
+
85
+ @Get('/public')
86
+ @ArbacPublic()
87
+ getPublicData() {
88
+ return { data: 'open' }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ## API
94
+
95
+ ### `MoostArbac<TUserAttrs, TScope>`
96
+
97
+ Extends `@prostojs/arbac` and integrates with MoostJS DI.
98
+
99
+ ### `ArbacUserProvider<TUserAttrs>`
100
+
101
+ Abstract class for defining user-related access control logic.
102
+
103
+ ### `@ArbacAuthorized()`
104
+
105
+ Method decorator to enforce ARBAC checks.
106
+
107
+ ### `@ArbacPublic()`
108
+
109
+ Marks a route as publicly accessible, bypassing authorization.
110
+
111
+ ### `useArbac()`
112
+
113
+ Composable function for evaluating access control dynamically.
114
+
115
+ ## License
116
+
117
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ //#region rolldown:runtime
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+
24
+ //#endregion
25
+ const moost = __toESM(require("moost"));
26
+ const __prostojs_arbac = __toESM(require("@prostojs/arbac"));
27
+ const __wooksjs_event_http = __toESM(require("@wooksjs/event-http"));
28
+
29
+ //#region packages/arbac/src/moost-arbac.ts
30
+ function _ts_decorate$1(decorators, target, key, desc) {
31
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
32
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
33
+ 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;
34
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
35
+ }
36
+ var MoostArbac = class extends __prostojs_arbac.Arbac {};
37
+ MoostArbac = _ts_decorate$1([(0, moost.Injectable)()], MoostArbac);
38
+
39
+ //#endregion
40
+ //#region packages/arbac/src/user.provider.ts
41
+ function _ts_decorate(decorators, target, key, desc) {
42
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
43
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
44
+ 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;
45
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
46
+ }
47
+ var ArbacUserProvider = class {
48
+ /**
49
+ * Retrieves the unique identifier of the user.
50
+ *
51
+ * @returns {string | Promise<string>} The user ID, or a rejected promise if not implemented.
52
+ * @throws {Error} If the method is not overridden by a subclass.
53
+ */ getUserId() {
54
+ return Promise.reject(new Error("ArbacUserProvider class must be extended"));
55
+ }
56
+ /**
57
+ * Retrieves the roles assigned to a user based on their ID.
58
+ *
59
+ * @param {string} id - The user ID.
60
+ * @returns {string[] | Promise<string[]>} An array of role identifiers, or a rejected promise if not implemented.
61
+ * @throws {Error} If the method is not overridden by a subclass.
62
+ */ getRoles(id) {
63
+ return Promise.reject(new Error("ArbacUserProvider class must be extended"));
64
+ }
65
+ /**
66
+ * Retrieves the attributes associated with a user based on their ID.
67
+ *
68
+ * @param {string} id - The user ID.
69
+ * @returns {TUserAttrs | Promise<TUserAttrs>} The user attributes, or a rejected promise if not implemented.
70
+ * @throws {Error} If the method is not overridden by a subclass.
71
+ */ getAttrs(id) {
72
+ return Promise.reject(new Error("ArbacUserProvider class must be extended"));
73
+ }
74
+ };
75
+ ArbacUserProvider = _ts_decorate([(0, moost.Injectable)()], ArbacUserProvider);
76
+
77
+ //#endregion
78
+ //#region packages/arbac/src/arbac.composables.ts
79
+ function useArbac() {
80
+ const store = (0, moost.useAsyncEventContext)().store("arbac");
81
+ const cc = (0, moost.useControllerContext)();
82
+ const getScopes = () => store.get("scopes");
83
+ const setScopes = (scope) => store.set("scopes", scope);
84
+ const evaluate = async (opts) => {
85
+ const user = await cc.instantiate(ArbacUserProvider);
86
+ const userId = await user.getUserId();
87
+ const arbac = await cc.instantiate(MoostArbac);
88
+ const result = await arbac.evaluate(opts, {
89
+ id: userId,
90
+ roles: await user.getRoles(userId),
91
+ attrs: async (id) => user.getAttrs(id)
92
+ });
93
+ Object.assign(result, { userId });
94
+ return result;
95
+ };
96
+ const cMeta = cc.getControllerMeta();
97
+ const mMeta = cc.getMethodMeta();
98
+ const resource = mMeta?.arbacResourceId || cMeta?.arbacResourceId || cMeta?.id || (0, moost.getConstructor)(cc.getController()).name;
99
+ const action = mMeta?.arbacActionId || mMeta?.id || cc.getMethod() || "";
100
+ const isPublic = mMeta?.arbacPublic || cMeta?.arbacPublic || false;
101
+ return {
102
+ getScopes,
103
+ setScopes,
104
+ evaluate,
105
+ resource,
106
+ action,
107
+ isPublic
108
+ };
109
+ }
110
+
111
+ //#endregion
112
+ //#region packages/arbac/src/arbac.mate.ts
113
+ function getArbacMate() {
114
+ return (0, moost.getMoostMate)();
115
+ }
116
+
117
+ //#endregion
118
+ //#region packages/arbac/src/arbac.decorator.ts
119
+ const arbackAuthorizeInterceptor = (0, moost.defineInterceptorFn)(async (before, after, onError) => {
120
+ const logger = (0, moost.useEventLogger)("arbac");
121
+ const { setScopes, evaluate, resource, action, isPublic } = useArbac();
122
+ if (!action || !resource || isPublic) return;
123
+ try {
124
+ const { allowed, scopes, userId } = await evaluate({
125
+ resource,
126
+ action
127
+ });
128
+ logger.debug(`[${userId}] ${allowed ? "Authorized" : "Blocked"} "${resource}" : "${action}"`);
129
+ if (!allowed) throw new __wooksjs_event_http.HttpError(403, `Insufficient privileges for action "${action}" on resource "${resource}"`);
130
+ setScopes(scopes);
131
+ } catch (error) {
132
+ if (error instanceof __wooksjs_event_http.HttpError) throw error;
133
+ logger.warn(error);
134
+ throw new __wooksjs_event_http.HttpError(401, `Authorization error`);
135
+ }
136
+ }, moost.TInterceptorPriority.GUARD);
137
+ const ArbacAuthorize = () => (0, moost.Intercept)(arbackAuthorizeInterceptor);
138
+ const ArbacScopes = () => (0, moost.Resolve)(() => useArbac().getScopes());
139
+ const ArbacResource = (name) => getArbacMate().decorate("arbacResourceId", name);
140
+ const ArbacAction = (name) => getArbacMate().decorate("arbacActionId", name);
141
+ const ArbacPublic = () => getArbacMate().decorate("arbacPublic", true);
142
+
143
+ //#endregion
144
+ exports.ArbacAction = ArbacAction
145
+ exports.ArbacAuthorize = ArbacAuthorize
146
+ exports.ArbacPublic = ArbacPublic
147
+ exports.ArbacResource = ArbacResource
148
+ exports.ArbacScopes = ArbacScopes
149
+ Object.defineProperty(exports, 'ArbacUserProvider', {
150
+ enumerable: true,
151
+ get: function () {
152
+ return ArbacUserProvider;
153
+ }
154
+ });
155
+ Object.defineProperty(exports, 'MoostArbac', {
156
+ enumerable: true,
157
+ get: function () {
158
+ return MoostArbac;
159
+ }
160
+ });
161
+ exports.arbackAuthorizeInterceptor = arbackAuthorizeInterceptor
162
+ exports.getArbacMate = getArbacMate
163
+ exports.useArbac = useArbac
@@ -0,0 +1,47 @@
1
+ import * as _prostojs_arbac from '@prostojs/arbac';
2
+ import { Arbac } from '@prostojs/arbac';
3
+ import * as moost from 'moost';
4
+ import { Mate, TMoostMetadata, TMateParamMeta } from 'moost';
5
+
6
+ declare function useArbac<TScope extends object>(): {
7
+ getScopes: () => TScope[] | undefined;
8
+ setScopes: (scope: TScope[] | undefined) => TScope[] | undefined;
9
+ evaluate: (opts: {
10
+ resource: string;
11
+ action: string;
12
+ }) => Promise<_prostojs_arbac.TArbacEvalResult<TScope> & {
13
+ userId: string;
14
+ }>;
15
+ resource: string;
16
+ action: string;
17
+ isPublic: boolean;
18
+ };
19
+
20
+ declare const arbackAuthorizeInterceptor: moost.TInterceptorFn;
21
+ declare const ArbacAuthorize: () => ClassDecorator & MethodDecorator;
22
+ declare const ArbacScopes: () => ParameterDecorator & PropertyDecorator;
23
+ declare const ArbacResource: (name: string) => MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
24
+ declare const ArbacAction: (name: string) => MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
25
+ declare const ArbacPublic: () => MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
26
+
27
+ interface TArbacMeta {
28
+ arbacResourceId?: string;
29
+ arbacActionId?: string;
30
+ arbacPublic?: boolean;
31
+ }
32
+ declare function getArbacMate(): Mate<TMoostMetadata & TArbacMeta & {
33
+ params: Array<TMateParamMeta>;
34
+ }, TMoostMetadata & TArbacMeta & {
35
+ params: Array<TMateParamMeta>;
36
+ }>;
37
+
38
+ declare class MoostArbac<TUserAttrs extends object, TScope extends object> extends Arbac<TUserAttrs, TScope> {
39
+ }
40
+
41
+ declare class ArbacUserProvider<TUserAttrs extends object> {
42
+ getUserId(): string | Promise<string>;
43
+ getRoles(id: string): string[] | Promise<string[]>;
44
+ getAttrs(id: string): TUserAttrs | Promise<TUserAttrs>;
45
+ }
46
+
47
+ export { ArbacAction, ArbacAuthorize, ArbacPublic, ArbacResource, ArbacScopes, ArbacUserProvider, MoostArbac, type TArbacMeta, arbackAuthorizeInterceptor, getArbacMate, useArbac };
package/dist/index.mjs ADDED
@@ -0,0 +1,120 @@
1
+ import { Injectable, Intercept, Resolve, TInterceptorPriority, defineInterceptorFn, getConstructor, getMoostMate, useAsyncEventContext, useControllerContext, useEventLogger } from "moost";
2
+ import { Arbac } from "@prostojs/arbac";
3
+ import { HttpError } from "@wooksjs/event-http";
4
+
5
+ //#region packages/arbac/src/moost-arbac.ts
6
+ function _ts_decorate$1(decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ 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;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ }
12
+ var MoostArbac = class extends Arbac {};
13
+ MoostArbac = _ts_decorate$1([Injectable()], MoostArbac);
14
+
15
+ //#endregion
16
+ //#region packages/arbac/src/user.provider.ts
17
+ function _ts_decorate(decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ 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;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ }
23
+ var ArbacUserProvider = class {
24
+ /**
25
+ * Retrieves the unique identifier of the user.
26
+ *
27
+ * @returns {string | Promise<string>} The user ID, or a rejected promise if not implemented.
28
+ * @throws {Error} If the method is not overridden by a subclass.
29
+ */ getUserId() {
30
+ return Promise.reject(new Error("ArbacUserProvider class must be extended"));
31
+ }
32
+ /**
33
+ * Retrieves the roles assigned to a user based on their ID.
34
+ *
35
+ * @param {string} id - The user ID.
36
+ * @returns {string[] | Promise<string[]>} An array of role identifiers, or a rejected promise if not implemented.
37
+ * @throws {Error} If the method is not overridden by a subclass.
38
+ */ getRoles(id) {
39
+ return Promise.reject(new Error("ArbacUserProvider class must be extended"));
40
+ }
41
+ /**
42
+ * Retrieves the attributes associated with a user based on their ID.
43
+ *
44
+ * @param {string} id - The user ID.
45
+ * @returns {TUserAttrs | Promise<TUserAttrs>} The user attributes, or a rejected promise if not implemented.
46
+ * @throws {Error} If the method is not overridden by a subclass.
47
+ */ getAttrs(id) {
48
+ return Promise.reject(new Error("ArbacUserProvider class must be extended"));
49
+ }
50
+ };
51
+ ArbacUserProvider = _ts_decorate([Injectable()], ArbacUserProvider);
52
+
53
+ //#endregion
54
+ //#region packages/arbac/src/arbac.composables.ts
55
+ function useArbac() {
56
+ const store = useAsyncEventContext().store("arbac");
57
+ const cc = useControllerContext();
58
+ const getScopes = () => store.get("scopes");
59
+ const setScopes = (scope) => store.set("scopes", scope);
60
+ const evaluate = async (opts) => {
61
+ const user = await cc.instantiate(ArbacUserProvider);
62
+ const userId = await user.getUserId();
63
+ const arbac = await cc.instantiate(MoostArbac);
64
+ const result = await arbac.evaluate(opts, {
65
+ id: userId,
66
+ roles: await user.getRoles(userId),
67
+ attrs: async (id) => user.getAttrs(id)
68
+ });
69
+ Object.assign(result, { userId });
70
+ return result;
71
+ };
72
+ const cMeta = cc.getControllerMeta();
73
+ const mMeta = cc.getMethodMeta();
74
+ const resource = mMeta?.arbacResourceId || cMeta?.arbacResourceId || cMeta?.id || getConstructor(cc.getController()).name;
75
+ const action = mMeta?.arbacActionId || mMeta?.id || cc.getMethod() || "";
76
+ const isPublic = mMeta?.arbacPublic || cMeta?.arbacPublic || false;
77
+ return {
78
+ getScopes,
79
+ setScopes,
80
+ evaluate,
81
+ resource,
82
+ action,
83
+ isPublic
84
+ };
85
+ }
86
+
87
+ //#endregion
88
+ //#region packages/arbac/src/arbac.mate.ts
89
+ function getArbacMate() {
90
+ return getMoostMate();
91
+ }
92
+
93
+ //#endregion
94
+ //#region packages/arbac/src/arbac.decorator.ts
95
+ const arbackAuthorizeInterceptor = defineInterceptorFn(async (before, after, onError) => {
96
+ const logger = useEventLogger("arbac");
97
+ const { setScopes, evaluate, resource, action, isPublic } = useArbac();
98
+ if (!action || !resource || isPublic) return;
99
+ try {
100
+ const { allowed, scopes, userId } = await evaluate({
101
+ resource,
102
+ action
103
+ });
104
+ logger.debug(`[${userId}] ${allowed ? "Authorized" : "Blocked"} "${resource}" : "${action}"`);
105
+ if (!allowed) throw new HttpError(403, `Insufficient privileges for action "${action}" on resource "${resource}"`);
106
+ setScopes(scopes);
107
+ } catch (error) {
108
+ if (error instanceof HttpError) throw error;
109
+ logger.warn(error);
110
+ throw new HttpError(401, `Authorization error`);
111
+ }
112
+ }, TInterceptorPriority.GUARD);
113
+ const ArbacAuthorize = () => Intercept(arbackAuthorizeInterceptor);
114
+ const ArbacScopes = () => Resolve(() => useArbac().getScopes());
115
+ const ArbacResource = (name) => getArbacMate().decorate("arbacResourceId", name);
116
+ const ArbacAction = (name) => getArbacMate().decorate("arbacActionId", name);
117
+ const ArbacPublic = () => getArbacMate().decorate("arbacPublic", true);
118
+
119
+ //#endregion
120
+ export { ArbacAction, ArbacAuthorize, ArbacPublic, ArbacResource, ArbacScopes, ArbacUserProvider, MoostArbac, arbackAuthorizeInterceptor, getArbacMate, useArbac };
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@moostjs/arbac",
3
+ "version": "0.5.27",
4
+ "description": "Access Control @prostojs/arbac",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ "./package.json": "./package.json",
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/moostjs/moostjs.git",
23
+ "directory": "packages/arbac"
24
+ },
25
+ "keywords": [
26
+ "moost",
27
+ "moostjs",
28
+ "arbac",
29
+ "rbac",
30
+ "abac",
31
+ "access control"
32
+ ],
33
+ "author": "Artem Maltsev",
34
+ "license": "MIT",
35
+ "bugs": {
36
+ "url": "https://github.com/moostjs/moostjs/issues"
37
+ },
38
+ "homepage": "https://github.com/moostjs/moostjs/tree/main/packages/arbac#readme",
39
+ "dependencies": {
40
+ "@wooksjs/event-http": "^0.5.25",
41
+ "@prostojs/arbac": "^0.0.2",
42
+ "moost": "^0.5.27"
43
+ },
44
+ "devDependencies": {
45
+ "vitest": "^3.0.5"
46
+ },
47
+ "scripts": {
48
+ "pub": "pnpm publish --access public",
49
+ "test": "vitest"
50
+ }
51
+ }