@nocobase/plugin-acl 0.11.1-alpha.5 → 0.12.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.
Files changed (96) hide show
  1. package/client.d.ts +2 -3
  2. package/client.js +1 -1
  3. package/dist/client/index.js +11 -0
  4. package/{lib/server → dist}/index.d.ts +1 -0
  5. package/dist/index.js +18 -0
  6. package/{src/server/actions/available-actions.ts → dist/server/actions/available-actions.js} +7 -5
  7. package/{src/server/actions/role-check.ts → dist/server/actions/role-check.js} +17 -22
  8. package/dist/server/actions/role-collections.js +53 -0
  9. package/dist/server/actions/user-setDefaultRole.js +43 -0
  10. package/dist/server/collections/roles-users.js +10 -0
  11. package/dist/server/collections/roles.js +103 -0
  12. package/dist/server/collections/rolesResources.js +35 -0
  13. package/dist/server/collections/rolesResourcesActions.js +33 -0
  14. package/dist/server/collections/rolesResourcesScopes.js +27 -0
  15. package/dist/server/collections/users.js +35 -0
  16. package/dist/server/index.js +11 -0
  17. package/dist/server/middlewares/setCurrentRole.js +31 -0
  18. package/dist/server/migrations/20221214072638-set-role-snippets.js +25 -0
  19. package/dist/server/model/RoleModel.js +23 -0
  20. package/dist/server/model/RoleResourceActionModel.js +64 -0
  21. package/dist/server/model/RoleResourceModel.js +55 -0
  22. package/dist/server/server.js +709 -0
  23. package/package.json +12 -21
  24. package/server.d.ts +3 -3
  25. package/server.js +1 -1
  26. package/lib/client/index.js +0 -22
  27. package/lib/index.js +0 -13
  28. package/lib/server/actions/available-actions.js +0 -34
  29. package/lib/server/actions/role-check.js +0 -77
  30. package/lib/server/actions/role-collections.js +0 -98
  31. package/lib/server/actions/user-setDefaultRole.js +0 -52
  32. package/lib/server/collections/roles-users.js +0 -16
  33. package/lib/server/collections/roles.js +0 -92
  34. package/lib/server/collections/rolesResources.js +0 -31
  35. package/lib/server/collections/rolesResourcesActions.js +0 -31
  36. package/lib/server/collections/rolesResourcesScopes.js +0 -25
  37. package/lib/server/collections/users.js +0 -41
  38. package/lib/server/index.js +0 -13
  39. package/lib/server/middlewares/setCurrentRole.js +0 -45
  40. package/lib/server/migrations/20221214072638-set-role-snippets.js +0 -43
  41. package/lib/server/model/RoleModel.js +0 -35
  42. package/lib/server/model/RoleResourceActionModel.js +0 -91
  43. package/lib/server/model/RoleResourceModel.js +0 -106
  44. package/lib/server/server.js +0 -947
  45. package/src/client/index.ts +0 -8
  46. package/src/index.ts +0 -1
  47. package/src/server/__tests__/acl.test.ts +0 -835
  48. package/src/server/__tests__/actions.test.ts +0 -141
  49. package/src/server/__tests__/association-field.test.ts +0 -413
  50. package/src/server/__tests__/configuration.test.ts +0 -70
  51. package/src/server/__tests__/list-action.test.ts +0 -446
  52. package/src/server/__tests__/middleware.test.ts +0 -210
  53. package/src/server/__tests__/own.test.ts +0 -124
  54. package/src/server/__tests__/prepare.ts +0 -20
  55. package/src/server/__tests__/role-check.test.ts +0 -46
  56. package/src/server/__tests__/role-resource.test.ts +0 -177
  57. package/src/server/__tests__/role-user.test.ts +0 -127
  58. package/src/server/__tests__/role.test.ts +0 -118
  59. package/src/server/__tests__/scope.test.ts +0 -55
  60. package/src/server/__tests__/setCurrentRole.test.ts +0 -86
  61. package/src/server/__tests__/snippets.test.ts +0 -35
  62. package/src/server/__tests__/users.test.ts +0 -136
  63. package/src/server/__tests__/write-role-to-acl.test.ts +0 -41
  64. package/src/server/actions/role-collections.ts +0 -95
  65. package/src/server/actions/user-setDefaultRole.ts +0 -47
  66. package/src/server/collections/roles-users.ts +0 -8
  67. package/src/server/collections/roles.ts +0 -101
  68. package/src/server/collections/rolesResources.ts +0 -33
  69. package/src/server/collections/rolesResourcesActions.ts +0 -31
  70. package/src/server/collections/rolesResourcesScopes.ts +0 -25
  71. package/src/server/collections/users.ts +0 -31
  72. package/src/server/index.ts +0 -1
  73. package/src/server/middlewares/setCurrentRole.ts +0 -35
  74. package/src/server/migrations/20221214072638-set-role-snippets.ts +0 -23
  75. package/src/server/model/RoleModel.ts +0 -23
  76. package/src/server/model/RoleResourceActionModel.ts +0 -95
  77. package/src/server/model/RoleResourceModel.ts +0 -74
  78. package/src/server/server.ts +0 -854
  79. /package/{lib → dist}/client/index.d.ts +0 -0
  80. /package/{lib → dist}/server/actions/available-actions.d.ts +0 -0
  81. /package/{lib → dist}/server/actions/role-check.d.ts +0 -0
  82. /package/{lib → dist}/server/actions/role-collections.d.ts +0 -0
  83. /package/{lib → dist}/server/actions/user-setDefaultRole.d.ts +0 -0
  84. /package/{lib → dist}/server/collections/roles-users.d.ts +0 -0
  85. /package/{lib → dist}/server/collections/roles.d.ts +0 -0
  86. /package/{lib → dist}/server/collections/rolesResources.d.ts +0 -0
  87. /package/{lib → dist}/server/collections/rolesResourcesActions.d.ts +0 -0
  88. /package/{lib → dist}/server/collections/rolesResourcesScopes.d.ts +0 -0
  89. /package/{lib → dist}/server/collections/users.d.ts +0 -0
  90. /package/{lib → dist/server}/index.d.ts +0 -0
  91. /package/{lib → dist}/server/middlewares/setCurrentRole.d.ts +0 -0
  92. /package/{lib → dist}/server/migrations/20221214072638-set-role-snippets.d.ts +0 -0
  93. /package/{lib → dist}/server/model/RoleModel.d.ts +0 -0
  94. /package/{lib → dist}/server/model/RoleResourceActionModel.d.ts +0 -0
  95. /package/{lib → dist}/server/model/RoleResourceModel.d.ts +0 -0
  96. /package/{lib → dist}/server/server.d.ts +0 -0
@@ -1,947 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = exports.PluginACL = exports.GrantHelper = void 0;
7
- function _acl() {
8
- const data = require("@nocobase/acl");
9
- _acl = function _acl() {
10
- return data;
11
- };
12
- return data;
13
- }
14
- function _actions() {
15
- const data = require("@nocobase/actions");
16
- _actions = function _actions() {
17
- return data;
18
- };
19
- return data;
20
- }
21
- function _database() {
22
- const data = require("@nocobase/database");
23
- _database = function _database() {
24
- return data;
25
- };
26
- return data;
27
- }
28
- function _server() {
29
- const data = require("@nocobase/server");
30
- _server = function _server() {
31
- return data;
32
- };
33
- return data;
34
- }
35
- function _utils() {
36
- const data = require("@nocobase/utils");
37
- _utils = function _utils() {
38
- return data;
39
- };
40
- return data;
41
- }
42
- function _path() {
43
- const data = require("path");
44
- _path = function _path() {
45
- return data;
46
- };
47
- return data;
48
- }
49
- var _availableActions = require("./actions/available-actions");
50
- var _roleCheck = require("./actions/role-check");
51
- var _roleCollections = require("./actions/role-collections");
52
- var _userSetDefaultRole = require("./actions/user-setDefaultRole");
53
- var _setCurrentRole = require("./middlewares/setCurrentRole");
54
- var _RoleModel = require("./model/RoleModel");
55
- var _RoleResourceActionModel = require("./model/RoleResourceActionModel");
56
- var _RoleResourceModel = require("./model/RoleResourceModel");
57
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
58
- 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."); }
59
- function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
60
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
61
- 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; }
62
- 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; }
63
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
64
- function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
65
- function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
66
- 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; } } }; }
67
- 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); }
68
- 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; }
69
- 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); } }
70
- 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); }); }; }
71
- class GrantHelper {
72
- constructor() {
73
- this.resourceTargetActionMap = new Map();
74
- this.targetActionResourceMap = new Map();
75
- }
76
- }
77
- exports.GrantHelper = GrantHelper;
78
- class PluginACL extends _server().Plugin {
79
- constructor(...args) {
80
- super(...args);
81
- // association field actions config
82
- this.associationFieldsActions = {};
83
- this.grantHelper = new GrantHelper();
84
- }
85
- get acl() {
86
- return this.app.acl;
87
- }
88
- registerAssociationFieldAction(associationType, value) {
89
- this.associationFieldsActions[associationType] = value;
90
- }
91
- registerAssociationFieldsActions() {
92
- // if grant create action to role, it should
93
- // also grant add action and association target's view action
94
- this.registerAssociationFieldAction('hasOne', {
95
- view: {
96
- associationActions: ['list', 'get', 'view']
97
- },
98
- create: {
99
- associationActions: ['create', 'set']
100
- },
101
- update: {
102
- associationActions: ['update', 'remove', 'set']
103
- }
104
- });
105
- this.registerAssociationFieldAction('hasMany', {
106
- view: {
107
- associationActions: ['list', 'get', 'view']
108
- },
109
- create: {
110
- associationActions: ['create', 'set', 'add']
111
- },
112
- update: {
113
- associationActions: ['update', 'remove', 'set']
114
- }
115
- });
116
- this.registerAssociationFieldAction('belongsTo', {
117
- view: {
118
- associationActions: ['list', 'get', 'view']
119
- },
120
- create: {
121
- associationActions: ['create', 'set']
122
- },
123
- update: {
124
- associationActions: ['update', 'remove', 'set']
125
- }
126
- });
127
- this.registerAssociationFieldAction('belongsToMany', {
128
- view: {
129
- associationActions: ['list', 'get', 'view']
130
- },
131
- create: {
132
- associationActions: ['create', 'set', 'add']
133
- },
134
- update: {
135
- associationActions: ['update', 'remove', 'set', 'toggle']
136
- }
137
- });
138
- }
139
- writeResourceToACL(resourceModel, transaction) {
140
- var _this = this;
141
- return _asyncToGenerator(function* () {
142
- yield resourceModel.writeToACL({
143
- acl: _this.acl,
144
- associationFieldsActions: _this.associationFieldsActions,
145
- transaction: transaction,
146
- grantHelper: _this.grantHelper
147
- });
148
- })();
149
- }
150
- writeActionToACL(actionModel, transaction) {
151
- var _this2 = this;
152
- return _asyncToGenerator(function* () {
153
- const resource = actionModel.get('resource');
154
- const role = _this2.acl.getRole(resource.get('roleName'));
155
- yield actionModel.writeToACL({
156
- acl: _this2.acl,
157
- role,
158
- resourceName: resource.get('name'),
159
- associationFieldsActions: _this2.associationFieldsActions,
160
- grantHelper: _this2.grantHelper
161
- });
162
- })();
163
- }
164
- writeRolesToACL() {
165
- var _this3 = this;
166
- return _asyncToGenerator(function* () {
167
- const roles = yield _this3.app.db.getRepository('roles').find({
168
- appends: ['resources', 'resources.actions']
169
- });
170
- var _iterator = _createForOfIteratorHelper(roles),
171
- _step;
172
- try {
173
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
174
- const role = _step.value;
175
- yield _this3.writeRoleToACL(role);
176
- }
177
- } catch (err) {
178
- _iterator.e(err);
179
- } finally {
180
- _iterator.f();
181
- }
182
- })();
183
- }
184
- writeRoleToACL(role, transaction = null) {
185
- var _this4 = this;
186
- return _asyncToGenerator(function* () {
187
- role.writeToAcl({
188
- acl: _this4.acl
189
- });
190
- let resources = role.get('resources');
191
- if (!resources) {
192
- resources = yield role.getResources({
193
- transaction
194
- });
195
- }
196
- var _iterator2 = _createForOfIteratorHelper(resources),
197
- _step2;
198
- try {
199
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
200
- const resource = _step2.value;
201
- yield _this4.writeResourceToACL(resource, transaction);
202
- }
203
- } catch (err) {
204
- _iterator2.e(err);
205
- } finally {
206
- _iterator2.f();
207
- }
208
- })();
209
- }
210
- beforeLoad() {
211
- var _this5 = this;
212
- return _asyncToGenerator(function* () {
213
- _this5.db.addMigrations({
214
- namespace: _this5.name,
215
- directory: (0, _path().resolve)(__dirname, './migrations'),
216
- context: {
217
- plugin: _this5
218
- }
219
- });
220
- _this5.app.db.registerModels({
221
- RoleResourceActionModel: _RoleResourceActionModel.RoleResourceActionModel,
222
- RoleResourceModel: _RoleResourceModel.RoleResourceModel,
223
- RoleModel: _RoleModel.RoleModel
224
- });
225
- _this5.app.acl.registerSnippet({
226
- name: `pm.${_this5.name}.roles`,
227
- actions: ['roles:*', 'roles.snippets:*', 'availableActions:list', 'roles.collections:list', 'roles.resources:*', 'uiSchemas:getProperties', 'roles.menuUiSchemas:*']
228
- });
229
- // change resource fields to association fields
230
- _this5.app.acl.beforeGrantAction(ctx => {
231
- const actionName = _this5.app.acl.resolveActionAlias(ctx.actionName);
232
- const collection = _this5.app.db.getCollection(ctx.resourceName);
233
- if (!collection) {
234
- return;
235
- }
236
- const fieldsParams = ctx.params.fields;
237
- if (!fieldsParams) {
238
- return;
239
- }
240
- if (actionName == 'view' || actionName == 'export') {
241
- const associationsFields = fieldsParams.filter(fieldName => {
242
- const field = collection.getField(fieldName);
243
- return field instanceof _database().RelationField;
244
- });
245
- ctx.params = _objectSpread(_objectSpread({}, ctx.params), {}, {
246
- fields: _utils().lodash.difference(fieldsParams, associationsFields),
247
- appends: associationsFields
248
- });
249
- }
250
- });
251
- _this5.registerAssociationFieldsActions();
252
- _this5.app.resourcer.define(_availableActions.availableActionResource);
253
- _this5.app.resourcer.define(_roleCollections.roleCollectionsResource);
254
- _this5.app.resourcer.registerActionHandler('roles:check', _roleCheck.checkAction);
255
- _this5.app.resourcer.registerActionHandler(`users:setDefaultRole`, _userSetDefaultRole.setDefaultRole);
256
- _this5.db.on('users.afterCreateWithAssociations', /*#__PURE__*/function () {
257
- var _ref = _asyncToGenerator(function* (model, options) {
258
- const transaction = options.transaction;
259
- const repository = _this5.app.db.getRepository('roles');
260
- const defaultRole = yield repository.findOne({
261
- filter: {
262
- default: true
263
- },
264
- transaction
265
- });
266
- if (defaultRole && (yield model.countRoles({
267
- transaction
268
- })) == 0) {
269
- yield model.addRoles(defaultRole, {
270
- transaction
271
- });
272
- }
273
- });
274
- return function (_x, _x2) {
275
- return _ref.apply(this, arguments);
276
- };
277
- }());
278
- _this5.app.on('acl:writeRoleToACL', /*#__PURE__*/function () {
279
- var _ref2 = _asyncToGenerator(function* (roleModel) {
280
- yield _this5.writeRoleToACL(roleModel);
281
- });
282
- return function (_x3) {
283
- return _ref2.apply(this, arguments);
284
- };
285
- }());
286
- _this5.app.db.on('roles.afterSaveWithAssociations', /*#__PURE__*/function () {
287
- var _ref3 = _asyncToGenerator(function* (model, options) {
288
- const transaction = options.transaction;
289
- yield _this5.writeRoleToACL(model, transaction);
290
- // model is default
291
- if (model.get('default')) {
292
- yield _this5.app.db.getRepository('roles').update({
293
- values: {
294
- default: false
295
- },
296
- filter: {
297
- 'name.$ne': model.get('name')
298
- },
299
- hooks: false,
300
- transaction
301
- });
302
- }
303
- });
304
- return function (_x4, _x5) {
305
- return _ref3.apply(this, arguments);
306
- };
307
- }());
308
- _this5.app.db.on('roles.afterDestroy', model => {
309
- const roleName = model.get('name');
310
- _this5.acl.removeRole(roleName);
311
- });
312
- _this5.app.db.on('rolesResources.afterSaveWithAssociations', /*#__PURE__*/function () {
313
- var _ref4 = _asyncToGenerator(function* (model, options) {
314
- yield _this5.writeResourceToACL(model, options.transaction);
315
- });
316
- return function (_x6, _x7) {
317
- return _ref4.apply(this, arguments);
318
- };
319
- }());
320
- _this5.app.db.on('rolesResourcesActions.afterUpdateWithAssociations', /*#__PURE__*/function () {
321
- var _ref5 = _asyncToGenerator(function* (model, options) {
322
- const transaction = options.transaction;
323
- const resource = yield model.getResource({
324
- transaction
325
- });
326
- yield _this5.writeResourceToACL(resource, transaction);
327
- });
328
- return function (_x8, _x9) {
329
- return _ref5.apply(this, arguments);
330
- };
331
- }());
332
- _this5.app.db.on('rolesResources.afterDestroy', /*#__PURE__*/function () {
333
- var _ref6 = _asyncToGenerator(function* (model, options) {
334
- const role = _this5.acl.getRole(model.get('roleName'));
335
- if (role) {
336
- role.revokeResource(model.get('name'));
337
- }
338
- });
339
- return function (_x10, _x11) {
340
- return _ref6.apply(this, arguments);
341
- };
342
- }());
343
- _this5.app.db.on('collections.afterDestroy', /*#__PURE__*/function () {
344
- var _ref7 = _asyncToGenerator(function* (model, options) {
345
- const transaction = options.transaction;
346
- yield _this5.app.db.getRepository('rolesResources').destroy({
347
- filter: {
348
- name: model.get('name')
349
- },
350
- transaction
351
- });
352
- });
353
- return function (_x12, _x13) {
354
- return _ref7.apply(this, arguments);
355
- };
356
- }());
357
- _this5.app.db.on('fields.afterCreate', /*#__PURE__*/function () {
358
- var _ref8 = _asyncToGenerator(function* (model, options) {
359
- const transaction = options.transaction;
360
- const collectionName = model.get('collectionName');
361
- const fieldName = model.get('name');
362
- const resourceActions = yield _this5.app.db.getRepository('rolesResourcesActions').find({
363
- filter: {
364
- 'resource.name': collectionName
365
- },
366
- transaction,
367
- appends: ['resource']
368
- });
369
- var _iterator3 = _createForOfIteratorHelper(resourceActions),
370
- _step3;
371
- try {
372
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
373
- const resourceAction = _step3.value;
374
- const fields = resourceAction.get('fields');
375
- const newFields = [...fields, fieldName];
376
- yield _this5.app.db.getRepository('rolesResourcesActions').update({
377
- filterByTk: resourceAction.get('id'),
378
- values: {
379
- fields: newFields
380
- },
381
- transaction
382
- });
383
- }
384
- } catch (err) {
385
- _iterator3.e(err);
386
- } finally {
387
- _iterator3.f();
388
- }
389
- });
390
- return function (_x14, _x15) {
391
- return _ref8.apply(this, arguments);
392
- };
393
- }());
394
- _this5.app.db.on('fields.afterDestroy', /*#__PURE__*/function () {
395
- var _ref9 = _asyncToGenerator(function* (model, options) {
396
- const collectionName = model.get('collectionName');
397
- const fieldName = model.get('name');
398
- const resourceActions = yield _this5.app.db.getRepository('rolesResourcesActions').find({
399
- filter: {
400
- 'resource.name': collectionName,
401
- 'fields.$anyOf': [fieldName]
402
- },
403
- transaction: options.transaction
404
- });
405
- var _iterator4 = _createForOfIteratorHelper(resourceActions),
406
- _step4;
407
- try {
408
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
409
- const resourceAction = _step4.value;
410
- const fields = resourceAction.get('fields');
411
- const newFields = fields.filter(field => field != fieldName);
412
- yield _this5.app.db.getRepository('rolesResourcesActions').update({
413
- filterByTk: resourceAction.get('id'),
414
- values: {
415
- fields: newFields
416
- },
417
- transaction: options.transaction
418
- });
419
- }
420
- } catch (err) {
421
- _iterator4.e(err);
422
- } finally {
423
- _iterator4.f();
424
- }
425
- });
426
- return function (_x16, _x17) {
427
- return _ref9.apply(this, arguments);
428
- };
429
- }());
430
- // sync database role data to acl
431
- _this5.app.on('afterLoad', /*#__PURE__*/function () {
432
- var _ref10 = _asyncToGenerator(function* (app, options) {
433
- if ((options === null || options === void 0 ? void 0 : options.method) === 'install' || (options === null || options === void 0 ? void 0 : options.method) === 'upgrade') {
434
- return;
435
- }
436
- const exists = yield _this5.app.db.collectionExistsInDb('roles');
437
- if (exists) {
438
- yield _this5.writeRolesToACL();
439
- }
440
- });
441
- return function (_x18, _x19) {
442
- return _ref10.apply(this, arguments);
443
- };
444
- }());
445
- _this5.app.on('afterInstall', /*#__PURE__*/function () {
446
- var _ref11 = _asyncToGenerator(function* (app, options) {
447
- const exists = yield _this5.app.db.collectionExistsInDb('roles');
448
- if (exists) {
449
- yield _this5.writeRolesToACL();
450
- }
451
- });
452
- return function (_x20, _x21) {
453
- return _ref11.apply(this, arguments);
454
- };
455
- }());
456
- _this5.app.on('afterInstallPlugin', /*#__PURE__*/function () {
457
- var _ref12 = _asyncToGenerator(function* (plugin) {
458
- if (plugin.getName() !== 'users') {
459
- return;
460
- }
461
- const User = _this5.db.getCollection('users');
462
- yield User.repository.update({
463
- values: {
464
- roles: ['root', 'admin', 'member']
465
- },
466
- forceUpdate: true
467
- });
468
- const RolesUsers = _this5.db.getCollection('rolesUsers');
469
- yield RolesUsers.repository.update({
470
- filter: {
471
- userId: 1,
472
- roleName: 'root'
473
- },
474
- values: {
475
- default: true
476
- }
477
- });
478
- });
479
- return function (_x22) {
480
- return _ref12.apply(this, arguments);
481
- };
482
- }());
483
- _this5.app.on('beforeInstallPlugin', /*#__PURE__*/function () {
484
- var _ref13 = _asyncToGenerator(function* (plugin) {
485
- if (plugin.getName() !== 'users') {
486
- return;
487
- }
488
- const roles = _this5.app.db.getRepository('roles');
489
- yield roles.createMany({
490
- records: [{
491
- name: 'root',
492
- title: '{{t("Root")}}',
493
- hidden: true,
494
- snippets: ['ui.*', 'pm', 'pm.*']
495
- }, {
496
- name: 'admin',
497
- title: '{{t("Admin")}}',
498
- allowConfigure: true,
499
- allowNewMenu: true,
500
- strategy: {
501
- actions: ['create', 'view', 'update', 'destroy']
502
- },
503
- snippets: ['ui.*', 'pm', 'pm.*']
504
- }, {
505
- name: 'member',
506
- title: '{{t("Member")}}',
507
- allowNewMenu: true,
508
- strategy: {
509
- actions: ['view', 'update:own', 'destroy:own', 'create']
510
- },
511
- default: true,
512
- snippets: ['!ui.*', '!pm', '!pm.*']
513
- }]
514
- });
515
- const rolesResourcesScopes = _this5.app.db.getRepository('rolesResourcesScopes');
516
- yield rolesResourcesScopes.createMany({
517
- records: [{
518
- key: 'all',
519
- name: '{{t("All records")}}',
520
- scope: {}
521
- }, {
522
- key: 'own',
523
- name: '{{t("Own records")}}',
524
- scope: {
525
- createdById: '{{ ctx.state.currentUser.id }}'
526
- }
527
- }]
528
- });
529
- });
530
- return function (_x23) {
531
- return _ref13.apply(this, arguments);
532
- };
533
- }());
534
- _this5.app.resourcer.use(_setCurrentRole.setCurrentRole, {
535
- tag: 'setCurrentRole',
536
- before: 'acl',
537
- after: 'auth'
538
- });
539
- _this5.app.acl.allow('users', 'setDefaultRole', 'loggedIn');
540
- _this5.app.acl.allow('roles', 'check', 'loggedIn');
541
- _this5.app.acl.allow('*', '*', ctx => {
542
- return ctx.state.currentRole === 'root';
543
- });
544
- _this5.app.acl.addFixedParams('collections', 'destroy', () => {
545
- return {
546
- filter: {
547
- $and: [{
548
- 'name.$ne': 'roles'
549
- }, {
550
- 'name.$ne': 'rolesUsers'
551
- }]
552
- }
553
- };
554
- });
555
- _this5.app.acl.addFixedParams('rolesResourcesScopes', 'destroy', () => {
556
- return {
557
- filter: {
558
- $and: [{
559
- 'key.$ne': 'all'
560
- }, {
561
- 'key.$ne': 'own'
562
- }]
563
- }
564
- };
565
- });
566
- _this5.app.acl.addFixedParams('rolesResourcesScopes', 'update', () => {
567
- return {
568
- filter: {
569
- $and: [{
570
- 'key.$ne': 'all'
571
- }, {
572
- 'key.$ne': 'own'
573
- }]
574
- }
575
- };
576
- });
577
- _this5.app.acl.addFixedParams('roles', 'destroy', () => {
578
- return {
579
- filter: {
580
- $and: [{
581
- 'name.$ne': 'root'
582
- }, {
583
- 'name.$ne': 'admin'
584
- }, {
585
- 'name.$ne': 'member'
586
- }]
587
- }
588
- };
589
- });
590
- _this5.app.resourcer.use( /*#__PURE__*/function () {
591
- var _ref14 = _asyncToGenerator(function* (ctx, next) {
592
- const _ctx$action = ctx.action,
593
- actionName = _ctx$action.actionName,
594
- resourceName = _ctx$action.resourceName,
595
- params = _ctx$action.params;
596
- const _ref15 = params || {},
597
- showAnonymous = _ref15.showAnonymous;
598
- if (actionName === 'list' && resourceName === 'roles') {
599
- if (!showAnonymous) {
600
- ctx.action.mergeParams({
601
- filter: {
602
- 'name.$ne': 'anonymous'
603
- }
604
- });
605
- }
606
- }
607
- if (actionName === 'update' && resourceName === 'roles.resources') {
608
- ctx.action.mergeParams({
609
- updateAssociationValues: ['actions']
610
- });
611
- }
612
- yield next();
613
- });
614
- return function (_x24, _x25) {
615
- return _ref14.apply(this, arguments);
616
- };
617
- }());
618
- _this5.app.acl.use( /*#__PURE__*/function () {
619
- var _ref16 = _asyncToGenerator(function* (ctx, next) {
620
- const _ctx$action2 = ctx.action,
621
- actionName = _ctx$action2.actionName,
622
- resourceName = _ctx$action2.resourceName;
623
- if (actionName === 'get' || actionName === 'list') {
624
- var _ctx$permission, _ctx$permission$can, _ctx$permission$can$p;
625
- if (!Array.isArray(ctx === null || ctx === void 0 ? void 0 : (_ctx$permission = ctx.permission) === null || _ctx$permission === void 0 ? void 0 : (_ctx$permission$can = _ctx$permission.can) === null || _ctx$permission$can === void 0 ? void 0 : (_ctx$permission$can$p = _ctx$permission$can.params) === null || _ctx$permission$can$p === void 0 ? void 0 : _ctx$permission$can$p.fields)) {
626
- return next();
627
- }
628
- let collection;
629
- if (resourceName.includes('.')) {
630
- var _ctx$db$getCollection, _ctx$db$getCollection2;
631
- const _resourceName$split = resourceName.split('.'),
632
- _resourceName$split2 = _slicedToArray(_resourceName$split, 2),
633
- collectionName = _resourceName$split2[0],
634
- associationName = _resourceName$split2[1];
635
- const field = (_ctx$db$getCollection = ctx.db.getCollection(collectionName)) === null || _ctx$db$getCollection === void 0 ? void 0 : (_ctx$db$getCollection2 = _ctx$db$getCollection.getField) === null || _ctx$db$getCollection2 === void 0 ? void 0 : _ctx$db$getCollection2.call(_ctx$db$getCollection, associationName);
636
- if (field.target) {
637
- collection = ctx.db.getCollection(field.target);
638
- }
639
- } else {
640
- collection = ctx.db.getCollection(resourceName);
641
- }
642
- if (collection && collection.hasField('createdById')) {
643
- ctx.permission.can.params.fields.push('createdById');
644
- }
645
- }
646
- return next();
647
- });
648
- return function (_x26, _x27) {
649
- return _ref16.apply(this, arguments);
650
- };
651
- }());
652
- const parseJsonTemplate = _this5.app.acl.parseJsonTemplate;
653
- _this5.app.acl.use( /*#__PURE__*/function () {
654
- var _ref17 = _asyncToGenerator(function* (ctx, next) {
655
- const _ctx$action3 = ctx.action,
656
- actionName = _ctx$action3.actionName,
657
- resourceName = _ctx$action3.resourceName,
658
- resourceOf = _ctx$action3.resourceOf;
659
- // is association request
660
- if (resourceName.includes('.') && resourceOf) {
661
- var _ctx$permission2, _ctx$permission2$can, _availableAction$opti;
662
- if (!(ctx !== null && ctx !== void 0 && (_ctx$permission2 = ctx.permission) !== null && _ctx$permission2 !== void 0 && (_ctx$permission2$can = _ctx$permission2.can) !== null && _ctx$permission2$can !== void 0 && _ctx$permission2$can.params)) {
663
- return next();
664
- }
665
- // 关联数据去掉 filter
666
- delete ctx.permission.can.params.filter;
667
- // 关联数据能不能处理取决于 source 是否有权限
668
- const _resourceName$split3 = resourceName.split('.'),
669
- _resourceName$split4 = _slicedToArray(_resourceName$split3, 1),
670
- collectionName = _resourceName$split4[0];
671
- const action = ctx.can({
672
- resource: collectionName,
673
- action: actionName
674
- });
675
- const availableAction = _this5.app.acl.getAvailableAction(actionName);
676
- if (availableAction !== null && availableAction !== void 0 && (_availableAction$opti = availableAction.options) !== null && _availableAction$opti !== void 0 && _availableAction$opti.onNewRecord) {
677
- if (action) {
678
- ctx.permission.skip = true;
679
- } else {
680
- ctx.permission.can = false;
681
- }
682
- } else {
683
- var _action$params;
684
- const filter = yield parseJsonTemplate((action === null || action === void 0 ? void 0 : (_action$params = action.params) === null || _action$params === void 0 ? void 0 : _action$params.filter) || {}, ctx);
685
- const sourceInstance = yield ctx.db.getRepository(collectionName).findOne({
686
- filterByTk: resourceOf,
687
- filter
688
- });
689
- if (!sourceInstance) {
690
- ctx.permission.can = false;
691
- }
692
- }
693
- }
694
- yield next();
695
- });
696
- return function (_x28, _x29) {
697
- return _ref17.apply(this, arguments);
698
- };
699
- }(), {
700
- before: 'core'
701
- });
702
- // throw error when user has no fixed params permissions
703
- _this5.app.acl.use( /*#__PURE__*/function () {
704
- var _ref18 = _asyncToGenerator(function* (ctx, next) {
705
- var _ctx$permission3, _ctx$permission3$can;
706
- const action = (_ctx$permission3 = ctx.permission) === null || _ctx$permission3 === void 0 ? void 0 : (_ctx$permission3$can = _ctx$permission3.can) === null || _ctx$permission3$can === void 0 ? void 0 : _ctx$permission3$can.action;
707
- if (action == 'destroy' && !ctx.action.resourceName.includes('.')) {
708
- const repository = _actions().utils.getRepositoryFromParams(ctx);
709
- // params after merge with fixed params
710
- const filteredCount = yield repository.count(ctx.permission.mergedParams);
711
- // params user requested
712
- const queryCount = yield repository.count(ctx.permission.rawParams);
713
- if (queryCount > filteredCount) {
714
- ctx.throw(403, 'No permissions');
715
- return;
716
- }
717
- }
718
- yield next();
719
- });
720
- return function (_x30, _x31) {
721
- return _ref18.apply(this, arguments);
722
- };
723
- }(), {
724
- after: 'core',
725
- group: 'after'
726
- });
727
- const withACLMeta = /*#__PURE__*/function () {
728
- var _ref19 = _asyncToGenerator(function* (ctx, next) {
729
- var _ctx$body;
730
- yield next();
731
- if (!ctx.action || !ctx.get('X-With-ACL-Meta') || ctx.status !== 200) {
732
- return;
733
- }
734
- const _ctx$action4 = ctx.action,
735
- resourceName = _ctx$action4.resourceName,
736
- actionName = _ctx$action4.actionName;
737
- if (!['list', 'get'].includes(actionName)) {
738
- return;
739
- }
740
- const collection = ctx.db.getCollection(resourceName);
741
- if (!collection) {
742
- return;
743
- }
744
- const Model = collection.model;
745
- const primaryKeyField = Model.primaryKeyField || Model.primaryKeyAttribute;
746
- const dataPath = (_ctx$body = ctx.body) !== null && _ctx$body !== void 0 && _ctx$body.rows ? 'body.rows' : 'body';
747
- let listData = _utils().lodash.get(ctx, dataPath);
748
- if (actionName == 'get') {
749
- listData = _utils().lodash.castArray(listData);
750
- }
751
- const inspectActions = ['view', 'update', 'destroy'];
752
- const actionsParams = [];
753
- for (var _i2 = 0, _inspectActions = inspectActions; _i2 < _inspectActions.length; _i2++) {
754
- var _actionCtx$permission, _actionCtx$permission2;
755
- const action = _inspectActions[_i2];
756
- const actionCtx = {
757
- db: ctx.db,
758
- action: {
759
- actionName: action,
760
- name: action,
761
- params: {},
762
- resourceName: ctx.action.resourceName,
763
- resourceOf: ctx.action.resourceOf,
764
- mergeParams() {}
765
- },
766
- state: {
767
- currentRole: ctx.state.currentRole,
768
- currentUser: (() => {
769
- if (!ctx.state.currentUser) {
770
- return null;
771
- }
772
- if (ctx.state.currentUser.toJSON) {
773
- var _ctx$state$currentUse;
774
- return (_ctx$state$currentUse = ctx.state.currentUser) === null || _ctx$state$currentUse === void 0 ? void 0 : _ctx$state$currentUse.toJSON();
775
- }
776
- return ctx.state.currentUser;
777
- })()
778
- },
779
- permission: {},
780
- throw(...args) {
781
- throw new (_acl().NoPermissionError)(...args);
782
- }
783
- };
784
- try {
785
- yield _this5.app.acl.getActionParams(actionCtx);
786
- } catch (e) {
787
- if (e instanceof _acl().NoPermissionError) {
788
- continue;
789
- }
790
- throw e;
791
- }
792
- actionsParams.push([action, ((_actionCtx$permission = actionCtx.permission) === null || _actionCtx$permission === void 0 ? void 0 : _actionCtx$permission.can) === null && !actionCtx.permission.skip ? null : ((_actionCtx$permission2 = actionCtx.permission) === null || _actionCtx$permission2 === void 0 ? void 0 : _actionCtx$permission2.parsedParams) || {}, actionCtx]);
793
- }
794
- const ids = (() => {
795
- if (collection.options.tree) {
796
- if (listData.length == 0) return [];
797
- const getAllNodeIds = data => [data[primaryKeyField], ...(data.children || []).flatMap(getAllNodeIds)];
798
- return listData.map(tree => getAllNodeIds(tree.toJSON())).flat();
799
- }
800
- return listData.map(item => item[primaryKeyField]);
801
- })();
802
- const conditions = [];
803
- const allAllowed = [];
804
- for (var _i3 = 0, _actionsParams = actionsParams; _i3 < _actionsParams.length; _i3++) {
805
- const _actionsParams$_i = _slicedToArray(_actionsParams[_i3], 3),
806
- action = _actionsParams$_i[0],
807
- params = _actionsParams$_i[1],
808
- actionCtx = _actionsParams$_i[2];
809
- if (!params) {
810
- continue;
811
- }
812
- if (_utils().lodash.isEmpty(params) || _utils().lodash.isEmpty(params.filter)) {
813
- allAllowed.push(action);
814
- continue;
815
- }
816
- const queryParams = collection.repository.buildQueryOptions(_objectSpread(_objectSpread({}, params), {}, {
817
- context: actionCtx
818
- }));
819
- const actionSql = ctx.db.sequelize.queryInterface.queryGenerator.selectQuery(Model.getTableName(), {
820
- where: (() => {
821
- const filterObj = queryParams.where;
822
- if (!_this5.db.options.underscored) {
823
- return filterObj;
824
- }
825
- const isAssociationKey = key => {
826
- return key.startsWith('$') && key.endsWith('$');
827
- };
828
- // change camelCase to snake_case
829
- const iterate = (rootObj, path = []) => {
830
- const obj = path.length == 0 ? rootObj : _utils().lodash.get(rootObj, path);
831
- if (Array.isArray(obj)) {
832
- for (let i = 0; i < obj.length; i++) {
833
- if (obj[i] === null) {
834
- continue;
835
- }
836
- if (typeof obj[i] === 'object') {
837
- iterate(rootObj, [...path, i]);
838
- }
839
- }
840
- return;
841
- }
842
- Reflect.ownKeys(obj).forEach(key => {
843
- if (Array.isArray(obj) && key == 'length') {
844
- return;
845
- }
846
- if (typeof obj[key] === 'object' && obj[key] !== null || typeof obj[key] === 'symbol') {
847
- iterate(rootObj, [...path, key]);
848
- }
849
- if (typeof key === 'string' && key !== (0, _database().snakeCase)(key)) {
850
- const setKey = isAssociationKey(key) ? (() => {
851
- const parts = key.split('.');
852
- parts[parts.length - 1] = _utils().lodash.snakeCase(parts[parts.length - 1]);
853
- const result = parts.join('.');
854
- return result.endsWith('$') ? result : `${result}$`;
855
- })() : (0, _database().snakeCase)(key);
856
- const setValue = _utils().lodash.cloneDeep(obj[key]);
857
- _utils().lodash.unset(rootObj, [...path, key]);
858
- _utils().lodash.set(rootObj, [...path, setKey], setValue);
859
- }
860
- });
861
- };
862
- iterate(filterObj);
863
- return filterObj;
864
- })(),
865
- attributes: [primaryKeyField],
866
- includeIgnoreAttributes: false
867
- }, Model);
868
- const whereCase = actionSql.match(/WHERE (.*?);/)[1];
869
- conditions.push({
870
- whereCase,
871
- action,
872
- include: queryParams.include
873
- });
874
- }
875
- const results = yield collection.model.findAll({
876
- where: {
877
- [primaryKeyField]: ids
878
- },
879
- attributes: [primaryKeyField, ...conditions.map(condition => {
880
- return [ctx.db.sequelize.literal(`CASE WHEN ${condition.whereCase} THEN 1 ELSE 0 END`), condition.action];
881
- })],
882
- include: conditions.map(condition => condition.include).flat()
883
- });
884
- const allowedActions = inspectActions.map(action => {
885
- if (allAllowed.includes(action)) {
886
- return [action, ids];
887
- }
888
- return [action, results.filter(item => Boolean(item.get(action))).map(item => item.get(primaryKeyField))];
889
- }).reduce((acc, [action, ids]) => {
890
- acc[action] = ids;
891
- return acc;
892
- }, {});
893
- if (actionName == 'get') {
894
- ctx.bodyMeta = _objectSpread(_objectSpread({}, ctx.bodyMeta || {}), {}, {
895
- allowedActions: allowedActions
896
- });
897
- }
898
- if (actionName == 'list') {
899
- ctx.body.allowedActions = allowedActions;
900
- }
901
- });
902
- return function withACLMeta(_x32, _x33) {
903
- return _ref19.apply(this, arguments);
904
- };
905
- }();
906
- // append allowedActions to list & get response
907
- _this5.app.use( /*#__PURE__*/function () {
908
- var _ref20 = _asyncToGenerator(function* (ctx, next) {
909
- try {
910
- yield withACLMeta(ctx, next);
911
- } catch (error) {
912
- ctx.logger.error(error);
913
- }
914
- });
915
- return function (_x34, _x35) {
916
- return _ref20.apply(this, arguments);
917
- };
918
- }(), {
919
- after: 'restApi',
920
- group: 'after'
921
- });
922
- })();
923
- }
924
- install() {
925
- var _this6 = this;
926
- return _asyncToGenerator(function* () {
927
- const repo = _this6.db.getRepository('collections');
928
- if (repo) {
929
- yield repo.db2cm('roles');
930
- }
931
- })();
932
- }
933
- load() {
934
- var _this7 = this;
935
- return _asyncToGenerator(function* () {
936
- yield _this7.importCollections((0, _path().resolve)(__dirname, 'collections'));
937
- _this7.db.extendCollection({
938
- name: 'rolesUischemas',
939
- namespace: 'acl.acl',
940
- duplicator: 'required'
941
- });
942
- })();
943
- }
944
- }
945
- exports.PluginACL = PluginACL;
946
- var _default = PluginACL;
947
- exports.default = _default;