@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.
- package/LICENSE +674 -0
- package/README.md +0 -0
- package/dist/agent.d.ts +76 -0
- package/dist/agent.js +133 -0
- package/dist/framework-mounter.d.ts +43 -0
- package/dist/framework-mounter.js +157 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +15 -0
- package/dist/routes/access/api-chart.d.ts +16 -0
- package/dist/routes/access/api-chart.js +47 -0
- package/dist/routes/access/chart.d.ts +18 -0
- package/dist/routes/access/chart.js +162 -0
- package/dist/routes/access/count-related.d.ts +9 -0
- package/dist/routes/access/count-related.js +31 -0
- package/dist/routes/access/count.d.ts +9 -0
- package/dist/routes/access/count.js +31 -0
- package/dist/routes/access/csv-related.d.ts +9 -0
- package/dist/routes/access/csv-related.js +33 -0
- package/dist/routes/access/csv.d.ts +9 -0
- package/dist/routes/access/csv.js +31 -0
- package/dist/routes/access/get.d.ts +9 -0
- package/dist/routes/access/get.js +29 -0
- package/dist/routes/access/list-related.d.ts +9 -0
- package/dist/routes/access/list-related.js +25 -0
- package/dist/routes/access/list.d.ts +9 -0
- package/dist/routes/access/list.js +22 -0
- package/dist/routes/base-route.d.ts +13 -0
- package/dist/routes/base-route.js +13 -0
- package/dist/routes/collection-route.d.ts +12 -0
- package/dist/routes/collection-route.js +20 -0
- package/dist/routes/index.d.ts +30 -0
- package/dist/routes/index.js +108 -0
- package/dist/routes/modification/action.d.ts +16 -0
- package/dist/routes/modification/action.js +104 -0
- package/dist/routes/modification/associate-related.d.ts +12 -0
- package/dist/routes/modification/associate-related.js +51 -0
- package/dist/routes/modification/create.d.ts +14 -0
- package/dist/routes/modification/create.js +83 -0
- package/dist/routes/modification/delete.d.ts +11 -0
- package/dist/routes/modification/delete.js +41 -0
- package/dist/routes/modification/dissociate-delete-related.d.ts +20 -0
- package/dist/routes/modification/dissociate-delete-related.js +89 -0
- package/dist/routes/modification/update-field.d.ts +9 -0
- package/dist/routes/modification/update-field.js +39 -0
- package/dist/routes/modification/update-relation.d.ts +11 -0
- package/dist/routes/modification/update-relation.js +59 -0
- package/dist/routes/modification/update.d.ts +9 -0
- package/dist/routes/modification/update.js +31 -0
- package/dist/routes/relation-route.d.ts +10 -0
- package/dist/routes/relation-route.js +18 -0
- package/dist/routes/security/authentication.d.ts +15 -0
- package/dist/routes/security/authentication.js +74 -0
- package/dist/routes/security/ip-whitelist.d.ts +14 -0
- package/dist/routes/security/ip-whitelist.js +35 -0
- package/dist/routes/security/scope-invalidation.d.ts +11 -0
- package/dist/routes/security/scope-invalidation.js +28 -0
- package/dist/routes/system/error-handling.d.ts +13 -0
- package/dist/routes/system/error-handling.js +75 -0
- package/dist/routes/system/healthcheck.d.ts +11 -0
- package/dist/routes/system/healthcheck.js +22 -0
- package/dist/routes/system/logger.d.ts +10 -0
- package/dist/routes/system/logger.js +35 -0
- package/dist/services/authorization/authorization.d.ts +15 -0
- package/dist/services/authorization/authorization.js +45 -0
- package/dist/services/authorization/index.d.ts +5 -0
- package/dist/services/authorization/index.js +16 -0
- package/dist/services/authorization/internal/action-permission.d.ts +16 -0
- package/dist/services/authorization/internal/action-permission.js +68 -0
- package/dist/services/authorization/internal/generate-action-identifier.d.ts +4 -0
- package/dist/services/authorization/internal/generate-action-identifier.js +12 -0
- package/dist/services/authorization/internal/generate-actions-from-permissions.d.ts +8 -0
- package/dist/services/authorization/internal/generate-actions-from-permissions.js +87 -0
- package/dist/services/authorization/internal/types.d.ts +61 -0
- package/dist/services/authorization/internal/types.js +26 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/index.js +16 -0
- package/dist/services/permissions.d.ts +19 -0
- package/dist/services/permissions.js +85 -0
- package/dist/services/serializer.d.ts +12 -0
- package/dist/services/serializer.js +120 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.js +23 -0
- package/dist/utils/body-parser.d.ts +7 -0
- package/dist/utils/body-parser.js +18 -0
- package/dist/utils/condition-tree-parser.d.ts +11 -0
- package/dist/utils/condition-tree-parser.js +53 -0
- package/dist/utils/context-filter-factory.d.ts +7 -0
- package/dist/utils/context-filter-factory.js +28 -0
- package/dist/utils/csv-generator.d.ts +12 -0
- package/dist/utils/csv-generator.js +39 -0
- package/dist/utils/csv-route-context.d.ts +5 -0
- package/dist/utils/csv-route-context.js +14 -0
- package/dist/utils/forest-http-api.d.ts +68 -0
- package/dist/utils/forest-http-api.js +202 -0
- package/dist/utils/forest-schema/action-values.d.ts +34 -0
- package/dist/utils/forest-schema/action-values.js +144 -0
- package/dist/utils/forest-schema/emitter.d.ts +20 -0
- package/dist/utils/forest-schema/emitter.js +70 -0
- package/dist/utils/forest-schema/filterable.d.ts +16 -0
- package/dist/utils/forest-schema/filterable.js +68 -0
- package/dist/utils/forest-schema/generator-actions.d.ts +14 -0
- package/dist/utils/forest-schema/generator-actions.js +99 -0
- package/dist/utils/forest-schema/generator-collection.d.ts +7 -0
- package/dist/utils/forest-schema/generator-collection.js +36 -0
- package/dist/utils/forest-schema/generator-fields.d.ts +14 -0
- package/dist/utils/forest-schema/generator-fields.js +160 -0
- package/dist/utils/forest-schema/generator-segments.d.ts +6 -0
- package/dist/utils/forest-schema/generator-segments.js +9 -0
- package/dist/utils/forest-schema/types.d.ts +85 -0
- package/dist/utils/forest-schema/types.js +16 -0
- package/dist/utils/forest-schema/validation.d.ts +10 -0
- package/dist/utils/forest-schema/validation.js +28 -0
- package/dist/utils/id.d.ts +8 -0
- package/dist/utils/id.js +43 -0
- package/dist/utils/options-validator.d.ts +12 -0
- package/dist/utils/options-validator.js +92 -0
- package/dist/utils/query-string.d.ts +14 -0
- package/dist/utils/query-string.js +134 -0
- package/package.json +66 -0
|
@@ -0,0 +1,39 @@
|
|
|
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 datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const collection_route_1 = __importDefault(require("../collection-route"));
|
|
9
|
+
const id_1 = __importDefault(require("../../utils/id"));
|
|
10
|
+
const query_string_1 = __importDefault(require("../../utils/query-string"));
|
|
11
|
+
class UpdateField extends collection_route_1.default {
|
|
12
|
+
setupRoutes(router) {
|
|
13
|
+
router.put(`/${this.collection.name}/:id/relationships/:field/:index(\\d+)`, this.handleUpdate.bind(this));
|
|
14
|
+
}
|
|
15
|
+
async handleUpdate(context) {
|
|
16
|
+
await this.services.authorization.assertCanEdit(context, this.collection.name);
|
|
17
|
+
const { field, index, id } = context.params;
|
|
18
|
+
const subRecord = context.request.body?.data?.attributes;
|
|
19
|
+
// Validate parameters
|
|
20
|
+
// @fixme At the time of writing this route, the Validator does not support composite types
|
|
21
|
+
datasource_toolkit_1.FieldValidator.validate(this.collection, field, [{ [field]: [subRecord] }]);
|
|
22
|
+
// Create caller & filter
|
|
23
|
+
const unpackedId = id_1.default.unpackId(this.collection.schema, id);
|
|
24
|
+
const conditionTree = datasource_toolkit_1.ConditionTreeFactory.intersect(datasource_toolkit_1.ConditionTreeFactory.matchIds(this.collection.schema, [unpackedId]), await this.services.permissions.getScope(this.collection, context));
|
|
25
|
+
const caller = query_string_1.default.parseCaller(context);
|
|
26
|
+
const filter = new datasource_toolkit_1.Filter({ conditionTree });
|
|
27
|
+
// Load & check record
|
|
28
|
+
const [record] = await this.collection.list(caller, filter, new datasource_toolkit_1.Projection(field));
|
|
29
|
+
if (index > record[field]?.length) {
|
|
30
|
+
throw new datasource_toolkit_1.ValidationError(`Field '${field}' is too short`);
|
|
31
|
+
}
|
|
32
|
+
record[field][index] = subRecord;
|
|
33
|
+
// Update record
|
|
34
|
+
await this.collection.update(caller, filter, { [field]: record[field] });
|
|
35
|
+
context.response.status = types_1.HttpCode.NoContent;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.default = UpdateField;
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLWZpZWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlcy9tb2RpZmljYXRpb24vdXBkYXRlLWZpZWxkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBTXlDO0FBSXpDLHVDQUF1QztBQUN2QywyRUFBa0Q7QUFDbEQsd0RBQXFDO0FBQ3JDLDRFQUF5RDtBQUV6RCxNQUFxQixXQUFZLFNBQVEsMEJBQWU7SUFDdEQsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FDUixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSx3Q0FBd0MsRUFDaEUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQzdCLENBQUM7SUFDSixDQUFDO0lBRU0sS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFnQjtRQUN4QyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUvRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQzVDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxVQUFVLENBQUM7UUFFekQsc0JBQXNCO1FBQ3RCLDJGQUEyRjtRQUMzRixtQ0FBYyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTVFLHlCQUF5QjtRQUN6QixNQUFNLFVBQVUsR0FBRyxZQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sYUFBYSxHQUFHLHlDQUFvQixDQUFDLFNBQVMsQ0FDbEQseUNBQW9CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsRUFDbkUsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FDbkUsQ0FBQztRQUVGLE1BQU0sTUFBTSxHQUFHLHNCQUFpQixDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0RCxNQUFNLE1BQU0sR0FBRyxJQUFJLDJCQUFNLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBRTdDLHNCQUFzQjtRQUN0QixNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksK0JBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBRW5GLElBQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUU7WUFDakMsTUFBTSxJQUFJLG9DQUFlLENBQUMsVUFBVSxLQUFLLGdCQUFnQixDQUFDLENBQUM7U0FDNUQ7UUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsU0FBUyxDQUFDO1FBRWpDLGdCQUFnQjtRQUNoQixNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFekUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsZ0JBQVEsQ0FBQyxTQUFTLENBQUM7SUFDL0MsQ0FBQztDQUNGO0FBMUNELDhCQTBDQyJ9
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
import Router from '@koa/router';
|
|
4
|
+
import RelationRoute from '../relation-route';
|
|
5
|
+
export default class UpdateRelation extends RelationRoute {
|
|
6
|
+
setupRoutes(router: Router): void;
|
|
7
|
+
handleUpdateRelationRoute(context: Context): Promise<void>;
|
|
8
|
+
private updateManyToOne;
|
|
9
|
+
private updateOneToOne;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=update-relation.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
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 datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const id_1 = __importDefault(require("../../utils/id"));
|
|
9
|
+
const query_string_1 = __importDefault(require("../../utils/query-string"));
|
|
10
|
+
const relation_route_1 = __importDefault(require("../relation-route"));
|
|
11
|
+
class UpdateRelation extends relation_route_1.default {
|
|
12
|
+
setupRoutes(router) {
|
|
13
|
+
router.put(`/${this.collection.name}/:parentId/relationships/${this.relationName}`, this.handleUpdateRelationRoute.bind(this));
|
|
14
|
+
}
|
|
15
|
+
async handleUpdateRelationRoute(context) {
|
|
16
|
+
const relation = this.collection.schema.fields[this.relationName];
|
|
17
|
+
const caller = query_string_1.default.parseCaller(context);
|
|
18
|
+
const parentId = id_1.default.unpackId(this.collection.schema, context.params.parentId);
|
|
19
|
+
const linkedId = context.request.body?.data?.id
|
|
20
|
+
? id_1.default.unpackId(this.foreignCollection.schema, context.request.body.data.id)
|
|
21
|
+
: null;
|
|
22
|
+
if (relation.type === 'ManyToOne') {
|
|
23
|
+
await this.updateManyToOne(context, relation, parentId, linkedId, caller);
|
|
24
|
+
}
|
|
25
|
+
else if (relation.type === 'OneToOne') {
|
|
26
|
+
await this.updateOneToOne(context, relation, parentId, linkedId, caller);
|
|
27
|
+
}
|
|
28
|
+
context.response.status = types_1.HttpCode.NoContent;
|
|
29
|
+
}
|
|
30
|
+
async updateManyToOne(context, relation, parentId, linkedId, caller) {
|
|
31
|
+
// Perms
|
|
32
|
+
const scope = await this.services.permissions.getScope(this.collection, context);
|
|
33
|
+
await this.services.authorization.assertCanEdit(context, this.collection.name);
|
|
34
|
+
// Load the value that will be used as foreignKey (=== linkedId[0] most of the time)
|
|
35
|
+
const foreignValue = linkedId
|
|
36
|
+
? await datasource_toolkit_1.CollectionUtils.getValue(this.foreignCollection, caller, linkedId, relation.foreignKeyTarget)
|
|
37
|
+
: null;
|
|
38
|
+
// Overwrite old foreign key with new one (only one query needed).
|
|
39
|
+
const fkOwner = datasource_toolkit_1.ConditionTreeFactory.matchIds(this.collection.schema, [parentId]);
|
|
40
|
+
await this.collection.update(caller, new datasource_toolkit_1.Filter({ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(fkOwner, scope) }), { [relation.foreignKey]: foreignValue });
|
|
41
|
+
}
|
|
42
|
+
async updateOneToOne(context, relation, parentId, linkedId, caller) {
|
|
43
|
+
// Permissions
|
|
44
|
+
const scope = await this.services.permissions.getScope(this.foreignCollection, context);
|
|
45
|
+
await this.services.authorization.assertCanEdit(context, this.foreignCollection.name);
|
|
46
|
+
// Load the value that will be used as originKey (=== parentId[0] most of the time)
|
|
47
|
+
const originValue = await datasource_toolkit_1.CollectionUtils.getValue(this.collection, caller, parentId, relation.originKeyTarget);
|
|
48
|
+
// Break old relation (may update zero or one records).
|
|
49
|
+
const oldFkOwner = new datasource_toolkit_1.ConditionTreeLeaf(relation.originKey, 'Equal', originValue);
|
|
50
|
+
await this.foreignCollection.update(caller, new datasource_toolkit_1.Filter({ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(oldFkOwner, scope) }), { [relation.originKey]: null });
|
|
51
|
+
// Create new relation (will update exactly one record).
|
|
52
|
+
if (linkedId) {
|
|
53
|
+
const newFkOwner = datasource_toolkit_1.ConditionTreeFactory.matchIds(this.foreignCollection.schema, [linkedId]);
|
|
54
|
+
await this.foreignCollection.update(caller, new datasource_toolkit_1.Filter({ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(newFkOwner, scope) }), { [relation.originKey]: originValue });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.default = UpdateRelation;
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLXJlbGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlcy9tb2RpZmljYXRpb24vdXBkYXRlLXJlbGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBU3lDO0FBSXpDLHVDQUF1QztBQUN2Qyx3REFBcUM7QUFDckMsNEVBQXlEO0FBQ3pELHVFQUE4QztBQUU5QyxNQUFxQixjQUFlLFNBQVEsd0JBQWE7SUFDdkQsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FDUixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSw0QkFBNEIsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUN2RSxJQUFJLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUMxQyxDQUFDO0lBQ0osQ0FBQztJQUVNLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxPQUFnQjtRQUNyRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sTUFBTSxHQUFHLHNCQUFpQixDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0RCxNQUFNLFFBQVEsR0FBRyxZQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFbkYsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDN0MsQ0FBQyxDQUFDLFlBQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQy9FLENBQUMsQ0FBQyxJ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
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
import Router from '@koa/router';
|
|
4
|
+
import CollectionRoute from '../collection-route';
|
|
5
|
+
export default class UpdateRoute extends CollectionRoute {
|
|
6
|
+
setupRoutes(router: Router): void;
|
|
7
|
+
handleUpdate(context: Context): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
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 datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
7
|
+
const collection_route_1 = __importDefault(require("../collection-route"));
|
|
8
|
+
const id_1 = __importDefault(require("../../utils/id"));
|
|
9
|
+
const query_string_1 = __importDefault(require("../../utils/query-string"));
|
|
10
|
+
class UpdateRoute extends collection_route_1.default {
|
|
11
|
+
setupRoutes(router) {
|
|
12
|
+
router.put(`/${this.collection.name}/:id`, this.handleUpdate.bind(this));
|
|
13
|
+
}
|
|
14
|
+
async handleUpdate(context) {
|
|
15
|
+
await this.services.authorization.assertCanEdit(context, this.collection.name);
|
|
16
|
+
const id = id_1.default.unpackId(this.collection.schema, context.params.id);
|
|
17
|
+
const { body } = context.request;
|
|
18
|
+
if ('relationships' in body.data) {
|
|
19
|
+
delete body.data.relationships;
|
|
20
|
+
}
|
|
21
|
+
const record = this.services.serializer.deserialize(this.collection, body);
|
|
22
|
+
datasource_toolkit_1.RecordValidator.validate(this.collection, record);
|
|
23
|
+
const conditionTree = datasource_toolkit_1.ConditionTreeFactory.intersect(datasource_toolkit_1.ConditionTreeFactory.matchIds(this.collection.schema, [id]), await this.services.permissions.getScope(this.collection, context));
|
|
24
|
+
const caller = query_string_1.default.parseCaller(context);
|
|
25
|
+
await this.collection.update(caller, new datasource_toolkit_1.Filter({ conditionTree }), record);
|
|
26
|
+
const [updateResult] = await this.collection.list(caller, new datasource_toolkit_1.Filter({ conditionTree }), datasource_toolkit_1.ProjectionFactory.all(this.collection));
|
|
27
|
+
context.response.body = this.services.serializer.serialize(this.collection, updateResult);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.default = UpdateRoute;
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlcy9tb2RpZmljYXRpb24vdXBkYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBS3lDO0FBSXpDLDJFQUFrRDtBQUNsRCx3REFBcUM7QUFDckMsNEVBQXlEO0FBRXpELE1BQXFCLFdBQVksU0FBUSwwQkFBZTtJQUN0RCxXQUFXLENBQUMsTUFBYztRQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLE1BQU0sRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzNFLENBQUM7SUFFTSxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQWdCO1FBQ3hDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRS9FLE1BQU0sRUFBRSxHQUFHLFlBQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUV2RSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUVqQyxJQUFJLGVBQWUsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7U0FDaEM7UUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMzRSxvQ0FBZSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRWxELE1BQU0sYUFBYSxHQUFHLHlDQUFvQixDQUFDLFNBQVMsQ0FDbEQseUNBQW9CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDM0QsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FDbkUsQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLHNCQUFpQixDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0RCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxJQUFJLDJCQUFNLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzVFLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUMvQyxNQUFNLEVBQ04sSUFBSSwyQkFBTSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFDN0Isc0NBQWlCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDdkMsQ0FBQztRQUVGLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzVGLENBQUM7Q0FDRjtBQWpDRCw4QkFpQ0MifQ==
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Collection, DataSource } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { AgentOptionsWithDefaults } from '../types';
|
|
3
|
+
import { ForestAdminHttpDriverServices } from '../services';
|
|
4
|
+
import CollectionRoute from './collection-route';
|
|
5
|
+
export default abstract class RelationRoute extends CollectionRoute {
|
|
6
|
+
protected readonly relationName: string;
|
|
7
|
+
protected get foreignCollection(): Collection;
|
|
8
|
+
constructor(services: ForestAdminHttpDriverServices, options: AgentOptionsWithDefaults, dataSource: DataSource, collectionName: string, relationName: string);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=relation-route.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
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 collection_route_1 = __importDefault(require("./collection-route"));
|
|
7
|
+
class RelationRoute extends collection_route_1.default {
|
|
8
|
+
constructor(services, options, dataSource, collectionName, relationName) {
|
|
9
|
+
super(services, options, dataSource, collectionName);
|
|
10
|
+
this.relationName = relationName;
|
|
11
|
+
}
|
|
12
|
+
get foreignCollection() {
|
|
13
|
+
const schema = this.collection.schema.fields[this.relationName];
|
|
14
|
+
return this.collection.dataSource.getCollection(schema.foreignCollection);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.default = RelationRoute;
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpb24tcm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcm91dGVzL3JlbGF0aW9uLXJvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBSUEsMEVBQWlEO0FBRWpELE1BQThCLGFBQWMsU0FBUSwwQkFBZTtJQVNqRSxZQUNFLFFBQXVDLEVBQ3ZDLE9BQWlDLEVBQ2pDLFVBQXNCLEVBQ3RCLGNBQXNCLEVBQ3RCLFlBQW9CO1FBRXBCLEtBQUssQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztJQUNuQyxDQUFDO0lBZkQsSUFBYyxpQkFBaUI7UUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQW1CLENBQUM7UUFFbEYsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDNUUsQ0FBQztDQVlGO0FBbkJELGdDQW1CQyJ9
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import Router from '@koa/router';
|
|
3
|
+
import { Context } from 'koa';
|
|
4
|
+
import { RouteType } from '../../types';
|
|
5
|
+
import BaseRoute from '../base-route';
|
|
6
|
+
export default class Authentication extends BaseRoute {
|
|
7
|
+
readonly type = RouteType.Authentication;
|
|
8
|
+
private client;
|
|
9
|
+
bootstrap(): Promise<void>;
|
|
10
|
+
setupRoutes(router: Router): void;
|
|
11
|
+
handleAuthentication(context: Context): Promise<void>;
|
|
12
|
+
handleAuthenticationCallback(context: Context): Promise<void>;
|
|
13
|
+
private static checkRenderingId;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=authentication.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
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 openid_client_1 = require("openid-client");
|
|
7
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
8
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
9
|
+
const koa_jwt_1 = __importDefault(require("koa-jwt"));
|
|
10
|
+
const types_1 = require("../../types");
|
|
11
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
12
|
+
const forest_http_api_1 = __importDefault(require("../../utils/forest-http-api"));
|
|
13
|
+
class Authentication extends base_route_1.default {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this.type = types_1.RouteType.Authentication;
|
|
17
|
+
}
|
|
18
|
+
async bootstrap() {
|
|
19
|
+
// Retrieve OpenId Issuer from forestadmin-server
|
|
20
|
+
// We can't use 'Issuer.discover' because the oidc config is behind an auth-wall.
|
|
21
|
+
const issuer = new openid_client_1.Issuer(await forest_http_api_1.default.getOpenIdIssuerMetadata(this.options));
|
|
22
|
+
const registration = {
|
|
23
|
+
token_endpoint_auth_method: 'none',
|
|
24
|
+
};
|
|
25
|
+
// Register a new oidc client
|
|
26
|
+
this.client = await issuer.Client.register(registration, {
|
|
27
|
+
initialAccessToken: this.options.envSecret,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
setupRoutes(router) {
|
|
31
|
+
router.post('/authentication', this.handleAuthentication.bind(this));
|
|
32
|
+
router.get('/authentication/callback', this.handleAuthenticationCallback.bind(this));
|
|
33
|
+
router.use((0, koa_jwt_1.default)({ secret: this.options.authSecret, cookie: 'forest_session_token' }));
|
|
34
|
+
}
|
|
35
|
+
async handleAuthentication(context) {
|
|
36
|
+
const renderingId = Number(context.request.body?.renderingId);
|
|
37
|
+
Authentication.checkRenderingId(renderingId);
|
|
38
|
+
const authorizationUrl = this.client.authorizationUrl({
|
|
39
|
+
scope: 'openid email profile',
|
|
40
|
+
state: JSON.stringify({ renderingId }),
|
|
41
|
+
});
|
|
42
|
+
context.response.body = { authorizationUrl };
|
|
43
|
+
}
|
|
44
|
+
async handleAuthenticationCallback(context) {
|
|
45
|
+
// Retrieve renderingId
|
|
46
|
+
const { query } = context.request;
|
|
47
|
+
const state = query.state.toString();
|
|
48
|
+
let renderingId;
|
|
49
|
+
try {
|
|
50
|
+
renderingId = JSON.parse(state).renderingId;
|
|
51
|
+
Authentication.checkRenderingId(renderingId);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
throw new datasource_toolkit_1.ValidationError('Failed to retrieve renderingId from query[state]');
|
|
55
|
+
}
|
|
56
|
+
// Retrieve user
|
|
57
|
+
const tokenSet = await this.client.callback(undefined, query, { state });
|
|
58
|
+
const accessToken = tokenSet.access_token;
|
|
59
|
+
const user = await forest_http_api_1.default.getUserInformation(this.options, renderingId, accessToken);
|
|
60
|
+
// Generate final token.
|
|
61
|
+
const token = jsonwebtoken_1.default.sign(user, this.options.authSecret, { expiresIn: '1 hours' });
|
|
62
|
+
context.response.body = {
|
|
63
|
+
token,
|
|
64
|
+
tokenData: jsonwebtoken_1.default.decode(token),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
static checkRenderingId(renderingId) {
|
|
68
|
+
if (Number.isNaN(renderingId)) {
|
|
69
|
+
throw new datasource_toolkit_1.ValidationError('Rendering id must be a number');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.default = Authentication;
|
|
74
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aGVudGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcm91dGVzL3NlY3VyaXR5L2F1dGhlbnRpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQWlFO0FBQ2pFLHdFQUFrRTtBQUVsRSxnRUFBd0M7QUFDeEMsc0RBQTBCO0FBRzFCLHVDQUF3QztBQUN4QywrREFBc0M7QUFDdEMsa0ZBQXdEO0FBRXhELE1BQXFCLGNBQWUsU0FBUSxvQkFBUztJQUFyRDs7UUFDVyxTQUFJLEdBQUcsaUJBQVMsQ0FBQyxjQUFjLENBQUM7SUFzRTNDLENBQUM7SUFsRVUsS0FBSyxDQUFDLFNBQVM7UUFDdEIsaURBQWlEO1FBQ2pELGlGQUFpRjtRQUNqRixNQUFNLE1BQU0sR0FBRyxJQUFJLHNCQUFNLENBQUMsTUFBTSx5QkFBYSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRXJGLE1BQU0sWUFBWSxHQUFHO1lBQ25CLDBCQUEwQixFQUFFLE1BQTBCO1NBQ3ZELENBQUM7UUFFRiw2QkFBNkI7UUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRTtZQUN2RCxrQkFBa0IsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVM7U0FDM0MsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLEVBQUUsSUFBSSxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRXJGLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBQSxpQkFBRyxFQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxzQkFBc0IsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRU0sS0FBSyxDQUFDLG9CQUFvQixDQUFDLE9BQWdCO1FBQ2hELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM5RCxjQUFjLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFN0MsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1lBQ3BELEtBQUssRUFBRSxzQkFBc0I7WUFDN0IsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQztTQUN2QyxDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRyxFQUFFLGdCQUFnQixFQUFFLENBQUM7SUFDL0MsQ0FBQztJQUVNLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxPQUFnQjtRQUN4RCx1QkFBdUI7UUFDdkIsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDbEMsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNyQyxJQUFJLFdBQW1CLENBQUM7UUFFeEIsSUFBSTtZQUNGLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFdBQVcsQ0FBQztZQUM1QyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDOUM7UUFBQyxNQUFNO1lBQ04sTUFBTSxJQUFJLG9DQUFlLENBQUMsa0RBQWtELENBQUMsQ0FBQztTQUMvRTtRQUVELGdCQUFnQjtRQUNoQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUM7UUFDMUMsTUFBTSxJQUFJLEdBQUcsTUFBTSx5QkFBYSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBRTVGLHdCQUF3QjtRQUN4QixNQUFNLEtBQUssR0FBRyxzQkFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUV6RixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRztZQUN0QixLQUFLO1lBQ0wsU0FBUyxFQUFFLHNCQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztTQUN0QyxDQUFDO0lBQ0osQ0FBQztJQUVPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFtQjtRQUNqRCxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDN0IsTUFBTSxJQUFJLG9DQUFlLENBQUMsK0JBQStCLENBQUMsQ0FBQztTQUM1RDtJQUNILENBQUM7Q0FDRjtBQXZFRCxpQ0F1RUMifQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import { Context, Next } from 'koa';
|
|
3
|
+
import Router from '@koa/router';
|
|
4
|
+
import { RouteType } from '../../types';
|
|
5
|
+
import BaseRoute from '../base-route';
|
|
6
|
+
export default class IpWhitelist extends BaseRoute {
|
|
7
|
+
type: RouteType;
|
|
8
|
+
private configuration;
|
|
9
|
+
setupRoutes(router: Router): void;
|
|
10
|
+
/** Load whitelist */
|
|
11
|
+
bootstrap(): Promise<void>;
|
|
12
|
+
checkIp(context: Context, next: Next): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ip-whitelist.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
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_ip_utils_1 = __importDefault(require("forest-ip-utils"));
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
9
|
+
const forest_http_api_1 = __importDefault(require("../../utils/forest-http-api"));
|
|
10
|
+
class IpWhitelist extends base_route_1.default {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.type = types_1.RouteType.Authentication;
|
|
14
|
+
}
|
|
15
|
+
setupRoutes(router) {
|
|
16
|
+
router.use(this.checkIp.bind(this));
|
|
17
|
+
}
|
|
18
|
+
/** Load whitelist */
|
|
19
|
+
async bootstrap() {
|
|
20
|
+
this.configuration = await forest_http_api_1.default.getIpWhitelistConfiguration(this.options);
|
|
21
|
+
}
|
|
22
|
+
async checkIp(context, next) {
|
|
23
|
+
if (this.configuration.isFeatureEnabled) {
|
|
24
|
+
const { ipRules } = this.configuration;
|
|
25
|
+
const currentIp = context.request.headers['x-forwarded-for'] ?? context.request.ip;
|
|
26
|
+
const allowed = ipRules.some(ipRule => forest_ip_utils_1.default.isIpMatchesRule(currentIp, ipRule));
|
|
27
|
+
if (!allowed) {
|
|
28
|
+
return context.throw(types_1.HttpCode.Forbidden, `IP address rejected (${currentIp})`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return next();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.default = IpWhitelist;
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXAtd2hpdGVsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlcy9zZWN1cml0eS9pcC13aGl0ZWxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSxzRUFBcUM7QUFHckMsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUN0QyxrRkFBc0Y7QUFFdEYsTUFBcUIsV0FBWSxTQUFRLG9CQUFTO0lBQWxEOztRQUNFLFNBQUksR0FBRyxpQkFBUyxDQUFDLGNBQWMsQ0FBQztJQTBCbEMsQ0FBQztJQXRCQyxXQUFXLENBQUMsTUFBYztRQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELHFCQUFxQjtJQUNaLEtBQUssQ0FBQyxTQUFTO1FBQ3RCLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSx5QkFBYSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFnQixFQUFFLElBQVU7UUFDeEMsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFO1lBQ3ZDLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1lBQ3ZDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDbkYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLHlCQUFNLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBRWxGLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ1osT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFRLENBQUMsU0FBUyxFQUFFLHdCQUF3QixTQUFTLEdBQUcsQ0FBQyxDQUFDO2FBQ2hGO1NBQ0Y7UUFFRCxPQUFPLElBQUksRUFBRSxDQUFDO0lBQ2hCLENBQUM7Q0FDRjtBQTNCRCw4QkEyQkMifQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import Router from '@koa/router';
|
|
3
|
+
import { RouteType } from '../../types';
|
|
4
|
+
import BaseRoute from '../base-route';
|
|
5
|
+
export default class ScopeInvalidation extends BaseRoute {
|
|
6
|
+
readonly type = RouteType.PrivateRoute;
|
|
7
|
+
setupRoutes(router: Router): void;
|
|
8
|
+
/** Route called when scopes are modified so that we don't have to wait for expiration. */
|
|
9
|
+
private invalidateCache;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=scope-invalidation.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
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 datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
9
|
+
class ScopeInvalidation extends base_route_1.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.type = types_1.RouteType.PrivateRoute;
|
|
13
|
+
}
|
|
14
|
+
setupRoutes(router) {
|
|
15
|
+
router.post(`/scope-cache-invalidation`, this.invalidateCache.bind(this));
|
|
16
|
+
}
|
|
17
|
+
/** Route called when scopes are modified so that we don't have to wait for expiration. */
|
|
18
|
+
async invalidateCache(context) {
|
|
19
|
+
const renderingId = Number(context.request.body?.renderingId);
|
|
20
|
+
if (Number.isNaN(renderingId)) {
|
|
21
|
+
throw new datasource_toolkit_1.ValidationError('Malformed body');
|
|
22
|
+
}
|
|
23
|
+
this.services.permissions.invalidateCache(renderingId);
|
|
24
|
+
context.response.status = types_1.HttpCode.NoContent;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.default = ScopeInvalidation;
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NvcGUtaW52YWxpZGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlcy9zZWN1cml0eS9zY29wZS1pbnZhbGlkYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSx3RUFBa0U7QUFHbEUsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUV0QyxNQUFxQixpQkFBa0IsU0FBUSxvQkFBUztJQUF4RDs7UUFDVyxTQUFJLEdBQUcsaUJBQVMsQ0FBQyxZQUFZLENBQUM7SUFrQnpDLENBQUM7SUFoQkMsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRCwwRkFBMEY7SUFDbEYsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFnQjtRQUM1QyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFOUQsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFO1lBQzdCLE1BQU0sSUFBSSxvQ0FBZSxDQUFDLGdCQUFnQixDQUFDLENBQUM7U0FDN0M7UUFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFdkQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsZ0JBQVEsQ0FBQyxTQUFTLENBQUM7SUFDL0MsQ0FBQztDQUNGO0FBbkJELG9DQW1CQyJ9
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import Router from '@koa/router';
|
|
3
|
+
import { RouteType } from '../../types';
|
|
4
|
+
import BaseRoute from '../base-route';
|
|
5
|
+
export default class ErrorHandling extends BaseRoute {
|
|
6
|
+
type: RouteType;
|
|
7
|
+
setupRoutes(router: Router): void;
|
|
8
|
+
private errorHandler;
|
|
9
|
+
private getErrorStatus;
|
|
10
|
+
private getErrorMessage;
|
|
11
|
+
private debugLogError;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=error-handling.d.ts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
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 koa_1 = require("koa");
|
|
7
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
8
|
+
const types_1 = require("../../types");
|
|
9
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
10
|
+
class ErrorHandling extends base_route_1.default {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.type = types_1.RouteType.ErrorHandler;
|
|
14
|
+
}
|
|
15
|
+
setupRoutes(router) {
|
|
16
|
+
router.use(this.errorHandler.bind(this));
|
|
17
|
+
}
|
|
18
|
+
async errorHandler(context, next) {
|
|
19
|
+
try {
|
|
20
|
+
await next();
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
context.response.status = this.getErrorStatus(e);
|
|
24
|
+
context.response.body = { errors: [{ detail: this.getErrorMessage(e) }] };
|
|
25
|
+
if (!this.options.isProduction) {
|
|
26
|
+
process.nextTick(() => this.debugLogError(context, e));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
getErrorStatus(error) {
|
|
31
|
+
if (error instanceof datasource_toolkit_1.ValidationError)
|
|
32
|
+
return types_1.HttpCode.BadRequest;
|
|
33
|
+
if (error instanceof datasource_toolkit_1.ForbiddenError)
|
|
34
|
+
return types_1.HttpCode.Forbidden;
|
|
35
|
+
if (error instanceof datasource_toolkit_1.UnprocessableError)
|
|
36
|
+
return types_1.HttpCode.Unprocessable;
|
|
37
|
+
if (error instanceof koa_1.HttpError)
|
|
38
|
+
return error.status;
|
|
39
|
+
return types_1.HttpCode.InternalServerError;
|
|
40
|
+
}
|
|
41
|
+
getErrorMessage(error) {
|
|
42
|
+
if (error instanceof koa_1.HttpError ||
|
|
43
|
+
error instanceof datasource_toolkit_1.ValidationError ||
|
|
44
|
+
error instanceof datasource_toolkit_1.UnprocessableError ||
|
|
45
|
+
error instanceof datasource_toolkit_1.ForbiddenError) {
|
|
46
|
+
return error.message;
|
|
47
|
+
}
|
|
48
|
+
if (this.options.customizeErrorMessage) {
|
|
49
|
+
const message = this.options.customizeErrorMessage(error);
|
|
50
|
+
if (message)
|
|
51
|
+
return message;
|
|
52
|
+
}
|
|
53
|
+
return 'Unexpected error';
|
|
54
|
+
}
|
|
55
|
+
debugLogError(context, error) {
|
|
56
|
+
const { request } = context;
|
|
57
|
+
const query = JSON.stringify(request.query, null, ' ')?.replace(/"/g, '');
|
|
58
|
+
console.error('');
|
|
59
|
+
console.error(`\x1b[33m===== An exception was raised =====\x1b[0m`);
|
|
60
|
+
console.error(`${request.method} \x1b[34m${request.path}\x1b[36m?${query}\x1b[0m`);
|
|
61
|
+
if (request.method === 'POST' || request.method === 'PUT' || request.method === 'PATCH') {
|
|
62
|
+
const body = JSON.stringify(request.body, null, ' ')?.replace(/"/g, '');
|
|
63
|
+
console.error('');
|
|
64
|
+
console.error(`Body \x1b[36m${body}\x1b[0m`);
|
|
65
|
+
}
|
|
66
|
+
console.error('');
|
|
67
|
+
console.error('\x1b[31m', error.message, '\x1b[0m');
|
|
68
|
+
console.error('');
|
|
69
|
+
console.error(error.stack);
|
|
70
|
+
console.error(`\x1b[33m===================================\x1b[0m`);
|
|
71
|
+
console.error('');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.default = ErrorHandling;
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItaGFuZGxpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcm91dGVzL3N5c3RlbS9lcnJvci1oYW5kbGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUErQztBQUMvQyx3RUFJeUM7QUFHekMsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUV0QyxNQUFxQixhQUFjLFNBQVEsb0JBQVM7SUFBcEQ7O1FBQ0UsU0FBSSxHQUFHLGlCQUFTLENBQUMsWUFBWSxDQUFDO0lBbUVoQyxDQUFDO0lBakVDLFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFnQixFQUFFLElBQVU7UUFDckQsSUFBSTtZQUNGLE1BQU0sSUFBSSxFQUFFLENBQUM7U0FDZDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqRCxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFFMUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFO2dCQUM5QixPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDeEQ7U0FDRjtJQUNILENBQUM7SUFFTyxjQUFjLENBQUMsS0FBWTtRQUNqQyxJQUFJLEtBQUssWUFBWSxvQ0FBZTtZQUFFLE9BQU8sZ0JBQVEs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
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
import Router from '@koa/router';
|
|
4
|
+
import { RouteType } from '../../types';
|
|
5
|
+
import BaseRoute from '../base-route';
|
|
6
|
+
export default class HealthCheck extends BaseRoute {
|
|
7
|
+
type: RouteType;
|
|
8
|
+
setupRoutes(router: Router): void;
|
|
9
|
+
handleRequest(ctx: Context): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=healthcheck.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
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 types_1 = require("../../types");
|
|
7
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
8
|
+
class HealthCheck extends base_route_1.default {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.type = types_1.RouteType.PublicRoute;
|
|
12
|
+
}
|
|
13
|
+
setupRoutes(router) {
|
|
14
|
+
router.get('/', this.handleRequest.bind(this));
|
|
15
|
+
}
|
|
16
|
+
async handleRequest(ctx) {
|
|
17
|
+
ctx.response.body = { error: null, message: 'Agent is running' };
|
|
18
|
+
ctx.response.status = types_1.HttpCode.Ok;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.default = HealthCheck;
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhbHRoY2hlY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcm91dGVzL3N5c3RlbS9oZWFsdGhjaGVjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUdBLHVDQUFrRDtBQUNsRCwrREFBc0M7QUFFdEMsTUFBcUIsV0FBWSxTQUFRLG9CQUFTO0lBQWxEOztRQUNFLFNBQUksR0FBRyxpQkFBUyxDQUFDLFdBQVcsQ0FBQztJQVUvQixDQUFDO0lBUkMsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRU0sS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFZO1FBQ3JDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQztRQUNqRSxHQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxnQkFBUSxDQUFDLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUFYRCw4QkFXQyJ9
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="koa__router" />
|
|
2
|
+
import Router from '@koa/router';
|
|
3
|
+
import { RouteType } from '../../types';
|
|
4
|
+
import BaseRoute from '../base-route';
|
|
5
|
+
export default class Logger extends BaseRoute {
|
|
6
|
+
type: RouteType;
|
|
7
|
+
setupRoutes(router: Router): void;
|
|
8
|
+
private logger;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
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 types_1 = require("../../types");
|
|
7
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
8
|
+
class Logger extends base_route_1.default {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.type = types_1.RouteType.LoggerHandler;
|
|
12
|
+
}
|
|
13
|
+
setupRoutes(router) {
|
|
14
|
+
router.use(this.logger.bind(this));
|
|
15
|
+
}
|
|
16
|
+
async logger(context, next) {
|
|
17
|
+
const timer = Date.now();
|
|
18
|
+
try {
|
|
19
|
+
await next();
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
let logLevel = 'Info';
|
|
23
|
+
if (context.response.status >= types_1.HttpCode.BadRequest)
|
|
24
|
+
logLevel = 'Warn';
|
|
25
|
+
if (context.response.status >= types_1.HttpCode.InternalServerError)
|
|
26
|
+
logLevel = 'Error';
|
|
27
|
+
let message = `[${context.response.status}]`;
|
|
28
|
+
message += ` ${context.request.method} ${context.request.path}`;
|
|
29
|
+
message += ` - ${Date.now() - timer}ms`;
|
|
30
|
+
this.options?.logger(logLevel, message);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.default = Logger;
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JvdXRlcy9zeXN0ZW0vbG9nZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBS0EsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUV0QyxNQUFxQixNQUFPLFNBQVEsb0JBQVM7SUFBN0M7O1FBQ0UsU0FBSSxHQUFHLGlCQUFTLENBQUMsYUFBYSxDQUFDO0lBdUJqQyxDQUFDO0lBckJDLFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFnQixFQUFFLElBQVU7UUFDL0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXpCLElBQUk7WUFDRixNQUFNLElBQUksRUFBRSxDQUFDO1NBQ2Q7Z0JBQVM7WUFDUixJQUFJLFFBQVEsR0FBZ0IsTUFBTSxDQUFDO1lBQ25DLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLElBQUksZ0JBQVEsQ0FBQyxVQUFVO2dCQUFFLFFBQVEsR0FBRyxNQUFNLENBQUM7WUFDdEUsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sSUFBSSxnQkFBUSxDQUFDLG1CQUFtQjtnQkFBRSxRQUFRLEdBQUcsT0FBTyxDQUFDO1lBRWhGLElBQUksT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUM3QyxPQUFPLElBQUksSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2hFLE9BQU8sSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLElBQUksQ0FBQztZQUV4QyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDekM7SUFDSCxDQUFDO0NBQ0Y7QUF4QkQseUJBd0JDIn0=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Context } from 'koa';
|
|
2
|
+
import ActionPermissionService from './internal/action-permission';
|
|
3
|
+
export default class AuthorizationService {
|
|
4
|
+
private readonly actionPermissionService;
|
|
5
|
+
constructor(actionPermissionService: ActionPermissionService);
|
|
6
|
+
assertCanBrowse(context: Context, collectionName: string): Promise<void>;
|
|
7
|
+
assertCanRead(context: Context, collectionName: string): Promise<void>;
|
|
8
|
+
assertCanAdd(context: Context, collectionName: string): Promise<void>;
|
|
9
|
+
assertCanEdit(context: Context, collectionName: string): Promise<void>;
|
|
10
|
+
assertCanDelete(context: Context, collectionName: string): Promise<void>;
|
|
11
|
+
assertCanExport(context: Context, collectionName: string): Promise<void>;
|
|
12
|
+
private assertCanOnCollection;
|
|
13
|
+
assertCanExecuteCustomAction(context: Context, customActionName: string, collectionName: string): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=authorization.d.ts.map
|