@nocobase/acl 0.8.1-alpha.3 → 0.9.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/acl-available-strategy.js +1 -5
- package/lib/acl-role.d.ts +8 -1
- package/lib/acl-role.js +143 -7
- package/lib/acl.d.ts +12 -1
- package/lib/acl.js +153 -57
- package/lib/allow-manager.d.ts +1 -0
- package/lib/allow-manager.js +64 -39
- package/lib/fixed-params-manager.d.ts +10 -0
- package/lib/fixed-params-manager.js +83 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +13 -0
- package/lib/no-permission-error.d.ts +4 -0
- package/lib/no-permission-error.js +15 -0
- package/lib/snippet-manager.d.ts +19 -0
- package/lib/snippet-manager.js +60 -0
- package/package.json +6 -10
|
@@ -78,7 +78,7 @@ class ACLAvailableStrategy {
|
|
|
78
78
|
const predicateName = this.actionsAsObject[actionName];
|
|
79
79
|
|
|
80
80
|
if (predicateName) {
|
|
81
|
-
return predicate[predicateName];
|
|
81
|
+
return _lodash().default.cloneDeep(predicate[predicateName]);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
return true;
|
|
@@ -88,10 +88,6 @@ class ACLAvailableStrategy {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
allow(resourceName, actionName) {
|
|
91
|
-
if (this.acl.isConfigResource(resourceName) && this.allowConfigure) {
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
91
|
return this.matchAction(this.acl.resolveActionAlias(actionName));
|
|
96
92
|
}
|
|
97
93
|
|
package/lib/acl-role.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ACL, DefineOptions } from './acl';
|
|
2
|
-
import { AvailableStrategyOptions } from './acl-available-strategy';
|
|
2
|
+
import { ACLAvailableStrategy, AvailableStrategyOptions } from './acl-available-strategy';
|
|
3
3
|
import { ACLResource } from './acl-resource';
|
|
4
4
|
export interface RoleActionParams {
|
|
5
5
|
fields?: string[];
|
|
@@ -17,14 +17,21 @@ export declare class ACLRole {
|
|
|
17
17
|
name: string;
|
|
18
18
|
strategy: string | AvailableStrategyOptions;
|
|
19
19
|
resources: Map<string, ACLResource>;
|
|
20
|
+
snippets: Set<string>;
|
|
20
21
|
constructor(acl: ACL, name: string);
|
|
21
22
|
getResource(name: string): ACLResource | undefined;
|
|
22
23
|
setStrategy(value: string | AvailableStrategyOptions): void;
|
|
24
|
+
getStrategy(): ACLAvailableStrategy;
|
|
23
25
|
getResourceActionsParams(resourceName: string): {};
|
|
24
26
|
revokeResource(resourceName: string): void;
|
|
25
27
|
grantAction(path: string, options?: RoleActionParams): void;
|
|
26
28
|
getActionParams(path: string): RoleActionParams;
|
|
27
29
|
revokeAction(path: string): void;
|
|
30
|
+
effectiveSnippets(): {
|
|
31
|
+
allowed: Array<string>;
|
|
32
|
+
rejected: Array<string>;
|
|
33
|
+
};
|
|
34
|
+
snippetAllowed(actionPath: string): boolean;
|
|
28
35
|
toJSON(): DefineOptions;
|
|
29
36
|
protected getResourceActionFromPath(path: string): {
|
|
30
37
|
resourceName: string;
|
package/lib/acl-role.js
CHANGED
|
@@ -5,8 +5,32 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.ACLRole = void 0;
|
|
7
7
|
|
|
8
|
+
var _aclAvailableStrategy = require("./acl-available-strategy");
|
|
9
|
+
|
|
8
10
|
var _aclResource = require("./acl-resource");
|
|
9
11
|
|
|
12
|
+
function _lodash() {
|
|
13
|
+
const data = _interopRequireDefault(require("lodash"));
|
|
14
|
+
|
|
15
|
+
_lodash = function _lodash() {
|
|
16
|
+
return data;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function _minimatch() {
|
|
23
|
+
const data = _interopRequireDefault(require("minimatch"));
|
|
24
|
+
|
|
25
|
+
_minimatch = function _minimatch() {
|
|
26
|
+
return data;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
33
|
+
|
|
10
34
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
11
35
|
|
|
12
36
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
@@ -27,6 +51,7 @@ class ACLRole {
|
|
|
27
51
|
this.name = void 0;
|
|
28
52
|
this.strategy = void 0;
|
|
29
53
|
this.resources = new Map();
|
|
54
|
+
this.snippets = new Set();
|
|
30
55
|
this.acl = acl;
|
|
31
56
|
this.name = name;
|
|
32
57
|
}
|
|
@@ -39,6 +64,14 @@ class ACLRole {
|
|
|
39
64
|
this.strategy = value;
|
|
40
65
|
}
|
|
41
66
|
|
|
67
|
+
getStrategy() {
|
|
68
|
+
if (!this.strategy) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return _lodash().default.isString(this.strategy) ? this.acl.availableStrategy.get(this.strategy) : new _aclAvailableStrategy.ACLAvailableStrategy(this.acl, this.strategy);
|
|
73
|
+
}
|
|
74
|
+
|
|
42
75
|
getResourceActionsParams(resourceName) {
|
|
43
76
|
const resource = this.getResource(resourceName);
|
|
44
77
|
return resource.getActions();
|
|
@@ -86,15 +119,117 @@ class ACLRole {
|
|
|
86
119
|
resource.removeAction(actionName);
|
|
87
120
|
}
|
|
88
121
|
|
|
89
|
-
|
|
90
|
-
const
|
|
122
|
+
effectiveSnippets() {
|
|
123
|
+
const allowedSnippets = new Set();
|
|
124
|
+
const rejectedSnippets = new Set();
|
|
125
|
+
const availableSnippets = this.acl.snippetManager.snippets;
|
|
91
126
|
|
|
92
|
-
var _iterator = _createForOfIteratorHelper(this.
|
|
127
|
+
var _iterator = _createForOfIteratorHelper(this.snippets),
|
|
93
128
|
_step;
|
|
94
129
|
|
|
95
130
|
try {
|
|
96
131
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
97
|
-
|
|
132
|
+
let snippetRule = _step.value;
|
|
133
|
+
const negated = snippetRule.startsWith('!');
|
|
134
|
+
snippetRule = negated ? snippetRule.slice(1) : snippetRule;
|
|
135
|
+
|
|
136
|
+
var _iterator2 = _createForOfIteratorHelper(availableSnippets),
|
|
137
|
+
_step2;
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
141
|
+
const _step2$value = _slicedToArray(_step2.value, 2),
|
|
142
|
+
_ = _step2$value[0],
|
|
143
|
+
availableSnippet = _step2$value[1];
|
|
144
|
+
|
|
145
|
+
if ((0, _minimatch().default)(availableSnippet.name, snippetRule)) {
|
|
146
|
+
if (negated) {
|
|
147
|
+
rejectedSnippets.add(availableSnippet.name);
|
|
148
|
+
} else {
|
|
149
|
+
allowedSnippets.add(availableSnippet.name);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} catch (err) {
|
|
154
|
+
_iterator2.e(err);
|
|
155
|
+
} finally {
|
|
156
|
+
_iterator2.f();
|
|
157
|
+
}
|
|
158
|
+
} // get difference of allowed and rejected snippets
|
|
159
|
+
|
|
160
|
+
} catch (err) {
|
|
161
|
+
_iterator.e(err);
|
|
162
|
+
} finally {
|
|
163
|
+
_iterator.f();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const effectiveSnippets = new Set([...allowedSnippets].filter(x => !rejectedSnippets.has(x)));
|
|
167
|
+
return {
|
|
168
|
+
allowed: [...effectiveSnippets],
|
|
169
|
+
rejected: [...rejectedSnippets]
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
snippetAllowed(actionPath) {
|
|
174
|
+
const effectiveSnippets = this.effectiveSnippets();
|
|
175
|
+
|
|
176
|
+
const getActions = snippets => {
|
|
177
|
+
return snippets.map(snippetName => this.acl.snippetManager.snippets.get(snippetName).actions).flat();
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const allowedActions = getActions(effectiveSnippets.allowed);
|
|
181
|
+
const rejectedActions = getActions(effectiveSnippets.rejected);
|
|
182
|
+
|
|
183
|
+
const actionMatched = (actionPath, actionRule) => {
|
|
184
|
+
return (0, _minimatch().default)(actionPath, actionRule);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
var _iterator3 = _createForOfIteratorHelper(allowedActions),
|
|
188
|
+
_step3;
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
192
|
+
const action = _step3.value;
|
|
193
|
+
|
|
194
|
+
if (actionMatched(actionPath, action)) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
_iterator3.e(err);
|
|
200
|
+
} finally {
|
|
201
|
+
_iterator3.f();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
var _iterator4 = _createForOfIteratorHelper(rejectedActions),
|
|
205
|
+
_step4;
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
209
|
+
const action = _step4.value;
|
|
210
|
+
|
|
211
|
+
if (actionMatched(actionPath, action)) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} catch (err) {
|
|
216
|
+
_iterator4.e(err);
|
|
217
|
+
} finally {
|
|
218
|
+
_iterator4.f();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
toJSON() {
|
|
225
|
+
const actions = {};
|
|
226
|
+
|
|
227
|
+
var _iterator5 = _createForOfIteratorHelper(this.resources.keys()),
|
|
228
|
+
_step5;
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
232
|
+
const resourceName = _step5.value;
|
|
98
233
|
const resourceActions = this.getResourceActionsParams(resourceName);
|
|
99
234
|
|
|
100
235
|
for (var _i2 = 0, _Object$keys = Object.keys(resourceActions); _i2 < _Object$keys.length; _i2++) {
|
|
@@ -103,15 +238,16 @@ class ACLRole {
|
|
|
103
238
|
}
|
|
104
239
|
}
|
|
105
240
|
} catch (err) {
|
|
106
|
-
|
|
241
|
+
_iterator5.e(err);
|
|
107
242
|
} finally {
|
|
108
|
-
|
|
243
|
+
_iterator5.f();
|
|
109
244
|
}
|
|
110
245
|
|
|
111
246
|
return {
|
|
112
247
|
role: this.name,
|
|
113
248
|
strategy: this.strategy,
|
|
114
|
-
actions
|
|
249
|
+
actions,
|
|
250
|
+
snippets: Array.from(this.snippets)
|
|
115
251
|
};
|
|
116
252
|
}
|
|
117
253
|
|
package/lib/acl.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { ACLAvailableAction, AvailableActionOptions } from './acl-available-acti
|
|
|
5
5
|
import { ACLAvailableStrategy, AvailableStrategyOptions } from './acl-available-strategy';
|
|
6
6
|
import { ACLRole, ResourceActionsOptions, RoleActionParams } from './acl-role';
|
|
7
7
|
import { AllowManager, ConditionFunc } from './allow-manager';
|
|
8
|
+
import FixedParamsManager, { Merger } from './fixed-params-manager';
|
|
9
|
+
import SnippetManager, { SnippetOptions } from './snippet-manager';
|
|
8
10
|
interface CanResult {
|
|
9
11
|
role: string;
|
|
10
12
|
resource: string;
|
|
@@ -17,6 +19,7 @@ export interface DefineOptions {
|
|
|
17
19
|
strategy?: string | AvailableStrategyOptions;
|
|
18
20
|
actions?: ResourceActionsOptions;
|
|
19
21
|
routes?: any;
|
|
22
|
+
snippets?: string[];
|
|
20
23
|
}
|
|
21
24
|
export interface ListenerContext {
|
|
22
25
|
acl: ACL;
|
|
@@ -31,16 +34,20 @@ interface CanArgs {
|
|
|
31
34
|
role: string;
|
|
32
35
|
resource: string;
|
|
33
36
|
action: string;
|
|
37
|
+
ctx?: any;
|
|
34
38
|
}
|
|
35
39
|
export declare class ACL extends EventEmitter {
|
|
36
40
|
protected availableActions: Map<string, ACLAvailableAction>;
|
|
37
|
-
|
|
41
|
+
availableStrategy: Map<string, ACLAvailableStrategy>;
|
|
42
|
+
protected fixedParamsManager: FixedParamsManager;
|
|
38
43
|
protected middlewares: Toposort<any>;
|
|
39
44
|
allowManager: AllowManager;
|
|
45
|
+
snippetManager: SnippetManager;
|
|
40
46
|
roles: Map<string, ACLRole>;
|
|
41
47
|
actionAlias: Map<string, string>;
|
|
42
48
|
configResources: string[];
|
|
43
49
|
constructor();
|
|
50
|
+
protected addCoreMiddleware(): void;
|
|
44
51
|
define(options: DefineOptions): ACLRole;
|
|
45
52
|
getRole(name: string): ACLRole;
|
|
46
53
|
removeRole(name: string): boolean;
|
|
@@ -57,7 +64,11 @@ export declare class ACL extends EventEmitter {
|
|
|
57
64
|
resolveActionAlias(action: string): string;
|
|
58
65
|
use(fn: any, options?: ToposortOptions): void;
|
|
59
66
|
allow(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc): void;
|
|
67
|
+
skip(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc): void;
|
|
60
68
|
parseJsonTemplate(json: any, ctx: any): any;
|
|
61
69
|
middleware(): (ctx: any, next: any) => Promise<void>;
|
|
70
|
+
getActionParams(ctx: any): Promise<void>;
|
|
71
|
+
addFixedParams(resource: string, action: string, merger: Merger): void;
|
|
72
|
+
registerSnippet(snippet: SnippetOptions): void;
|
|
62
73
|
}
|
|
63
74
|
export {};
|
package/lib/acl.js
CHANGED
|
@@ -63,11 +63,11 @@ var _aclRole = require("./acl-role");
|
|
|
63
63
|
|
|
64
64
|
var _allowManager = require("./allow-manager");
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
var _fixedParamsManager = _interopRequireDefault(require("./fixed-params-manager"));
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
var _snippetManager = _interopRequireDefault(require("./snippet-manager"));
|
|
69
69
|
|
|
70
|
-
function
|
|
70
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
71
71
|
|
|
72
72
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
73
73
|
|
|
@@ -83,6 +83,10 @@ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Sy
|
|
|
83
83
|
|
|
84
84
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
85
85
|
|
|
86
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
87
|
+
|
|
88
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
89
|
+
|
|
86
90
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
87
91
|
|
|
88
92
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
@@ -94,8 +98,10 @@ class ACL extends _events().default {
|
|
|
94
98
|
super();
|
|
95
99
|
this.availableActions = new Map();
|
|
96
100
|
this.availableStrategy = new Map();
|
|
101
|
+
this.fixedParamsManager = new _fixedParamsManager.default();
|
|
97
102
|
this.middlewares = void 0;
|
|
98
103
|
this.allowManager = new _allowManager.AllowManager(this);
|
|
104
|
+
this.snippetManager = new _snippetManager.default();
|
|
99
105
|
this.roles = new Map();
|
|
100
106
|
this.actionAlias = new Map();
|
|
101
107
|
this.configResources = [];
|
|
@@ -123,7 +129,73 @@ class ACL extends _events().default {
|
|
|
123
129
|
}
|
|
124
130
|
}
|
|
125
131
|
});
|
|
126
|
-
this.
|
|
132
|
+
this.use(this.allowManager.aclMiddleware(), {
|
|
133
|
+
tag: 'allow-manager',
|
|
134
|
+
before: 'core'
|
|
135
|
+
});
|
|
136
|
+
this.addCoreMiddleware();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
addCoreMiddleware() {
|
|
140
|
+
const acl = this;
|
|
141
|
+
|
|
142
|
+
const filterParams = (ctx, resourceName, params) => {
|
|
143
|
+
var _params$filter;
|
|
144
|
+
|
|
145
|
+
if (params === null || params === void 0 ? void 0 : (_params$filter = params.filter) === null || _params$filter === void 0 ? void 0 : _params$filter.createdById) {
|
|
146
|
+
const collection = ctx.db.getCollection(resourceName);
|
|
147
|
+
|
|
148
|
+
if (!collection || !collection.getField('createdById')) {
|
|
149
|
+
return _lodash().default.omit(params, 'filter.createdById');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return params;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
this.middlewares.add( /*#__PURE__*/function () {
|
|
157
|
+
var _ref = _asyncToGenerator(function* (ctx, next) {
|
|
158
|
+
var _ctx$log, _permission$can, _ctx$log2;
|
|
159
|
+
|
|
160
|
+
const resourcerAction = ctx.action;
|
|
161
|
+
const _ctx$action = ctx.action,
|
|
162
|
+
resourceName = _ctx$action.resourceName,
|
|
163
|
+
actionName = _ctx$action.actionName;
|
|
164
|
+
const permission = ctx.permission;
|
|
165
|
+
((_ctx$log = ctx.log) === null || _ctx$log === void 0 ? void 0 : _ctx$log.info) && ctx.log.info('ctx permission', permission);
|
|
166
|
+
|
|
167
|
+
if ((!permission.can || typeof permission.can !== 'object') && !permission.skip) {
|
|
168
|
+
ctx.throw(403, 'No permissions');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const params = ((_permission$can = permission.can) === null || _permission$can === void 0 ? void 0 : _permission$can.params) || acl.fixedParamsManager.getParams(resourceName, actionName);
|
|
173
|
+
((_ctx$log2 = ctx.log) === null || _ctx$log2 === void 0 ? void 0 : _ctx$log2.info) && ctx.log.info('acl params', params);
|
|
174
|
+
|
|
175
|
+
if (params && resourcerAction.mergeParams) {
|
|
176
|
+
var _ctx$log3;
|
|
177
|
+
|
|
178
|
+
const filteredParams = filterParams(ctx, resourceName, params);
|
|
179
|
+
const parsedParams = acl.parseJsonTemplate(filteredParams, ctx);
|
|
180
|
+
ctx.permission.parsedParams = parsedParams;
|
|
181
|
+
((_ctx$log3 = ctx.log) === null || _ctx$log3 === void 0 ? void 0 : _ctx$log3.info) && ctx.log.info('acl parsedParams', parsedParams);
|
|
182
|
+
ctx.permission.rawParams = _lodash().default.cloneDeep(resourcerAction.params);
|
|
183
|
+
resourcerAction.mergeParams(parsedParams, {
|
|
184
|
+
appends: (x, y) => _lodash().default.intersection(x, y)
|
|
185
|
+
});
|
|
186
|
+
ctx.permission.mergedParams = _lodash().default.cloneDeep(resourcerAction.params);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
yield next();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return function (_x, _x2) {
|
|
193
|
+
return _ref.apply(this, arguments);
|
|
194
|
+
};
|
|
195
|
+
}(), {
|
|
196
|
+
tag: 'core',
|
|
197
|
+
group: 'core'
|
|
198
|
+
});
|
|
127
199
|
}
|
|
128
200
|
|
|
129
201
|
define(options) {
|
|
@@ -217,6 +289,27 @@ class ACL extends _events().default {
|
|
|
217
289
|
return null;
|
|
218
290
|
}
|
|
219
291
|
|
|
292
|
+
const snippetAllowed = aclRole.snippetAllowed(`${resource}:${action}`);
|
|
293
|
+
|
|
294
|
+
if (snippetAllowed === false) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const fixedParams = this.fixedParamsManager.getParams(resource, action);
|
|
299
|
+
|
|
300
|
+
const mergeParams = result => {
|
|
301
|
+
const params = result['params'] || {};
|
|
302
|
+
const mergedParams = (0, _utils().assign)(params, fixedParams);
|
|
303
|
+
|
|
304
|
+
if (Object.keys(mergedParams).length) {
|
|
305
|
+
result['params'] = mergedParams;
|
|
306
|
+
} else {
|
|
307
|
+
delete result['params'];
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return result;
|
|
311
|
+
};
|
|
312
|
+
|
|
220
313
|
const aclResource = aclRole.getResource(resource);
|
|
221
314
|
|
|
222
315
|
if (aclResource) {
|
|
@@ -224,41 +317,42 @@ class ACL extends _events().default {
|
|
|
224
317
|
|
|
225
318
|
if (actionParams) {
|
|
226
319
|
// handle single action config
|
|
227
|
-
return {
|
|
320
|
+
return mergeParams({
|
|
228
321
|
role,
|
|
229
322
|
resource,
|
|
230
323
|
action,
|
|
231
324
|
params: actionParams
|
|
232
|
-
};
|
|
325
|
+
});
|
|
233
326
|
} else {
|
|
234
327
|
return null;
|
|
235
328
|
}
|
|
236
329
|
}
|
|
237
330
|
|
|
238
|
-
|
|
331
|
+
const roleStrategy = aclRole.getStrategy();
|
|
332
|
+
|
|
333
|
+
if (!roleStrategy && !snippetAllowed) {
|
|
239
334
|
return null;
|
|
240
335
|
}
|
|
241
336
|
|
|
242
|
-
|
|
337
|
+
let roleStrategyParams = roleStrategy === null || roleStrategy === void 0 ? void 0 : roleStrategy.allow(resource, this.resolveActionAlias(action));
|
|
243
338
|
|
|
244
|
-
if (!
|
|
245
|
-
|
|
339
|
+
if (!roleStrategyParams && snippetAllowed) {
|
|
340
|
+
roleStrategyParams = {};
|
|
246
341
|
}
|
|
247
342
|
|
|
248
|
-
const roleStrategyParams = roleStrategy.allow(resource, this.resolveActionAlias(action));
|
|
249
|
-
|
|
250
343
|
if (roleStrategyParams) {
|
|
251
344
|
const result = {
|
|
252
345
|
role,
|
|
253
346
|
resource,
|
|
254
|
-
action
|
|
347
|
+
action,
|
|
348
|
+
params: {}
|
|
255
349
|
};
|
|
256
350
|
|
|
257
351
|
if (_lodash().default.isPlainObject(roleStrategyParams)) {
|
|
258
352
|
result['params'] = roleStrategyParams;
|
|
259
353
|
}
|
|
260
354
|
|
|
261
|
-
return result;
|
|
355
|
+
return mergeParams(result);
|
|
262
356
|
}
|
|
263
357
|
|
|
264
358
|
return null;
|
|
@@ -273,10 +367,16 @@ class ACL extends _events().default {
|
|
|
273
367
|
}
|
|
274
368
|
|
|
275
369
|
use(fn, options) {
|
|
276
|
-
this.middlewares.add(fn,
|
|
370
|
+
this.middlewares.add(fn, _objectSpread({
|
|
371
|
+
group: 'prep'
|
|
372
|
+
}, options));
|
|
277
373
|
}
|
|
278
374
|
|
|
279
375
|
allow(resourceName, actionNames, condition) {
|
|
376
|
+
return this.skip(resourceName, actionNames, condition);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
skip(resourceName, actionNames, condition) {
|
|
280
380
|
if (!Array.isArray(actionNames)) {
|
|
281
381
|
actionNames = [actionNames];
|
|
282
382
|
}
|
|
@@ -306,28 +406,12 @@ class ACL extends _events().default {
|
|
|
306
406
|
|
|
307
407
|
middleware() {
|
|
308
408
|
const acl = this;
|
|
309
|
-
|
|
310
|
-
const filterParams = (ctx, resourceName, params) => {
|
|
311
|
-
var _params$filter;
|
|
312
|
-
|
|
313
|
-
if (params === null || params === void 0 ? void 0 : (_params$filter = params.filter) === null || _params$filter === void 0 ? void 0 : _params$filter.createdById) {
|
|
314
|
-
const collection = ctx.db.getCollection(resourceName);
|
|
315
|
-
|
|
316
|
-
if (collection && !collection.getField('createdById')) {
|
|
317
|
-
return _lodash().default.omit(params, 'filter.createdById');
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return params;
|
|
322
|
-
};
|
|
323
|
-
|
|
324
409
|
return /*#__PURE__*/function () {
|
|
325
410
|
var _ACLMiddleware = _asyncToGenerator(function* (ctx, next) {
|
|
326
411
|
const roleName = ctx.state.currentRole || 'anonymous';
|
|
327
|
-
const _ctx$
|
|
328
|
-
resourceName = _ctx$
|
|
329
|
-
actionName = _ctx$
|
|
330
|
-
const resourcerAction = ctx.action;
|
|
412
|
+
const _ctx$action2 = ctx.action,
|
|
413
|
+
resourceName = _ctx$action2.resourceName,
|
|
414
|
+
actionName = _ctx$action2.actionName;
|
|
331
415
|
|
|
332
416
|
ctx.can = options => {
|
|
333
417
|
return acl.can(_objectSpread({
|
|
@@ -341,31 +425,10 @@ class ACL extends _events().default {
|
|
|
341
425
|
action: actionName
|
|
342
426
|
})
|
|
343
427
|
};
|
|
344
|
-
return (0, _koaCompose().default)(acl.middlewares.nodes)(ctx,
|
|
345
|
-
const permission = ctx.permission;
|
|
346
|
-
|
|
347
|
-
if (permission.skip) {
|
|
348
|
-
return next();
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
if (!permission.can || typeof permission.can !== 'object') {
|
|
352
|
-
ctx.throw(403, 'No permissions');
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const params = permission.can.params;
|
|
357
|
-
|
|
358
|
-
if (params) {
|
|
359
|
-
const filteredParams = filterParams(ctx, resourceName, params);
|
|
360
|
-
const parsedParams = acl.parseJsonTemplate(filteredParams, ctx);
|
|
361
|
-
resourcerAction.mergeParams(parsedParams);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
yield next();
|
|
365
|
-
}));
|
|
428
|
+
return (0, _koaCompose().default)(acl.middlewares.nodes)(ctx, next);
|
|
366
429
|
});
|
|
367
430
|
|
|
368
|
-
function ACLMiddleware(
|
|
431
|
+
function ACLMiddleware(_x3, _x4) {
|
|
369
432
|
return _ACLMiddleware.apply(this, arguments);
|
|
370
433
|
}
|
|
371
434
|
|
|
@@ -373,6 +436,39 @@ class ACL extends _events().default {
|
|
|
373
436
|
}();
|
|
374
437
|
}
|
|
375
438
|
|
|
439
|
+
getActionParams(ctx) {
|
|
440
|
+
var _this = this;
|
|
441
|
+
|
|
442
|
+
return _asyncToGenerator(function* () {
|
|
443
|
+
const roleName = ctx.state.currentRole || 'anonymous';
|
|
444
|
+
const _ctx$action3 = ctx.action,
|
|
445
|
+
resourceName = _ctx$action3.resourceName,
|
|
446
|
+
actionName = _ctx$action3.actionName;
|
|
447
|
+
|
|
448
|
+
ctx.can = options => {
|
|
449
|
+
return _this.can(_objectSpread({
|
|
450
|
+
role: roleName
|
|
451
|
+
}, options));
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
ctx.permission = {
|
|
455
|
+
can: ctx.can({
|
|
456
|
+
resource: resourceName,
|
|
457
|
+
action: actionName
|
|
458
|
+
})
|
|
459
|
+
};
|
|
460
|
+
yield (0, _koaCompose().default)(_this.middlewares.nodes)(ctx, /*#__PURE__*/_asyncToGenerator(function* () {}));
|
|
461
|
+
})();
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
addFixedParams(resource, action, merger) {
|
|
465
|
+
this.fixedParamsManager.addParams(resource, action, merger);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
registerSnippet(snippet) {
|
|
469
|
+
this.snippetManager.register(snippet);
|
|
470
|
+
}
|
|
471
|
+
|
|
376
472
|
}
|
|
377
473
|
|
|
378
474
|
exports.ACL = ACL;
|
package/lib/allow-manager.d.ts
CHANGED
|
@@ -8,5 +8,6 @@ export declare class AllowManager {
|
|
|
8
8
|
allow(resourceName: string, actionName: string, condition?: string | ConditionFunc): void;
|
|
9
9
|
getAllowedConditions(resourceName: string, actionName: string): Array<ConditionFunc | true>;
|
|
10
10
|
registerAllowCondition(name: string, condition: ConditionFunc): void;
|
|
11
|
+
isAllowed(resourceName: string, actionName: string, ctx: any): Promise<boolean>;
|
|
11
12
|
aclMiddleware(): (ctx: any, next: any) => Promise<void>;
|
|
12
13
|
}
|
package/lib/allow-manager.js
CHANGED
|
@@ -5,6 +5,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.AllowManager = void 0;
|
|
7
7
|
|
|
8
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
9
|
+
|
|
10
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
11
|
+
|
|
12
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
13
|
+
|
|
8
14
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
9
15
|
|
|
10
16
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
@@ -24,20 +30,26 @@ class AllowManager {
|
|
|
24
30
|
this.registerAllowCondition('loggedIn', ctx => {
|
|
25
31
|
return ctx.state.currentUser;
|
|
26
32
|
});
|
|
33
|
+
this.registerAllowCondition('public', ctx => {
|
|
34
|
+
return true;
|
|
35
|
+
});
|
|
27
36
|
this.registerAllowCondition('allowConfigure', /*#__PURE__*/function () {
|
|
28
37
|
var _ref = _asyncToGenerator(function* (ctx) {
|
|
38
|
+
var _role$getStrategy;
|
|
39
|
+
|
|
29
40
|
const roleName = ctx.state.currentRole;
|
|
30
41
|
|
|
31
42
|
if (!roleName) {
|
|
32
43
|
return false;
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
46
|
+
const role = acl.getRole(roleName);
|
|
47
|
+
|
|
48
|
+
if (!role) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (_role$getStrategy = role.getStrategy()) === null || _role$getStrategy === void 0 ? void 0 : _role$getStrategy.allowConfigure;
|
|
41
53
|
});
|
|
42
54
|
|
|
43
55
|
return function (_x) {
|
|
@@ -61,10 +73,13 @@ class AllowManager {
|
|
|
61
73
|
const resource = this.skipActions.get(fetchActionStep);
|
|
62
74
|
|
|
63
75
|
if (resource) {
|
|
64
|
-
|
|
76
|
+
for (var _i2 = 0, _arr = ['*', actionName]; _i2 < _arr.length; _i2++) {
|
|
77
|
+
const fetchActionStep = _arr[_i2];
|
|
78
|
+
const condition = resource.get(fetchActionStep);
|
|
65
79
|
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
if (condition) {
|
|
81
|
+
results.push(typeof condition === 'string' ? this.registeredCondition.get(condition) : condition);
|
|
82
|
+
}
|
|
68
83
|
}
|
|
69
84
|
}
|
|
70
85
|
}
|
|
@@ -76,47 +91,57 @@ class AllowManager {
|
|
|
76
91
|
this.registeredCondition.set(name, condition);
|
|
77
92
|
}
|
|
78
93
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
var _ref2 = _asyncToGenerator(function* (ctx, next) {
|
|
82
|
-
const _ctx$action = ctx.action,
|
|
83
|
-
resourceName = _ctx$action.resourceName,
|
|
84
|
-
actionName = _ctx$action.actionName;
|
|
85
|
-
const skippedConditions = ctx.app.acl.allowManager.getAllowedConditions(resourceName, actionName);
|
|
86
|
-
let skip = false;
|
|
94
|
+
isAllowed(resourceName, actionName, ctx) {
|
|
95
|
+
var _this = this;
|
|
87
96
|
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
return _asyncToGenerator(function* () {
|
|
98
|
+
const skippedConditions = _this.getAllowedConditions(resourceName, actionName);
|
|
90
99
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const skippedCondition = _step.value;
|
|
100
|
+
var _iterator = _createForOfIteratorHelper(skippedConditions),
|
|
101
|
+
_step;
|
|
94
102
|
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
try {
|
|
104
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
105
|
+
const skippedCondition = _step.value;
|
|
97
106
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
if (skippedCondition) {
|
|
108
|
+
let skipResult = false;
|
|
109
|
+
|
|
110
|
+
if (typeof skippedCondition === 'function') {
|
|
111
|
+
skipResult = yield skippedCondition(ctx);
|
|
112
|
+
} else if (skippedCondition) {
|
|
113
|
+
skipResult = true;
|
|
114
|
+
}
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
116
|
+
if (skipResult) {
|
|
117
|
+
return true;
|
|
108
118
|
}
|
|
109
119
|
}
|
|
110
|
-
} catch (err) {
|
|
111
|
-
_iterator.e(err);
|
|
112
|
-
} finally {
|
|
113
|
-
_iterator.f();
|
|
114
120
|
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
_iterator.e(err);
|
|
123
|
+
} finally {
|
|
124
|
+
_iterator.f();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return false;
|
|
128
|
+
})();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
aclMiddleware() {
|
|
132
|
+
var _this2 = this;
|
|
133
|
+
|
|
134
|
+
return /*#__PURE__*/function () {
|
|
135
|
+
var _ref2 = _asyncToGenerator(function* (ctx, next) {
|
|
136
|
+
const _ctx$action = ctx.action,
|
|
137
|
+
resourceName = _ctx$action.resourceName,
|
|
138
|
+
actionName = _ctx$action.actionName;
|
|
139
|
+
let skip = yield _this2.acl.allowManager.isAllowed(resourceName, actionName, ctx);
|
|
115
140
|
|
|
116
141
|
if (skip) {
|
|
117
|
-
ctx.permission = {
|
|
142
|
+
ctx.permission = _objectSpread(_objectSpread({}, ctx.permission || {}), {}, {
|
|
118
143
|
skip: true
|
|
119
|
-
};
|
|
144
|
+
});
|
|
120
145
|
}
|
|
121
146
|
|
|
122
147
|
yield next();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare type Merger = () => object;
|
|
2
|
+
export declare type ActionPath = string;
|
|
3
|
+
export default class FixedParamsManager {
|
|
4
|
+
merger: Map<string, Merger[]>;
|
|
5
|
+
addParams(resource: string, action: string, merger: Merger): void;
|
|
6
|
+
getParamsMerger(resource: string, action: string): Merger[];
|
|
7
|
+
protected getActionPath(resource: string, action: string): string;
|
|
8
|
+
getParams(resource: string, action: string, extraParams?: any): {};
|
|
9
|
+
static mergeParams(a: any, b: any): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
function _utils() {
|
|
9
|
+
const data = require("@nocobase/utils");
|
|
10
|
+
|
|
11
|
+
_utils = function _utils() {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
19
|
+
|
|
20
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
21
|
+
|
|
22
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
23
|
+
|
|
24
|
+
const SPLIT = ':';
|
|
25
|
+
|
|
26
|
+
class FixedParamsManager {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.merger = new Map();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
addParams(resource, action, merger) {
|
|
32
|
+
const path = this.getActionPath(resource, action);
|
|
33
|
+
this.merger.set(path, [...this.getParamsMerger(resource, action), merger]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getParamsMerger(resource, action) {
|
|
37
|
+
const path = this.getActionPath(resource, action);
|
|
38
|
+
return this.merger.get(path) || [];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getActionPath(resource, action) {
|
|
42
|
+
return `${resource}${SPLIT}${action}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getParams(resource, action, extraParams = {}) {
|
|
46
|
+
const results = {};
|
|
47
|
+
|
|
48
|
+
var _iterator = _createForOfIteratorHelper(this.getParamsMerger(resource, action)),
|
|
49
|
+
_step;
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
53
|
+
const merger = _step.value;
|
|
54
|
+
FixedParamsManager.mergeParams(results, merger());
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
_iterator.e(err);
|
|
58
|
+
} finally {
|
|
59
|
+
_iterator.f();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (extraParams) {
|
|
63
|
+
FixedParamsManager.mergeParams(results, extraParams);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static mergeParams(a, b) {
|
|
70
|
+
(0, _utils().assign)(a, b, {
|
|
71
|
+
filter: 'andMerge',
|
|
72
|
+
fields: 'intersect',
|
|
73
|
+
appends: 'union',
|
|
74
|
+
except: 'union',
|
|
75
|
+
whitelist: 'intersect',
|
|
76
|
+
blacklist: 'intersect',
|
|
77
|
+
sort: 'overwrite'
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
exports.default = FixedParamsManager;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -69,6 +69,19 @@ Object.keys(_aclRole).forEach(function (key) {
|
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
+
var _noPermissionError = require("./no-permission-error");
|
|
73
|
+
|
|
74
|
+
Object.keys(_noPermissionError).forEach(function (key) {
|
|
75
|
+
if (key === "default" || key === "__esModule") return;
|
|
76
|
+
if (key in exports && exports[key] === _noPermissionError[key]) return;
|
|
77
|
+
Object.defineProperty(exports, key, {
|
|
78
|
+
enumerable: true,
|
|
79
|
+
get: function get() {
|
|
80
|
+
return _noPermissionError[key];
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
72
85
|
var _skipMiddleware = require("./skip-middleware");
|
|
73
86
|
|
|
74
87
|
Object.keys(_skipMiddleware).forEach(function (key) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.NoPermissionError = void 0;
|
|
7
|
+
|
|
8
|
+
class NoPermissionError extends Error {
|
|
9
|
+
constructor(...args) {
|
|
10
|
+
super(...args);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.NoPermissionError = NoPermissionError;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare type SnippetOptions = {
|
|
2
|
+
name: string;
|
|
3
|
+
actions: Array<string>;
|
|
4
|
+
};
|
|
5
|
+
declare class Snippet {
|
|
6
|
+
name: string;
|
|
7
|
+
actions: Array<string>;
|
|
8
|
+
constructor(name: string, actions: Array<string>);
|
|
9
|
+
}
|
|
10
|
+
export declare type SnippetGroup = {
|
|
11
|
+
name: string;
|
|
12
|
+
snippets: SnippetOptions[];
|
|
13
|
+
};
|
|
14
|
+
declare class SnippetManager {
|
|
15
|
+
snippets: Map<string, Snippet>;
|
|
16
|
+
register(snippet: SnippetOptions): void;
|
|
17
|
+
allow(actionPath: string, snippetName: string): boolean;
|
|
18
|
+
}
|
|
19
|
+
export default SnippetManager;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
function _minimatch() {
|
|
9
|
+
const data = _interopRequireDefault(require("minimatch"));
|
|
10
|
+
|
|
11
|
+
_minimatch = function _minimatch() {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
|
|
20
|
+
class Snippet {
|
|
21
|
+
constructor(name, actions) {
|
|
22
|
+
this.name = void 0;
|
|
23
|
+
this.actions = void 0;
|
|
24
|
+
this.name = name;
|
|
25
|
+
this.actions = actions;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class SnippetManager {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.snippets = new Map();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
register(snippet) {
|
|
36
|
+
this.snippets.set(snippet.name, snippet);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
allow(actionPath, snippetName) {
|
|
40
|
+
const negated = snippetName.startsWith('!');
|
|
41
|
+
snippetName = negated ? snippetName.slice(1) : snippetName;
|
|
42
|
+
const snippet = this.snippets.get(snippetName);
|
|
43
|
+
|
|
44
|
+
if (!snippet) {
|
|
45
|
+
throw new Error(`Snippet ${snippetName} not found`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const matched = snippet.actions.some(action => (0, _minimatch().default)(actionPath, action));
|
|
49
|
+
|
|
50
|
+
if (matched) {
|
|
51
|
+
return negated ? false : true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var _default = SnippetManager;
|
|
60
|
+
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/acl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-alpha.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"licenses": [
|
|
7
|
-
{
|
|
8
|
-
"type": "Apache-2.0",
|
|
9
|
-
"url": "http://www.apache.org/licenses/LICENSE-2.0"
|
|
10
|
-
}
|
|
11
|
-
],
|
|
12
6
|
"main": "./lib/index.js",
|
|
13
7
|
"types": "./lib/index.d.ts",
|
|
14
8
|
"dependencies": {
|
|
15
|
-
"@nocobase/resourcer": "0.
|
|
16
|
-
"
|
|
9
|
+
"@nocobase/resourcer": "0.9.0-alpha.1",
|
|
10
|
+
"@nocobase/utils": "0.9.0-alpha.1",
|
|
11
|
+
"json-templates": "^4.2.0",
|
|
12
|
+
"minimatch": "^5.1.1"
|
|
17
13
|
},
|
|
18
14
|
"repository": {
|
|
19
15
|
"type": "git",
|
|
20
16
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
21
17
|
"directory": "packages/acl"
|
|
22
18
|
},
|
|
23
|
-
"gitHead": "
|
|
19
|
+
"gitHead": "d84c2a47c42c2ffec4fbf317d53268952fbd58d7"
|
|
24
20
|
}
|