parse-server 2.8.4 → 8.6.2
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 +167 -25
- package/NOTICE +10 -0
- package/README.md +929 -278
- package/lib/AccountLockout.js +47 -30
- package/lib/Adapters/AdapterLoader.js +21 -6
- package/lib/Adapters/Analytics/AnalyticsAdapter.js +15 -12
- package/lib/Adapters/Auth/AuthAdapter.js +116 -13
- package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +99 -0
- package/lib/Adapters/Auth/OAuth1Client.js +27 -46
- package/lib/Adapters/Auth/apple.js +123 -0
- package/lib/Adapters/Auth/facebook.js +162 -35
- package/lib/Adapters/Auth/gcenter.js +217 -0
- package/lib/Adapters/Auth/github.js +118 -48
- package/lib/Adapters/Auth/google.js +160 -51
- package/lib/Adapters/Auth/gpgames.js +125 -0
- package/lib/Adapters/Auth/httpsRequest.js +6 -7
- package/lib/Adapters/Auth/index.js +170 -62
- package/lib/Adapters/Auth/instagram.js +114 -40
- package/lib/Adapters/Auth/janraincapture.js +52 -23
- package/lib/Adapters/Auth/janrainengage.js +19 -36
- package/lib/Adapters/Auth/keycloak.js +148 -0
- package/lib/Adapters/Auth/ldap.js +167 -0
- package/lib/Adapters/Auth/line.js +125 -0
- package/lib/Adapters/Auth/linkedin.js +111 -55
- package/lib/Adapters/Auth/meetup.js +24 -34
- package/lib/Adapters/Auth/mfa.js +324 -0
- package/lib/Adapters/Auth/microsoft.js +111 -0
- package/lib/Adapters/Auth/oauth2.js +97 -162
- package/lib/Adapters/Auth/phantauth.js +53 -0
- package/lib/Adapters/Auth/qq.js +108 -49
- package/lib/Adapters/Auth/spotify.js +107 -55
- package/lib/Adapters/Auth/twitter.js +188 -48
- package/lib/Adapters/Auth/utils.js +28 -0
- package/lib/Adapters/Auth/vkontakte.js +26 -39
- package/lib/Adapters/Auth/wechat.js +106 -44
- package/lib/Adapters/Auth/weibo.js +132 -58
- package/lib/Adapters/Cache/CacheAdapter.js +13 -8
- package/lib/Adapters/Cache/InMemoryCache.js +3 -13
- package/lib/Adapters/Cache/InMemoryCacheAdapter.js +5 -13
- package/lib/Adapters/Cache/LRUCache.js +13 -27
- package/lib/Adapters/Cache/NullCacheAdapter.js +3 -8
- package/lib/Adapters/Cache/RedisCacheAdapter.js +85 -76
- package/lib/Adapters/Cache/SchemaCache.js +25 -0
- package/lib/Adapters/Email/MailAdapter.js +10 -8
- package/lib/Adapters/Files/FilesAdapter.js +83 -25
- package/lib/Adapters/Files/GridFSBucketAdapter.js +231 -0
- package/lib/Adapters/Files/GridStoreAdapter.js +4 -91
- package/lib/Adapters/Logger/LoggerAdapter.js +18 -14
- package/lib/Adapters/Logger/WinstonLogger.js +69 -88
- package/lib/Adapters/Logger/WinstonLoggerAdapter.js +7 -16
- package/lib/Adapters/MessageQueue/EventEmitterMQ.js +8 -26
- package/lib/Adapters/PubSub/EventEmitterPubSub.js +12 -25
- package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
- package/lib/Adapters/PubSub/RedisPubSub.js +42 -19
- package/lib/Adapters/Push/PushAdapter.js +14 -7
- package/lib/Adapters/Storage/Mongo/MongoCollection.js +137 -45
- package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +158 -63
- package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +320 -168
- package/lib/Adapters/Storage/Mongo/MongoTransform.js +279 -306
- package/lib/Adapters/Storage/Postgres/PostgresClient.js +14 -10
- package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +47 -21
- package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +854 -468
- package/lib/Adapters/Storage/Postgres/sql/index.js +4 -6
- package/lib/Adapters/Storage/StorageAdapter.js +1 -1
- package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
- package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
- package/lib/Auth.js +488 -125
- package/lib/ClientSDK.js +2 -6
- package/lib/Config.js +525 -94
- package/lib/Controllers/AdaptableController.js +5 -25
- package/lib/Controllers/AnalyticsController.js +22 -23
- package/lib/Controllers/CacheController.js +10 -31
- package/lib/Controllers/DatabaseController.js +767 -313
- package/lib/Controllers/FilesController.js +49 -54
- package/lib/Controllers/HooksController.js +80 -84
- package/lib/Controllers/LiveQueryController.js +35 -22
- package/lib/Controllers/LoggerController.js +22 -58
- package/lib/Controllers/ParseGraphQLController.js +293 -0
- package/lib/Controllers/PushController.js +58 -49
- package/lib/Controllers/SchemaController.js +916 -422
- package/lib/Controllers/UserController.js +265 -180
- package/lib/Controllers/index.js +90 -125
- package/lib/Controllers/types.js +1 -1
- package/lib/Deprecator/Deprecations.js +30 -0
- package/lib/Deprecator/Deprecator.js +127 -0
- package/lib/Error.js +48 -0
- package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
- package/lib/GraphQL/ParseGraphQLServer.js +214 -0
- package/lib/GraphQL/helpers/objectsMutations.js +30 -0
- package/lib/GraphQL/helpers/objectsQueries.js +246 -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 +1098 -0
- package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
- package/lib/GraphQL/loaders/filesMutations.js +107 -0
- package/lib/GraphQL/loaders/functionsMutations.js +78 -0
- package/lib/GraphQL/loaders/parseClassMutations.js +268 -0
- package/lib/GraphQL/loaders/parseClassQueries.js +127 -0
- package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
- package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
- package/lib/GraphQL/loaders/schemaMutations.js +162 -0
- package/lib/GraphQL/loaders/schemaQueries.js +81 -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 +63 -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 +274 -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/KeyPromiseQueue.js +48 -0
- package/lib/LiveQuery/Client.js +25 -33
- package/lib/LiveQuery/Id.js +2 -5
- package/lib/LiveQuery/ParseCloudCodePublisher.js +26 -23
- package/lib/LiveQuery/ParseLiveQueryServer.js +560 -285
- package/lib/LiveQuery/ParsePubSub.js +7 -16
- package/lib/LiveQuery/ParseWebSocketServer.js +42 -39
- package/lib/LiveQuery/QueryTools.js +76 -15
- package/lib/LiveQuery/RequestSchema.js +111 -97
- package/lib/LiveQuery/SessionTokenCache.js +23 -36
- package/lib/LiveQuery/Subscription.js +8 -17
- package/lib/LiveQuery/equalObjects.js +2 -3
- package/lib/Options/Definitions.js +1355 -382
- package/lib/Options/docs.js +301 -62
- package/lib/Options/index.js +11 -1
- package/lib/Options/parsers.js +14 -10
- package/lib/Page.js +44 -0
- package/lib/ParseMessageQueue.js +6 -13
- package/lib/ParseServer.js +474 -235
- package/lib/ParseServerRESTController.js +102 -40
- package/lib/PromiseRouter.js +39 -50
- package/lib/Push/PushQueue.js +24 -30
- package/lib/Push/PushWorker.js +32 -56
- package/lib/Push/utils.js +22 -35
- package/lib/RestQuery.js +361 -139
- package/lib/RestWrite.js +713 -344
- package/lib/Routers/AggregateRouter.js +97 -71
- package/lib/Routers/AnalyticsRouter.js +8 -14
- package/lib/Routers/AudiencesRouter.js +16 -35
- package/lib/Routers/ClassesRouter.js +86 -72
- package/lib/Routers/CloudCodeRouter.js +28 -37
- package/lib/Routers/FeaturesRouter.js +22 -25
- package/lib/Routers/FilesRouter.js +266 -171
- package/lib/Routers/FunctionsRouter.js +87 -103
- package/lib/Routers/GlobalConfigRouter.js +94 -33
- package/lib/Routers/GraphQLRouter.js +41 -0
- package/lib/Routers/HooksRouter.js +43 -47
- package/lib/Routers/IAPValidationRouter.js +57 -70
- package/lib/Routers/InstallationsRouter.js +17 -25
- package/lib/Routers/LogsRouter.js +10 -25
- package/lib/Routers/PagesRouter.js +647 -0
- package/lib/Routers/PublicAPIRouter.js +104 -112
- package/lib/Routers/PurgeRouter.js +19 -29
- package/lib/Routers/PushRouter.js +14 -28
- package/lib/Routers/RolesRouter.js +7 -14
- package/lib/Routers/SchemasRouter.js +63 -42
- package/lib/Routers/SecurityRouter.js +34 -0
- package/lib/Routers/SessionsRouter.js +25 -38
- package/lib/Routers/UsersRouter.js +463 -190
- 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 +96 -0
- package/lib/Security/CheckGroups/CheckGroups.js +21 -0
- package/lib/Security/CheckRunner.js +213 -0
- package/lib/SharedRest.js +29 -0
- package/lib/StatusHandler.js +96 -93
- package/lib/TestUtils.js +70 -14
- package/lib/Utils.js +468 -0
- package/lib/batch.js +74 -40
- package/lib/cache.js +8 -8
- package/lib/cli/definitions/parse-live-query-server.js +4 -3
- package/lib/cli/definitions/parse-server.js +4 -3
- package/lib/cli/parse-live-query-server.js +9 -17
- package/lib/cli/parse-server.js +49 -47
- package/lib/cli/utils/commander.js +20 -29
- package/lib/cli/utils/runner.js +31 -32
- package/lib/cloud-code/Parse.Cloud.js +711 -36
- package/lib/cloud-code/Parse.Server.js +21 -0
- package/lib/cryptoUtils.js +6 -11
- package/lib/defaults.js +21 -15
- package/lib/deprecated.js +1 -1
- package/lib/index.js +78 -67
- package/lib/logger.js +12 -20
- package/lib/middlewares.js +484 -160
- package/lib/password.js +10 -6
- package/lib/request.js +175 -0
- package/lib/requiredParameter.js +4 -3
- package/lib/rest.js +157 -82
- package/lib/triggers.js +627 -185
- package/lib/vendor/README.md +3 -3
- package/lib/vendor/mongodbUrl.js +224 -137
- package/package.json +135 -57
- package/postinstall.js +38 -50
- package/public_html/invalid_verification_link.html +3 -3
- 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 +301 -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/CHANGELOG.md +0 -1246
- package/PATENTS +0 -37
- package/bin/dev +0 -37
- package/lib/.DS_Store +0 -0
- package/lib/Adapters/Auth/common.js +0 -2
- package/lib/Adapters/Auth/facebookaccountkit.js +0 -69
- package/lib/Controllers/SchemaCache.js +0 -97
- package/lib/LiveQuery/.DS_Store +0 -0
- package/lib/cli/utils/parsers.js +0 -77
- package/lib/cloud-code/.DS_Store +0 -0
- package/lib/cloud-code/HTTPResponse.js +0 -57
- package/lib/cloud-code/Untitled-1 +0 -123
- package/lib/cloud-code/httpRequest.js +0 -102
- package/lib/cloud-code/team.html +0 -123
- package/lib/graphql/ParseClass.js +0 -234
- package/lib/graphql/Schema.js +0 -197
- package/lib/graphql/index.js +0 -1
- package/lib/graphql/types/ACL.js +0 -35
- package/lib/graphql/types/Date.js +0 -25
- package/lib/graphql/types/File.js +0 -24
- package/lib/graphql/types/GeoPoint.js +0 -35
- package/lib/graphql/types/JSONObject.js +0 -30
- package/lib/graphql/types/NumberInput.js +0 -43
- package/lib/graphql/types/NumberQuery.js +0 -42
- package/lib/graphql/types/Pointer.js +0 -35
- package/lib/graphql/types/QueryConstraint.js +0 -61
- package/lib/graphql/types/StringQuery.js +0 -39
- package/lib/graphql/types/index.js +0 -110
package/lib/middlewares.js
CHANGED
|
@@ -1,40 +1,87 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.addRateLimit = exports.DEFAULT_ALLOWED_HEADERS = void 0;
|
|
7
7
|
exports.allowCrossDomain = allowCrossDomain;
|
|
8
|
+
exports.allowDoubleForwardSlash = allowDoubleForwardSlash;
|
|
8
9
|
exports.allowMethodOverride = allowMethodOverride;
|
|
9
|
-
exports.
|
|
10
|
+
exports.checkIp = void 0;
|
|
10
11
|
exports.enforceMasterKeyAccess = enforceMasterKeyAccess;
|
|
12
|
+
exports.handleParseErrors = handleParseErrors;
|
|
13
|
+
exports.handleParseHeaders = handleParseHeaders;
|
|
14
|
+
exports.handleParseSession = void 0;
|
|
11
15
|
exports.promiseEnforceMasterKeyAccess = promiseEnforceMasterKeyAccess;
|
|
16
|
+
exports.promiseEnsureIdempotency = promiseEnsureIdempotency;
|
|
17
|
+
var _cache = _interopRequireDefault(require("./cache"));
|
|
18
|
+
var _node = _interopRequireDefault(require("parse/node"));
|
|
19
|
+
var _Auth = _interopRequireDefault(require("./Auth"));
|
|
20
|
+
var _Config = _interopRequireDefault(require("./Config"));
|
|
21
|
+
var _ClientSDK = _interopRequireDefault(require("./ClientSDK"));
|
|
22
|
+
var _logger = _interopRequireDefault(require("./logger"));
|
|
23
|
+
var _rest = _interopRequireDefault(require("./rest"));
|
|
24
|
+
var _MongoStorageAdapter = _interopRequireDefault(require("./Adapters/Storage/Mongo/MongoStorageAdapter"));
|
|
25
|
+
var _PostgresStorageAdapter = _interopRequireDefault(require("./Adapters/Storage/Postgres/PostgresStorageAdapter"));
|
|
26
|
+
var _expressRateLimit = _interopRequireDefault(require("express-rate-limit"));
|
|
27
|
+
var _Definitions = require("./Options/Definitions");
|
|
28
|
+
var _pathToRegexp = require("path-to-regexp");
|
|
29
|
+
var _rateLimitRedis = _interopRequireDefault(require("rate-limit-redis"));
|
|
30
|
+
var _redis = require("redis");
|
|
31
|
+
var _net = require("net");
|
|
32
|
+
var _Error = require("./Error");
|
|
33
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
34
|
+
const DEFAULT_ALLOWED_HEADERS = exports.DEFAULT_ALLOWED_HEADERS = 'X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-Parse-Request-Id, Content-Type, Pragma, Cache-Control';
|
|
35
|
+
const getMountForRequest = function (req) {
|
|
36
|
+
const mountPathLength = req.originalUrl.length - req.url.length;
|
|
37
|
+
const mountPath = req.originalUrl.slice(0, mountPathLength);
|
|
38
|
+
return req.protocol + '://' + req.get('host') + mountPath;
|
|
39
|
+
};
|
|
40
|
+
const getBlockList = (ipRangeList, store) => {
|
|
41
|
+
if (store.get('blockList')) {
|
|
42
|
+
return store.get('blockList');
|
|
43
|
+
}
|
|
44
|
+
const blockList = new _net.BlockList();
|
|
45
|
+
ipRangeList.forEach(fullIp => {
|
|
46
|
+
if (fullIp === '::/0' || fullIp === '::') {
|
|
47
|
+
store.set('allowAllIpv6', true);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (fullIp === '0.0.0.0/0' || fullIp === '0.0.0.0') {
|
|
51
|
+
store.set('allowAllIpv4', true);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const [ip, mask] = fullIp.split('/');
|
|
55
|
+
if (!mask) {
|
|
56
|
+
blockList.addAddress(ip, (0, _net.isIPv4)(ip) ? 'ipv4' : 'ipv6');
|
|
57
|
+
} else {
|
|
58
|
+
blockList.addSubnet(ip, Number(mask), (0, _net.isIPv4)(ip) ? 'ipv4' : 'ipv6');
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
store.set('blockList', blockList);
|
|
62
|
+
return blockList;
|
|
63
|
+
};
|
|
64
|
+
const checkIp = (ip, ipRangeList, store) => {
|
|
65
|
+
const incomingIpIsV4 = (0, _net.isIPv4)(ip);
|
|
66
|
+
const blockList = getBlockList(ipRangeList, store);
|
|
67
|
+
if (store.get(ip)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
if (store.get('allowAllIpv4') && incomingIpIsV4) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
if (store.get('allowAllIpv6') && !incomingIpIsV4) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
const result = blockList.check(ip, incomingIpIsV4 ? 'ipv4' : 'ipv6');
|
|
12
77
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
var _node = require('parse/node');
|
|
22
|
-
|
|
23
|
-
var _node2 = _interopRequireDefault(_node);
|
|
24
|
-
|
|
25
|
-
var _Auth = require('./Auth');
|
|
26
|
-
|
|
27
|
-
var _Auth2 = _interopRequireDefault(_Auth);
|
|
28
|
-
|
|
29
|
-
var _Config = require('./Config');
|
|
30
|
-
|
|
31
|
-
var _Config2 = _interopRequireDefault(_Config);
|
|
32
|
-
|
|
33
|
-
var _ClientSDK = require('./ClientSDK');
|
|
34
|
-
|
|
35
|
-
var _ClientSDK2 = _interopRequireDefault(_ClientSDK);
|
|
36
|
-
|
|
37
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
78
|
+
// If the ip is in the list, we store the result in the store
|
|
79
|
+
// so we have a optimized path for the next request
|
|
80
|
+
if (ipRangeList.includes(ip) && result) {
|
|
81
|
+
store.set(ip, result);
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
};
|
|
38
85
|
|
|
39
86
|
// Checks that the request is authorized for this app and checks user
|
|
40
87
|
// auth too.
|
|
@@ -42,56 +89,67 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
42
89
|
// Adds info to the request:
|
|
43
90
|
// req.config - the Config for this app
|
|
44
91
|
// req.auth - the Auth for this request
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
|
|
92
|
+
exports.checkIp = checkIp;
|
|
93
|
+
async function handleParseHeaders(req, res, next) {
|
|
94
|
+
var mount = getMountForRequest(req);
|
|
95
|
+
let context = {};
|
|
96
|
+
if (req.get('X-Parse-Cloud-Context') != null) {
|
|
97
|
+
try {
|
|
98
|
+
context = JSON.parse(req.get('X-Parse-Cloud-Context'));
|
|
99
|
+
if (Object.prototype.toString.call(context) !== '[object Object]') {
|
|
100
|
+
throw 'Context is not an object';
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
return malformedContext(req, res);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
50
106
|
var info = {
|
|
51
107
|
appId: req.get('X-Parse-Application-Id'),
|
|
52
108
|
sessionToken: req.get('X-Parse-Session-Token'),
|
|
53
109
|
masterKey: req.get('X-Parse-Master-Key'),
|
|
110
|
+
maintenanceKey: req.get('X-Parse-Maintenance-Key'),
|
|
54
111
|
installationId: req.get('X-Parse-Installation-Id'),
|
|
55
112
|
clientKey: req.get('X-Parse-Client-Key'),
|
|
56
113
|
javascriptKey: req.get('X-Parse-Javascript-Key'),
|
|
57
114
|
dotNetKey: req.get('X-Parse-Windows-Key'),
|
|
58
115
|
restAPIKey: req.get('X-Parse-REST-API-Key'),
|
|
59
|
-
clientVersion: req.get('X-Parse-Client-Version')
|
|
116
|
+
clientVersion: req.get('X-Parse-Client-Version'),
|
|
117
|
+
context: context
|
|
60
118
|
};
|
|
61
|
-
|
|
62
119
|
var basicAuth = httpAuth(req);
|
|
63
|
-
|
|
64
120
|
if (basicAuth) {
|
|
65
121
|
var basicAuthAppId = basicAuth.appId;
|
|
66
|
-
if (
|
|
122
|
+
if (_cache.default.get(basicAuthAppId)) {
|
|
67
123
|
info.appId = basicAuthAppId;
|
|
68
124
|
info.masterKey = basicAuth.masterKey || info.masterKey;
|
|
69
125
|
info.javascriptKey = basicAuth.javascriptKey || info.javascriptKey;
|
|
70
126
|
}
|
|
71
127
|
}
|
|
72
|
-
|
|
73
128
|
if (req.body) {
|
|
74
129
|
// Unity SDK sends a _noBody key which needs to be removed.
|
|
75
130
|
// Unclear at this point if action needs to be taken.
|
|
76
131
|
delete req.body._noBody;
|
|
77
132
|
}
|
|
78
|
-
|
|
79
133
|
var fileViaJSON = false;
|
|
80
|
-
|
|
81
|
-
if (!info.appId || !_cache2.default.get(info.appId)) {
|
|
134
|
+
if (!info.appId || !_cache.default.get(info.appId)) {
|
|
82
135
|
// See if we can find the app id on the body.
|
|
83
136
|
if (req.body instanceof Buffer) {
|
|
84
137
|
// The only chance to find the app id is if this is a file
|
|
85
138
|
// upload that actually is a JSON body. So try to parse it.
|
|
86
|
-
|
|
139
|
+
// https://github.com/parse-community/parse-server/issues/6589
|
|
140
|
+
// It is also possible that the client is trying to upload a file but forgot
|
|
141
|
+
// to provide x-parse-app-id in header and parse a binary file will fail
|
|
142
|
+
try {
|
|
143
|
+
req.body = JSON.parse(req.body);
|
|
144
|
+
} catch {
|
|
145
|
+
return invalidRequest(req, res);
|
|
146
|
+
}
|
|
87
147
|
fileViaJSON = true;
|
|
88
148
|
}
|
|
89
|
-
|
|
90
149
|
if (req.body) {
|
|
91
150
|
delete req.body._RevocableSession;
|
|
92
151
|
}
|
|
93
|
-
|
|
94
|
-
if (req.body && req.body._ApplicationId && _cache2.default.get(req.body._ApplicationId) && (!info.masterKey || _cache2.default.get(req.body._ApplicationId).masterKey === info.masterKey)) {
|
|
152
|
+
if (req.body && req.body._ApplicationId && _cache.default.get(req.body._ApplicationId) && (!info.masterKey || _cache.default.get(req.body._ApplicationId).masterKey === info.masterKey)) {
|
|
95
153
|
info.appId = req.body._ApplicationId;
|
|
96
154
|
info.javascriptKey = req.body._JavaScriptKey || '';
|
|
97
155
|
delete req.body._ApplicationId;
|
|
@@ -114,6 +172,21 @@ function handleParseHeaders(req, res, next) {
|
|
|
114
172
|
info.masterKey = req.body._MasterKey;
|
|
115
173
|
delete req.body._MasterKey;
|
|
116
174
|
}
|
|
175
|
+
if (req.body._context) {
|
|
176
|
+
if (req.body._context instanceof Object) {
|
|
177
|
+
info.context = req.body._context;
|
|
178
|
+
} else {
|
|
179
|
+
try {
|
|
180
|
+
info.context = JSON.parse(req.body._context);
|
|
181
|
+
if (Object.prototype.toString.call(info.context) !== '[object Object]') {
|
|
182
|
+
throw 'Context is not an object';
|
|
183
|
+
}
|
|
184
|
+
} catch {
|
|
185
|
+
return malformedContext(req, res);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
delete req.body._context;
|
|
189
|
+
}
|
|
117
190
|
if (req.body._ContentType) {
|
|
118
191
|
req.headers['content-type'] = req.body._ContentType;
|
|
119
192
|
delete req.body._ContentType;
|
|
@@ -122,132 +195,191 @@ function handleParseHeaders(req, res, next) {
|
|
|
122
195
|
return invalidRequest(req, res);
|
|
123
196
|
}
|
|
124
197
|
}
|
|
125
|
-
|
|
198
|
+
if (info.sessionToken && typeof info.sessionToken !== 'string') {
|
|
199
|
+
info.sessionToken = info.sessionToken.toString();
|
|
200
|
+
}
|
|
126
201
|
if (info.clientVersion) {
|
|
127
|
-
info.clientSDK =
|
|
202
|
+
info.clientSDK = _ClientSDK.default.fromString(info.clientVersion);
|
|
128
203
|
}
|
|
129
|
-
|
|
130
|
-
|
|
204
|
+
if (fileViaJSON && req.body) {
|
|
205
|
+
req.fileData = req.body.fileData;
|
|
131
206
|
// We need to repopulate req.body with a buffer
|
|
132
207
|
var base64 = req.body.base64;
|
|
133
|
-
req.body =
|
|
208
|
+
req.body = Buffer.from(base64, 'base64');
|
|
134
209
|
}
|
|
135
|
-
|
|
136
210
|
const clientIp = getClientIp(req);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
211
|
+
const config = _Config.default.get(info.appId, mount);
|
|
212
|
+
if (config.state && config.state !== 'ok') {
|
|
213
|
+
res.status(500);
|
|
214
|
+
res.json({
|
|
215
|
+
code: _node.default.Error.INTERNAL_SERVER_ERROR,
|
|
216
|
+
error: `Invalid server state: ${config.state}`
|
|
217
|
+
});
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
await config.loadKeys();
|
|
221
|
+
info.app = _cache.default.get(info.appId);
|
|
222
|
+
req.config = config;
|
|
140
223
|
req.config.headers = req.headers || {};
|
|
141
224
|
req.config.ip = clientIp;
|
|
142
225
|
req.info = info;
|
|
143
|
-
|
|
144
|
-
if (
|
|
145
|
-
|
|
226
|
+
const isMaintenance = req.config.maintenanceKey && info.maintenanceKey === req.config.maintenanceKey;
|
|
227
|
+
if (isMaintenance) {
|
|
228
|
+
if (checkIp(clientIp, req.config.maintenanceKeyIps || [], req.config.maintenanceKeyIpsStore)) {
|
|
229
|
+
req.auth = new _Auth.default.Auth({
|
|
230
|
+
config: req.config,
|
|
231
|
+
installationId: info.installationId,
|
|
232
|
+
isMaintenance: true
|
|
233
|
+
});
|
|
234
|
+
next();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const log = req.config?.loggerController || _logger.default;
|
|
238
|
+
log.error(`Request using maintenance key rejected as the request IP address '${clientIp}' is not set in Parse Server option 'maintenanceKeyIps'.`);
|
|
239
|
+
}
|
|
240
|
+
const masterKey = await req.config.loadMasterKey();
|
|
241
|
+
let isMaster = info.masterKey === masterKey;
|
|
242
|
+
if (isMaster && !checkIp(clientIp, req.config.masterKeyIps || [], req.config.masterKeyIpsStore)) {
|
|
243
|
+
const log = req.config?.loggerController || _logger.default;
|
|
244
|
+
log.error(`Request using master key rejected as the request IP address '${clientIp}' is not set in Parse Server option 'masterKeyIps'.`);
|
|
245
|
+
isMaster = false;
|
|
246
|
+
const error = new Error();
|
|
247
|
+
error.status = 403;
|
|
248
|
+
error.message = `unauthorized`;
|
|
249
|
+
throw error;
|
|
146
250
|
}
|
|
147
|
-
|
|
148
|
-
var isMaster = info.masterKey === req.config.masterKey;
|
|
149
|
-
|
|
150
251
|
if (isMaster) {
|
|
151
|
-
req.auth = new
|
|
152
|
-
|
|
153
|
-
|
|
252
|
+
req.auth = new _Auth.default.Auth({
|
|
253
|
+
config: req.config,
|
|
254
|
+
installationId: info.installationId,
|
|
255
|
+
isMaster: true
|
|
256
|
+
});
|
|
257
|
+
return handleRateLimit(req, res, next);
|
|
154
258
|
}
|
|
155
|
-
|
|
156
259
|
var isReadOnlyMaster = info.masterKey === req.config.readOnlyMasterKey;
|
|
157
260
|
if (typeof req.config.readOnlyMasterKey != 'undefined' && req.config.readOnlyMasterKey && isReadOnlyMaster) {
|
|
158
|
-
req.auth = new
|
|
159
|
-
|
|
160
|
-
|
|
261
|
+
req.auth = new _Auth.default.Auth({
|
|
262
|
+
config: req.config,
|
|
263
|
+
installationId: info.installationId,
|
|
264
|
+
isMaster: true,
|
|
265
|
+
isReadOnly: true
|
|
266
|
+
});
|
|
267
|
+
return handleRateLimit(req, res, next);
|
|
161
268
|
}
|
|
162
269
|
|
|
163
270
|
// Client keys are not required in parse-server, but if any have been configured in the server, validate them
|
|
164
271
|
// to preserve original behavior.
|
|
165
|
-
const keys = [
|
|
272
|
+
const keys = ['clientKey', 'javascriptKey', 'dotNetKey', 'restAPIKey'];
|
|
166
273
|
const oneKeyConfigured = keys.some(function (key) {
|
|
167
274
|
return req.config[key] !== undefined;
|
|
168
275
|
});
|
|
169
276
|
const oneKeyMatches = keys.some(function (key) {
|
|
170
277
|
return req.config[key] !== undefined && info[key] === req.config[key];
|
|
171
278
|
});
|
|
172
|
-
|
|
173
279
|
if (oneKeyConfigured && !oneKeyMatches) {
|
|
174
280
|
return invalidRequest(req, res);
|
|
175
281
|
}
|
|
176
|
-
|
|
177
|
-
if (req.url == "/login") {
|
|
282
|
+
if (req.url == '/login') {
|
|
178
283
|
delete info.sessionToken;
|
|
179
284
|
}
|
|
180
|
-
|
|
285
|
+
if (req.userFromJWT) {
|
|
286
|
+
req.auth = new _Auth.default.Auth({
|
|
287
|
+
config: req.config,
|
|
288
|
+
installationId: info.installationId,
|
|
289
|
+
isMaster: false,
|
|
290
|
+
user: req.userFromJWT
|
|
291
|
+
});
|
|
292
|
+
return handleRateLimit(req, res, next);
|
|
293
|
+
}
|
|
181
294
|
if (!info.sessionToken) {
|
|
182
|
-
req.auth = new
|
|
183
|
-
|
|
295
|
+
req.auth = new _Auth.default.Auth({
|
|
296
|
+
config: req.config,
|
|
297
|
+
installationId: info.installationId,
|
|
298
|
+
isMaster: false
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
handleRateLimit(req, res, next);
|
|
302
|
+
}
|
|
303
|
+
const handleRateLimit = async (req, res, next) => {
|
|
304
|
+
const rateLimits = req.config.rateLimits || [];
|
|
305
|
+
try {
|
|
306
|
+
await Promise.all(rateLimits.map(async limit => {
|
|
307
|
+
const pathExp = new RegExp(limit.path);
|
|
308
|
+
if (pathExp.test(req.url)) {
|
|
309
|
+
await limit.handler(req, res, err => {
|
|
310
|
+
if (err) {
|
|
311
|
+
if (err.code === _node.default.Error.CONNECTION_FAILED) {
|
|
312
|
+
throw err;
|
|
313
|
+
}
|
|
314
|
+
req.config.loggerController.error('An unknown error occured when attempting to apply the rate limiter: ', err);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}));
|
|
319
|
+
} catch (error) {
|
|
320
|
+
res.status(429);
|
|
321
|
+
res.json({
|
|
322
|
+
code: _node.default.Error.CONNECTION_FAILED,
|
|
323
|
+
error: error.message
|
|
324
|
+
});
|
|
184
325
|
return;
|
|
185
326
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
327
|
+
next();
|
|
328
|
+
};
|
|
329
|
+
const handleParseSession = async (req, res, next) => {
|
|
330
|
+
try {
|
|
331
|
+
const info = req.info;
|
|
332
|
+
if (req.auth || req.url === '/sessions/me') {
|
|
333
|
+
next();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
let requestAuth = null;
|
|
189
337
|
if (info.sessionToken && req.url === '/upgradeToRevocableSession' && info.sessionToken.indexOf('r:') != 0) {
|
|
190
|
-
|
|
338
|
+
requestAuth = await _Auth.default.getAuthForLegacySessionToken({
|
|
339
|
+
config: req.config,
|
|
340
|
+
installationId: info.installationId,
|
|
341
|
+
sessionToken: info.sessionToken
|
|
342
|
+
});
|
|
191
343
|
} else {
|
|
192
|
-
|
|
344
|
+
requestAuth = await _Auth.default.getAuthForSessionToken({
|
|
345
|
+
config: req.config,
|
|
346
|
+
installationId: info.installationId,
|
|
347
|
+
sessionToken: info.sessionToken
|
|
348
|
+
});
|
|
193
349
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
}).catch(error => {
|
|
200
|
-
if (error instanceof _node2.default.Error) {
|
|
350
|
+
req.auth = requestAuth;
|
|
351
|
+
next();
|
|
352
|
+
} catch (error) {
|
|
353
|
+
if (error instanceof _node.default.Error) {
|
|
201
354
|
next(error);
|
|
202
355
|
return;
|
|
203
|
-
} else {
|
|
204
|
-
// TODO: Determine the correct error scenario.
|
|
205
|
-
_logger2.default.error('error getting auth for sessionToken', error);
|
|
206
|
-
throw new _node2.default.Error(_node2.default.Error.UNKNOWN_ERROR, error);
|
|
207
356
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
function getClientIp(req) {
|
|
212
|
-
if (req.headers['x-forwarded-for']) {
|
|
213
|
-
// try to get from x-forwared-for if it set (behind reverse proxy)
|
|
214
|
-
return req.headers['x-forwarded-for'].split(',')[0];
|
|
215
|
-
} else if (req.connection && req.connection.remoteAddress) {
|
|
216
|
-
// no proxy, try getting from connection.remoteAddress
|
|
217
|
-
return req.connection.remoteAddress;
|
|
218
|
-
} else if (req.socket) {
|
|
219
|
-
// try to get it from req.socket
|
|
220
|
-
return req.socket.remoteAddress;
|
|
221
|
-
} else if (req.connection && req.connection.socket) {
|
|
222
|
-
// try to get it form the connection.socket
|
|
223
|
-
return req.connection.socket.remoteAddress;
|
|
224
|
-
} else {
|
|
225
|
-
// if non above, fallback.
|
|
226
|
-
return req.ip;
|
|
357
|
+
// TODO: Determine the correct error scenario.
|
|
358
|
+
req.config.loggerController.error('error getting auth for sessionToken', error);
|
|
359
|
+
throw new _node.default.Error(_node.default.Error.UNKNOWN_ERROR, error);
|
|
227
360
|
}
|
|
361
|
+
};
|
|
362
|
+
exports.handleParseSession = handleParseSession;
|
|
363
|
+
function getClientIp(req) {
|
|
364
|
+
return req.ip;
|
|
228
365
|
}
|
|
229
|
-
|
|
230
366
|
function httpAuth(req) {
|
|
231
|
-
if (!(req.req || req).headers.authorization)
|
|
232
|
-
|
|
367
|
+
if (!(req.req || req).headers.authorization) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
233
370
|
var header = (req.req || req).headers.authorization;
|
|
234
371
|
var appId, masterKey, javascriptKey;
|
|
235
372
|
|
|
236
373
|
// parse header
|
|
237
374
|
var authPrefix = 'basic ';
|
|
238
|
-
|
|
239
375
|
var match = header.toLowerCase().indexOf(authPrefix);
|
|
240
|
-
|
|
241
376
|
if (match == 0) {
|
|
242
377
|
var encodedAuth = header.substring(authPrefix.length, header.length);
|
|
243
378
|
var credentials = decodeBase64(encodedAuth).split(':');
|
|
244
|
-
|
|
245
379
|
if (credentials.length == 2) {
|
|
246
380
|
appId = credentials[0];
|
|
247
381
|
var key = credentials[1];
|
|
248
|
-
|
|
249
382
|
var jsKeyPrefix = 'javascript-key=';
|
|
250
|
-
|
|
251
383
|
var matchKey = key.indexOf(jsKeyPrefix);
|
|
252
384
|
if (matchKey == 0) {
|
|
253
385
|
javascriptKey = key.substring(jsKeyPrefix.length, key.length);
|
|
@@ -256,93 +388,285 @@ function httpAuth(req) {
|
|
|
256
388
|
}
|
|
257
389
|
}
|
|
258
390
|
}
|
|
259
|
-
|
|
260
|
-
|
|
391
|
+
return {
|
|
392
|
+
appId: appId,
|
|
393
|
+
masterKey: masterKey,
|
|
394
|
+
javascriptKey: javascriptKey
|
|
395
|
+
};
|
|
261
396
|
}
|
|
262
|
-
|
|
263
397
|
function decodeBase64(str) {
|
|
264
|
-
return
|
|
398
|
+
return Buffer.from(str, 'base64').toString();
|
|
265
399
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
400
|
+
function allowCrossDomain(appId) {
|
|
401
|
+
return (req, res, next) => {
|
|
402
|
+
const config = _Config.default.get(appId, getMountForRequest(req));
|
|
403
|
+
let allowHeaders = DEFAULT_ALLOWED_HEADERS;
|
|
404
|
+
if (config && config.allowHeaders) {
|
|
405
|
+
allowHeaders += `, ${config.allowHeaders.join(', ')}`;
|
|
406
|
+
}
|
|
407
|
+
const baseOrigins = typeof config?.allowOrigin === 'string' ? [config.allowOrigin] : config?.allowOrigin ?? ['*'];
|
|
408
|
+
const requestOrigin = req.headers.origin;
|
|
409
|
+
const allowOrigins = requestOrigin && baseOrigins.includes(requestOrigin) ? requestOrigin : baseOrigins[0];
|
|
410
|
+
res.header('Access-Control-Allow-Origin', allowOrigins);
|
|
411
|
+
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
412
|
+
res.header('Access-Control-Allow-Headers', allowHeaders);
|
|
413
|
+
res.header('Access-Control-Expose-Headers', 'X-Parse-Job-Status-Id, X-Parse-Push-Status-Id');
|
|
414
|
+
// intercept OPTIONS method
|
|
415
|
+
if ('OPTIONS' == req.method) {
|
|
416
|
+
res.sendStatus(200);
|
|
417
|
+
} else {
|
|
418
|
+
next();
|
|
419
|
+
}
|
|
420
|
+
};
|
|
278
421
|
}
|
|
279
|
-
|
|
280
422
|
function allowMethodOverride(req, res, next) {
|
|
281
|
-
if (req.method === 'POST' && req.body
|
|
423
|
+
if (req.method === 'POST' && req.body?._method) {
|
|
282
424
|
req.originalMethod = req.method;
|
|
283
425
|
req.method = req.body._method;
|
|
284
426
|
delete req.body._method;
|
|
285
427
|
}
|
|
286
428
|
next();
|
|
287
429
|
}
|
|
288
|
-
|
|
289
430
|
function handleParseErrors(err, req, res, next) {
|
|
290
|
-
|
|
431
|
+
const log = req.config && req.config.loggerController || _logger.default;
|
|
432
|
+
if (err instanceof _node.default.Error) {
|
|
433
|
+
if (req.config && req.config.enableExpressErrorHandler) {
|
|
434
|
+
return next(err);
|
|
435
|
+
}
|
|
291
436
|
let httpStatus;
|
|
292
437
|
// TODO: fill out this mapping
|
|
293
438
|
switch (err.code) {
|
|
294
|
-
case
|
|
439
|
+
case _node.default.Error.INTERNAL_SERVER_ERROR:
|
|
295
440
|
httpStatus = 500;
|
|
296
441
|
break;
|
|
297
|
-
case
|
|
442
|
+
case _node.default.Error.OBJECT_NOT_FOUND:
|
|
298
443
|
httpStatus = 404;
|
|
299
444
|
break;
|
|
300
445
|
default:
|
|
301
446
|
httpStatus = 400;
|
|
302
447
|
}
|
|
303
|
-
|
|
304
448
|
res.status(httpStatus);
|
|
305
|
-
res.json({
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
449
|
+
res.json({
|
|
450
|
+
code: err.code,
|
|
451
|
+
error: err.message
|
|
452
|
+
});
|
|
453
|
+
log.error('Parse error: ', err);
|
|
310
454
|
} else if (err.status && err.message) {
|
|
311
455
|
res.status(err.status);
|
|
312
|
-
res.json({
|
|
313
|
-
|
|
456
|
+
res.json({
|
|
457
|
+
error: err.message
|
|
458
|
+
});
|
|
459
|
+
if (!(process && process.env.TESTING)) {
|
|
460
|
+
next(err);
|
|
461
|
+
}
|
|
314
462
|
} else {
|
|
315
|
-
|
|
463
|
+
log.error('Uncaught internal server error.', err, err.stack);
|
|
316
464
|
res.status(500);
|
|
317
465
|
res.json({
|
|
318
|
-
code:
|
|
466
|
+
code: _node.default.Error.INTERNAL_SERVER_ERROR,
|
|
319
467
|
message: 'Internal server error.'
|
|
320
468
|
});
|
|
321
|
-
|
|
469
|
+
if (!(process && process.env.TESTING)) {
|
|
470
|
+
next(err);
|
|
471
|
+
}
|
|
322
472
|
}
|
|
323
473
|
}
|
|
324
|
-
|
|
325
474
|
function enforceMasterKeyAccess(req, res, next) {
|
|
326
475
|
if (!req.auth.isMaster) {
|
|
327
|
-
|
|
328
|
-
res.
|
|
476
|
+
const error = (0, _Error.createSanitizedHttpError)(403, 'unauthorized: master key is required', req.config);
|
|
477
|
+
res.status(error.status);
|
|
478
|
+
res.end(`{"error":"${error.message}"}`);
|
|
329
479
|
return;
|
|
330
480
|
}
|
|
331
481
|
next();
|
|
332
482
|
}
|
|
333
|
-
|
|
334
483
|
function promiseEnforceMasterKeyAccess(request) {
|
|
335
484
|
if (!request.auth.isMaster) {
|
|
336
|
-
|
|
337
|
-
error.status = 403;
|
|
338
|
-
error.message = "unauthorized: master key is required";
|
|
339
|
-
throw error;
|
|
485
|
+
throw (0, _Error.createSanitizedHttpError)(403, 'unauthorized: master key is required', request.config);
|
|
340
486
|
}
|
|
341
487
|
return Promise.resolve();
|
|
342
488
|
}
|
|
343
|
-
|
|
489
|
+
const addRateLimit = (route, config, cloud) => {
|
|
490
|
+
if (typeof config === 'string') {
|
|
491
|
+
config = _Config.default.get(config);
|
|
492
|
+
}
|
|
493
|
+
for (const key in route) {
|
|
494
|
+
if (!_Definitions.RateLimitOptions[key]) {
|
|
495
|
+
throw `Invalid rate limit option "${key}"`;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
if (!config.rateLimits) {
|
|
499
|
+
config.rateLimits = [];
|
|
500
|
+
}
|
|
501
|
+
const redisStore = {
|
|
502
|
+
connectionPromise: Promise.resolve(),
|
|
503
|
+
store: null
|
|
504
|
+
};
|
|
505
|
+
if (route.redisUrl) {
|
|
506
|
+
const log = config?.loggerController || _logger.default;
|
|
507
|
+
const client = (0, _redis.createClient)({
|
|
508
|
+
url: route.redisUrl
|
|
509
|
+
});
|
|
510
|
+
client.on('error', err => {
|
|
511
|
+
log.error('Middlewares addRateLimit Redis client error', {
|
|
512
|
+
error: err
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
client.on('connect', () => {});
|
|
516
|
+
client.on('reconnecting', () => {});
|
|
517
|
+
client.on('ready', () => {});
|
|
518
|
+
redisStore.connectionPromise = async () => {
|
|
519
|
+
if (client.isOpen) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
try {
|
|
523
|
+
await client.connect();
|
|
524
|
+
} catch (e) {
|
|
525
|
+
log.error(`Could not connect to redisURL in rate limit: ${e}`);
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
redisStore.connectionPromise();
|
|
529
|
+
redisStore.store = new _rateLimitRedis.default({
|
|
530
|
+
sendCommand: async (...args) => {
|
|
531
|
+
await redisStore.connectionPromise();
|
|
532
|
+
return client.sendCommand(args);
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
let transformPath = route.requestPath.split('/*').join('/(.*)');
|
|
537
|
+
if (transformPath === '*') {
|
|
538
|
+
transformPath = '(.*)';
|
|
539
|
+
}
|
|
540
|
+
config.rateLimits.push({
|
|
541
|
+
path: (0, _pathToRegexp.pathToRegexp)(transformPath),
|
|
542
|
+
handler: (0, _expressRateLimit.default)({
|
|
543
|
+
windowMs: route.requestTimeWindow,
|
|
544
|
+
max: route.requestCount,
|
|
545
|
+
message: route.errorResponseMessage || _Definitions.RateLimitOptions.errorResponseMessage.default,
|
|
546
|
+
handler: (request, response, next, options) => {
|
|
547
|
+
throw {
|
|
548
|
+
code: _node.default.Error.CONNECTION_FAILED,
|
|
549
|
+
message: options.message
|
|
550
|
+
};
|
|
551
|
+
},
|
|
552
|
+
skip: request => {
|
|
553
|
+
if (request.ip === '127.0.0.1' && !route.includeInternalRequests) {
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
556
|
+
if (route.includeMasterKey) {
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
if (route.requestMethods) {
|
|
560
|
+
if (Array.isArray(route.requestMethods)) {
|
|
561
|
+
if (!route.requestMethods.includes(request.method)) {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
} else {
|
|
565
|
+
const regExp = new RegExp(route.requestMethods);
|
|
566
|
+
if (!regExp.test(request.method)) {
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return request.auth?.isMaster;
|
|
572
|
+
},
|
|
573
|
+
keyGenerator: async request => {
|
|
574
|
+
if (route.zone === _node.default.Server.RateLimitZone.global) {
|
|
575
|
+
return request.config.appId;
|
|
576
|
+
}
|
|
577
|
+
const token = request.info.sessionToken;
|
|
578
|
+
if (route.zone === _node.default.Server.RateLimitZone.session && token) {
|
|
579
|
+
return token;
|
|
580
|
+
}
|
|
581
|
+
if (route.zone === _node.default.Server.RateLimitZone.user && token) {
|
|
582
|
+
if (!request.auth) {
|
|
583
|
+
await new Promise(resolve => handleParseSession(request, null, resolve));
|
|
584
|
+
}
|
|
585
|
+
if (request.auth?.user?.id && request.zone === 'user') {
|
|
586
|
+
return request.auth.user.id;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return request.config.ip;
|
|
590
|
+
},
|
|
591
|
+
store: redisStore.store
|
|
592
|
+
}),
|
|
593
|
+
cloud
|
|
594
|
+
});
|
|
595
|
+
_Config.default.put(config);
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Deduplicates a request to ensure idempotency. Duplicates are determined by the request ID
|
|
600
|
+
* in the request header. If a request has no request ID, it is executed anyway.
|
|
601
|
+
* @param {*} req The request to evaluate.
|
|
602
|
+
* @returns Promise<{}>
|
|
603
|
+
*/
|
|
604
|
+
exports.addRateLimit = addRateLimit;
|
|
605
|
+
function promiseEnsureIdempotency(req) {
|
|
606
|
+
// Enable feature only for MongoDB
|
|
607
|
+
if (!(req.config.database.adapter instanceof _MongoStorageAdapter.default || req.config.database.adapter instanceof _PostgresStorageAdapter.default)) {
|
|
608
|
+
return Promise.resolve();
|
|
609
|
+
}
|
|
610
|
+
// Get parameters
|
|
611
|
+
const config = req.config;
|
|
612
|
+
const requestId = ((req || {}).headers || {})['x-parse-request-id'];
|
|
613
|
+
const {
|
|
614
|
+
paths,
|
|
615
|
+
ttl
|
|
616
|
+
} = config.idempotencyOptions;
|
|
617
|
+
if (!requestId || !config.idempotencyOptions) {
|
|
618
|
+
return Promise.resolve();
|
|
619
|
+
}
|
|
620
|
+
// Request path may contain trailing slashes, depending on the original request, so remove
|
|
621
|
+
// leading and trailing slashes to make it easier to specify paths in the configuration
|
|
622
|
+
const reqPath = req.path.replace(/^\/|\/$/, '');
|
|
623
|
+
// Determine whether idempotency is enabled for current request path
|
|
624
|
+
let match = false;
|
|
625
|
+
for (const path of paths) {
|
|
626
|
+
// Assume one wants a path to always match from the beginning to prevent any mistakes
|
|
627
|
+
const regex = new RegExp(path.charAt(0) === '^' ? path : '^' + path);
|
|
628
|
+
if (reqPath.match(regex)) {
|
|
629
|
+
match = true;
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (!match) {
|
|
634
|
+
return Promise.resolve();
|
|
635
|
+
}
|
|
636
|
+
// Try to store request
|
|
637
|
+
const expiryDate = new Date(new Date().setSeconds(new Date().getSeconds() + ttl));
|
|
638
|
+
return _rest.default.create(config, _Auth.default.master(config), '_Idempotency', {
|
|
639
|
+
reqId: requestId,
|
|
640
|
+
expire: _node.default._encode(expiryDate)
|
|
641
|
+
}).catch(e => {
|
|
642
|
+
if (e.code == _node.default.Error.DUPLICATE_VALUE) {
|
|
643
|
+
throw new _node.default.Error(_node.default.Error.DUPLICATE_REQUEST, 'Duplicate request');
|
|
644
|
+
}
|
|
645
|
+
throw e;
|
|
646
|
+
});
|
|
647
|
+
}
|
|
344
648
|
function invalidRequest(req, res) {
|
|
345
649
|
res.status(403);
|
|
346
650
|
res.end('{"error":"unauthorized"}');
|
|
347
651
|
}
|
|
348
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9taWRkbGV3YXJlcy5qcyJdLCJuYW1lcyI6WyJoYW5kbGVQYXJzZUhlYWRlcnMiLCJhbGxvd0Nyb3NzRG9tYWluIiwiYWxsb3dNZXRob2RPdmVycmlkZSIsImhhbmRsZVBhcnNlRXJyb3JzIiwiZW5mb3JjZU1hc3RlcktleUFjY2VzcyIsInByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwicmVxIiwicmVzIiwibmV4dCIsIm1vdW50UGF0aExlbmd0aCIsIm9yaWdpbmFsVXJsIiwibGVuZ3RoIiwidXJsIiwibW91bnRQYXRoIiwic2xpY2UiLCJtb3VudCIsInByb3RvY29sIiwiZ2V0IiwiaW5mbyIsImFwcElkIiwic2Vzc2lvblRva2VuIiwibWFzdGVyS2V5IiwiaW5zdGFsbGF0aW9uSWQiLCJjbGllbnRLZXkiLCJqYXZhc2NyaXB0S2V5IiwiZG90TmV0S2V5IiwicmVzdEFQSUtleSIsImNsaWVudFZlcnNpb24iLCJiYXNpY0F1dGgiLCJodHRwQXV0aCIsImJhc2ljQXV0aEFwcElkIiwiQXBwQ2FjaGUiLCJib2R5IiwiX25vQm9keSIsImZpbGVWaWFKU09OIiwiQnVmZmVyIiwiSlNPTiIsInBhcnNlIiwiX1Jldm9jYWJsZVNlc3Npb24iLCJfQXBwbGljYXRpb25JZCIsIl9KYXZhU2NyaXB0S2V5IiwiX0NsaWVudFZlcnNpb24iLCJfSW5zdGFsbGF0aW9uSWQiLCJfU2Vzc2lvblRva2VuIiwiX01hc3RlcktleSIsIl9Db250ZW50VHlwZSIsImhlYWRlcnMiLCJpbnZhbGlkUmVxdWVzdCIsImNsaWVudFNESyIsIkNsaWVudFNESyIsImZyb21TdHJpbmciLCJiYXNlNjQiLCJjbGllbnRJcCIsImdldENsaWVudElwIiwiYXBwIiwiY29uZmlnIiwiQ29uZmlnIiwiaXAiLCJtYXN0ZXJLZXlJcHMiLCJpbmRleE9mIiwiaXNNYXN0ZXIiLCJhdXRoIiwiQXV0aCIsImlzUmVhZE9ubHlNYXN0ZXIiLCJyZWFkT25seU1hc3RlcktleSIsImlzUmVhZE9ubHkiLCJrZXlzIiwib25lS2V5Q29uZmlndXJlZCIsInNvbWUiLCJrZXkiLCJ1bmRlZmluZWQiLCJvbmVLZXlNYXRjaGVzIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwiZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbiIsImdldEF1dGhGb3JTZXNzaW9uVG9rZW4iLCJjYXRjaCIsImVycm9yIiwiUGFyc2UiLCJFcnJvciIsImxvZyIsIlVOS05PV05fRVJST1IiLCJzcGxpdCIsImNvbm5lY3Rpb24iLCJyZW1vdGVBZGRyZXNzIiwic29ja2V0IiwiYXV0aG9yaXphdGlvbiIsImhlYWRlciIsImF1dGhQcmVmaXgiLCJtYXRjaCIsInRvTG93ZXJDYXNlIiwiZW5jb2RlZEF1dGgiLCJzdWJzdHJpbmciLCJjcmVkZW50aWFscyIsImRlY29kZUJhc2U2NCIsImpzS2V5UHJlZml4IiwibWF0Y2hLZXkiLCJzdHIiLCJ0b1N0cmluZyIsIm1ldGhvZCIsInNlbmRTdGF0dXMiLCJfbWV0aG9kIiwib3JpZ2luYWxNZXRob2QiLCJlcnIiLCJodHRwU3RhdHVzIiwiY29kZSIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsIk9CSkVDVF9OT1RfRk9VTkQiLCJzdGF0dXMiLCJqc29uIiwibWVzc2FnZSIsImVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXIiLCJzdGFjayIsImVuZCIsInJlcXVlc3QiXSwibWFwcGluZ3MiOiI7Ozs7O1FBYWdCQSxrQixHQUFBQSxrQjtRQXdPQUMsZ0IsR0FBQUEsZ0I7UUFjQUMsbUIsR0FBQUEsbUI7UUFTQUMsaUIsR0FBQUEsaUI7UUFxQ0FDLHNCLEdBQUFBLHNCO1FBU0FDLDZCLEdBQUFBLDZCOztBQTFUaEI7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTTCxrQkFBVCxDQUE0Qk0sR0FBNUIsRUFBaUNDLEdBQWpDLEVBQXNDQyxJQUF0QyxFQUE0QztBQUNqRCxNQUFJQyxrQkFBa0JI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LEVBQUVoQyxPQUFPMEIsSUFBSU8sT0FBYixFQUFUO0FBQ0F2RyxTQUFLZ0csR0FBTDtBQUNELEdBSk0sTUFJQTtBQUNMdkIscUJBQUlILEtBQUosQ0FBVSxpQ0FBVixFQUE2QzBCLEdBQTdDLEVBQWtEQSxJQUFJUyxLQUF0RDtBQUNBMUcsUUFBSXNHLE1BQUosQ0FBVyxHQUFYO0FBQ0F0RyxRQUFJdUcsSUFBSixDQUFTO0FBQ1BKLFlBQU0zQixlQUFNQyxLQUFOLENBQVkyQixxQkFEWDtBQUVQSSxlQUFTO0FBRkYsS0FBVDtBQUlBdkcsU0FBS2dHLEdBQUw7QUFDRDtBQUVGOztBQUVNLFNBQVNwRyxzQkFBVCxDQUFnQ0UsR0FBaEMsRUFBcUNDLEdBQXJDLEVBQTBDQyxJQUExQyxFQUFnRDtBQUNyRCxNQUFJLENBQUNGLElBQUl1RCxJQUFKLENBQVNELFFBQWQsRUFBd0I7QUFDdEJyRCxRQUFJc0csTUFBSixDQUFXLEdBQVg7QUFDQXRHLFFBQUkyRyxHQUFKLENBQVEsa0RBQVI7QUFDQTtBQUNEO0FBQ0QxRztBQUNEOztBQUVNLFNBQVNILDZCQUFULENBQXVDOEcsT0FBdkMsRUFBZ0Q7QUFDckQsTUFBSSxDQUFDQSxRQUFRdEQsSUFBUixDQUFhRCxRQUFsQixFQUE0QjtBQUMxQixVQUFNa0IsUUFBUSxJQUFJRSxLQUFKLEVBQWQ7QUFDQUYsVUFBTStCLE1BQU4sR0FBZSxHQUFmO0FBQ0EvQixVQUFNaUMsT0FBTixHQUFnQixzQ0FBaEI7QUFDQSxVQUFNakMsS0FBTjtBQUNEO0FBQ0QsU0FBT04sUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQsU0FBUzFCLGNBQVQsQ0FBd0J6QyxHQUF4QixFQUE2QkMsR0FBN0IsRUFBa0M7QUFDaENBLE1BQUlzRyxNQUFKLENBQVcsR0FBWDtBQUNBdEcsTUFBSTJHLEdBQUosQ0FBUSwwQkFBUjtBQUNEIiwiZmlsZSI6Im1pZGRsZXdhcmVzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEFwcENhY2hlIGZyb20gJy4vY2FjaGUnO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgYXV0aCBmcm9tICcuL0F1dGgnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuL0NvbmZpZyc7XG5pbXBvcnQgQ2xpZW50U0RLIGZyb20gJy4vQ2xpZW50U0RLJztcblxuLy8gQ2hlY2tzIHRoYXQgdGhlIHJlcXVlc3QgaXMgYXV0aG9yaXplZCBmb3IgdGhpcyBhcHAgYW5kIGNoZWNrcyB1c2VyXG4vLyBhdXRoIHRvby5cbi8vIFRoZSBib2R5cGFyc2VyIHNob3VsZCBydW4gYmVmb3JlIHRoaXMgbWlkZGxld2FyZS5cbi8vIEFkZHMgaW5mbyB0byB0aGUgcmVxdWVzdDpcbi8vIHJlcS5jb25maWcgLSB0aGUgQ29uZmlnIGZvciB0aGlzIGFwcFxuLy8gcmVxLmF1dGggLSB0aGUgQXV0aCBmb3IgdGhpcyByZXF1ZXN0XG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlUGFyc2VIZWFkZXJzKHJlcSwgcmVzLCBuZXh0KSB7XG4gIHZhciBtb3VudFBhdGhMZW5ndGggPSByZXEub3JpZ2luYWxVcmwubGVuZ3RoIC0gcmVxLnVybC5sZW5ndGg7XG4gIHZhciBtb3VudFBhdGggPSByZXEub3JpZ2luYWxVcmwuc2xpY2UoMCwgbW91bnRQYXRoTGVuZ3RoKTtcbiAgdmFyIG1vdW50ID0gcmVxLnByb3RvY29sICsgJzovLycgKyByZXEuZ2V0KCdob3N0JykgKyBtb3VudFBhdGg7XG5cbiAgdmFyIGluZm8gPSB7XG4gICAgYXBwSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtQXBwbGljYXRpb24tSWQnKSxcbiAgICBzZXNzaW9uVG9rZW46IHJlcS5nZXQoJ1gtUGFyc2UtU2Vzc2lvbi1Ub2tlbicpLFxuICAgIG1hc3RlcktleTogcmVxLmdldCgnWC1QYXJzZS1NYXN0ZXItS2V5JyksXG4gICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtSW5zdGFsbGF0aW9uLUlkJyksXG4gICAgY2xpZW50S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1LZXknKSxcbiAgICBqYXZhc2NyaXB0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUphdmFzY3JpcHQtS2V5JyksXG4gICAgZG90TmV0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLVdpbmRvd3MtS2V5JyksXG4gICAgcmVzdEFQSUtleTogcmVxLmdldCgnWC1QYXJzZS1SRVNULUFQSS1LZXknKSxcbiAgICBjbGllbnRWZXJzaW9uOiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1WZXJzaW9uJylcbiAgfTtcblxuICB2YXIgYmFzaWNBdXRoID0gaHR0cEF1dGgocmVxKTtcblxuICBpZiAoYmFzaWNBdXRoKSB7XG4gICAgdmFyIGJhc2ljQXV0aEFwcElkID0gYmFzaWNBdXRoLmFwcElkO1xuICAgIGlmIChBcHBDYWNoZS5nZXQoYmFzaWNBdXRoQXBwSWQpKSB7XG4gICAgICBpbmZvLmFwcElkID0gYmFzaWNBdXRoQXBwSWQ7XG4gICAgICBpbmZvLm1hc3RlcktleSA9IGJhc2ljQXV0aC5tYXN0ZXJLZXkgfHwgaW5mby5tYXN0ZXJLZXk7XG4gICAgICBpbmZvLmphdmFzY3JpcHRLZXkgPSBiYXNpY0F1dGguamF2YXNjcmlwdEtleSB8fCBpbmZvLmphdmFzY3JpcHRLZXk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlcS5ib2R5KSB7XG4gICAgLy8gVW5pdHkgU0RLIHNlbmRzIGEgX25vQm9keSBrZXkgd2hpY2ggbmVlZHMgdG8gYmUgcmVtb3ZlZC5cbiAgICAvLyBVbmNsZWFyIGF0IHRoaXMgcG9pbnQgaWYgYWN0aW9uIG5lZWRzIHRvIGJlIHRha2VuLlxuICAgIGRlbGV0ZSByZXEuYm9keS5fbm9Cb2R5O1xuICB9XG5cbiAgdmFyIGZpbGVWaWFKU09OID0gZmFsc2U7XG5cbiAgaWYgKCFpbmZvLmFwcElkIHx8ICFBcHBDYWNoZS5nZXQoaW5mby5hcHBJZCkpIHtcbiAgICAvLyBTZWUgaWYgd2UgY2FuIGZpbmQgdGhlIGFwcCBpZCBvbiB0aGUgYm9keS5cbiAgICBpZiAocmVxLmJvZHkgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgIC8vIFRoZSBvbmx5IGNoYW5jZSB0byBmaW5kIHRoZSBhcHAgaWQgaXMgaWYgdGhpcyBpcyBhIGZpbGVcbiAgICAgIC8vIHVwbG9hZCB0aGF0IGFjdHVhbGx5IGlzIGEgSlNPTiBib2R5LiBTbyB0cnkgdG8gcGFyc2UgaXQuXG4gICAgICByZXEuYm9keSA9IEpTT04ucGFyc2UocmVxLmJvZHkpO1xuICAgICAgZmlsZVZpYUpTT04gPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZXEuYm9keSkge1xuICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9SZXZvY2FibGVTZXNzaW9uO1xuICAgIH1cblxuICAgIGlmIChyZXEuYm9keSAmJlxuICAgICAgcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQgJiZcbiAgICAgIEFwcENhY2hlLmdldChyZXEuYm9keS5fQXBwbGljYXRpb25JZCkgJiZcbiAgICAgICghaW5mby5tYXN0ZXJLZXkgfHwgQXBwQ2FjaGUuZ2V0KHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkKS5tYXN0ZXJLZXkgPT09IGluZm8ubWFzdGVyS2V5KVxuICAgICkge1xuICAgICAgaW5mby5hcHBJZCA9IHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkO1xuICAgICAgaW5mby5qYXZhc2NyaXB0S2V5ID0gcmVxLmJvZHkuX0phdmFTY3JpcHRLZXkgfHwgJyc7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQ7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX0phdmFTY3JpcHRLZXk7XG4gICAgICAvLyBUT0RPOiB0ZXN0IHRoYXQgdGhlIFJFU1QgQVBJIGZvcm1hdHMgZ2VuZXJhdGVkIGJ5IHRoZSBvdGhlclxuICAgICAgLy8gU0RLcyBhcmUgaGFuZGxlZCBva1xuICAgICAgaWYgKHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uKSB7XG4gICAgICAgIGluZm8uY2xpZW50VmVyc2lvbiA9IHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0NsaWVudFZlcnNpb247XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX0luc3RhbGxhdGlvbklkKSB7XG4gICAgICAgIGluZm8uaW5zdGFsbGF0aW9uSWQgPSByZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQ7XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fSW5zdGFsbGF0aW9uSWQ7XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX1Nlc3Npb25Ub2tlbikge1xuICAgICAgICBpbmZvLnNlc3Npb25Ub2tlbiA9IHJlcS5ib2R5Ll9TZXNzaW9uVG9rZW47XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fU2Vzc2lvblRva2VuO1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9NYXN0ZXJLZXkpIHtcbiAgICAgICAgaW5mby5tYXN0ZXJLZXkgPSByZXEuYm9keS5fTWFzdGVyS2V5O1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX01hc3RlcktleTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXEuYm9keS5fQ29udGVudFR5cGUpIHtcbiAgICAgICAgcmVxLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddID0gcmVxLmJvZHkuX0NvbnRlbnRUeXBlO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0NvbnRlbnRUeXBlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpbmZvLmNsaWVudFZlcnNpb24pIHtcbiAgICBpbmZvLmNsaWVudFNESyA9IENsaWVudFNESy5mcm9tU3RyaW5nKGluZm8uY2xpZW50VmVyc2lvbik7XG4gIH1cblxuICBpZiAoZmlsZVZpYUpTT04pIHtcbiAgICAvLyBXZSBuZWVkIHRvIHJlcG9wdWxhdGUgcmVxLmJvZHkgd2l0aCBhIGJ1ZmZlclxuICAgIHZhciBiYXNlNjQgPSByZXEuYm9keS5iYXNlNjQ7XG4gICAgcmVxLmJvZHkgPSBuZXcgQnVmZmVyKGJhc2U2NCwgJ2Jhc2U2NCcpO1xuICB9XG5cbiAgY29uc3QgY2xpZW50SXAgPSBnZXRDbGllbnRJcChyZXEpO1xuXG4gIGluZm8uYXBwID0gQXBwQ2FjaGUuZ2V0KGluZm8uYXBwSWQpO1xuICByZXEuY29uZmlnID0gQ29uZmlnLmdldChpbmZvLmFwcElkLCBtb3VudCk7XG4gIHJlcS5jb25maWcuaGVhZGVycyA9IHJlcS5oZWFkZXJzIHx8IHt9O1xuICByZXEuY29uZmlnLmlwID0gY2xpZW50SXA7XG4gIHJlcS5pbmZvID0gaW5mbztcblxuICBpZiAoaW5mby5tYXN0ZXJLZXkgJiYgcmVxLmNvbmZpZy5tYXN0ZXJLZXlJcHMgJiYgcmVxLmNvbmZpZy5tYXN0ZXJLZXlJcHMubGVuZ3RoICE9PSAwICYmIHJlcS5jb25maWcubWFzdGVyS2V5SXBzLmluZGV4T2YoY2xpZW50SXApID09PSAtMSkge1xuICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gIH1cblxuICB2YXIgaXNNYXN0ZXIgPSAoaW5mby5tYXN0ZXJLZXkgPT09IHJlcS5jb25maWcubWFzdGVyS2V5KTtcblxuICBpZiAoaXNNYXN0ZXIpIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoeyBjb25maWc6IHJlcS5jb25maWcsIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLCBpc01hc3RlcjogdHJ1ZSB9KTtcbiAgICBuZXh0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGlzUmVhZE9ubHlNYXN0ZXIgPSAoaW5mby5tYXN0ZXJLZXkgPT09IHJlcS5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXkpO1xuICBpZiAodHlwZW9mIHJlcS5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXkgIT0gJ3VuZGVmaW5lZCcgJiYgcmVxLmNvbmZpZy5yZWFkT25seU1hc3RlcktleSAmJiBpc1JlYWRPbmx5TWFzdGVyKSB7XG4gICAgcmVxLmF1dGggPSBuZXcgYXV0aC5BdXRoKHsgY29uZmlnOiByZXEuY29uZmlnLCBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCwgaXNNYXN0ZXI6IHRydWUsIGlzUmVhZE9ubHk6IHRydWUgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIENsaWVudCBrZXlzIGFyZSBub3QgcmVxdWlyZWQgaW4gcGFyc2Utc2VydmVyLCBidXQgaWYgYW55IGhhdmUgYmVlbiBjb25maWd1cmVkIGluIHRoZSBzZXJ2ZXIsIHZhbGlkYXRlIHRoZW1cbiAgLy8gIHRvIHByZXNlcnZlIG9yaWdpbmFsIGJlaGF2aW9yLlxuICBjb25zdCBrZXlzID0gW1wiY2xpZW50S2V5XCIsIFwiamF2YXNjcmlwdEtleVwiLCBcImRvdE5ldEtleVwiLCBcInJlc3RBUElLZXlcIl07XG4gIGNvbnN0IG9uZUtleUNvbmZpZ3VyZWQgPSBrZXlzLnNvbWUoZnVuY3Rpb24oa2V5KSB7XG4gICAgcmV0dXJuIHJlcS5jb25maWdba2V5XSAhPT0gdW5kZWZpbmVkO1xuICB9KTtcbiAgY29uc3Qgb25lS2V5TWF0Y2hlcyA9IGtleXMuc29tZShmdW5jdGlvbihrZXkpe1xuICAgIHJldHVybiByZXEuY29uZmlnW2tleV0gIT09IHVuZGVmaW5lZCAmJiBpbmZvW2tleV0gPT09IHJlcS5jb25maWdba2V5XTtcbiAgfSk7XG5cbiAgaWYgKG9uZUtleUNvbmZpZ3VyZWQgJiYgIW9uZUtleU1hdGNoZXMpIHtcbiAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICB9XG5cbiAgaWYgKHJlcS51cmwgPT0gXCIvbG9naW5cIikge1xuICAgIGRlbGV0ZSBpbmZvLnNlc3Npb25Ub2tlbjtcbiAgfVxuXG4gIGlmICghaW5mby5zZXNzaW9uVG9rZW4pIHtcbiAgICByZXEuYXV0aCA9IG5ldyBhdXRoLkF1dGgoeyBjb25maWc6IHJlcS5jb25maWcsIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLCBpc01hc3RlcjogZmFsc2UgfSk7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcbiAgICAvLyBoYW5kbGUgdGhlIHVwZ3JhZGVUb1Jldm9jYWJsZVNlc3Npb24gcGF0aCBvbiBpdCdzIG93blxuICAgIGlmIChpbmZvLnNlc3Npb25Ub2tlbiAmJlxuICAgICAgICByZXEudXJsID09PSAnL3VwZ3JhZGVUb1Jldm9jYWJsZVNlc3Npb24nICYmXG4gICAgICAgIGluZm8uc2Vzc2lvblRva2VuLmluZGV4T2YoJ3I6JykgIT0gMCkge1xuICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvckxlZ2FjeVNlc3Npb25Ub2tlbih7IGNvbmZpZzogcmVxLmNvbmZpZywgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4gfSlcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGF1dGguZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih7IGNvbmZpZzogcmVxLmNvbmZpZywgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4gfSlcbiAgICB9XG4gIH0pLnRoZW4oKGF1dGgpID0+IHtcbiAgICBpZiAoYXV0aCkge1xuICAgICAgcmVxLmF1dGggPSBhdXRoO1xuICAgICAgbmV4dCgpO1xuICAgIH1cbiAgfSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIFBhcnNlLkVycm9yKSB7XG4gICAgICAgIG5leHQoZXJyb3IpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgLy8gVE9ETzogRGV0ZXJtaW5lIHRoZSBjb3JyZWN0IGVycm9yIHNjZW5hcmlvLlxuICAgICAgICBsb2cuZXJyb3IoJ2Vycm9yIGdldHRpbmcgYXV0aCBmb3Igc2Vzc2lvblRva2VuJywgZXJyb3IpO1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVU5LTk9XTl9FUlJPUiwgZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRDbGllbnRJcChyZXEpe1xuICBpZiAocmVxLmhlYWRlcnNbJ3gtZm9yd2FyZGVkLWZvciddKSB7XG4gICAgLy8gdHJ5IHRvIGdldCBmcm9tIHgtZm9yd2FyZWQtZm9yIGlmIGl0IHNldCAoYmVoaW5kIHJldmVyc2UgcHJveHkpXG4gICAgcmV0dXJuIHJlcS5oZWFkZXJzWyd4LWZvcndhcmRlZC1mb3InXS5zcGxpdCgnLCcpWzBdO1xuICB9IGVsc2UgaWYgKHJlcS5jb25uZWN0aW9uICYmIHJlcS5jb25uZWN0aW9uLnJlbW90ZUFkZHJlc3MpIHtcbiAgICAvLyBubyBwcm94eSwgdHJ5IGdldHRpbmcgZnJvbSBjb25uZWN0aW9uLnJlbW90ZUFkZHJlc3NcbiAgICByZXR1cm4gcmVxLmNvbm5lY3Rpb24ucmVtb3RlQWRkcmVzcztcbiAgfSBlbHNlIGlmIChyZXEuc29ja2V0KSB7XG4gICAgLy8gdHJ5IHRvIGdldCBpdCBmcm9tIHJlcS5zb2NrZXRcbiAgICByZXR1cm4gcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzO1xuICB9IGVsc2UgaWYgKHJlcS5jb25uZWN0aW9uICYmIHJlcS5jb25uZWN0aW9uLnNvY2tldCkge1xuICAgIC8vIHRyeSB0byBnZXQgaXQgZm9ybSB0aGUgY29ubmVjdGlvbi5zb2NrZXRcbiAgICByZXR1cm4gcmVxLmNvbm5lY3Rpb24uc29ja2V0LnJlbW90ZUFkZHJlc3M7XG4gIH0gZWxzZSB7XG4gICAgLy8gaWYgbm9uIGFib3ZlLCBmYWxsYmFjay5cbiAgICByZXR1cm4gcmVxLmlwO1xuICB9XG59XG5cbmZ1bmN0aW9uIGh0dHBBdXRoKHJlcSkge1xuICBpZiAoIShyZXEucmVxIHx8IHJlcSkuaGVhZGVycy5hdXRob3JpemF0aW9uKVxuICAgIHJldHVybiA7XG5cbiAgdmFyIGhlYWRlciA9IChyZXEucmVxIHx8IHJlcSkuaGVhZGVycy5hdXRob3JpemF0aW9uO1xuICB2YXIgYXBwSWQsIG1hc3RlcktleSwgamF2YXNjcmlwdEtleTtcblxuICAvLyBwYXJzZSBoZWFkZXJcbiAgdmFyIGF1dGhQcmVmaXggPSAnYmFzaWMgJztcblxuICB2YXIgbWF0Y2ggPSBoZWFkZXIudG9Mb3dlckNhc2UoKS5pbmRleE9mKGF1dGhQcmVmaXgpO1xuXG4gIGlmIChtYXRjaCA9PSAwKSB7XG4gICAgdmFyIGVuY29kZWRBdXRoID0gaGVhZGVyLnN1YnN0cmluZyhhdXRoUHJlZml4Lmxlbmd0aCwgaGVhZGVyLmxlbmd0aCk7XG4gICAgdmFyIGNyZWRlbnRpYWxzID0gZGVjb2RlQmFzZTY0KGVuY29kZWRBdXRoKS5zcGxpdCgnOicpO1xuXG4gICAgaWYgKGNyZWRlbnRpYWxzLmxlbmd0aCA9PSAyKSB7XG4gICAgICBhcHBJZCA9IGNyZWRlbnRpYWxzWzBdO1xuICAgICAgdmFyIGtleSA9IGNyZWRlbnRpYWxzWzFdO1xuXG4gICAgICB2YXIganNLZXlQcmVmaXggPSAnamF2YXNjcmlwdC1rZXk9JztcblxuICAgICAgdmFyIG1hdGNoS2V5ID0ga2V5LmluZGV4T2YoanNLZXlQcmVmaXgpXG4gICAgICBpZiAobWF0Y2hLZXkgPT0gMCkge1xuICAgICAgICBqYXZhc2NyaXB0S2V5ID0ga2V5LnN1YnN0cmluZyhqc0tleVByZWZpeC5sZW5ndGgsIGtleS5sZW5ndGgpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIG1hc3RlcktleSA9IGtleTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4ge2FwcElkOiBhcHBJZCwgbWFzdGVyS2V5OiBtYXN0ZXJLZXksIGphdmFzY3JpcHRLZXk6IGphdmFzY3JpcHRLZXl9O1xufVxuXG5mdW5jdGlvbiBkZWNvZGVCYXNlNjQoc3RyKSB7XG4gIHJldHVybiBuZXcgQnVmZmVyKHN0ciwgJ2Jhc2U2NCcpLnRvU3RyaW5nKClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFsbG93Q3Jvc3NEb21haW4ocmVxLCByZXMsIG5leHQpIHtcbiAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgJyonKTtcbiAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcycsICdHRVQsUFVULFBPU1QsREVMRVRFLE9QVElPTlMnKTtcbiAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctSGVhZGVycycsICdYLVBhcnNlLU1hc3Rlci1LZXksIFgtUGFyc2UtUkVTVC1BUEktS2V5LCBYLVBhcnNlLUphdmFzY3JpcHQtS2V5LCBYLVBhcnNlLUFwcGxpY2F0aW9uLUlkLCBYLVBhcnNlLUNsaWVudC1WZXJzaW9uLCBYLVBhcnNlLVNlc3Npb24tVG9rZW4sIFgtUmVxdWVzdGVkLVdpdGgsIFgtUGFyc2UtUmV2b2NhYmxlLVNlc3Npb24sIENvbnRlbnQtVHlwZScpO1xuICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1FeHBvc2UtSGVhZGVycycsICdYLVBhcnNlLUpvYi1TdGF0dXMtSWQsIFgtUGFyc2UtUHVzaC1TdGF0dXMtSWQnKTtcbiAgLy8gaW50ZXJjZXB0IE9QVElPTlMgbWV0aG9kXG4gIGlmICgnT1BUSU9OUycgPT0gcmVxLm1ldGhvZCkge1xuICAgIHJlcy5zZW5kU3RhdHVzKDIwMCk7XG4gIH1cbiAgZWxzZSB7XG4gICAgbmV4dCgpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhbGxvd01ldGhvZE92ZXJyaWRlKHJlcSwgcmVzLCBuZXh0KSB7XG4gIGlmIChyZXEubWV0aG9kID09PSAnUE9TVCcgJiYgcmVxLmJvZHkuX21ldGhvZCkge1xuICAgIHJlcS5vcmlnaW5hbE1ldGhvZCA9IHJlcS5tZXRob2Q7XG4gICAgcmVxLm1ldGhvZCA9IHJlcS5ib2R5Ll9tZXRob2Q7XG4gICAgZGVsZXRlIHJlcS5ib2R5Ll9tZXRob2Q7XG4gIH1cbiAgbmV4dCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlUGFyc2VFcnJvcnMoZXJyLCByZXEsIHJlcywgbmV4dCkge1xuICBpZiAoZXJyIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICBsZXQgaHR0cFN0YXR1cztcbiAgICAvLyBUT0RPOiBmaWxsIG91dCB0aGlzIG1hcHBpbmdcbiAgICBzd2l0Y2ggKGVyci5jb2RlKSB7XG4gICAgY2FzZSBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1I6XG4gICAgICBodHRwU3RhdHVzID0gNTAwO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EOlxuICAgICAgaHR0cFN0YXR1cyA9IDQwNDtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBodHRwU3RhdHVzID0gNDAwO1xuICAgIH1cblxuICAgIHJlcy5zdGF0dXMoaHR0cFN0YXR1cyk7XG4gICAgcmVzLmpzb24oeyBjb2RlOiBlcnIuY29kZSwgZXJyb3I6IGVyci5tZXNzYWdlIH0pO1xuICAgIGxvZy5lcnJvcihlcnIubWVzc2FnZSwgZXJyKTtcbiAgICBpZiAocmVxLmNvbmZpZyAmJiByZXEuY29uZmlnLmVuYWJsZUV4cHJlc3NFcnJvckhhbmRsZXIpIHtcbiAgICAgIG5leHQoZXJyKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoZXJyLnN0YXR1cyAmJiBlcnIubWVzc2FnZSkge1xuICAgIHJlcy5zdGF0dXMoZXJyLnN0YXR1cyk7XG4gICAgcmVzLmpzb24oeyBlcnJvcjogZXJyLm1lc3NhZ2UgfSk7XG4gICAgbmV4dChlcnIpO1xuICB9IGVsc2Uge1xuICAgIGxvZy5lcnJvcignVW5jYXVnaHQgaW50ZXJuYWwgc2VydmVyIGVycm9yLicsIGVyciwgZXJyLnN0YWNrKTtcbiAgICByZXMuc3RhdHVzKDUwMCk7XG4gICAgcmVzLmpzb24oe1xuICAgICAgY29kZTogUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLFxuICAgICAgbWVzc2FnZTogJ0ludGVybmFsIHNlcnZlciBlcnJvci4nXG4gICAgfSk7XG4gICAgbmV4dChlcnIpO1xuICB9XG5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MocmVxLCByZXMsIG5leHQpIHtcbiAgaWYgKCFyZXEuYXV0aC5pc01hc3Rlcikge1xuICAgIHJlcy5zdGF0dXMoNDAzKTtcbiAgICByZXMuZW5kKCd7XCJlcnJvclwiOlwidW5hdXRob3JpemVkOiBtYXN0ZXIga2V5IGlzIHJlcXVpcmVkXCJ9Jyk7XG4gICAgcmV0dXJuO1xuICB9XG4gIG5leHQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByb21pc2VFbmZvcmNlTWFzdGVyS2V5QWNjZXNzKHJlcXVlc3QpIHtcbiAgaWYgKCFyZXF1ZXN0LmF1dGguaXNNYXN0ZXIpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIGVycm9yLnN0YXR1cyA9IDQwMztcbiAgICBlcnJvci5tZXNzYWdlID0gXCJ1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWRcIjtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbmZ1bmN0aW9uIGludmFsaWRSZXF1ZXN0KHJlcSwgcmVzKSB7XG4gIHJlcy5zdGF0dXMoNDAzKTtcbiAgcmVzLmVuZCgne1wiZXJyb3JcIjpcInVuYXV0aG9yaXplZFwifScpO1xufVxuIl19
|
|
652
|
+
function malformedContext(req, res) {
|
|
653
|
+
res.status(400);
|
|
654
|
+
res.json({
|
|
655
|
+
code: _node.default.Error.INVALID_JSON,
|
|
656
|
+
error: 'Invalid object for context.'
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Express 4 allowed a double forward slash between a route and router. Although
|
|
662
|
+
* this should be considered an anti-pattern, we need to support it for backwards
|
|
663
|
+
* compatibility.
|
|
664
|
+
*
|
|
665
|
+
* Technically valid URL with double foroward slash:
|
|
666
|
+
* http://localhost:1337/parse//functions/testFunction
|
|
667
|
+
*/
|
|
668
|
+
function allowDoubleForwardSlash(req, res, next) {
|
|
669
|
+
req.url = req.url.startsWith('//') ? req.url.substring(1) : req.url;
|
|
670
|
+
next();
|
|
671
|
+
}
|
|
672
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY2FjaGUiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9ub2RlIiwiX0F1dGgiLCJfQ29uZmlnIiwiX0NsaWVudFNESyIsIl9sb2dnZXIiLCJfcmVzdCIsIl9Nb25nb1N0b3JhZ2VBZGFwdGVyIiwiX1Bvc3RncmVzU3RvcmFnZUFkYXB0ZXIiLCJfZXhwcmVzc1JhdGVMaW1pdCIsIl9EZWZpbml0aW9ucyIsIl9wYXRoVG9SZWdleHAiLCJfcmF0ZUxpbWl0UmVkaXMiLCJfcmVkaXMiLCJfbmV0IiwiX0Vycm9yIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiREVGQVVMVF9BTExPV0VEX0hFQURFUlMiLCJleHBvcnRzIiwiZ2V0TW91bnRGb3JSZXF1ZXN0IiwicmVxIiwibW91bnRQYXRoTGVuZ3RoIiwib3JpZ2luYWxVcmwiLCJsZW5ndGgiLCJ1cmwiLCJtb3VudFBhdGgiLCJzbGljZSIsInByb3RvY29sIiwiZ2V0IiwiZ2V0QmxvY2tMaXN0IiwiaXBSYW5nZUxpc3QiLCJzdG9yZSIsImJsb2NrTGlzdCIsIkJsb2NrTGlzdCIsImZvckVhY2giLCJmdWxsSXAiLCJzZXQiLCJpcCIsIm1hc2siLCJzcGxpdCIsImFkZEFkZHJlc3MiLCJpc0lQdjQiLCJhZGRTdWJuZXQiLCJOdW1iZXIiLCJjaGVja0lwIiwiaW5jb21pbmdJcElzVjQiLCJyZXN1bHQiLCJjaGVjayIsImluY2x1ZGVzIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwicmVzIiwibmV4dCIsIm1vdW50IiwiY29udGV4dCIsIkpTT04iLCJwYXJzZSIsIk9iamVjdCIsInByb3RvdHlwZSIsInRvU3RyaW5nIiwiY2FsbCIsIm1hbGZvcm1lZENvbnRleHQiLCJpbmZvIiwiYXBwSWQiLCJzZXNzaW9uVG9rZW4iLCJtYXN0ZXJLZXkiLCJtYWludGVuYW5jZUtleSIsImluc3RhbGxhdGlvbklkIiwiY2xpZW50S2V5IiwiamF2YXNjcmlwdEtleSIsImRvdE5ldEtleSIsInJlc3RBUElLZXkiLCJjbGllbnRWZXJzaW9uIiwiYmFzaWNBdXRoIiwiaHR0cEF1dGgiLCJiYXNpY0F1dGhBcHBJZCIsIkFwcENhY2hlIiwiYm9keSIsIl9ub0JvZHkiLCJmaWxlVmlhSlNPTiIsIkJ1ZmZlciIsImludmFsaWRSZXF1ZXN0IiwiX1Jldm9jYWJsZVNlc3Npb24iLCJfQXBwbGljYXRpb25JZCIsIl9KYXZhU2NyaXB0S2V5IiwiX0NsaWVudFZlcnNpb24iLCJfSW5zdGFsbGF0aW9uSWQiLCJfU2Vzc2lvblRva2VuIiwiX01hc3RlcktleSIsIl9jb250ZXh0IiwiX0NvbnRlbnRUeXBlIiwiaGVhZGVycyIsImNsaWVudFNESyIsIkNsaWVudFNESyIsImZyb21TdHJpbmciLCJmaWxlRGF0YSIsImJhc2U2NCIsImZyb20iLCJjbGllbnRJcCIsImdldENsaWVudElwIiwiY29uZmlnIiwiQ29uZmlnIiwic3RhdGUiLCJzdGF0dXMiLCJqc29uIiwiY29kZSIsIlBhcnNlIiwiRXJyb3IiLCJJTlRFUk5BTF9TRVJWRVJfRVJST1IiLCJlcnJvciIsImxvYWRLZXlzIiwiYXBwIiwiaXNNYWludGVuYW5jZSIsIm1haW50ZW5hbmNlS2V5SXBzIiwibWFpbnRlbmFuY2VLZXlJcHNTdG9yZSIsImF1dGgiLCJBdXRoIiwibG9nIiwibG9nZ2VyQ29udHJvbGxlciIsImRlZmF1bHRMb2dnZXIiLCJsb2FkTWFzdGVyS2V5IiwiaXNNYXN0ZXIiLCJtYXN0ZXJLZXlJcHMiLCJtYXN0ZXJLZXlJcHNTdG9yZSIsIm1lc3NhZ2UiLCJoYW5kbGVSYXRlTGltaXQiLCJpc1JlYWRPbmx5TWFzdGVyIiwicmVhZE9ubHlNYXN0ZXJLZXkiLCJpc1JlYWRPbmx5Iiwia2V5cyIsIm9uZUtleUNvbmZpZ3VyZWQiLCJzb21lIiwia2V5IiwidW5kZWZpbmVkIiwib25lS2V5TWF0Y2hlcyIsInVzZXJGcm9tSldUIiwidXNlciIsInJhdGVMaW1pdHMiLCJQcm9taXNlIiwiYWxsIiwibWFwIiwibGltaXQiLCJwYXRoRXhwIiwiUmVnRXhwIiwicGF0aCIsInRlc3QiLCJoYW5kbGVyIiwiZXJyIiwiQ09OTkVDVElPTl9GQUlMRUQiLCJoYW5kbGVQYXJzZVNlc3Npb24iLCJyZXF1ZXN0QXV0aCIsImluZGV4T2YiLCJnZXRBdXRoRm9yTGVnYWN5U2Vzc2lvblRva2VuIiwiZ2V0QXV0aEZvclNlc3Npb25Ub2tlbiIsIlVOS05PV05fRVJST1IiLCJhdXRob3JpemF0aW9uIiwiaGVhZGVyIiwiYXV0aFByZWZpeCIsIm1hdGNoIiwidG9Mb3dlckNhc2UiLCJlbmNvZGVkQXV0aCIsInN1YnN0cmluZyIsImNyZWRlbnRpYWxzIiwiZGVjb2RlQmFzZTY0IiwianNLZXlQcmVmaXgiLCJtYXRjaEtleSIsInN0ciIsImFsbG93Q3Jvc3NEb21haW4iLCJhbGxvd0hlYWRlcnMiLCJqb2luIiwiYmFzZU9yaWdpbnMiLCJhbGxvd09yaWdpbiIsInJlcXVlc3RPcmlnaW4iLCJvcmlnaW4iLCJhbGxvd09yaWdpbnMiLCJtZXRob2QiLCJzZW5kU3RhdHVzIiwiYWxsb3dNZXRob2RPdmVycmlkZSIsIl9tZXRob2QiLCJvcmlnaW5hbE1ldGhvZCIsImhhbmRsZVBhcnNlRXJyb3JzIiwiZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlciIsImh0dHBTdGF0dXMiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwicHJvY2VzcyIsImVudiIsIlRFU1RJTkciLCJzdGFjayIsImVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJjcmVhdGVTYW5pdGl6ZWRIdHRwRXJyb3IiLCJlbmQiLCJwcm9taXNlRW5mb3JjZU1hc3RlcktleUFjY2VzcyIsInJlcXVlc3QiLCJyZXNvbHZlIiwiYWRkUmF0ZUxpbWl0Iiwicm91dGUiLCJjbG91ZCIsIlJhdGVMaW1pdE9wdGlvbnMiLCJyZWRpc1N0b3JlIiwiY29ubmVjdGlvblByb21pc2UiLCJyZWRpc1VybCIsImNsaWVudCIsImNyZWF0ZUNsaWVudCIsIm9uIiwiaXNPcGVuIiwiY29ubmVjdCIsIlJlZGlzU3RvcmUiLCJzZW5kQ29tbWFuZCIsImFyZ3MiLCJ0cmFuc2Zvcm1QYXRoIiwicmVxdWVzdFBhdGgiLCJwdXNoIiwicGF0aFRvUmVnZXhwIiwicmF0ZUxpbWl0Iiwid2luZG93TXMiLCJyZXF1ZXN0VGltZVdpbmRvdyIsIm1heCIsInJlcXVlc3RDb3VudCIsImVycm9yUmVzcG9uc2VNZXNzYWdlIiwicmVzcG9uc2UiLCJvcHRpb25zIiwic2tpcCIsImluY2x1ZGVJbnRlcm5hbFJlcXVlc3RzIiwiaW5jbHVkZU1hc3RlcktleSIsInJlcXVlc3RNZXRob2RzIiwiQXJyYXkiLCJpc0FycmF5IiwicmVnRXhwIiwia2V5R2VuZXJhdG9yIiwiem9uZSIsIlNlcnZlciIsIlJhdGVMaW1pdFpvbmUiLCJnbG9iYWwiLCJ0b2tlbiIsInNlc3Npb24iLCJpZCIsInB1dCIsInByb21pc2VFbnN1cmVJZGVtcG90ZW5jeSIsImRhdGFiYXNlIiwiYWRhcHRlciIsIk1vbmdvU3RvcmFnZUFkYXB0ZXIiLCJQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyIiwicmVxdWVzdElkIiwicGF0aHMiLCJ0dGwiLCJpZGVtcG90ZW5jeU9wdGlvbnMiLCJyZXFQYXRoIiwicmVwbGFjZSIsInJlZ2V4IiwiY2hhckF0IiwiZXhwaXJ5RGF0ZSIsIkRhdGUiLCJzZXRTZWNvbmRzIiwiZ2V0U2Vjb25kcyIsInJlc3QiLCJjcmVhdGUiLCJtYXN0ZXIiLCJyZXFJZCIsImV4cGlyZSIsIl9lbmNvZGUiLCJjYXRjaCIsIkRVUExJQ0FURV9WQUxVRSIsIkRVUExJQ0FURV9SRVFVRVNUIiwiSU5WQUxJRF9KU09OIiwiYWxsb3dEb3VibGVGb3J3YXJkU2xhc2giLCJzdGFydHNXaXRoIl0sInNvdXJjZXMiOlsiLi4vc3JjL21pZGRsZXdhcmVzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBBcHBDYWNoZSBmcm9tICcuL2NhY2hlJztcbmltcG9ydCBQYXJzZSBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBhdXRoIGZyb20gJy4vQXV0aCc7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4vQ29uZmlnJztcbmltcG9ydCBDbGllbnRTREsgZnJvbSAnLi9DbGllbnRTREsnO1xuaW1wb3J0IGRlZmF1bHRMb2dnZXIgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi9yZXN0JztcbmltcG9ydCBNb25nb1N0b3JhZ2VBZGFwdGVyIGZyb20gJy4vQWRhcHRlcnMvU3RvcmFnZS9Nb25nby9Nb25nb1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCBQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyIGZyb20gJy4vQWRhcHRlcnMvU3RvcmFnZS9Qb3N0Z3Jlcy9Qb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyJztcbmltcG9ydCByYXRlTGltaXQgZnJvbSAnZXhwcmVzcy1yYXRlLWxpbWl0JztcbmltcG9ydCB7IFJhdGVMaW1pdE9wdGlvbnMgfSBmcm9tICcuL09wdGlvbnMvRGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgcGF0aFRvUmVnZXhwIH0gZnJvbSAncGF0aC10by1yZWdleHAnO1xuaW1wb3J0IFJlZGlzU3RvcmUgZnJvbSAncmF0ZS1saW1pdC1yZWRpcyc7XG5pbXBvcnQgeyBjcmVhdGVDbGllbnQgfSBmcm9tICdyZWRpcyc7XG5pbXBvcnQgeyBCbG9ja0xpc3QsIGlzSVB2NCB9IGZyb20gJ25ldCc7XG5pbXBvcnQgeyBjcmVhdGVTYW5pdGl6ZWRIdHRwRXJyb3IgfSBmcm9tICcuL0Vycm9yJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfQUxMT1dFRF9IRUFERVJTID1cbiAgJ1gtUGFyc2UtTWFzdGVyLUtleSwgWC1QYXJzZS1SRVNULUFQSS1LZXksIFgtUGFyc2UtSmF2YXNjcmlwdC1LZXksIFgtUGFyc2UtQXBwbGljYXRpb24tSWQsIFgtUGFyc2UtQ2xpZW50LVZlcnNpb24sIFgtUGFyc2UtU2Vzc2lvbi1Ub2tlbiwgWC1SZXF1ZXN0ZWQtV2l0aCwgWC1QYXJzZS1SZXZvY2FibGUtU2Vzc2lvbiwgWC1QYXJzZS1SZXF1ZXN0LUlkLCBDb250ZW50LVR5cGUsIFByYWdtYSwgQ2FjaGUtQ29udHJvbCc7XG5cbmNvbnN0IGdldE1vdW50Rm9yUmVxdWVzdCA9IGZ1bmN0aW9uIChyZXEpIHtcbiAgY29uc3QgbW91bnRQYXRoTGVuZ3RoID0gcmVxLm9yaWdpbmFsVXJsLmxlbmd0aCAtIHJlcS51cmwubGVuZ3RoO1xuICBjb25zdCBtb3VudFBhdGggPSByZXEub3JpZ2luYWxVcmwuc2xpY2UoMCwgbW91bnRQYXRoTGVuZ3RoKTtcbiAgcmV0dXJuIHJlcS5wcm90b2NvbCArICc6Ly8nICsgcmVxLmdldCgnaG9zdCcpICsgbW91bnRQYXRoO1xufTtcblxuY29uc3QgZ2V0QmxvY2tMaXN0ID0gKGlwUmFuZ2VMaXN0LCBzdG9yZSkgPT4ge1xuICBpZiAoc3RvcmUuZ2V0KCdibG9ja0xpc3QnKSkgeyByZXR1cm4gc3RvcmUuZ2V0KCdibG9ja0xpc3QnKTsgfVxuICBjb25zdCBibG9ja0xpc3QgPSBuZXcgQmxvY2tMaXN0KCk7XG4gIGlwUmFuZ2VMaXN0LmZvckVhY2goZnVsbElwID0+IHtcbiAgICBpZiAoZnVsbElwID09PSAnOjovMCcgfHwgZnVsbElwID09PSAnOjonKSB7XG4gICAgICBzdG9yZS5zZXQoJ2FsbG93QWxsSXB2NicsIHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZnVsbElwID09PSAnMC4wLjAuMC8wJyB8fCBmdWxsSXAgPT09ICcwLjAuMC4wJykge1xuICAgICAgc3RvcmUuc2V0KCdhbGxvd0FsbElwdjQnLCB0cnVlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgW2lwLCBtYXNrXSA9IGZ1bGxJcC5zcGxpdCgnLycpO1xuICAgIGlmICghbWFzaykge1xuICAgICAgYmxvY2tMaXN0LmFkZEFkZHJlc3MoaXAsIGlzSVB2NChpcCkgPyAnaXB2NCcgOiAnaXB2NicpO1xuICAgIH0gZWxzZSB7XG4gICAgICBibG9ja0xpc3QuYWRkU3VibmV0KGlwLCBOdW1iZXIobWFzayksIGlzSVB2NChpcCkgPyAnaXB2NCcgOiAnaXB2NicpO1xuICAgIH1cbiAgfSk7XG4gIHN0b3JlLnNldCgnYmxvY2tMaXN0JywgYmxvY2tMaXN0KTtcbiAgcmV0dXJuIGJsb2NrTGlzdDtcbn07XG5cbmV4cG9ydCBjb25zdCBjaGVja0lwID0gKGlwLCBpcFJhbmdlTGlzdCwgc3RvcmUpID0+IHtcbiAgY29uc3QgaW5jb21pbmdJcElzVjQgPSBpc0lQdjQoaXApO1xuICBjb25zdCBibG9ja0xpc3QgPSBnZXRCbG9ja0xpc3QoaXBSYW5nZUxpc3QsIHN0b3JlKTtcblxuICBpZiAoc3RvcmUuZ2V0KGlwKSkgeyByZXR1cm4gdHJ1ZTsgfVxuICBpZiAoc3RvcmUuZ2V0KCdhbGxvd0FsbElwdjQnKSAmJiBpbmNvbWluZ0lwSXNWNCkgeyByZXR1cm4gdHJ1ZTsgfVxuICBpZiAoc3RvcmUuZ2V0KCdhbGxvd0FsbElwdjYnKSAmJiAhaW5jb21pbmdJcElzVjQpIHsgcmV0dXJuIHRydWU7IH1cbiAgY29uc3QgcmVzdWx0ID0gYmxvY2tMaXN0LmNoZWNrKGlwLCBpbmNvbWluZ0lwSXNWNCA/ICdpcHY0JyA6ICdpcHY2Jyk7XG5cbiAgLy8gSWYgdGhlIGlwIGlzIGluIHRoZSBsaXN0LCB3ZSBzdG9yZSB0aGUgcmVzdWx0IGluIHRoZSBzdG9yZVxuICAvLyBzbyB3ZSBoYXZlIGEgb3B0aW1pemVkIHBhdGggZm9yIHRoZSBuZXh0IHJlcXVlc3RcbiAgaWYgKGlwUmFuZ2VMaXN0LmluY2x1ZGVzKGlwKSAmJiByZXN1bHQpIHtcbiAgICBzdG9yZS5zZXQoaXAsIHJlc3VsdCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbi8vIENoZWNrcyB0aGF0IHRoZSByZXF1ZXN0IGlzIGF1dGhvcml6ZWQgZm9yIHRoaXMgYXBwIGFuZCBjaGVja3MgdXNlclxuLy8gYXV0aCB0b28uXG4vLyBUaGUgYm9keXBhcnNlciBzaG91bGQgcnVuIGJlZm9yZSB0aGlzIG1pZGRsZXdhcmUuXG4vLyBBZGRzIGluZm8gdG8gdGhlIHJlcXVlc3Q6XG4vLyByZXEuY29uZmlnIC0gdGhlIENvbmZpZyBmb3IgdGhpcyBhcHBcbi8vIHJlcS5hdXRoIC0gdGhlIEF1dGggZm9yIHRoaXMgcmVxdWVzdFxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVBhcnNlSGVhZGVycyhyZXEsIHJlcywgbmV4dCkge1xuICB2YXIgbW91bnQgPSBnZXRNb3VudEZvclJlcXVlc3QocmVxKTtcblxuICBsZXQgY29udGV4dCA9IHt9O1xuICBpZiAocmVxLmdldCgnWC1QYXJzZS1DbG91ZC1Db250ZXh0JykgIT0gbnVsbCkge1xuICAgIHRyeSB7XG4gICAgICBjb250ZXh0ID0gSlNPTi5wYXJzZShyZXEuZ2V0KCdYLVBhcnNlLUNsb3VkLUNvbnRleHQnKSk7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGNvbnRleHQpICE9PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgICB0aHJvdyAnQ29udGV4dCBpcyBub3QgYW4gb2JqZWN0JztcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBtYWxmb3JtZWRDb250ZXh0KHJlcSwgcmVzKTtcbiAgICB9XG4gIH1cbiAgdmFyIGluZm8gPSB7XG4gICAgYXBwSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtQXBwbGljYXRpb24tSWQnKSxcbiAgICBzZXNzaW9uVG9rZW46IHJlcS5nZXQoJ1gtUGFyc2UtU2Vzc2lvbi1Ub2tlbicpLFxuICAgIG1hc3RlcktleTogcmVxLmdldCgnWC1QYXJzZS1NYXN0ZXItS2V5JyksXG4gICAgbWFpbnRlbmFuY2VLZXk6IHJlcS5nZXQoJ1gtUGFyc2UtTWFpbnRlbmFuY2UtS2V5JyksXG4gICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtSW5zdGFsbGF0aW9uLUlkJyksXG4gICAgY2xpZW50S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1LZXknKSxcbiAgICBqYXZhc2NyaXB0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLUphdmFzY3JpcHQtS2V5JyksXG4gICAgZG90TmV0S2V5OiByZXEuZ2V0KCdYLVBhcnNlLVdpbmRvd3MtS2V5JyksXG4gICAgcmVzdEFQSUtleTogcmVxLmdldCgnWC1QYXJzZS1SRVNULUFQSS1LZXknKSxcbiAgICBjbGllbnRWZXJzaW9uOiByZXEuZ2V0KCdYLVBhcnNlLUNsaWVudC1WZXJzaW9uJyksXG4gICAgY29udGV4dDogY29udGV4dCxcbiAgfTtcblxuICB2YXIgYmFzaWNBdXRoID0gaHR0cEF1dGgocmVxKTtcblxuICBpZiAoYmFzaWNBdXRoKSB7XG4gICAgdmFyIGJhc2ljQXV0aEFwcElkID0gYmFzaWNBdXRoLmFwcElkO1xuICAgIGlmIChBcHBDYWNoZS5nZXQoYmFzaWNBdXRoQXBwSWQpKSB7XG4gICAgICBpbmZvLmFwcElkID0gYmFzaWNBdXRoQXBwSWQ7XG4gICAgICBpbmZvLm1hc3RlcktleSA9IGJhc2ljQXV0aC5tYXN0ZXJLZXkgfHwgaW5mby5tYXN0ZXJLZXk7XG4gICAgICBpbmZvLmphdmFzY3JpcHRLZXkgPSBiYXNpY0F1dGguamF2YXNjcmlwdEtleSB8fCBpbmZvLmphdmFzY3JpcHRLZXk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlcS5ib2R5KSB7XG4gICAgLy8gVW5pdHkgU0RLIHNlbmRzIGEgX25vQm9keSBrZXkgd2hpY2ggbmVlZHMgdG8gYmUgcmVtb3ZlZC5cbiAgICAvLyBVbmNsZWFyIGF0IHRoaXMgcG9pbnQgaWYgYWN0aW9uIG5lZWRzIHRvIGJlIHRha2VuLlxuICAgIGRlbGV0ZSByZXEuYm9keS5fbm9Cb2R5O1xuICB9XG5cbiAgdmFyIGZpbGVWaWFKU09OID0gZmFsc2U7XG5cbiAgaWYgKCFpbmZvLmFwcElkIHx8ICFBcHBDYWNoZS5nZXQoaW5mby5hcHBJZCkpIHtcbiAgICAvLyBTZWUgaWYgd2UgY2FuIGZpbmQgdGhlIGFwcCBpZCBvbiB0aGUgYm9keS5cbiAgICBpZiAocmVxLmJvZHkgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgIC8vIFRoZSBvbmx5IGNoYW5jZSB0byBmaW5kIHRoZSBhcHAgaWQgaXMgaWYgdGhpcyBpcyBhIGZpbGVcbiAgICAgIC8vIHVwbG9hZCB0aGF0IGFjdHVhbGx5IGlzIGEgSlNPTiBib2R5LiBTbyB0cnkgdG8gcGFyc2UgaXQuXG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vcGFyc2UtY29tbXVuaXR5L3BhcnNlLXNlcnZlci9pc3N1ZXMvNjU4OVxuICAgICAgLy8gSXQgaXMgYWxzbyBwb3NzaWJsZSB0aGF0IHRoZSBjbGllbnQgaXMgdHJ5aW5nIHRvIHVwbG9hZCBhIGZpbGUgYnV0IGZvcmdvdFxuICAgICAgLy8gdG8gcHJvdmlkZSB4LXBhcnNlLWFwcC1pZCBpbiBoZWFkZXIgYW5kIHBhcnNlIGEgYmluYXJ5IGZpbGUgd2lsbCBmYWlsXG4gICAgICB0cnkge1xuICAgICAgICByZXEuYm9keSA9IEpTT04ucGFyc2UocmVxLmJvZHkpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gICAgICB9XG4gICAgICBmaWxlVmlhSlNPTiA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHJlcS5ib2R5KSB7XG4gICAgICBkZWxldGUgcmVxLmJvZHkuX1Jldm9jYWJsZVNlc3Npb247XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgcmVxLmJvZHkgJiZcbiAgICAgIHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkICYmXG4gICAgICBBcHBDYWNoZS5nZXQocmVxLmJvZHkuX0FwcGxpY2F0aW9uSWQpICYmXG4gICAgICAoIWluZm8ubWFzdGVyS2V5IHx8IEFwcENhY2hlLmdldChyZXEuYm9keS5fQXBwbGljYXRpb25JZCkubWFzdGVyS2V5ID09PSBpbmZvLm1hc3RlcktleSlcbiAgICApIHtcbiAgICAgIGluZm8uYXBwSWQgPSByZXEuYm9keS5fQXBwbGljYXRpb25JZDtcbiAgICAgIGluZm8uamF2YXNjcmlwdEtleSA9IHJlcS5ib2R5Ll9KYXZhU2NyaXB0S2V5IHx8ICcnO1xuICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9BcHBsaWNhdGlvbklkO1xuICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9KYXZhU2NyaXB0S2V5O1xuICAgICAgLy8gVE9ETzogdGVzdCB0aGF0IHRoZSBSRVNUIEFQSSBmb3JtYXRzIGdlbmVyYXRlZCBieSB0aGUgb3RoZXJcbiAgICAgIC8vIFNES3MgYXJlIGhhbmRsZWQgb2tcbiAgICAgIGlmIChyZXEuYm9keS5fQ2xpZW50VmVyc2lvbikge1xuICAgICAgICBpbmZvLmNsaWVudFZlcnNpb24gPSByZXEuYm9keS5fQ2xpZW50VmVyc2lvbjtcbiAgICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9DbGllbnRWZXJzaW9uO1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9JbnN0YWxsYXRpb25JZCkge1xuICAgICAgICBpbmZvLmluc3RhbGxhdGlvbklkID0gcmVxLmJvZHkuX0luc3RhbGxhdGlvbklkO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX0luc3RhbGxhdGlvbklkO1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9TZXNzaW9uVG9rZW4pIHtcbiAgICAgICAgaW5mby5zZXNzaW9uVG9rZW4gPSByZXEuYm9keS5fU2Vzc2lvblRva2VuO1xuICAgICAgICBkZWxldGUgcmVxLmJvZHkuX1Nlc3Npb25Ub2tlbjtcbiAgICAgIH1cbiAgICAgIGlmIChyZXEuYm9keS5fTWFzdGVyS2V5KSB7XG4gICAgICAgIGluZm8ubWFzdGVyS2V5ID0gcmVxLmJvZHkuX01hc3RlcktleTtcbiAgICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9NYXN0ZXJLZXk7XG4gICAgICB9XG4gICAgICBpZiAocmVxLmJvZHkuX2NvbnRleHQpIHtcbiAgICAgICAgaWYgKHJlcS5ib2R5Ll9jb250ZXh0IGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgaW5mby5jb250ZXh0ID0gcmVxLmJvZHkuX2NvbnRleHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGluZm8uY29udGV4dCA9IEpTT04ucGFyc2UocmVxLmJvZHkuX2NvbnRleHQpO1xuICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbmZvLmNvbnRleHQpICE9PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgICAgICAgICB0aHJvdyAnQ29udGV4dCBpcyBub3QgYW4gb2JqZWN0JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBtYWxmb3JtZWRDb250ZXh0KHJlcSwgcmVzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIHJlcS5ib2R5Ll9jb250ZXh0O1xuICAgICAgfVxuICAgICAgaWYgKHJlcS5ib2R5Ll9Db250ZW50VHlwZSkge1xuICAgICAgICByZXEuaGVhZGVyc1snY29udGVudC10eXBlJ10gPSByZXEuYm9keS5fQ29udGVudFR5cGU7XG4gICAgICAgIGRlbGV0ZSByZXEuYm9keS5fQ29udGVudFR5cGU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpbnZhbGlkUmVxdWVzdChyZXEsIHJlcyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGluZm8uc2Vzc2lvblRva2VuICYmIHR5cGVvZiBpbmZvLnNlc3Npb25Ub2tlbiAhPT0gJ3N0cmluZycpIHtcbiAgICBpbmZvLnNlc3Npb25Ub2tlbiA9IGluZm8uc2Vzc2lvblRva2VuLnRvU3RyaW5nKCk7XG4gIH1cblxuICBpZiAoaW5mby5jbGllbnRWZXJzaW9uKSB7XG4gICAgaW5mby5jbGllbnRTREsgPSBDbGllbnRTREsuZnJvbVN0cmluZyhpbmZvLmNsaWVudFZlcnNpb24pO1xuICB9XG5cbiAgaWYgKGZpbGVWaWFKU09OICYmIHJlcS5ib2R5KSB7XG4gICAgcmVxLmZpbGVEYXRhID0gcmVxLmJvZHkuZmlsZURhdGE7XG4gICAgLy8gV2UgbmVlZCB0byByZXBvcHVsYXRlIHJlcS5ib2R5IHdpdGggYSBidWZmZXJcbiAgICB2YXIgYmFzZTY0ID0gcmVxLmJvZHkuYmFzZTY0O1xuICAgIHJlcS5ib2R5ID0gQnVmZmVyLmZyb20oYmFzZTY0LCAnYmFzZTY0Jyk7XG4gIH1cblxuICBjb25zdCBjbGllbnRJcCA9IGdldENsaWVudElwKHJlcSk7XG4gIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoaW5mby5hcHBJZCwgbW91bnQpO1xuICBpZiAoY29uZmlnLnN0YXRlICYmIGNvbmZpZy5zdGF0ZSAhPT0gJ29rJykge1xuICAgIHJlcy5zdGF0dXMoNTAwKTtcbiAgICByZXMuanNvbih7XG4gICAgICBjb2RlOiBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICBlcnJvcjogYEludmFsaWQgc2VydmVyIHN0YXRlOiAke2NvbmZpZy5zdGF0ZX1gLFxuICAgIH0pO1xuICAgIHJldHVybjtcbiAgfVxuICBhd2FpdCBjb25maWcubG9hZEtleXMoKTtcblxuICBpbmZvLmFwcCA9IEFwcENhY2hlLmdldChpbmZvLmFwcElkKTtcbiAgcmVxLmNvbmZpZyA9IGNvbmZpZztcbiAgcmVxLmNvbmZpZy5oZWFkZXJzID0gcmVxLmhlYWRlcnMgfHwge307XG4gIHJlcS5jb25maWcuaXAgPSBjbGllbnRJcDtcbiAgcmVxLmluZm8gPSBpbmZvO1xuXG4gIGNvbnN0IGlzTWFpbnRlbmFuY2UgPVxuICAgIHJlcS5jb25maWcubWFpbnRlbmFuY2VLZXkgJiYgaW5mby5tYWludGVuYW5jZUtleSA9PT0gcmVxLmNvbmZpZy5tYWludGVuYW5jZUtleTtcbiAgaWYgKGlzTWFpbnRlbmFuY2UpIHtcbiAgICBpZiAoY2hlY2tJcChjbGllbnRJcCwgcmVxLmNvbmZpZy5tYWludGVuYW5jZUtleUlwcyB8fCBbXSwgcmVxLmNvbmZpZy5tYWludGVuYW5jZUtleUlwc1N0b3JlKSkge1xuICAgICAgcmVxLmF1dGggPSBuZXcgYXV0aC5BdXRoKHtcbiAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCxcbiAgICAgICAgaXNNYWludGVuYW5jZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgbmV4dCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBsb2cgPSByZXEuY29uZmlnPy5sb2dnZXJDb250cm9sbGVyIHx8IGRlZmF1bHRMb2dnZXI7XG4gICAgbG9nLmVycm9yKFxuICAgICAgYFJlcXVlc3QgdXNpbmcgbWFpbnRlbmFuY2Uga2V5IHJlamVjdGVkIGFzIHRoZSByZXF1ZXN0IElQIGFkZHJlc3MgJyR7Y2xpZW50SXB9JyBpcyBub3Qgc2V0IGluIFBhcnNlIFNlcnZlciBvcHRpb24gJ21haW50ZW5hbmNlS2V5SXBzJy5gXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IG1hc3RlcktleSA9IGF3YWl0IHJlcS5jb25maWcubG9hZE1hc3RlcktleSgpO1xuICBsZXQgaXNNYXN0ZXIgPSBpbmZvLm1hc3RlcktleSA9PT0gbWFzdGVyS2V5O1xuXG4gIGlmIChpc01hc3RlciAmJiAhY2hlY2tJcChjbGllbnRJcCwgcmVxLmNvbmZpZy5tYXN0ZXJLZXlJcHMgfHwgW10sIHJlcS5jb25maWcubWFzdGVyS2V5SXBzU3RvcmUpKSB7XG4gICAgY29uc3QgbG9nID0gcmVxLmNvbmZpZz8ubG9nZ2VyQ29udHJvbGxlciB8fCBkZWZhdWx0TG9nZ2VyO1xuICAgIGxvZy5lcnJvcihcbiAgICAgIGBSZXF1ZXN0IHVzaW5nIG1hc3RlciBrZXkgcmVqZWN0ZWQgYXMgdGhlIHJlcXVlc3QgSVAgYWRkcmVzcyAnJHtjbGllbnRJcH0nIGlzIG5vdCBzZXQgaW4gUGFyc2UgU2VydmVyIG9wdGlvbiAnbWFzdGVyS2V5SXBzJy5gXG4gICAgKTtcbiAgICBpc01hc3RlciA9IGZhbHNlO1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKCk7XG4gICAgZXJyb3Iuc3RhdHVzID0gNDAzO1xuICAgIGVycm9yLm1lc3NhZ2UgPSBgdW5hdXRob3JpemVkYDtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuXG4gIGlmIChpc01hc3Rlcikge1xuICAgIHJlcS5hdXRoID0gbmV3IGF1dGguQXV0aCh7XG4gICAgICBjb25maWc6IHJlcS5jb25maWcsXG4gICAgICBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCxcbiAgICAgIGlzTWFzdGVyOiB0cnVlLFxuICAgIH0pO1xuICAgIHJldHVybiBoYW5kbGVSYXRlTGltaXQocmVxLCByZXMsIG5leHQpO1xuICB9XG5cbiAgdmFyIGlzUmVhZE9ubHlNYXN0ZXIgPSBpbmZvLm1hc3RlcktleSA9PT0gcmVxLmNvbmZpZy5yZWFkT25seU1hc3RlcktleTtcbiAgaWYgKFxuICAgIHR5cGVvZiByZXEuY29uZmlnLnJlYWRPbmx5TWFzdGVyS2V5ICE9ICd1bmRlZmluZWQnICYmXG4gICAgcmVxLmNvbmZpZy5yZWFkT25seU1hc3RlcktleSAmJlxuICAgIGlzUmVhZE9ubHlNYXN0ZXJcbiAgKSB7XG4gICAgcmVxLmF1dGggPSBuZXcgYXV0aC5BdXRoKHtcbiAgICAgIGNvbmZpZzogcmVxLmNvbmZpZyxcbiAgICAgIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgaXNNYXN0ZXI6IHRydWUsXG4gICAgICBpc1JlYWRPbmx5OiB0cnVlLFxuICAgIH0pO1xuICAgIHJldHVybiBoYW5kbGVSYXRlTGltaXQocmVxLCByZXMsIG5leHQpO1xuICB9XG5cbiAgLy8gQ2xpZW50IGtleXMgYXJlIG5vdCByZXF1aXJlZCBpbiBwYXJzZS1zZXJ2ZXIsIGJ1dCBpZiBhbnkgaGF2ZSBiZWVuIGNvbmZpZ3VyZWQgaW4gdGhlIHNlcnZlciwgdmFsaWRhdGUgdGhlbVxuICAvLyAgdG8gcHJlc2VydmUgb3JpZ2luYWwgYmVoYXZpb3IuXG4gIGNvbnN0IGtleXMgPSBbJ2NsaWVudEtleScsICdqYXZhc2NyaXB0S2V5JywgJ2RvdE5ldEtleScsICdyZXN0QVBJS2V5J107XG4gIGNvbnN0IG9uZUtleUNvbmZpZ3VyZWQgPSBrZXlzLnNvbWUoZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiByZXEuY29uZmlnW2tleV0gIT09IHVuZGVmaW5lZDtcbiAgfSk7XG4gIGNvbnN0IG9uZUtleU1hdGNoZXMgPSBrZXlzLnNvbWUoZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiByZXEuY29uZmlnW2tleV0gIT09IHVuZGVmaW5lZCAmJiBpbmZvW2tleV0gPT09IHJlcS5jb25maWdba2V5XTtcbiAgfSk7XG5cbiAgaWYgKG9uZUtleUNvbmZpZ3VyZWQgJiYgIW9uZUtleU1hdGNoZXMpIHtcbiAgICByZXR1cm4gaW52YWxpZFJlcXVlc3QocmVxLCByZXMpO1xuICB9XG5cbiAgaWYgKHJlcS51cmwgPT0gJy9sb2dpbicpIHtcbiAgICBkZWxldGUgaW5mby5zZXNzaW9uVG9rZW47XG4gIH1cblxuICBpZiAocmVxLnVzZXJGcm9tSldUKSB7XG4gICAgcmVxLmF1dGggPSBuZXcgYXV0aC5BdXRoKHtcbiAgICAgIGNvbmZpZzogcmVxLmNvbmZpZyxcbiAgICAgIGluc3RhbGxhdGlvbklkOiBpbmZvLmluc3RhbGxhdGlvbklkLFxuICAgICAgaXNNYXN0ZXI6IGZhbHNlLFxuICAgICAgdXNlcjogcmVxLnVzZXJGcm9tSldULFxuICAgIH0pO1xuICAgIHJldHVybiBoYW5kbGVSYXRlTGltaXQocmVxLCByZXMsIG5leHQpO1xuICB9XG5cbiAgaWYgKCFpbmZvLnNlc3Npb25Ub2tlbikge1xuICAgIHJlcS5hdXRoID0gbmV3IGF1dGguQXV0aCh7XG4gICAgICBjb25maWc6IHJlcS5jb25maWcsXG4gICAgICBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCxcbiAgICAgIGlzTWFzdGVyOiBmYWxzZSxcbiAgICB9KTtcbiAgfVxuICBoYW5kbGVSYXRlTGltaXQocmVxLCByZXMsIG5leHQpO1xufVxuXG5jb25zdCBoYW5kbGVSYXRlTGltaXQgPSBhc3luYyAocmVxLCByZXMsIG5leHQpID0+IHtcbiAgY29uc3QgcmF0ZUxpbWl0cyA9IHJlcS5jb25maWcucmF0ZUxpbWl0cyB8fCBbXTtcbiAgdHJ5IHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHJhdGVMaW1pdHMubWFwKGFzeW5jIGxpbWl0ID0+IHtcbiAgICAgICAgY29uc3QgcGF0aEV4cCA9IG5ldyBSZWdFeHAobGltaXQucGF0aCk7XG4gICAgICAgIGlmIChwYXRoRXhwLnRlc3QocmVxLnVybCkpIHtcbiAgICAgICAgICBhd2FpdCBsaW1pdC5oYW5kbGVyKHJlcSwgcmVzLCBlcnIgPT4ge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICBpZiAoZXJyLmNvZGUgPT09IFBhcnNlLkVycm9yLkNPTk5FQ1RJT05fRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlcS5jb25maWcubG9nZ2VyQ29udHJvbGxlci5lcnJvcihcbiAgICAgICAgICAgICAgICAnQW4gdW5rbm93biBlcnJvciBvY2N1cmVkIHdoZW4gYXR0ZW1wdGluZyB0byBhcHBseSB0aGUgcmF0ZSBsaW1pdGVyOiAnLFxuICAgICAgICAgICAgICAgIGVyclxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmVzLnN0YXR1cyg0MjkpO1xuICAgIHJlcy5qc29uKHsgY29kZTogUGFyc2UuRXJyb3IuQ09OTkVDVElPTl9GQUlMRUQsIGVycm9yOiBlcnJvci5tZXNzYWdlIH0pO1xuICAgIHJldHVybjtcbiAgfVxuICBuZXh0KCk7XG59O1xuXG5leHBvcnQgY29uc3QgaGFuZGxlUGFyc2VTZXNzaW9uID0gYXN5bmMgKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgaW5mbyA9IHJlcS5pbmZvO1xuICAgIGlmIChyZXEuYXV0aCB8fCByZXEudXJsID09PSAnL3Nlc3Npb25zL21lJykge1xuICAgICAgbmV4dCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcmVxdWVzdEF1dGggPSBudWxsO1xuICAgIGlmIChcbiAgICAgIGluZm8uc2Vzc2lvblRva2VuICYmXG4gICAgICByZXEudXJsID09PSAnL3VwZ3JhZGVUb1Jldm9jYWJsZVNlc3Npb24nICYmXG4gICAgICBpbmZvLnNlc3Npb25Ub2tlbi5pbmRleE9mKCdyOicpICE9IDBcbiAgICApIHtcbiAgICAgIHJlcXVlc3RBdXRoID0gYXdhaXQgYXV0aC5nZXRBdXRoRm9yTGVnYWN5U2Vzc2lvblRva2VuKHtcbiAgICAgICAgY29uZmlnOiByZXEuY29uZmlnLFxuICAgICAgICBpbnN0YWxsYXRpb25JZDogaW5mby5pbnN0YWxsYXRpb25JZCxcbiAgICAgICAgc2Vzc2lvblRva2VuOiBpbmZvLnNlc3Npb25Ub2tlbixcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXF1ZXN0QXV0aCA9IGF3YWl0IGF1dGguZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih7XG4gICAgICAgIGNvbmZpZzogcmVxLmNvbmZpZyxcbiAgICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluZm8uaW5zdGFsbGF0aW9uSWQsXG4gICAgICAgIHNlc3Npb25Ub2tlbjogaW5mby5zZXNzaW9uVG9rZW4sXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmVxLmF1dGggPSByZXF1ZXN0QXV0aDtcbiAgICBuZXh0KCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICAgIG5leHQoZXJyb3IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBUT0RPOiBEZXRlcm1pbmUgdGhlIGNvcnJlY3QgZXJyb3Igc2NlbmFyaW8uXG4gICAgcmVxLmNvbmZpZy5sb2dnZXJDb250cm9sbGVyLmVycm9yKCdlcnJvciBnZXR0aW5nIGF1dGggZm9yIHNlc3Npb25Ub2tlbicsIGVycm9yKTtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVU5LTk9XTl9FUlJPUiwgZXJyb3IpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBnZXRDbGllbnRJcChyZXEpIHtcbiAgcmV0dXJuIHJlcS5pcDtcbn1cblxuZnVuY3Rpb24gaHR0cEF1dGgocmVxKSB7XG4gIGlmICghKHJlcS5yZXEgfHwgcmVxKS5oZWFkZXJzLmF1dGhvcml6YXRpb24pIHsgcmV0dXJuOyB9XG5cbiAgdmFyIGhlYWRlciA9IChyZXEucmVxIHx8IHJlcSkuaGVhZGVycy5hdXRob3JpemF0aW9uO1xuICB2YXIgYXBwSWQsIG1hc3RlcktleSwgamF2YXNjcmlwdEtleTtcblxuICAvLyBwYXJzZSBoZWFkZXJcbiAgdmFyIGF1dGhQcmVmaXggPSAnYmFzaWMgJztcblxuICB2YXIgbWF0Y2ggPSBoZWFkZXIudG9Mb3dlckNhc2UoKS5pbmRleE9mKGF1dGhQcmVmaXgpO1xuXG4gIGlmIChtYXRjaCA9PSAwKSB7XG4gICAgdmFyIGVuY29kZWRBdXRoID0gaGVhZGVyLnN1YnN0cmluZyhhdXRoUHJlZml4Lmxlbmd0aCwgaGVhZGVyLmxlbmd0aCk7XG4gICAgdmFyIGNyZWRlbnRpYWxzID0gZGVjb2RlQmFzZTY0KGVuY29kZWRBdXRoKS5zcGxpdCgnOicpO1xuXG4gICAgaWYgKGNyZWRlbnRpYWxzLmxlbmd0aCA9PSAyKSB7XG4gICAgICBhcHBJZCA9IGNyZWRlbnRpYWxzWzBdO1xuICAgICAgdmFyIGtleSA9IGNyZWRlbnRpYWxzWzFdO1xuXG4gICAgICB2YXIganNLZXlQcmVmaXggPSAnamF2YXNjcmlwdC1rZXk9JztcblxuICAgICAgdmFyIG1hdGNoS2V5ID0ga2V5LmluZGV4T2YoanNLZXlQcmVmaXgpO1xuICAgICAgaWYgKG1hdGNoS2V5ID09IDApIHtcbiAgICAgICAgamF2YXNjcmlwdEtleSA9IGtleS5zdWJzdHJpbmcoanNLZXlQcmVmaXgubGVuZ3RoLCBrZXkubGVuZ3RoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1hc3RlcktleSA9IGtleTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBhcHBJZDogYXBwSWQsIG1hc3RlcktleTogbWFzdGVyS2V5LCBqYXZhc2NyaXB0S2V5OiBqYXZhc2NyaXB0S2V5IH07XG59XG5cbmZ1bmN0aW9uIGRlY29kZUJhc2U2NChzdHIpIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKHN0ciwgJ2Jhc2U2NCcpLnRvU3RyaW5nKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhbGxvd0Nyb3NzRG9tYWluKGFwcElkKSB7XG4gIHJldHVybiAocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICBjb25zdCBjb25maWcgPSBDb25maWcuZ2V0KGFwcElkLCBnZXRNb3VudEZvclJlcXVlc3QocmVxKSk7XG4gICAgbGV0IGFsbG93SGVhZGVycyA9IERFRkFVTFRfQUxMT1dFRF9IRUFERVJTO1xuICAgIGlmIChjb25maWcgJiYgY29uZmlnLmFsbG93SGVhZGVycykge1xuICAgICAgYWxsb3dIZWFkZXJzICs9IGAsICR7Y29uZmlnLmFsbG93SGVhZGVycy5qb2luKCcsICcpfWA7XG4gICAgfVxuXG4gICAgY29uc3QgYmFzZU9yaWdpbnMgPVxuICAgICAgdHlwZW9mIGNvbmZpZz8uYWxsb3dPcmlnaW4gPT09ICdzdHJpbmcnID8gW2NvbmZpZy5hbGxvd09yaWdpbl0gOiBjb25maWc/LmFsbG93T3JpZ2luID8/IFsnKiddO1xuICAgIGNvbnN0IHJlcXVlc3RPcmlnaW4gPSByZXEuaGVhZGVycy5vcmlnaW47XG4gICAgY29uc3QgYWxsb3dPcmlnaW5zID1cbiAgICAgIHJlcXVlc3RPcmlnaW4gJiYgYmFzZU9yaWdpbnMuaW5jbHVkZXMocmVxdWVzdE9yaWdpbikgPyByZXF1ZXN0T3JpZ2luIDogYmFzZU9yaWdpbnNbMF07XG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgYWxsb3dPcmlnaW5zKTtcbiAgICByZXMuaGVhZGVyKCdBY2Nlc3MtQ29udHJvbC1BbGxvdy1NZXRob2RzJywgJ0dFVCxQVVQsUE9TVCxERUxFVEUsT1BUSU9OUycpO1xuICAgIHJlcy5oZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnLCBhbGxvd0hlYWRlcnMpO1xuICAgIHJlcy5oZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUV4cG9zZS1IZWFkZXJzJywgJ1gtUGFyc2UtSm9iLVN0YXR1cy1JZCwgWC1QYXJzZS1QdXNoLVN0YXR1cy1JZCcpO1xuICAgIC8vIGludGVyY2VwdCBPUFRJT05TIG1ldGhvZFxuICAgIGlmICgnT1BUSU9OUycgPT0gcmVxLm1ldGhvZCkge1xuICAgICAgcmVzLnNlbmRTdGF0dXMoMjAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV4dCgpO1xuICAgIH1cbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFsbG93TWV0aG9kT3ZlcnJpZGUocmVxLCByZXMsIG5leHQpIHtcbiAgaWYgKHJlcS5tZXRob2QgPT09ICdQT1NUJyAmJiByZXEuYm9keT8uX21ldGhvZCkge1xuICAgIHJlcS5vcmlnaW5hbE1ldGhvZCA9IHJlcS5tZXRob2Q7XG4gICAgcmVxLm1ldGhvZCA9IHJlcS5ib2R5Ll9tZXRob2Q7XG4gICAgZGVsZXRlIHJlcS5ib2R5Ll9tZXRob2Q7XG4gIH1cbiAgbmV4dCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlUGFyc2VFcnJvcnMoZXJyLCByZXEsIHJlcywgbmV4dCkge1xuICBjb25zdCBsb2cgPSAocmVxLmNvbmZpZyAmJiByZXEuY29uZmlnLmxvZ2dlckNvbnRyb2xsZXIpIHx8IGRlZmF1bHRMb2dnZXI7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBQYXJzZS5FcnJvcikge1xuICAgIGlmIChyZXEuY29uZmlnICYmIHJlcS5jb25maWcuZW5hYmxlRXhwcmVzc0Vycm9ySGFuZGxlcikge1xuICAgICAgcmV0dXJuIG5leHQoZXJyKTtcbiAgICB9XG4gICAgbGV0IGh0dHBTdGF0dXM7XG4gICAgLy8gVE9ETzogZmlsbCBvdXQgdGhpcyBtYXBwaW5nXG4gICAgc3dpdGNoIChlcnIuY29kZSkge1xuICAgICAgY2FzZSBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1I6XG4gICAgICAgIGh0dHBTdGF0dXMgPSA1MDA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5EOlxuICAgICAgICBodHRwU3RhdHVzID0gNDA0O1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGh0dHBTdGF0dXMgPSA0MDA7XG4gICAgfVxuICAgIHJlcy5zdGF0dXMoaHR0cFN0YXR1cyk7XG4gICAgcmVzLmpzb24oeyBjb2RlOiBlcnIuY29kZSwgZXJyb3I6IGVyci5tZXNzYWdlIH0pO1xuICAgIGxvZy5lcnJvcignUGFyc2UgZXJyb3I6ICcsIGVycik7XG4gIH0gZWxzZSBpZiAoZXJyLnN0YXR1cyAmJiBlcnIubWVzc2FnZSkge1xuICAgIHJlcy5zdGF0dXMoZXJyLnN0YXR1cyk7XG4gICAgcmVzLmpzb24oeyBlcnJvcjogZXJyLm1lc3NhZ2UgfSk7XG4gICAgaWYgKCEocHJvY2VzcyAmJiBwcm9jZXNzLmVudi5URVNUSU5HKSkge1xuICAgICAgbmV4dChlcnIpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsb2cuZXJyb3IoJ1VuY2F1Z2h0IGludGVybmFsIHNlcnZlciBlcnJvci4nLCBlcnIsIGVyci5zdGFjayk7XG4gICAgcmVzLnN0YXR1cyg1MDApO1xuICAgIHJlcy5qc29uKHtcbiAgICAgIGNvZGU6IFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgIG1lc3NhZ2U6ICdJbnRlcm5hbCBzZXJ2ZXIgZXJyb3IuJyxcbiAgICB9KTtcbiAgICBpZiAoIShwcm9jZXNzICYmIHByb2Nlc3MuZW52LlRFU1RJTkcpKSB7XG4gICAgICBuZXh0KGVycik7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmZvcmNlTWFzdGVyS2V5QWNjZXNzKHJlcSwgcmVzLCBuZXh0KSB7XG4gIGlmICghcmVxLmF1dGguaXNNYXN0ZXIpIHtcbiAgICBjb25zdCBlcnJvciA9IGNyZWF0ZVNhbml0aXplZEh0dHBFcnJvcig0MDMsICd1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWQnLCByZXEuY29uZmlnKTtcbiAgICByZXMuc3RhdHVzKGVycm9yLnN0YXR1cyk7XG4gICAgcmVzLmVuZChge1wiZXJyb3JcIjpcIiR7ZXJyb3IubWVzc2FnZX1cIn1gKTtcbiAgICByZXR1cm47XG4gIH1cbiAgbmV4dCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJvbWlzZUVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MocmVxdWVzdCkge1xuICBpZiAoIXJlcXVlc3QuYXV0aC5pc01hc3Rlcikge1xuICAgIHRocm93IGNyZWF0ZVNhbml0aXplZEh0dHBFcnJvcig0MDMsICd1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWQnLCByZXF1ZXN0LmNvbmZpZyk7XG4gIH1cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG5leHBvcnQgY29uc3QgYWRkUmF0ZUxpbWl0ID0gKHJvdXRlLCBjb25maWcsIGNsb3VkKSA9PiB7XG4gIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgIGNvbmZpZyA9IENvbmZpZy5nZXQoY29uZmlnKTtcbiAgfVxuICBmb3IgKGNvbnN0IGtleSBpbiByb3V0ZSkge1xuICAgIGlmICghUmF0ZUxpbWl0T3B0aW9uc1trZXldKSB7XG4gICAgICB0aHJvdyBgSW52YWxpZCByYXRlIGxpbWl0IG9wdGlvbiBcIiR7a2V5fVwiYDtcbiAgICB9XG4gIH1cbiAgaWYgKCFjb25maWcucmF0ZUxpbWl0cykge1xuICAgIGNvbmZpZy5yYXRlTGltaXRzID0gW107XG4gIH1cbiAgY29uc3QgcmVkaXNTdG9yZSA9IHtcbiAgICBjb25uZWN0aW9uUHJvbWlzZTogUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgc3RvcmU6IG51bGwsXG4gIH07XG4gIGlmIChyb3V0ZS5yZWRpc1VybCkge1xuICAgIGNvbnN0IGxvZyA9IGNvbmZpZz8ubG9nZ2VyQ29udHJvbGxlciB8fCBkZWZhdWx0TG9nZ2VyO1xuICAgIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUNsaWVudCh7XG4gICAgICB1cmw6IHJvdXRlLnJlZGlzVXJsLFxuICAgIH0pO1xuICAgIGNsaWVudC5vbignZXJyb3InLCBlcnIgPT4geyBsb2cuZXJyb3IoJ01pZGRsZXdhcmVzIGFkZFJhdGVMaW1pdCBSZWRpcyBjbGllbnQgZXJyb3InLCB7IGVycm9yOiBlcnIgfSkgfSk7XG4gICAgY2xpZW50Lm9uKCdjb25uZWN0JywgKCkgPT4geyB9KTtcbiAgICBjbGllbnQub24oJ3JlY29ubmVjdGluZycsICgpID0+IHsgfSk7XG4gICAgY2xpZW50Lm9uKCdyZWFkeScsICgpID0+IHsgfSk7XG4gICAgcmVkaXNTdG9yZS5jb25uZWN0aW9uUHJvbWlzZSA9IGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChjbGllbnQuaXNPcGVuKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5jb25uZWN0KCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGxvZy5lcnJvcihgQ291bGQgbm90IGNvbm5lY3QgdG8gcmVkaXNVUkwgaW4gcmF0ZSBsaW1pdDogJHtlfWApO1xuICAgICAgfVxuICAgIH07XG4gICAgcmVkaXNTdG9yZS5jb25uZWN0aW9uUHJvbWlzZSgpO1xuICAgIHJlZGlzU3RvcmUuc3RvcmUgPSBuZXcgUmVkaXNTdG9yZSh7XG4gICAgICBzZW5kQ29tbWFuZDogYXN5bmMgKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgYXdhaXQgcmVkaXNTdG9yZS5jb25uZWN0aW9uUHJvbWlzZSgpO1xuICAgICAgICByZXR1cm4gY2xpZW50LnNlbmRDb21tYW5kKGFyZ3MpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuICBsZXQgdHJhbnNmb3JtUGF0aCA9IHJvdXRlLnJlcXVlc3RQYXRoLnNwbGl0KCcvKicpLmpvaW4oJy8oLiopJyk7XG4gIGlmICh0cmFuc2Zvcm1QYXRoID09PSAnKicpIHtcbiAgICB0cmFuc2Zvcm1QYXRoID0gJyguKiknO1xuICB9XG4gIGNvbmZpZy5yYXRlTGltaXRzLnB1c2goe1xuICAgIHBhdGg6IHBhdGhUb1JlZ2V4cCh0cmFuc2Zvcm1QYXRoKSxcbiAgICBoYW5kbGVyOiByYXRlTGltaXQoe1xuICAgICAgd2luZG93TXM6IHJvdXRlLnJlcXVlc3RUaW1lV2luZG93LFxuICAgICAgbWF4OiByb3V0ZS5yZXF1ZXN0Q291bnQsXG4gICAgICBtZXNzYWdlOiByb3V0ZS5lcnJvclJlc3BvbnNlTWVzc2FnZSB8fCBSYXRlTGltaXRPcHRpb25zLmVycm9yUmVzcG9uc2VNZXNzYWdlLmRlZmF1bHQsXG4gICAgICBoYW5kbGVyOiAocmVxdWVzdCwgcmVzcG9uc2UsIG5leHQsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgdGhyb3cge1xuICAgICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLkNPTk5FQ1RJT05fRkFJTEVELFxuICAgICAgICAgIG1lc3NhZ2U6IG9wdGlvbnMubWVzc2FnZSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBza2lwOiByZXF1ZXN0ID0+IHtcbiAgICAgICAgaWYgKHJlcXVlc3QuaXAgPT09ICcxMjcuMC4wLjEnICYmICFyb3V0ZS5pbmNsdWRlSW50ZXJuYWxSZXF1ZXN0cykge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyb3V0ZS5pbmNsdWRlTWFzdGVyS2V5KSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyb3V0ZS5yZXF1ZXN0TWV0aG9kcykge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJvdXRlLnJlcXVlc3RNZXRob2RzKSkge1xuICAgICAgICAgICAgaWYgKCFyb3V0ZS5yZXF1ZXN0TWV0aG9kcy5pbmNsdWRlcyhyZXF1ZXN0Lm1ldGhvZCkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJlZ0V4cCA9IG5ldyBSZWdFeHAocm91dGUucmVxdWVzdE1ldGhvZHMpO1xuICAgICAgICAgICAgaWYgKCFyZWdFeHAudGVzdChyZXF1ZXN0Lm1ldGhvZCkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXF1ZXN0LmF1dGg/LmlzTWFzdGVyO1xuICAgICAgfSxcbiAgICAgIGtleUdlbmVyYXRvcjogYXN5bmMgcmVxdWVzdCA9PiB7XG4gICAgICAgIGlmIChyb3V0ZS56b25lID09PSBQYXJzZS5TZXJ2ZXIuUmF0ZUxpbWl0Wm9uZS5nbG9iYWwpIHtcbiAgICAgICAgICByZXR1cm4gcmVxdWVzdC5jb25maWcuYXBwSWQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdG9rZW4gPSByZXF1ZXN0LmluZm8uc2Vzc2lvblRva2VuO1xuICAgICAgICBpZiAocm91dGUuem9uZSA9PT0gUGFyc2UuU2VydmVyLlJhdGVMaW1pdFpvbmUuc2Vzc2lvbiAmJiB0b2tlbikge1xuICAgICAgICAgIHJldHVybiB0b2tlbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocm91dGUuem9uZSA9PT0gUGFyc2UuU2VydmVyLlJhdGVMaW1pdFpvbmUudXNlciAmJiB0b2tlbikge1xuICAgICAgICAgIGlmICghcmVxdWVzdC5hdXRoKSB7XG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IGhhbmRsZVBhcnNlU2Vzc2lvbihyZXF1ZXN0LCBudWxsLCByZXNvbHZlKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChyZXF1ZXN0LmF1dGg/LnVzZXI/LmlkICYmIHJlcXVlc3Quem9uZSA9PT0gJ3VzZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVxdWVzdC5hdXRoLnVzZXIuaWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXF1ZXN0LmNvbmZpZy5pcDtcbiAgICAgIH0sXG4gICAgICBzdG9yZTogcmVkaXNTdG9yZS5zdG9yZSxcbiAgICB9KSxcbiAgICBjbG91ZCxcbiAgfSk7XG4gIENvbmZpZy5wdXQoY29uZmlnKTtcbn07XG5cbi8qKlxuICogRGVkdXBsaWNhdGVzIGEgcmVxdWVzdCB0byBlbnN1cmUgaWRlbXBvdGVuY3kuIER1cGxpY2F0ZXMgYXJlIGRldGVybWluZWQgYnkgdGhlIHJlcXVlc3QgSURcbiAqIGluIHRoZSByZXF1ZXN0IGhlYWRlci4gSWYgYSByZXF1ZXN0IGhhcyBubyByZXF1ZXN0IElELCBpdCBpcyBleGVjdXRlZCBhbnl3YXkuXG4gKiBAcGFyYW0geyp9IHJlcSBUaGUgcmVxdWVzdCB0byBldmFsdWF0ZS5cbiAqIEByZXR1cm5zIFByb21pc2U8e30+XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9taXNlRW5zdXJlSWRlbXBvdGVuY3kocmVxKSB7XG4gIC8vIEVuYWJsZSBmZWF0dXJlIG9ubHkgZm9yIE1vbmdvREJcbiAgaWYgKFxuICAgICEoXG4gICAgICByZXEuY29uZmlnLmRhdGFiYXNlLmFkYXB0ZXIgaW5zdGFuY2VvZiBNb25nb1N0b3JhZ2VBZGFwdGVyIHx8XG4gICAgICByZXEuY29uZmlnLmRhdGFiYXNlLmFkYXB0ZXIgaW5zdGFuY2VvZiBQb3N0Z3Jlc1N0b3JhZ2VBZGFwdGVyXG4gICAgKVxuICApIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cbiAgLy8gR2V0IHBhcmFtZXRlcnNcbiAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcbiAgY29uc3QgcmVxdWVzdElkID0gKChyZXEgfHwge30pLmhlYWRlcnMgfHwge30pWyd4LXBhcnNlLXJlcXVlc3QtaWQnXTtcbiAgY29uc3QgeyBwYXRocywgdHRsIH0gPSBjb25maWcuaWRlbXBvdGVuY3lPcHRpb25zO1xuICBpZiAoIXJlcXVlc3RJZCB8fCAhY29uZmlnLmlkZW1wb3RlbmN5T3B0aW9ucykge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICAvLyBSZXF1ZXN0IHBhdGggbWF5IGNvbnRhaW4gdHJhaWxpbmcgc2xhc2hlcywgZGVwZW5kaW5nIG9uIHRoZSBvcmlnaW5hbCByZXF1ZXN0LCBzbyByZW1vdmVcbiAgLy8gbGVhZGluZyBhbmQgdHJhaWxpbmcgc2xhc2hlcyB0byBtYWtlIGl0IGVhc2llciB0byBzcGVjaWZ5IHBhdGhzIGluIHRoZSBjb25maWd1cmF0aW9uXG4gIGNvbnN0IHJlcVBhdGggPSByZXEucGF0aC5yZXBsYWNlKC9eXFwvfFxcLyQvLCAnJyk7XG4gIC8vIERldGVybWluZSB3aGV0aGVyIGlkZW1wb3RlbmN5IGlzIGVuYWJsZWQgZm9yIGN1cnJlbnQgcmVxdWVzdCBwYXRoXG4gIGxldCBtYXRjaCA9IGZhbHNlO1xuICBmb3IgKGNvbnN0IHBhdGggb2YgcGF0aHMpIHtcbiAgICAvLyBBc3N1bWUgb25lIHdhbnRzIGEgcGF0aCB0byBhbHdheXMgbWF0Y2ggZnJvbSB0aGUgYmVnaW5uaW5nIHRvIHByZXZlbnQgYW55IG1pc3Rha2VzXG4gICAgY29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKHBhdGguY2hhckF0KDApID09PSAnXicgPyBwYXRoIDogJ14nICsgcGF0aCk7XG4gICAgaWYgKHJlcVBhdGgubWF0Y2gocmVnZXgpKSB7XG4gICAgICBtYXRjaCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgaWYgKCFtYXRjaCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICAvLyBUcnkgdG8gc3RvcmUgcmVxdWVzdFxuICBjb25zdCBleHBpcnlEYXRlID0gbmV3IERhdGUobmV3IERhdGUoKS5zZXRTZWNvbmRzKG5ldyBEYXRlKCkuZ2V0U2Vjb25kcygpICsgdHRsKSk7XG4gIHJldHVybiByZXN0XG4gICAgLmNyZWF0ZShjb25maWcsIGF1dGgubWFzdGVyKGNvbmZpZyksICdfSWRlbXBvdGVuY3knLCB7XG4gICAgICByZXFJZDogcmVxdWVzdElkLFxuICAgICAgZXhwaXJlOiBQYXJzZS5fZW5jb2RlKGV4cGlyeURhdGUpLFxuICAgIH0pXG4gICAgLmNhdGNoKGUgPT4ge1xuICAgICAgaWYgKGUuY29kZSA9PSBQYXJzZS5FcnJvci5EVVBMSUNBVEVfVkFMVUUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkRVUExJQ0FURV9SRVFVRVNULCAnRHVwbGljYXRlIHJlcXVlc3QnKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGludmFsaWRSZXF1ZXN0KHJlcSwgcmVzKSB7XG4gIHJlcy5zdGF0dXMoNDAzKTtcbiAgcmVzLmVuZCgne1wiZXJyb3JcIjpcInVuYXV0aG9yaXplZFwifScpO1xufVxuXG5mdW5jdGlvbiBtYWxmb3JtZWRDb250ZXh0KHJlcSwgcmVzKSB7XG4gIHJlcy5zdGF0dXMoNDAwKTtcbiAgcmVzLmpzb24oeyBjb2RlOiBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIGVycm9yOiAnSW52YWxpZCBvYmplY3QgZm9yIGNvbnRleHQuJyB9KTtcbn1cblxuLyoqXG4gKiBFeHByZXNzIDQgYWxsb3dlZCBhIGRvdWJsZSBmb3J3YXJkIHNsYXNoIGJldHdlZW4gYSByb3V0ZSBhbmQgcm91dGVyLiBBbHRob3VnaFxuICogdGhpcyBzaG91bGQgYmUgY29uc2lkZXJlZCBhbiBhbnRpLXBhdHRlcm4sIHdlIG5lZWQgdG8gc3VwcG9ydCBpdCBmb3IgYmFja3dhcmRzXG4gKiBjb21wYXRpYmlsaXR5LlxuICpcbiAqIFRlY2huaWNhbGx5IHZhbGlkIFVSTCB3aXRoIGRvdWJsZSBmb3Jvd2FyZCBzbGFzaDpcbiAqIGh0dHA6Ly9sb2NhbGhvc3Q6MTMzNy9wYXJzZS8vZnVuY3Rpb25zL3Rlc3RGdW5jdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gYWxsb3dEb3VibGVGb3J3YXJkU2xhc2gocmVxLCByZXMsIG5leHQpIHtcbiAgcmVxLnVybCA9IHJlcS51cmwuc3RhcnRzV2l0aCgnLy8nKSA/IHJlcS51cmwuc3Vic3RyaW5nKDEpIDogcmVxLnVybDtcbiAgbmV4dCgpO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsS0FBQSxHQUFBRixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUUsS0FBQSxHQUFBSCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUksVUFBQSxHQUFBTCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUssT0FBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sS0FBQSxHQUFBUCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU8sb0JBQUEsR0FBQVIsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFRLHVCQUFBLEdBQUFULHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUyxpQkFBQSxHQUFBVixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVUsWUFBQSxHQUFBVixPQUFBO0FBQ0EsSUFBQVcsYUFBQSxHQUFBWCxPQUFBO0FBQ0EsSUFBQVksZUFBQSxHQUFBYixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWEsTUFBQSxHQUFBYixPQUFBO0FBQ0EsSUFBQWMsSUFBQSxHQUFBZCxPQUFBO0FBQ0EsSUFBQWUsTUFBQSxHQUFBZixPQUFBO0FBQW1ELFNBQUFELHVCQUFBaUIsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUU1QyxNQUFNRyx1QkFBdUIsR0FBQUMsT0FBQSxDQUFBRCx1QkFBQSxHQUNsQywrT0FBK087QUFFalAsTUFBTUUsa0JBQWtCLEdBQUcsU0FBQUEsQ0FBVUMsR0FBRyxFQUFFO0VBQ3hDLE1BQU1DLGVBQWUsR0FBR0QsR0FBRyxDQUFDRSxX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
|