@forestadmin/agent 1.0.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 (119) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +0 -0
  3. package/dist/agent.d.ts +76 -0
  4. package/dist/agent.js +133 -0
  5. package/dist/framework-mounter.d.ts +43 -0
  6. package/dist/framework-mounter.js +157 -0
  7. package/dist/index.d.ts +8 -0
  8. package/dist/index.js +15 -0
  9. package/dist/routes/access/api-chart.d.ts +16 -0
  10. package/dist/routes/access/api-chart.js +47 -0
  11. package/dist/routes/access/chart.d.ts +18 -0
  12. package/dist/routes/access/chart.js +162 -0
  13. package/dist/routes/access/count-related.d.ts +9 -0
  14. package/dist/routes/access/count-related.js +31 -0
  15. package/dist/routes/access/count.d.ts +9 -0
  16. package/dist/routes/access/count.js +31 -0
  17. package/dist/routes/access/csv-related.d.ts +9 -0
  18. package/dist/routes/access/csv-related.js +33 -0
  19. package/dist/routes/access/csv.d.ts +9 -0
  20. package/dist/routes/access/csv.js +31 -0
  21. package/dist/routes/access/get.d.ts +9 -0
  22. package/dist/routes/access/get.js +29 -0
  23. package/dist/routes/access/list-related.d.ts +9 -0
  24. package/dist/routes/access/list-related.js +25 -0
  25. package/dist/routes/access/list.d.ts +9 -0
  26. package/dist/routes/access/list.js +22 -0
  27. package/dist/routes/base-route.d.ts +13 -0
  28. package/dist/routes/base-route.js +13 -0
  29. package/dist/routes/collection-route.d.ts +12 -0
  30. package/dist/routes/collection-route.js +20 -0
  31. package/dist/routes/index.d.ts +30 -0
  32. package/dist/routes/index.js +108 -0
  33. package/dist/routes/modification/action.d.ts +16 -0
  34. package/dist/routes/modification/action.js +104 -0
  35. package/dist/routes/modification/associate-related.d.ts +12 -0
  36. package/dist/routes/modification/associate-related.js +51 -0
  37. package/dist/routes/modification/create.d.ts +14 -0
  38. package/dist/routes/modification/create.js +83 -0
  39. package/dist/routes/modification/delete.d.ts +11 -0
  40. package/dist/routes/modification/delete.js +41 -0
  41. package/dist/routes/modification/dissociate-delete-related.d.ts +20 -0
  42. package/dist/routes/modification/dissociate-delete-related.js +89 -0
  43. package/dist/routes/modification/update-field.d.ts +9 -0
  44. package/dist/routes/modification/update-field.js +39 -0
  45. package/dist/routes/modification/update-relation.d.ts +11 -0
  46. package/dist/routes/modification/update-relation.js +59 -0
  47. package/dist/routes/modification/update.d.ts +9 -0
  48. package/dist/routes/modification/update.js +31 -0
  49. package/dist/routes/relation-route.d.ts +10 -0
  50. package/dist/routes/relation-route.js +18 -0
  51. package/dist/routes/security/authentication.d.ts +15 -0
  52. package/dist/routes/security/authentication.js +74 -0
  53. package/dist/routes/security/ip-whitelist.d.ts +14 -0
  54. package/dist/routes/security/ip-whitelist.js +35 -0
  55. package/dist/routes/security/scope-invalidation.d.ts +11 -0
  56. package/dist/routes/security/scope-invalidation.js +28 -0
  57. package/dist/routes/system/error-handling.d.ts +13 -0
  58. package/dist/routes/system/error-handling.js +75 -0
  59. package/dist/routes/system/healthcheck.d.ts +11 -0
  60. package/dist/routes/system/healthcheck.js +22 -0
  61. package/dist/routes/system/logger.d.ts +10 -0
  62. package/dist/routes/system/logger.js +35 -0
  63. package/dist/services/authorization/authorization.d.ts +15 -0
  64. package/dist/services/authorization/authorization.js +45 -0
  65. package/dist/services/authorization/index.d.ts +5 -0
  66. package/dist/services/authorization/index.js +16 -0
  67. package/dist/services/authorization/internal/action-permission.d.ts +16 -0
  68. package/dist/services/authorization/internal/action-permission.js +68 -0
  69. package/dist/services/authorization/internal/generate-action-identifier.d.ts +4 -0
  70. package/dist/services/authorization/internal/generate-action-identifier.js +12 -0
  71. package/dist/services/authorization/internal/generate-actions-from-permissions.d.ts +8 -0
  72. package/dist/services/authorization/internal/generate-actions-from-permissions.js +87 -0
  73. package/dist/services/authorization/internal/types.d.ts +61 -0
  74. package/dist/services/authorization/internal/types.js +26 -0
  75. package/dist/services/index.d.ts +12 -0
  76. package/dist/services/index.js +16 -0
  77. package/dist/services/permissions.d.ts +19 -0
  78. package/dist/services/permissions.js +85 -0
  79. package/dist/services/serializer.d.ts +12 -0
  80. package/dist/services/serializer.js +120 -0
  81. package/dist/types.d.ts +41 -0
  82. package/dist/types.js +23 -0
  83. package/dist/utils/body-parser.d.ts +7 -0
  84. package/dist/utils/body-parser.js +18 -0
  85. package/dist/utils/condition-tree-parser.d.ts +11 -0
  86. package/dist/utils/condition-tree-parser.js +53 -0
  87. package/dist/utils/context-filter-factory.d.ts +7 -0
  88. package/dist/utils/context-filter-factory.js +28 -0
  89. package/dist/utils/csv-generator.d.ts +12 -0
  90. package/dist/utils/csv-generator.js +39 -0
  91. package/dist/utils/csv-route-context.d.ts +5 -0
  92. package/dist/utils/csv-route-context.js +14 -0
  93. package/dist/utils/forest-http-api.d.ts +68 -0
  94. package/dist/utils/forest-http-api.js +202 -0
  95. package/dist/utils/forest-schema/action-values.d.ts +34 -0
  96. package/dist/utils/forest-schema/action-values.js +144 -0
  97. package/dist/utils/forest-schema/emitter.d.ts +20 -0
  98. package/dist/utils/forest-schema/emitter.js +70 -0
  99. package/dist/utils/forest-schema/filterable.d.ts +16 -0
  100. package/dist/utils/forest-schema/filterable.js +68 -0
  101. package/dist/utils/forest-schema/generator-actions.d.ts +14 -0
  102. package/dist/utils/forest-schema/generator-actions.js +99 -0
  103. package/dist/utils/forest-schema/generator-collection.d.ts +7 -0
  104. package/dist/utils/forest-schema/generator-collection.js +36 -0
  105. package/dist/utils/forest-schema/generator-fields.d.ts +14 -0
  106. package/dist/utils/forest-schema/generator-fields.js +160 -0
  107. package/dist/utils/forest-schema/generator-segments.d.ts +6 -0
  108. package/dist/utils/forest-schema/generator-segments.js +9 -0
  109. package/dist/utils/forest-schema/types.d.ts +85 -0
  110. package/dist/utils/forest-schema/types.js +16 -0
  111. package/dist/utils/forest-schema/validation.d.ts +10 -0
  112. package/dist/utils/forest-schema/validation.js +28 -0
  113. package/dist/utils/id.d.ts +8 -0
  114. package/dist/utils/id.js +43 -0
  115. package/dist/utils/options-validator.d.ts +12 -0
  116. package/dist/utils/options-validator.js +92 -0
  117. package/dist/utils/query-string.d.ts +14 -0
  118. package/dist/utils/query-string.js +134 -0
  119. package/package.json +66 -0
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const types_1 = require("./internal/types");
4
+ const generate_action_identifier_1 = require("./internal/generate-action-identifier");
5
+ class AuthorizationService {
6
+ constructor(actionPermissionService) {
7
+ this.actionPermissionService = actionPermissionService;
8
+ }
9
+ async assertCanBrowse(context, collectionName) {
10
+ await this.assertCanOnCollection(context, types_1.CollectionActionEvent.Browse, collectionName);
11
+ }
12
+ async assertCanRead(context, collectionName) {
13
+ await this.assertCanOnCollection(context, types_1.CollectionActionEvent.Read, collectionName);
14
+ }
15
+ async assertCanAdd(context, collectionName) {
16
+ await this.assertCanOnCollection(context, types_1.CollectionActionEvent.Add, collectionName);
17
+ }
18
+ async assertCanEdit(context, collectionName) {
19
+ await this.assertCanOnCollection(context, types_1.CollectionActionEvent.Edit, collectionName);
20
+ }
21
+ async assertCanDelete(context, collectionName) {
22
+ await this.assertCanOnCollection(context, types_1.CollectionActionEvent.Delete, collectionName);
23
+ }
24
+ async assertCanExport(context, collectionName) {
25
+ await this.assertCanOnCollection(context, types_1.CollectionActionEvent.Export, collectionName);
26
+ }
27
+ async assertCanOnCollection(context, event, collectionName) {
28
+ const { id: userId } = context.state.user;
29
+ if (!(await this.actionPermissionService.can(`${userId}`, (0, generate_action_identifier_1.generateCollectionActionIdentifier)(event, collectionName)))) {
30
+ context.throw(403, 'Forbidden');
31
+ }
32
+ }
33
+ async assertCanExecuteCustomAction(context, customActionName, collectionName) {
34
+ const { id: userId } = context.state.user;
35
+ if (!(await this.actionPermissionService.canOneOf(`${userId}`, [
36
+ (0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.Trigger, customActionName, collectionName),
37
+ (0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.Approve, customActionName, collectionName),
38
+ (0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.SelfApprove, customActionName, collectionName),
39
+ ]))) {
40
+ context.throw(403, 'Forbidden');
41
+ }
42
+ }
43
+ }
44
+ exports.default = AuthorizationService;
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aG9yaXphdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9hdXRob3JpemF0aW9uL2F1dGhvcml6YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSw0Q0FBNEU7QUFDNUUsc0ZBRytDO0FBRy9DLE1BQXFCLG9CQUFvQjtJQUN2QyxZQUE2Qix1QkFBZ0Q7UUFBaEQsNEJBQXVCLEdBQXZCLHVCQUF1QixDQUF5QjtJQUFHLENBQUM7SUFFMUUsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFnQixFQUFFLGNBQXNCO1FBQ25FLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sRUFBRSw2QkFBcUIsQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDMUYsQ0FBQztJQUVNLEtBQUssQ0FBQyxhQUFhLENBQUMsT0FBZ0IsRUFBRSxjQUFzQjtRQUNqRSxNQUFNLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsNkJBQXFCLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3hGLENBQUM7SUFFTSxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQWdCLEVBQUUsY0FBc0I7UUFDaEUsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsT0FBTyxFQUFFLDZCQUFxQixDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRU0sS0FBSyxDQUFDLGFBQWEsQ0FBQyxPQUFnQixFQUFFLGNBQXNCO1FBQ2pFLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sRUFBRSw2QkFBcUIsQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDeEYsQ0FBQztJQUVNLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBZ0IsRUFBRSxjQUFzQjtRQUNuRSxNQUFNLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsNkJBQXFCLENBQUMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFTSxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQWdCLEVBQUUsY0FBc0I7UUFDbkUsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsT0FBTyxFQUFFLDZCQUFxQixDQUFDLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztJQUMxRixDQUFDO0lBRU8sS0FBSyxDQUFDLHFCQUFxQixDQUNqQyxPQUFnQixFQUNoQixLQUE0QixFQUM1QixjQUFzQjtRQUV0QixNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO1FBRTFDLElBQ0UsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLEdBQUcsQ0FDdEMsR0FBRyxNQUFNLEVBQUUsRUFDWCxJQUFBLCtEQUFrQyxFQUFDLEtBQUssRUFBRSxjQUFjLENBQUMsQ0FDMUQsQ0FBQyxFQUNGO1lBQ0EsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDakM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLDRCQUE0QixDQUN2QyxPQUFnQixFQUNoQixnQkFBd0IsRUFDeEIsY0FBc0I7UUFFdEIsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztRQUUxQyxJQUNFLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsR0FBRyxNQUFNLEVBQUUsRUFBRTtZQUN6RCxJQUFBLDJEQUE4QixFQUFDLHlCQUFpQixDQUFDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLENBQUM7WUFDM0YsSUFBQSwyREFBOEIsRUFBQyx5QkFBaUIsQ0FBQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxDQUFDO1lBQzNGLElBQUEsMkRBQThCLEVBQzVCLHlCQUFpQixDQUFDLFdBQVcsRUFDN0IsZ0JBQWdCLEVBQ2hCLGNBQWMsQ0FDZjtTQUNGLENBQUMsQ0FBQyxFQUNIO1lBQ0EsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDakM7SUFDSCxDQUFDO0NBQ0Y7QUFqRUQsdUNBaUVDIn0=
@@ -0,0 +1,5 @@
1
+ import { AgentOptionsWithDefaults } from '../../types';
2
+ import AuthorizationService from './authorization';
3
+ export default function authorizationServiceFactory(options: AgentOptionsWithDefaults): AuthorizationService;
4
+ export { CustomActionEvent, EnvironmentPermissionsV4, UserPermissionV4 } from './internal/types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CustomActionEvent = void 0;
7
+ const action_permission_1 = __importDefault(require("./internal/action-permission"));
8
+ const authorization_1 = __importDefault(require("./authorization"));
9
+ function authorizationServiceFactory(options) {
10
+ const actionPermissionService = new action_permission_1.default(options);
11
+ return new authorization_1.default(actionPermissionService);
12
+ }
13
+ exports.default = authorizationServiceFactory;
14
+ var types_1 = require("./internal/types");
15
+ Object.defineProperty(exports, "CustomActionEvent", { enumerable: true, get: function () { return types_1.CustomActionEvent; } });
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvYXV0aG9yaXphdGlvbi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxxRkFBbUU7QUFDbkUsb0VBQW1EO0FBRW5ELFNBQXdCLDJCQUEyQixDQUNqRCxPQUFpQztJQUVqQyxNQUFNLHVCQUF1QixHQUFHLElBQUksMkJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFckUsT0FBTyxJQUFJLHVCQUFvQixDQUFDLHVCQUF1QixDQUFDLENBQUM7QUFDM0QsQ0FBQztBQU5ELDhDQU1DO0FBRUQsMENBQWlHO0FBQXhGLDBHQUFBLGlCQUFpQixPQUFBIn0=
@@ -0,0 +1,16 @@
1
+ import { AgentOptionsWithDefaults } from '../../../types';
2
+ export declare type ActionPermissionOptions = Pick<AgentOptionsWithDefaults, 'forestServerUrl' | 'envSecret' | 'isProduction' | 'permissionsCacheDurationInSeconds'>;
3
+ export default class ActionPermissionService {
4
+ private readonly options;
5
+ private permissionsPromise;
6
+ private permissionExpirationTimestamp;
7
+ constructor(options: ActionPermissionOptions);
8
+ canOneOf(userId: string, actionNames: string[]): Promise<boolean>;
9
+ can(userId: string, actionName: string): Promise<boolean>;
10
+ private hasPermissionOrRefetch;
11
+ private isAllowedOneOf;
12
+ private isAllowed;
13
+ private getPermissions;
14
+ private fetchEnvironmentPermissions;
15
+ }
16
+ //# sourceMappingURL=action-permission.d.ts.map
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const forest_http_api_1 = __importDefault(require("../../../utils/forest-http-api"));
7
+ const generate_actions_from_permissions_1 = __importDefault(require("./generate-actions-from-permissions"));
8
+ class ActionPermissionService {
9
+ constructor(options) {
10
+ this.options = options;
11
+ }
12
+ canOneOf(userId, actionNames) {
13
+ return this.hasPermissionOrRefetch({
14
+ userId,
15
+ actionNames,
16
+ allowRefetch: true,
17
+ });
18
+ }
19
+ can(userId, actionName) {
20
+ return this.hasPermissionOrRefetch({
21
+ userId,
22
+ actionNames: [actionName],
23
+ allowRefetch: true,
24
+ });
25
+ }
26
+ async hasPermissionOrRefetch({ userId, actionNames, allowRefetch, }) {
27
+ const permissions = await this.getPermissions();
28
+ const isAllowed = this.isAllowedOneOf({ permissions, actionNames, userId });
29
+ if (!isAllowed && allowRefetch) {
30
+ this.permissionsPromise = undefined;
31
+ this.permissionExpirationTimestamp = undefined;
32
+ return this.hasPermissionOrRefetch({
33
+ userId,
34
+ actionNames,
35
+ allowRefetch: false,
36
+ });
37
+ }
38
+ return isAllowed;
39
+ }
40
+ isAllowedOneOf({ permissions, actionNames, userId, }) {
41
+ return actionNames.some(actionName => this.isAllowed({ permissions, actionName, userId }));
42
+ }
43
+ isAllowed({ permissions, actionName, userId, }) {
44
+ return (permissions.everythingAllowed ||
45
+ permissions.actionsGloballyAllowed.has(actionName) ||
46
+ permissions.actionsAllowedByUser.get(actionName)?.has(userId));
47
+ }
48
+ async getPermissions() {
49
+ if (this.permissionsPromise &&
50
+ this.permissionExpirationTimestamp &&
51
+ this.permissionExpirationTimestamp > Date.now()) {
52
+ return this.permissionsPromise;
53
+ }
54
+ this.permissionsPromise = this.fetchEnvironmentPermissions();
55
+ this.permissionExpirationTimestamp =
56
+ Date.now() + this.options.permissionsCacheDurationInSeconds * 1000;
57
+ return this.permissionsPromise;
58
+ }
59
+ async fetchEnvironmentPermissions() {
60
+ const [rawPermissions, users] = await Promise.all([
61
+ forest_http_api_1.default.getEnvironmentPermissions(this.options),
62
+ forest_http_api_1.default.getUsers(this.options),
63
+ ]);
64
+ return (0, generate_actions_from_permissions_1.default)(rawPermissions, users);
65
+ }
66
+ }
67
+ exports.default = ActionPermissionService;
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLXBlcm1pc3Npb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvYXV0aG9yaXphdGlvbi9pbnRlcm5hbC9hY3Rpb24tcGVybWlzc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLHFGQUEyRDtBQUMzRCw0R0FFNkM7QUFPN0MsTUFBcUIsdUJBQXVCO0lBSTFDLFlBQTZCLE9BQWdDO1FBQWhDLFlBQU8sR0FBUCxPQUFPLENBQXlCO0lBQUcsQ0FBQztJQUUxRCxRQUFRLENBQUMsTUFBYyxFQUFFLFdBQXFCO1FBQ25ELE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDO1lBQ2pDLE1BQU07WUFDTixXQUFXO1lBQ1gsWUFBWSxFQUFFLElBQUk7U0FDbkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEdBQUcsQ0FBQyxNQUFjLEVBQUUsVUFBa0I7UUFDM0MsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUM7WUFDakMsTUFBTTtZQUNOLFdBQVcsRUFBRSxDQUFDLFVBQVUsQ0FBQztZQUN6QixZQUFZLEVBQUUsSUFBSTtTQUNuQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUFDLEVBQ25DLE1BQU0sRUFDTixXQUFXLEVBQ1gsWUFBWSxHQUtiO1FBQ0MsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDaEQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUU1RSxJQUFJLENBQUMsU0FBUyxJQUFJLFlBQVksRUFBRTtZQUM5QixJQUFJLENBQUMsa0JBQWtCLEdBQUcsU0FBUyxDQUFDO1lBQ3BDLElBQUksQ0FBQyw2QkFBNkIsR0FBRyxTQUFTLENBQUM7WUFFL0MsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUM7Z0JBQ2pDLE1BQU07Z0JBQ04sV0FBVztnQkFDWCxZQUFZLEVBQUUsS0FBSzthQUNwQixDQUFDLENBQUM7U0FDSjtRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFTyxjQUFjLENBQUMsRUFDckIsV0FBVyxFQUNYLFdBQVcsRUFDWCxNQUFNLEdBS1A7UUFDQyxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0YsQ0FBQztJQUVPLFNBQVMsQ0FBQyxFQUNoQixXQUFXLEVBQ1gsVUFBVSxFQUNWLE1BQU0sR0FLUDtRQUNDLE9BQU8sQ0FDTCxXQUFXLENBQUMsaUJBQWlCO1lBQzdCLFdBQVcsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO1lBQ2xELFdBQVcsQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUM5RCxDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjO1FBQzFCLElBQ0UsSUFBSSxDQUFDLGtCQUFrQjtZQUN2QixJQUFJLENBQUMsNkJBQTZCO1lBQ2xDLElBQUksQ0FBQyw2QkFBNkIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQy9DO1lBQ0EsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7U0FDaEM7UUFFRCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7UUFDN0QsSUFBSSxDQUFDLDZCQUE2QjtZQUNoQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQ0FBaUMsR0FBRyxJQUFJLENBQUM7UUFFckUsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztJQUVPLEtBQUssQ0FBQywyQkFBMkI7UUFDdkMsTUFBTSxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDaEQseUJBQWEsQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQ3JELHlCQUFhLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7U0FDckMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxJQUFBLDJDQUE4QixFQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvRCxDQUFDO0NBQ0Y7QUFwR0QsMENBb0dDIn0=
@@ -0,0 +1,4 @@
1
+ import { CollectionActionEvent, CustomActionEvent } from './types';
2
+ export declare function generateCustomActionIdentifier(actionEventName: CustomActionEvent, customActionName: string, collectionName: string): string;
3
+ export declare function generateCollectionActionIdentifier(action: CollectionActionEvent, collectionName: string): string;
4
+ //# sourceMappingURL=generate-action-identifier.d.ts.map
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateCollectionActionIdentifier = exports.generateCustomActionIdentifier = void 0;
4
+ function generateCustomActionIdentifier(actionEventName, customActionName, collectionName) {
5
+ return `custom:${collectionName}:${customActionName}:${actionEventName}`;
6
+ }
7
+ exports.generateCustomActionIdentifier = generateCustomActionIdentifier;
8
+ function generateCollectionActionIdentifier(action, collectionName) {
9
+ return `collection:${collectionName}:${action}`;
10
+ }
11
+ exports.generateCollectionActionIdentifier = generateCollectionActionIdentifier;
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtYWN0aW9uLWlkZW50aWZpZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvYXV0aG9yaXphdGlvbi9pbnRlcm5hbC9nZW5lcmF0ZS1hY3Rpb24taWRlbnRpZmllci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxTQUFnQiw4QkFBOEIsQ0FDNUMsZUFBa0MsRUFDbEMsZ0JBQXdCLEVBQ3hCLGNBQXNCO0lBRXRCLE9BQU8sVUFBVSxjQUFjLElBQUksZ0JBQWdCLElBQUksZUFBZSxFQUFFLENBQUM7QUFDM0UsQ0FBQztBQU5ELHdFQU1DO0FBRUQsU0FBZ0Isa0NBQWtDLENBQ2hELE1BQTZCLEVBQzdCLGNBQXNCO0lBRXRCLE9BQU8sY0FBYyxjQUFjLElBQUksTUFBTSxFQUFFLENBQUM7QUFDbEQsQ0FBQztBQUxELGdGQUtDIn0=
@@ -0,0 +1,8 @@
1
+ import { EnvironmentPermissionsV4, UserPermissionV4 } from './types';
2
+ export declare type ActionPermissions = {
3
+ everythingAllowed: boolean;
4
+ actionsGloballyAllowed: Set<string>;
5
+ actionsAllowedByUser: Map<string, Set<string>>;
6
+ };
7
+ export default function generateActionsFromPermissions(environmentPermissions: EnvironmentPermissionsV4, users: UserPermissionV4[]): ActionPermissions;
8
+ //# sourceMappingURL=generate-actions-from-permissions.d.ts.map
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const types_1 = require("./types");
4
+ const generate_action_identifier_1 = require("./generate-action-identifier");
5
+ function generateCollectionPermissions(permissions) {
6
+ return Object.entries(permissions).reduce((acc, [collectionId, collectionPermissions]) => {
7
+ const { collection } = collectionPermissions;
8
+ return {
9
+ ...acc,
10
+ [(0, generate_action_identifier_1.generateCollectionActionIdentifier)(types_1.CollectionActionEvent.Browse, collectionId)]: collection.browseEnabled,
11
+ [(0, generate_action_identifier_1.generateCollectionActionIdentifier)(types_1.CollectionActionEvent.Read, collectionId)]: collection.readEnabled,
12
+ [(0, generate_action_identifier_1.generateCollectionActionIdentifier)(types_1.CollectionActionEvent.Edit, collectionId)]: collection.editEnabled,
13
+ [(0, generate_action_identifier_1.generateCollectionActionIdentifier)(types_1.CollectionActionEvent.Add, collectionId)]: collection.addEnabled,
14
+ [(0, generate_action_identifier_1.generateCollectionActionIdentifier)(types_1.CollectionActionEvent.Delete, collectionId)]: collection.deleteEnabled,
15
+ [(0, generate_action_identifier_1.generateCollectionActionIdentifier)(types_1.CollectionActionEvent.Export, collectionId)]: collection.exportEnabled,
16
+ };
17
+ }, {});
18
+ }
19
+ function generateCollectionActionPermission(collectionId, actions) {
20
+ return Object.entries(actions).reduce((acc, [actionName, actionPermissions]) => {
21
+ return {
22
+ ...acc,
23
+ ...{
24
+ [(0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.Approve, actionName, collectionId)]: actionPermissions.userApprovalEnabled,
25
+ [(0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.SelfApprove, actionName, collectionId)]: actionPermissions.selfApprovalEnabled,
26
+ [(0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.Trigger, actionName, collectionId)]: actionPermissions.triggerEnabled,
27
+ [(0, generate_action_identifier_1.generateCustomActionIdentifier)(types_1.CustomActionEvent.RequireApproval, actionName, collectionId)]: actionPermissions.approvalRequired,
28
+ },
29
+ };
30
+ }, {});
31
+ }
32
+ function generateActionPermissions(permissions) {
33
+ return Object.entries(permissions).reduce((acc, [collectionId, collectionPermissions]) => {
34
+ const { actions } = collectionPermissions;
35
+ return {
36
+ ...acc,
37
+ ...generateCollectionActionPermission(collectionId, actions),
38
+ };
39
+ }, {});
40
+ }
41
+ function generateActionsGloballyAllowed(permissions) {
42
+ return new Set(Object.entries(permissions)
43
+ .filter(([, permission]) => permission === true)
44
+ .map(([action]) => action));
45
+ }
46
+ function getUsersForRoles(roles, userIdsByRole) {
47
+ return new Set(roles.reduce((acc, roleId) => {
48
+ const userIds = (userIdsByRole.get(roleId) || []).map(userId => `${userId}`);
49
+ if (userIds) {
50
+ return [...acc, ...userIds];
51
+ }
52
+ return acc;
53
+ }, []));
54
+ }
55
+ function generateActionsAllowedByUser(permissions, users) {
56
+ const userIdsByRole = users.reduce((acc, user) => {
57
+ acc.set(user.roleId, [...(acc.get(user.roleId) || []), user.id]);
58
+ return acc;
59
+ }, new Map());
60
+ return new Map(Object.entries(permissions)
61
+ .filter(([, permission]) => typeof permission !== 'boolean')
62
+ .map(([name, permission]) => [
63
+ name,
64
+ getUsersForRoles(permission.roles, userIdsByRole),
65
+ ]));
66
+ }
67
+ function generateActionsFromPermissions(environmentPermissions, users) {
68
+ if (environmentPermissions === true) {
69
+ return {
70
+ everythingAllowed: true,
71
+ actionsGloballyAllowed: new Set(),
72
+ actionsAllowedByUser: new Map(),
73
+ };
74
+ }
75
+ const remotePermissions = environmentPermissions;
76
+ const allPermissions = {
77
+ ...generateCollectionPermissions(remotePermissions.collections),
78
+ ...generateActionPermissions(remotePermissions.collections),
79
+ };
80
+ return {
81
+ everythingAllowed: false,
82
+ actionsGloballyAllowed: generateActionsGloballyAllowed(allPermissions),
83
+ actionsAllowedByUser: generateActionsAllowedByUser(allPermissions, users),
84
+ };
85
+ }
86
+ exports.default = generateActionsFromPermissions;
87
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtYWN0aW9ucy1mcm9tLXBlcm1pc3Npb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NlcnZpY2VzL2F1dGhvcml6YXRpb24vaW50ZXJuYWwvZ2VuZXJhdGUtYWN0aW9ucy1mcm9tLXBlcm1pc3Npb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBVWlCO0FBQ2pCLDZFQUdzQztBQVl0QyxTQUFTLDZCQUE2QixDQUNwQyxXQUFnRDtJQUVoRCxPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsWUFBWSxFQUFFLHFCQUFxQixDQUFDLEVBQUUsRUFBRTtRQUN2RixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcscUJBQXFCLENBQUM7UUFFN0MsT0FBTztZQUNMLEdBQUcsR0FBRztZQUNOLENBQUMsSUFBQSwrREFBa0MsRUFBQyw2QkFBcUIsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUMsRUFDOUUsVUFBVSxDQUFDLGFBQWE7WUFDMUIsQ0FBQyxJQUFBLCtEQUFrQyxFQUFDLDZCQUFxQixDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQyxFQUM1RSxVQUFVLENBQUMsV0FBVztZQUN4QixDQUFDLElBQUEsK0RBQWtDLEVBQUMsNkJBQXFCLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDLEVBQzVFLFVBQVUsQ0FBQyxXQUFXO1lBQ3hCLENBQUMsSUFBQSwrREFBa0MsRUFBQyw2QkFBcUIsQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUMsRUFDM0UsVUFBVSxDQUFDLFVBQVU7WUFDdkIsQ0FBQyxJQUFBLCtEQUFrQyxFQUFDLDZCQUFxQixDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQyxFQUM5RSxVQUFVLENBQUMsYUFBYTtZQUMxQixDQUFDLElBQUEsK0RBQWtDLEVBQUMsNkJBQXFCLENBQUMs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
@@ -0,0 +1,61 @@
1
+ export declare type EnvironmentPermissionsV4 = EnvironmentPermissionsV4Remote | true;
2
+ export declare type RightDescriptionWithRolesV4 = {
3
+ roles: number[];
4
+ };
5
+ export declare type RightDescriptionV4 = boolean | RightDescriptionWithRolesV4;
6
+ export interface EnvironmentCollectionAccessPermissionsV4 {
7
+ browseEnabled: RightDescriptionV4;
8
+ readEnabled: RightDescriptionV4;
9
+ editEnabled: RightDescriptionV4;
10
+ addEnabled: RightDescriptionV4;
11
+ deleteEnabled: RightDescriptionV4;
12
+ exportEnabled: RightDescriptionV4;
13
+ }
14
+ export interface EnvironmentSmartActionPermissionsV4 {
15
+ triggerEnabled: RightDescriptionV4;
16
+ approvalRequired: RightDescriptionV4;
17
+ userApprovalEnabled: RightDescriptionV4;
18
+ selfApprovalEnabled: RightDescriptionV4;
19
+ }
20
+ export interface EnvironmentCollectionActionPermissionsV4 {
21
+ [actionName: string]: EnvironmentSmartActionPermissionsV4;
22
+ }
23
+ export interface EnvironmentCollectionPermissionsV4 {
24
+ collection: EnvironmentCollectionAccessPermissionsV4;
25
+ actions: EnvironmentCollectionActionPermissionsV4;
26
+ }
27
+ export interface EnvironmentCollectionsPermissionsV4 {
28
+ [id: string]: EnvironmentCollectionPermissionsV4;
29
+ }
30
+ export interface EnvironmentPermissionsV4Remote {
31
+ collections: EnvironmentCollectionsPermissionsV4;
32
+ }
33
+ export declare enum PermissionLevel {
34
+ Admin = "admin",
35
+ User = "user",
36
+ Developer = "developer"
37
+ }
38
+ export declare type UserPermissionV4 = {
39
+ id: number;
40
+ firstName: string;
41
+ lastName: string;
42
+ email: string;
43
+ roleId: number;
44
+ permissionLevel: PermissionLevel;
45
+ tags: Record<string, string>;
46
+ };
47
+ export declare enum CollectionActionEvent {
48
+ Browse = "browse",
49
+ Export = "export",
50
+ Read = "read",
51
+ Edit = "edit",
52
+ Delete = "delete",
53
+ Add = "add"
54
+ }
55
+ export declare enum CustomActionEvent {
56
+ Trigger = "trigger",
57
+ Approve = "approve",
58
+ SelfApprove = "self-approve",
59
+ RequireApproval = "require-approval"
60
+ }
61
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CustomActionEvent = exports.CollectionActionEvent = exports.PermissionLevel = void 0;
4
+ var PermissionLevel;
5
+ (function (PermissionLevel) {
6
+ PermissionLevel["Admin"] = "admin";
7
+ PermissionLevel["User"] = "user";
8
+ PermissionLevel["Developer"] = "developer";
9
+ })(PermissionLevel = exports.PermissionLevel || (exports.PermissionLevel = {}));
10
+ var CollectionActionEvent;
11
+ (function (CollectionActionEvent) {
12
+ CollectionActionEvent["Browse"] = "browse";
13
+ CollectionActionEvent["Export"] = "export";
14
+ CollectionActionEvent["Read"] = "read";
15
+ CollectionActionEvent["Edit"] = "edit";
16
+ CollectionActionEvent["Delete"] = "delete";
17
+ CollectionActionEvent["Add"] = "add";
18
+ })(CollectionActionEvent = exports.CollectionActionEvent || (exports.CollectionActionEvent = {}));
19
+ var CustomActionEvent;
20
+ (function (CustomActionEvent) {
21
+ CustomActionEvent["Trigger"] = "trigger";
22
+ CustomActionEvent["Approve"] = "approve";
23
+ CustomActionEvent["SelfApprove"] = "self-approve";
24
+ CustomActionEvent["RequireApproval"] = "require-approval";
25
+ })(CustomActionEvent = exports.CustomActionEvent || (exports.CustomActionEvent = {}));
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvYXV0aG9yaXphdGlvbi9pbnRlcm5hbC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFzQ0EsSUFBWSxlQUlYO0FBSkQsV0FBWSxlQUFlO0lBQ3pCLGtDQUFlLENBQUE7SUFDZixnQ0FBYSxDQUFBO0lBQ2IsMENBQXVCLENBQUE7QUFDekIsQ0FBQyxFQUpXLGVBQWUsR0FBZix1QkFBZSxLQUFmLHVCQUFlLFFBSTFCO0FBWUQsSUFBWSxxQkFPWDtBQVBELFdBQVkscUJBQXFCO0lBQy9CLDBDQUFpQixDQUFBO0lBQ2pCLDBDQUFpQixDQUFBO0lBQ2pCLHNDQUFhLENBQUE7SUFDYixzQ0FBYSxDQUFBO0lBQ2IsMENBQWlCLENBQUE7SUFDakIsb0NBQVcsQ0FBQTtBQUNiLENBQUMsRUFQVyxxQkFBcUIsR0FBckIsNkJBQXFCLEtBQXJCLDZCQUFxQixRQU9oQztBQUVELElBQVksaUJBS1g7QUFMRCxXQUFZLGlCQUFpQjtJQUMzQix3Q0FBbUIsQ0FBQTtJQUNuQix3Q0FBbUIsQ0FBQTtJQUNuQixpREFBNEIsQ0FBQTtJQUM1Qix5REFBb0MsQ0FBQTtBQUN0QyxDQUFDLEVBTFcsaUJBQWlCLEdBQWpCLHlCQUFpQixLQUFqQix5QkFBaUIsUUFLNUIifQ==
@@ -0,0 +1,12 @@
1
+ import { AgentOptionsWithDefaults } from '../types';
2
+ import AuthorizationService from './authorization/authorization';
3
+ import PermissionService from './permissions';
4
+ import Serializer from './serializer';
5
+ export declare type ForestAdminHttpDriverServices = {
6
+ permissions: PermissionService;
7
+ serializer: Serializer;
8
+ authorization: AuthorizationService;
9
+ };
10
+ declare const _default: (options: AgentOptionsWithDefaults) => ForestAdminHttpDriverServices;
11
+ export default _default;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const permissions_1 = __importDefault(require("./permissions"));
7
+ const serializer_1 = __importDefault(require("./serializer"));
8
+ const authorization_1 = __importDefault(require("./authorization"));
9
+ exports.default = (options) => {
10
+ return {
11
+ permissions: new permissions_1.default(options),
12
+ authorization: (0, authorization_1.default)(options),
13
+ serializer: new serializer_1.default(),
14
+ };
15
+ };
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSxnRUFBOEM7QUFDOUMsOERBQXNDO0FBQ3RDLG9FQUEwRDtBQVExRCxrQkFBZSxDQUFDLE9BQWlDLEVBQWlDLEVBQUU7SUFDbEYsT0FBTztRQUNMLFdBQVcsRUFBRSxJQUFJLHFCQUFpQixDQUFDLE9BQU8sQ0FBQztRQUMzQyxhQUFhLEVBQUUsSUFBQSx1QkFBMkIsRUFBQyxPQUFPLENBQUM7UUFDbkQsVUFBVSxFQUFFLElBQUksb0JBQVUsRUFBRTtLQUM3QixDQUFDO0FBQ0osQ0FBQyxDQUFDIn0=
@@ -0,0 +1,19 @@
1
+ import { Collection, ConditionTree } from '@forestadmin/datasource-toolkit';
2
+ import { Context } from 'koa';
3
+ import { AgentOptionsWithDefaults } from '../types';
4
+ declare type RolesOptions = Pick<AgentOptionsWithDefaults, 'forestServerUrl' | 'envSecret' | 'isProduction' | 'permissionsCacheDurationInSeconds'>;
5
+ export default class PermissionService {
6
+ private options;
7
+ private cache;
8
+ constructor(options: RolesOptions);
9
+ invalidateCache(renderingId: number): void;
10
+ /** Checks that a charting query is in the list of allowed queries */
11
+ canChart(context: Context): Promise<void>;
12
+ /** Check if a user is allowed to perform a specific action */
13
+ can(context: Context, action: string, allowRefetch?: boolean): Promise<void>;
14
+ getScope(collection: Collection, context: Context): Promise<ConditionTree>;
15
+ /** Get cached version of "rendering permissions" */
16
+ private getRenderingPermissions;
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const lru_cache_1 = __importDefault(require("lru-cache"));
7
+ const object_hash_1 = __importDefault(require("object-hash"));
8
+ const types_1 = require("../types");
9
+ const condition_tree_parser_1 = __importDefault(require("../utils/condition-tree-parser"));
10
+ const forest_http_api_1 = __importDefault(require("../utils/forest-http-api"));
11
+ class PermissionService {
12
+ constructor(options) {
13
+ this.options = options;
14
+ this.cache = new lru_cache_1.default({
15
+ max: 256,
16
+ ttl: this.options.permissionsCacheDurationInSeconds * 1000,
17
+ });
18
+ }
19
+ invalidateCache(renderingId) {
20
+ this.cache.delete(renderingId);
21
+ }
22
+ /** Checks that a charting query is in the list of allowed queries */
23
+ async canChart(context) {
24
+ // If the permissions level already allow the chart, no need to check further
25
+ if (['admin', 'editor', 'developer'].includes(context.state.user.permissionLevel)) {
26
+ return;
27
+ }
28
+ const chart = { ...context.request.body };
29
+ // When the server sends the data of the allowed charts, the target column is not specified
30
+ // for relations => allow them all.
31
+ if (chart?.group_by_field?.includes(':'))
32
+ chart.group_by_field = chart.group_by_field.substring(0, chart.group_by_field.indexOf(':'));
33
+ const chartHash = (0, object_hash_1.default)(chart, {
34
+ respectType: false,
35
+ excludeKeys: key => chart[key] === null,
36
+ });
37
+ await this.can(context, `chart:${chartHash}`);
38
+ }
39
+ /** Check if a user is allowed to perform a specific action */
40
+ async can(context, action, allowRefetch = true) {
41
+ const { id: userId, renderingId } = context.state.user;
42
+ const perms = await this.getRenderingPermissions(renderingId);
43
+ const isAllowed = perms.actions.has(action) || perms.actionsByUser[action]?.has(userId);
44
+ if (!isAllowed && allowRefetch) {
45
+ this.invalidateCache(renderingId);
46
+ return this.can(context, action, false);
47
+ }
48
+ if (!isAllowed) {
49
+ context.throw(types_1.HttpCode.Forbidden, 'Forbidden');
50
+ }
51
+ }
52
+ async getScope(collection, context) {
53
+ const { user } = context.state;
54
+ const perms = await this.getRenderingPermissions(user.renderingId);
55
+ const scopes = perms.scopes[collection.name];
56
+ if (!scopes)
57
+ return null;
58
+ const conditionTree = condition_tree_parser_1.default.fromPlainObject(collection, scopes.conditionTree);
59
+ return conditionTree.replaceLeafs(leaf => {
60
+ const dynamicValues = scopes.dynamicScopeValues?.[user.id];
61
+ if (typeof leaf.value === 'string' && leaf.value.startsWith('$currentUser')) {
62
+ // Search replacement hash from forestadmin server
63
+ if (dynamicValues) {
64
+ return leaf.override({ value: dynamicValues[leaf.value] });
65
+ }
66
+ // Search JWT token (new user)
67
+ return leaf.override({
68
+ value: leaf.value.startsWith('$currentUser.tags.')
69
+ ? user.tags[leaf.value.substring(18)]
70
+ : user[leaf.value.substring(13)],
71
+ });
72
+ }
73
+ return leaf;
74
+ });
75
+ }
76
+ /** Get cached version of "rendering permissions" */
77
+ getRenderingPermissions(renderingId) {
78
+ if (!this.cache.has(renderingId))
79
+ this.cache.set(renderingId, forest_http_api_1.default.getPermissions(this.options, renderingId));
80
+ // We already checked the entry is up-to-date with the .has() call => allowStale
81
+ return this.cache.get(renderingId, { allowStale: true });
82
+ }
83
+ }
84
+ exports.default = PermissionService;
85
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvcGVybWlzc2lvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSwwREFBaUM7QUFDakMsOERBQXFDO0FBRXJDLG9DQUE4RDtBQUM5RCwyRkFBaUU7QUFDakUsK0VBQStFO0FBTy9FLE1BQXFCLGlCQUFpQjtJQUlwQyxZQUFZLE9BQXFCO1FBQy9CLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxtQkFBUSxDQUFDO1lBQ3hCLEdBQUcsRUFBRSxHQUFHO1lBQ1IsR0FBRyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsaUNBQWlDLEdBQUcsSUFBSTtTQUMzRCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsZUFBZSxDQUFDLFdBQW1CO1FBQ2pDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCxxRUFBcUU7SUFDckUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFnQjtRQUM3Qiw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFO1lBQ2pGLE9BQU87U0FDUjtRQUVELE1BQU0sS0FBSyxHQUFHLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTFDLDJGQUEyRjtRQUMzRixtQ0FBbUM7UUFDbkMsSUFBSSxLQUFLLEVBQUUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUM7WUFDdEMsS0FBSyxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFP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
@@ -0,0 +1,12 @@
1
+ import { Collection, RecordData } from '@forestadmin/datasource-toolkit';
2
+ export default class Serializer {
3
+ private readonly serializers;
4
+ serialize(collection: Collection, data: RecordData | RecordData[]): unknown;
5
+ deserialize(collection: Collection, body: unknown): RecordData;
6
+ serializeWithSearchMetadata(collection: Collection, data: RecordData[], searchValue: string): unknown;
7
+ private getSerializer;
8
+ private registerCollection;
9
+ private buildRelationshipsConfiguration;
10
+ private stripUndefinedsInPlace;
11
+ }
12
+ //# sourceMappingURL=serializer.d.ts.map