@iushev/react-rbac 1.0.40 → 1.0.42
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/eslint.config.mjs +22 -2
- package/lib/CheckAccess.d.ts.map +1 -1
- package/lib/CheckAccess.js +2 -1
- package/lib/NullComponent.d.ts +4 -0
- package/lib/NullComponent.d.ts.map +1 -0
- package/lib/NullComponent.js +4 -0
- package/lib/RbacContext.d.ts +5 -6
- package/lib/RbacContext.d.ts.map +1 -1
- package/lib/RbacContext.js +29 -56
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/useCheckAccess.d.ts.map +1 -1
- package/lib/useCheckAccess.js +31 -20
- package/package.json +21 -19
- package/src/CheckAccess.tsx +2 -1
- package/src/NullComponent.tsx +5 -0
- package/src/RbacContext.tsx +35 -62
- package/src/index.ts +1 -0
- package/src/useCheckAccess.ts +14 -11
- package/lib/RbacCheckAccess.d.ts +0 -18
- package/lib/RbacCheckAccess.d.ts.map +0 -1
- package/lib/RbacCheckAccess.js +0 -137
- package/src/RbacCheckAccess.ts +0 -144
package/eslint.config.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { fixupConfigRules, fixupPluginRules } from "@eslint/compat";
|
|
2
|
+
import react from "eslint-plugin-react";
|
|
3
|
+
import reactHooks from "eslint-plugin-react-hooks";
|
|
1
4
|
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
|
2
5
|
import prettier from "eslint-plugin-prettier";
|
|
3
6
|
import globals from "globals";
|
|
@@ -19,10 +22,21 @@ export default [
|
|
|
19
22
|
{
|
|
20
23
|
ignores: ["**/lib/", "**/node_modules/"],
|
|
21
24
|
},
|
|
22
|
-
...
|
|
25
|
+
...fixupConfigRules(
|
|
26
|
+
compat.extends(
|
|
27
|
+
"eslint:recommended",
|
|
28
|
+
"plugin:react/recommended",
|
|
29
|
+
"plugin:react/jsx-runtime",
|
|
30
|
+
"plugin:react-hooks/recommended",
|
|
31
|
+
"plugin:@typescript-eslint/recommended",
|
|
32
|
+
"prettier",
|
|
33
|
+
),
|
|
34
|
+
),
|
|
23
35
|
{
|
|
24
36
|
plugins: {
|
|
25
|
-
|
|
37
|
+
react: fixupPluginRules(react),
|
|
38
|
+
"react-hooks": fixupPluginRules(reactHooks),
|
|
39
|
+
"@typescript-eslint": fixupPluginRules(typescriptEslint),
|
|
26
40
|
prettier,
|
|
27
41
|
},
|
|
28
42
|
|
|
@@ -37,6 +51,12 @@ export default [
|
|
|
37
51
|
sourceType: "module",
|
|
38
52
|
},
|
|
39
53
|
|
|
54
|
+
settings: {
|
|
55
|
+
react: {
|
|
56
|
+
version: "detect",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
|
|
40
60
|
rules: {
|
|
41
61
|
"@typescript-eslint/no-namespace": "off",
|
|
42
62
|
"@typescript-eslint/no-explicit-any": "off",
|
package/lib/CheckAccess.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckAccess.d.ts","sourceRoot":"","sources":["../src/CheckAccess.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"CheckAccess.d.ts","sourceRoot":"","sources":["../src/CheckAccess.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAKnD,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG;IAClD,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAgB3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
package/lib/CheckAccess.js
CHANGED
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const useCheckAccess_1 = __importDefault(require("./useCheckAccess"));
|
|
8
8
|
const NoAccess_1 = __importDefault(require("./NoAccess"));
|
|
9
|
-
const
|
|
9
|
+
const NullComponent_1 = __importDefault(require("./NullComponent"));
|
|
10
|
+
const CheckAccess = ({ roles, allow, params, match, busy: BusyComponent = NullComponent_1.default, noAccess: NoAccessComponent = NoAccess_1.default, children, }) => {
|
|
10
11
|
const { checking, hasAccess } = (0, useCheckAccess_1.default)({ roles, allow, params, match });
|
|
11
12
|
if (checking) {
|
|
12
13
|
return (0, jsx_runtime_1.jsx)(BusyComponent, {});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NullComponent.d.ts","sourceRoot":"","sources":["../src/NullComponent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAe,CAAC;AAE3C,eAAe,aAAa,CAAC"}
|
package/lib/RbacContext.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { RuleParams, Rule, RuleCtor } from "@iushev/rbac";
|
|
3
|
-
import RbacCheckAccess from "./RbacCheckAccess";
|
|
2
|
+
import { RuleParams, Rule, RuleCtor, Identity, BaseManager } from "@iushev/rbac";
|
|
4
3
|
export type RuleParamsFunction = () => RuleParams;
|
|
5
4
|
export type MatchFunction = () => boolean;
|
|
6
5
|
export type CheckAccessOptions = {
|
|
@@ -10,19 +9,19 @@ export type CheckAccessOptions = {
|
|
|
10
9
|
match?: MatchFunction;
|
|
11
10
|
};
|
|
12
11
|
export type RbacContextProps = {
|
|
13
|
-
|
|
12
|
+
rbacManager: BaseManager | null;
|
|
14
13
|
checkAccess: (options: CheckAccessOptions) => Promise<boolean>;
|
|
15
14
|
};
|
|
16
15
|
declare const RbacContext: React.Context<RbacContextProps | null>;
|
|
17
16
|
export declare const useRbac: () => RbacContextProps;
|
|
18
17
|
export type RbacProviderProps = {
|
|
19
|
-
|
|
18
|
+
identity: Identity;
|
|
20
19
|
rbacUrl: string;
|
|
21
20
|
token: string;
|
|
22
|
-
isSuperuser: boolean;
|
|
23
|
-
isGuest: boolean;
|
|
24
21
|
ruleClasses: Map<string, RuleCtor<Rule>>;
|
|
22
|
+
afterInitManager?: (webManager: any) => void;
|
|
25
23
|
children: React.ReactNode;
|
|
24
|
+
logging?: false | ((...args: any[]) => void);
|
|
26
25
|
};
|
|
27
26
|
export declare const RbacProvider: React.FC<RbacProviderProps>;
|
|
28
27
|
export declare const RbacConsumer: React.Consumer<RbacContextProps | null>;
|
package/lib/RbacContext.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RbacContext.d.ts","sourceRoot":"","sources":["../src/RbacContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAErF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"RbacContext.d.ts","sourceRoot":"","sources":["../src/RbacContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAErF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAuB,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGtG,MAAM,MAAM,kBAAkB,GAAG,MAAM,UAAU,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC;AAC1C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,GAAG,kBAAkB,CAAC;IACzC,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE,CAAC;AAEF,QAAA,MAAM,WAAW,wCAAqD,CAAC;AAEvE,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA0DpD,CAAC;AAEF,eAAO,MAAM,YAAY,yCAAuB,CAAC;AAEjD,eAAe,WAAW,CAAC"}
|
package/lib/RbacContext.js
CHANGED
|
@@ -41,14 +41,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
41
41
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
-
};
|
|
47
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
45
|
exports.RbacConsumer = exports.RbacProvider = exports.useRbac = void 0;
|
|
49
46
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
50
47
|
const react_1 = __importStar(require("react"));
|
|
51
|
-
const
|
|
48
|
+
const rbac_1 = require("@iushev/rbac");
|
|
49
|
+
const rbac_web_manager_1 = require("@iushev/rbac-web-manager");
|
|
52
50
|
const RbacContext = react_1.default.createContext(null);
|
|
53
51
|
const useRbac = () => {
|
|
54
52
|
const ctx = (0, react_1.useContext)(RbacContext);
|
|
@@ -58,70 +56,45 @@ const useRbac = () => {
|
|
|
58
56
|
return ctx;
|
|
59
57
|
};
|
|
60
58
|
exports.useRbac = useRbac;
|
|
61
|
-
const RbacProvider = ({
|
|
62
|
-
const [
|
|
59
|
+
const RbacProvider = ({ identity, rbacUrl, token, ruleClasses, children, logging, }) => {
|
|
60
|
+
const [rbacManager, setRbacManager] = (0, react_1.useState)(null);
|
|
63
61
|
(0, react_1.useEffect)(() => {
|
|
64
62
|
const initRbac = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
});
|
|
78
|
-
yield _rbac.load();
|
|
79
|
-
setRbac(_rbac);
|
|
80
|
-
}
|
|
63
|
+
const manager = new rbac_web_manager_1.WebManager({
|
|
64
|
+
path: rbacUrl,
|
|
65
|
+
authorization: () => {
|
|
66
|
+
return token;
|
|
67
|
+
},
|
|
68
|
+
logging,
|
|
69
|
+
});
|
|
70
|
+
ruleClasses.forEach((RuleClass, ruleName) => {
|
|
71
|
+
manager.ruleClasses.set(ruleName, RuleClass);
|
|
72
|
+
});
|
|
73
|
+
yield manager.load();
|
|
74
|
+
setRbacManager(manager);
|
|
81
75
|
});
|
|
82
76
|
initRbac();
|
|
83
|
-
}, [rbacUrl,
|
|
84
|
-
const
|
|
85
|
-
if (!
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
if (!rbac) {
|
|
77
|
+
}, [logging, rbacUrl, ruleClasses, token]);
|
|
78
|
+
const checkAccess = (0, react_1.useCallback)((_a) => __awaiter(void 0, [_a], void 0, function* ({ roles, allow = true, match, params = {} }) {
|
|
79
|
+
if (!rbacManager) {
|
|
89
80
|
return false;
|
|
90
81
|
}
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
// only guest users
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
else if (role === "@" && !isGuest) {
|
|
97
|
-
// only authenticated users
|
|
82
|
+
const matchCustom = (match) => {
|
|
83
|
+
if (!match) {
|
|
98
84
|
return true;
|
|
99
85
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return false;
|
|
109
|
-
}), [isGuest, rbac, username]);
|
|
110
|
-
const matchCustom = (0, react_1.useCallback)((match) => {
|
|
111
|
-
if (!match) {
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
return match();
|
|
115
|
-
}, []);
|
|
116
|
-
const checkAccess = (0, react_1.useCallback)((_a) => __awaiter(void 0, [_a], void 0, function* ({ roles, allow = true, match, params = {} }) {
|
|
117
|
-
return isSuperuser || ((yield matchRole(roles, params)) && matchCustom(match) && allow);
|
|
118
|
-
}), [isSuperuser, matchCustom, matchRole]);
|
|
86
|
+
return match();
|
|
87
|
+
};
|
|
88
|
+
const user = new rbac_1.RbacUser(rbacManager);
|
|
89
|
+
user.identity = identity;
|
|
90
|
+
return user.isSuperuser || ((yield (0, rbac_1.matchRole)({ user, roles, params })) && matchCustom(match) && allow);
|
|
91
|
+
}), [identity, rbacManager]);
|
|
119
92
|
const value = (0, react_1.useMemo)(() => {
|
|
120
93
|
return {
|
|
121
|
-
|
|
94
|
+
rbacManager,
|
|
122
95
|
checkAccess,
|
|
123
96
|
};
|
|
124
|
-
}, [
|
|
97
|
+
}, [rbacManager, checkAccess]);
|
|
125
98
|
return (0, jsx_runtime_1.jsx)(RbacContext.Provider, { value: value, children: children });
|
|
126
99
|
};
|
|
127
100
|
exports.RbacProvider = RbacProvider;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as RbacContext, RbacConsumer, RbacProvider, useRbac } from "./RbacContext";
|
|
2
2
|
export { default as CheckAccess, CheckAccessProps } from "./CheckAccess";
|
|
3
3
|
export { default as NoAccess } from "./NoAccess";
|
|
4
|
+
export { default as NullComponent } from "./NullComponent";
|
|
4
5
|
export { default as useCheckAccess } from "./useCheckAccess";
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useCheckAccess = exports.NoAccess = exports.CheckAccess = exports.useRbac = exports.RbacProvider = exports.RbacConsumer = exports.RbacContext = void 0;
|
|
6
|
+
exports.useCheckAccess = exports.NullComponent = exports.NoAccess = exports.CheckAccess = exports.useRbac = exports.RbacProvider = exports.RbacConsumer = exports.RbacContext = void 0;
|
|
7
7
|
var RbacContext_1 = require("./RbacContext");
|
|
8
8
|
Object.defineProperty(exports, "RbacContext", { enumerable: true, get: function () { return __importDefault(RbacContext_1).default; } });
|
|
9
9
|
Object.defineProperty(exports, "RbacConsumer", { enumerable: true, get: function () { return RbacContext_1.RbacConsumer; } });
|
|
@@ -13,5 +13,7 @@ var CheckAccess_1 = require("./CheckAccess");
|
|
|
13
13
|
Object.defineProperty(exports, "CheckAccess", { enumerable: true, get: function () { return __importDefault(CheckAccess_1).default; } });
|
|
14
14
|
var NoAccess_1 = require("./NoAccess");
|
|
15
15
|
Object.defineProperty(exports, "NoAccess", { enumerable: true, get: function () { return __importDefault(NoAccess_1).default; } });
|
|
16
|
+
var NullComponent_1 = require("./NullComponent");
|
|
17
|
+
Object.defineProperty(exports, "NullComponent", { enumerable: true, get: function () { return __importDefault(NullComponent_1).default; } });
|
|
16
18
|
var useCheckAccess_1 = require("./useCheckAccess");
|
|
17
19
|
Object.defineProperty(exports, "useCheckAccess", { enumerable: true, get: function () { return __importDefault(useCheckAccess_1).default; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCheckAccess.d.ts","sourceRoot":"","sources":["../src/useCheckAccess.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAW,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,iBAAS,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"useCheckAccess.d.ts","sourceRoot":"","sources":["../src/useCheckAccess.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAW,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,iBAAS,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,kBAAkB,oBA4C1E;AAED,eAAe,cAAc,CAAC"}
|
package/lib/useCheckAccess.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
const react_1 = require("react");
|
|
4
13
|
const RbacContext_1 = require("./RbacContext");
|
|
@@ -10,29 +19,31 @@ function useCheckAccess({ roles, allow, params, match }) {
|
|
|
10
19
|
});
|
|
11
20
|
(0, react_1.useEffect)(() => {
|
|
12
21
|
let subscribed = true;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const checkAccess = () => __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
setState({
|
|
24
|
+
checking: true,
|
|
25
|
+
hasAccess: false,
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
const result = yield rbac.checkAccess({ roles, allow, params, match });
|
|
29
|
+
if (subscribed) {
|
|
30
|
+
setState({
|
|
31
|
+
checking: false,
|
|
32
|
+
hasAccess: result,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
25
35
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.error(err);
|
|
38
|
+
if (subscribed) {
|
|
39
|
+
setState({
|
|
40
|
+
checking: false,
|
|
41
|
+
hasAccess: false,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
34
44
|
}
|
|
35
45
|
});
|
|
46
|
+
checkAccess();
|
|
36
47
|
return () => {
|
|
37
48
|
subscribed = false;
|
|
38
49
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iushev/react-rbac",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.42",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Ivaylo Ushev",
|
|
6
6
|
"description": "",
|
|
@@ -9,36 +9,38 @@
|
|
|
9
9
|
"main": "./lib/index",
|
|
10
10
|
"types": "./lib/index",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"build": "tsc",
|
|
12
|
+
"build": "rimraf ./lib && tsc",
|
|
13
13
|
"watch": "tsc -w --preserveWatchOutput",
|
|
14
14
|
"test": "jest --runInBand",
|
|
15
15
|
"test:watch": "jest --watchAll --runInBand",
|
|
16
16
|
"coverage": "jest --coverage --runInBand",
|
|
17
17
|
"lint": "eslint src",
|
|
18
|
-
"preversion": "
|
|
18
|
+
"preversion": "npm run build"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"http-status-codes": "^2.3.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@
|
|
25
|
-
"@types/react
|
|
26
|
-
"@
|
|
27
|
-
"@typescript-eslint/
|
|
28
|
-
"eslint": "^
|
|
29
|
-
"eslint
|
|
30
|
-
"eslint-
|
|
31
|
-
"eslint-plugin-
|
|
32
|
-
"eslint-plugin-react
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
24
|
+
"@eslint/compat": "^2.0.0",
|
|
25
|
+
"@types/react": "^19.2.7",
|
|
26
|
+
"@types/react-dom": "^19.2.3",
|
|
27
|
+
"@typescript-eslint/eslint-plugin": "^8.50.0",
|
|
28
|
+
"@typescript-eslint/parser": "^8.50.0",
|
|
29
|
+
"eslint": "^9.39.2",
|
|
30
|
+
"eslint-config-prettier": "^10.1.8",
|
|
31
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
32
|
+
"eslint-plugin-react": "^7.37.5",
|
|
33
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
34
|
+
"jest": "^30.2.0",
|
|
35
|
+
"prettier": "^3.7.4",
|
|
36
|
+
"rimraf": "^6.1.2",
|
|
37
|
+
"ts-jest": "^29.4.6",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
|
-
"@iushev/rbac": "^1.0.
|
|
41
|
-
"
|
|
41
|
+
"@iushev/rbac": "^1.0.54",
|
|
42
|
+
"@iushev/rbac-web-manager": "^1.0.2",
|
|
43
|
+
"axios": "^1.13.2",
|
|
42
44
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
43
45
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
44
46
|
},
|
package/src/CheckAccess.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import React from "react";
|
|
|
3
3
|
import { CheckAccessOptions } from "./RbacContext";
|
|
4
4
|
import useCheckAccess from "./useCheckAccess";
|
|
5
5
|
import NoAccess from "./NoAccess";
|
|
6
|
+
import NullComponent from "./NullComponent";
|
|
6
7
|
|
|
7
8
|
export type CheckAccessProps = CheckAccessOptions & {
|
|
8
9
|
busy?: React.ComponentType;
|
|
@@ -15,7 +16,7 @@ const CheckAccess: React.FC<CheckAccessProps> = ({
|
|
|
15
16
|
allow,
|
|
16
17
|
params,
|
|
17
18
|
match,
|
|
18
|
-
busy: BusyComponent =
|
|
19
|
+
busy: BusyComponent = NullComponent,
|
|
19
20
|
noAccess: NoAccessComponent = NoAccess,
|
|
20
21
|
children,
|
|
21
22
|
}) => {
|
package/src/RbacContext.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
2
2
|
|
|
3
|
-
import { RuleParams, Rule, RuleCtor } from "@iushev/rbac";
|
|
4
|
-
import
|
|
3
|
+
import { RuleParams, Rule, RuleCtor, RbacUser, matchRole, Identity, BaseManager } from "@iushev/rbac";
|
|
4
|
+
import { WebManager } from "@iushev/rbac-web-manager";
|
|
5
5
|
|
|
6
6
|
export type RuleParamsFunction = () => RuleParams;
|
|
7
7
|
export type MatchFunction = () => boolean;
|
|
@@ -13,7 +13,7 @@ export type CheckAccessOptions = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export type RbacContextProps = {
|
|
16
|
-
|
|
16
|
+
rbacManager: BaseManager | null;
|
|
17
17
|
checkAccess: (options: CheckAccessOptions) => Promise<boolean>;
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -28,98 +28,71 @@ export const useRbac = (): RbacContextProps => {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export type RbacProviderProps = {
|
|
31
|
-
|
|
31
|
+
identity: Identity;
|
|
32
32
|
rbacUrl: string;
|
|
33
33
|
token: string;
|
|
34
|
-
isSuperuser: boolean;
|
|
35
|
-
isGuest: boolean;
|
|
36
34
|
ruleClasses: Map<string, RuleCtor<Rule>>;
|
|
35
|
+
afterInitManager?: (webManager: any) => void;
|
|
37
36
|
children: React.ReactNode;
|
|
37
|
+
logging?: false | ((...args: any[]) => void);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
export const RbacProvider: React.FC<RbacProviderProps> = ({
|
|
41
|
-
|
|
41
|
+
identity,
|
|
42
42
|
rbacUrl,
|
|
43
43
|
token,
|
|
44
|
-
isSuperuser,
|
|
45
|
-
isGuest,
|
|
46
44
|
ruleClasses,
|
|
47
45
|
children,
|
|
46
|
+
logging,
|
|
48
47
|
}) => {
|
|
49
|
-
const [
|
|
48
|
+
const [rbacManager, setRbacManager] = useState<BaseManager | null>(null);
|
|
50
49
|
|
|
51
50
|
useEffect(() => {
|
|
52
51
|
const initRbac = async () => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
await _rbac.load();
|
|
66
|
-
setRbac(_rbac);
|
|
67
|
-
}
|
|
52
|
+
const manager = new WebManager({
|
|
53
|
+
path: rbacUrl,
|
|
54
|
+
authorization: () => {
|
|
55
|
+
return token;
|
|
56
|
+
},
|
|
57
|
+
logging,
|
|
58
|
+
});
|
|
59
|
+
ruleClasses.forEach((RuleClass, ruleName) => {
|
|
60
|
+
manager.ruleClasses.set(ruleName, RuleClass);
|
|
61
|
+
});
|
|
62
|
+
await manager.load();
|
|
63
|
+
setRbacManager(manager);
|
|
68
64
|
};
|
|
69
65
|
|
|
70
66
|
initRbac();
|
|
71
|
-
}, [rbacUrl,
|
|
72
|
-
|
|
73
|
-
const matchRole = useCallback(
|
|
74
|
-
async (roles: string[], params: RuleParams | RuleParamsFunction) => {
|
|
75
|
-
if (!roles || roles.length === 0) {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
67
|
+
}, [logging, rbacUrl, ruleClasses, token]);
|
|
78
68
|
|
|
79
|
-
|
|
69
|
+
const checkAccess = useCallback(
|
|
70
|
+
async ({ roles, allow = true, match, params = {} }: CheckAccessOptions) => {
|
|
71
|
+
if (!rbacManager) {
|
|
80
72
|
return false;
|
|
81
73
|
}
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
// only guest users
|
|
86
|
-
return true;
|
|
87
|
-
} else if (role === "@" && !isGuest) {
|
|
88
|
-
// only authenticated users
|
|
89
|
-
return true;
|
|
90
|
-
} else if (await rbac.checkAccess(username, role, typeof params === "function" ? params() : params)) {
|
|
91
|
-
// only authenticated users that has permission
|
|
75
|
+
const matchCustom = (match?: MatchFunction) => {
|
|
76
|
+
if (!match) {
|
|
92
77
|
return true;
|
|
93
|
-
} else {
|
|
94
|
-
continue;
|
|
95
78
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return false;
|
|
99
|
-
},
|
|
100
|
-
[isGuest, rbac, username],
|
|
101
|
-
);
|
|
79
|
+
return match();
|
|
80
|
+
};
|
|
102
81
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
return match();
|
|
108
|
-
}, []);
|
|
82
|
+
const user = new RbacUser(rbacManager);
|
|
83
|
+
user.identity = identity;
|
|
109
84
|
|
|
110
|
-
|
|
111
|
-
async ({ roles, allow = true, match, params = {} }: CheckAccessOptions) => {
|
|
112
|
-
return isSuperuser || ((await matchRole(roles, params)) && matchCustom(match) && allow);
|
|
85
|
+
return user.isSuperuser || ((await matchRole({ user, roles, params })) && matchCustom(match) && allow);
|
|
113
86
|
},
|
|
114
|
-
[
|
|
87
|
+
[identity, rbacManager],
|
|
115
88
|
);
|
|
116
89
|
|
|
117
90
|
const value = useMemo(() => {
|
|
118
91
|
return {
|
|
119
|
-
|
|
92
|
+
rbacManager,
|
|
120
93
|
checkAccess,
|
|
121
94
|
};
|
|
122
|
-
}, [
|
|
95
|
+
}, [rbacManager, checkAccess]);
|
|
123
96
|
|
|
124
97
|
return <RbacContext.Provider value={value}>{children}</RbacContext.Provider>;
|
|
125
98
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as RbacContext, RbacConsumer, RbacProvider, useRbac } from "./RbacContext";
|
|
2
2
|
export { default as CheckAccess, CheckAccessProps } from "./CheckAccess";
|
|
3
3
|
export { default as NoAccess } from "./NoAccess";
|
|
4
|
+
export { default as NullComponent } from "./NullComponent";
|
|
4
5
|
export { default as useCheckAccess } from "./useCheckAccess";
|
package/src/useCheckAccess.ts
CHANGED
|
@@ -16,22 +16,22 @@ function useCheckAccess({ roles, allow, params, match }: CheckAccessOptions) {
|
|
|
16
16
|
|
|
17
17
|
useEffect(() => {
|
|
18
18
|
let subscribed = true;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
|
|
20
|
+
const checkAccess = async () => {
|
|
21
|
+
setState({
|
|
22
|
+
checking: true,
|
|
23
|
+
hasAccess: false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const result = await rbac.checkAccess({ roles, allow, params, match });
|
|
27
28
|
if (subscribed) {
|
|
28
29
|
setState({
|
|
29
30
|
checking: false,
|
|
30
31
|
hasAccess: result,
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
|
-
})
|
|
34
|
-
.catch((err) => {
|
|
34
|
+
} catch (err) {
|
|
35
35
|
console.error(err);
|
|
36
36
|
if (subscribed) {
|
|
37
37
|
setState({
|
|
@@ -39,7 +39,10 @@ function useCheckAccess({ roles, allow, params, match }: CheckAccessOptions) {
|
|
|
39
39
|
hasAccess: false,
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
-
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
checkAccess();
|
|
43
46
|
|
|
44
47
|
return () => {
|
|
45
48
|
subscribed = false;
|
package/lib/RbacCheckAccess.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { AxiosRequestConfig } from "axios";
|
|
2
|
-
import { Assignment, BaseCheckAccess, BaseCheckAccessOptions, RuleParams } from "@iushev/rbac";
|
|
3
|
-
export type RbacCheckAccessOptions = BaseCheckAccessOptions & {
|
|
4
|
-
path: string;
|
|
5
|
-
authorization: () => string;
|
|
6
|
-
};
|
|
7
|
-
export default class RbacCheckAccess extends BaseCheckAccess {
|
|
8
|
-
private readonly axiosInstance;
|
|
9
|
-
protected assignments: Map<string, Map<string, Assignment>>;
|
|
10
|
-
constructor(options: RbacCheckAccessOptions);
|
|
11
|
-
checkAccess(username: string, itemName: string, params: RuleParams): Promise<boolean>;
|
|
12
|
-
load(config?: AxiosRequestConfig): Promise<void>;
|
|
13
|
-
private getRbacItems;
|
|
14
|
-
private getRbacParents;
|
|
15
|
-
private getRbacRules;
|
|
16
|
-
private getRbacAssignments;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=RbacCheckAccess.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RbacCheckAccess.d.ts","sourceRoot":"","sources":["../src/RbacCheckAccess.ts"],"names":[],"mappings":"AAAA,OAAc,EAAiB,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAGjE,OAAO,EACL,UAAU,EACV,eAAe,EACf,sBAAsB,EAOtB,UAAU,EACX,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,GAAG;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,eAAe;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAE9C,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAa;gBAE5D,OAAO,EAAE,sBAAsB;IAkB9B,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrF,IAAI,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB7D,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,cAAc;IA4BtB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,kBAAkB;CAa3B"}
|
package/lib/RbacCheckAccess.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const axios_1 = __importDefault(require("axios"));
|
|
16
|
-
const http_status_codes_1 = __importDefault(require("http-status-codes"));
|
|
17
|
-
const rbac_1 = require("@iushev/rbac");
|
|
18
|
-
class RbacCheckAccess extends rbac_1.BaseCheckAccess {
|
|
19
|
-
constructor(options) {
|
|
20
|
-
super(options);
|
|
21
|
-
this.assignments = new Map();
|
|
22
|
-
this.axiosInstance = axios_1.default.create({
|
|
23
|
-
baseURL: options.path,
|
|
24
|
-
});
|
|
25
|
-
this.axiosInstance.interceptors.request.use((config) => {
|
|
26
|
-
if (options.authorization) {
|
|
27
|
-
const token = options.authorization();
|
|
28
|
-
config.headers.Authorization = "Bearer " + token;
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
config.headers.Authorization = undefined;
|
|
32
|
-
}
|
|
33
|
-
return config;
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
checkAccess(username, itemName, params) {
|
|
37
|
-
const _super = Object.create(null, {
|
|
38
|
-
checkAccess: { get: () => super.checkAccess }
|
|
39
|
-
});
|
|
40
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
-
var _a;
|
|
42
|
-
if (this.items.size === 0) {
|
|
43
|
-
yield this.load();
|
|
44
|
-
}
|
|
45
|
-
return _super.checkAccess.call(this, username, itemName, params, (_a = this.assignments.get(username)) !== null && _a !== void 0 ? _a : new Map());
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
load(config) {
|
|
49
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
var _a;
|
|
51
|
-
let _rbac;
|
|
52
|
-
try {
|
|
53
|
-
console.log("Load RBAC");
|
|
54
|
-
const response = yield this.axiosInstance.get("/rbac", config);
|
|
55
|
-
_rbac = response.data;
|
|
56
|
-
}
|
|
57
|
-
catch (err) {
|
|
58
|
-
if (axios_1.default.isAxiosError(err) && ((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === http_status_codes_1.default.NOT_FOUND) {
|
|
59
|
-
_rbac = {
|
|
60
|
-
assignments: {},
|
|
61
|
-
items: {},
|
|
62
|
-
rules: {},
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
throw err;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
this.items = this.getRbacItems(_rbac);
|
|
70
|
-
this.parents = this.getRbacParents(_rbac);
|
|
71
|
-
this.rules = this.getRbacRules(_rbac);
|
|
72
|
-
this.assignments = this.getRbacAssignments(_rbac);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
getRbacItems({ items }) {
|
|
76
|
-
return Object.keys(items).reduce((prevValue, name) => {
|
|
77
|
-
var _a, _b;
|
|
78
|
-
const item = items[name];
|
|
79
|
-
const ItemClass = item.type === rbac_1.ItemType.permission ? rbac_1.Permission : rbac_1.Role;
|
|
80
|
-
prevValue.set(name, new ItemClass({
|
|
81
|
-
name,
|
|
82
|
-
description: (_a = item.description) !== null && _a !== void 0 ? _a : null,
|
|
83
|
-
ruleName: (_b = item.ruleName) !== null && _b !== void 0 ? _b : null,
|
|
84
|
-
}));
|
|
85
|
-
return prevValue;
|
|
86
|
-
}, new Map());
|
|
87
|
-
}
|
|
88
|
-
getRbacParents({ items }) {
|
|
89
|
-
return Object.keys(items).reduce((prevValue, name) => {
|
|
90
|
-
const item = items[name];
|
|
91
|
-
if (!item.children || item.children.length === 0) {
|
|
92
|
-
return prevValue;
|
|
93
|
-
}
|
|
94
|
-
item.children.forEach((childName) => {
|
|
95
|
-
if (!this.items.has(childName)) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
let child = prevValue.get(childName);
|
|
99
|
-
if (!child) {
|
|
100
|
-
child = new Map();
|
|
101
|
-
prevValue.set(childName, child);
|
|
102
|
-
}
|
|
103
|
-
const item = this.items.get(name);
|
|
104
|
-
if (item) {
|
|
105
|
-
child.set(name, item);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
return prevValue;
|
|
109
|
-
}, new Map());
|
|
110
|
-
}
|
|
111
|
-
getRbacRules({ rules }) {
|
|
112
|
-
return Object.keys(rules).reduce((prevValue, name) => {
|
|
113
|
-
var _a;
|
|
114
|
-
const ruleData = rules[name];
|
|
115
|
-
const RuleClass = (_a = this.ruleClasses.get(ruleData.data.typeName)) !== null && _a !== void 0 ? _a : rbac_1.Rule;
|
|
116
|
-
const rule = new RuleClass(name, JSON.parse(ruleData.data.ruleData));
|
|
117
|
-
prevValue.set(name, rule);
|
|
118
|
-
return prevValue;
|
|
119
|
-
}, new Map());
|
|
120
|
-
}
|
|
121
|
-
getRbacAssignments({ assignments }) {
|
|
122
|
-
return Object.keys(assignments).reduce((prevValue, username) => {
|
|
123
|
-
const _assignments = assignments[username];
|
|
124
|
-
_assignments.forEach((itemName) => {
|
|
125
|
-
var _a;
|
|
126
|
-
if (prevValue.has(username)) {
|
|
127
|
-
(_a = prevValue.get(username)) === null || _a === void 0 ? void 0 : _a.set(itemName, new rbac_1.Assignment(username, itemName));
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
prevValue.set(username, new Map([[itemName, new rbac_1.Assignment(username, itemName)]]));
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
return prevValue;
|
|
134
|
-
}, new Map());
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
exports.default = RbacCheckAccess;
|
package/src/RbacCheckAccess.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
|
|
2
|
-
import statusCodes from "http-status-codes";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
Assignment,
|
|
6
|
-
BaseCheckAccess,
|
|
7
|
-
BaseCheckAccessOptions,
|
|
8
|
-
IItem,
|
|
9
|
-
ItemType,
|
|
10
|
-
Permission,
|
|
11
|
-
RBACResponse,
|
|
12
|
-
Role,
|
|
13
|
-
Rule,
|
|
14
|
-
RuleParams,
|
|
15
|
-
} from "@iushev/rbac";
|
|
16
|
-
|
|
17
|
-
export type RbacCheckAccessOptions = BaseCheckAccessOptions & {
|
|
18
|
-
path: string;
|
|
19
|
-
authorization: () => string;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default class RbacCheckAccess extends BaseCheckAccess {
|
|
23
|
-
private readonly axiosInstance: AxiosInstance;
|
|
24
|
-
|
|
25
|
-
protected assignments: Map<string, Map<string, Assignment>> = new Map();
|
|
26
|
-
|
|
27
|
-
constructor(options: RbacCheckAccessOptions) {
|
|
28
|
-
super(options);
|
|
29
|
-
|
|
30
|
-
this.axiosInstance = axios.create({
|
|
31
|
-
baseURL: options.path,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
this.axiosInstance.interceptors.request.use((config) => {
|
|
35
|
-
if (options.authorization) {
|
|
36
|
-
const token = options.authorization();
|
|
37
|
-
config.headers.Authorization = "Bearer " + token;
|
|
38
|
-
} else {
|
|
39
|
-
config.headers.Authorization = undefined;
|
|
40
|
-
}
|
|
41
|
-
return config;
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public async checkAccess(username: string, itemName: string, params: RuleParams): Promise<boolean> {
|
|
46
|
-
if (this.items.size === 0) {
|
|
47
|
-
await this.load();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return super.checkAccess(username, itemName, params, this.assignments.get(username) ?? new Map());
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public async load(config?: AxiosRequestConfig): Promise<void> {
|
|
54
|
-
let _rbac: RBACResponse;
|
|
55
|
-
try {
|
|
56
|
-
console.log("Load RBAC");
|
|
57
|
-
const response = await this.axiosInstance.get<RBACResponse>("/rbac", config);
|
|
58
|
-
_rbac = response.data;
|
|
59
|
-
} catch (err) {
|
|
60
|
-
if (axios.isAxiosError(err) && err.response?.status === statusCodes.NOT_FOUND) {
|
|
61
|
-
_rbac = {
|
|
62
|
-
assignments: {},
|
|
63
|
-
items: {},
|
|
64
|
-
rules: {},
|
|
65
|
-
};
|
|
66
|
-
} else {
|
|
67
|
-
throw err;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
this.items = this.getRbacItems(_rbac);
|
|
72
|
-
this.parents = this.getRbacParents(_rbac);
|
|
73
|
-
this.rules = this.getRbacRules(_rbac);
|
|
74
|
-
this.assignments = this.getRbacAssignments(_rbac);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private getRbacItems({ items }: RBACResponse) {
|
|
78
|
-
return Object.keys(items).reduce<Map<string, IItem>>((prevValue, name) => {
|
|
79
|
-
const item = items[name];
|
|
80
|
-
const ItemClass = item.type === ItemType.permission ? Permission : Role;
|
|
81
|
-
prevValue.set(
|
|
82
|
-
name,
|
|
83
|
-
new ItemClass({
|
|
84
|
-
name,
|
|
85
|
-
description: item.description ?? null,
|
|
86
|
-
ruleName: item.ruleName ?? null,
|
|
87
|
-
}),
|
|
88
|
-
);
|
|
89
|
-
return prevValue;
|
|
90
|
-
}, new Map());
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private getRbacParents({ items }: RBACResponse) {
|
|
94
|
-
return Object.keys(items).reduce<Map<string, Map<string, IItem>>>((prevValue, name) => {
|
|
95
|
-
const item = items[name];
|
|
96
|
-
if (!item.children || item.children.length === 0) {
|
|
97
|
-
return prevValue;
|
|
98
|
-
}
|
|
99
|
-
item.children.forEach((childName: string) => {
|
|
100
|
-
if (!this.items.has(childName)) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let child = prevValue.get(childName);
|
|
105
|
-
|
|
106
|
-
if (!child) {
|
|
107
|
-
child = new Map();
|
|
108
|
-
prevValue.set(childName, child);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const item = this.items.get(name);
|
|
112
|
-
if (item) {
|
|
113
|
-
child.set(name, item);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return prevValue;
|
|
118
|
-
}, new Map());
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private getRbacRules({ rules }: RBACResponse) {
|
|
122
|
-
return Object.keys(rules).reduce<Map<string, Rule>>((prevValue, name) => {
|
|
123
|
-
const ruleData = rules[name];
|
|
124
|
-
const RuleClass = this.ruleClasses.get(ruleData.data.typeName) ?? Rule;
|
|
125
|
-
const rule = new RuleClass(name, JSON.parse(ruleData.data.ruleData));
|
|
126
|
-
prevValue.set(name, rule);
|
|
127
|
-
return prevValue;
|
|
128
|
-
}, new Map());
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
private getRbacAssignments({ assignments }: RBACResponse) {
|
|
132
|
-
return Object.keys(assignments).reduce<Map<string, Map<string, Assignment>>>((prevValue, username) => {
|
|
133
|
-
const _assignments = assignments[username];
|
|
134
|
-
_assignments.forEach((itemName) => {
|
|
135
|
-
if (prevValue.has(username)) {
|
|
136
|
-
prevValue.get(username)?.set(itemName, new Assignment(username, itemName));
|
|
137
|
-
} else {
|
|
138
|
-
prevValue.set(username, new Map([[itemName, new Assignment(username, itemName)]]));
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
return prevValue;
|
|
142
|
-
}, new Map());
|
|
143
|
-
}
|
|
144
|
-
}
|