@forestadmin/agent 1.0.0-beta.23 → 1.0.0-beta.24
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# @forestadmin/agent [1.0.0-beta.24](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent@1.0.0-beta.23...@forestadmin/agent@1.0.0-beta.24) (2022-05-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **onboarding:** display better errors when the agent fails to start ([#294](https://github.com/ForestAdmin/agent-nodejs/issues/294)) ([03f756b](https://github.com/ForestAdmin/agent-nodejs/commit/03f756b9964ba5970d7f5be37b47956fbcf9c5f7))
|
|
7
|
+
|
|
1
8
|
# @forestadmin/agent [1.0.0-beta.23](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent@1.0.0-beta.22...@forestadmin/agent@1.0.0-beta.23) (2022-05-12)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -39,23 +39,34 @@ class ForestAdminHttpDriver {
|
|
|
39
39
|
if (this.status !== 'waiting') {
|
|
40
40
|
throw new Error('Agent cannot be restarted.');
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
try {
|
|
43
|
+
this.status = 'running';
|
|
44
|
+
// Build http application
|
|
45
|
+
const router = new router_1.default({ prefix: path_1.default.join('/', this.options.prefix) });
|
|
46
|
+
this.routes = (0, routes_1.default)(this.dataSource, this.options, this.services);
|
|
47
|
+
this.routes.forEach(route => route.setupRoutes(router));
|
|
48
|
+
await Promise.all(this.routes.map(route => route.bootstrap()));
|
|
49
|
+
this.app
|
|
50
|
+
.use((0, cors_1.default)({ credentials: true, maxAge: 24 * 3600, privateNetworkAccess: true }))
|
|
51
|
+
.use((0, koa_bodyparser_1.default)({ jsonLimit: '50mb' }))
|
|
52
|
+
.use(router.routes());
|
|
53
|
+
// Send schema to forestadmin-server (if relevant).
|
|
54
|
+
const schema = await emitter_1.default.getSerializedSchema(this.options, this.dataSource);
|
|
55
|
+
const schemaIsKnown = await forest_http_api_1.default.hasSchema(this.options, schema.meta.schemaFileHash);
|
|
56
|
+
if (!schemaIsKnown) {
|
|
57
|
+
this.options.logger('Info', 'Schema was updated, sending new version');
|
|
58
|
+
await forest_http_api_1.default.uploadSchema(this.options, schema);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.options.logger('Info', 'Schema was not updated since last run');
|
|
62
|
+
}
|
|
63
|
+
this.options.logger('Info', 'Started');
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
this.options.logger('Error', e.message);
|
|
67
|
+
this.status = 'done';
|
|
68
|
+
throw e;
|
|
57
69
|
}
|
|
58
|
-
this.options?.logger('Info', 'Started');
|
|
59
70
|
}
|
|
60
71
|
/**
|
|
61
72
|
* Tear down all routes (close open sockets, ...)
|
|
@@ -69,4 +80,4 @@ class ForestAdminHttpDriver {
|
|
|
69
80
|
}
|
|
70
81
|
}
|
|
71
82
|
exports.default = ForestAdminHttpDriver;
|
|
72
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZXN0YWRtaW4taHR0cC1kcml2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWdlbnQvZm9yZXN0YWRtaW4taHR0cC1kcml2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSw4Q0FBc0I7QUFDdEIseURBQWlDO0FBQ2pDLG9FQUF3QztBQUN4QyxxREFBNkI7QUFDN0IsZ0RBQXdCO0FBS3hCLDhFQUFvRDtBQUNwRCxzRkFBdUQ7QUFDdkQsNEVBQTBEO0FBQzFELHNEQUFrQztBQUNsQywwREFBeUU7QUFLekUsTUFBcUIscUJBQXFCO0lBa0J4QyxZQUFZLFVBQXNCLEVBQUUsT0FBcUI7UUFkbEQsV0FBTSxHQUFnQixFQUFFLENBQUM7UUFFZixRQUFHLEdBQUcsSUFBSSxhQUFHLEVBQUUsQ0FBQztRQUN6QixXQUFNLEdBQW1DLFNBQVMsQ0FBQztRQVl6RCxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsT0FBTyxHQUFHLDZCQUFZLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBQSxrQkFBWSxFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUzQyw2QkFBWSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQWZEOzs7O09BSUc7SUFDSCxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQVVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxLQUFLO1FBQ1QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7U0FDL0M7UUFFRCxJQUFJO1lBQ0YsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFFeEIs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
|
|
@@ -58,6 +58,7 @@ export default class ForestHttpApi {
|
|
|
58
58
|
private static decodeActionPermissions;
|
|
59
59
|
/** Helper to format permissions into something easy to validate against */
|
|
60
60
|
private static decodeScopePermissions;
|
|
61
|
+
private static handleResponseError;
|
|
61
62
|
}
|
|
62
63
|
export {};
|
|
63
64
|
//# sourceMappingURL=forest-http-api.d.ts.map
|
|
@@ -16,8 +16,8 @@ class ForestHttpApi {
|
|
|
16
16
|
const { attributes } = response.body.data;
|
|
17
17
|
return { isFeatureEnabled: attributes.use_ip_whitelist, ipRules: attributes.rules };
|
|
18
18
|
}
|
|
19
|
-
catch {
|
|
20
|
-
|
|
19
|
+
catch (e) {
|
|
20
|
+
this.handleResponseError(e);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
static async getOpenIdIssuerMetadata(options) {
|
|
@@ -27,8 +27,8 @@ class ForestHttpApi {
|
|
|
27
27
|
.set('forest-secret-key', options.envSecret);
|
|
28
28
|
return response.body;
|
|
29
29
|
}
|
|
30
|
-
catch {
|
|
31
|
-
|
|
30
|
+
catch (e) {
|
|
31
|
+
this.handleResponseError(e);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
static async getUserInformation(options, renderingId, accessToken) {
|
|
@@ -50,16 +50,21 @@ class ForestHttpApi {
|
|
|
50
50
|
renderingId,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
catch {
|
|
54
|
-
|
|
53
|
+
catch (e) {
|
|
54
|
+
this.handleResponseError(e);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
static async hasSchema(options, hash) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
try {
|
|
59
|
+
const response = await superagent_1.default
|
|
60
|
+
.post(new URL('/forest/apimaps/hashcheck', options.forestServerUrl).toString())
|
|
61
|
+
.send({ schemaFileHash: hash })
|
|
62
|
+
.set('forest-secret-key', options.envSecret);
|
|
63
|
+
return !response?.body?.sendSchema;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
this.handleResponseError(e);
|
|
67
|
+
}
|
|
63
68
|
}
|
|
64
69
|
static async uploadSchema(options, apimap) {
|
|
65
70
|
try {
|
|
@@ -69,48 +74,31 @@ class ForestHttpApi {
|
|
|
69
74
|
.set('forest-secret-key', options.envSecret);
|
|
70
75
|
}
|
|
71
76
|
catch (e) {
|
|
72
|
-
|
|
73
|
-
let message;
|
|
74
|
-
switch (e.response?.status) {
|
|
75
|
-
case 0:
|
|
76
|
-
message = 'Cannot send the apimap to Forest. Are you online?';
|
|
77
|
-
break;
|
|
78
|
-
case 404:
|
|
79
|
-
message =
|
|
80
|
-
'Cannot find the project related to the envSecret you configured. ' +
|
|
81
|
-
'Can you check on Forest that you copied it properly in the Forest initialization?';
|
|
82
|
-
break;
|
|
83
|
-
case 503:
|
|
84
|
-
message =
|
|
85
|
-
'Forest is in maintenance for a few minutes. ' +
|
|
86
|
-
'We are upgrading your experience in the forest. ' +
|
|
87
|
-
'We just need a few more minutes to get it right.';
|
|
88
|
-
break;
|
|
89
|
-
default:
|
|
90
|
-
message =
|
|
91
|
-
'An error occured with the apimap sent to Forest. ' +
|
|
92
|
-
'Please contact support@forestadmin.com for further investigations.';
|
|
93
|
-
}
|
|
94
|
-
throw new Error(message);
|
|
77
|
+
this.handleResponseError(e);
|
|
95
78
|
}
|
|
96
79
|
}
|
|
97
80
|
static async getPermissions(options, renderingId) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
81
|
+
try {
|
|
82
|
+
const { body } = await superagent_1.default
|
|
83
|
+
.get(`${options.forestServerUrl}/liana/v3/permissions`)
|
|
84
|
+
.set('forest-secret-key', options.envSecret)
|
|
85
|
+
.query(`renderingId=${renderingId}`);
|
|
86
|
+
if (!body.meta?.rolesACLActivated) {
|
|
87
|
+
throw new Error('Roles V2 are unsupported');
|
|
88
|
+
}
|
|
89
|
+
const actions = new Set();
|
|
90
|
+
const actionsByUser = {};
|
|
91
|
+
ForestHttpApi.decodeChartPermissions(body?.stats ?? {}, actions);
|
|
92
|
+
ForestHttpApi.decodeActionPermissions(body?.data?.collections ?? {}, actions, actionsByUser);
|
|
93
|
+
return {
|
|
94
|
+
actions,
|
|
95
|
+
actionsByUser,
|
|
96
|
+
scopes: ForestHttpApi.decodeScopePermissions(body?.data?.renderings?.[renderingId] ?? {}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
this.handleResponseError(e);
|
|
104
101
|
}
|
|
105
|
-
const actions = new Set();
|
|
106
|
-
const actionsByUser = {};
|
|
107
|
-
ForestHttpApi.decodeChartPermissions(body?.stats ?? {}, actions);
|
|
108
|
-
ForestHttpApi.decodeActionPermissions(body?.data?.collections ?? {}, actions, actionsByUser);
|
|
109
|
-
return {
|
|
110
|
-
actions,
|
|
111
|
-
actionsByUser,
|
|
112
|
-
scopes: ForestHttpApi.decodeScopePermissions(body?.data?.renderings?.[renderingId] ?? {}),
|
|
113
|
-
};
|
|
114
102
|
}
|
|
115
103
|
/** Helper to format permissions into something easy to validate against */
|
|
116
104
|
static decodeChartPermissions(chartsByType, actions) {
|
|
@@ -168,6 +156,26 @@ class ForestHttpApi {
|
|
|
168
156
|
}
|
|
169
157
|
return scopes;
|
|
170
158
|
}
|
|
159
|
+
static handleResponseError(e) {
|
|
160
|
+
if (/certificate/i.test(e.message))
|
|
161
|
+
throw new Error('ForestAdmin server TLS certificate cannot be verified. ' +
|
|
162
|
+
'Please check that your system time is set properly.');
|
|
163
|
+
if (e.response) {
|
|
164
|
+
const status = e?.response?.status;
|
|
165
|
+
// 0 == offline, 502 == bad gateway from proxy
|
|
166
|
+
if (status === 0 || status === 502)
|
|
167
|
+
throw new Error('Failed to reach ForestAdmin server. Are you online?');
|
|
168
|
+
if (status === 404)
|
|
169
|
+
throw new Error('ForestAdmin server failed to find the project related to the envSecret you configured.' +
|
|
170
|
+
' Can you check that you copied it properly in the Forest initialization?');
|
|
171
|
+
if (status === 503)
|
|
172
|
+
throw new Error('Forest is in maintenance for a few minutes. We are upgrading your experience in ' +
|
|
173
|
+
'the forest. We just need a few more minutes to get it right.');
|
|
174
|
+
throw new Error('An unexpected error occured while contacting the ForestAdmin server. ' +
|
|
175
|
+
'Please contact support@forestadmin.com for further investigations.');
|
|
176
|
+
}
|
|
177
|
+
throw e;
|
|
178
|
+
}
|
|
171
179
|
}
|
|
172
180
|
exports.default = ForestHttpApi;
|
|
173
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
181
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZXN0LWh0dHAtYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FnZW50L3V0aWxzL2ZvcmVzdC1odHRwLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHVEQUF1RDtBQUN2RCx3RUFBc0Y7QUFHdEYsOERBQXFDO0FBQ3JDLDREQUFpRTtBQXVDakUsTUFBcUIsYUFBYTtJQUNoQyxNQUFNLENBQUMsS0FBSyxDQUFDLDJCQUEyQixDQUN0QyxPQUFvQjtRQUVwQixJQUFJO1lBQ0YsTUFBTSxRQUFRLEdBQWEsTUFBTSxvQkFBVTtpQkFDeEMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLDhCQUE4QixFQUFFLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztpQkFDaEYsR0FBRyxDQUFDLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUUvQyxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFFMUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ3JGO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDN0I7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxPQUFvQjtRQUN2RCxJQUFJO1lBQ0YsTUFBTSxRQUFRLEdBQWEsTUFBTSxvQkFBVTtpQkFDeEMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLHdDQUF3QyxFQUFFLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztpQkFDMUYsR0FBRyxDQUFDLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUUvQyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUM7U0FDdEI7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM3QjtJQUNILENBQUM7SUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUM3QixPQUFvQixFQUNwQixXQUFtQixFQUNuQixXQUFtQjtRQUVuQixJQUFJO1lBQ0YsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLENBQ2pCLHdCQUF3QixXQUFXLGdCQUFnQixFQUNuRCxPQUFPLENBQUMsZUFBZSxDQUN4QixDQUFDO1lBRUYsTUFBTSxRQUFRLEdBQUcsTUFBTSxvQkFBVTtpQkFDOUIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztpQkFDbkIsR0FBRyxDQUFDLGNBQWMsRUFBRSxXQUFXLENBQUM7aUJBQ2hDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFL0MsTUFBTSxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUU5QyxPQUFPO2dCQUNMLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDO2dCQUNkLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztnQkFDdkIsU0FBUyxFQUFFLFVBQVUsQ0FBQyxVQUFVO2dCQUNoQyxRQUFRLEVBQUUsVUFBVSxDQUFDLFNBQVM7Z0JBQzlCLElBQUksRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDekIsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO2dCQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUN4RixXQUFXO2FBQ1osQ0FBQztTQUNIO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDN0I7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsT0FBb0IsRUFBRSxJQUFZO1FBQ3ZELElBQUk7WUFDRixNQUFNLFFBQVEsR0FBRyxNQUFNLG9CQUFVO2lCQUM5QixJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsMkJBQTJCLEVBQUUsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO2lCQUM5RSxJQUFJLENBQUMsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQzlCLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFL0MsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDO1NBQ3BDO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDN0I7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBb0IsRUFBRSxNQUF1QjtRQUNyRSxJQUFJO1lBQ0YsTUFBTSxvQkFBVTtpQkFDYixJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO2lCQUNwRSxJQUFJLENBQUMsTUFBTSxDQUFDO2lCQUNaLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDaEQ7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM3QjtJQUNILENBQUM7SUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FDekIsT0FBb0IsRUFDcEIsV0FBbUI7UUFFbkIsSUFBSTtZQUNGLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLG9CQUFVO2lCQUM5QixHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsZUFBZSx1QkFBdUIsQ0FBQztpQkFDdEQsR0FBRyxDQUFDLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUM7aUJBQzNDLEtBQUssQ0FBQyxlQUFlLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFFdkMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7Z0JBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQzthQUM3QztZQUVELE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7WUFDbEMsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO1lBRXpCLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLEVBQUUsS0FBSyxJQUFJLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNqRSxhQUFhLENBQUMsdUJBQXVCLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxXQUFXLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQztZQUU3RixPQUFPO2dCQUNMLE9BQU87Z0JBQ1AsYUFBYTtnQkFDYixNQUFNLEVBQUUsYUFBYSxDQUFDLHNCQUFzQixDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO2FBQzFGLENBQUM7U0FDSDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzdCO0lBQ0gsQ0FBQztJQUVELDJFQUEyRTtJQUNuRSxNQUFNLENBQUMsc0JBQXNCLENBQUMsWUFBaUIsRUFBRSxPQUFvQjtRQUMzRSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFNLFlBQVksQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzdELE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2hELElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtZQUNoQixPQUFPLEVBQUUsS0FBSyxDQUFDLE1BQU07WUFDckIsU0FBUyxFQUFFLEtBQUssQ0FBQyxVQUFVO1lBQzNCLGVBQWUsRUFBRSxLQUFLLENBQUMsa0JBQWtCO1lBQ3pDLFVBQVUsRUFBRSxLQUFLLENBQUMsa0JBQWtCO1lBQ3BDLFVBQVUsRUFBRSxLQUFLLENBQUMsU0FBUztZQUMzQixtQkFBbUIsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLElBQUk7WUFDOUUsY0FBYyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLElBQUksS0FBSyxDQUFDLGdCQUFnQixDQUFDLElBQUksSUFBSTtZQUN6RSxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7WUFDbEIsV0FBVyxFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQ2pDLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxxQkFBcUI7U0FDaEQsQ0FBQyxDQUFDLENBQUM7UUFFSixNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQ3hDLElBQUEscUJBQVUsRUFBQyxLQUFLLEVBQUU7WUFDaEIsV0FBVyxFQUFFLEtBQUs7WUFDbEIsV0FBVyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLElBQUksSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssU0FBUztTQUNwRSxDQUFDLENBQ0gsQ0FBQztRQUVGLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssTUFBTSxDQUFDLHVCQUF1QixDQUNwQyxXQUFnQixFQUNoQixPQUFvQixFQUNwQixhQUFvRDtRQUVwRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBTSxXQUFXLENBQUMsRUFBRTtZQUMvRCxLQUFLLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBTSxRQUFRLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFO2dCQUNsRixNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDaEYsSUFBSSxPQUFPLE9BQU8sS0FBSyxTQUFTO29CQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQzs7b0JBQ2pFLGFBQWEsQ0FBQyxHQUFHLFNBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFTLE9BQU8sQ0FBQyxDQUFDO2FBQ3ZFO1lBRUQsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQU0sUUFBUSxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUMsRUFBRTtnQkFDbkYsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLGNBQWMsQ0FBQztnQkFDM0MsSUFBSSxPQUFPLE9BQU8sS0FBSyxTQUFTO29CQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxVQUFVLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQzs7b0JBQ3pFLGFBQWEsQ0FBQyxVQUFVLFVBQVUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFTLE9BQU8sQ0FBQyxDQUFDO2FBQy9FO1NBQ0Y7SUFDSCxDQUFDO0lBRUQsMkVBQTJFO0lBQ25FLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxTQUFjO1FBQ2xELE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUVsQixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQU0sU0FBUyxDQUFDLEVBQUU7WUFDOUQsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssSUFBSTtnQkFDdEIsYUFBYSxFQUFFLHlDQUFvQixDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO2dCQUNqRSxrQkFBa0IsRUFBRSxLQUFLLENBQUMsbUJBQW1CLEVBQUUsS0FBSyxJQUFJLEVBQUU7YUFDM0QsQ0FBQztTQUNIO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFRO1FBQ3pDLElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQ2IseURBQXlEO2dCQUN2RCxxREFBcUQsQ0FDeEQsQ0FBQztRQUVKLElBQUssQ0FBbUIsQ0FBQyxRQUFRLEVBQUU7WUFDakMsTUFBTSxNQUFNLEdBQUksQ0FBbUIsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDO1lBRXRELDhDQUE4QztZQUM5QyxJQUFJLE1BQU0sS0FBSyxDQUFDLElBQUksTUFBTSxLQUFLLEdBQUc7Z0JBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztZQUV6RSxJQUFJLE1BQU0sS0FBSyxHQUFHO2dCQUNoQixNQUFNLElBQUksS0FBSyxDQUNiLHdGQUF3RjtvQkFDdEYsMEVBQTBFLENBQzdFLENBQUM7WUFFSixJQUFJLE1BQU0sS0FBSyxHQUFHO2dCQUNoQixNQUFNLElBQUksS0FBSyxDQUNiLGtGQUFrRjtvQkFDaEYsOERBQThELENBQ2pFLENBQUM7WUFFSixNQUFNLElBQUksS0FBSyxDQUNiLHVFQUF1RTtnQkFDckUsb0VBQW9FLENBQ3ZFLENBQUM7U0FDSDtRQUVELE1BQU0sQ0FBQyxDQUFDO0lBQ1YsQ0FBQztDQUNGO0FBeE5ELGdDQXdOQyJ9
|