@beiguancyc/parse-server 9.9.0-ruixiang.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 +176 -0
- package/NOTICE +10 -0
- package/README.md +1311 -0
- package/bin/parse-live-query-server +3 -0
- package/bin/parse-server +3 -0
- package/lib/AccountLockout.js +149 -0
- package/lib/Adapters/AdapterLoader.js +60 -0
- package/lib/Adapters/Analytics/AnalyticsAdapter.js +32 -0
- package/lib/Adapters/Auth/AuthAdapter.js +132 -0
- package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +119 -0
- package/lib/Adapters/Auth/OAuth1Client.js +204 -0
- package/lib/Adapters/Auth/apple.js +125 -0
- package/lib/Adapters/Auth/facebook.js +187 -0
- package/lib/Adapters/Auth/gcenter.js +217 -0
- package/lib/Adapters/Auth/github.js +125 -0
- package/lib/Adapters/Auth/google.js +122 -0
- package/lib/Adapters/Auth/gpgames.js +125 -0
- package/lib/Adapters/Auth/httpsRequest.js +41 -0
- package/lib/Adapters/Auth/index.js +248 -0
- package/lib/Adapters/Auth/instagram.js +118 -0
- package/lib/Adapters/Auth/janraincapture.js +85 -0
- package/lib/Adapters/Auth/janrainengage.js +57 -0
- package/lib/Adapters/Auth/keycloak.js +168 -0
- package/lib/Adapters/Auth/ldap.js +193 -0
- package/lib/Adapters/Auth/line.js +125 -0
- package/lib/Adapters/Auth/linkedin.js +117 -0
- package/lib/Adapters/Auth/meetup.js +44 -0
- package/lib/Adapters/Auth/mfa.js +334 -0
- package/lib/Adapters/Auth/microsoft.js +111 -0
- package/lib/Adapters/Auth/oauth2.js +115 -0
- package/lib/Adapters/Auth/phantauth.js +53 -0
- package/lib/Adapters/Auth/qq.js +113 -0
- package/lib/Adapters/Auth/spotify.js +115 -0
- package/lib/Adapters/Auth/twitter.js +197 -0
- package/lib/Adapters/Auth/utils.js +28 -0
- package/lib/Adapters/Auth/vkontakte.js +55 -0
- package/lib/Adapters/Auth/wechat.js +110 -0
- package/lib/Adapters/Auth/weibo.js +141 -0
- package/lib/Adapters/Cache/CacheAdapter.js +40 -0
- package/lib/Adapters/Cache/InMemoryCache.js +61 -0
- package/lib/Adapters/Cache/InMemoryCacheAdapter.js +34 -0
- package/lib/Adapters/Cache/LRUCache.js +35 -0
- package/lib/Adapters/Cache/NullCacheAdapter.js +26 -0
- package/lib/Adapters/Cache/RedisCacheAdapter.js +109 -0
- package/lib/Adapters/Cache/SchemaCache.js +25 -0
- package/lib/Adapters/Email/MailAdapter.js +32 -0
- package/lib/Adapters/Files/FilesAdapter.js +129 -0
- package/lib/Adapters/Files/GridFSBucketAdapter.js +280 -0
- package/lib/Adapters/Files/GridStoreAdapter.js +5 -0
- package/lib/Adapters/Logger/LoggerAdapter.js +27 -0
- package/lib/Adapters/Logger/WinstonLogger.js +107 -0
- package/lib/Adapters/Logger/WinstonLoggerAdapter.js +63 -0
- package/lib/Adapters/MessageQueue/EventEmitterMQ.js +55 -0
- package/lib/Adapters/PubSub/EventEmitterPubSub.js +53 -0
- package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
- package/lib/Adapters/PubSub/RedisPubSub.js +49 -0
- package/lib/Adapters/Push/PushAdapter.js +40 -0
- package/lib/Adapters/Storage/Mongo/MongoCollection.js +212 -0
- package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +334 -0
- package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +1047 -0
- package/lib/Adapters/Storage/Mongo/MongoTransform.js +1397 -0
- package/lib/Adapters/Storage/Postgres/PostgresClient.js +38 -0
- package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +73 -0
- package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +2409 -0
- package/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/array/add.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql +14 -0
- package/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql +14 -0
- package/lib/Adapters/Storage/Postgres/sql/array/contains.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/array/remove.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/index.js +32 -0
- package/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql +19 -0
- package/lib/Adapters/Storage/StorageAdapter.js +2 -0
- package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
- package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
- package/lib/Auth.js +687 -0
- package/lib/AuthDataLock.js +53 -0
- package/lib/ClientSDK.js +39 -0
- package/lib/Config.js +879 -0
- package/lib/Controllers/AdaptableController.js +72 -0
- package/lib/Controllers/AnalyticsController.js +43 -0
- package/lib/Controllers/CacheController.js +71 -0
- package/lib/Controllers/DatabaseController.js +1685 -0
- package/lib/Controllers/FilesController.js +122 -0
- package/lib/Controllers/HooksController.js +254 -0
- package/lib/Controllers/LiveQueryController.js +72 -0
- package/lib/Controllers/LoggerController.js +222 -0
- package/lib/Controllers/ParseGraphQLController.js +294 -0
- package/lib/Controllers/PushController.js +224 -0
- package/lib/Controllers/SchemaController.js +1563 -0
- package/lib/Controllers/UserController.js +364 -0
- package/lib/Controllers/index.js +251 -0
- package/lib/Controllers/types.js +2 -0
- package/lib/Deprecator/Deprecations.js +100 -0
- package/lib/Deprecator/Deprecator.js +140 -0
- package/lib/Error.js +50 -0
- package/lib/FileUrlValidator.js +69 -0
- package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
- package/lib/GraphQL/ParseGraphQLServer.js +241 -0
- package/lib/GraphQL/helpers/objectsMutations.js +30 -0
- package/lib/GraphQL/helpers/objectsQueries.js +246 -0
- package/lib/GraphQL/helpers/queryComplexity.js +138 -0
- package/lib/GraphQL/loaders/configMutations.js +87 -0
- package/lib/GraphQL/loaders/configQueries.js +79 -0
- package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
- package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
- package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1099 -0
- package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
- package/lib/GraphQL/loaders/filesMutations.js +107 -0
- package/lib/GraphQL/loaders/functionsMutations.js +77 -0
- package/lib/GraphQL/loaders/parseClassMutations.js +267 -0
- package/lib/GraphQL/loaders/parseClassQueries.js +126 -0
- package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
- package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
- package/lib/GraphQL/loaders/schemaMutations.js +161 -0
- package/lib/GraphQL/loaders/schemaQueries.js +80 -0
- package/lib/GraphQL/loaders/schemaTypes.js +341 -0
- package/lib/GraphQL/loaders/usersMutations.js +433 -0
- package/lib/GraphQL/loaders/usersQueries.js +90 -0
- package/lib/GraphQL/parseGraphQLUtils.js +71 -0
- package/lib/GraphQL/transformers/className.js +14 -0
- package/lib/GraphQL/transformers/constraintType.js +53 -0
- package/lib/GraphQL/transformers/inputType.js +51 -0
- package/lib/GraphQL/transformers/mutation.js +280 -0
- package/lib/GraphQL/transformers/outputType.js +51 -0
- package/lib/GraphQL/transformers/query.js +237 -0
- package/lib/GraphQL/transformers/schemaFields.js +99 -0
- package/lib/InstallationDedup.js +178 -0
- package/lib/KeyPromiseQueue.js +48 -0
- package/lib/LiveQuery/Client.js +90 -0
- package/lib/LiveQuery/Id.js +20 -0
- package/lib/LiveQuery/ParseCloudCodePublisher.js +54 -0
- package/lib/LiveQuery/ParseLiveQueryServer.js +1071 -0
- package/lib/LiveQuery/ParsePubSub.js +37 -0
- package/lib/LiveQuery/ParseWebSocketServer.js +66 -0
- package/lib/LiveQuery/QueryTools.js +443 -0
- package/lib/LiveQuery/RequestSchema.js +161 -0
- package/lib/LiveQuery/SessionTokenCache.js +51 -0
- package/lib/LiveQuery/Subscription.js +47 -0
- package/lib/LiveQuery/equalObjects.js +50 -0
- package/lib/Options/Definitions.js +1599 -0
- package/lib/Options/docs.js +389 -0
- package/lib/Options/index.js +12 -0
- package/lib/Options/parsers.js +89 -0
- package/lib/Page.js +44 -0
- package/lib/ParseMessageQueue.js +24 -0
- package/lib/ParseServer.js +632 -0
- package/lib/ParseServerRESTController.js +173 -0
- package/lib/PromiseRouter.js +208 -0
- package/lib/Push/PushQueue.js +67 -0
- package/lib/Push/PushWorker.js +101 -0
- package/lib/Push/utils.js +129 -0
- package/lib/RestQuery.js +1208 -0
- package/lib/RestWrite.js +1671 -0
- package/lib/Routers/AggregateRouter.js +150 -0
- package/lib/Routers/AnalyticsRouter.js +26 -0
- package/lib/Routers/AudiencesRouter.js +54 -0
- package/lib/Routers/ClassesRouter.js +191 -0
- package/lib/Routers/CloudCodeRouter.js +87 -0
- package/lib/Routers/FeaturesRouter.js +72 -0
- package/lib/Routers/FilesRouter.js +772 -0
- package/lib/Routers/FunctionsRouter.js +341 -0
- package/lib/Routers/GlobalConfigRouter.js +123 -0
- package/lib/Routers/GraphQLRouter.js +41 -0
- package/lib/Routers/HooksRouter.js +121 -0
- package/lib/Routers/IAPValidationRouter.js +113 -0
- package/lib/Routers/InstallationsRouter.js +46 -0
- package/lib/Routers/LogsRouter.js +57 -0
- package/lib/Routers/PagesRouter.js +676 -0
- package/lib/Routers/PurgeRouter.js +45 -0
- package/lib/Routers/PushRouter.js +75 -0
- package/lib/Routers/RolesRouter.js +33 -0
- package/lib/Routers/SchemasRouter.js +118 -0
- package/lib/Routers/SecurityRouter.js +34 -0
- package/lib/Routers/SessionsRouter.js +126 -0
- package/lib/Routers/UsersRouter.js +733 -0
- package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
- package/lib/SchemaMigrations/Migrations.js +30 -0
- package/lib/Security/Check.js +109 -0
- package/lib/Security/CheckGroup.js +44 -0
- package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
- package/lib/Security/CheckGroups/CheckGroupServerConfig.js +160 -0
- package/lib/Security/CheckGroups/CheckGroups.js +21 -0
- package/lib/Security/CheckRunner.js +213 -0
- package/lib/SharedRest.js +34 -0
- package/lib/StatusHandler.js +329 -0
- package/lib/TestUtils.js +87 -0
- package/lib/Utils.js +577 -0
- package/lib/batch.js +185 -0
- package/lib/cache.js +12 -0
- package/lib/cli/definitions/parse-live-query-server.js +9 -0
- package/lib/cli/definitions/parse-server.js +9 -0
- package/lib/cli/parse-live-query-server.js +14 -0
- package/lib/cli/parse-server.js +101 -0
- package/lib/cli/utils/commander.js +132 -0
- package/lib/cli/utils/runner.js +53 -0
- package/lib/cloud-code/Parse.Cloud.js +797 -0
- package/lib/cloud-code/Parse.Server.js +21 -0
- package/lib/cryptoUtils.js +54 -0
- package/lib/defaults.js +58 -0
- package/lib/deprecated.js +12 -0
- package/lib/index.js +89 -0
- package/lib/logger.js +40 -0
- package/lib/middlewares.js +810 -0
- package/lib/password.js +40 -0
- package/lib/request.js +175 -0
- package/lib/requiredParameter.js +11 -0
- package/lib/rest.js +264 -0
- package/lib/triggers.js +949 -0
- package/lib/vendor/README.md +8 -0
- package/lib/vendor/mongodbUrl.js +1012 -0
- package/package.json +172 -0
- package/postinstall.js +38 -0
- package/public/custom_json.html +17 -0
- package/public/custom_json.json +23 -0
- package/public/custom_page.html +15 -0
- package/public/de/email_verification_link_expired.html +24 -0
- package/public/de/email_verification_link_invalid.html +21 -0
- package/public/de/email_verification_send_fail.html +21 -0
- package/public/de/email_verification_send_success.html +19 -0
- package/public/de/email_verification_success.html +18 -0
- package/public/de/password_reset.html +65 -0
- package/public/de/password_reset_link_invalid.html +19 -0
- package/public/de/password_reset_success.html +18 -0
- package/public/de-AT/email_verification_link_expired.html +24 -0
- package/public/de-AT/email_verification_link_invalid.html +21 -0
- package/public/de-AT/email_verification_send_fail.html +21 -0
- package/public/de-AT/email_verification_send_success.html +19 -0
- package/public/de-AT/email_verification_success.html +18 -0
- package/public/de-AT/password_reset.html +65 -0
- package/public/de-AT/password_reset_link_invalid.html +19 -0
- package/public/de-AT/password_reset_success.html +18 -0
- package/public/email_verification_link_expired.html +24 -0
- package/public/email_verification_link_invalid.html +21 -0
- package/public/email_verification_send_fail.html +21 -0
- package/public/email_verification_send_success.html +19 -0
- package/public/email_verification_success.html +18 -0
- package/public/password_reset.html +65 -0
- package/public/password_reset_link_invalid.html +19 -0
- package/public/password_reset_success.html +18 -0
- package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
- package/types/@types/deepcopy/index.d.ts +5 -0
- package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
- package/types/Options/index.d.ts +320 -0
- package/types/ParseServer.d.ts +65 -0
- package/types/eslint.config.mjs +30 -0
- package/types/index.d.ts +21 -0
- package/types/logger.d.ts +2 -0
- package/types/tests.ts +44 -0
- package/types/tsconfig.json +24 -0
- package/views/choose_password +215 -0
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.PagesRouter = void 0;
|
|
7
|
+
var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter"));
|
|
8
|
+
var _Config = _interopRequireDefault(require("../Config"));
|
|
9
|
+
var _express = _interopRequireDefault(require("express"));
|
|
10
|
+
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
var _fs = require("fs");
|
|
12
|
+
var _node = require("parse/node");
|
|
13
|
+
var _Utils = _interopRequireDefault(require("../Utils"));
|
|
14
|
+
var _mustache = _interopRequireDefault(require("mustache"));
|
|
15
|
+
var _Page = _interopRequireDefault(require("../Page"));
|
|
16
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
// All pages with custom page key for reference and file name
|
|
18
|
+
const pages = Object.freeze({
|
|
19
|
+
passwordReset: new _Page.default({
|
|
20
|
+
id: 'passwordReset',
|
|
21
|
+
defaultFile: 'password_reset.html'
|
|
22
|
+
}),
|
|
23
|
+
passwordResetSuccess: new _Page.default({
|
|
24
|
+
id: 'passwordResetSuccess',
|
|
25
|
+
defaultFile: 'password_reset_success.html'
|
|
26
|
+
}),
|
|
27
|
+
passwordResetLinkInvalid: new _Page.default({
|
|
28
|
+
id: 'passwordResetLinkInvalid',
|
|
29
|
+
defaultFile: 'password_reset_link_invalid.html'
|
|
30
|
+
}),
|
|
31
|
+
emailVerificationSuccess: new _Page.default({
|
|
32
|
+
id: 'emailVerificationSuccess',
|
|
33
|
+
defaultFile: 'email_verification_success.html'
|
|
34
|
+
}),
|
|
35
|
+
emailVerificationSendFail: new _Page.default({
|
|
36
|
+
id: 'emailVerificationSendFail',
|
|
37
|
+
defaultFile: 'email_verification_send_fail.html'
|
|
38
|
+
}),
|
|
39
|
+
emailVerificationSendSuccess: new _Page.default({
|
|
40
|
+
id: 'emailVerificationSendSuccess',
|
|
41
|
+
defaultFile: 'email_verification_send_success.html'
|
|
42
|
+
}),
|
|
43
|
+
emailVerificationLinkInvalid: new _Page.default({
|
|
44
|
+
id: 'emailVerificationLinkInvalid',
|
|
45
|
+
defaultFile: 'email_verification_link_invalid.html'
|
|
46
|
+
}),
|
|
47
|
+
emailVerificationLinkExpired: new _Page.default({
|
|
48
|
+
id: 'emailVerificationLinkExpired',
|
|
49
|
+
defaultFile: 'email_verification_link_expired.html'
|
|
50
|
+
})
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// All page parameters for reference to be used as template placeholders or query params
|
|
54
|
+
const pageParams = Object.freeze({
|
|
55
|
+
appName: 'appName',
|
|
56
|
+
appId: 'appId',
|
|
57
|
+
token: 'token',
|
|
58
|
+
username: 'username',
|
|
59
|
+
error: 'error',
|
|
60
|
+
locale: 'locale',
|
|
61
|
+
publicServerUrl: 'publicServerUrl'
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// The header prefix to add page params as response headers
|
|
65
|
+
const pageParamHeaderPrefix = 'x-parse-page-param-';
|
|
66
|
+
|
|
67
|
+
// The errors being thrown
|
|
68
|
+
const errors = Object.freeze({
|
|
69
|
+
jsonFailedFileLoading: 'failed to load JSON file',
|
|
70
|
+
fileOutsideAllowedScope: 'not allowed to read file outside of pages directory'
|
|
71
|
+
});
|
|
72
|
+
class PagesRouter extends _PromiseRouter.default {
|
|
73
|
+
/**
|
|
74
|
+
* Constructs a PagesRouter.
|
|
75
|
+
* @param {Object} pages The pages options from the Parse Server configuration.
|
|
76
|
+
*/
|
|
77
|
+
constructor(pages = {}) {
|
|
78
|
+
super();
|
|
79
|
+
|
|
80
|
+
// Set instance properties
|
|
81
|
+
this.pagesConfig = pages;
|
|
82
|
+
this.pagesEndpoint = pages.pagesEndpoint ? pages.pagesEndpoint : 'apps';
|
|
83
|
+
this.pagesPath = pages.pagesPath ? _path.default.resolve('./', pages.pagesPath) : _path.default.resolve(__dirname, '../../public');
|
|
84
|
+
this.loadJsonResource();
|
|
85
|
+
this.mountPagesRoutes();
|
|
86
|
+
this.mountCustomRoutes();
|
|
87
|
+
this.mountStaticRoute();
|
|
88
|
+
}
|
|
89
|
+
verifyEmail(req) {
|
|
90
|
+
const config = req.config;
|
|
91
|
+
const {
|
|
92
|
+
token: rawToken
|
|
93
|
+
} = req.query;
|
|
94
|
+
const token = typeof rawToken === 'string' ? rawToken : undefined;
|
|
95
|
+
if (!config) {
|
|
96
|
+
this.invalidRequest();
|
|
97
|
+
}
|
|
98
|
+
if (!token) {
|
|
99
|
+
return this.goToPage(req, pages.emailVerificationLinkInvalid);
|
|
100
|
+
}
|
|
101
|
+
const userController = config.userController;
|
|
102
|
+
return userController.verifyEmail(token).then(() => {
|
|
103
|
+
return this.goToPage(req, pages.emailVerificationSuccess);
|
|
104
|
+
}, () => {
|
|
105
|
+
return this.goToPage(req, pages.emailVerificationLinkInvalid);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
resendVerificationEmail(req) {
|
|
109
|
+
const config = req.config;
|
|
110
|
+
const username = req.body?.username;
|
|
111
|
+
const rawToken = req.body?.token;
|
|
112
|
+
const token = typeof rawToken === 'string' ? rawToken : undefined;
|
|
113
|
+
if (!config) {
|
|
114
|
+
this.invalidRequest();
|
|
115
|
+
}
|
|
116
|
+
if (!username && !token) {
|
|
117
|
+
return this.goToPage(req, pages.emailVerificationLinkInvalid);
|
|
118
|
+
}
|
|
119
|
+
const userController = config.userController;
|
|
120
|
+
const suppressError = config.emailVerifySuccessOnInvalidEmail ?? true;
|
|
121
|
+
return userController.resendVerificationEmail(username, req, token).then(() => {
|
|
122
|
+
return this.goToPage(req, pages.emailVerificationSendSuccess);
|
|
123
|
+
}, () => {
|
|
124
|
+
if (suppressError) {
|
|
125
|
+
return this.goToPage(req, pages.emailVerificationSendSuccess);
|
|
126
|
+
}
|
|
127
|
+
return this.goToPage(req, pages.emailVerificationSendFail);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
passwordReset(req) {
|
|
131
|
+
const config = req.config;
|
|
132
|
+
const params = {
|
|
133
|
+
[pageParams.appId]: req.params.appId,
|
|
134
|
+
[pageParams.appName]: config.appName,
|
|
135
|
+
[pageParams.token]: req.query.token,
|
|
136
|
+
[pageParams.username]: req.query.username,
|
|
137
|
+
[pageParams.publicServerUrl]: config.publicServerURL
|
|
138
|
+
};
|
|
139
|
+
return this.goToPage(req, pages.passwordReset, params);
|
|
140
|
+
}
|
|
141
|
+
requestResetPassword(req) {
|
|
142
|
+
const config = req.config;
|
|
143
|
+
if (!config) {
|
|
144
|
+
this.invalidRequest();
|
|
145
|
+
}
|
|
146
|
+
const {
|
|
147
|
+
token: rawToken
|
|
148
|
+
} = req.query;
|
|
149
|
+
const token = typeof rawToken === 'string' ? rawToken : undefined;
|
|
150
|
+
if (!token) {
|
|
151
|
+
return this.goToPage(req, pages.passwordResetLinkInvalid);
|
|
152
|
+
}
|
|
153
|
+
return config.userController.checkResetTokenValidity(token).then(() => {
|
|
154
|
+
const params = {
|
|
155
|
+
[pageParams.token]: token,
|
|
156
|
+
[pageParams.appId]: config.applicationId,
|
|
157
|
+
[pageParams.appName]: config.appName
|
|
158
|
+
};
|
|
159
|
+
return this.goToPage(req, pages.passwordReset, params);
|
|
160
|
+
}, () => {
|
|
161
|
+
return this.goToPage(req, pages.passwordResetLinkInvalid);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
resetPassword(req) {
|
|
165
|
+
const config = req.config;
|
|
166
|
+
if (!config) {
|
|
167
|
+
this.invalidRequest();
|
|
168
|
+
}
|
|
169
|
+
const {
|
|
170
|
+
new_password,
|
|
171
|
+
token: rawToken
|
|
172
|
+
} = req.body || {};
|
|
173
|
+
const token = typeof rawToken === 'string' ? rawToken : undefined;
|
|
174
|
+
if ((!token || !new_password) && req.xhr === false) {
|
|
175
|
+
return this.goToPage(req, pages.passwordResetLinkInvalid);
|
|
176
|
+
}
|
|
177
|
+
if (!token) {
|
|
178
|
+
throw new _node.Parse.Error(_node.Parse.Error.OTHER_CAUSE, 'Missing token');
|
|
179
|
+
}
|
|
180
|
+
if (!new_password) {
|
|
181
|
+
throw new _node.Parse.Error(_node.Parse.Error.PASSWORD_MISSING, 'Missing password');
|
|
182
|
+
}
|
|
183
|
+
return config.userController.updatePassword(token, new_password).then(() => {
|
|
184
|
+
return Promise.resolve({
|
|
185
|
+
success: true
|
|
186
|
+
});
|
|
187
|
+
}, err => {
|
|
188
|
+
return Promise.resolve({
|
|
189
|
+
success: false,
|
|
190
|
+
err
|
|
191
|
+
});
|
|
192
|
+
}).then(result => {
|
|
193
|
+
if (req.xhr) {
|
|
194
|
+
if (result.success) {
|
|
195
|
+
return Promise.resolve({
|
|
196
|
+
status: 200,
|
|
197
|
+
response: 'Password successfully reset'
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (result.err) {
|
|
201
|
+
throw new _node.Parse.Error(_node.Parse.Error.OTHER_CAUSE, `${result.err}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const query = result.success ? {} : {
|
|
205
|
+
[pageParams.token]: token,
|
|
206
|
+
[pageParams.appId]: config.applicationId,
|
|
207
|
+
[pageParams.error]: result.err,
|
|
208
|
+
[pageParams.appName]: config.appName
|
|
209
|
+
};
|
|
210
|
+
if (result?.err === 'The password reset link has expired') {
|
|
211
|
+
delete query[pageParams.token];
|
|
212
|
+
query[pageParams.token] = token;
|
|
213
|
+
}
|
|
214
|
+
const page = result.success ? pages.passwordResetSuccess : pages.passwordReset;
|
|
215
|
+
return this.goToPage(req, page, query, false);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Returns page content if the page is a local file or returns a
|
|
221
|
+
* redirect to a custom page.
|
|
222
|
+
* @param {Object} req The express request.
|
|
223
|
+
* @param {Page} page The page to go to.
|
|
224
|
+
* @param {Object} [params={}] The query parameters to attach to the URL in case of
|
|
225
|
+
* HTTP redirect responses for POST requests, or the placeholders to fill into
|
|
226
|
+
* the response content in case of HTTP content responses for GET requests.
|
|
227
|
+
* @param {Boolean} [responseType] Is true if a redirect response should be forced,
|
|
228
|
+
* false if a content response should be forced, undefined if the response type
|
|
229
|
+
* should depend on the request type by default:
|
|
230
|
+
* - GET request -> content response
|
|
231
|
+
* - POST request -> redirect response (PRG pattern)
|
|
232
|
+
* @returns {Promise<Object>} The PromiseRouter response.
|
|
233
|
+
*/
|
|
234
|
+
goToPage(req, page, params = {}, responseType) {
|
|
235
|
+
const config = req.config;
|
|
236
|
+
|
|
237
|
+
// Determine redirect either by force, response setting or request method
|
|
238
|
+
const redirect = config.pages.forceRedirect ? true : responseType !== undefined ? responseType : req.method == 'POST';
|
|
239
|
+
|
|
240
|
+
// Include default parameters
|
|
241
|
+
const defaultParams = this.getDefaultParams(config);
|
|
242
|
+
if (Object.values(defaultParams).includes(undefined)) {
|
|
243
|
+
return this.notFound();
|
|
244
|
+
}
|
|
245
|
+
params = Object.assign(params, defaultParams);
|
|
246
|
+
|
|
247
|
+
// Add locale to params to ensure it is passed on with every request;
|
|
248
|
+
// that means, once a locale is set, it is passed on to any follow-up page,
|
|
249
|
+
// e.g. request_password_reset -> password_reset -> password_reset_success
|
|
250
|
+
const locale = this.getLocale(req);
|
|
251
|
+
params[pageParams.locale] = locale;
|
|
252
|
+
|
|
253
|
+
// Compose paths and URLs
|
|
254
|
+
const defaultFile = page.defaultFile;
|
|
255
|
+
const defaultPath = this.defaultPagePath(defaultFile);
|
|
256
|
+
const defaultUrl = this.composePageUrl(defaultFile, config.publicServerURL);
|
|
257
|
+
|
|
258
|
+
// If custom URL is set redirect to it without localization
|
|
259
|
+
const customUrl = config.pages.customUrls[page.id];
|
|
260
|
+
if (customUrl && !_Utils.default.isPath(customUrl)) {
|
|
261
|
+
return this.redirectResponse(customUrl, params);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Get JSON placeholders
|
|
265
|
+
let placeholders = {};
|
|
266
|
+
if (config.pages.enableLocalization && config.pages.localizationJsonPath) {
|
|
267
|
+
placeholders = this.getJsonPlaceholders(locale, params);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Send response
|
|
271
|
+
if (config.pages.enableLocalization && locale) {
|
|
272
|
+
return _Utils.default.getLocalizedPath(defaultPath, locale).then(({
|
|
273
|
+
path,
|
|
274
|
+
subdir
|
|
275
|
+
}) => redirect ? this.redirectResponse(this.composePageUrl(defaultFile, config.publicServerURL, subdir), params) : this.pageResponse(path, params, placeholders));
|
|
276
|
+
} else {
|
|
277
|
+
return redirect ? this.redirectResponse(defaultUrl, params) : this.pageResponse(defaultPath, params, placeholders);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Serves a request to a static resource and localizes the resource if it
|
|
283
|
+
* is a HTML file.
|
|
284
|
+
* @param {Object} req The request object.
|
|
285
|
+
* @returns {Promise<Object>} The response.
|
|
286
|
+
*/
|
|
287
|
+
staticRoute(req) {
|
|
288
|
+
// Get requested path
|
|
289
|
+
const relativePath = req.params['resource'][0];
|
|
290
|
+
|
|
291
|
+
// Resolve requested path to absolute path
|
|
292
|
+
const absolutePath = _path.default.resolve(this.pagesPath, relativePath);
|
|
293
|
+
|
|
294
|
+
// If the requested file is not a HTML file send its raw content
|
|
295
|
+
if (!absolutePath || !absolutePath.endsWith('.html')) {
|
|
296
|
+
return this.fileResponse(absolutePath);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Get parameters
|
|
300
|
+
const params = this.getDefaultParams(req.config);
|
|
301
|
+
const locale = this.getLocale(req);
|
|
302
|
+
if (locale) {
|
|
303
|
+
params.locale = locale;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Get JSON placeholders
|
|
307
|
+
const placeholders = this.getJsonPlaceholders(locale, params);
|
|
308
|
+
return this.pageResponse(absolutePath, params, placeholders);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Returns a translation from the JSON resource for a given locale. The JSON
|
|
313
|
+
* resource is parsed according to i18next syntax.
|
|
314
|
+
*
|
|
315
|
+
* Example JSON content:
|
|
316
|
+
* ```js
|
|
317
|
+
* {
|
|
318
|
+
* "en": { // resource for language `en` (English)
|
|
319
|
+
* "translation": {
|
|
320
|
+
* "greeting": "Hello!"
|
|
321
|
+
* }
|
|
322
|
+
* },
|
|
323
|
+
* "de": { // resource for language `de` (German)
|
|
324
|
+
* "translation": {
|
|
325
|
+
* "greeting": "Hallo!"
|
|
326
|
+
* }
|
|
327
|
+
* }
|
|
328
|
+
* "de-CH": { // resource for locale `de-CH` (Swiss German)
|
|
329
|
+
* "translation": {
|
|
330
|
+
* "greeting": "Grüezi!"
|
|
331
|
+
* }
|
|
332
|
+
* }
|
|
333
|
+
* }
|
|
334
|
+
* ```
|
|
335
|
+
* @param {String} locale The locale to translate to.
|
|
336
|
+
* @returns {Object} The translation or an empty object if no matching
|
|
337
|
+
* translation was found.
|
|
338
|
+
*/
|
|
339
|
+
getJsonTranslation(locale) {
|
|
340
|
+
// If there is no JSON resource
|
|
341
|
+
if (this.jsonParameters === undefined) {
|
|
342
|
+
return {};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// If locale is not set use the fallback locale
|
|
346
|
+
locale = locale || this.pagesConfig.localizationFallbackLocale;
|
|
347
|
+
|
|
348
|
+
// Get matching translation by locale, language or fallback locale
|
|
349
|
+
const language = locale.split('-')[0];
|
|
350
|
+
const resource = this.jsonParameters[locale] || this.jsonParameters[language] || this.jsonParameters[this.pagesConfig.localizationFallbackLocale] || {};
|
|
351
|
+
const translation = resource.translation || {};
|
|
352
|
+
return translation;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Returns a translation from the JSON resource for a given locale with
|
|
357
|
+
* placeholders filled in by given parameters.
|
|
358
|
+
* @param {String} locale The locale to translate to.
|
|
359
|
+
* @param {Object} params The parameters to fill into any placeholders
|
|
360
|
+
* within the translations.
|
|
361
|
+
* @returns {Object} The translation or an empty object if no matching
|
|
362
|
+
* translation was found.
|
|
363
|
+
*/
|
|
364
|
+
getJsonPlaceholders(locale, params = {}) {
|
|
365
|
+
// If localization is disabled or there is no JSON resource
|
|
366
|
+
if (!this.pagesConfig.enableLocalization || !this.pagesConfig.localizationJsonPath) {
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Get JSON placeholders
|
|
371
|
+
let placeholders = this.getJsonTranslation(locale);
|
|
372
|
+
|
|
373
|
+
// Fill in any placeholders in the translation; this allows a translation
|
|
374
|
+
// to contain default placeholders like {{appName}} which are filled here
|
|
375
|
+
placeholders = JSON.stringify(placeholders);
|
|
376
|
+
placeholders = _mustache.default.render(placeholders, params);
|
|
377
|
+
placeholders = JSON.parse(placeholders);
|
|
378
|
+
return placeholders;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Creates a response with file content.
|
|
383
|
+
* @param {String} path The path of the file to return.
|
|
384
|
+
* @param {Object} [params={}] The parameters to be included in the response
|
|
385
|
+
* header. These will also be used to fill placeholders.
|
|
386
|
+
* @param {Object} [placeholders={}] The placeholders to fill in the content.
|
|
387
|
+
* These will not be included in the response header.
|
|
388
|
+
* @returns {Object} The Promise Router response.
|
|
389
|
+
*/
|
|
390
|
+
async pageResponse(path, params = {}, placeholders = {}) {
|
|
391
|
+
// Get file content
|
|
392
|
+
let data;
|
|
393
|
+
try {
|
|
394
|
+
data = await this.readFile(path);
|
|
395
|
+
} catch {
|
|
396
|
+
return this.notFound();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Get config placeholders; can be an object, a function or an async function
|
|
400
|
+
let configPlaceholders = typeof this.pagesConfig.placeholders === 'function' ? this.pagesConfig.placeholders(params) : Object.prototype.toString.call(this.pagesConfig.placeholders) === '[object Object]' ? this.pagesConfig.placeholders : {};
|
|
401
|
+
if (_Utils.default.isPromise(configPlaceholders)) {
|
|
402
|
+
configPlaceholders = await configPlaceholders;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Fill placeholders
|
|
406
|
+
const allPlaceholders = Object.assign({}, configPlaceholders, placeholders);
|
|
407
|
+
const paramsAndPlaceholders = Object.assign({}, params, allPlaceholders);
|
|
408
|
+
data = _mustache.default.render(data, paramsAndPlaceholders);
|
|
409
|
+
|
|
410
|
+
// Add placeholders in header to allow parsing for programmatic use
|
|
411
|
+
// of response, instead of having to parse the HTML content.
|
|
412
|
+
const headers = this.composePageParamHeaders(params);
|
|
413
|
+
return {
|
|
414
|
+
text: data,
|
|
415
|
+
headers: headers
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Creates a response with file content.
|
|
421
|
+
* @param {String} path The path of the file to return.
|
|
422
|
+
* @returns {Object} The PromiseRouter response.
|
|
423
|
+
*/
|
|
424
|
+
async fileResponse(path) {
|
|
425
|
+
// Get file content
|
|
426
|
+
let data;
|
|
427
|
+
try {
|
|
428
|
+
data = await this.readFile(path);
|
|
429
|
+
} catch {
|
|
430
|
+
return this.notFound();
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
text: data
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Reads and returns the content of a file at a given path. File reading to
|
|
439
|
+
* serve content on the static route is only allowed from the pages
|
|
440
|
+
* directory on downwards.
|
|
441
|
+
* -----------------------------------------------------------------------
|
|
442
|
+
* **WARNING:** All file reads in the PagesRouter must be executed by this
|
|
443
|
+
* wrapper because it also detects and prevents common exploits.
|
|
444
|
+
* -----------------------------------------------------------------------
|
|
445
|
+
* @param {String} filePath The path to the file to read.
|
|
446
|
+
* @returns {Promise<String>} The file content.
|
|
447
|
+
*/
|
|
448
|
+
async readFile(filePath) {
|
|
449
|
+
// Normalize path to prevent it from containing any directory changing
|
|
450
|
+
// UNIX patterns which could expose the whole file system, e.g.
|
|
451
|
+
// `http://example.com/parse/apps/../file.txt` requests a file outside
|
|
452
|
+
// of the pages directory scope.
|
|
453
|
+
const normalizedPath = _path.default.normalize(filePath);
|
|
454
|
+
|
|
455
|
+
// Abort if the path is outside of the path directory scope
|
|
456
|
+
if (!normalizedPath.startsWith(this.pagesPath + _path.default.sep)) {
|
|
457
|
+
throw errors.fileOutsideAllowedScope;
|
|
458
|
+
}
|
|
459
|
+
return await _fs.promises.readFile(normalizedPath, 'utf-8');
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Loads a language resource JSON file that is used for translations.
|
|
464
|
+
*/
|
|
465
|
+
loadJsonResource() {
|
|
466
|
+
if (this.pagesConfig.localizationJsonPath === undefined) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
const json = require(_path.default.resolve('./', this.pagesConfig.localizationJsonPath));
|
|
471
|
+
this.jsonParameters = json;
|
|
472
|
+
} catch {
|
|
473
|
+
throw errors.jsonFailedFileLoading;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Extracts and returns the page default parameters from the Parse Server
|
|
479
|
+
* configuration. These parameters are made accessible in every page served
|
|
480
|
+
* by this router.
|
|
481
|
+
* @param {Object} config The Parse Server configuration.
|
|
482
|
+
* @returns {Object} The default parameters.
|
|
483
|
+
*/
|
|
484
|
+
getDefaultParams(config) {
|
|
485
|
+
return config ? {
|
|
486
|
+
[pageParams.appId]: config.appId,
|
|
487
|
+
[pageParams.appName]: config.appName,
|
|
488
|
+
[pageParams.publicServerUrl]: config.publicServerURL
|
|
489
|
+
} : {};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Extracts and returns the locale from an express request.
|
|
494
|
+
* @param {Object} req The express request.
|
|
495
|
+
* @returns {String|undefined} The locale, or undefined if no locale was set.
|
|
496
|
+
*/
|
|
497
|
+
getLocale(req) {
|
|
498
|
+
const locale = (req.query || {})[pageParams.locale] || (req.body || {})[pageParams.locale] || (req.params || {})[pageParams.locale] || (req.headers || {})[pageParamHeaderPrefix + pageParams.locale];
|
|
499
|
+
|
|
500
|
+
// Validate locale format to prevent path traversal; only allow
|
|
501
|
+
// standard locale patterns like "en", "en-US", "de-AT", "zh-Hans-CN"
|
|
502
|
+
if (locale !== undefined && typeof locale !== 'string') {
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
if (typeof locale === 'string' && !/^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$/.test(locale)) {
|
|
506
|
+
return undefined;
|
|
507
|
+
}
|
|
508
|
+
return locale;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Composes page parameter headers from the given parameters. Control
|
|
513
|
+
* characters are always stripped from header values to prevent
|
|
514
|
+
* ERR_INVALID_CHAR errors. Values are URI-encoded if the
|
|
515
|
+
* `encodePageParamHeaders` option is enabled.
|
|
516
|
+
* @param {Object} params The parameters to include in the headers.
|
|
517
|
+
* @returns {Object} The headers object.
|
|
518
|
+
*/
|
|
519
|
+
composePageParamHeaders(params) {
|
|
520
|
+
const encode = this.pagesConfig.encodePageParamHeaders;
|
|
521
|
+
return Object.entries(params).reduce((m, p) => {
|
|
522
|
+
if (p[1] !== undefined) {
|
|
523
|
+
let value = encode ? encodeURIComponent(p[1]) : p[1];
|
|
524
|
+
if (typeof value === 'string') {
|
|
525
|
+
// eslint-disable-next-line no-control-regex
|
|
526
|
+
value = value.replace(/[\x00-\x1f\x7f]/g, '');
|
|
527
|
+
}
|
|
528
|
+
m[`${pageParamHeaderPrefix}${p[0].toLowerCase()}`] = value;
|
|
529
|
+
}
|
|
530
|
+
return m;
|
|
531
|
+
}, {});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Creates a response with http redirect.
|
|
536
|
+
* @param {Object} req The express request.
|
|
537
|
+
* @param {String} path The path of the file to return.
|
|
538
|
+
* @param {Object} params The query parameters to include.
|
|
539
|
+
* @returns {Object} The Promise Router response.
|
|
540
|
+
*/
|
|
541
|
+
async redirectResponse(url, params) {
|
|
542
|
+
// Remove any parameters with undefined value
|
|
543
|
+
params = Object.entries(params).reduce((m, p) => {
|
|
544
|
+
if (p[1] !== undefined) {
|
|
545
|
+
m[p[0]] = p[1];
|
|
546
|
+
}
|
|
547
|
+
return m;
|
|
548
|
+
}, {});
|
|
549
|
+
|
|
550
|
+
// Compose URL with parameters in query
|
|
551
|
+
const location = new URL(url);
|
|
552
|
+
Object.entries(params).forEach(p => location.searchParams.set(p[0], p[1]));
|
|
553
|
+
const locationString = location.toString();
|
|
554
|
+
|
|
555
|
+
// Add parameters to header to allow parsing for programmatic use
|
|
556
|
+
// of response, instead of having to parse the HTML content.
|
|
557
|
+
const headers = this.composePageParamHeaders(params);
|
|
558
|
+
return {
|
|
559
|
+
status: 303,
|
|
560
|
+
location: locationString,
|
|
561
|
+
headers: headers
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
defaultPagePath(file) {
|
|
565
|
+
return _path.default.join(this.pagesPath, file);
|
|
566
|
+
}
|
|
567
|
+
composePageUrl(file, publicServerUrl, locale) {
|
|
568
|
+
let url = publicServerUrl;
|
|
569
|
+
url += url.endsWith('/') ? '' : '/';
|
|
570
|
+
url += this.pagesEndpoint + '/';
|
|
571
|
+
url += locale === undefined ? '' : locale + '/';
|
|
572
|
+
url += file;
|
|
573
|
+
return url;
|
|
574
|
+
}
|
|
575
|
+
notFound() {
|
|
576
|
+
return {
|
|
577
|
+
text: 'Not found.',
|
|
578
|
+
status: 404
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
invalidRequest() {
|
|
582
|
+
const error = new Error();
|
|
583
|
+
error.status = 403;
|
|
584
|
+
error.message = 'unauthorized';
|
|
585
|
+
throw error;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Sets the Parse Server configuration in the request object to make it
|
|
590
|
+
* easily accessible throughtout request processing.
|
|
591
|
+
* @param {Object} req The request.
|
|
592
|
+
* @param {Boolean} failGracefully Is true if failing to set the config should
|
|
593
|
+
* not result in an invalid request response. Default is `false`.
|
|
594
|
+
*/
|
|
595
|
+
async setConfig(req, failGracefully = false) {
|
|
596
|
+
req.config = _Config.default.get(req.params.appId || req.query.appId);
|
|
597
|
+
if (!req.config && !failGracefully) {
|
|
598
|
+
this.invalidRequest();
|
|
599
|
+
}
|
|
600
|
+
if (req.config) {
|
|
601
|
+
await req.config.loadKeys();
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
mountPagesRoutes() {
|
|
605
|
+
this.route('GET', `/${this.pagesEndpoint}/:appId/verify_email`, req => {
|
|
606
|
+
return this.setConfig(req);
|
|
607
|
+
}, req => {
|
|
608
|
+
return this.verifyEmail(req);
|
|
609
|
+
});
|
|
610
|
+
this.route('POST', `/${this.pagesEndpoint}/:appId/resend_verification_email`, req => {
|
|
611
|
+
return this.setConfig(req);
|
|
612
|
+
}, req => {
|
|
613
|
+
return this.resendVerificationEmail(req);
|
|
614
|
+
});
|
|
615
|
+
this.route('GET', `/${this.pagesEndpoint}/choose_password`, req => {
|
|
616
|
+
return this.setConfig(req);
|
|
617
|
+
}, req => {
|
|
618
|
+
return this.passwordReset(req);
|
|
619
|
+
});
|
|
620
|
+
this.route('POST', `/${this.pagesEndpoint}/:appId/request_password_reset`, req => {
|
|
621
|
+
return this.setConfig(req);
|
|
622
|
+
}, req => {
|
|
623
|
+
return this.resetPassword(req);
|
|
624
|
+
});
|
|
625
|
+
this.route('GET', `/${this.pagesEndpoint}/:appId/request_password_reset`, req => {
|
|
626
|
+
return this.setConfig(req);
|
|
627
|
+
}, req => {
|
|
628
|
+
return this.requestResetPassword(req);
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
mountCustomRoutes() {
|
|
632
|
+
for (const route of this.pagesConfig.customRoutes || []) {
|
|
633
|
+
this.route(route.method, `/${this.pagesEndpoint}/:appId/${route.path}`, req => {
|
|
634
|
+
return this.setConfig(req);
|
|
635
|
+
}, async req => {
|
|
636
|
+
const {
|
|
637
|
+
file,
|
|
638
|
+
query = {}
|
|
639
|
+
} = (await route.handler(req)) || {};
|
|
640
|
+
|
|
641
|
+
// If route handler did not return a page send 404 response
|
|
642
|
+
if (!file) {
|
|
643
|
+
return this.notFound();
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Send page response
|
|
647
|
+
const page = new _Page.default({
|
|
648
|
+
id: file,
|
|
649
|
+
defaultFile: file
|
|
650
|
+
});
|
|
651
|
+
return this.goToPage(req, page, query, false);
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
mountStaticRoute() {
|
|
656
|
+
this.route('GET', `/${this.pagesEndpoint}/*resource`, req => {
|
|
657
|
+
return this.setConfig(req, true);
|
|
658
|
+
}, req => {
|
|
659
|
+
return this.staticRoute(req);
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
expressRouter() {
|
|
663
|
+
const router = _express.default.Router();
|
|
664
|
+
router.use('/', super.expressRouter());
|
|
665
|
+
return router;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
exports.PagesRouter = PagesRouter;
|
|
669
|
+
var _default = exports.default = PagesRouter;
|
|
670
|
+
module.exports = {
|
|
671
|
+
PagesRouter,
|
|
672
|
+
pageParamHeaderPrefix,
|
|
673
|
+
pageParams,
|
|
674
|
+
pages
|
|
675
|
+
};
|
|
676
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfUHJvbWlzZVJvdXRlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX0NvbmZpZyIsIl9leHByZXNzIiwiX3BhdGgiLCJfZnMiLCJfbm9kZSIsIl9VdGlscyIsIl9tdXN0YWNoZSIsIl9QYWdlIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwicGFnZXMiLCJPYmplY3QiLCJmcmVlemUiLCJwYXNzd29yZFJlc2V0IiwiUGFnZSIsImlkIiwiZGVmYXVsdEZpbGUiLCJwYXNzd29yZFJlc2V0U3VjY2VzcyIsInBhc3N3b3JkUmVzZXRMaW5rSW52YWxpZCIsImVtYWlsVmVyaWZpY2F0aW9uU3VjY2VzcyIsImVtYWlsVmVyaWZpY2F0aW9uU2VuZEZhaWwiLCJlbWFpbFZlcmlmaWNhdGlvblNlbmRTdWNjZXNzIiwiZW1haWxWZXJpZmljYXRpb25MaW5rSW52YWxpZCIsImVtYWlsVmVyaWZpY2F0aW9uTGlua0V4cGlyZWQiLCJwYWdlUGFyYW1zIiwiYXBwTmFtZSIsImFwcElkIiwidG9rZW4iLCJ1c2VybmFtZSIsImVycm9yIiwibG9jYWxlIiwicHVibGljU2VydmVyVXJsIiwicGFnZVBhcmFtSGVhZGVyUHJlZml4IiwiZXJyb3JzIiwianNvbkZhaWxlZEZpbGVMb2FkaW5nIiwiZmlsZU91dHNpZGVBbGxvd2VkU2NvcGUiLCJQYWdlc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJjb25zdHJ1Y3RvciIsInBhZ2VzQ29uZmlnIiwicGFnZXNFbmRwb2ludCIsInBhZ2VzUGF0aCIsInBhdGgiLCJyZXNvbHZlIiwiX19kaXJuYW1lIiwibG9hZEpzb25SZXNvdXJjZSIsIm1vdW50UGFnZXNSb3V0ZXMiLCJtb3VudEN1c3RvbVJvdXRlcyIsIm1vdW50U3RhdGljUm91dGUiLCJ2ZXJpZnlFbWFpbCIsInJlcSIsImNvbmZpZyIsInJhd1Rva2VuIiwicXVlcnkiLCJ1bmRlZmluZWQiLCJpbnZhbGlkUmVxdWVzdCIsImdvVG9QYWdlIiwidXNlckNvbnRyb2xsZXIiLCJ0aGVuIiwicmVzZW5kVmVyaWZpY2F0aW9uRW1haWwiLCJib2R5Iiwic3VwcHJlc3NFcnJvciIsImVtYWlsVmVyaWZ5U3VjY2Vzc09uSW52YWxpZEVtYWlsIiwicGFyYW1zIiwicHVibGljU2VydmVyVVJMIiwicmVxdWVzdFJlc2V0UGFzc3dvcmQiLCJjaGVja1Jlc2V0VG9rZW5WYWxpZGl0eSIsImFwcGxpY2F0aW9uSWQiLCJyZXNldFBhc3N3b3JkIiwibmV3X3Bhc3N3b3JkIiwieGhyIiwiUGFyc2UiLCJFcnJvciIsIk9USEVSX0NBVVNFIiwiUEFTU1dPUkRfTUlTU0lORyIsInVwZGF0ZVBhc3N3b3JkIiwiUHJvbWlzZSIsInN1Y2Nlc3MiLCJlcnIiLCJyZXN1bHQiLCJzdGF0dXMiLCJyZXNwb25zZSIsInBhZ2UiLCJyZXNwb25zZVR5cGUiLCJyZWRpcmVjdCIsImZvcmNlUmVkaXJlY3QiLCJtZXRob2QiLCJkZWZhdWx0UGFyYW1zIiwiZ2V0RGVmYXVsdFBhcmFtcyIsInZhbHVlcyIsImluY2x1ZGVzIiwibm90Rm91bmQiLCJhc3NpZ24iLCJnZXRMb2NhbGUiLCJkZWZhdWx0UGF0aCIsImRlZmF1bHRQYWdlUGF0aCIsImRlZmF1bHRVcmwiLCJjb21wb3NlUGFnZVVybCIsImN1c3RvbVVybCIsImN1c3RvbVVybHMiLCJVdGlscyIsImlzUGF0aCIsInJlZGlyZWN0UmVzcG9uc2UiLCJwbGFjZWhvbGRlcnMiLCJlbmFibGVMb2NhbGl6YXRpb24iLCJsb2NhbGl6YXRpb25Kc29uUGF0aCIsImdldEpzb25QbGFjZWhvbGRlcnMiLCJnZXRMb2NhbGl6ZWRQYXRoIiwic3ViZGlyIiwicGFnZVJlc3BvbnNlIiwic3RhdGljUm91dGUiLCJyZWxhdGl2ZVBhdGgiLCJhYnNvbHV0ZVBhdGgiLCJlbmRzV2l0aCIsImZpbGVSZXNwb25zZSIsImdldEpzb25UcmFuc2xhdGlvbiIsImpzb25QYXJhbWV0ZXJzIiwibG9jYWxpemF0aW9uRmFsbGJhY2tMb2NhbGUiLCJsYW5ndWFnZSIsInNwbGl0IiwicmVzb3VyY2UiLCJ0cmFuc2xhdGlvbiIsIkpTT04iLCJzdHJpbmdpZnkiLCJtdXN0YWNoZSIsInJlbmRlciIsInBhcnNlIiwiZGF0YSIsInJlYWRGaWxlIiwiY29uZmlnUGxhY2Vob2xkZXJzIiwicHJvdG90eXBlIiwidG9TdHJpbmciLCJjYWxsIiwiaXNQcm9taXNlIiwiYWxsUGxhY2Vob2xkZXJzIiwicGFyYW1zQW5kUGxhY2Vob2xkZXJzIiwiaGVhZGVycyIsImNvbXBvc2VQYWdlUGFyYW1IZWFkZXJzIiwidGV4dCIsImZpbGVQYXRoIiwibm9ybWFsaXplZFBhdGgiLCJub3JtYWxpemUiLCJzdGFydHNXaXRoIiwic2VwIiwiZnMiLCJqc29uIiwidGVzdCIsImVuY29kZSIsImVuY29kZVBhZ2VQYXJhbUhlYWRlcnMiLCJlbnRyaWVzIiwicmVkdWNlIiwibSIsInAiLCJ2YWx1ZSIsImVuY29kZVVSSUNvbXBvbmVudCIsInJlcGxhY2UiLCJ0b0xvd2VyQ2FzZSIsInVybCIsImxvY2F0aW9uIiwiVVJMIiwiZm9yRWFjaCIsInNlYXJjaFBhcmFtcyIsInNldCIsImxvY2F0aW9uU3RyaW5nIiwiZmlsZSIsImpvaW4iLCJtZXNzYWdlIiwic2V0Q29uZmlnIiwiZmFpbEdyYWNlZnVsbHkiLCJDb25maWciLCJnZXQiLCJsb2FkS2V5cyIsInJvdXRlIiwiY3VzdG9tUm91dGVzIiwiaGFuZGxlciIsImV4cHJlc3NSb3V0ZXIiLCJyb3V0ZXIiLCJleHByZXNzIiwiUm91dGVyIiwidXNlIiwiZXhwb3J0cyIsIl9kZWZhdWx0IiwibW9kdWxlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL1JvdXRlcnMvUGFnZXNSb3V0ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFByb21pc2VSb3V0ZXIgZnJvbSAnLi4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4uL0NvbmZpZyc7XG5pbXBvcnQgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgeyBQYXJzZSB9IGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IFV0aWxzIGZyb20gJy4uL1V0aWxzJztcbmltcG9ydCBtdXN0YWNoZSBmcm9tICdtdXN0YWNoZSc7XG5pbXBvcnQgUGFnZSBmcm9tICcuLi9QYWdlJztcblxuLy8gQWxsIHBhZ2VzIHdpdGggY3VzdG9tIHBhZ2Uga2V5IGZvciByZWZlcmVuY2UgYW5kIGZpbGUgbmFtZVxuY29uc3QgcGFnZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgcGFzc3dvcmRSZXNldDogbmV3IFBhZ2UoeyBpZDogJ3Bhc3N3b3JkUmVzZXQnLCBkZWZhdWx0RmlsZTogJ3Bhc3N3b3JkX3Jlc2V0Lmh0bWwnIH0pLFxuICBwYXNzd29yZFJlc2V0U3VjY2VzczogbmV3IFBhZ2Uoe1xuICAgIGlkOiAncGFzc3dvcmRSZXNldFN1Y2Nlc3MnLFxuICAgIGRlZmF1bHRGaWxlOiAncGFzc3dvcmRfcmVzZXRfc3VjY2Vzcy5odG1sJyxcbiAgfSksXG4gIHBhc3N3b3JkUmVzZXRMaW5rSW52YWxpZDogbmV3IFBhZ2Uoe1xuICAgIGlkOiAncGFzc3dvcmRSZXNldExpbmtJbnZhbGlkJyxcbiAgICBkZWZhdWx0RmlsZTogJ3Bhc3N3b3JkX3Jlc2V0X2xpbmtfaW52YWxpZC5odG1sJyxcbiAgfSksXG4gIGVtYWlsVmVyaWZpY2F0aW9uU3VjY2VzczogbmV3IFBhZ2Uoe1xuICAgIGlkOiAnZW1haWxWZXJpZmljYXRpb25TdWNjZXNzJyxcbiAgICBkZWZhdWx0RmlsZTogJ2VtYWlsX3ZlcmlmaWNhdGlvbl9zdWNjZXNzLmh0bWwnLFxuICB9KSxcbiAgZW1haWxWZXJpZmljYXRpb25TZW5kRmFpbDogbmV3IFBhZ2Uoe1xuICAgIGlkOiAnZW1haWxWZXJpZmljYXRpb25TZW5kRmFpbCcsXG4gICAgZGVmYXVsdEZpbGU6ICdlbWFpbF92ZXJpZmljYXRpb25fc2VuZF9mYWlsLmh0bWwnLFxuICB9KSxcbiAgZW1haWxWZXJpZmljYXRpb25TZW5kU3VjY2VzczogbmV3IFBhZ2Uoe1xuICAgIGlkOiAnZW1haWxWZXJpZmljYXRpb25TZW5kU3VjY2VzcycsXG4gICAgZGVmYXVsdEZpbGU6ICdlbWFpbF92ZXJpZmljYXRpb25fc2VuZF9zdWNjZXNzLmh0bWwnLFxuICB9KSxcbiAgZW1haWxWZXJpZmljYXRpb25MaW5rSW52YWxpZDogbmV3IFBhZ2Uoe1xuICAgIGlkOiAnZW1haWxWZXJpZmljYXRpb25MaW5rSW52YWxpZCcsXG4gICAgZGVmYXVsdEZpbGU6ICdlbWFpbF92ZXJpZmljYXRpb25fbGlua19pbnZhbGlkLmh0bWwnLFxuICB9KSxcbiAgZW1haWxWZXJpZmljYXRpb25MaW5rRXhwaXJlZDogbmV3IFBhZ2Uoe1xuICAgIGlkOiAnZW1haWxWZXJpZmljYXRpb25MaW5rRXhwaXJlZCcsXG4gICAgZGVmYXVsdEZpbGU6ICdlbWFpbF92ZXJpZmljYXRpb25fbGlua19leHBpcmVkLmh0bWwnLFxuICB9KSxcbn0pO1xuXG4vLyBBbGwgcGFnZSBwYXJhbWV0ZXJzIGZvciByZWZlcmVuY2UgdG8gYmUgdXNlZCBhcyB0ZW1wbGF0ZSBwbGFjZWhvbGRlcnMgb3IgcXVlcnkgcGFyYW1zXG5jb25zdCBwYWdlUGFyYW1zID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGFwcE5hbWU6ICdhcHBOYW1lJyxcbiAgYXBwSWQ6ICdhcHBJZCcsXG4gIHRva2VuOiAndG9rZW4nLFxuICB1c2VybmFtZTogJ3VzZXJuYW1lJyxcbiAgZXJyb3I6ICdlcnJvcicsXG4gIGxvY2FsZTogJ2xvY2FsZScsXG4gIHB1YmxpY1NlcnZlclVybDogJ3B1YmxpY1NlcnZlclVybCcsXG59KTtcblxuLy8gVGhlIGhlYWRlciBwcmVmaXggdG8gYWRkIHBhZ2UgcGFyYW1zIGFzIHJlc3BvbnNlIGhlYWRlcnNcbmNvbnN0IHBhZ2VQYXJhbUhlYWRlclByZWZpeCA9ICd4LXBhcnNlLXBhZ2UtcGFyYW0tJztcblxuLy8gVGhlIGVycm9ycyBiZWluZyB0aHJvd25cbmNvbnN0IGVycm9ycyA9IE9iamVjdC5mcmVlemUoe1xuICBqc29uRmFpbGVkRmlsZUxvYWRpbmc6ICdmYWlsZWQgdG8gbG9hZCBKU09OIGZpbGUnLFxuICBmaWxlT3V0c2lkZUFsbG93ZWRTY29wZTogJ25vdCBhbGxvd2VkIHRvIHJlYWQgZmlsZSBvdXRzaWRlIG9mIHBhZ2VzIGRpcmVjdG9yeScsXG59KTtcblxuZXhwb3J0IGNsYXNzIFBhZ2VzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgUGFnZXNSb3V0ZXIuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwYWdlcyBUaGUgcGFnZXMgb3B0aW9ucyBmcm9tIHRoZSBQYXJzZSBTZXJ2ZXIgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhZ2VzID0ge30pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgLy8gU2V0IGluc3RhbmNlIHByb3BlcnRpZXNcbiAgICB0aGlzLnBhZ2VzQ29uZmlnID0gcGFnZXM7XG4gICAgdGhpcy5wYWdlc0VuZHBvaW50ID0gcGFnZXMucGFnZXNFbmRwb2ludCA/IHBhZ2VzLnBhZ2VzRW5kcG9pbnQgOiAnYXBwcyc7XG4gICAgdGhpcy5wYWdlc1BhdGggPSBwYWdlcy5wYWdlc1BhdGhcbiAgICAgID8gcGF0aC5yZXNvbHZlKCcuLycsIHBhZ2VzLnBhZ2VzUGF0aClcbiAgICAgIDogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uLy4uL3B1YmxpYycpO1xuICAgIHRoaXMubG9hZEpzb25SZXNvdXJjZSgpO1xuICAgIHRoaXMubW91bnRQYWdlc1JvdXRlcygpO1xuICAgIHRoaXMubW91bnRDdXN0b21Sb3V0ZXMoKTtcbiAgICB0aGlzLm1vdW50U3RhdGljUm91dGUoKTtcbiAgfVxuXG4gIHZlcmlmeUVtYWlsKHJlcSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3QgeyB0b2tlbjogcmF3VG9rZW4gfSA9IHJlcS5xdWVyeTtcbiAgICBjb25zdCB0b2tlbiA9IHR5cGVvZiByYXdUb2tlbiA9PT0gJ3N0cmluZycgPyByYXdUb2tlbiA6IHVuZGVmaW5lZDtcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlbikge1xuICAgICAgcmV0dXJuIHRoaXMuZ29Ub1BhZ2UocmVxLCBwYWdlcy5lbWFpbFZlcmlmaWNhdGlvbkxpbmtJbnZhbGlkKTtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyQ29udHJvbGxlciA9IGNvbmZpZy51c2VyQ29udHJvbGxlcjtcbiAgICByZXR1cm4gdXNlckNvbnRyb2xsZXIudmVyaWZ5RW1haWwodG9rZW4pLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmdvVG9QYWdlKHJlcSwgcGFnZXMuZW1haWxWZXJpZmljYXRpb25TdWNjZXNzKTtcbiAgICAgIH0sXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmdvVG9QYWdlKHJlcSwgcGFnZXMuZW1haWxWZXJpZmljYXRpb25MaW5rSW52YWxpZCk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHJlc2VuZFZlcmlmaWNhdGlvbkVtYWlsKHJlcSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3QgdXNlcm5hbWUgPSByZXEuYm9keT8udXNlcm5hbWU7XG4gICAgY29uc3QgcmF3VG9rZW4gPSByZXEuYm9keT8udG9rZW47XG4gICAgY29uc3QgdG9rZW4gPSB0eXBlb2YgcmF3VG9rZW4gPT09ICdzdHJpbmcnID8gcmF3VG9rZW4gOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgdGhpcy5pbnZhbGlkUmVxdWVzdCgpO1xuICAgIH1cblxuICAgIGlmICghdXNlcm5hbWUgJiYgIXRva2VuKSB7XG4gICAgICByZXR1cm4gdGhpcy5nb1RvUGFnZShyZXEsIHBhZ2VzLmVtYWlsVmVyaWZpY2F0aW9uTGlua0ludmFsaWQpO1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJDb250cm9sbGVyID0gY29uZmlnLnVzZXJDb250cm9sbGVyO1xuICAgIGNvbnN0IHN1cHByZXNzRXJyb3IgPSBjb25maWcuZW1haWxWZXJpZnlTdWNjZXNzT25JbnZhbGlkRW1haWwgPz8gdHJ1ZTtcblxuICAgIHJldHVybiB1c2VyQ29udHJvbGxlci5yZXNlbmRWZXJpZmljYXRpb25FbWFpbCh1c2VybmFtZSwgcmVxLCB0b2tlbikudGhlbihcbiAgICAgICgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ29Ub1BhZ2UocmVxLCBwYWdlcy5lbWFpbFZlcmlmaWNhdGlvblNlbmRTdWNjZXNzKTtcbiAgICAgIH0sXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGlmIChzdXBwcmVzc0Vycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZ29Ub1BhZ2UocmVxLCBwYWdlcy5lbWFpbFZlcmlmaWNhdGlvblNlbmRTdWNjZXNzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nb1RvUGFnZShyZXEsIHBhZ2VzLmVtYWlsVmVyaWZpY2F0aW9uU2VuZEZhaWwpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBwYXNzd29yZFJlc2V0KHJlcSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgW3BhZ2VQYXJhbXMuYXBwSWRdOiByZXEucGFyYW1zLmFwcElkLFxuICAgICAgW3BhZ2VQYXJhbXMuYXBwTmFtZV06IGNvbmZpZy5hcHBOYW1lLFxuICAgICAgW3BhZ2VQYXJhbXMudG9rZW5dOiByZXEucXVlcnkudG9rZW4sXG4gICAgICBbcGFnZVBhcmFtcy51c2VybmFtZV06IHJlcS5xdWVyeS51c2VybmFtZSxcbiAgICAgIFtwYWdlUGFyYW1zLnB1YmxpY1NlcnZlclVybF06IGNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwsXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5nb1RvUGFnZShyZXEsIHBhZ2VzLnBhc3N3b3JkUmVzZXQsIHBhcmFtcyk7XG4gIH1cblxuICByZXF1ZXN0UmVzZXRQYXNzd29yZChyZXEpIHtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHRoaXMuaW52YWxpZFJlcXVlc3QoKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHRva2VuOiByYXdUb2tlbiB9ID0gcmVxLnF1ZXJ5O1xuICAgIGNvbnN0IHRva2VuID0gdHlwZW9mIHJhd1Rva2VuID09PSAnc3RyaW5nJyA/IHJhd1Rva2VuIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKCF0b2tlbikge1xuICAgICAgcmV0dXJuIHRoaXMuZ29Ub1BhZ2UocmVxLCBwYWdlcy5wYXNzd29yZFJlc2V0TGlua0ludmFsaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBjb25maWcudXNlckNvbnRyb2xsZXIuY2hlY2tSZXNldFRva2VuVmFsaWRpdHkodG9rZW4pLnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICBbcGFnZVBhcmFtcy50b2tlbl06IHRva2VuLFxuICAgICAgICAgIFtwYWdlUGFyYW1zLmFwcElkXTogY29uZmlnLmFwcGxpY2F0aW9uSWQsXG4gICAgICAgICAgW3BhZ2VQYXJhbXMuYXBwTmFtZV06IGNvbmZpZy5hcHBOYW1lLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcy5nb1RvUGFnZShyZXEsIHBhZ2VzLnBhc3N3b3JkUmVzZXQsIHBhcmFtcyk7XG4gICAgICB9LFxuICAgICAgKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nb1RvUGFnZShyZXEsIHBhZ2VzLnBhc3N3b3JkUmVzZXRMaW5rSW52YWxpZCk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHJlc2V0UGFzc3dvcmQocmVxKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICB0aGlzLmludmFsaWRSZXF1ZXN0KCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBuZXdfcGFzc3dvcmQsIHRva2VuOiByYXdUb2tlbiB9ID0gcmVxLmJvZHkgfHwge307XG4gICAgY29uc3QgdG9rZW4gPSB0eXBlb2YgcmF3VG9rZW4gPT09ICdzdHJpbmcnID8gcmF3VG9rZW4gOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoKCF0b2tlbiB8fCAhbmV3X3Bhc3N3b3JkKSAmJiByZXEueGhyID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ29Ub1BhZ2UocmVxLCBwYWdlcy5wYXNzd29yZFJlc2V0TGlua0ludmFsaWQpO1xuICAgIH1cblxuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PVEhFUl9DQVVTRSwgJ01pc3NpbmcgdG9rZW4nKTtcbiAgICB9XG5cbiAgICBpZiAoIW5ld19wYXNzd29yZCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlBBU1NXT1JEX01JU1NJTkcsICdNaXNzaW5nIHBhc3N3b3JkJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZy51c2VyQ29udHJvbGxlclxuICAgICAgLnVwZGF0ZVBhc3N3b3JkKHRva2VuLCBuZXdfcGFzc3dvcmQpXG4gICAgICAudGhlbihcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyID0+IHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgZXJyLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICApXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBpZiAocmVxLnhocikge1xuICAgICAgICAgIGlmIChyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgICAgIHN0YXR1czogMjAwLFxuICAgICAgICAgICAgICByZXNwb25zZTogJ1Bhc3N3b3JkIHN1Y2Nlc3NmdWxseSByZXNldCcsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHJlc3VsdC5lcnIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PVEhFUl9DQVVTRSwgYCR7cmVzdWx0LmVycn1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBxdWVyeSA9IHJlc3VsdC5zdWNjZXNzXG4gICAgICAgICAgPyB7fVxuICAgICAgICAgIDoge1xuICAgICAgICAgICAgW3BhZ2VQYXJhbXMudG9rZW5dOiB0b2tlbixcbiAgICAgICAgICAgIFtwYWdlUGFyYW1zLmFwcElkXTogY29uZmlnLmFwcGxpY2F0aW9uSWQsXG4gICAgICAgICAgICBbcGFnZVBhcmFtcy5lcnJvcl06IHJlc3VsdC5lcnIsXG4gICAgICAgICAgICBbcGFnZVBhcmFtcy5hcHBOYW1lXTogY29uZmlnLmFwcE5hbWUsXG4gICAgICAgICAgfTtcblxuICAgICAgICBpZiAocmVzdWx0Py5lcnIgPT09ICdUaGUgcGFzc3dvcmQgcmVzZXQgbGluayBoYXMgZXhwaXJlZCcpIHtcbiAgICAgICAgICBkZWxldGUgcXVlcnlbcGFnZVBhcmFtcy50b2tlbl07XG4gICAgICAgICAgcXVlcnlbcGFnZVBhcmFtcy50b2tlbl0gPSB0b2tlbjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYWdlID0gcmVzdWx0LnN1Y2Nlc3MgPyBwYWdlcy5wYXNzd29yZFJlc2V0U3VjY2VzcyA6IHBhZ2VzLnBhc3N3b3JkUmVzZXQ7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ29Ub1BhZ2UocmVxLCBwYWdlLCBxdWVyeSwgZmFsc2UpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwYWdlIGNvbnRlbnQgaWYgdGhlIHBhZ2UgaXMgYSBsb2NhbCBmaWxlIG9yIHJldHVybnMgYVxuICAgKiByZWRpcmVjdCB0byBhIGN1c3RvbSBwYWdlLlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxIFRoZSBleHByZXNzIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7UGFnZX0gcGFnZSBUaGUgcGFnZSB0byBnbyB0by5cbiAgICogQHBhcmFtIHtPYmplY3R9IFtwYXJhbXM9e31dIFRoZSBxdWVyeSBwYXJhbWV0ZXJzIHRvIGF0dGFjaCB0byB0aGUgVVJMIGluIGNhc2Ugb2ZcbiAgICogSFRUUCByZWRpcmVjdCByZXNwb25zZXMgZm9yIFBPU1QgcmVxdWVzdHMsIG9yIHRoZSBwbGFjZWhvbGRlcnMgdG8gZmlsbCBpbnRvXG4gICAqIHRoZSByZXNwb25zZSBjb250ZW50IGluIGNhc2Ugb2YgSFRUUCBjb250ZW50IHJlc3BvbnNlcyBmb3IgR0VUIHJlcXVlc3RzLlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtyZXNwb25zZVR5cGVdIElzIHRydWUgaWYgYSByZWRpcmVjdCByZXNwb25zZSBzaG91bGQgYmUgZm9yY2VkLFxuICAgKiBmYWxzZSBpZiBhIGNvbnRlbnQgcmVzcG9uc2Ugc2hvdWxkIGJlIGZvcmNlZCwgdW5kZWZpbmVkIGlmIHRoZSByZXNwb25zZSB0eXBlXG4gICAqIHNob3VsZCBkZXBlbmQgb24gdGhlIHJlcXVlc3QgdHlwZSBieSBkZWZhdWx0OlxuICAgKiAtIEdFVCByZXF1ZXN0IC0+IGNvbnRlbnQgcmVzcG9uc2VcbiAgICogLSBQT1NUIHJlcXVlc3QgLT4gcmVkaXJlY3QgcmVzcG9uc2UgKFBSRyBwYXR0ZXJuKVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fSBUaGUgUHJvbWlzZVJvdXRlciByZXNwb25zZS5cbiAgICovXG4gIGdvVG9QYWdlKHJlcSwgcGFnZSwgcGFyYW1zID0ge30sIHJlc3BvbnNlVHlwZSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG5cbiAgICAvLyBEZXRlcm1pbmUgcmVkaXJlY3QgZWl0aGVyIGJ5IGZvcmNlLCByZXNwb25zZSBzZXR0aW5nIG9yIHJlcXVlc3QgbWV0aG9kXG4gICAgY29uc3QgcmVkaXJlY3QgPSBjb25maWcucGFnZXMuZm9yY2VSZWRpcmVjdFxuICAgICAgPyB0cnVlXG4gICAgICA6IHJlc3BvbnNlVHlwZSAhPT0gdW5kZWZpbmVkXG4gICAgICAgID8gcmVzcG9uc2VUeXBlXG4gICAgICAgIDogcmVxLm1ldGhvZCA9PSAnUE9TVCc7XG5cbiAgICAvLyBJbmNsdWRlIGRlZmF1bHQgcGFyYW1ldGVyc1xuICAgIGNvbnN0IGRlZmF1bHRQYXJhbXMgPSB0aGlzLmdldERlZmF1bHRQYXJhbXMoY29uZmlnKTtcbiAgICBpZiAoT2JqZWN0LnZhbHVlcyhkZWZhdWx0UGFyYW1zKS5pbmNsdWRlcyh1bmRlZmluZWQpKSB7XG4gICAgICByZXR1cm4gdGhpcy5ub3RGb3VuZCgpO1xuICAgIH1cbiAgICBwYXJhbXMgPSBPYmplY3QuYXNzaWduKHBhcmFtcywgZGVmYXVsdFBhcmFtcyk7XG5cbiAgICAvLyBBZGQgbG9jYWxlIHRvIHBhcmFtcyB0byBlbnN1cmUgaXQgaXMgcGFzc2VkIG9uIHdpdGggZXZlcnkgcmVxdWVzdDtcbiAgICAvLyB0aGF0IG1lYW5zLCBvbmNlIGEgbG9jYWxlIGlzIHNldCwgaXQgaXMgcGFzc2VkIG9uIHRvIGFueSBmb2xsb3ctdXAgcGFnZSxcbiAgICAvLyBlLmcuIHJlcXVlc3RfcGFzc3dvcmRfcmVzZXQgLT4gcGFzc3dvcmRfcmVzZXQgLT4gcGFzc3dvcmRfcmVzZXRfc3VjY2Vzc1xuICAgIGNvbnN0IGxvY2FsZSA9IHRoaXMuZ2V0TG9jYWxlKHJlcSk7XG4gICAgcGFyYW1zW3BhZ2VQYXJhbXMubG9jYWxlXSA9IGxvY2FsZTtcblxuICAgIC8vIENvbXBvc2UgcGF0aHMgYW5kIFVSTHNcbiAgICBjb25zdCBkZWZhdWx0RmlsZSA9IHBhZ2UuZGVmYXVsdEZpbGU7XG4gICAgY29uc3QgZGVmYXVsdFBhdGggPSB0aGlzLmRlZmF1bHRQYWdlUGF0aChkZWZhdWx0RmlsZSk7XG4gICAgY29uc3QgZGVmYXVsdFVybCA9IHRoaXMuY29tcG9zZVBhZ2VVcmwoZGVmYXVsdEZpbGUsIGNvbmZpZy5wdWJsaWNTZXJ2ZXJVUkwpO1xuXG4gICAgLy8gSWYgY3VzdG9tIFVSTCBpcyBzZXQgcmVkaXJlY3QgdG8gaXQgd2l0aG91dCBsb2NhbGl6YXRpb25cbiAgICBjb25zdCBjdXN0b21VcmwgPSBjb25maWcucGFnZXMuY3VzdG9tVXJsc1twYWdlLmlkXTtcbiAgICBpZiAoY3VzdG9tVXJsICYmICFVdGlscy5pc1BhdGgoY3VzdG9tVXJsKSkge1xuICAgICAgcmV0dXJuIHRoaXMucmVkaXJlY3RSZXNwb25zZShjdXN0b21VcmwsIHBhcmFtcyk7XG4gICAgfVxuXG4gICAgLy8gR2V0IEpTT04gcGxhY2Vob2xkZXJzXG4gICAgbGV0IHBsYWNlaG9sZGVycyA9IHt9O1xuICAgIGlmIChjb25maWcucGFnZXMuZW5hYmxlTG9jYWxpemF0aW9uICYmIGNvbmZpZy5wYWdlcy5sb2NhbGl6YXRpb25Kc29uUGF0aCkge1xuICAgICAgcGxhY2Vob2xkZXJzID0gdGhpcy5nZXRKc29uUGxhY2Vob2xkZXJzKGxvY2FsZSwgcGFyYW1zKTtcbiAgICB9XG5cbiAgICAvLyBTZW5kIHJlc3BvbnNlXG4gICAgaWYgKGNvbmZpZy5wYWdlcy5lbmFibGVMb2NhbGl6YXRpb24gJiYgbG9jYWxlKSB7XG4gICAgICByZXR1cm4gVXRpbHMuZ2V0TG9jYWxpemVkUGF0aChkZWZhdWx0UGF0aCwgbG9jYWxlKS50aGVuKCh7IHBhdGgsIHN1YmRpciB9KSA9PlxuICAgICAgICByZWRpcmVjdFxuICAgICAgICAgID8gdGhpcy5yZWRpcmVjdFJlc3BvbnNlKFxuICAgICAgICAgICAgdGhpcy5jb21wb3NlUGFnZVVybChkZWZhdWx0RmlsZSwgY29uZmlnLnB1YmxpY1NlcnZlclVSTCwgc3ViZGlyKSxcbiAgICAgICAgICAgIHBhcmFtc1xuICAgICAgICAgIClcbiAgICAgICAgICA6IHRoaXMucGFnZVJlc3BvbnNlKHBhdGgsIHBhcmFtcywgcGxhY2Vob2xkZXJzKVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlZGlyZWN0XG4gICAgICAgID8gdGhpcy5yZWRpcmVjdFJlc3BvbnNlKGRlZmF1bHRVcmwsIHBhcmFtcylcbiAgICAgICAgOiB0aGlzLnBhZ2VSZXNwb25zZShkZWZhdWx0UGF0aCwgcGFyYW1zLCBwbGFjZWhvbGRlcnMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXJ2ZXMgYSByZXF1ZXN0IHRvIGEgc3RhdGljIHJlc291cmNlIGFuZCBsb2NhbGl6ZXMgdGhlIHJlc291cmNlIGlmIGl0XG4gICAqIGlzIGEgSFRNTCBmaWxlLlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxIFRoZSByZXF1ZXN0IG9iamVjdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gVGhlIHJlc3BvbnNlLlxuICAgKi9cbiAgc3RhdGljUm91dGUocmVxKSB7XG4gICAgLy8gR2V0IHJlcXVlc3RlZCBwYXRoXG4gICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcmVxLnBhcmFtc1sncmVzb3VyY2UnXVswXTtcblxuICAgIC8vIFJlc29sdmUgcmVxdWVzdGVkIHBhdGggdG8gYWJzb2x1dGUgcGF0aFxuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGgucmVzb2x2ZSh0aGlzLnBhZ2VzUGF0aCwgcmVsYXRpdmVQYXRoKTtcblxuICAgIC8vIElmIHRoZSByZXF1ZXN0ZWQgZmlsZSBpcyBub3QgYSBIVE1MIGZpbGUgc2VuZCBpdHMgcmF3IGNvbnRlbnRcbiAgICBpZiAoIWFic29sdXRlUGF0aCB8fCAhYWJzb2x1dGVQYXRoLmVuZHNXaXRoKCcuaHRtbCcpKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWxlUmVzcG9uc2UoYWJzb2x1dGVQYXRoKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgcGFyYW1ldGVyc1xuICAgIGNvbnN0IHBhcmFtcyA9IHRoaXMuZ2V0RGVmYXVsdFBhcmFtcyhyZXEuY29uZmlnKTtcbiAgICBjb25zdCBsb2NhbGUgPSB0aGlzLmdldExvY2FsZShyZXEpO1xuICAgIGlmIChsb2NhbGUpIHtcbiAgICAgIHBhcmFtcy5sb2NhbGUgPSBsb2NhbGU7XG4gICAgfVxuXG4gICAgLy8gR2V0IEpTT04gcGxhY2Vob2xkZXJzXG4gICAgY29uc3QgcGxhY2Vob2xkZXJzID0gdGhpcy5nZXRKc29uUGxhY2Vob2xkZXJzKGxvY2FsZSwgcGFyYW1zKTtcblxuICAgIHJldHVybiB0aGlzLnBhZ2VSZXNwb25zZShhYnNvbHV0ZVBhdGgsIHBhcmFtcywgcGxhY2Vob2xkZXJzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgdHJhbnNsYXRpb24gZnJvbSB0aGUgSlNPTiByZXNvdXJjZSBmb3IgYSBnaXZlbiBsb2NhbGUuIFRoZSBKU09OXG4gICAqIHJlc291cmNlIGlzIHBhcnNlZCBhY2NvcmRpbmcgdG8gaTE4bmV4dCBzeW50YXguXG4gICAqXG4gICAqIEV4YW1wbGUgSlNPTiBjb250ZW50OlxuICAgKiBgYGBqc1xuICAgKiAge1xuICAgKiAgICBcImVuXCI6IHsgICAgICAgICAgICAgICAvLyByZXNvdXJjZSBmb3IgbGFuZ3VhZ2UgYGVuYCAoRW5nbGlzaClcbiAgICogICAgICBcInRyYW5zbGF0aW9uXCI6IHtcbiAgICogICAgICAgIFwiZ3JlZXRpbmdcIjogXCJIZWxsbyFcIlxuICAgKiAgICAgIH1cbiAgICogICAgfSxcbiAgICogICAgXCJkZVwiOiB7ICAgICAgICAgICAgICAgLy8gcmVzb3VyY2UgZm9yIGxhbmd1YWdlIGBkZWAgKEdlcm1hbilcbiAgICogICAgICBcInRyYW5zbGF0aW9uXCI6IHtcbiAgICogICAgICAgIFwiZ3JlZXRpbmdcIjogXCJIYWxsbyFcIlxuICAgKiAgICAgIH1cbiAgICogICAgfVxuICAgKiAgICBcImRlLUNIXCI6IHsgICAgICAgICAgICAvLyByZXNvdXJjZSBmb3IgbG9jYWxlIGBkZS1DSGAgKFN3aXNzIEdlcm1hbilcbiAgICogICAgICBcInRyYW5zbGF0aW9uXCI6IHtcbiAgICogICAgICAgIFwiZ3JlZXRpbmdcIjogXCJHcsO8ZXppIVwiXG4gICAqICAgICAgfVxuICAgKiAgICB9XG4gICAqICB9XG4gICAqIGBgYFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbG9jYWxlIFRoZSBsb2NhbGUgdG8gdHJhbnNsYXRlIHRvLlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgdHJhbnNsYXRpb24gb3IgYW4gZW1wdHkgb2JqZWN0IGlmIG5vIG1hdGNoaW5nXG4gICAqIHRyYW5zbGF0aW9uIHdhcyBmb3VuZC5cbiAgICovXG4gIGdldEpzb25UcmFuc2xhdGlvbihsb2NhbGUpIHtcbiAgICAvLyBJZiB0aGVyZSBpcyBubyBKU09OIHJlc291cmNlXG4gICAgaWYgKHRoaXMuanNvblBhcmFtZXRlcnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIC8vIElmIGxvY2FsZSBpcyBub3Qgc2V0IHVzZSB0aGUgZmFsbGJhY2sgbG9jYWxlXG4gICAgbG9jYWxlID0gbG9jYWxlIHx8IHRoaXMucGFnZXNDb25maWcubG9jYWxpemF0aW9uRmFsbGJhY2tMb2NhbGU7XG5cbiAgICAvLyBHZXQgbWF0Y2hpbmcgdHJhbnNsYXRpb24gYnkgbG9jYWxlLCBsYW5ndWFnZSBvciBmYWxsYmFjayBsb2NhbGVcbiAgICBjb25zdCBsYW5ndWFnZSA9IGxvY2FsZS5zcGxpdCgnLScpWzBdO1xuICAgIGNvbnN0IHJlc291cmNlID1cbiAgICAgIHRoaXMuanNvblBhcmFtZXRlcnNbbG9jYWxlXSB8fFxuICAgICAgdGhpcy5qc29uUGFyYW1ldGVyc1tsYW5ndWFnZV0gfHxcbiAgICAgIHRoaXMuanNvblBhcmFtZXRlcnNbdGhpcy5wYWdlc0NvbmZpZy5sb2NhbGl6YXRpb25GYWxsYmFja0xvY2FsZV0gfHxcbiAgICAgIHt9O1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gcmVzb3VyY2UudHJhbnNsYXRpb24gfHwge307XG4gICAgcmV0dXJuIHRyYW5zbGF0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSB0cmFuc2xhdGlvbiBmcm9tIHRoZSBKU09OIHJlc291cmNlIGZvciBhIGdpdmVuIGxvY2FsZSB3aXRoXG4gICAqIHBsYWNlaG9sZGVycyBmaWxsZWQgaW4gYnkgZ2l2ZW4gcGFyYW1ldGVycy5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGxvY2FsZSBUaGUgbG9jYWxlIHRvIHRyYW5zbGF0ZSB0by5cbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcyBUaGUgcGFyYW1ldGVycyB0byBmaWxsIGludG8gYW55IHBsYWNlaG9sZGVyc1xuICAgKiB3aXRoaW4gdGhlIHRyYW5zbGF0aW9ucy5cbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIHRyYW5zbGF0aW9uIG9yIGFuIGVtcHR5IG9iamVjdCBpZiBubyBtYXRjaGluZ1xuICAgKiB0cmFuc2xhdGlvbiB3YXMgZm91bmQuXG4gICAqL1xuICBnZXRKc29uUGxhY2Vob2xkZXJzKGxvY2FsZSwgcGFyYW1zID0ge30pIHtcbiAgICAvLyBJZiBsb2NhbGl6YXRpb24gaXMgZGlzYWJsZWQgb3IgdGhlcmUgaXMgbm8gSlNPTiByZXNvdXJjZVxuICAgIGlmICghdGhpcy5wYWdlc0NvbmZpZy5lbmFibGVMb2NhbGl6YXRpb24gfHwgIXRoaXMucGFnZXNDb25maWcubG9jYWxpemF0aW9uSnNvblBhdGgpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICAvLyBHZXQgSlNPTiBwbGFjZWhvbGRlcnNcbiAgICBsZXQgcGxhY2Vob2xkZXJzID0gdGhpcy5nZXRKc29uVHJhbnNsYXRpb24obG9jYWxlKTtcblxuICAgIC8vIEZpbGwgaW4gYW55IHBsYWNlaG9sZGVycyBpbiB0aGUgdHJhbnNsYXRpb247IHRoaXMgYWxsb3dzIGEgdHJhbnNsYXRpb25cbiAgICAvLyB0byBjb250YWluIGRlZmF1bHQgcGxhY2Vob2xkZXJzIGxpa2Uge3thcHBOYW1lfX0gd2hpY2ggYXJlIGZpbGxlZCBoZXJlXG4gICAgcGxhY2Vob2xkZXJzID0gSlNPTi5zdHJpbmdpZnkocGxhY2Vob2xkZXJzKTtcbiAgICBwbGFjZWhvbGRlcnMgPSBtdXN0YWNoZS5yZW5kZXIocGxhY2Vob2xkZXJzLCBwYXJhbXMpO1xuICAgIHBsYWNlaG9sZGVycyA9IEpTT04ucGFyc2UocGxhY2Vob2xkZXJzKTtcblxuICAgIHJldHVybiBwbGFjZWhvbGRlcnM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHJlc3BvbnNlIHdpdGggZmlsZSBjb250ZW50LlxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgZmlsZSB0byByZXR1cm4uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zPXt9XSBUaGUgcGFyYW1ldGVycyB0byBiZSBpbmNsdWRlZCBpbiB0aGUgcmVzcG9uc2VcbiAgICogaGVhZGVyLiBUaGVzZSB3aWxsIGFsc28gYmUgdXNlZCB0byBmaWxsIHBsYWNlaG9sZGVycy5cbiAgICogQHBhcmFtIHtPYmplY3R9IFtwbGFjZWhvbGRlcnM9e31dIFRoZSBwbGFjZWhvbGRlcnMgdG8gZmlsbCBpbiB0aGUgY29udGVudC5cbiAgICogVGhlc2Ugd2lsbCBub3QgYmUgaW5jbHVkZWQgaW4gdGhlIHJlc3BvbnNlIGhlYWRlci5cbiAgICogQHJldHVybnMge09iamVjdH0gVGhlIFByb21pc2UgUm91dGVyIHJlc3BvbnNlLlxuICAgKi9cbiAgYXN5bmMgcGFnZVJlc3BvbnNlKHBhdGgsIHBhcmFtcyA9IHt9LCBwbGFjZWhvbGRlcnMgPSB7fSkge1xuICAgIC8vIEdldCBmaWxlIGNvbnRlbnRcbiAgICBsZXQgZGF0YTtcbiAgICB0cnkge1xuICAgICAgZGF0YSA9IGF3YWl0IHRoaXMucmVhZEZpbGUocGF0aCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gdGhpcy5ub3RGb3VuZCgpO1xuICAgIH1cblxuICAgIC8vIEdldCBjb25maWcgcGxhY2Vob2xkZXJzOyBjYW4gYmUgYW4gb2JqZWN0LCBhIGZ1bmN0aW9uIG9yIGFuIGFzeW5jIGZ1bmN0aW9uXG4gICAgbGV0IGNvbmZpZ1BsYWNlaG9sZGVycyA9XG4gICAgICB0eXBlb2YgdGhpcy5wYWdlc0NvbmZpZy5wbGFjZWhvbGRlcnMgPT09ICdmdW5jdGlvbidcbiAgICAgICAgPyB0aGlzLnBhZ2VzQ29uZmlnLnBsYWNlaG9sZGVycyhwYXJhbXMpXG4gICAgICAgIDogT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHRoaXMucGFnZXNDb25maWcucGxhY2Vob2xkZXJzKSA9PT0gJ1tvYmplY3QgT2JqZWN0XSdcbiAgICAgICAgICA/IHRoaXMucGFnZXNDb25maWcucGxhY2Vob2xkZXJzXG4gICAgICAgICAgOiB7fTtcbiAgICBpZiAoVXRpbHMuaXNQcm9taXNlKGNvbmZpZ1BsYWNlaG9sZGVycykpIHtcbiAgICAgIGNvbmZpZ1BsYWNlaG9sZGVycyA9IGF3YWl0IGNvbmZpZ1BsYWNlaG9sZGVycztcbiAgICB9XG5cbiAgICAvLyBGaWxsIHBsYWNlaG9sZGVyc1xuICAgIGNvbnN0IGFsbFBsYWNlaG9sZGVycyA9IE9iamVjdC5hc3NpZ24oe30sIGNvbmZpZ1BsYWNlaG9sZGVycywgcGxhY2Vob2xkZXJzKTtcbiAgICBjb25zdCBwYXJhbXNBbmRQbGFjZWhvbGRlcnMgPSBPYmplY3QuYXNzaWduKHt9LCBwYXJhbXMsIGFsbFBsYWNlaG9sZGVycyk7XG4gICAgZGF0YSA9IG11c3RhY2hlLnJlbmRlcihkYXRhLCBwYXJhbXNBbmRQbGFjZWhvbGRlcnMpO1xuXG4gICAgLy8gQWRkIHBsYWNlaG9sZGVycyBpbiBoZWFkZXIgdG8gYWxsb3cgcGFyc2luZyBmb3IgcHJvZ3JhbW1hdGljIHVzZVxuICAgIC8vIG9mIHJlc3BvbnNlLCBpbnN0ZWFkIG9mIGhhdmluZyB0byBwYXJzZSB0aGUgSFRNTCBjb250ZW50LlxuICAgIGNvbnN0IGhlYWRlcnMgPSB0aGlzLmNvbXBvc2VQYWdlUGFyYW1IZWFkZXJzKHBhcmFtcyk7XG5cbiAgICByZXR1cm4geyB0ZXh0OiBkYXRhLCBoZWFkZXJzOiBoZWFkZXJzIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHJlc3BvbnNlIHdpdGggZmlsZSBjb250ZW50LlxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgZmlsZSB0byByZXR1cm4uXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBQcm9taXNlUm91dGVyIHJlc3BvbnNlLlxuICAgKi9cbiAgYXN5bmMgZmlsZVJlc3BvbnNlKHBhdGgpIHtcbiAgICAvLyBHZXQgZmlsZSBjb250ZW50XG4gICAgbGV0IGRhdGE7XG4gICAgdHJ5IHtcbiAgICAgIGRhdGEgPSBhd2FpdCB0aGlzLnJlYWRGaWxlKHBhdGgpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHRoaXMubm90Rm91bmQoKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB0ZXh0OiBkYXRhIH07XG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgYW5kIHJldHVybnMgdGhlIGNvbnRlbnQgb2YgYSBmaWxlIGF0IGEgZ2l2ZW4gcGF0aC4gRmlsZSByZWFkaW5nIHRvXG4gICAqIHNlcnZlIGNvbnRlbnQgb24gdGhlIHN0YXRpYyByb3V0ZSBpcyBvbmx5IGFsbG93ZWQgZnJvbSB0aGUgcGFnZXNcbiAgICogZGlyZWN0b3J5IG9uIGRvd253YXJkcy5cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogKipXQVJOSU5HOioqIEFsbCBmaWxlIHJlYWRzIGluIHRoZSBQYWdlc1JvdXRlciBtdXN0IGJlIGV4ZWN1dGVkIGJ5IHRoaXNcbiAgICogd3JhcHBlciBiZWNhdXNlIGl0IGFsc28gZGV0ZWN0cyBhbmQgcHJldmVudHMgY29tbW9uIGV4cGxvaXRzLlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZmlsZVBhdGggVGhlIHBhdGggdG8gdGhlIGZpbGUgdG8gcmVhZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3RyaW5nPn0gVGhlIGZpbGUgY29udGVudC5cbiAgICovXG4gIGFzeW5jIHJlYWRGaWxlKGZpbGVQYXRoKSB7XG4gICAgLy8gTm9ybWFsaXplIHBhdGggdG8gcHJldmVudCBpdCBmcm9tIGNvbnRhaW5pbmcgYW55IGRpcmVjdG9yeSBjaGFuZ2luZ1xuICAgIC8vIFVOSVggcGF0dGVybnMgd2hpY2ggY291bGQgZXhwb3NlIHRoZSB3aG9sZSBmaWxlIHN5c3RlbSwgZS5nLlxuICAgIC8vIGBodHRwOi8vZXhhbXBsZS5jb20vcGFyc2UvYXBwcy8uLi9maWxlLnR4dGAgcmVxdWVzdHMgYSBmaWxlIG91dHNpZGVcbiAgICAvLyBvZiB0aGUgcGFnZXMgZGlyZWN0b3J5IHNjb3BlLlxuICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gcGF0aC5ub3JtYWxpemUoZmlsZVBhdGgpO1xuXG4gICAgLy8gQWJvcnQgaWYgdGhlIHBhdGggaXMgb3V0c2lkZSBvZiB0aGUgcGF0aCBkaXJlY3Rvcnkgc2NvcGVcbiAgICBpZiAoIW5vcm1hbGl6ZWRQYXRoLnN0YXJ0c1dpdGgodGhpcy5wYWdlc1BhdGggKyBwYXRoLnNlcCkpIHtcbiAgICAgIHRocm93IGVycm9ycy5maWxlT3V0c2lkZUFsbG93ZWRTY29wZTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgZnMucmVhZEZpbGUobm9ybWFsaXplZFBhdGgsICd1dGYtOCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIGEgbGFuZ3VhZ2UgcmVzb3VyY2UgSlNPTiBmaWxlIHRoYXQgaXMgdXNlZCBmb3IgdHJhbnNsYXRpb25zLlxuICAgKi9cbiAgbG9hZEpzb25SZXNvdXJjZSgpIHtcbiAgICBpZiAodGhpcy5wYWdlc0NvbmZpZy5sb2NhbGl6YXRpb25Kc29uUGF0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBqc29uID0gcmVxdWlyZShwYXRoLnJlc29sdmUoJy4vJywgdGhpcy5wYWdlc0NvbmZpZy5sb2NhbGl6YXRpb25Kc29uUGF0aCkpO1xuICAgICAgdGhpcy5qc29uUGFyYW1ldGVycyA9IGpzb247XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aHJvdyBlcnJvcnMuanNvbkZhaWxlZEZpbGVMb2FkaW5nO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0cyBhbmQgcmV0dXJucyB0aGUgcGFnZSBkZWZhdWx0IHBhcmFtZXRlcnMgZnJvbSB0aGUgUGFyc2UgU2VydmVyXG4gICAqIGNvbmZpZ3VyYXRpb24uIFRoZXNlIHBhcmFtZXRlcnMgYXJlIG1hZGUgYWNjZXNzaWJsZSBpbiBldmVyeSBwYWdlIHNlcnZlZFxuICAgKiBieSB0aGlzIHJvdXRlci5cbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZyBUaGUgUGFyc2UgU2VydmVyIGNvbmZpZ3VyYXRpb24uXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkZWZhdWx0IHBhcmFtZXRlcnMuXG4gICAqL1xuICBnZXREZWZhdWx0UGFyYW1zKGNvbmZpZykge1xuICAgIHJldHVybiBjb25maWdcbiAgICAgID8ge1xuICAgICAgICBbcGFnZVBhcmFtcy5hcHBJZF06IGNvbmZpZy5hcHBJZCxcbiAgICAgICAgW3BhZ2VQYXJhbXMuYXBwTmFtZV06IGNvbmZpZy5hcHBOYW1lLFxuICAgICAgICBbcGFnZVBhcmFtcy5wdWJsaWNTZXJ2ZXJVcmxdOiBjb25maWcucHVibGljU2VydmVyVVJMLFxuICAgICAgfVxuICAgICAgOiB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0cyBhbmQgcmV0dXJucyB0aGUgbG9jYWxlIGZyb20gYW4gZXhwcmVzcyByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxIFRoZSBleHByZXNzIHJlcXVlc3QuXG4gICAqIEByZXR1cm5zIHtTdHJpbmd8dW5kZWZpbmVkfSBUaGUgbG9jYWxlLCBvciB1bmRlZmluZWQgaWYgbm8gbG9jYWxlIHdhcyBzZXQuXG4gICAqL1xuICBnZXRMb2NhbGUocmVxKSB7XG4gICAgY29uc3QgbG9jYWxlID1cbiAgICAgIChyZXEucXVlcnkgfHwge30pW3BhZ2VQYXJhbXMubG9jYWxlXSB8fFxuICAgICAgKHJlcS5ib2R5IHx8IHt9KVtwYWdlUGFyYW1zLmxvY2FsZV0gfHxcbiAgICAgIChyZXEucGFyYW1zIHx8IHt9KVtwYWdlUGFyYW1zLmxvY2FsZV0gfHxcbiAgICAgIChyZXEuaGVhZGVycyB8fCB7fSlbcGFnZVBhcmFtSGVhZGVyUHJlZml4ICsgcGFnZVBhcmFtcy5sb2NhbGVdO1xuXG4gICAgLy8gVmFsaWRhdGUgbG9jYWxlIGZvcm1hdCB0byBwcmV2ZW50IHBhdGggdHJhdmVyc2FsOyBvbmx5IGFsbG93XG4gICAgLy8gc3RhbmRhcmQgbG9jYWxlIHBhdHRlcm5zIGxpa2UgXCJlblwiLCBcImVuLVVTXCIsIFwiZGUtQVRcIiwgXCJ6aC1IYW5zLUNOXCJcbiAgICBpZiAobG9jYWxlICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGxvY2FsZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgbG9jYWxlID09PSAnc3RyaW5nJyAmJiAhL15bYS16QS1aXXsyLDN9KC1bYS16QS1aMC05XXsyLDh9KSokLy50ZXN0KGxvY2FsZSkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiBsb2NhbGU7XG4gIH1cblxuICAvKipcbiAgICogQ29tcG9zZXMgcGFnZSBwYXJhbWV0ZXIgaGVhZGVycyBmcm9tIHRoZSBnaXZlbiBwYXJhbWV0ZXJzLiBDb250cm9sXG4gICAqIGNoYXJhY3RlcnMgYXJlIGFsd2F5cyBzdHJpcHBlZCBmcm9tIGhlYWRlciB2YWx1ZXMgdG8gcHJldmVudFxuICAgKiBFUlJfSU5WQUxJRF9DSEFSIGVycm9ycy4gVmFsdWVzIGFyZSBVUkktZW5jb2RlZCBpZiB0aGVcbiAgICogYGVuY29kZVBhZ2VQYXJhbUhlYWRlcnNgIG9wdGlvbiBpcyBlbmFibGVkLlxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIFRoZSBwYXJhbWV0ZXJzIHRvIGluY2x1ZGUgaW4gdGhlIGhlYWRlcnMuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBoZWFkZXJzIG9iamVjdC5cbiAgICovXG4gIGNvbXBvc2VQYWdlUGFyYW1IZWFkZXJzKHBhcmFtcykge1xuICAgIGNvbnN0IGVuY29kZSA9IHRoaXMucGFnZXNDb25maWcuZW5jb2RlUGFnZVBhcmFtSGVhZGVycztcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMocGFyYW1zKS5yZWR1Y2UoKG0sIHApID0+IHtcbiAgICAgIGlmIChwWzFdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbGV0IHZhbHVlID0gZW5jb2RlID8gZW5jb2RlVVJJQ29tcG9uZW50KHBbMV0pIDogcFsxXTtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29udHJvbC1yZWdleFxuICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgvW1xceDAwLVxceDFmXFx4N2ZdL2csICcnKTtcbiAgICAgICAgfVxuICAgICAgICBtW2Ake3BhZ2VQYXJhbUhlYWRlclByZWZpeH0ke3BbMF0udG9Mb3dlckNhc2UoKX1gXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG07XG4gICAgfSwge30pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSByZXNwb25zZSB3aXRoIGh0dHAgcmVkaXJlY3QuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZXEgVGhlIGV4cHJlc3MgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIGZpbGUgdG8gcmV0dXJuLlxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIFRoZSBxdWVyeSBwYXJhbWV0ZXJzIHRvIGluY2x1ZGUuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBQcm9taXNlIFJvdXRlciByZXNwb25zZS5cbiAgICovXG4gIGFzeW5jIHJlZGlyZWN0UmVzcG9uc2UodXJsLCBwYXJhbXMpIHtcbiAgICAvLyBSZW1vdmUgYW55IHBhcmFtZXRlcnMgd2l0aCB1bmRlZmluZWQgdmFsdWVcbiAgICBwYXJhbXMgPSBPYmplY3QuZW50cmllcyhwYXJhbXMpLnJlZHVjZSgobSwgcCkgPT4ge1xuICAgICAgaWYgKHBbMV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBtW3BbMF1dID0gcFsxXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtO1xuICAgIH0sIHt9KTtcblxuICAgIC8vIENvbXBvc2UgVVJMIHdpdGggcGFyYW1ldGVycyBpbiBxdWVyeVxuICAgIGNvbnN0IGxvY2F0aW9uID0gbmV3IFVSTCh1cmwpO1xuICAgIE9iamVjdC5lbnRyaWVzKHBhcmFtcykuZm9yRWFjaChwID0+IGxvY2F0aW9uLnNlYXJjaFBhcmFtcy5zZXQocFswXSwgcFsxXSkpO1xuICAgIGNvbnN0IGxvY2F0aW9uU3RyaW5nID0gbG9jYXRpb24udG9TdHJpbmcoKTtcblxuICAgIC8vIEFkZCBwYXJhbWV0ZXJzIHRvIGhlYWRlciB0byBhbGxvdyBwYXJzaW5nIGZvciBwcm9ncmFtbWF0aWMgdXNlXG4gICAgLy8gb2YgcmVzcG9uc2UsIGluc3RlYWQgb2YgaGF2aW5nIHRvIHBhcnNlIHRoZSBIVE1MIGNvbnRlbnQuXG4gICAgY29uc3QgaGVhZGVycyA9IHRoaXMuY29tcG9zZVBhZ2VQYXJhbUhlYWRlcnMocGFyYW1zKTtcblxuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6IDMwMyxcbiAgICAgIGxvY2F0aW9uOiBsb2NhdGlvblN0cmluZyxcbiAgICAgIGhlYWRlcnM6IGhlYWRlcnMsXG4gICAgfTtcbiAgfVxuXG4gIGRlZmF1bHRQYWdlUGF0aChmaWxlKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbih0aGlzLnBhZ2VzUGF0aCwgZmlsZSk7XG4gIH1cblxuICBjb21wb3NlUGFnZVVybChmaWxlLCBwdWJsaWNTZXJ2ZXJVcmwsIGxvY2FsZSkge1xuICAgIGxldCB1cmwgPSBwdWJsaWNTZXJ2ZXJVcmw7XG4gICAgdXJsICs9IHVybC5lbmRzV2l0aCgnLycpID8gJycgOiAnLyc7XG4gICAgdXJsICs9IHRoaXMucGFnZXNFbmRwb2ludCArICcvJztcbiAgICB1cmwgKz0gbG9jYWxlID09PSB1bmRlZmluZWQgPyAnJyA6IGxvY2FsZSArICcvJztcbiAgICB1cmwgKz0gZmlsZTtcbiAgICByZXR1cm4gdXJsO1xuICB9XG5cbiAgbm90Rm91bmQoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRleHQ6ICdOb3QgZm91bmQuJyxcbiAgICAgIHN0YXR1czogNDA0LFxuICAgIH07XG4gIH1cblxuICBpbnZhbGlkUmVxdWVzdCgpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIGVycm9yLnN0YXR1cyA9IDQwMztcbiAgICBlcnJvci5tZXNzYWdlID0gJ3VuYXV0aG9yaXplZCc7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgUGFyc2UgU2VydmVyIGNvbmZpZ3VyYXRpb24gaW4gdGhlIHJlcXVlc3Qgb2JqZWN0IHRvIG1ha2UgaXRcbiAgICogZWFzaWx5IGFjY2Vzc2libGUgdGhyb3VnaHRvdXQgcmVxdWVzdCBwcm9jZXNzaW5nLlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVxIFRoZSByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZhaWxHcmFjZWZ1bGx5IElzIHRydWUgaWYgZmFpbGluZyB0byBzZXQgdGhlIGNvbmZpZyBzaG91bGRcbiAgICogbm90IHJlc3VsdCBpbiBhbiBpbnZhbGlkIHJlcXVlc3QgcmVzcG9uc2UuIERlZmF1bHQgaXMgYGZhbHNlYC5cbiAgICovXG4gIGFzeW5jIHNldENvbmZpZyhyZXEsIGZhaWxHcmFjZWZ1bGx5ID0gZmFsc2UpIHtcbiAgICByZXEuY29uZmlnID0gQ29uZmlnLmdldChyZXEucGFyYW1zLmFwcElkIHx8IHJlcS5xdWVyeS5hcHBJZCk7XG4gICAgaWYgKCFyZXEuY29uZmlnICYmICFmYWlsR3JhY2VmdWxseSkge1xuICAgICAgdGhpcy5pbnZhbGlkUmVxdWVzdCgpO1xuICAgIH1cbiAgICBpZiAocmVxLmNvbmZpZykge1xuICAgICAgYXdhaXQgcmVxLmNvbmZpZy5sb2FkS2V5cygpO1xuICAgIH1cbiAgfVxuXG4gIG1vdW50UGFnZXNSb3V0ZXMoKSB7XG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgYC8ke3RoaXMucGFnZXNFbmRwb2ludH0vOmFwcElkL3ZlcmlmeV9lbWFpbGAsXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXRDb25maWcocmVxKTtcbiAgICAgIH0sXG4gICAgICByZXEgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy52ZXJpZnlFbWFpbChyZXEpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ1BPU1QnLFxuICAgICAgYC8ke3RoaXMucGFnZXNFbmRwb2ludH0vOmFwcElkL3Jlc2VuZF92ZXJpZmljYXRpb25fZW1haWxgLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0Q29uZmlnKHJlcSk7XG4gICAgICB9LFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzZW5kVmVyaWZpY2F0aW9uRW1haWwocmVxKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgYC8ke3RoaXMucGFnZXNFbmRwb2ludH0vY2hvb3NlX3Bhc3N3b3JkYCxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldENvbmZpZyhyZXEpO1xuICAgICAgfSxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhc3N3b3JkUmVzZXQocmVxKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdQT1NUJyxcbiAgICAgIGAvJHt0aGlzLnBhZ2VzRW5kcG9pbnR9LzphcHBJZC9yZXF1ZXN0X3Bhc3N3b3JkX3Jlc2V0YCxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldENvbmZpZyhyZXEpO1xuICAgICAgfSxcbiAgICAgIHJlcSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlc2V0UGFzc3dvcmQocmVxKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy5yb3V0ZShcbiAgICAgICdHRVQnLFxuICAgICAgYC8ke3RoaXMucGFnZXNFbmRwb2ludH0vOmFwcElkL3JlcXVlc3RfcGFzc3dvcmRfcmVzZXRgLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0Q29uZmlnKHJlcSk7XG4gICAgICB9LFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVxdWVzdFJlc2V0UGFzc3dvcmQocmVxKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgbW91bnRDdXN0b21Sb3V0ZXMoKSB7XG4gICAgZm9yIChjb25zdCByb3V0ZSBvZiB0aGlzLnBhZ2VzQ29uZmlnLmN1c3RvbVJvdXRlcyB8fCBbXSkge1xuICAgICAgdGhpcy5yb3V0ZShcbiAgICAgICAgcm91dGUubWV0aG9kLFxuICAgICAgICBgLyR7dGhpcy5wYWdlc0VuZHBvaW50fS86YXBwSWQvJHtyb3V0ZS5wYXRofWAsXG4gICAgICAgIHJlcSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuc2V0Q29uZmlnKHJlcSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFzeW5jIHJlcSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBmaWxlLCBxdWVyeSA9IHt9IH0gPSAoYXdhaXQgcm91dGUuaGFuZGxlcihyZXEpKSB8fCB7fTtcblxuICAgICAgICAgIC8vIElmIHJvdXRlIGhhbmRsZXIgZGlkIG5vdCByZXR1cm4gYSBwYWdlIHNlbmQgNDA0IHJlc3BvbnNlXG4gICAgICAgICAgaWYgKCFmaWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ub3RGb3VuZCgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFNlbmQgcGFnZSByZXNwb25zZVxuICAgICAgICAgIGNvbnN0IHBhZ2UgPSBuZXcgUGFnZSh7IGlkOiBmaWxlLCBkZWZhdWx0RmlsZTogZmlsZSB9KTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5nb1RvUGFnZShyZXEsIHBhZ2UsIHF1ZXJ5LCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgbW91bnRTdGF0aWNSb3V0ZSgpIHtcbiAgICB0aGlzLnJvdXRlKFxuICAgICAgJ0dFVCcsXG4gICAgICBgLyR7dGhpcy5wYWdlc0VuZHBvaW50fS8qcmVzb3VyY2VgLFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0Q29uZmlnKHJlcSwgdHJ1ZSk7XG4gICAgICB9LFxuICAgICAgcmVxID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGljUm91dGUocmVxKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgZXhwcmVzc1JvdXRlcigpIHtcbiAgICBjb25zdCByb3V0ZXIgPSBleHByZXNzLlJvdXRlcigpO1xuICAgIHJvdXRlci51c2UoJy8nLCBzdXBlci5leHByZXNzUm91dGVyKCkpO1xuICAgIHJldHVybiByb3V0ZXI7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUGFnZXNSb3V0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgUGFnZXNSb3V0ZXIsXG4gIHBhZ2VQYXJhbUhlYWRlclByZWZpeCxcbiAgcGFnZVBh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SUFBSTtRQUNMLE9BQU8sSUFBSSxDQUFDcUgsU0FBUyxDQUFDckgsR0FBRyxDQUFDO01BQzVCLENBQUMsRUFDRCxNQUFNQSxHQUFHLElBQUk7UUFDWCxNQUFNO1VBQUVrSCxJQUFJO1VBQUUvRyxLQUFLLEdBQUcsQ0FBQztRQUFFLENBQUMsR0FBRyxDQUFDLE1BQU11SCxLQUFLLENBQUNFLE9BQU8sQ0FBQzVILEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQzs7UUFFN0Q7UUFDQSxJQUFJLENBQUNrSCxJQUFJLEVBQUU7VUFDVCxPQUFPLElBQUksQ0FBQ3pFLFFBQVEsQ0FBQyxDQUFDO1FBQ3hCOztRQUVBO1FBQ0EsTUFBTVQsSUFBSSxHQUFHLElBQUlwRSxhQUFJLENBQUM7VUFBRUMsRUFBRSxFQUFFcUosSUFBSTtVQUFFcEosV0FBVyxFQUFFb0o7UUFBSyxDQUFDLENBQUM7UUFDdEQsT0FBTyxJQUFJLENBQUM1RyxRQUFRLENBQUNOLEdBQUcsRUFBRWdDLElBQUksRUFBRTdCLEtBQUssRUFBRSxLQUFLLENBQUM7TUFDL0MsQ0FDRixDQUFDO0lBQ0g7RUFDRjtFQUVBTCxnQkFBZ0JBLENBQUEsRUFBRztJQUNqQixJQUFJLENBQUM0SCxLQUFLLENBQ1IsS0FBSyxFQUNMLElBQUksSUFBSSxDQUFDcEksYUFBYSxZQUFZLEVBQ2xDVSxHQUFHLElBQUk7TUFDTCxPQUFPLElBQUksQ0FBQ3FILFNBQVMsQ0FBQ3JILEdBQUcsRUFBRSxJQUFJLENBQUM7SUFDbEMsQ0FBQyxFQUNEQSxHQUFHLElBQUk7TUFDTCxPQUFPLElBQUksQ0FBQzRELFdBQVcsQ0FBQzVELEdBQUcsQ0FBQztJQUM5QixDQUNGLENBQUM7RUFDSDtFQUVBNkgsYUFBYUEsQ0FBQSxFQUFHO0lBQ2QsTUFBTUMsTUFBTSxHQUFHQyxnQkFBTyxDQUFDQyxNQUFNLENBQUMsQ0FBQztJQUMvQkYsTUFBTSxDQUFDRyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQ0osYUFBYSxDQUFDLENBQUMsQ0FBQztJQUN0QyxPQUFPQyxNQUFNO0VBQ2Y7QUFDRjtBQUFDSSxPQUFBLENBQUFoSixXQUFBLEdBQUFBLFdBQUE7QUFBQSxJQUFBaUosUUFBQSxHQUFBRCxPQUFBLENBQUEzSyxPQUFBLEdBRWMyQixXQUFXO0FBQzFCa0osTUFBTSxDQUFDRixPQUFPLEdBQUc7RUFDZmhKLFdBQVc7RUFDWEoscUJBQXFCO0VBQ3JCUixVQUFVO0VBQ1ZkO0FBQ0YsQ0FBQyIsImlnbm9yZUxpc3QiOltdfQ==
|