@forestadmin/agent 1.0.0-beta.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/forestadmin-http-driver.d.ts +34 -0
- package/dist/agent/forestadmin-http-driver.js +73 -0
- package/dist/agent/routes/access/chart.d.ts +17 -0
- package/dist/agent/routes/access/chart.js +125 -0
- package/dist/agent/routes/access/count-related.d.ts +9 -0
- package/dist/agent/routes/access/count-related.js +24 -0
- package/dist/agent/routes/access/count.d.ts +9 -0
- package/dist/agent/routes/access/count.js +24 -0
- package/dist/agent/routes/access/csv-related.d.ts +9 -0
- package/dist/agent/routes/access/csv-related.js +33 -0
- package/dist/agent/routes/access/csv.d.ts +9 -0
- package/dist/agent/routes/access/csv.js +30 -0
- package/dist/agent/routes/access/get.d.ts +9 -0
- package/dist/agent/routes/access/get.js +28 -0
- package/dist/agent/routes/access/list-related.d.ts +9 -0
- package/dist/agent/routes/access/list-related.js +26 -0
- package/dist/agent/routes/access/list.d.ts +9 -0
- package/dist/agent/routes/access/list.js +23 -0
- package/dist/agent/routes/base-route.d.ts +14 -0
- package/dist/agent/routes/base-route.js +16 -0
- package/dist/agent/routes/collection-route.d.ts +12 -0
- package/dist/agent/routes/collection-route.js +20 -0
- package/dist/agent/routes/index.d.ts +30 -0
- package/dist/agent/routes/index.js +90 -0
- package/dist/agent/routes/modification/action.d.ts +17 -0
- package/dist/agent/routes/modification/action.js +103 -0
- package/dist/agent/routes/modification/associate-related.d.ts +12 -0
- package/dist/agent/routes/modification/associate-related.js +49 -0
- package/dist/agent/routes/modification/create.d.ts +14 -0
- package/dist/agent/routes/modification/create.js +81 -0
- package/dist/agent/routes/modification/delete.d.ts +11 -0
- package/dist/agent/routes/modification/delete.js +40 -0
- package/dist/agent/routes/modification/dissociate-delete-related.d.ts +20 -0
- package/dist/agent/routes/modification/dissociate-delete-related.js +88 -0
- package/dist/agent/routes/modification/update-relation.d.ts +11 -0
- package/dist/agent/routes/modification/update-relation.js +53 -0
- package/dist/agent/routes/modification/update.d.ts +9 -0
- package/dist/agent/routes/modification/update.js +29 -0
- package/dist/agent/routes/relation-route.d.ts +10 -0
- package/dist/agent/routes/relation-route.js +18 -0
- package/dist/agent/routes/security/authentication.d.ts +17 -0
- package/dist/agent/routes/security/authentication.js +86 -0
- package/dist/agent/routes/security/ip-whitelist.d.ts +14 -0
- package/dist/agent/routes/security/ip-whitelist.js +35 -0
- package/dist/agent/routes/security/scope-invalidation.d.ts +11 -0
- package/dist/agent/routes/security/scope-invalidation.js +28 -0
- package/dist/agent/routes/system/error-handling.d.ts +11 -0
- package/dist/agent/routes/system/error-handling.js +56 -0
- package/dist/agent/routes/system/healthcheck.d.ts +11 -0
- package/dist/agent/routes/system/healthcheck.js +22 -0
- package/dist/agent/routes/system/logger.d.ts +10 -0
- package/dist/agent/routes/system/logger.js +36 -0
- package/dist/agent/services/index.d.ts +10 -0
- package/dist/agent/services/index.js +12 -0
- package/dist/agent/services/permissions.d.ts +19 -0
- package/dist/agent/services/permissions.js +79 -0
- package/dist/agent/services/serializer.d.ts +17 -0
- package/dist/agent/services/serializer.js +120 -0
- package/dist/agent/types.d.ts +23 -0
- package/dist/agent/types.js +22 -0
- package/dist/agent/utils/body-parser.d.ts +7 -0
- package/dist/agent/utils/body-parser.js +18 -0
- package/dist/agent/utils/context-filter-factory.d.ts +7 -0
- package/dist/agent/utils/context-filter-factory.js +29 -0
- package/dist/agent/utils/csv-generator.d.ts +12 -0
- package/dist/agent/utils/csv-generator.js +39 -0
- package/dist/agent/utils/csv-route-context.d.ts +5 -0
- package/dist/agent/utils/csv-route-context.js +14 -0
- package/dist/agent/utils/forest-http-api.d.ts +63 -0
- package/dist/agent/utils/forest-http-api.js +173 -0
- package/dist/agent/utils/forest-schema/action-values.d.ts +34 -0
- package/dist/agent/utils/forest-schema/action-values.js +144 -0
- package/dist/agent/utils/forest-schema/emitter.d.ts +20 -0
- package/dist/agent/utils/forest-schema/emitter.js +70 -0
- package/dist/agent/utils/forest-schema/filterable.d.ts +16 -0
- package/dist/agent/utils/forest-schema/filterable.js +68 -0
- package/dist/agent/utils/forest-schema/generator-actions.d.ts +14 -0
- package/dist/agent/utils/forest-schema/generator-actions.js +99 -0
- package/dist/agent/utils/forest-schema/generator-collection.d.ts +7 -0
- package/dist/agent/utils/forest-schema/generator-collection.js +31 -0
- package/dist/agent/utils/forest-schema/generator-fields.d.ts +13 -0
- package/dist/agent/utils/forest-schema/generator-fields.js +131 -0
- package/dist/agent/utils/forest-schema/generator-segments.d.ts +6 -0
- package/dist/agent/utils/forest-schema/generator-segments.js +9 -0
- package/dist/agent/utils/forest-schema/types.d.ts +79 -0
- package/dist/agent/utils/forest-schema/types.js +16 -0
- package/dist/agent/utils/forest-schema/validation.d.ts +10 -0
- package/dist/agent/utils/forest-schema/validation.js +26 -0
- package/dist/agent/utils/http-driver-options.d.ts +13 -0
- package/dist/agent/utils/http-driver-options.js +86 -0
- package/dist/agent/utils/id.d.ts +8 -0
- package/dist/agent/utils/id.js +43 -0
- package/dist/agent/utils/query-string.d.ts +14 -0
- package/dist/agent/utils/query-string.js +130 -0
- package/dist/builder/agent.d.ts +81 -0
- package/dist/builder/agent.js +113 -0
- package/dist/builder/collection.d.ts +148 -0
- package/dist/builder/collection.js +226 -0
- package/dist/builder/types.d.ts +5 -0
- package/dist/builder/types.js +3 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +22 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.js +11 -0
- package/dist/utils/csv-generator.d.ts +12 -0
- package/dist/utils/csv-generator.js +39 -0
- package/package.json +55 -0
|
@@ -0,0 +1,53 @@
|
|
|
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 timezone = query_string_1.default.parseTimezone(context);
|
|
18
|
+
const parentId = id_1.default.unpackId(this.collection.schema, context.params.parentId);
|
|
19
|
+
const linkedId = id_1.default.unpackId(this.foreignCollection.schema, context.request.body?.data.id);
|
|
20
|
+
if (relation.type === 'ManyToOne') {
|
|
21
|
+
await this.updateManyToOne(context, relation, parentId, linkedId, timezone);
|
|
22
|
+
}
|
|
23
|
+
else if (relation.type === 'OneToOne') {
|
|
24
|
+
await this.updateOneToOne(context, relation, parentId, linkedId, timezone);
|
|
25
|
+
}
|
|
26
|
+
context.response.status = types_1.HttpCode.NoContent;
|
|
27
|
+
}
|
|
28
|
+
async updateManyToOne(context, relation, parentId, linkedId, timezone) {
|
|
29
|
+
// Perms
|
|
30
|
+
const scope = await this.services.permissions.getScope(this.collection, context);
|
|
31
|
+
await this.services.permissions.can(context, `edit:${this.collection.name}`);
|
|
32
|
+
// Load the value that will be used as foreignKey (=== linkedId[0] most of the time)
|
|
33
|
+
const foreignValue = await datasource_toolkit_1.CollectionUtils.getValue(this.foreignCollection, linkedId, relation.foreignKeyTarget);
|
|
34
|
+
// Overwrite old foreign key with new one (only one query needed).
|
|
35
|
+
const fkOwner = datasource_toolkit_1.ConditionTreeFactory.matchIds(this.collection.schema, [parentId]);
|
|
36
|
+
await this.collection.update(new datasource_toolkit_1.Filter({ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(fkOwner, scope), timezone }), { [relation.foreignKey]: foreignValue });
|
|
37
|
+
}
|
|
38
|
+
async updateOneToOne(context, relation, parentId, linkedId, timezone) {
|
|
39
|
+
// Permissions
|
|
40
|
+
const scope = await this.services.permissions.getScope(this.foreignCollection, context);
|
|
41
|
+
await this.services.permissions.can(context, `edit:${this.foreignCollection.name}`);
|
|
42
|
+
// Load the value that will be used as originKey (=== parentId[0] most of the time)
|
|
43
|
+
const originValue = await datasource_toolkit_1.CollectionUtils.getValue(this.collection, parentId, relation.originKeyTarget);
|
|
44
|
+
// Break old relation (may update zero or one records).
|
|
45
|
+
const oldFkOwner = new datasource_toolkit_1.ConditionTreeLeaf(relation.originKey, 'Equal', originValue);
|
|
46
|
+
await this.foreignCollection.update(new datasource_toolkit_1.Filter({ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(oldFkOwner, scope), timezone }), { [relation.originKey]: null });
|
|
47
|
+
// Create new relation (will update exactly one record).
|
|
48
|
+
const newFkOwner = datasource_toolkit_1.ConditionTreeFactory.matchIds(this.foreignCollection.schema, [linkedId]);
|
|
49
|
+
await this.foreignCollection.update(new datasource_toolkit_1.Filter({ conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(newFkOwner, scope), timezone }), { [relation.originKey]: originValue });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.default = UpdateRelation;
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLXJlbGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FnZW50L3JvdXRlcy9tb2RpZmljYXRpb24vdXBkYXRlLXJlbGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBUXlDO0FBSXpDLHVDQUF1QztBQUN2Qyx3REFBcUM7QUFDckMsNEVBQXlEO0FBQ3pELHVFQUE4QztBQUU5QyxNQUFxQixjQUFlLFNBQVEsd0JBQWE7SUFDdkQsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FDUixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSw0QkFBNEIsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUN2RSxJQUFJLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUMxQyxDQUFDO0lBQ0osQ0FBQztJQUVNLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxPQUFnQjtRQUNyRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sUUFBUSxHQUFHLHNCQUFpQixDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxNQUFNLFFBQVEsR0FBRyxZQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbkYsTUFBTSxRQUFRLEdBQUcsWUFBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVoRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFO1lBQ2pDLE1BQU0sSUFBSSxDQUFDLGVB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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,29 @@
|
|
|
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
|
+
class UpdateRoute extends collection_route_1.default {
|
|
10
|
+
setupRoutes(router) {
|
|
11
|
+
router.put(`/${this.collection.name}/:id`, this.handleUpdate.bind(this));
|
|
12
|
+
}
|
|
13
|
+
async handleUpdate(context) {
|
|
14
|
+
await this.services.permissions.can(context, `edit:${this.collection.name}`);
|
|
15
|
+
const id = id_1.default.unpackId(this.collection.schema, context.params.id);
|
|
16
|
+
const { body } = context.request;
|
|
17
|
+
if ('relationships' in body.data) {
|
|
18
|
+
delete body.data.relationships;
|
|
19
|
+
}
|
|
20
|
+
const record = this.services.serializer.deserialize(this.collection, body);
|
|
21
|
+
datasource_toolkit_1.RecordValidator.validate(this.collection, record);
|
|
22
|
+
const conditionTree = datasource_toolkit_1.ConditionTreeFactory.intersect(datasource_toolkit_1.ConditionTreeFactory.matchIds(this.collection.schema, [id]), await this.services.permissions.getScope(this.collection, context));
|
|
23
|
+
await this.collection.update(new datasource_toolkit_1.Filter({ conditionTree }), record);
|
|
24
|
+
const [updateResult] = await this.collection.list(new datasource_toolkit_1.Filter({ conditionTree }), datasource_toolkit_1.ProjectionFactory.all(this.collection));
|
|
25
|
+
context.response.body = this.services.serializer.serialize(this.collection, updateResult);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = UpdateRoute;
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FnZW50L3JvdXRlcy9tb2RpZmljYXRpb24vdXBkYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBS3lDO0FBSXpDLDJFQUFrRDtBQUNsRCx3REFBcUM7QUFFckMsTUFBcUIsV0FBWSxTQUFRLDBCQUFlO0lBQ3RELFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksTUFBTSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVNLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBZ0I7UUFDeEMsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRTdFLE1BQU0sRUFBRSxHQUFHLFlBQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUV2RSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUVqQyxJQUFJLGVBQWUsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7U0FDaEM7UUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMzRSxvQ0FBZSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRWxELE1BQU0sYUFBYSxHQUFHLHlDQUFvQixDQUFDLFNBQVMsQ0FDbEQseUNBQW9CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDM0QsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FDbkUsQ0FBQztRQUVGLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSwyQkFBTSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNwRSxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FDL0MsSUFBSSwyQkFBTSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFDN0Isc0NBQWlCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDdkMsQ0FBQztRQUVGLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzVGLENBQUM7Q0FDRjtBQWhDRCw4QkFnQ0MifQ==
|
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpb24tcm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWdlbnQvcm91dGVzL3JlbGF0aW9uLXJvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBSUEsMEVBQWlEO0FBRWpELE1BQThCLGFBQWMsU0FBUSwwQkFBZTtJQVNqRSxZQUNFLFFBQXVDLEVBQ3ZDLE9BQWlDLEVBQ2pDLFVBQXNCLEVBQ3RCLGNBQXNCLEVBQ3RCLFlBQW9CO1FBRXBCLEtBQUssQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztJQUNuQyxDQUFDO0lBZkQsSUFBYyxpQkFBaUI7UUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQW1CLENBQUM7UUFFbEYsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDNUUsQ0FBQztDQVlGO0FBbkJELGdDQW1CQyJ9
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
private get redirectUrl();
|
|
10
|
+
bootstrap(): Promise<void>;
|
|
11
|
+
setupRoutes(router: Router): void;
|
|
12
|
+
handleAuthentication(context: Context): Promise<void>;
|
|
13
|
+
handleAuthenticationCallback(context: Context): Promise<void>;
|
|
14
|
+
handleAuthenticationLogout(context: Context): Promise<void>;
|
|
15
|
+
private checkRenderingId;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=authentication.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
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 path_1 = require("path");
|
|
9
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
10
|
+
const koa_jwt_1 = __importDefault(require("koa-jwt"));
|
|
11
|
+
const types_1 = require("../../types");
|
|
12
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
13
|
+
const forest_http_api_1 = __importDefault(require("../../utils/forest-http-api"));
|
|
14
|
+
class Authentication extends base_route_1.default {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.type = types_1.RouteType.Authentication;
|
|
18
|
+
}
|
|
19
|
+
get redirectUrl() {
|
|
20
|
+
const base = this.options.agentUrl;
|
|
21
|
+
const path = (0, path_1.join)(this.options.prefix, '/authentication/callback');
|
|
22
|
+
return new URL(path, base).toString();
|
|
23
|
+
}
|
|
24
|
+
async bootstrap() {
|
|
25
|
+
// Retrieve OpenId Issuer from forestadmin-server
|
|
26
|
+
// We can't use 'Issuer.discover' because the oidc config is behind an auth-wall.
|
|
27
|
+
const issuer = new openid_client_1.Issuer(await forest_http_api_1.default.getOpenIdIssuerMetadata(this.options));
|
|
28
|
+
// Either instanciate or create a new oidc client.
|
|
29
|
+
const registration = {
|
|
30
|
+
client_id: this.options.clientId,
|
|
31
|
+
token_endpoint_auth_method: 'none',
|
|
32
|
+
redirect_uris: [this.redirectUrl],
|
|
33
|
+
};
|
|
34
|
+
this.client = registration.client_id
|
|
35
|
+
? new issuer.Client(registration)
|
|
36
|
+
: await issuer.Client.register(registration, { initialAccessToken: this.options.envSecret });
|
|
37
|
+
}
|
|
38
|
+
setupRoutes(router) {
|
|
39
|
+
router.post('/authentication', this.handleAuthentication.bind(this));
|
|
40
|
+
router.get('/authentication/callback', this.handleAuthenticationCallback.bind(this));
|
|
41
|
+
router.use((0, koa_jwt_1.default)({ secret: this.options.authSecret, cookie: 'forest_session_token' }));
|
|
42
|
+
router.post('/authentication/logout', this.handleAuthenticationLogout.bind(this));
|
|
43
|
+
}
|
|
44
|
+
async handleAuthentication(context) {
|
|
45
|
+
const renderingId = Number(context.request.body?.renderingId);
|
|
46
|
+
this.checkRenderingId(renderingId);
|
|
47
|
+
const authorizationUrl = this.client.authorizationUrl({
|
|
48
|
+
scope: 'openid email profile',
|
|
49
|
+
state: JSON.stringify({ renderingId }),
|
|
50
|
+
});
|
|
51
|
+
context.response.body = { authorizationUrl };
|
|
52
|
+
}
|
|
53
|
+
async handleAuthenticationCallback(context) {
|
|
54
|
+
// Retrieve renderingId
|
|
55
|
+
const { query } = context.request;
|
|
56
|
+
const state = query.state.toString();
|
|
57
|
+
let renderingId;
|
|
58
|
+
try {
|
|
59
|
+
renderingId = JSON.parse(state).renderingId;
|
|
60
|
+
this.checkRenderingId(renderingId);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
throw new datasource_toolkit_1.ValidationError('Failed to retrieve renderingId from query[state]');
|
|
64
|
+
}
|
|
65
|
+
// Retrieve user
|
|
66
|
+
const tokenSet = await this.client.callback(this.redirectUrl, query, { state });
|
|
67
|
+
const accessToken = tokenSet.access_token;
|
|
68
|
+
const user = await forest_http_api_1.default.getUserInformation(this.options, renderingId, accessToken);
|
|
69
|
+
// Generate final token.
|
|
70
|
+
const token = jsonwebtoken_1.default.sign(user, this.options.authSecret, { expiresIn: '1 hours' });
|
|
71
|
+
context.response.body = {
|
|
72
|
+
token,
|
|
73
|
+
tokenData: jsonwebtoken_1.default.decode(token),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async handleAuthenticationLogout(context) {
|
|
77
|
+
context.response.status = types_1.HttpCode.NoContent;
|
|
78
|
+
}
|
|
79
|
+
checkRenderingId(renderingId) {
|
|
80
|
+
if (Number.isNaN(renderingId)) {
|
|
81
|
+
throw new datasource_toolkit_1.ValidationError('Rendering id must be a number');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.default = Authentication;
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aGVudGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYWdlbnQvcm91dGVzL3NlY3VyaXR5L2F1dGhlbnRpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQWlFO0FBQ2pFLHdFQUFrRTtBQUNsRSwrQkFBNEI7QUFFNUIsZ0VBQXdDO0FBQ3hDLHNEQUEwQjtBQUcxQix1Q0FBa0Q7QUFDbEQsK0RBQXNDO0FBQ3RDLGtGQUF3RDtBQUV4RCxNQUFxQixjQUFlLFNBQVEsb0JBQVM7SUFBckQ7O1FBQ1csU0FBSSxHQUFHLGlCQUFTLENBQUMsY0FBYyxDQUFDO0lBcUYzQyxDQUFDO0lBakZDLElBQVksV0FBVztRQUNyQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUNuQyxNQUFNLElBQUksR0FBRyxJQUFBLFdBQUksRUFBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO1FBRW5FLE9BQU8sSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFUSxLQUFLLENBQUMsU0FBUztRQUN0QixpREFBaUQ7UUFDakQsaUZBQWlGO1FBQ2pGLE1BQU0sTUFBTSxHQUFHLElBQUksc0JBQU0sQ0FBQyxNQUFNLHlCQUFhLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFFckYsa0RBQWtEO1FBQ2xELE1BQU0sWUFBWSxHQUFHO1lBQ25CLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVE7WUFDaEMsMEJBQTBCLEVBQUUsTUFBMEI7WUFDdEQsYUFBYSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztTQUNsQyxDQUFDO1FBRUYsSUFBSSxDQUFDLE1BQU0sR0FBRyxZQUFZLENBQUMsU0FBUztZ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
|
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXAtd2hpdGVsaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FnZW50L3JvdXRlcy9zZWN1cml0eS9pcC13aGl0ZWxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSxzRUFBcUM7QUFHckMsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUN0QyxrRkFBc0Y7QUFFdEYsTUFBcUIsV0FBWSxTQUFRLG9CQUFTO0lBQWxEOztRQUNFLFNBQUksR0FBRyxpQkFBUyxDQUFDLGNBQWMsQ0FBQztJQTBCbEMsQ0FBQztJQXRCQyxXQUFXLENBQUMsTUFBYztRQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELHFCQUFxQjtJQUNaLEtBQUssQ0FBQyxTQUFTO1FBQ3RCLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSx5QkFBYSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFnQixFQUFFLElBQVU7UUFDeEMsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFO1lBQ3ZDLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1lBQ3ZDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDbkYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLHlCQUFNLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBRWxGLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ1osT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFRLENBQUMsU0FBUyxFQUFFLHdCQUF3QixTQUFTLEdBQUcsQ0FBQyxDQUFDO2FBQ2hGO1NBQ0Y7UUFFRCxPQUFPLElBQUksRUFBRSxDQUFDO0lBQ2hCLENBQUM7Q0FDRjtBQTNCRCw4QkEyQkMifQ==
|
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NvcGUtaW52YWxpZGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FnZW50L3JvdXRlcy9zZWN1cml0eS9zY29wZS1pbnZhbGlkYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSx3RUFBa0U7QUFHbEUsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUV0QyxNQUFxQixpQkFBa0IsU0FBUSxvQkFBUztJQUF4RDs7UUFDVyxTQUFJLEdBQUcsaUJBQVMsQ0FBQyxZQUFZLENBQUM7SUFrQnpDLENBQUM7SUFoQkMsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRCwwRkFBMEY7SUFDbEYsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFnQjtRQUM1QyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFOUQsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFO1lBQzdCLE1BQU0sSUFBSSxvQ0FBZSxDQUFDLGdCQUFnQixDQUFDLENBQUM7U0FDN0M7UUFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFdkQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsZ0JBQVEsQ0FBQyxTQUFTLENBQUM7SUFDL0MsQ0FBQztDQUNGO0FBbkJELG9DQW1CQyJ9
|
|
@@ -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 ErrorHandling extends BaseRoute {
|
|
6
|
+
type: RouteType;
|
|
7
|
+
setupRoutes(router: Router): void;
|
|
8
|
+
private errorHandler;
|
|
9
|
+
private debugLogError;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=error-handling.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
let status = types_1.HttpCode.InternalServerError;
|
|
24
|
+
let message = 'Unexpected error';
|
|
25
|
+
if (e instanceof koa_1.HttpError || e instanceof datasource_toolkit_1.ValidationError) {
|
|
26
|
+
status = e instanceof koa_1.HttpError ? e.status : types_1.HttpCode.BadRequest;
|
|
27
|
+
message = e.message;
|
|
28
|
+
}
|
|
29
|
+
context.response.status = status;
|
|
30
|
+
context.response.body = { errors: [{ detail: message }] };
|
|
31
|
+
if (!this.options.isProduction) {
|
|
32
|
+
process.nextTick(() => this.debugLogError(context, e));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
debugLogError(context, error) {
|
|
37
|
+
const { request } = context;
|
|
38
|
+
const query = JSON.stringify(request.query, null, ' ')?.replace(/"/g, '');
|
|
39
|
+
console.error('');
|
|
40
|
+
console.error(`\x1b[33m===== An exception was raised =====\x1b[0m`);
|
|
41
|
+
console.error(`${request.method} \x1b[34m${request.path}\x1b[36m?${query}\x1b[0m`);
|
|
42
|
+
if (request.method === 'POST' || request.method === 'PUT' || request.method === 'PATCH') {
|
|
43
|
+
const body = JSON.stringify(request.body, null, ' ')?.replace(/"/g, '');
|
|
44
|
+
console.error('');
|
|
45
|
+
console.error(`Body \x1b[36m${body}\x1b[0m`);
|
|
46
|
+
}
|
|
47
|
+
console.error('');
|
|
48
|
+
console.error('\x1b[31m', error.message, '\x1b[0m');
|
|
49
|
+
console.error('');
|
|
50
|
+
console.error(error.stack);
|
|
51
|
+
console.error(`\x1b[33m===================================\x1b[0m`);
|
|
52
|
+
console.error('');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.default = ErrorHandling;
|
|
56
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItaGFuZGxpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYWdlbnQvcm91dGVzL3N5c3RlbS9lcnJvci1oYW5kbGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUErQztBQUMvQyx3RUFBa0U7QUFHbEUsdUNBQWtEO0FBQ2xELCtEQUFzQztBQUV0QyxNQUFxQixhQUFjLFNBQVEsb0JBQVM7SUFBcEQ7O1FBQ0UsU0FBSSxHQUFHLGlCQUFTLENBQUMsWUFBWSxDQUFDO0lBZ0RoQyxDQUFDO0lBOUNDLFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFnQixFQUFFLElBQVU7UUFDckQsSUFBSTtZQUNGLE1BQU0sSUFBSSxFQUFFLENBQUM7U0FDZDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxNQUFNLEdBQUcsZ0JBQVEsQ0FBQyxtQkFBbUIsQ0FBQztZQUMxQyxJQUFJLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQztZQUVqQyxJQUFJLENBQUMsWUFBWSxlQUFTLElBQUksQ0FBQyxZQUFZLG9DQUFlLEVBQUU7Z0JBQzFELE1BQU0sR0FBRyxDQUFDLFlBQVksZUFBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLFVBQVUsQ0FBQztnQkFDakUsT0FBTyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUM7YUFDckI7WUFFRCxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7WUFDakMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFFMUQsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFO2dCQUM5QixPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDeEQ7U0FDRjtJQUNILENBQUM7SUFFTyxhQUFhLENBQUMsT0FBZ0IsRUFBRSxLQUFZO1FBQ2xELE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFFNUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3BFLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxZQUFZLE9BQU8sQ0FBQyxJQUFJLFlBQVksS0FBSyxTQUFTLENBQUMsQ0FBQztRQUVuRixJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssT0FBTyxFQUFFO1lBQ3ZGLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN4RSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xCLE9BQU8sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLElBQUksU0FBUyxDQUFDLENBQUM7U0FDOUM7UUFFRCxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2xCLE9BQU8sQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDcEQsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNsQixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzQixPQUFPLENBQUMsS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDcEUsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUFqREQsZ0NBaURDIn0=
|
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhbHRoY2hlY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYWdlbnQvcm91dGVzL3N5c3RlbS9oZWFsdGhjaGVjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUdBLHVDQUFrRDtBQUNsRCwrREFBc0M7QUFFdEMsTUFBcUIsV0FBWSxTQUFRLG9CQUFTO0lBQWxEOztRQUNFLFNBQUksR0FBRyxpQkFBUyxDQUFDLFdBQVcsQ0FBQztJQVUvQixDQUFDO0lBUkMsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRU0sS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFZO1FBQ3JDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQztRQUNqRSxHQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxnQkFBUSxDQUFDLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUFYRCw4QkFXQyJ9
|
|
@@ -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,36 @@
|
|
|
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 types_2 = require("../../../types");
|
|
8
|
+
const base_route_1 = __importDefault(require("../base-route"));
|
|
9
|
+
class Logger extends base_route_1.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.type = types_1.RouteType.Logger;
|
|
13
|
+
}
|
|
14
|
+
setupRoutes(router) {
|
|
15
|
+
router.use(this.logger.bind(this));
|
|
16
|
+
}
|
|
17
|
+
async logger(context, next) {
|
|
18
|
+
const timer = Date.now();
|
|
19
|
+
try {
|
|
20
|
+
await next();
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
let logLevel = types_2.LoggerLevel.Info;
|
|
24
|
+
if (context.response.status >= types_1.HttpCode.BadRequest)
|
|
25
|
+
logLevel = types_2.LoggerLevel.Warn;
|
|
26
|
+
if (context.response.status >= types_1.HttpCode.InternalServerError)
|
|
27
|
+
logLevel = types_2.LoggerLevel.Error;
|
|
28
|
+
let message = `[${context.response.status}]`;
|
|
29
|
+
message += ` ${context.request.method} ${context.request.path}`;
|
|
30
|
+
message += ` - ${Date.now() - timer}ms`;
|
|
31
|
+
this.options?.logger(logLevel, message);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.default = Logger;
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FnZW50L3JvdXRlcy9zeXN0ZW0vbG9nZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBR0EsdUNBQWtEO0FBQ2xELDBDQUE2QztBQUM3QywrREFBc0M7QUFFdEMsTUFBcUIsTUFBTyxTQUFRLG9CQUFTO0lBQTdDOztRQUNFLFNBQUksR0FBRyxpQkFBUyxDQUFDLE1BQU0sQ0FBQztJQXVCMUIsQ0FBQztJQXJCQyxXQUFXLENBQUMsTUFBYztRQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVPLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBZ0IsRUFBRSxJQUFVO1FBQy9DLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUV6QixJQUFJO1lBQ0YsTUFBTSxJQUFJLEVBQUUsQ0FBQztTQUNkO2dCQUFTO1lBQ1IsSUFBSSxRQUFRLEdBQUcsbUJBQVcsQ0FBQyxJQUFJLENBQUM7WUFDaEMsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sSUFBSSxnQkFBUSxDQUFDLFVBQVU7Z0JBQUUsUUFBUSxHQUFHLG1CQUFXLENBQUMsSUFBSSxDQUFDO1lBQ2hGLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLElBQUksZ0JBQVEsQ0FBQyxtQkFBbUI7Z0JBQUUsUUFBUSxHQUFHLG1CQUFXLENBQUMsS0FBSyxDQUFDO1lBRTFGLElBQUksT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUM3QyxPQUFPLElBQUksSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2hFLE9BQU8sSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLElBQUksQ0FBQztZQUV4QyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDekM7SUFDSCxDQUFDO0NBQ0Y7QUF4QkQseUJBd0JDIn0=
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AgentOptionsWithDefaults } from '../types';
|
|
2
|
+
import PermissionService from './permissions';
|
|
3
|
+
import Serializer from './serializer';
|
|
4
|
+
export declare type ForestAdminHttpDriverServices = {
|
|
5
|
+
permissions: PermissionService;
|
|
6
|
+
serializer: Serializer;
|
|
7
|
+
};
|
|
8
|
+
declare const _default: (options: AgentOptionsWithDefaults) => ForestAdminHttpDriverServices;
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
exports.default = (options) => ({
|
|
9
|
+
permissions: new permissions_1.default(options),
|
|
10
|
+
serializer: new serializer_1.default(options),
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWdlbnQvc2VydmljZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSxnRUFBOEM7QUFDOUMsOERBQXNDO0FBT3RDLGtCQUFlLENBQUMsT0FBaUMsRUFBaUMsRUFBRSxDQUFDLENBQUM7SUFDcEYsV0FBVyxFQUFFLElBQUkscUJBQWlCLENBQUMsT0FBTyxDQUFDO0lBQzNDLFVBQVUsRUFBRSxJQUFJLG9CQUFVLENBQUMsT0FBTyxDQUFDO0NBQ3BDLENBQUMsQ0FBQyJ9
|
|
@@ -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
|