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
|
@@ -1,58 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.ParseLiveQueryServer =
|
|
7
|
-
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
var
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
var _QueryTools = require('./QueryTools');
|
|
31
|
-
|
|
32
|
-
var _ParsePubSub = require('./ParsePubSub');
|
|
33
|
-
|
|
34
|
-
var _SessionTokenCache = require('./SessionTokenCache');
|
|
35
|
-
|
|
36
|
-
var _lodash = require('lodash');
|
|
37
|
-
|
|
38
|
-
var _lodash2 = _interopRequireDefault(_lodash);
|
|
39
|
-
|
|
40
|
-
var _uuid = require('uuid');
|
|
41
|
-
|
|
42
|
-
var _uuid2 = _interopRequireDefault(_uuid);
|
|
43
|
-
|
|
44
|
-
var _triggers = require('../triggers');
|
|
45
|
-
|
|
46
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
6
|
+
exports.ParseLiveQueryServer = void 0;
|
|
7
|
+
var _tv = _interopRequireDefault(require("tv4"));
|
|
8
|
+
var _node = _interopRequireDefault(require("parse/node"));
|
|
9
|
+
var _Subscription = require("./Subscription");
|
|
10
|
+
var _Client = require("./Client");
|
|
11
|
+
var _ParseWebSocketServer = require("./ParseWebSocketServer");
|
|
12
|
+
var _logger = _interopRequireDefault(require("../logger"));
|
|
13
|
+
var _RequestSchema = _interopRequireDefault(require("./RequestSchema"));
|
|
14
|
+
var _QueryTools = require("./QueryTools");
|
|
15
|
+
var _ParsePubSub = require("./ParsePubSub");
|
|
16
|
+
var _SchemaController = _interopRequireDefault(require("../Controllers/SchemaController"));
|
|
17
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
18
|
+
var _uuid = require("uuid");
|
|
19
|
+
var _triggers = require("../triggers");
|
|
20
|
+
var _Auth = require("../Auth");
|
|
21
|
+
var _Controllers = require("../Controllers");
|
|
22
|
+
var _lruCache = require("lru-cache");
|
|
23
|
+
var _UsersRouter = _interopRequireDefault(require("../Routers/UsersRouter"));
|
|
24
|
+
var _DatabaseController = _interopRequireDefault(require("../Controllers/DatabaseController"));
|
|
25
|
+
var _util = require("util");
|
|
26
|
+
var _deepcopy = _interopRequireDefault(require("deepcopy"));
|
|
27
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
28
|
+
// @ts-ignore
|
|
47
29
|
|
|
48
30
|
class ParseLiveQueryServer {
|
|
49
31
|
// className -> (queryHash -> subscription)
|
|
50
|
-
|
|
32
|
+
|
|
33
|
+
// The subscriber we use to get object update from publisher
|
|
34
|
+
|
|
35
|
+
constructor(server, config = {}, parseServerConfig = {}) {
|
|
51
36
|
this.server = server;
|
|
52
37
|
this.clients = new Map();
|
|
53
38
|
this.subscriptions = new Map();
|
|
54
|
-
|
|
55
|
-
config = config ||
|
|
39
|
+
this.config = config;
|
|
40
|
+
config.appId = config.appId || _node.default.applicationId;
|
|
41
|
+
config.masterKey = config.masterKey || _node.default.masterKey;
|
|
56
42
|
|
|
57
43
|
// Store keys, convert obj to map
|
|
58
44
|
const keyPairs = config.keyPairs || {};
|
|
@@ -60,66 +46,106 @@ class ParseLiveQueryServer {
|
|
|
60
46
|
for (const key of Object.keys(keyPairs)) {
|
|
61
47
|
this.keyPairs.set(key, keyPairs[key]);
|
|
62
48
|
}
|
|
63
|
-
|
|
49
|
+
_logger.default.verbose('Support key pairs', this.keyPairs);
|
|
64
50
|
|
|
65
51
|
// Initialize Parse
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
_node.default.Object.disableSingleInstance();
|
|
53
|
+
const serverURL = config.serverURL || _node.default.serverURL;
|
|
54
|
+
_node.default.serverURL = serverURL;
|
|
55
|
+
_node.default.initialize(config.appId, _node.default.javaScriptKey, config.masterKey);
|
|
56
|
+
|
|
57
|
+
// The cache controller is a proper cache controller
|
|
58
|
+
// with access to User and Roles
|
|
59
|
+
this.cacheController = (0, _Controllers.getCacheController)(parseServerConfig);
|
|
60
|
+
config.cacheTimeout = config.cacheTimeout || 5 * 1000; // 5s
|
|
61
|
+
|
|
62
|
+
// This auth cache stores the promises for each auth resolution.
|
|
63
|
+
// The main benefit is to be able to reuse the same user / session token resolution.
|
|
64
|
+
this.authCache = new _lruCache.LRUCache({
|
|
65
|
+
max: 500,
|
|
66
|
+
// 500 concurrent
|
|
67
|
+
ttl: config.cacheTimeout
|
|
68
|
+
});
|
|
75
69
|
// Initialize websocket server
|
|
76
|
-
this.parseWebSocketServer = new _ParseWebSocketServer.ParseWebSocketServer(server, parseWebsocket => this._onConnect(parseWebsocket), config
|
|
77
|
-
|
|
78
|
-
// Initialize subscriber
|
|
70
|
+
this.parseWebSocketServer = new _ParseWebSocketServer.ParseWebSocketServer(server, parseWebsocket => this._onConnect(parseWebsocket), config);
|
|
79
71
|
this.subscriber = _ParsePubSub.ParsePubSub.createSubscriber(config);
|
|
80
|
-
this.subscriber.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
if (!this.subscriber.connect) {
|
|
73
|
+
this.connect();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async connect() {
|
|
77
|
+
if (this.subscriber.isOpen) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (typeof this.subscriber.connect === 'function') {
|
|
81
|
+
await Promise.resolve(this.subscriber.connect());
|
|
82
|
+
} else {
|
|
83
|
+
this.subscriber.isOpen = true;
|
|
84
|
+
}
|
|
85
|
+
this._createSubscribers();
|
|
86
|
+
}
|
|
87
|
+
async shutdown() {
|
|
88
|
+
if (this.subscriber.isOpen) {
|
|
89
|
+
await Promise.all([...[...this.clients.values()].map(client => client.parseWebSocket.ws.close()), this.parseWebSocketServer.close?.(), ...Array.from(this.subscriber.subscriptions?.keys() || []).map(key => this.subscriber.unsubscribe(key)), this.subscriber.close?.()]);
|
|
90
|
+
}
|
|
91
|
+
if (typeof this.subscriber.quit === 'function') {
|
|
92
|
+
try {
|
|
93
|
+
await this.subscriber.quit();
|
|
94
|
+
} catch (err) {
|
|
95
|
+
_logger.default.error('PubSubAdapter error on shutdown', {
|
|
96
|
+
error: err
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
this.subscriber.isOpen = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
_createSubscribers() {
|
|
104
|
+
const messageRecieved = (channel, messageStr) => {
|
|
105
|
+
_logger.default.verbose('Subscribe message %j', messageStr);
|
|
86
106
|
let message;
|
|
87
107
|
try {
|
|
88
108
|
message = JSON.parse(messageStr);
|
|
89
109
|
} catch (e) {
|
|
90
|
-
|
|
110
|
+
_logger.default.error('unable to parse message', messageStr, e);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (channel === _node.default.applicationId + 'clearCache') {
|
|
114
|
+
this._clearCachedRoles(message.userId);
|
|
91
115
|
return;
|
|
92
116
|
}
|
|
93
117
|
this._inflateParseObject(message);
|
|
94
|
-
if (channel ===
|
|
118
|
+
if (channel === _node.default.applicationId + 'afterSave') {
|
|
95
119
|
this._onAfterSave(message);
|
|
96
|
-
} else if (channel ===
|
|
120
|
+
} else if (channel === _node.default.applicationId + 'afterDelete') {
|
|
97
121
|
this._onAfterDelete(message);
|
|
98
122
|
} else {
|
|
99
|
-
|
|
123
|
+
_logger.default.error('Get message %s from unknown channel %j', message, channel);
|
|
100
124
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
125
|
+
};
|
|
126
|
+
this.subscriber.on('message', (channel, messageStr) => messageRecieved(channel, messageStr));
|
|
127
|
+
for (const field of ['afterSave', 'afterDelete', 'clearCache']) {
|
|
128
|
+
const channel = `${_node.default.applicationId}${field}`;
|
|
129
|
+
this.subscriber.subscribe(channel, messageStr => messageRecieved(channel, messageStr));
|
|
130
|
+
}
|
|
105
131
|
}
|
|
106
132
|
|
|
107
133
|
// Message is the JSON object from publisher. Message.currentParseObject is the ParseObject JSON after changes.
|
|
108
134
|
// Message.originalParseObject is the original ParseObject JSON.
|
|
109
|
-
|
|
110
|
-
// The subscriber we use to get object update from publisher
|
|
111
135
|
_inflateParseObject(message) {
|
|
112
136
|
// Inflate merged object
|
|
113
137
|
const currentParseObject = message.currentParseObject;
|
|
138
|
+
_UsersRouter.default.removeHiddenProperties(currentParseObject);
|
|
114
139
|
let className = currentParseObject.className;
|
|
115
|
-
let parseObject = new
|
|
140
|
+
let parseObject = new _node.default.Object(className);
|
|
116
141
|
parseObject._finishFetch(currentParseObject);
|
|
117
142
|
message.currentParseObject = parseObject;
|
|
118
143
|
// Inflate original object
|
|
119
144
|
const originalParseObject = message.originalParseObject;
|
|
120
145
|
if (originalParseObject) {
|
|
146
|
+
_UsersRouter.default.removeHiddenProperties(originalParseObject);
|
|
121
147
|
className = originalParseObject.className;
|
|
122
|
-
parseObject = new
|
|
148
|
+
parseObject = new _node.default.Object(className);
|
|
123
149
|
parseObject._finishFetch(originalParseObject);
|
|
124
150
|
message.originalParseObject = parseObject;
|
|
125
151
|
}
|
|
@@ -127,17 +153,16 @@ class ParseLiveQueryServer {
|
|
|
127
153
|
|
|
128
154
|
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
|
|
129
155
|
// Message.originalParseObject is the original ParseObject.
|
|
130
|
-
_onAfterDelete(message) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
156
|
+
async _onAfterDelete(message) {
|
|
157
|
+
_logger.default.verbose(_node.default.applicationId + 'afterDelete is triggered');
|
|
158
|
+
let deletedParseObject = message.currentParseObject.toJSON();
|
|
159
|
+
const classLevelPermissions = message.classLevelPermissions;
|
|
134
160
|
const className = deletedParseObject.className;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
161
|
+
_logger.default.verbose('ClassName: %j | ObjectId: %s', className, deletedParseObject.id);
|
|
162
|
+
_logger.default.verbose('Current client number : %d', this.clients.size);
|
|
138
163
|
const classSubscriptions = this.subscriptions.get(className);
|
|
139
164
|
if (typeof classSubscriptions === 'undefined') {
|
|
140
|
-
|
|
165
|
+
_logger.default.debug('Can not find subscriptions under this class ' + className);
|
|
141
166
|
return;
|
|
142
167
|
}
|
|
143
168
|
for (const subscription of classSubscriptions.values()) {
|
|
@@ -145,60 +170,93 @@ class ParseLiveQueryServer {
|
|
|
145
170
|
if (!isSubscriptionMatched) {
|
|
146
171
|
continue;
|
|
147
172
|
}
|
|
148
|
-
for (const [clientId, requestIds] of
|
|
173
|
+
for (const [clientId, requestIds] of _lodash.default.entries(subscription.clientRequestIds)) {
|
|
149
174
|
const client = this.clients.get(clientId);
|
|
150
175
|
if (typeof client === 'undefined') {
|
|
151
176
|
continue;
|
|
152
177
|
}
|
|
153
|
-
|
|
178
|
+
requestIds.forEach(async requestId => {
|
|
154
179
|
const acl = message.currentParseObject.getACL();
|
|
155
|
-
// Check
|
|
156
|
-
this.
|
|
180
|
+
// Check CLP
|
|
181
|
+
const op = this._getCLPOperation(subscription.query);
|
|
182
|
+
let res = {};
|
|
183
|
+
try {
|
|
184
|
+
await this._matchesCLP(classLevelPermissions, message.currentParseObject, client, requestId, op);
|
|
185
|
+
const isMatched = await this._matchesACL(acl, client, requestId);
|
|
157
186
|
if (!isMatched) {
|
|
158
187
|
return null;
|
|
159
188
|
}
|
|
189
|
+
res = {
|
|
190
|
+
event: 'delete',
|
|
191
|
+
sessionToken: client.sessionToken,
|
|
192
|
+
object: deletedParseObject,
|
|
193
|
+
clients: this.clients.size,
|
|
194
|
+
subscriptions: this.subscriptions.size,
|
|
195
|
+
useMasterKey: client.hasMasterKey,
|
|
196
|
+
installationId: client.installationId,
|
|
197
|
+
sendEvent: true
|
|
198
|
+
};
|
|
199
|
+
const trigger = (0, _triggers.getTrigger)(className, 'afterEvent', _node.default.applicationId);
|
|
200
|
+
if (trigger) {
|
|
201
|
+
const auth = await this.getAuthFromClient(client, requestId);
|
|
202
|
+
if (auth && auth.user) {
|
|
203
|
+
res.user = auth.user;
|
|
204
|
+
}
|
|
205
|
+
if (res.object) {
|
|
206
|
+
res.object = _node.default.Object.fromJSON(res.object);
|
|
207
|
+
}
|
|
208
|
+
await (0, _triggers.runTrigger)(trigger, `afterEvent.${className}`, res, auth);
|
|
209
|
+
}
|
|
210
|
+
if (!res.sendEvent) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (res.object && typeof res.object.toJSON === 'function') {
|
|
214
|
+
deletedParseObject = (0, _triggers.toJSONwithObjects)(res.object, res.object.className || className);
|
|
215
|
+
}
|
|
216
|
+
await this._filterSensitiveData(classLevelPermissions, res, client, requestId, op, subscription.query);
|
|
160
217
|
client.pushDelete(requestId, deletedParseObject);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
218
|
+
} catch (e) {
|
|
219
|
+
const error = (0, _triggers.resolveError)(e);
|
|
220
|
+
_Client.Client.pushError(client.parseWebSocket, error.code, error.message, false, requestId);
|
|
221
|
+
_logger.default.error(`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` + JSON.stringify(error));
|
|
222
|
+
}
|
|
223
|
+
});
|
|
165
224
|
}
|
|
166
225
|
}
|
|
167
226
|
}
|
|
168
227
|
|
|
169
228
|
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
|
|
170
229
|
// Message.originalParseObject is the original ParseObject.
|
|
171
|
-
_onAfterSave(message) {
|
|
172
|
-
|
|
173
|
-
|
|
230
|
+
async _onAfterSave(message) {
|
|
231
|
+
_logger.default.verbose(_node.default.applicationId + 'afterSave is triggered');
|
|
174
232
|
let originalParseObject = null;
|
|
175
233
|
if (message.originalParseObject) {
|
|
176
234
|
originalParseObject = message.originalParseObject.toJSON();
|
|
177
235
|
}
|
|
178
|
-
const
|
|
236
|
+
const classLevelPermissions = message.classLevelPermissions;
|
|
237
|
+
let currentParseObject = message.currentParseObject.toJSON();
|
|
179
238
|
const className = currentParseObject.className;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
239
|
+
_logger.default.verbose('ClassName: %s | ObjectId: %s', className, currentParseObject.id);
|
|
240
|
+
_logger.default.verbose('Current client number : %d', this.clients.size);
|
|
183
241
|
const classSubscriptions = this.subscriptions.get(className);
|
|
184
242
|
if (typeof classSubscriptions === 'undefined') {
|
|
185
|
-
|
|
243
|
+
_logger.default.debug('Can not find subscriptions under this class ' + className);
|
|
186
244
|
return;
|
|
187
245
|
}
|
|
188
246
|
for (const subscription of classSubscriptions.values()) {
|
|
189
247
|
const isOriginalSubscriptionMatched = this._matchesSubscription(originalParseObject, subscription);
|
|
190
248
|
const isCurrentSubscriptionMatched = this._matchesSubscription(currentParseObject, subscription);
|
|
191
|
-
for (const [clientId, requestIds] of
|
|
249
|
+
for (const [clientId, requestIds] of _lodash.default.entries(subscription.clientRequestIds)) {
|
|
192
250
|
const client = this.clients.get(clientId);
|
|
193
251
|
if (typeof client === 'undefined') {
|
|
194
252
|
continue;
|
|
195
253
|
}
|
|
196
|
-
|
|
254
|
+
requestIds.forEach(async requestId => {
|
|
197
255
|
// Set orignal ParseObject ACL checking promise, if the object does not match
|
|
198
256
|
// subscription, we do not need to check ACL
|
|
199
257
|
let originalACLCheckingPromise;
|
|
200
258
|
if (!isOriginalSubscriptionMatched) {
|
|
201
|
-
originalACLCheckingPromise =
|
|
259
|
+
originalACLCheckingPromise = Promise.resolve(false);
|
|
202
260
|
} else {
|
|
203
261
|
let originalACL;
|
|
204
262
|
if (message.originalParseObject) {
|
|
@@ -209,60 +267,103 @@ class ParseLiveQueryServer {
|
|
|
209
267
|
// Set current ParseObject ACL checking promise, if the object does not match
|
|
210
268
|
// subscription, we do not need to check ACL
|
|
211
269
|
let currentACLCheckingPromise;
|
|
270
|
+
let res = {};
|
|
212
271
|
if (!isCurrentSubscriptionMatched) {
|
|
213
|
-
currentACLCheckingPromise =
|
|
272
|
+
currentACLCheckingPromise = Promise.resolve(false);
|
|
214
273
|
} else {
|
|
215
274
|
const currentACL = message.currentParseObject.getACL();
|
|
216
275
|
currentACLCheckingPromise = this._matchesACL(currentACL, client, requestId);
|
|
217
276
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
277
|
+
try {
|
|
278
|
+
const op = this._getCLPOperation(subscription.query);
|
|
279
|
+
await this._matchesCLP(classLevelPermissions, message.currentParseObject, client, requestId, op);
|
|
280
|
+
const [isOriginalMatched, isCurrentMatched] = await Promise.all([originalACLCheckingPromise, currentACLCheckingPromise]);
|
|
281
|
+
_logger.default.verbose('Original %j | Current %j | Match: %s, %s, %s, %s | Query: %s', originalParseObject, currentParseObject, isOriginalSubscriptionMatched, isCurrentSubscriptionMatched, isOriginalMatched, isCurrentMatched, subscription.hash);
|
|
222
282
|
// Decide event type
|
|
223
283
|
let type;
|
|
224
284
|
if (isOriginalMatched && isCurrentMatched) {
|
|
225
|
-
type = '
|
|
285
|
+
type = 'update';
|
|
226
286
|
} else if (isOriginalMatched && !isCurrentMatched) {
|
|
227
|
-
type = '
|
|
287
|
+
type = 'leave';
|
|
228
288
|
} else if (!isOriginalMatched && isCurrentMatched) {
|
|
229
289
|
if (originalParseObject) {
|
|
230
|
-
type = '
|
|
290
|
+
type = 'enter';
|
|
231
291
|
} else {
|
|
232
|
-
type = '
|
|
292
|
+
type = 'create';
|
|
233
293
|
}
|
|
234
294
|
} else {
|
|
235
295
|
return null;
|
|
236
296
|
}
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
297
|
+
const watchFieldsChanged = this._checkWatchFields(client, requestId, message);
|
|
298
|
+
if (!watchFieldsChanged && (type === 'update' || type === 'create')) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
res = {
|
|
302
|
+
event: type,
|
|
303
|
+
sessionToken: client.sessionToken,
|
|
304
|
+
object: currentParseObject,
|
|
305
|
+
original: originalParseObject,
|
|
306
|
+
clients: this.clients.size,
|
|
307
|
+
subscriptions: this.subscriptions.size,
|
|
308
|
+
useMasterKey: client.hasMasterKey,
|
|
309
|
+
installationId: client.installationId,
|
|
310
|
+
sendEvent: true
|
|
311
|
+
};
|
|
312
|
+
const trigger = (0, _triggers.getTrigger)(className, 'afterEvent', _node.default.applicationId);
|
|
313
|
+
if (trigger) {
|
|
314
|
+
if (res.object) {
|
|
315
|
+
res.object = _node.default.Object.fromJSON(res.object);
|
|
316
|
+
}
|
|
317
|
+
if (res.original) {
|
|
318
|
+
res.original = _node.default.Object.fromJSON(res.original);
|
|
319
|
+
}
|
|
320
|
+
const auth = await this.getAuthFromClient(client, requestId);
|
|
321
|
+
if (auth && auth.user) {
|
|
322
|
+
res.user = auth.user;
|
|
323
|
+
}
|
|
324
|
+
await (0, _triggers.runTrigger)(trigger, `afterEvent.${className}`, res, auth);
|
|
325
|
+
}
|
|
326
|
+
if (!res.sendEvent) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (res.object && typeof res.object.toJSON === 'function') {
|
|
330
|
+
currentParseObject = (0, _triggers.toJSONwithObjects)(res.object, res.object.className || className);
|
|
331
|
+
}
|
|
332
|
+
if (res.original && typeof res.original.toJSON === 'function') {
|
|
333
|
+
originalParseObject = (0, _triggers.toJSONwithObjects)(res.original, res.original.className || className);
|
|
334
|
+
}
|
|
335
|
+
await this._filterSensitiveData(classLevelPermissions, res, client, requestId, op, subscription.query);
|
|
336
|
+
const functionName = 'push' + res.event.charAt(0).toUpperCase() + res.event.slice(1);
|
|
337
|
+
if (client[functionName]) {
|
|
338
|
+
client[functionName](requestId, currentParseObject, originalParseObject);
|
|
339
|
+
}
|
|
340
|
+
} catch (e) {
|
|
341
|
+
const error = (0, _triggers.resolveError)(e);
|
|
342
|
+
_Client.Client.pushError(client.parseWebSocket, error.code, error.message, false, requestId);
|
|
343
|
+
_logger.default.error(`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` + JSON.stringify(error));
|
|
344
|
+
}
|
|
345
|
+
});
|
|
243
346
|
}
|
|
244
347
|
}
|
|
245
348
|
}
|
|
246
|
-
|
|
247
349
|
_onConnect(parseWebsocket) {
|
|
248
350
|
parseWebsocket.on('message', request => {
|
|
249
351
|
if (typeof request === 'string') {
|
|
250
352
|
try {
|
|
251
353
|
request = JSON.parse(request);
|
|
252
354
|
} catch (e) {
|
|
253
|
-
|
|
355
|
+
_logger.default.error('unable to parse request', request, e);
|
|
254
356
|
return;
|
|
255
357
|
}
|
|
256
358
|
}
|
|
257
|
-
|
|
359
|
+
_logger.default.verbose('Request: %j', request);
|
|
258
360
|
|
|
259
361
|
// Check whether this request is a valid request, return error directly if not
|
|
260
|
-
if (!
|
|
261
|
-
_Client.Client.pushError(parseWebsocket, 1,
|
|
262
|
-
|
|
362
|
+
if (!_tv.default.validate(request, _RequestSchema.default['general']) || !_tv.default.validate(request, _RequestSchema.default[request.op])) {
|
|
363
|
+
_Client.Client.pushError(parseWebsocket, 1, _tv.default.error.message);
|
|
364
|
+
_logger.default.error('Connect message error %s', _tv.default.error.message);
|
|
263
365
|
return;
|
|
264
366
|
}
|
|
265
|
-
|
|
266
367
|
switch (request.op) {
|
|
267
368
|
case 'connect':
|
|
268
369
|
this._handleConnect(parseWebsocket, request);
|
|
@@ -278,12 +379,11 @@ class ParseLiveQueryServer {
|
|
|
278
379
|
break;
|
|
279
380
|
default:
|
|
280
381
|
_Client.Client.pushError(parseWebsocket, 3, 'Get unknown operation');
|
|
281
|
-
|
|
382
|
+
_logger.default.error('Get unknown operation', request.op);
|
|
282
383
|
}
|
|
283
384
|
});
|
|
284
|
-
|
|
285
385
|
parseWebsocket.on('disconnect', () => {
|
|
286
|
-
|
|
386
|
+
_logger.default.info(`Client disconnect: ${parseWebsocket.clientId}`);
|
|
287
387
|
const clientId = parseWebsocket.clientId;
|
|
288
388
|
if (!this.clients.has(clientId)) {
|
|
289
389
|
(0, _triggers.runLiveQueryEventHandlers)({
|
|
@@ -292,7 +392,7 @@ class ParseLiveQueryServer {
|
|
|
292
392
|
subscriptions: this.subscriptions.size,
|
|
293
393
|
error: `Unable to find client ${clientId}`
|
|
294
394
|
});
|
|
295
|
-
|
|
395
|
+
_logger.default.error(`Can not find client ${clientId} on disconnect`);
|
|
296
396
|
return;
|
|
297
397
|
}
|
|
298
398
|
|
|
@@ -301,7 +401,7 @@ class ParseLiveQueryServer {
|
|
|
301
401
|
this.clients.delete(clientId);
|
|
302
402
|
|
|
303
403
|
// Delete client from subscriptions
|
|
304
|
-
for (const [requestId, subscriptionInfo] of
|
|
404
|
+
for (const [requestId, subscriptionInfo] of _lodash.default.entries(client.subscriptionInfos)) {
|
|
305
405
|
const subscription = subscriptionInfo.subscription;
|
|
306
406
|
subscription.deleteClientSubscription(clientId, requestId);
|
|
307
407
|
|
|
@@ -315,143 +415,282 @@ class ParseLiveQueryServer {
|
|
|
315
415
|
this.subscriptions.delete(subscription.className);
|
|
316
416
|
}
|
|
317
417
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
_logger2.default.verbose('Current subscriptions %d', this.subscriptions.size);
|
|
418
|
+
_logger.default.verbose('Current clients %d', this.clients.size);
|
|
419
|
+
_logger.default.verbose('Current subscriptions %d', this.subscriptions.size);
|
|
321
420
|
(0, _triggers.runLiveQueryEventHandlers)({
|
|
322
421
|
event: 'ws_disconnect',
|
|
323
422
|
clients: this.clients.size,
|
|
324
|
-
subscriptions: this.subscriptions.size
|
|
423
|
+
subscriptions: this.subscriptions.size,
|
|
424
|
+
useMasterKey: client.hasMasterKey,
|
|
425
|
+
installationId: client.installationId,
|
|
426
|
+
sessionToken: client.sessionToken
|
|
325
427
|
});
|
|
326
428
|
});
|
|
327
|
-
|
|
328
429
|
(0, _triggers.runLiveQueryEventHandlers)({
|
|
329
430
|
event: 'ws_connect',
|
|
330
431
|
clients: this.clients.size,
|
|
331
432
|
subscriptions: this.subscriptions.size
|
|
332
433
|
});
|
|
333
434
|
}
|
|
334
|
-
|
|
335
435
|
_matchesSubscription(parseObject, subscription) {
|
|
336
436
|
// Object is undefined or null, not match
|
|
337
437
|
if (!parseObject) {
|
|
338
438
|
return false;
|
|
339
439
|
}
|
|
340
|
-
return (0, _QueryTools.matchesQuery)(parseObject, subscription.query);
|
|
440
|
+
return (0, _QueryTools.matchesQuery)((0, _deepcopy.default)(parseObject), subscription.query);
|
|
341
441
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
442
|
+
async _clearCachedRoles(userId) {
|
|
443
|
+
try {
|
|
444
|
+
const validTokens = await new _node.default.Query(_node.default.Session).equalTo('user', _node.default.User.createWithoutData(userId)).find({
|
|
445
|
+
useMasterKey: true
|
|
446
|
+
});
|
|
447
|
+
await Promise.all(validTokens.map(async token => {
|
|
448
|
+
const sessionToken = token.get('sessionToken');
|
|
449
|
+
const authPromise = this.authCache.get(sessionToken);
|
|
450
|
+
if (!authPromise) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const [auth1, auth2] = await Promise.all([authPromise, (0, _Auth.getAuthForSessionToken)({
|
|
454
|
+
cacheController: this.cacheController,
|
|
455
|
+
sessionToken
|
|
456
|
+
})]);
|
|
457
|
+
auth1.auth?.clearRoleCache(sessionToken);
|
|
458
|
+
auth2.auth?.clearRoleCache(sessionToken);
|
|
459
|
+
this.authCache.delete(sessionToken);
|
|
460
|
+
}));
|
|
461
|
+
} catch (e) {
|
|
462
|
+
_logger.default.verbose(`Could not clear role cache. ${e}`);
|
|
347
463
|
}
|
|
348
|
-
|
|
464
|
+
}
|
|
465
|
+
getAuthForSessionToken(sessionToken) {
|
|
466
|
+
if (!sessionToken) {
|
|
467
|
+
return Promise.resolve({});
|
|
468
|
+
}
|
|
469
|
+
const fromCache = this.authCache.get(sessionToken);
|
|
470
|
+
if (fromCache) {
|
|
471
|
+
return fromCache;
|
|
472
|
+
}
|
|
473
|
+
const authPromise = (0, _Auth.getAuthForSessionToken)({
|
|
474
|
+
cacheController: this.cacheController,
|
|
475
|
+
sessionToken: sessionToken
|
|
476
|
+
}).then(auth => {
|
|
477
|
+
return {
|
|
478
|
+
auth,
|
|
479
|
+
userId: auth && auth.user && auth.user.id
|
|
480
|
+
};
|
|
481
|
+
}).catch(error => {
|
|
482
|
+
// There was an error with the session token
|
|
483
|
+
const result = {};
|
|
484
|
+
if (error && error.code === _node.default.Error.INVALID_SESSION_TOKEN) {
|
|
485
|
+
result.error = error;
|
|
486
|
+
this.authCache.set(sessionToken, Promise.resolve(result), this.config.cacheTimeout);
|
|
487
|
+
} else {
|
|
488
|
+
this.authCache.delete(sessionToken);
|
|
489
|
+
}
|
|
490
|
+
return result;
|
|
491
|
+
});
|
|
492
|
+
this.authCache.set(sessionToken, authPromise);
|
|
493
|
+
return authPromise;
|
|
494
|
+
}
|
|
495
|
+
async _matchesCLP(classLevelPermissions, object, client, requestId, op) {
|
|
496
|
+
// try to match on user first, less expensive than with roles
|
|
349
497
|
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
|
350
|
-
|
|
351
|
-
|
|
498
|
+
const aclGroup = ['*'];
|
|
499
|
+
let userId;
|
|
500
|
+
if (typeof subscriptionInfo !== 'undefined') {
|
|
501
|
+
const {
|
|
502
|
+
userId
|
|
503
|
+
} = await this.getAuthForSessionToken(subscriptionInfo.sessionToken);
|
|
504
|
+
if (userId) {
|
|
505
|
+
aclGroup.push(userId);
|
|
506
|
+
}
|
|
352
507
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
508
|
+
try {
|
|
509
|
+
await _SchemaController.default.validatePermission(classLevelPermissions, object.className, aclGroup, op);
|
|
510
|
+
return true;
|
|
511
|
+
} catch (e) {
|
|
512
|
+
_logger.default.verbose(`Failed matching CLP for ${object.id} ${userId} ${e}`);
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
// TODO: handle roles permissions
|
|
516
|
+
// Object.keys(classLevelPermissions).forEach((key) => {
|
|
517
|
+
// const perm = classLevelPermissions[key];
|
|
518
|
+
// Object.keys(perm).forEach((key) => {
|
|
519
|
+
// if (key.indexOf('role'))
|
|
520
|
+
// });
|
|
521
|
+
// })
|
|
522
|
+
// // it's rejected here, check the roles
|
|
523
|
+
// var rolesQuery = new Parse.Query(Parse.Role);
|
|
524
|
+
// rolesQuery.equalTo("users", user);
|
|
525
|
+
// return rolesQuery.find({useMasterKey:true});
|
|
526
|
+
}
|
|
527
|
+
async _filterSensitiveData(classLevelPermissions, res, client, requestId, op, query) {
|
|
528
|
+
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
|
529
|
+
const aclGroup = ['*'];
|
|
530
|
+
let clientAuth;
|
|
531
|
+
if (typeof subscriptionInfo !== 'undefined') {
|
|
532
|
+
const {
|
|
533
|
+
userId,
|
|
534
|
+
auth
|
|
535
|
+
} = await this.getAuthForSessionToken(subscriptionInfo.sessionToken);
|
|
536
|
+
if (userId) {
|
|
537
|
+
aclGroup.push(userId);
|
|
360
538
|
}
|
|
539
|
+
clientAuth = auth;
|
|
540
|
+
}
|
|
541
|
+
const filter = obj => {
|
|
542
|
+
if (!obj) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
let protectedFields = classLevelPermissions?.protectedFields || [];
|
|
546
|
+
if (!client.hasMasterKey && !Array.isArray(protectedFields)) {
|
|
547
|
+
protectedFields = (0, _Controllers.getDatabaseController)(this.config).addProtectedFields(classLevelPermissions, res.object.className, query, aclGroup, clientAuth);
|
|
548
|
+
}
|
|
549
|
+
return _DatabaseController.default.filterSensitiveData(client.hasMasterKey, false, aclGroup, clientAuth, op, classLevelPermissions, res.object.className, protectedFields, obj, query);
|
|
550
|
+
};
|
|
551
|
+
res.object = filter(res.object);
|
|
552
|
+
res.original = filter(res.original);
|
|
553
|
+
}
|
|
554
|
+
_getCLPOperation(query) {
|
|
555
|
+
return typeof query === 'object' && Object.keys(query).length == 1 && typeof query.objectId === 'string' ? 'get' : 'find';
|
|
556
|
+
}
|
|
557
|
+
async _verifyACL(acl, token) {
|
|
558
|
+
if (!token) {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
const {
|
|
562
|
+
auth,
|
|
563
|
+
userId
|
|
564
|
+
} = await this.getAuthForSessionToken(token);
|
|
565
|
+
|
|
566
|
+
// Getting the session token failed
|
|
567
|
+
// This means that no additional auth is available
|
|
568
|
+
// At this point, just bail out as no additional visibility can be inferred.
|
|
569
|
+
if (!auth || !userId) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
const isSubscriptionSessionTokenMatched = acl.getReadAccess(userId);
|
|
573
|
+
if (isSubscriptionSessionTokenMatched) {
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
361
576
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
577
|
+
// Check if the user has any roles that match the ACL
|
|
578
|
+
return Promise.resolve().then(async () => {
|
|
579
|
+
// Resolve false right away if the acl doesn't have any roles
|
|
580
|
+
const acl_has_roles = Object.keys(acl.permissionsById).some(key => key.startsWith('role:'));
|
|
581
|
+
if (!acl_has_roles) {
|
|
582
|
+
return false;
|
|
583
|
+
}
|
|
584
|
+
const roleNames = await auth.getUserRoles();
|
|
585
|
+
// Finally, see if any of the user's roles allow them read access
|
|
586
|
+
for (const role of roleNames) {
|
|
587
|
+
// We use getReadAccess as `role` is in the form `role:roleName`
|
|
588
|
+
if (acl.getReadAccess(role)) {
|
|
589
|
+
return true;
|
|
369
590
|
}
|
|
370
|
-
|
|
371
|
-
this.sessionTokenCache.getUserId(subscriptionSessionToken).then(userId => {
|
|
372
|
-
|
|
373
|
-
// Pass along a null if there is no user id
|
|
374
|
-
if (!userId) {
|
|
375
|
-
return _node2.default.Promise.as(null);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Prepare a user object to query for roles
|
|
379
|
-
// To eliminate a query for the user, create one locally with the id
|
|
380
|
-
var user = new _node2.default.User();
|
|
381
|
-
user.id = userId;
|
|
382
|
-
return user;
|
|
383
|
-
}).then(user => {
|
|
384
|
-
|
|
385
|
-
// Pass along an empty array (of roles) if no user
|
|
386
|
-
if (!user) {
|
|
387
|
-
return _node2.default.Promise.as([]);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Then get the user's roles
|
|
391
|
-
var rolesQuery = new _node2.default.Query(_node2.default.Role);
|
|
392
|
-
rolesQuery.equalTo("users", user);
|
|
393
|
-
return rolesQuery.find({ useMasterKey: true });
|
|
394
|
-
}).then(roles => {
|
|
395
|
-
|
|
396
|
-
// Finally, see if any of the user's roles allow them read access
|
|
397
|
-
for (const role of roles) {
|
|
398
|
-
if (acl.getRoleReadAccess(role)) {
|
|
399
|
-
return resolve(true);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
resolve(false);
|
|
403
|
-
}).catch(error => {
|
|
404
|
-
reject(error);
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
}).then(isRoleMatched => {
|
|
408
|
-
|
|
409
|
-
if (isRoleMatched) {
|
|
410
|
-
return _node2.default.Promise.as(true);
|
|
411
591
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return this.sessionTokenCache.getUserId(clientSessionToken).then(userId => {
|
|
416
|
-
return acl.getReadAccess(userId);
|
|
417
|
-
});
|
|
418
|
-
}).then(isMatched => {
|
|
419
|
-
return _node2.default.Promise.as(isMatched);
|
|
420
|
-
}, () => {
|
|
421
|
-
return _node2.default.Promise.as(false);
|
|
592
|
+
return false;
|
|
593
|
+
}).catch(() => {
|
|
594
|
+
return false;
|
|
422
595
|
});
|
|
423
596
|
}
|
|
424
|
-
|
|
425
|
-
|
|
597
|
+
async getAuthFromClient(client, requestId, sessionToken) {
|
|
598
|
+
const getSessionFromClient = () => {
|
|
599
|
+
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
|
600
|
+
if (typeof subscriptionInfo === 'undefined') {
|
|
601
|
+
return client.sessionToken;
|
|
602
|
+
}
|
|
603
|
+
return subscriptionInfo.sessionToken || client.sessionToken;
|
|
604
|
+
};
|
|
605
|
+
if (!sessionToken) {
|
|
606
|
+
sessionToken = getSessionFromClient();
|
|
607
|
+
}
|
|
608
|
+
if (!sessionToken) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const {
|
|
612
|
+
auth
|
|
613
|
+
} = await this.getAuthForSessionToken(sessionToken);
|
|
614
|
+
return auth;
|
|
615
|
+
}
|
|
616
|
+
_checkWatchFields(client, requestId, message) {
|
|
617
|
+
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
|
618
|
+
const watch = subscriptionInfo?.watch;
|
|
619
|
+
if (!watch) {
|
|
620
|
+
return true;
|
|
621
|
+
}
|
|
622
|
+
const object = message.currentParseObject;
|
|
623
|
+
const original = message.originalParseObject;
|
|
624
|
+
return watch.some(field => !(0, _util.isDeepStrictEqual)(object.get(field), original?.get(field)));
|
|
625
|
+
}
|
|
626
|
+
async _matchesACL(acl, client, requestId) {
|
|
627
|
+
// Return true directly if ACL isn't present, ACL is public read, or client has master key
|
|
628
|
+
if (!acl || acl.getPublicReadAccess() || client.hasMasterKey) {
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
// Check subscription sessionToken matches ACL first
|
|
632
|
+
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
|
633
|
+
if (typeof subscriptionInfo === 'undefined') {
|
|
634
|
+
return false;
|
|
635
|
+
}
|
|
636
|
+
const subscriptionToken = subscriptionInfo.sessionToken;
|
|
637
|
+
const clientSessionToken = client.sessionToken;
|
|
638
|
+
if (await this._verifyACL(acl, subscriptionToken)) {
|
|
639
|
+
return true;
|
|
640
|
+
}
|
|
641
|
+
if (await this._verifyACL(acl, clientSessionToken)) {
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
async _handleConnect(parseWebsocket, request) {
|
|
426
647
|
if (!this._validateKeys(request, this.keyPairs)) {
|
|
427
648
|
_Client.Client.pushError(parseWebsocket, 4, 'Key in request is not valid');
|
|
428
|
-
|
|
649
|
+
_logger.default.error('Key in request is not valid');
|
|
429
650
|
return;
|
|
430
651
|
}
|
|
431
652
|
const hasMasterKey = this._hasMasterKey(request, this.keyPairs);
|
|
432
|
-
const clientId = (0,
|
|
433
|
-
const client = new _Client.Client(clientId, parseWebsocket, hasMasterKey);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
653
|
+
const clientId = (0, _uuid.v4)();
|
|
654
|
+
const client = new _Client.Client(clientId, parseWebsocket, hasMasterKey, request.sessionToken, request.installationId);
|
|
655
|
+
try {
|
|
656
|
+
const req = {
|
|
657
|
+
client,
|
|
658
|
+
event: 'connect',
|
|
659
|
+
clients: this.clients.size,
|
|
660
|
+
subscriptions: this.subscriptions.size,
|
|
661
|
+
sessionToken: request.sessionToken,
|
|
662
|
+
useMasterKey: client.hasMasterKey,
|
|
663
|
+
installationId: request.installationId,
|
|
664
|
+
user: undefined
|
|
665
|
+
};
|
|
666
|
+
const trigger = (0, _triggers.getTrigger)('@Connect', 'beforeConnect', _node.default.applicationId);
|
|
667
|
+
if (trigger) {
|
|
668
|
+
const auth = await this.getAuthFromClient(client, request.requestId, req.sessionToken);
|
|
669
|
+
if (auth && auth.user) {
|
|
670
|
+
req.user = auth.user;
|
|
671
|
+
}
|
|
672
|
+
await (0, _triggers.runTrigger)(trigger, `beforeConnect.@Connect`, req, auth);
|
|
673
|
+
}
|
|
674
|
+
parseWebsocket.clientId = clientId;
|
|
675
|
+
this.clients.set(parseWebsocket.clientId, client);
|
|
676
|
+
_logger.default.info(`Create new client: ${parseWebsocket.clientId}`);
|
|
677
|
+
client.pushConnect();
|
|
678
|
+
(0, _triggers.runLiveQueryEventHandlers)(req);
|
|
679
|
+
} catch (e) {
|
|
680
|
+
const error = (0, _triggers.resolveError)(e);
|
|
681
|
+
_Client.Client.pushError(parseWebsocket, error.code, error.message, false);
|
|
682
|
+
_logger.default.error(`Failed running beforeConnect for session ${request.sessionToken} with:\n Error: ` + JSON.stringify(error));
|
|
683
|
+
}
|
|
443
684
|
}
|
|
444
|
-
|
|
445
685
|
_hasMasterKey(request, validKeyPairs) {
|
|
446
|
-
if (!validKeyPairs || validKeyPairs.size == 0 || !validKeyPairs.has(
|
|
686
|
+
if (!validKeyPairs || validKeyPairs.size == 0 || !validKeyPairs.has('masterKey')) {
|
|
447
687
|
return false;
|
|
448
688
|
}
|
|
449
|
-
if (!request || !
|
|
689
|
+
if (!request || !Object.prototype.hasOwnProperty.call(request, 'masterKey')) {
|
|
450
690
|
return false;
|
|
451
691
|
}
|
|
452
|
-
return request.masterKey === validKeyPairs.get(
|
|
692
|
+
return request.masterKey === validKeyPairs.get('masterKey');
|
|
453
693
|
}
|
|
454
|
-
|
|
455
694
|
_validateKeys(request, validKeyPairs) {
|
|
456
695
|
if (!validKeyPairs || validKeyPairs.size == 0) {
|
|
457
696
|
return true;
|
|
@@ -466,83 +705,119 @@ class ParseLiveQueryServer {
|
|
|
466
705
|
}
|
|
467
706
|
return isValid;
|
|
468
707
|
}
|
|
469
|
-
|
|
470
|
-
_handleSubscribe(parseWebsocket, request) {
|
|
708
|
+
async _handleSubscribe(parseWebsocket, request) {
|
|
471
709
|
// If we can not find this client, return error to client
|
|
472
|
-
if (!
|
|
710
|
+
if (!Object.prototype.hasOwnProperty.call(parseWebsocket, 'clientId')) {
|
|
473
711
|
_Client.Client.pushError(parseWebsocket, 2, 'Can not find this client, make sure you connect to server before subscribing');
|
|
474
|
-
|
|
712
|
+
_logger.default.error('Can not find this client, make sure you connect to server before subscribing');
|
|
475
713
|
return;
|
|
476
714
|
}
|
|
477
715
|
const client = this.clients.get(parseWebsocket.clientId);
|
|
478
|
-
|
|
479
|
-
// Get subscription from subscriptions, create one if necessary
|
|
480
|
-
const subscriptionHash = (0, _QueryTools.queryHash)(request.query);
|
|
481
|
-
// Add className to subscriptions if necessary
|
|
482
716
|
const className = request.query.className;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
717
|
+
let authCalled = false;
|
|
718
|
+
try {
|
|
719
|
+
const trigger = (0, _triggers.getTrigger)(className, 'beforeSubscribe', _node.default.applicationId);
|
|
720
|
+
if (trigger) {
|
|
721
|
+
const auth = await this.getAuthFromClient(client, request.requestId, request.sessionToken);
|
|
722
|
+
authCalled = true;
|
|
723
|
+
if (auth && auth.user) {
|
|
724
|
+
request.user = auth.user;
|
|
725
|
+
}
|
|
726
|
+
const parseQuery = new _node.default.Query(className);
|
|
727
|
+
parseQuery.withJSON(request.query);
|
|
728
|
+
request.query = parseQuery;
|
|
729
|
+
await (0, _triggers.runTrigger)(trigger, `beforeSubscribe.${className}`, request, auth);
|
|
730
|
+
const query = request.query.toJSON();
|
|
731
|
+
request.query = query;
|
|
732
|
+
}
|
|
733
|
+
if (className === '_Session') {
|
|
734
|
+
if (!authCalled) {
|
|
735
|
+
const auth = await this.getAuthFromClient(client, request.requestId, request.sessionToken);
|
|
736
|
+
if (auth && auth.user) {
|
|
737
|
+
request.user = auth.user;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
if (request.user) {
|
|
741
|
+
request.query.where.user = request.user.toPointer();
|
|
742
|
+
} else if (!request.master) {
|
|
743
|
+
_Client.Client.pushError(parseWebsocket, _node.default.Error.INVALID_SESSION_TOKEN, 'Invalid session token', false, request.requestId);
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
// Get subscription from subscriptions, create one if necessary
|
|
748
|
+
const subscriptionHash = (0, _QueryTools.queryHash)(request.query);
|
|
749
|
+
// Add className to subscriptions if necessary
|
|
507
750
|
|
|
508
|
-
|
|
509
|
-
|
|
751
|
+
if (!this.subscriptions.has(className)) {
|
|
752
|
+
this.subscriptions.set(className, new Map());
|
|
753
|
+
}
|
|
754
|
+
const classSubscriptions = this.subscriptions.get(className);
|
|
755
|
+
let subscription;
|
|
756
|
+
if (classSubscriptions.has(subscriptionHash)) {
|
|
757
|
+
subscription = classSubscriptions.get(subscriptionHash);
|
|
758
|
+
} else {
|
|
759
|
+
subscription = new _Subscription.Subscription(className, request.query.where, subscriptionHash);
|
|
760
|
+
classSubscriptions.set(subscriptionHash, subscription);
|
|
761
|
+
}
|
|
510
762
|
|
|
511
|
-
|
|
763
|
+
// Add subscriptionInfo to client
|
|
764
|
+
const subscriptionInfo = {
|
|
765
|
+
subscription: subscription
|
|
766
|
+
};
|
|
767
|
+
// Add selected fields, sessionToken and installationId for this subscription if necessary
|
|
768
|
+
if (request.query.keys) {
|
|
769
|
+
subscriptionInfo.keys = Array.isArray(request.query.keys) ? request.query.keys : request.query.keys.split(',');
|
|
770
|
+
}
|
|
771
|
+
if (request.query.watch) {
|
|
772
|
+
subscriptionInfo.watch = request.query.watch;
|
|
773
|
+
}
|
|
774
|
+
if (request.sessionToken) {
|
|
775
|
+
subscriptionInfo.sessionToken = request.sessionToken;
|
|
776
|
+
}
|
|
777
|
+
client.addSubscriptionInfo(request.requestId, subscriptionInfo);
|
|
512
778
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
779
|
+
// Add clientId to subscription
|
|
780
|
+
subscription.addClientSubscription(parseWebsocket.clientId, request.requestId);
|
|
781
|
+
client.pushSubscribe(request.requestId);
|
|
782
|
+
_logger.default.verbose(`Create client ${parseWebsocket.clientId} new subscription: ${request.requestId}`);
|
|
783
|
+
_logger.default.verbose('Current client number: %d', this.clients.size);
|
|
784
|
+
(0, _triggers.runLiveQueryEventHandlers)({
|
|
785
|
+
client,
|
|
786
|
+
event: 'subscribe',
|
|
787
|
+
clients: this.clients.size,
|
|
788
|
+
subscriptions: this.subscriptions.size,
|
|
789
|
+
sessionToken: request.sessionToken,
|
|
790
|
+
useMasterKey: client.hasMasterKey,
|
|
791
|
+
installationId: client.installationId
|
|
792
|
+
});
|
|
793
|
+
} catch (e) {
|
|
794
|
+
const error = (0, _triggers.resolveError)(e);
|
|
795
|
+
_Client.Client.pushError(parseWebsocket, error.code, error.message, false, request.requestId);
|
|
796
|
+
_logger.default.error(`Failed running beforeSubscribe on ${className} for session ${request.sessionToken} with:\n Error: ` + JSON.stringify(error));
|
|
797
|
+
}
|
|
520
798
|
}
|
|
521
|
-
|
|
522
799
|
_handleUpdateSubscription(parseWebsocket, request) {
|
|
523
800
|
this._handleUnsubscribe(parseWebsocket, request, false);
|
|
524
801
|
this._handleSubscribe(parseWebsocket, request);
|
|
525
802
|
}
|
|
526
|
-
|
|
527
803
|
_handleUnsubscribe(parseWebsocket, request, notifyClient = true) {
|
|
528
804
|
// If we can not find this client, return error to client
|
|
529
|
-
if (!
|
|
805
|
+
if (!Object.prototype.hasOwnProperty.call(parseWebsocket, 'clientId')) {
|
|
530
806
|
_Client.Client.pushError(parseWebsocket, 2, 'Can not find this client, make sure you connect to server before unsubscribing');
|
|
531
|
-
|
|
807
|
+
_logger.default.error('Can not find this client, make sure you connect to server before unsubscribing');
|
|
532
808
|
return;
|
|
533
809
|
}
|
|
534
810
|
const requestId = request.requestId;
|
|
535
811
|
const client = this.clients.get(parseWebsocket.clientId);
|
|
536
812
|
if (typeof client === 'undefined') {
|
|
537
813
|
_Client.Client.pushError(parseWebsocket, 2, 'Cannot find client with clientId ' + parseWebsocket.clientId + '. Make sure you connect to live query server before unsubscribing.');
|
|
538
|
-
|
|
814
|
+
_logger.default.error('Can not find this client ' + parseWebsocket.clientId);
|
|
539
815
|
return;
|
|
540
816
|
}
|
|
541
|
-
|
|
542
817
|
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
|
543
818
|
if (typeof subscriptionInfo === 'undefined') {
|
|
544
819
|
_Client.Client.pushError(parseWebsocket, 2, 'Cannot find subscription with clientId ' + parseWebsocket.clientId + ' subscriptionId ' + requestId + '. Make sure you subscribe to live query server before unsubscribing.');
|
|
545
|
-
|
|
820
|
+
_logger.default.error('Can not find subscription with clientId ' + parseWebsocket.clientId + ' subscriptionId ' + requestId);
|
|
546
821
|
return;
|
|
547
822
|
}
|
|
548
823
|
|
|
@@ -562,20 +837,20 @@ class ParseLiveQueryServer {
|
|
|
562
837
|
this.subscriptions.delete(className);
|
|
563
838
|
}
|
|
564
839
|
(0, _triggers.runLiveQueryEventHandlers)({
|
|
840
|
+
client,
|
|
565
841
|
event: 'unsubscribe',
|
|
566
842
|
clients: this.clients.size,
|
|
567
|
-
subscriptions: this.subscriptions.size
|
|
843
|
+
subscriptions: this.subscriptions.size,
|
|
844
|
+
sessionToken: subscriptionInfo.sessionToken,
|
|
845
|
+
useMasterKey: client.hasMasterKey,
|
|
846
|
+
installationId: client.installationId
|
|
568
847
|
});
|
|
569
|
-
|
|
570
848
|
if (!notifyClient) {
|
|
571
849
|
return;
|
|
572
850
|
}
|
|
573
|
-
|
|
574
851
|
client.pushUnsubscribe(request.requestId);
|
|
575
|
-
|
|
576
|
-
_logger2.default.verbose(`Delete client: ${parseWebsocket.clientId} | subscription: ${request.requestId}`);
|
|
852
|
+
_logger.default.verbose(`Delete client: ${parseWebsocket.clientId} | subscription: ${request.requestId}`);
|
|
577
853
|
}
|
|
578
854
|
}
|
|
579
|
-
|
|
580
855
|
exports.ParseLiveQueryServer = ParseLiveQueryServer;
|
|
581
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MaXZlUXVlcnkvUGFyc2VMaXZlUXVlcnlTZXJ2ZXIuanMiXSwibmFtZXMiOlsiUGFyc2VMaXZlUXVlcnlTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsInNlcnZlciIsImNvbmZpZyIsImNsaWVudHMiLCJNYXAiLCJzdWJzY3JpcHRpb25zIiwia2V5UGFpcnMiLCJrZXkiLCJPYmplY3QiLCJrZXlzIiwic2V0IiwibG9nZ2VyIiwidmVyYm9zZSIsIlBhcnNlIiwiZGlzYWJsZVNpbmdsZUluc3RhbmNlIiwic2VydmVyVVJMIiwiYXBwSWQiLCJhcHBsaWNhdGlvbklkIiwiamF2YXNjcmlwdEtleSIsImphdmFTY3JpcHRLZXkiLCJtYXN0ZXJLZXkiLCJpbml0aWFsaXplIiwicGFyc2VXZWJTb2NrZXRTZXJ2ZXIiLCJQYXJzZVdlYlNvY2tldFNlcnZlciIsInBhcnNlV2Vic29ja2V0IiwiX29uQ29ubmVjdCIsIndlYnNvY2tldFRpbWVvdXQiLCJzdWJzY3JpYmVyIiwiUGFyc2VQdWJTdWIiLCJjcmVhdGVTdWJzY3JpYmVyIiwic3Vic2NyaWJlIiwib24iLCJjaGFubmVsIiwibWVzc2FnZVN0ciIsIm1lc3NhZ2UiLCJKU09OIiwicGFyc2UiLCJlIiwiZXJyb3IiLCJfaW5mbGF0ZVBhcnNlT2JqZWN0IiwiX29uQWZ0ZXJTYXZlIiwiX29uQWZ0ZXJEZWxldGUiLCJzZXNzaW9uVG9rZW5DYWNoZSIsIlNlc3Npb25Ub2tlbkNhY2hlIiwiY2FjaGVUaW1lb3V0IiwiY3VycmVudFBhcnNlT2JqZWN0IiwiY2xhc3NOYW1lIiwicGFyc2VPYmplY3QiLCJfZmluaXNoRmV0Y2giLCJvcmlnaW5hbFBhcnNlT2JqZWN0IiwiZGVsZXRlZFBhcnNlT2JqZWN0IiwidG9KU09OIiwiaWQiLCJzaXplIiwiY2xhc3NTdWJzY3JpcHRpb25zIiwiZ2V0IiwiZGVidWciLCJzdWJzY3JpcHRpb24iLCJ2YWx1ZXMiLCJpc1N1YnNjcmlwdGlvbk1hdGNoZWQiLCJfbWF0Y2hlc1N1YnNjcmlwdGlvbiIsImNsaWVudElkIiwicmVxdWVzdElkcyIsIl8iLCJlbnRyaWVzIiwiY2xpZW50UmVxdWVzdElkcyIsImNsaWVudCIsInJlcXVlc3RJZCIsImFjbCIsImdldEFDTCIsIl9tYXRjaGVzQUNMIiwidGhlbiIsImlzTWF0Y2hlZCIsInB1c2hEZWxldGUiLCJpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCIsImlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQiLCJvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSIsIlByb21pc2UiLCJhcyIsIm9yaWdpbmFsQUNMIiwiY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSIsImN1cnJlbnRBQ0wiLCJ3aGVuIiwiaXNPcmlnaW5hbE1hdGNoZWQiLCJpc0N1cnJlbnRNYXRjaGVkIiwiaGFzaCIsInR5cGUiLCJmdW5jdGlvbk5hbWUiLCJyZXF1ZXN0IiwidHY0IiwidmFsaWRhdGUiLCJSZXF1ZXN0U2NoZW1hIiwib3AiLCJDbGllbnQiLCJwdXNoRXJyb3IiLCJfaGFuZGxlQ29ubmVjdCIsIl9oYW5kbGVTdWJzY3JpYmUiLCJfaGFuZGxlVXBkYXRlU3Vic2NyaXB0aW9uIiwiX2hhbmRsZVVuc3Vic2NyaWJlIiwiaW5mbyIsImhhcyIsImV2ZW50IiwiZGVsZXRlIiwic3Vic2NyaXB0aW9uSW5mbyIsInN1YnNjcmlwdGlvbkluZm9zIiwiZGVsZXRlQ2xpZW50U3Vic2NyaXB0aW9uIiwiaGFzU3Vic2NyaWJpbmdDbGllbnQiLCJxdWVyeSIsImdldFB1YmxpY1JlYWRBY2Nlc3MiLCJoYXNNYXN0ZXJLZXkiLCJnZXRTdWJzY3JpcHRpb25JbmZvIiwic3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuIiwic2Vzc2lvblRva2VuIiwiZ2V0VXNlcklkIiwidXNlcklkIiwiZ2V0UmVhZEFjY2VzcyIsImlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCIsInJlc29sdmUiLCJyZWplY3QiLCJhY2xfaGFzX3JvbGVzIiwicGVybWlzc2lvbnNCeUlkIiwic29tZSIsInN0YXJ0c1dpdGgiLCJ1c2VyIiwiVXNlciIsInJvbGVzUXVlcnkiLCJRdWVyeSIsIlJvbGUiLCJlcXVhbFRvIiwiZmluZCIsInVzZU1hc3RlcktleSIsInJvbGVzIiwicm9sZSIsImdldFJvbGVSZWFkQWNjZXNzIiwiY2F0Y2giLCJpc1JvbGVNYXRjaGVkIiwiY2xpZW50U2Vzc2lvblRva2VuIiwiX3ZhbGlkYXRlS2V5cyIsIl9oYXNNYXN0ZXJLZXkiLCJwdXNoQ29ubmVjdCIsInZhbGlkS2V5UGFpcnMiLCJoYXNPd25Qcm9wZXJ0eSIsImlzVmFsaWQiLCJzZWNyZXQiLCJzdWJzY3JpcHRpb25IYXNoIiwiU3Vic2NyaXB0aW9uIiwid2hlcmUiLCJmaWVsZHMiLCJhZGRTdWJzY3JpcHRpb25JbmZvIiwiYWRkQ2xpZW50U3Vic2NyaXB0aW9uIiwicHVzaFN1YnNjcmliZSIsIm5vdGlmeUNsaWVudCIsImRlbGV0ZVN1YnNjcmlwdGlvbkluZm8iLCJwdXNoVW5zdWJzY3JpYmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUVBLE1BQU1BLG9CQUFOLENBQTJCO0FBRXpCO0FBT0FDLGNBQVlDLE1BQVosRUFBeUJDLE1BQXpCLEVBQXNDO0FBQ3BDLFNBQUtELE1BQUwsR0FBY0EsTUFBZDtBQUNBLFNBQUtFLE9BQUwsR0FBZSxJQUFJQyxHQUFKLEVBQWY7QUFDQSxTQUFLQyxhQUFMLEdBQXFCLElBQUlELEdBQUosRUFBckI7O0FBRUFGLGFBQVNBLFVBQVUsRUFBbkI7O0FBRUE7QUFDQSxVQUFNSSxXQUFXSixPQUFPSSxRQUFQLElBQW1CLEVBQXBDO0FBQ0EsU0FBS0EsUUFBTCxHQUFnQixJQUFJRixHQUFKLEVBQWhCO0FBQ0EsU0FBSyxNQUFNRyxHQUFYLElBQWtCQyxPQUFPQyxJQUFQLENBQVlILFFBQVosQ0FBbEIsRUFBeUM7QUFDdkMsV0FBS0EsUUFBTCxDQUFjSSxHQUFkLENBQWtCSCxHQUFsQixFQUF1QkQsU0FBU0MsR0FBVCxDQUF2QjtBQUNEO0FBQ0RJLHFCQUFPQyxPQUFQLENBQWUsbUJBQWYsRUFBb0MsS0FBS04sUUFBekM7O0FBRUE7QUFDQU8sbUJBQU1MLE1BQU4sQ0FBYU0scUJBQWI7O0FBRUEsVUFBTUMsWUFBWWIsT0FBT2EsU0FBUCxJQUFvQkYsZUFBTUUsU0FBNUM7QUFDQUYsbUJBQU1FLFNBQU4sR0FBa0JBLFNBQWxCO0FBQ0EsVUFBTUMsUUFBUWQsT0FBT2MsS0FBUCxJQUFnQkgsZUFBTUksYUFBcEM7QUFDQSxVQUFNQyxnQkFBZ0JMLGVBQU1NLGFBQTVCO0FBQ0EsVUFBTUMsWUFBWWxCLE9BQU9rQixTQUFQLElBQW9CUCxlQUFNTyxTQUE1QztBQUNBUCxtQkFBTVEsVUFBTixDQUFpQkwsS0FBakIsRUFBd0JFLGFBQXhCLEVBQXVDRSxTQUF2Qzs7QUFFQTtBQUNBLFNBQUtFLG9CQUFMLEdBQTRCLElBQUlDLDBDQUFKLENBQzFCdEIsTUFEMEIsRUFFekJ1QixjQUFELElBQW9CLEtBQUtDLFVBQUwsQ0FBZ0JELGNBQWhCLENBRk0sRUFHMUJ0QixPQUFPd0IsZ0JBSG1CLENBQTVCOztBQU1BO0FBQ0EsU0FBS0MsVUFBTCxHQUFrQkMseUJBQVlDLGdCQUFaLENBQTZCM0IsTUFBN0IsQ0FBbEI7QUFDQSxTQUFLeUIsVUFBTCxDQUFnQkcsU0FBaEIsQ0FBMEJqQixlQUFNSSxhQUFOLEdBQXNCLFdBQWhEO0FBQ0EsU0FBS1UsVUFBTCxDQUFnQkcsU0FBaEIsQ0FBMEJqQixlQUFNSSxhQUFOLEdBQXNCLGFBQWhEO0FBQ0E7QUFDQTtBQUNBLFNBQUtVLFVBQUwsQ0FBZ0JJLEVBQWhCLENBQW1CLFNBQW5CLEVBQThCLENBQUNDLE9BQUQsRUFBVUMsVUFBVixLQUF5QjtBQUNyRHRCLHVCQUFPQyxPQUFQLENBQWUsdUJBQWYsRUFBd0NxQixVQUF4QztBQUNBLFVBQUlDLE9BQUo7QUFDQSxVQUFJO0FBQ0ZBLGtCQUFVQyxLQUFLQyxLQUFMLENBQVdILFVBQVgsQ0FBVjtBQUNELE9BRkQsQ0FFRSxPQUFNSSxDQUFOLEVBQVM7QUFDVDFCLHlCQUFPMkIsS0FBUCxDQUFhLHlCQUFiLEVBQXdDTCxVQUF4QyxFQUFvREksQ0FBcEQ7QUFDQTtBQUNEO0FBQ0QsV0FBS0UsbUJBQUwsQ0FBeUJMLE9BQXpCO0FBQ0EsVUFBSUYsWUFBWW5CLGVBQU1JLGFBQU4sR0FBc0IsV0FBdEMsRUFBbUQ7QUFDakQsYUFBS3VCLFlBQUwsQ0FBa0JOLE9BQWxCO0FBQ0QsT0FGRCxNQUVPLElBQUlGLFlBQVluQixlQUFNSSxhQUFOLEdBQXNCLGFBQXRDLEVBQXFEO0FBQzFELGFBQUt3QixjQUFMLENBQW9CUCxPQUFwQjtBQUNELE9BRk0sTUFFQTtBQUNMdkIseUJBQU8yQixLQUFQLENBQWEsd0NBQWIsRUFBdURKLE9BQXZELEVBQWdFRixPQUFoRTtBQUNEO0FBQ0YsS0FqQkQ7O0FBbUJBO0FBQ0EsU0FBS1UsaUJBQUwsR0FBeUIsSUFBSUMsb0NBQUosQ0FBc0J6QyxPQUFPMEMsWUFBN0IsQ0FBekI7QUFDRDs7QUFFRDtBQUNBOztBQWpFQTtBQWtFQUwsc0JBQW9CTCxPQUFwQixFQUF3QztBQUN0QztBQUNBLFVBQU1XLHFCQUFxQlgsUUFBUVcsa0JBQW5DO0FBQ0EsUUFBSUMsWUFBWUQsbUJBQW1CQyxTQUFuQztBQUNBLFFBQUlDLGNBQWMsSUFBSWxDLGVBQU1MLE1BQVYsQ0FBaUJzQyxTQUFqQixDQUFsQjtBQUNBQyxnQkFBWUMsWUFBWixDQUF5Qkgsa0JBQXpCO0FBQ0FYLFlBQVFXLGtCQUFSLEdBQTZCRSxXQUE3QjtBQUNBO0FBQ0EsVUFBTUUsc0JBQXNCZixRQUFRZSxtQkFBcEM7QUFDQSxRQUFJQSxtQkFBSixFQUF5QjtBQUN2Qkgsa0JBQVlHLG9CQUFvQkgsU0FBaEM7QUFDQUMsb0JBQWMsSUFBSWxDLGVBQU1MLE1BQVYsQ0FBaUJzQyxTQUFqQixDQUFkO0FBQ0FDLGtCQUFZQyxZQUFaLENBQXlCQyxtQkFBekI7QUFDQWYsY0FBUWUsbUJBQVIsR0FBOEJGLFdBQTlCO0FBQ0Q7QUFDRjs7QUFFRDtBQUNBO0FBQ0FOLGlCQUFlUCxPQUFmLEVBQW1DO0FBQ2pDdkIscUJBQU9DLE9BQVAsQ0FBZUMsZUFBTUksYUFBTixHQUFzQiwwQkFBckM7O0FBRUEsVUFBTWlDLHFCQUFxQmhCLFFBQVFXLGtCQUFSLENBQTJCTSxNQUEzQixFQUEzQjtBQUNBLFVBQU1MLFlBQVlJLG1CQUFtQkosU0FBckM7QUFDQW5DLHFCQUFPQyxPQUFQLENBQWUsOEJBQWYsRUFBK0NrQyxTQUEvQyxFQUEwREksbUJBQW1CRSxFQUE3RTtBQUNBekMscUJBQU9DLE9BQVAsQ0FBZSw0QkFBZixFQUE2QyxLQUFLVCxPQUFMLENBQWFrRCxJQUExRDs7QUFFQSxVQUFNQyxxQkFBcUIsS0FBS2pELGFBQUwsQ0FBbUJrRCxHQUFuQixDQUF1QlQsU0FBdkIsQ0FBM0I7QUFDQSxRQUFJLE9BQU9RLGtCQUFQLEtBQThCLFdBQWxDLEVBQStDO0FBQzdDM0MsdUJBQU82QyxLQUFQLENBQWEsaURBQWlEVixTQUE5RDtBQUNBO0FBQ0Q7QUFDRCxTQUFLLE1BQU1XLFlBQVgsSUFBMkJILG1CQUFtQkksTUFBbkIsRUFBM0IsRUFBd0Q7QUFDdEQsWUFBTUMsd0JBQXdCLEtBQUtDLG9CQUFMLENBQTBCVixrQkFBMUIsRUFBOENPLFlBQTlDLENBQTlCO0FBQ0EsVUFBSSxDQUFDRSxxQkFBTCxFQUE0QjtBQUMxQjtBQUNEO0FBQ0QsV0FBSyxNQUFNLENBQUNFLFFBQUQsRUFBV0MsVUFBWCxDQUFYLElBQXFDQyxpQkFBRUMsT0FBRixDQUFVUCxhQUFhUSxnQkFBdkIsQ0FBckMsRUFBK0U7QUFDN0UsY0FBTUMsU0FBUyxLQUFLL0QsT0FBTCxDQUFhb0QsR0FBYixDQUFpQk0sUUFBakIsQ0FBZjtBQUNBLFlBQUksT0FBT0ssTUFBUCxLQUFrQixXQUF0QixFQUFtQztBQUNqQztBQUNEO0FBQ0QsYUFBSyxNQUFNQyxTQUFYLElBQXdCTCxVQUF4QixFQUFvQztBQUNsQyxnQkFBTU0sTUFBTWxDLFFBQVFXLGtCQUFSLENBQTJCd0IsTUFBM0IsRUFBWjtBQUNBO0FBQ0EsZUFBS0MsV0FBTCxDQUFpQkYsR0FBakIsRUFBc0JGLE1BQXRCLEVBQThCQyxTQUE5QixFQUF5Q0ksSUFBekMsQ0FBK0NDLFNBQUQsSUFBZTtBQUMzRCxnQkFBSSxDQUFDQSxTQUFMLEVBQWdCO0FBQ2QscUJBQU8sSUFBUDtBQUNEO0FBQ0ROLG1CQUFPTyxVQUFQLENBQWtCTixTQUFsQixFQUE2QmpCLGtCQUE3QjtBQUNELFdBTEQsRUFLSVosS0FBRCxJQUFXO0FBQ1ozQiw2QkFBTzJCLEtBQVAsQ0FBYSx1QkFBYixFQUFzQ0EsS0FBdEM7QUFDRCxXQVBEO0FBUUQ7QUFDRjtBQUNGO0FBQ0Y7O0FBRUQ7QUFDQTtBQUNBRSxlQUFhTixPQUFiLEVBQWlDO0FBQy9CdkIscUJBQU9DLE9BQVAsQ0FBZUMsZUFBTUksYUFBTixHQUFzQix3QkFBckM7O0FBRUEsUUFBSWdDLHNCQUFzQixJQUExQjtBQUNBLFFBQUlmLFFBQVFlLG1CQUFaLEVBQWlDO0FBQy9CQSw0QkFBc0JmLFFBQVFlLG1CQUFSLENBQTRCRSxNQUE1QixFQUF0QjtBQUNEO0FBQ0QsVUFBTU4scUJBQXFCWCxRQUFRVyxrQkFBUixDQUEyQk0sTUFBM0IsRUFBM0I7QUFDQSxVQUFNTCxZQUFZRCxtQkFBbUJDLFNBQXJDO0FBQ0FuQyxxQkFBT0MsT0FBUCxDQUFlLDhCQUFmLEVBQStDa0MsU0FBL0MsRUFBMERELG1CQUFtQk8sRUFBN0U7QUFDQXpDLHFCQUFPQyxPQUFQLENBQWUsNEJBQWYsRUFBNkMsS0FBS1QsT0FBTCxDQUFha0QsSUFBMUQ7O0FBRUEsVUFBTUMscUJBQXFCLEtBQUtqRCxhQUFMLENBQW1Ca0QsR0FBbkIsQ0FBdUJULFNBQXZCLENBQTNCO0FBQ0EsUUFBSSxPQUFPUSxrQkFBUCxLQUE4QixXQUFsQyxFQUErQztBQUM3QzNDLHVCQUFPNkMsS0FBUCxDQUFhLGlEQUFpRFYsU0FBOUQ7QUFDQTtBQUNEO0FBQ0QsU0FBSyxNQUFNVyxZQUFYLElBQTJCSCxtQkFBbUJJLE1BQW5CLEVBQTNCLEVBQXdEO0FBQ3RELFlBQU1nQixnQ0FBZ0MsS0FBS2Qsb0JBQUwsQ0FBMEJYLG1CQUExQixFQUErQ1EsWUFBL0MsQ0FBdEM7QUFDQSxZQUFNa0IsK0JBQStCLEtBQUtmLG9CQUFMLENBQTBCZixrQkFBMUIsRUFBOENZLFlBQTlDLENBQXJDO0FBQ0EsV0FBSyxNQUFNLENBQUNJLFFBQUQsRUFBV0MsVUFBWCxDQUFYLElBQXFDQyxpQkFBRUMsT0FBRixDQUFVUCxhQUFhUSxnQkFBdkIsQ0FBckMsRUFBK0U7QUFDN0UsY0FBTUMsU0FBUyxLQUFLL0QsT0FBTCxDQUFhb0QsR0FBYixDQUFpQk0sUUFBakIsQ0FBZjtBQUNBLFlBQUksT0FBT0ssTUFBUCxLQUFrQixXQUF0QixFQUFtQztBQUNqQztBQUNEO0FBQ0QsYUFBSyxNQUFNQyxTQUFYLElBQXdCTCxVQUF4QixFQUFvQztBQUNsQztBQUNBO0FBQ0EsY0FBSWMsMEJBQUo7QUFDQSxjQUFJLENBQUNGLDZCQUFMLEVBQW9DO0FBQ2xDRSx5Q0FBNkIvRCxlQUFNZ0UsT0FBTixDQUFjQyxFQUFkLENBQWlCLEtBQWpCLENBQTdCO0FBQ0QsV0FGRCxNQUVPO0FBQ0wsZ0JBQUlDLFdBQUo7QUFDQSxnQkFBSTdDLFFBQVFlLG1CQUFaLEVBQWlDO0FBQy9COEIsNEJBQWM3QyxRQUFRZSxtQkFBUixDQUE0Qm9CLE1BQTVCLEVBQWQ7QUFDRDtBQUNETyx5Q0FBNkIsS0FBS04sV0FBTCxDQUFpQlMsV0FBakIsRUFBOEJiLE1BQTlCLEVBQXNDQyxTQUF0QyxDQUE3QjtBQUNEO0FBQ0Q7QUFDQTtBQUNBLGNBQUlhLHlCQUFKO0FBQ0EsY0FBSSxDQUFDTCw0QkFBTCxFQUFtQztBQUNqQ0ssd0NBQTRCbkUsZUFBTWdFLE9BQU4sQ0FBY0MsRUFBZCxDQUFpQixLQUFqQixDQUE1QjtBQUNELFdBRkQsTUFFTztBQUNMLGtCQUFNRyxhQUFhL0MsUUFBUVcsa0JBQVIsQ0FBMkJ3QixNQUEzQixFQUFuQjtBQUNBVyx3Q0FBNEIsS0FBS1YsV0FBTCxDQUFpQlcsVUFBakIsRUFBNkJmLE1BQTdCLEVBQXFDQyxTQUFyQyxDQUE1QjtBQUNEOztBQUVEdEQseUJBQU1nRSxPQUFOLENBQWNLLElBQWQsQ0FDRU4sMEJBREYsRUFFRUkseUJBRkYsRUFHRVQsSUFIRixDQUdPLENBQUNZLGlCQUFELEVBQW9CQyxnQkFBcEIsS0FBeUM7QUFDOUN6RSw2QkFBT0MsT0FBUCxDQUFlLDhEQUFmLEVBQ0VxQyxtQkFERixFQUVFSixrQkFGRixFQUdFNkIsNkJBSEYsRUFJRUMsNEJBSkYsRUFLRVEsaUJBTEYsRUFNRUMsZ0JBTkYsRUFPRTNCLGFBQWE0QixJQVBmOztBQVVBO0FBQ0EsZ0JBQUlDLElBQUo7QUFDQSxnQkFBSUgscUJBQXFCQyxnQkFBekIsRUFBMkM7QUFDekNFLHFCQUFPLFFBQVA7QUFDRCxhQUZELE1BRU8sSUFBSUgscUJBQXFCLENBQUNDLGdCQUExQixFQUE0QztBQUNqREUscUJBQU8sT0FBUDtBQUNELGFBRk0sTUFFQSxJQUFJLENBQUNILGlCQUFELElBQXNCQyxnQkFBMUIsRUFBNEM7QUFDakQsa0JBQUluQyxtQkFBSixFQUF5QjtBQUN2QnFDLHVCQUFPLE9BQVA7QUFDRCxlQUZELE1BRU87QUFDTEEsdUJBQU8sUUFBUDtBQUNEO0FBQ0YsYUFOTSxNQU1BO0FBQ0wscUJBQU8sSUFBUDtBQUNEO0FBQ0Qsa0JBQU1DLGVBQWUsU0FBU0QsSUFBOUI7QUFDQXBCLG1CQUFPcUIsWUFBUCxFQUFxQnBCLFNBQXJCLEVBQWdDdEIsa0JBQWhDO0FBQ0QsV0EvQkQsRUErQklQLEtBQUQsSUFBVztBQUNaM0IsNkJBQU8yQixLQUFQLENBQWEsdUJBQWIsRUFBc0NBLEtBQXRDO0FBQ0QsV0FqQ0Q7QUFrQ0Q7QUFDRjtBQUNGO0FBQ0Y7O0FBRURiLGFBQVdELGNBQVgsRUFBc0M7QUFDcENBLG1CQUFlTyxFQUFmLENBQWtCLFNBQWxCLEVBQThCeUQsT0FBRCxJQUFhO0FBQ3hDLFVBQUksT0FBT0EsT0FBUCxLQUFtQixRQUF2QixFQUFpQztBQUMvQixZQUFJO0FBQ0ZBLG9CQUFVckQsS0FBS0MsS0FBTCxDQUFXb0QsT0FBWCxDQUFWO0FBQ0QsU0FGRCxDQUVFLE9BQU1uRCxDQUFOLEVBQVM7QUFDVDFCLDJCQUFPMkIsS0FBUCxDQUFhLHlCQUFiLEVBQXdDa0QsT0FBeEMsRUFBaURuRCxDQUFqRDtBQUNBO0FBQ0Q7QUFDRjtBQUNEMUIsdUJBQU9DLE9BQVAsQ0FBZSxhQUFmLEVBQThCNEUsT0FBOUI7O0FBRUE7QUFDQSxVQUFJLENBQUNDLGFBQUlDLFFBQUosQ0FBYUYsT0FBYixFQUFzQkcsd0JBQWMsU0FBZCxDQUF0QixDQUFELElBQW9ELENBQUNGLGFBQUlDLFFBQUosQ0FBYUYsT0FBYixFQUFzQkcsd0JBQWNILFFBQVFJLEVBQXRCLENBQXRCLENBQXpELEVBQTJHO0FBQ3pHQyx1QkFBT0MsU0FBUCxDQUFpQnRFLGNBQWpCLEVBQWlDLENBQWpDLEVBQW9DaUUsYUFBSW5ELEtBQUosQ0FBVUosT0FBOUM7QUFDQXZCLHlCQUFPMkIsS0FBUCxDQUFhLDBCQUFiLEVBQXlDbUQsYUFBSW5ELEtBQUosQ0FBVUosT0FBbkQ7QUFDQTtBQUNEOztBQUVELGNBQU9zRCxRQUFRSSxFQUFmO0FBQ0EsYUFBSyxTQUFMO0FBQ0UsZUFBS0csY0FBTCxDQUFvQnZFLGNBQXBCLEVBQW9DZ0UsT0FBcEM7QUFDQTtBQUNGLGFBQUssV0FBTDtBQUNFLGVBQUtRLGdCQUFMLENBQXNCeEUsY0FBdEIsRUFBc0NnRSxPQUF0QztBQUNBO0FBQ0YsYUFBSyxRQUFMO0FBQ0UsZUFBS1MseUJBQUwsQ0FBK0J6RSxjQUEvQixFQUErQ2dFLE9BQS9DO0FBQ0E7QUFDRixhQUFLLGFBQUw7QUFDRSxlQUFLVSxrQkFBTCxDQUF3QjFFLGNBQXhCLEVBQXdDZ0UsT0FBeEM7QUFDQTtBQUNGO0FBQ0VLLHlCQUFPQyxTQUFQLENBQWlCdEUsY0FBakIsRUFBaUMsQ0FBakMsRUFBb0MsdUJBQXBDO0FBQ0FiLDJCQUFPMkIsS0FBUCxDQUFhLHVCQUFiLEVBQXNDa0QsUUFBUUksRUFBOUM7QUFmRjtBQWlCRCxLQW5DRDs7QUFxQ0FwRSxtQkFBZU8sRUFBZixDQUFrQixZQUFsQixFQUFnQyxNQUFNO0FBQ3BDcEIsdUJBQU93RixJQUFQLENBQWEsc0JBQXFCM0UsZUFBZXFDLFFBQVMsRUFBMUQ7QUFDQSxZQUFNQSxXQUFXckMsZUFBZXFDLFFBQWhDO0FBQ0EsVUFBSSxDQUFDLEtBQUsxRCxPQUFMLENBQWFpRyxHQUFiLENBQWlCdkMsUUFBakIsQ0FBTCxFQUFpQztBQUMvQixpREFBMEI7QUFDeEJ3QyxpQkFBTyxxQkFEaUI7QUFFeEJsRyxtQkFBUyxLQUFLQSxPQUFMLENBQWFrRCxJQUZFO0FBR3hCaEQseUJBQWUsS0FBS0EsYUFBTCxDQUFtQmdELElBSFY7QUFJeEJmLGlCQUFRLHlCQUF3QnVCLFFBQVM7QUFKakIsU0FBMUI7QUFNQWxELHlCQUFPMkIsS0FBUCxDQUFjLHVCQUFzQnVCLFFBQVMsZ0JBQTdDO0FBQ0E7QUFDRDs7QUFFRDtBQUNBLFlBQU1LLFNBQVMsS0FBSy9ELE9BQUwsQ0FBYW9ELEdBQWIsQ0FBaUJNLFFBQWpCLENBQWY7QUFDQSxXQUFLMUQsT0FBTCxDQUFhbUcsTUFBYixDQUFvQnpDLFFBQXBCOztBQUVBO0FBQ0EsV0FBSyxNQUFNLENBQUNNLFNBQUQsRUFBWW9DLGdCQUFaLENBQVgsSUFBNEN4QyxpQkFBRUMsT0FBRixDQUFVRSxPQUFPc0MsaUJBQWpCLENBQTVDLEVBQWlGO0FBQy9FLGNBQU0vQyxlQUFlOEMsaUJBQWlCOUMsWUFBdEM7QUFDQUEscUJBQWFnRCx3QkFBYixDQUFzQzVDLFFBQXRDLEVBQWdETSxTQUFoRDs7QUFFQTtBQUNBLGNBQU1iLHFCQUFxQixLQUFLakQsYUFBTCxDQUFtQmtELEdBQW5CLENBQXVCRSxhQUFhWCxTQUFwQyxDQUEzQjtBQUNBLFlBQUksQ0FBQ1csYUFBYWlELG9CQUFiLEVBQUwsRUFBMEM7QUFDeENwRCw2QkFBbUJnRCxNQUFuQixDQUEwQjdDLGFBQWE0QixJQUF2QztBQUNEO0FBQ0Q7QUFDQSxZQUFJL0IsbUJBQW1CRCxJQUFuQixLQUE0QixDQUFoQyxFQUFtQztBQUNqQyxlQUFLaEQsYUFBTCxDQUFtQmlHLE1BQW5CLENBQTBCN0MsYUFBYVgsU0FBdkM7QUFDRDtBQUNGOztBQUVEbkMsdUJBQU9DLE9BQVAsQ0FBZSxvQkFBZixFQUFxQyxLQUFLVCxPQUFMLENBQWFrRCxJQUFsRDtBQUNBMUMsdUJBQU9DLE9BQVAsQ0FBZSwwQkFBZixFQUEyQyxLQUFLUCxhQUFMLENBQW1CZ0QsSUFBOUQ7QUFDQSwrQ0FBMEI7QUFDeEJnRCxlQUFPLGVBRGlCO0FBRXhCbEcsaUJBQVMsS0FBS0EsT0FBTCxDQUFha0QsSUFGRTtBQUd4QmhELHVCQUFlLEtBQUtBLGFBQUwsQ0FBbUJnRDtBQUhWLE9BQTFCO0FBS0QsS0F6Q0Q7O0FBMkNBLDZDQUEwQjtBQUN4QmdELGFBQU8sWUFEaUI7QUFFeEJsRyxlQUFTLEtBQUtBLE9BQUwsQ0FBYWtELElBRkU7QUFHeEJoRCxxQkFBZSxLQUFLQSxhQUFMLENBQW1CZ0Q7QUFIVixLQUExQjtBQUtEOztBQUVETyx1QkFBcUJiLFdBQXJCLEVBQXVDVSxZQUF2QyxFQUFtRTtBQUNqRTtBQUNBLFFBQUksQ0FBQ1YsV0FBTCxFQUFrQjtBQUNoQixhQUFPLEtBQVA7QUFDRDtBQUNELFdBQU8sOEJBQWFBLFdBQWIsRUFBMEJVLGFBQWFrRCxLQUF2QyxDQUFQO0FBQ0Q7O0FBRURyQyxjQUFZRixHQUFaLEVBQXNCRixNQUF0QixFQUFtQ0MsU0FBbkMsRUFBMkQ7QUFDekQ7QUFDQSxRQUFJLENBQUNDLEdBQUQsSUFBUUEsSUFBSXdDLG1CQUFKLEVBQVIsSUFBcUMxQyxPQUFPMkMsWUFBaEQsRUFBOEQ7QUFDNUQsYUFBT2hHLGVBQU1nRSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsSUFBakIsQ0FBUDtBQUNEO0FBQ0Q7QUFDQSxVQUFNeUIsbUJBQW1CckMsT0FBTzRDLG1CQUFQLENBQTJCM0MsU0FBM0IsQ0FBekI7QUFDQSxRQUFJLE9BQU9vQyxnQkFBUCxLQUE0QixXQUFoQyxFQUE2QztBQUMzQyxhQUFPMUYsZUFBTWdFLE9BQU4sQ0FBY0MsRUFBZCxDQUFpQixLQUFqQixDQUFQO0FBQ0Q7O0FBRUQsVUFBTWlDLDJCQUEyQlIsaUJBQWlCUyxZQUFsRDtBQUNBLFdBQU8sS0FBS3RFLGlCQUFMLENBQXVCdUUsU0FBdkIsQ0FBaUNGLHdCQUFqQyxFQUEyRHhDLElBQTNELENBQWlFMkMsTUFBRCxJQUFZO0FBQ2pGLGFBQU85QyxJQUFJK0MsYUFBSixDQUFrQkQsTUFBbEIsQ0FBUDtBQUNELEtBRk0sRUFFSjNDLElBRkksQ0FFRTZDLGlDQUFELElBQXVDO0FBQzdDLFVBQUlBLGlDQUFKLEVBQXVDO0FBQ3JDLGVBQU92RyxlQUFNZ0UsT0FBTixDQUFjQyxFQUFkLENBQWlCLElBQWpCLENBQVA7QUFDRDs7QUFFRDtBQUNBLGFBQU8sSUFBSWpFLGVBQU1nRSxPQUFWLENBQWtCLENBQUN3QyxPQUFELEVBQVVDLE1BQVYsS0FBcUI7O0FBRTVDO0FBQ0EsY0FBTUMsZ0JBQWdCL0csT0FBT0MsSUFBUCxDQUFZMkQsSUFBSW9ELGVBQWhCLEVBQWlDQyxJQUFqQyxDQUFzQ2xILE9BQU9BLElBQUltSCxVQUFKLENBQWUsT0FBZixDQUE3QyxDQUF0QjtBQUNBLFlBQUksQ0FBQ0gsYUFBTCxFQUFvQjtBQUNsQixpQkFBT0YsUUFBUSxLQUFSLENBQVA7QUFDRDs7QUFFRCxhQUFLM0UsaUJBQUwsQ0FBdUJ1RSxTQUF2QixDQUFpQ0Ysd0JBQWpDLEVBQ0d4QyxJQURILENBQ1MyQyxNQUFELElBQVk7O0FBRWhCO0FBQ0EsY0FBSSxDQUFDQSxNQUFMLEVBQWE7QUFDWCxtQkFBT3JHLGVBQU1nRSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsSUFBakIsQ0FBUDtBQUNEOztBQUVEO0FBQ0E7QUFDQSxjQUFJNkMsT0FBTyxJQUFJOUcsZUFBTStHLElBQVYsRUFBWDtBQUNBRCxlQUFLdkUsRUFBTCxHQUFVOEQsTUFBVjtBQUNBLGlCQUFPUyxJQUFQO0FBRUQsU0FkSCxFQWVHcEQsSUFmSCxDQWVTb0QsSUFBRCxJQUFVOztBQUVkO0FBQ0EsY0FBSSxDQUFDQSxJQUFMLEVBQVc7QUFDVCxtQkFBTzlHLGVBQU1nRSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsRUFBakIsQ0FBUDtBQUNEOztBQUVEO0FBQ0EsY0FBSStDLGFBQWEsSUFBSWhILGVBQU1pSCxLQUFWLENBQWdCakgsZUFBTWtILElBQXRCLENBQWpCO0FBQ0FGLHFCQUFXRyxPQUFYLENBQW1CLE9BQW5CLEVBQTRCTCxJQUE1QjtBQUNBLGlCQUFPRSxXQUFXSSxJQUFYLENBQWdCLEVBQUNDLGNBQWEsSUFBZCxFQUFoQixDQUFQO0FBQ0QsU0ExQkgsRUEyQkUzRCxJQTNCRixDQTJCUTRELEtBQUQsSUFBVzs7QUFFZDtBQUNBLGVBQUssTUFBTUMsSUFBWCxJQUFtQkQsS0FBbkIsRUFBMEI7QUFDeEIsZ0JBQUkvRCxJQUFJaUUsaUJBQUosQ0FBc0JELElBQXRCLENBQUosRUFBaUM7QUFDL0IscUJBQU9mLFFBQVEsSUFBUixDQUFQO0FBQ0Q7QUFDRjtBQUNEQSxrQkFBUSxLQUFSO0FBQ0QsU0FwQ0gsRUFxQ0dpQixLQXJDSCxDQXFDVWhHLEtBQUQsSUFBVztBQUNoQmdGLGlCQUFPaEYsS0FBUDtBQUNELFNBdkNIO0FBeUNELE9BakRNLENBQVA7QUFrREQsS0ExRE0sRUEwREppQyxJQTFESSxDQTBERWdFLGFBQUQsSUFBbUI7O0FBRXpCLFVBQUdBLGFBQUgsRUFBa0I7QUFDaEIsZUFBTzFILGVBQU1nRSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsSUFBakIsQ0FBUDtBQUNEOztBQUVEO0FBQ0EsWUFBTTBELHFCQUFxQnRFLE9BQU84QyxZQUFsQztBQUNBLGFBQU8sS0FBS3RFLGlCQUFMLENBQXVCdUUsU0FBdkIsQ0FBaUN1QixrQkFBakMsRUFBcURqRSxJQUFyRCxDQUEyRDJDLE1BQUQsSUFBWTtBQUMzRSxlQUFPOUMsSUFBSStDLGFBQUosQ0FBa0JELE1BQWxCLENBQVA7QUFDRCxPQUZNLENBQVA7QUFHRCxLQXJFTSxFQXFFSjNDLElBckVJLENBcUVFQyxTQUFELElBQWU7QUFDckIsYUFBTzNELGVBQU1nRSxPQUFOLENBQWNDLEVBQWQsQ0FBaUJOLFNBQWpCLENBQVA7QUFDRCxLQXZFTSxFQXVFSixNQUFNO0FBQ1AsYUFBTzNELGVBQU1nRSxPQUFOLENBQWNDLEVBQWQsQ0FBaUIsS0FBakIsQ0FBUDtBQUNELEtBekVNLENBQVA7QUEwRUQ7O0FBRURpQixpQkFBZXZFLGNBQWYsRUFBb0NnRSxPQUFwQyxFQUF1RDtBQUNyRCxRQUFJLENBQUMsS0FBS2lELGFBQUwsQ0FBbUJqRCxPQUFuQixFQUE0QixLQUFLbEYsUUFBakMsQ0FBTCxFQUFpRDtBQUMvQ3VGLHFCQUFPQyxTQUFQLENBQWlCdEUsY0FBakIsRUFBaUMsQ0FBakMsRUFBb0MsNkJBQXBDO0FBQ0FiLHVCQUFPMkIsS0FBUCxDQUFhLDZCQUFiO0FBQ0E7QUFDRDtBQUNELFVBQU11RSxlQUFlLEtBQUs2QixhQUFMLENBQW1CbEQsT0FBbkIsRUFBNEIsS0FBS2xGLFFBQWpDLENBQXJCO0FBQ0EsVUFBTXVELFdBQVcscUJBQWpCO0FBQ0EsVUFBTUssU0FBUyxJQUFJMkIsY0FBSixDQUFXaEMsUUFBWCxFQUFxQnJDLGNBQXJCLEVBQXFDcUYsWUFBckMsQ0FBZjtBQUNBckYsbUJBQWVxQyxRQUFmLEdBQTBCQSxRQUExQjtBQUNBLFNBQUsxRCxPQUFMLENBQWFPLEdBQWIsQ0FBaUJjLGVBQWVxQyxRQUFoQyxFQUEwQ0ssTUFBMUM7QUFDQXZELHFCQUFPd0YsSUFBUCxDQUFhLHNCQUFxQjNFLGVBQWVxQyxRQUFTLEVBQTFEO0FBQ0FLLFdBQU95RSxXQUFQO0FBQ0EsNkNBQTBCO0FBQ3hCdEMsYUFBTyxTQURpQjtBQUV4QmxHLGVBQVMsS0FBS0EsT0FBTCxDQUFha0QsSUFGRTtBQUd4QmhELHFCQUFlLEtBQUtBLGFBQUwsQ0FBbUJnRDtBQUhWLEtBQTFCO0FBS0Q7O0FBRURxRixnQkFBY2xELE9BQWQsRUFBNEJvRCxhQUE1QixFQUF5RDtBQUN2RCxRQUFHLENBQUNBLGFBQUQsSUFBa0JBLGNBQWN2RixJQUFkLElBQXNCLENBQXhDLElBQ0QsQ0FBQ3VGLGNBQWN4QyxHQUFkLENBQWtCLFdBQWxCLENBREgsRUFDbUM7QUFDakMsYUFBTyxLQUFQO0FBQ0Q7QUFDRCxRQUFHLENBQUNaLE9BQUQsSUFBWSxDQUFDQSxRQUFRcUQsY0FBUixDQUF1QixXQUF2QixDQUFoQixFQUFxRDtBQUNuRCxhQUFPLEtBQVA7QUFDRDtBQUNELFdBQU9yRCxRQUFRcEUsU0FBUixLQUFzQndILGNBQWNyRixHQUFkLENBQWtCLFdBQWxCLENBQTdCO0FBQ0Q7O0FBRURrRixnQkFBY2pELE9BQWQsRUFBNEJvRCxhQUE1QixFQUF5RDtBQUN2RCxRQUFJLENBQUNBLGFBQUQsSUFBa0JBLGNBQWN2RixJQUFkLElBQXNCLENBQTVDLEVBQStDO0FBQzdDLGFBQU8sSUFBUDtBQUNEO0FBQ0QsUUFBSXlGLFVBQVUsS0FBZDtBQUNBLFNBQUssTUFBTSxDQUFDdkksR0FBRCxFQUFNd0ksTUFBTixDQUFYLElBQTRCSCxhQUE1QixFQUEyQztBQUN6QyxVQUFJLENBQUNwRCxRQUFRakYsR0FBUixDQUFELElBQWlCaUYsUUFBUWpGLEdBQVIsTUFBaUJ3SSxNQUF0QyxFQUE4QztBQUM1QztBQUNEO0FBQ0RELGdCQUFVLElBQVY7QUFDQTtBQUNEO0FBQ0QsV0FBT0EsT0FBUDtBQUNEOztBQUVEOUMsbUJBQWlCeEUsY0FBakIsRUFBc0NnRSxPQUF0QyxFQUF5RDtBQUN2RDtBQUNBLFFBQUksQ0FBQ2hFLGVBQWVxSCxjQUFmLENBQThCLFVBQTlCLENBQUwsRUFBZ0Q7QUFDOUNoRCxxQkFBT0MsU0FBUCxDQUFpQnRFLGNBQWpCLEVBQWlDLENBQWpDLEVBQW9DLDhFQUFwQztBQUNBYix1QkFBTzJCLEtBQVAsQ0FBYSw4RUFBYjtBQUNBO0FBQ0Q7QUFDRCxVQUFNNEIsU0FBUyxLQUFLL0QsT0FBTCxDQUFhb0QsR0FBYixDQUFpQi9CLGVBQWVxQyxRQUFoQyxDQUFmOztBQUVBO0FBQ0EsVUFBTW1GLG1CQUFtQiwyQkFBVXhELFFBQVFtQixLQUFsQixDQUF6QjtBQUNBO0FBQ0EsVUFBTTdELFlBQVkwQyxRQUFRbUIsS0FBUixDQUFjN0QsU0FBaEM7QUFDQSxRQUFJLENBQUMsS0FBS3pDLGFBQUwsQ0FBbUIrRixHQUFuQixDQUF1QnRELFNBQXZCLENBQUwsRUFBd0M7QUFDdEMsV0FBS3pDLGFBQUwsQ0FBbUJLLEdBQW5CLENBQXVCb0MsU0FBdkIsRUFBa0MsSUFBSTFDLEdBQUosRUFBbEM7QUFDRDtBQUNELFVBQU1rRCxxQkFBcUIsS0FBS2pELGFBQUwsQ0FBbUJrRCxHQUFuQixDQUF1QlQsU0FBdkIsQ0FBM0I7QUFDQSxRQUFJVyxZQUFKO0FBQ0EsUUFBSUgsbUJBQW1COEMsR0FBbkIsQ0FBdUI0QyxnQkFBdkIsQ0FBSixFQUE4QztBQUM1Q3ZGLHFCQUFlSCxtQkFBbUJDLEdBQW5CLENBQXVCeUYsZ0JBQXZCLENBQWY7QUFDRCxLQUZELE1BRU87QUFDTHZGLHFCQUFlLElBQUl3RiwwQkFBSixDQUFpQm5HLFNBQWpCLEVBQTRCMEMsUUFBUW1CLEtBQVIsQ0FBY3VDLEtBQTFDLEVBQWlERixnQkFBakQsQ0FBZjtBQUNBMUYseUJBQW1CNUMsR0FBbkIsQ0FBdUJzSSxnQkFBdkIsRUFBeUN2RixZQUF6QztBQUNEOztBQUVEO0FBQ0EsVUFBTThDLG1CQUFtQjtBQUN2QjlDLG9CQUFjQTtBQURTLEtBQXpCO0FBR0E7QUFDQSxRQUFJK0IsUUFBUW1CLEtBQVIsQ0FBY3dDLE1BQWxCLEVBQTBCO0FBQ3hCNUMsdUJBQWlCNEMsTUFBakIsR0FBMEIzRCxRQUFRbUIsS0FBUixDQUFjd0MsTUFBeEM7QUFDRDtBQUNELFFBQUkzRCxRQUFRd0IsWUFBWixFQUEwQjtBQUN4QlQsdUJBQWlCUyxZQUFqQixHQUFnQ3hCLFFBQVF3QixZQUF4QztBQUNEO0FBQ0Q5QyxXQUFPa0YsbUJBQVAsQ0FBMkI1RCxRQUFRckIsU0FBbkMsRUFBOENvQyxnQkFBOUM7O0FBRUE7QUFDQTlDLGlCQUFhNEYscUJBQWIsQ0FBbUM3SCxlQUFlcUMsUUFBbEQsRUFBNEQyQixRQUFRckIsU0FBcEU7O0FBRUFELFdBQU9vRixhQUFQLENBQXFCOUQsUUFBUXJCLFNBQTdCOztBQUVBeEQscUJBQU9DLE9BQVAsQ0FBZ0IsaUJBQWdCWSxlQUFlcUMsUUFBUyxzQkFBcUIyQixRQUFRckIsU0FBVSxFQUEvRjtBQUNBeEQscUJBQU9DLE9BQVAsQ0FBZSwyQkFBZixFQUE0QyxLQUFLVCxPQUFMLENBQWFrRCxJQUF6RDtBQUNBLDZDQUEwQjtBQUN4QmdELGFBQU8sV0FEaUI7QUFFeEJsRyxlQUFTLEtBQUtBLE9BQUwsQ0FBYWtELElBRkU7QUFHeEJoRCxxQkFBZSxLQUFLQSxhQUFMLENBQW1CZ0Q7QUFIVixLQUExQjtBQUtEOztBQUVENEMsNEJBQTBCekUsY0FBMUIsRUFBK0NnRSxPQUEvQyxFQUFrRTtBQUNoRSxTQUFLVSxrQkFBTCxDQUF3QjFFLGNBQXhCLEVBQXdDZ0UsT0FBeEMsRUFBaUQsS0FBakQ7QUFDQSxTQUFLUSxnQkFBTCxDQUFzQnhFLGNBQXRCLEVBQXNDZ0UsT0FBdEM7QUFDRDs7QUFFRFUscUJBQW1CMUUsY0FBbkIsRUFBd0NnRSxPQUF4QyxFQUFzRCtELGVBQXFCLElBQTNFLEVBQXNGO0FBQ3BGO0FBQ0EsUUFBSSxDQUFDL0gsZUFBZXFILGNBQWYsQ0FBOEIsVUFBOUIsQ0FBTCxFQUFnRDtBQUM5Q2hELHFCQUFPQyxTQUFQLENBQWlCdEUsY0FBakIsRUFBaUMsQ0FBakMsRUFBb0MsZ0ZBQXBDO0FBQ0FiLHVCQUFPMkIsS0FBUCxDQUFhLGdGQUFiO0FBQ0E7QUFDRDtBQUNELFVBQU02QixZQUFZcUIsUUFBUXJCLFNBQTFCO0FBQ0EsVUFBTUQsU0FBUyxLQUFLL0QsT0FBTCxDQUFhb0QsR0FBYixDQUFpQi9CLGVBQWVxQyxRQUFoQyxDQUFmO0FBQ0EsUUFBSSxPQUFPSyxNQUFQLEtBQWtCLFdBQXRCLEVBQW1DO0FBQ2pDMkIscUJBQU9DLFNBQVAsQ0FBaUJ0RSxjQUFqQixFQUFpQyxDQUFqQyxFQUFvQyxzQ0FBdUNBLGVBQWVxQyxRQUF0RCxHQUNsQyxvRUFERjtBQUVBbEQsdUJBQU8yQixLQUFQLENBQWEsOEJBQThCZCxlQUFlcUMsUUFBMUQ7QUFDQTtBQUNEOztBQUVELFVBQU0wQyxtQkFBbUJyQyxPQUFPNEMsbUJBQVAsQ0FBMkIzQyxTQUEzQixDQUF6QjtBQUNBLFFBQUksT0FBT29DLGdCQUFQLEtBQTRCLFdBQWhDLEVBQTZDO0FBQzNDVixxQkFBT0MsU0FBUCxDQUFpQnRFLGNBQWpCLEVBQWlDLENBQWpDLEVBQW9DLDRDQUE2Q0EsZUFBZXFDLFFBQTVELEdBQ2xDLGtCQURrQyxHQUNiTSxTQURhLEdBQ0Qsc0VBRG5DO0FBRUF4RCx1QkFBTzJCLEtBQVAsQ0FBYSw2Q0FBNkNkLGVBQWVxQyxRQUE1RCxHQUF3RSxrQkFBeEUsR0FBNkZNLFNBQTFHO0FBQ0E7QUFDRDs7QUFFRDtBQUNBRCxXQUFPc0Ysc0JBQVAsQ0FBOEJyRixTQUE5QjtBQUNBO0FBQ0EsVUFBTVYsZUFBZThDLGlCQUFpQjlDLFlBQXRDO0FBQ0EsVUFBTVgsWUFBWVcsYUFBYVgsU0FBL0I7QUFDQVcsaUJBQWFnRCx3QkFBYixDQUFzQ2pGLGVBQWVxQyxRQUFyRCxFQUErRE0sU0FBL0Q7QUFDQTtBQUNBLFVBQU1iLHFCQUFxQixLQUFLakQsYUFBTCxDQUFtQmtELEdBQW5CLENBQXVCVCxTQUF2QixDQUEzQjtBQUNBLFFBQUksQ0FBQ1csYUFBYWlELG9CQUFiLEVBQUwsRUFBMEM7QUFDeENwRCx5QkFBbUJnRCxNQUFuQixDQUEwQjdDLGFBQWE0QixJQUF2QztBQUNEO0FBQ0Q7QUFDQSxRQUFJL0IsbUJBQW1CRCxJQUFuQixLQUE0QixDQUFoQyxFQUFtQztBQUNqQyxXQUFLaEQsYUFBTCxDQUFtQmlHLE1BQW5CLENBQTBCeEQsU0FBMUI7QUFDRDtBQUNELDZDQUEwQjtBQUN4QnVELGFBQU8sYUFEaUI7QUFFeEJsRyxlQUFTLEtBQUtBLE9BQUwsQ0FBYWtELElBRkU7QUFHeEJoRCxxQkFBZSxLQUFLQSxhQUFMLENBQW1CZ0Q7QUFIVixLQUExQjs7QUFNQSxRQUFJLENBQUNrRyxZQUFMLEVBQW1CO0FBQ2pCO0FBQ0Q7O0FBRURyRixXQUFPdUYsZUFBUCxDQUF1QmpFLFFBQVFyQixTQUEvQjs7QUFFQXhELHFCQUFPQyxPQUFQLENBQWdCLGtCQUFpQlksZUFBZXFDLFFBQVMsb0JBQW1CMkIsUUFBUXJCLFNBQVUsRUFBOUY7QUFDRDtBQTlpQndCOztRQWtqQnpCcEUsb0IsR0FBQUEsb0IiLCJmaWxlIjoiUGFyc2VMaXZlUXVlcnlTZXJ2ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHY0IGZyb20gJ3R2NCc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICcuL1N1YnNjcmlwdGlvbic7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tICcuL0NsaWVudCc7XG5pbXBvcnQgeyBQYXJzZVdlYlNvY2tldFNlcnZlciB9IGZyb20gJy4vUGFyc2VXZWJTb2NrZXRTZXJ2ZXInO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IFJlcXVlc3RTY2hlbWEgZnJvbSAnLi9SZXF1ZXN0U2NoZW1hJztcbmltcG9ydCB7IG1hdGNoZXNRdWVyeSwgcXVlcnlIYXNoIH0gZnJvbSAnLi9RdWVyeVRvb2xzJztcbmltcG9ydCB7IFBhcnNlUHViU3ViIH0gZnJvbSAnLi9QYXJzZVB1YlN1Yic7XG5pbXBvcnQgeyBTZXNzaW9uVG9rZW5DYWNoZSB9IGZyb20gJy4vU2Vzc2lvblRva2VuQ2FjaGUnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB1dWlkIGZyb20gJ3V1aWQnO1xuaW1wb3J0IHsgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyB9IGZyb20gJy4uL3RyaWdnZXJzJztcblxuY2xhc3MgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIge1xuICBjbGllbnRzOiBNYXA7XG4gIC8vIGNsYXNzTmFtZSAtPiAocXVlcnlIYXNoIC0+IHN1YnNjcmlwdGlvbilcbiAgc3Vic2NyaXB0aW9uczogT2JqZWN0O1xuICBwYXJzZVdlYlNvY2tldFNlcnZlcjogT2JqZWN0O1xuICBrZXlQYWlycyA6IGFueTtcbiAgLy8gVGhlIHN1YnNjcmliZXIgd2UgdXNlIHRvIGdldCBvYmplY3QgdXBkYXRlIGZyb20gcHVibGlzaGVyXG4gIHN1YnNjcmliZXI6IE9iamVjdDtcblxuICBjb25zdHJ1Y3RvcihzZXJ2ZXI6IGFueSwgY29uZmlnOiBhbnkpIHtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICB0aGlzLmNsaWVudHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zID0gbmV3IE1hcCgpO1xuXG4gICAgY29uZmlnID0gY29uZmlnIHx8IHt9O1xuXG4gICAgLy8gU3RvcmUga2V5cywgY29udmVydCBvYmogdG8gbWFwXG4gICAgY29uc3Qga2V5UGFpcnMgPSBjb25maWcua2V5UGFpcnMgfHwge307XG4gICAgdGhpcy5rZXlQYWlycyA9IG5ldyBNYXAoKTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhrZXlQYWlycykpIHtcbiAgICAgIHRoaXMua2V5UGFpcnMuc2V0KGtleSwga2V5UGFpcnNba2V5XSk7XG4gICAgfVxuICAgIGxvZ2dlci52ZXJib3NlKCdTdXBwb3J0IGtleSBwYWlycycsIHRoaXMua2V5UGFpcnMpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBQYXJzZVxuICAgIFBhcnNlLk9iamVjdC5kaXNhYmxlU2luZ2xlSW5zdGFuY2UoKTtcblxuICAgIGNvbnN0IHNlcnZlclVSTCA9IGNvbmZpZy5zZXJ2ZXJVUkwgfHwgUGFyc2Uuc2VydmVyVVJMO1xuICAgIFBhcnNlLnNlcnZlclVSTCA9IHNlcnZlclVSTDtcbiAgICBjb25zdCBhcHBJZCA9IGNvbmZpZy5hcHBJZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICAgIGNvbnN0IGphdmFzY3JpcHRLZXkgPSBQYXJzZS5qYXZhU2NyaXB0S2V5O1xuICAgIGNvbnN0IG1hc3RlcktleSA9IGNvbmZpZy5tYXN0ZXJLZXkgfHwgUGFyc2UubWFzdGVyS2V5O1xuICAgIFBhcnNlLmluaXRpYWxpemUoYXBwSWQsIGphdmFzY3JpcHRLZXksIG1hc3RlcktleSk7XG5cbiAgICAvLyBJbml0aWFsaXplIHdlYnNvY2tldCBzZXJ2ZXJcbiAgICB0aGlzLnBhcnNlV2ViU29ja2V0U2VydmVyID0gbmV3IFBhcnNlV2ViU29ja2V0U2VydmVyKFxuICAgICAgc2VydmVyLFxuICAgICAgKHBhcnNlV2Vic29ja2V0KSA9PiB0aGlzLl9vbkNvbm5lY3QocGFyc2VXZWJzb2NrZXQpLFxuICAgICAgY29uZmlnLndlYnNvY2tldFRpbWVvdXRcbiAgICApO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzdWJzY3JpYmVyXG4gICAgdGhpcy5zdWJzY3JpYmVyID0gUGFyc2VQdWJTdWIuY3JlYXRlU3Vic2NyaWJlcihjb25maWcpO1xuICAgIHRoaXMuc3Vic2NyaWJlci5zdWJzY3JpYmUoUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlclNhdmUnKTtcbiAgICB0aGlzLnN1YnNjcmliZXIuc3Vic2NyaWJlKFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJEZWxldGUnKTtcbiAgICAvLyBSZWdpc3RlciBtZXNzYWdlIGhhbmRsZXIgZm9yIHN1YnNjcmliZXIuIFdoZW4gcHVibGlzaGVyIGdldCBtZXNzYWdlcywgaXQgd2lsbCBwdWJsaXNoIG1lc3NhZ2VcbiAgICAvLyB0byB0aGUgc3Vic2NyaWJlcnMgYW5kIHRoZSBoYW5kbGVyIHdpbGwgYmUgY2FsbGVkLlxuICAgIHRoaXMuc3Vic2NyaWJlci5vbignbWVzc2FnZScsIChjaGFubmVsLCBtZXNzYWdlU3RyKSA9PiB7XG4gICAgICBsb2dnZXIudmVyYm9zZSgnU3Vic2NyaWJlIG1lc3NzYWdlICVqJywgbWVzc2FnZVN0cik7XG4gICAgICBsZXQgbWVzc2FnZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG1lc3NhZ2VTdHIpO1xuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcigndW5hYmxlIHRvIHBhcnNlIG1lc3NhZ2UnLCBtZXNzYWdlU3RyLCBlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5faW5mbGF0ZVBhcnNlT2JqZWN0KG1lc3NhZ2UpO1xuICAgICAgaWYgKGNoYW5uZWwgPT09IFBhcnNlLmFwcGxpY2F0aW9uSWQgKyAnYWZ0ZXJTYXZlJykge1xuICAgICAgICB0aGlzLl9vbkFmdGVyU2F2ZShtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbm5lbCA9PT0gUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlckRlbGV0ZScpIHtcbiAgICAgICAgdGhpcy5fb25BZnRlckRlbGV0ZShtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcignR2V0IG1lc3NhZ2UgJXMgZnJvbSB1bmtub3duIGNoYW5uZWwgJWonLCBtZXNzYWdlLCBjaGFubmVsKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEluaXRpYWxpemUgc2Vzc2lvblRva2VuIGNhY2hlXG4gICAgdGhpcy5zZXNzaW9uVG9rZW5DYWNoZSA9IG5ldyBTZXNzaW9uVG9rZW5DYWNoZShjb25maWcuY2FjaGVUaW1lb3V0KTtcbiAgfVxuXG4gIC8vIE1lc3NhZ2UgaXMgdGhlIEpTT04gb2JqZWN0IGZyb20gcHVibGlzaGVyLiBNZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdCBpcyB0aGUgUGFyc2VPYmplY3QgSlNPTiBhZnRlciBjaGFuZ2VzLlxuICAvLyBNZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgaXMgdGhlIG9yaWdpbmFsIFBhcnNlT2JqZWN0IEpTT04uXG4gIF9pbmZsYXRlUGFyc2VPYmplY3QobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgLy8gSW5mbGF0ZSBtZXJnZWQgb2JqZWN0XG4gICAgY29uc3QgY3VycmVudFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3Q7XG4gICAgbGV0IGNsYXNzTmFtZSA9IGN1cnJlbnRQYXJzZU9iamVjdC5jbGFzc05hbWU7XG4gICAgbGV0IHBhcnNlT2JqZWN0ID0gbmV3IFBhcnNlLk9iamVjdChjbGFzc05hbWUpO1xuICAgIHBhcnNlT2JqZWN0Ll9maW5pc2hGZXRjaChjdXJyZW50UGFyc2VPYmplY3QpO1xuICAgIG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0ID0gcGFyc2VPYmplY3Q7XG4gICAgLy8gSW5mbGF0ZSBvcmlnaW5hbCBvYmplY3RcbiAgICBjb25zdCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0O1xuICAgIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBjbGFzc05hbWUgPSBvcmlnaW5hbFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICAgIHBhcnNlT2JqZWN0ID0gbmV3IFBhcnNlLk9iamVjdChjbGFzc05hbWUpO1xuICAgICAgcGFyc2VPYmplY3QuX2ZpbmlzaEZldGNoKG9yaWdpbmFsUGFyc2VPYmplY3QpO1xuICAgICAgbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0ID0gcGFyc2VPYmplY3Q7XG4gICAgfVxuICB9XG5cbiAgLy8gTWVzc2FnZSBpcyB0aGUgSlNPTiBvYmplY3QgZnJvbSBwdWJsaXNoZXIgYWZ0ZXIgaW5mbGF0ZWQuIE1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0IGlzIHRoZSBQYXJzZU9iamVjdCBhZnRlciBjaGFuZ2VzLlxuICAvLyBNZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgaXMgdGhlIG9yaWdpbmFsIFBhcnNlT2JqZWN0LlxuICBfb25BZnRlckRlbGV0ZShtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyRGVsZXRlIGlzIHRyaWdnZXJlZCcpO1xuXG4gICAgY29uc3QgZGVsZXRlZFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QudG9KU09OKCk7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gZGVsZXRlZFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ2xhc3NOYW1lOiAlaiB8IE9iamVjdElkOiAlcycsIGNsYXNzTmFtZSwgZGVsZXRlZFBhcnNlT2JqZWN0LmlkKTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBjbGllbnQgbnVtYmVyIDogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG5cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgaWYgKHR5cGVvZiBjbGFzc1N1YnNjcmlwdGlvbnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NhbiBub3QgZmluZCBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MgJyArIGNsYXNzTmFtZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc3Vic2NyaXB0aW9uIG9mIGNsYXNzU3Vic2NyaXB0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgaXNTdWJzY3JpcHRpb25NYXRjaGVkID0gdGhpcy5fbWF0Y2hlc1N1YnNjcmlwdGlvbihkZWxldGVkUGFyc2VPYmplY3QsIHN1YnNjcmlwdGlvbik7XG4gICAgICBpZiAoIWlzU3Vic2NyaXB0aW9uTWF0Y2hlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgW2NsaWVudElkLCByZXF1ZXN0SWRzXSBvZiBfLmVudHJpZXMoc3Vic2NyaXB0aW9uLmNsaWVudFJlcXVlc3RJZHMpKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWQpO1xuICAgICAgICBpZiAodHlwZW9mIGNsaWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7XG4gICAgICAgICAgY29uc3QgYWNsID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QuZ2V0QUNMKCk7XG4gICAgICAgICAgLy8gQ2hlY2sgQUNMXG4gICAgICAgICAgdGhpcy5fbWF0Y2hlc0FDTChhY2wsIGNsaWVudCwgcmVxdWVzdElkKS50aGVuKChpc01hdGNoZWQpID0+IHtcbiAgICAgICAgICAgIGlmICghaXNNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2xpZW50LnB1c2hEZWxldGUocmVxdWVzdElkLCBkZWxldGVkUGFyc2VPYmplY3QpO1xuICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdNYXRjaGluZyBBQ0wgZXJyb3IgOiAnLCBlcnJvcik7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBNZXNzYWdlIGlzIHRoZSBKU09OIG9iamVjdCBmcm9tIHB1Ymxpc2hlciBhZnRlciBpbmZsYXRlZC4gTWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QgaXMgdGhlIFBhcnNlT2JqZWN0IGFmdGVyIGNoYW5nZXMuXG4gIC8vIE1lc3NhZ2Uub3JpZ2luYWxQYXJzZU9iamVjdCBpcyB0aGUgb3JpZ2luYWwgUGFyc2VPYmplY3QuXG4gIF9vbkFmdGVyU2F2ZShtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyU2F2ZSBpcyB0cmlnZ2VyZWQnKTtcblxuICAgIGxldCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbnVsbDtcbiAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LnRvSlNPTigpO1xuICAgIH1cbiAgICBjb25zdCBjdXJyZW50UGFyc2VPYmplY3QgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdC50b0pTT04oKTtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBjdXJyZW50UGFyc2VPYmplY3QuY2xhc3NOYW1lO1xuICAgIGxvZ2dlci52ZXJib3NlKCdDbGFzc05hbWU6ICVzIHwgT2JqZWN0SWQ6ICVzJywgY2xhc3NOYW1lLCBjdXJyZW50UGFyc2VPYmplY3QuaWQpO1xuICAgIGxvZ2dlci52ZXJib3NlKCdDdXJyZW50IGNsaWVudCBudW1iZXIgOiAlZCcsIHRoaXMuY2xpZW50cy5zaXplKTtcblxuICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoY2xhc3NOYW1lKTtcbiAgICBpZiAodHlwZW9mIGNsYXNzU3Vic2NyaXB0aW9ucyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ2FuIG5vdCBmaW5kIHN1YnNjcmlwdGlvbnMgdW5kZXIgdGhpcyBjbGFzcyAnICsgY2xhc3NOYW1lKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBzdWJzY3JpcHRpb24gb2YgY2xhc3NTdWJzY3JpcHRpb25zLnZhbHVlcygpKSB7XG4gICAgICBjb25zdCBpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCA9IHRoaXMuX21hdGNoZXNTdWJzY3JpcHRpb24ob3JpZ2luYWxQYXJzZU9iamVjdCwgc3Vic2NyaXB0aW9uKTtcbiAgICAgIGNvbnN0IGlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQgPSB0aGlzLl9tYXRjaGVzU3Vic2NyaXB0aW9uKGN1cnJlbnRQYXJzZU9iamVjdCwgc3Vic2NyaXB0aW9uKTtcbiAgICAgIGZvciAoY29uc3QgW2NsaWVudElkLCByZXF1ZXN0SWRzXSBvZiBfLmVudHJpZXMoc3Vic2NyaXB0aW9uLmNsaWVudFJlcXVlc3RJZHMpKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWQpO1xuICAgICAgICBpZiAodHlwZW9mIGNsaWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7XG4gICAgICAgICAgLy8gU2V0IG9yaWduYWwgUGFyc2VPYmplY3QgQUNMIGNoZWNraW5nIHByb21pc2UsIGlmIHRoZSBvYmplY3QgZG9lcyBub3QgbWF0Y2hcbiAgICAgICAgICAvLyBzdWJzY3JpcHRpb24sIHdlIGRvIG5vdCBuZWVkIHRvIGNoZWNrIEFDTFxuICAgICAgICAgIGxldCBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZTtcbiAgICAgICAgICBpZiAoIWlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkKSB7XG4gICAgICAgICAgICBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSA9IFBhcnNlLlByb21pc2UuYXMoZmFsc2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxBQ0w7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICAgICAgICAgIG9yaWdpbmFsQUNMID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LmdldEFDTCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3JpZ2luYWxBQ0xDaGVja2luZ1Byb21pc2UgPSB0aGlzLl9tYXRjaGVzQUNMKG9yaWdpbmFsQUNMLCBjbGllbnQsIHJlcXVlc3RJZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFNldCBjdXJyZW50IFBhcnNlT2JqZWN0IEFDTCBjaGVja2luZyBwcm9taXNlLCBpZiB0aGUgb2JqZWN0IGRvZXMgbm90IG1hdGNoXG4gICAgICAgICAgLy8gc3Vic2NyaXB0aW9uLCB3ZSBkbyBub3QgbmVlZCB0byBjaGVjayBBQ0xcbiAgICAgICAgICBsZXQgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZTtcbiAgICAgICAgICBpZiAoIWlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRBQ0xDaGVja2luZ1Byb21pc2UgPSBQYXJzZS5Qcm9taXNlLmFzKGZhbHNlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudEFDTCA9IG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0LmdldEFDTCgpO1xuICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSA9IHRoaXMuX21hdGNoZXNBQ0woY3VycmVudEFDTCwgY2xpZW50LCByZXF1ZXN0SWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIFBhcnNlLlByb21pc2Uud2hlbihcbiAgICAgICAgICAgIG9yaWdpbmFsQUNMQ2hlY2tpbmdQcm9taXNlLFxuICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZVxuICAgICAgICAgICkudGhlbigoaXNPcmlnaW5hbE1hdGNoZWQsIGlzQ3VycmVudE1hdGNoZWQpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci52ZXJib3NlKCdPcmlnaW5hbCAlaiB8IEN1cnJlbnQgJWogfCBNYXRjaDogJXMsICVzLCAlcywgJXMgfCBRdWVyeTogJXMnLFxuICAgICAgICAgICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgICBjdXJyZW50UGFyc2VPYmplY3QsXG4gICAgICAgICAgICAgIGlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkLFxuICAgICAgICAgICAgICBpc0N1cnJlbnRTdWJzY3JpcHRpb25NYXRjaGVkLFxuICAgICAgICAgICAgICBpc09yaWdpbmFsTWF0Y2hlZCxcbiAgICAgICAgICAgICAgaXNDdXJyZW50TWF0Y2hlZCxcbiAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLmhhc2hcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIERlY2lkZSBldmVudCB0eXBlXG4gICAgICAgICAgICBsZXQgdHlwZTtcbiAgICAgICAgICAgIGlmIChpc09yaWdpbmFsTWF0Y2hlZCAmJiBpc0N1cnJlbnRNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIHR5cGUgPSAnVXBkYXRlJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPcmlnaW5hbE1hdGNoZWQgJiYgIWlzQ3VycmVudE1hdGNoZWQpIHtcbiAgICAgICAgICAgICAgdHlwZSA9ICdMZWF2ZSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFpc09yaWdpbmFsTWF0Y2hlZCAmJiBpc0N1cnJlbnRNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgdHlwZSA9ICdFbnRlcic7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHlwZSA9ICdDcmVhdGUnO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGZ1bmN0aW9uTmFtZSA9ICdwdXNoJyArIHR5cGU7XG4gICAgICAgICAgICBjbGllbnRbZnVuY3Rpb25OYW1lXShyZXF1ZXN0SWQsIGN1cnJlbnRQYXJzZU9iamVjdCk7XG4gICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ01hdGNoaW5nIEFDTCBlcnJvciA6ICcsIGVycm9yKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9vbkNvbm5lY3QocGFyc2VXZWJzb2NrZXQ6IGFueSk6IHZvaWQge1xuICAgIHBhcnNlV2Vic29ja2V0Lm9uKCdtZXNzYWdlJywgKHJlcXVlc3QpID0+IHtcbiAgICAgIGlmICh0eXBlb2YgcmVxdWVzdCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXF1ZXN0ID0gSlNPTi5wYXJzZShyZXF1ZXN0KTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKCd1bmFibGUgdG8gcGFyc2UgcmVxdWVzdCcsIHJlcXVlc3QsIGUpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbG9nZ2VyLnZlcmJvc2UoJ1JlcXVlc3Q6ICVqJywgcmVxdWVzdCk7XG5cbiAgICAgIC8vIENoZWNrIHdoZXRoZXIgdGhpcyByZXF1ZXN0IGlzIGEgdmFsaWQgcmVxdWVzdCwgcmV0dXJuIGVycm9yIGRpcmVjdGx5IGlmIG5vdFxuICAgICAgaWYgKCF0djQudmFsaWRhdGUocmVxdWVzdCwgUmVxdWVzdFNjaGVtYVsnZ2VuZXJhbCddKSB8fCAhdHY0LnZhbGlkYXRlKHJlcXVlc3QsIFJlcXVlc3RTY2hlbWFbcmVxdWVzdC5vcF0pKSB7XG4gICAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDEsIHR2NC5lcnJvci5tZXNzYWdlKTtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdDb25uZWN0IG1lc3NhZ2UgZXJyb3IgJXMnLCB0djQuZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc3dpdGNoKHJlcXVlc3Qub3ApIHtcbiAgICAgIGNhc2UgJ2Nvbm5lY3QnOlxuICAgICAgICB0aGlzLl9oYW5kbGVDb25uZWN0KHBhcnNlV2Vic29ja2V0LCByZXF1ZXN0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzdWJzY3JpYmUnOlxuICAgICAgICB0aGlzLl9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3VwZGF0ZSc6XG4gICAgICAgIHRoaXMuX2hhbmRsZVVwZGF0ZVN1YnNjcmlwdGlvbihwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndW5zdWJzY3JpYmUnOlxuICAgICAgICB0aGlzLl9oYW5kbGVVbnN1YnNjcmliZShwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMywgJ0dldCB1bmtub3duIG9wZXJhdGlvbicpO1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ0dldCB1bmtub3duIG9wZXJhdGlvbicsIHJlcXVlc3Qub3ApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcGFyc2VXZWJzb2NrZXQub24oJ2Rpc2Nvbm5lY3QnLCAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgQ2xpZW50IGRpc2Nvbm5lY3Q6ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9YCk7XG4gICAgICBjb25zdCBjbGllbnRJZCA9IHBhcnNlV2Vic29ja2V0LmNsaWVudElkO1xuICAgICAgaWYgKCF0aGlzLmNsaWVudHMuaGFzKGNsaWVudElkKSkge1xuICAgICAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgICAgICBldmVudDogJ3dzX2Rpc2Nvbm5lY3RfZXJyb3InLFxuICAgICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgICAgIGVycm9yOiBgVW5hYmxlIHRvIGZpbmQgY2xpZW50ICR7Y2xpZW50SWR9YFxuICAgICAgICB9KTtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBDYW4gbm90IGZpbmQgY2xpZW50ICR7Y2xpZW50SWR9IG9uIGRpc2Nvbm5lY3RgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBEZWxldGUgY2xpZW50XG4gICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHMuZ2V0KGNsaWVudElkKTtcbiAgICAgIHRoaXMuY2xpZW50cy5kZWxldGUoY2xpZW50SWQpO1xuXG4gICAgICAvLyBEZWxldGUgY2xpZW50IGZyb20gc3Vic2NyaXB0aW9uc1xuICAgICAgZm9yIChjb25zdCBbcmVxdWVzdElkLCBzdWJzY3JpcHRpb25JbmZvXSBvZiBfLmVudHJpZXMoY2xpZW50LnN1YnNjcmlwdGlvbkluZm9zKSkge1xuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBzdWJzY3JpcHRpb25JbmZvLnN1YnNjcmlwdGlvbjtcbiAgICAgICAgc3Vic2NyaXB0aW9uLmRlbGV0ZUNsaWVudFN1YnNjcmlwdGlvbihjbGllbnRJZCwgcmVxdWVzdElkKTtcblxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBubyBjbGllbnQgd2hpY2ggaXMgc3Vic2NyaWJpbmcgdGhpcyBzdWJzY3JpcHRpb24sIHJlbW92ZSBpdCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICAgICAgY29uc3QgY2xhc3NTdWJzY3JpcHRpb25zID0gdGhpcy5zdWJzY3JpcHRpb25zLmdldChzdWJzY3JpcHRpb24uY2xhc3NOYW1lKTtcbiAgICAgICAgaWYgKCFzdWJzY3JpcHRpb24uaGFzU3Vic2NyaWJpbmdDbGllbnQoKSkge1xuICAgICAgICAgIGNsYXNzU3Vic2NyaXB0aW9ucy5kZWxldGUoc3Vic2NyaXB0aW9uLmhhc2gpO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHRoZXJlIGlzIG5vIHN1YnNjcmlwdGlvbnMgdW5kZXIgdGhpcyBjbGFzcywgcmVtb3ZlIGl0IGZyb20gc3Vic2NyaXB0aW9uc1xuICAgICAgICBpZiAoY2xhc3NTdWJzY3JpcHRpb25zLnNpemUgPT09IDApIHtcbiAgICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZGVsZXRlKHN1YnNjcmlwdGlvbi5jbGFzc05hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxvZ2dlci52ZXJib3NlKCdDdXJyZW50IGNsaWVudHMgJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG4gICAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBzdWJzY3JpcHRpb25zICVkJywgdGhpcy5zdWJzY3JpcHRpb25zLnNpemUpO1xuICAgICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICAgIGV2ZW50OiAnd3NfZGlzY29ubmVjdCcsXG4gICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICBzdWJzY3JpcHRpb25zOiB0aGlzLnN1YnNjcmlwdGlvbnMuc2l6ZVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgIGV2ZW50OiAnd3NfY29ubmVjdCcsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplXG4gICAgfSk7XG4gIH1cblxuICBfbWF0Y2hlc1N1YnNjcmlwdGlvbihwYXJzZU9iamVjdDogYW55LCBzdWJzY3JpcHRpb246IGFueSk6IGJvb2xlYW4ge1xuICAgIC8vIE9iamVjdCBpcyB1bmRlZmluZWQgb3IgbnVsbCwgbm90IG1hdGNoXG4gICAgaWYgKCFwYXJzZU9iamVjdCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2hlc1F1ZXJ5KHBhcnNlT2JqZWN0LCBzdWJzY3JpcHRpb24ucXVlcnkpO1xuICB9XG5cbiAgX21hdGNoZXNBQ0woYWNsOiBhbnksIGNsaWVudDogYW55LCByZXF1ZXN0SWQ6IG51bWJlcik6IGFueSB7XG4gICAgLy8gUmV0dXJuIHRydWUgZGlyZWN0bHkgaWYgQUNMIGlzbid0IHByZXNlbnQsIEFDTCBpcyBwdWJsaWMgcmVhZCwgb3IgY2xpZW50IGhhcyBtYXN0ZXIga2V5XG4gICAgaWYgKCFhY2wgfHwgYWNsLmdldFB1YmxpY1JlYWRBY2Nlc3MoKSB8fCBjbGllbnQuaGFzTWFzdGVyS2V5KSB7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyh0cnVlKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgc3Vic2NyaXB0aW9uIHNlc3Npb25Ub2tlbiBtYXRjaGVzIEFDTCBmaXJzdFxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSW5mbyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKGZhbHNlKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25TZXNzaW9uVG9rZW4gPSBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlbjtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uVG9rZW5DYWNoZS5nZXRVc2VySWQoc3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuKS50aGVuKCh1c2VySWQpID0+IHtcbiAgICAgIHJldHVybiBhY2wuZ2V0UmVhZEFjY2Vzcyh1c2VySWQpO1xuICAgIH0pLnRoZW4oKGlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCkgPT4ge1xuICAgICAgaWYgKGlzU3Vic2NyaXB0aW9uU2Vzc2lvblRva2VuTWF0Y2hlZCkge1xuICAgICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyh0cnVlKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIHVzZXIgaGFzIGFueSByb2xlcyB0aGF0IG1hdGNoIHRoZSBBQ0xcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBmYWxzZSByaWdodCBhd2F5IGlmIHRoZSBhY2wgZG9lc24ndCBoYXZlIGFueSByb2xlc1xuICAgICAgICBjb25zdCBhY2xfaGFzX3JvbGVzID0gT2JqZWN0LmtleXMoYWNsLnBlcm1pc3Npb25zQnlJZCkuc29tZShrZXkgPT4ga2V5LnN0YXJ0c1dpdGgoXCJyb2xlOlwiKSk7XG4gICAgICAgIGlmICghYWNsX2hhc19yb2xlcykge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2Vzc2lvblRva2VuQ2FjaGUuZ2V0VXNlcklkKHN1YnNjcmlwdGlvblNlc3Npb25Ub2tlbilcbiAgICAgICAgICAudGhlbigodXNlcklkKSA9PiB7XG5cbiAgICAgICAgICAgIC8vIFBhc3MgYWxvbmcgYSBudWxsIGlmIHRoZXJlIGlzIG5vIHVzZXIgaWRcbiAgICAgICAgICAgIGlmICghdXNlcklkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKG51bGwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQcmVwYXJlIGEgdXNlciBvYmplY3QgdG8gcXVlcnkgZm9yIHJvbGVzXG4gICAgICAgICAgICAvLyBUbyBlbGltaW5hdGUgYSBxdWVyeSBmb3IgdGhlIHVzZXIsIGNyZWF0ZSBvbmUgbG9jYWxseSB3aXRoIHRoZSBpZFxuICAgICAgICAgICAgdmFyIHVzZXIgPSBuZXcgUGFyc2UuVXNlcigpO1xuICAgICAgICAgICAgdXNlci5pZCA9IHVzZXJJZDtcbiAgICAgICAgICAgIHJldHVybiB1c2VyO1xuXG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbigodXNlcikgPT4ge1xuXG4gICAgICAgICAgICAvLyBQYXNzIGFsb25nIGFuIGVtcHR5IGFycmF5IChvZiByb2xlcykgaWYgbm8gdXNlclxuICAgICAgICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKFtdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVGhlbiBnZXQgdGhlIHVzZXIncyByb2xlc1xuICAgICAgICAgICAgdmFyIHJvbGVzUXVlcnkgPSBuZXcgUGFyc2UuUXVlcnkoUGFyc2UuUm9sZSk7XG4gICAgICAgICAgICByb2xlc1F1ZXJ5LmVxdWFsVG8oXCJ1c2Vyc1wiLCB1c2VyKTtcbiAgICAgICAgICAgIHJldHVybiByb2xlc1F1ZXJ5LmZpbmQoe3VzZU1hc3RlcktleTp0cnVlfSk7XG4gICAgICAgICAgfSkuXG4gICAgICAgICAgdGhlbigocm9sZXMpID0+IHtcblxuICAgICAgICAgICAgLy8gRmluYWxseSwgc2VlIGlmIGFueSBvZiB0aGUgdXNlcidzIHJvbGVzIGFsbG93IHRoZW0gcmVhZCBhY2Nlc3NcbiAgICAgICAgICAgIGZvciAoY29uc3Qgcm9sZSBvZiByb2xlcykge1xuICAgICAgICAgICAgICBpZiAoYWNsLmdldFJvbGVSZWFkQWNjZXNzKHJvbGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfSkudGhlbigoaXNSb2xlTWF0Y2hlZCkgPT4ge1xuXG4gICAgICBpZihpc1JvbGVNYXRjaGVkKSB7XG4gICAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKHRydWUpO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBjbGllbnQgc2Vzc2lvblRva2VuIG1hdGNoZXMgQUNMXG4gICAgICBjb25zdCBjbGllbnRTZXNzaW9uVG9rZW4gPSBjbGllbnQuc2Vzc2lvblRva2VuO1xuICAgICAgcmV0dXJuIHRoaXMuc2Vzc2lvblRva2VuQ2FjaGUuZ2V0VXNlcklkKGNsaWVudFNlc3Npb25Ub2tlbikudGhlbigodXNlcklkKSA9PiB7XG4gICAgICAgIHJldHVybiBhY2wuZ2V0UmVhZEFjY2Vzcyh1c2VySWQpO1xuICAgICAgfSk7XG4gICAgfSkudGhlbigoaXNNYXRjaGVkKSA9PiB7XG4gICAgICByZXR1cm4gUGFyc2UuUHJvbWlzZS5hcyhpc01hdGNoZWQpO1xuICAgIH0sICgpID0+IHtcbiAgICAgIHJldHVybiBQYXJzZS5Qcm9taXNlLmFzKGZhbHNlKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9oYW5kbGVDb25uZWN0KHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IGFueSB7XG4gICAgaWYgKCF0aGlzLl92YWxpZGF0ZUtleXMocmVxdWVzdCwgdGhpcy5rZXlQYWlycykpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDQsICdLZXkgaW4gcmVxdWVzdCBpcyBub3QgdmFsaWQnKTtcbiAgICAgIGxvZ2dlci5lcnJvcignS2V5IGluIHJlcXVlc3QgaXMgbm90IHZhbGlkJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGhhc01hc3RlcktleSA9IHRoaXMuX2hhc01hc3RlcktleShyZXF1ZXN0LCB0aGlzLmtleVBhaXJzKTtcbiAgICBjb25zdCBjbGllbnRJZCA9IHV1aWQoKTtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQ2xpZW50KGNsaWVudElkLCBwYXJzZVdlYnNvY2tldCwgaGFzTWFzdGVyS2V5KTtcbiAgICBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCA9IGNsaWVudElkO1xuICAgIHRoaXMuY2xpZW50cy5zZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIGNsaWVudCk7XG4gICAgbG9nZ2VyLmluZm8oYENyZWF0ZSBuZXcgY2xpZW50OiAke3BhcnNlV2Vic29ja2V0LmNsaWVudElkfWApO1xuICAgIGNsaWVudC5wdXNoQ29ubmVjdCgpO1xuICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMoe1xuICAgICAgZXZlbnQ6ICdjb25uZWN0JyxcbiAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemVcbiAgICB9KTtcbiAgfVxuXG4gIF9oYXNNYXN0ZXJLZXkocmVxdWVzdDogYW55LCB2YWxpZEtleVBhaXJzOiBhbnkpOiBib29sZWFuIHtcbiAgICBpZighdmFsaWRLZXlQYWlycyB8fCB2YWxpZEtleVBhaXJzLnNpemUgPT0gMCB8fFxuICAgICAgIXZhbGlkS2V5UGFpcnMuaGFzKFwibWFzdGVyS2V5XCIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmKCFyZXF1ZXN0IHx8ICFyZXF1ZXN0Lmhhc093blByb3BlcnR5KFwibWFzdGVyS2V5XCIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiByZXF1ZXN0Lm1hc3RlcktleSA9PT0gdmFsaWRLZXlQYWlycy5nZXQoXCJtYXN0ZXJLZXlcIik7XG4gIH1cblxuICBfdmFsaWRhdGVLZXlzKHJlcXVlc3Q6IGFueSwgdmFsaWRLZXlQYWlyczogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKCF2YWxpZEtleVBhaXJzIHx8IHZhbGlkS2V5UGFpcnMuc2l6ZSA9PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHNlY3JldF0gb2YgdmFsaWRLZXlQYWlycykge1xuICAgICAgaWYgKCFyZXF1ZXN0W2tleV0gfHwgcmVxdWVzdFtrZXldICE9PSBzZWNyZXQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gaXNWYWxpZDtcbiAgfVxuXG4gIF9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQ6IGFueSwgcmVxdWVzdDogYW55KTogYW55IHtcbiAgICAvLyBJZiB3ZSBjYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIHJldHVybiBlcnJvciB0byBjbGllbnRcbiAgICBpZiAoIXBhcnNlV2Vic29ja2V0Lmhhc093blByb3BlcnR5KCdjbGllbnRJZCcpKSB7XG4gICAgICBDbGllbnQucHVzaEVycm9yKHBhcnNlV2Vic29ja2V0LCAyLCAnQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCBtYWtlIHN1cmUgeW91IGNvbm5lY3QgdG8gc2VydmVyIGJlZm9yZSBzdWJzY3JpYmluZycpO1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIG1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBzZXJ2ZXIgYmVmb3JlIHN1YnNjcmliaW5nJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuXG4gICAgLy8gR2V0IHN1YnNjcmlwdGlvbiBmcm9tIHN1YnNjcmlwdGlvbnMsIGNyZWF0ZSBvbmUgaWYgbmVjZXNzYXJ5XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSGFzaCA9IHF1ZXJ5SGFzaChyZXF1ZXN0LnF1ZXJ5KTtcbiAgICAvLyBBZGQgY2xhc3NOYW1lIHRvIHN1YnNjcmlwdGlvbnMgaWYgbmVjZXNzYXJ5XG4gICAgY29uc3QgY2xhc3NOYW1lID0gcmVxdWVzdC5xdWVyeS5jbGFzc05hbWU7XG4gICAgaWYgKCF0aGlzLnN1YnNjcmlwdGlvbnMuaGFzKGNsYXNzTmFtZSkpIHtcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5zZXQoY2xhc3NOYW1lLCBuZXcgTWFwKCkpO1xuICAgIH1cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgbGV0IHN1YnNjcmlwdGlvbjtcbiAgICBpZiAoY2xhc3NTdWJzY3JpcHRpb25zLmhhcyhzdWJzY3JpcHRpb25IYXNoKSkge1xuICAgICAgc3Vic2NyaXB0aW9uID0gY2xhc3NTdWJzY3JpcHRpb25zLmdldChzdWJzY3JpcHRpb25IYXNoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbihjbGFzc05hbWUsIHJlcXVlc3QucXVlcnkud2hlcmUsIHN1YnNjcmlwdGlvbkhhc2gpO1xuICAgICAgY2xhc3NTdWJzY3JpcHRpb25zLnNldChzdWJzY3JpcHRpb25IYXNoLCBzdWJzY3JpcHRpb24pO1xuICAgIH1cblxuICAgIC8vIEFkZCBzdWJzY3JpcHRpb25JbmZvIHRvIGNsaWVudFxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSB7XG4gICAgICBzdWJzY3JpcHRpb246IHN1YnNjcmlwdGlvblxuICAgIH07XG4gICAgLy8gQWRkIHNlbGVjdGVkIGZpZWxkcyBhbmQgc2Vzc2lvblRva2VuIGZvciB0aGlzIHN1YnNjcmlwdGlvbiBpZiBuZWNlc3NhcnlcbiAgICBpZiAocmVxdWVzdC5xdWVyeS5maWVsZHMpIHtcbiAgICAgIHN1YnNjcmlwdGlvbkluZm8uZmllbGRzID0gcmVxdWVzdC5xdWVyeS5maWVsZHM7XG4gICAgfVxuICAgIGlmIChyZXF1ZXN0LnNlc3Npb25Ub2tlbikge1xuICAgICAgc3Vic2NyaXB0aW9uSW5mby5zZXNzaW9uVG9rZW4gPSByZXF1ZXN0LnNlc3Npb25Ub2tlbjtcbiAgICB9XG4gICAgY2xpZW50LmFkZFN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdC5yZXF1ZXN0SWQsIHN1YnNjcmlwdGlvbkluZm8pO1xuXG4gICAgLy8gQWRkIGNsaWVudElkIHRvIHN1YnNjcmlwdGlvblxuICAgIHN1YnNjcmlwdGlvbi5hZGRDbGllbnRTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIHJlcXVlc3QucmVxdWVzdElkKTtcblxuICAgIGNsaWVudC5wdXNoU3Vic2NyaWJlKHJlcXVlc3QucmVxdWVzdElkKTtcblxuICAgIGxvZ2dlci52ZXJib3NlKGBDcmVhdGUgY2xpZW50ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9IG5ldyBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YCk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgY2xpZW50IG51bWJlcjogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG4gICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICBldmVudDogJ3N1YnNjcmliZScsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplXG4gICAgfSk7XG4gIH1cblxuICBfaGFuZGxlVXBkYXRlU3Vic2NyaXB0aW9uKHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IGFueSB7XG4gICAgdGhpcy5faGFuZGxlVW5zdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QsIGZhbHNlKTtcbiAgICB0aGlzLl9oYW5kbGVTdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICB9XG5cbiAgX2hhbmRsZVVuc3Vic2NyaWJlKHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSwgbm90aWZ5Q2xpZW50OiBib29sID0gdHJ1ZSk6IGFueSB7XG4gICAgLy8gSWYgd2UgY2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCByZXR1cm4gZXJyb3IgdG8gY2xpZW50XG4gICAgaWYgKCFwYXJzZVdlYnNvY2tldC5oYXNPd25Qcm9wZXJ0eSgnY2xpZW50SWQnKSkge1xuICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMiwgJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCwgbWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZycpO1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIG1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBzZXJ2ZXIgYmVmb3JlIHVuc3Vic2NyaWJpbmcnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVxdWVzdElkID0gcmVxdWVzdC5yZXF1ZXN0SWQ7XG4gICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzLmdldChwYXJzZVdlYnNvY2tldC5jbGllbnRJZCk7XG4gICAgaWYgKHR5cGVvZiBjbGllbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBDbGllbnQucHVzaEVycm9yKHBhcnNlV2Vic29ja2V0LCAyLCAnQ2Fubm90IGZpbmQgY2xpZW50IHdpdGggY2xpZW50SWQgJyAgKyBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCArXG4gICAgICAgICcuIE1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBsaXZlIHF1ZXJ5IHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZy4nKTtcbiAgICAgIGxvZ2dlci5lcnJvcignQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50ICcgKyBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSW5mbyA9IGNsaWVudC5nZXRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3RJZCk7XG4gICAgaWYgKHR5cGVvZiBzdWJzY3JpcHRpb25JbmZvID09PSAndW5kZWZpbmVkJykge1xuICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMiwgJ0Nhbm5vdCBmaW5kIHN1YnNjcmlwdGlvbiB3aXRoIGNsaWVudElkICcgICsgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQgK1xuICAgICAgICAnIHN1YnNjcmlwdGlvbklkICcgKyByZXF1ZXN0SWQgKyAnLiBNYWtlIHN1cmUgeW91IHN1YnNjcmliZSB0byBsaXZlIHF1ZXJ5IHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZy4nKTtcbiAgICAgIGxvZ2dlci5lcnJvcignQ2FuIG5vdCBmaW5kIHN1YnNjcmlwdGlvbiB3aXRoIGNsaWVudElkICcgKyBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCArICAnIHN1YnNjcmlwdGlvbklkICcgKyByZXF1ZXN0SWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFJlbW92ZSBzdWJzY3JpcHRpb24gZnJvbSBjbGllbnRcbiAgICBjbGllbnQuZGVsZXRlU3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIC8vIFJlbW92ZSBjbGllbnQgZnJvbSBzdWJzY3JpcHRpb25cbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBzdWJzY3JpcHRpb25JbmZvLnN1YnNjcmlwdGlvbjtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBzdWJzY3JpcHRpb24uY2xhc3NOYW1lO1xuICAgIHN1YnNjcmlwdGlvbi5kZWxldGVDbGllbnRTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIHJlcXVlc3RJZCk7XG4gICAgLy8gSWYgdGhlcmUgaXMgbm8gY2xpZW50IHdoaWNoIGlzIHN1YnNjcmliaW5nIHRoaXMgc3Vic2NyaXB0aW9uLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgY29uc3QgY2xhc3NTdWJzY3JpcHRpb25zID0gdGhpcy5zdWJzY3JpcHRpb25zLmdldChjbGFzc05hbWUpO1xuICAgIGlmICghc3Vic2NyaXB0aW9uLmhhc1N1YnNjcmliaW5nQ2xpZW50KCkpIHtcbiAgICAgIGNsYXNzU3Vic2NyaXB0aW9ucy5kZWxldGUoc3Vic2NyaXB0aW9uLmhhc2gpO1xuICAgIH1cbiAgICAvLyBJZiB0aGVyZSBpcyBubyBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MsIHJlbW92ZSBpdCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICBpZiAoY2xhc3NTdWJzY3JpcHRpb25zLnNpemUgPT09IDApIHtcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5kZWxldGUoY2xhc3NOYW1lKTtcbiAgICB9XG4gICAgcnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyh7XG4gICAgICBldmVudDogJ3Vuc3Vic2NyaWJlJyxcbiAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemVcbiAgICB9KTtcblxuICAgIGlmICghbm90aWZ5Q2xpZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY2xpZW50LnB1c2hVbnN1YnNjcmliZShyZXF1ZXN0LnJlcXVlc3RJZCk7XG5cbiAgICBsb2dnZXIudmVyYm9zZShgRGVsZXRlIGNsaWVudDogJHtwYXJzZVdlYnNvY2tldC5jbGllbnRJZH0gfCBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YCk7XG4gIH1cbn1cblxuZXhwb3J0IHtcbiAgUGFyc2VMaXZlUXVlcnlTZXJ2ZXJcbn1cbiJdfQ==
|
|
856
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdHYiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9ub2RlIiwiX1N1YnNjcmlwdGlvbiIsIl9DbGllbnQiLCJfUGFyc2VXZWJTb2NrZXRTZXJ2ZXIiLCJfbG9nZ2VyIiwiX1JlcXVlc3RTY2hlbWEiLCJfUXVlcnlUb29scyIsIl9QYXJzZVB1YlN1YiIsIl9TY2hlbWFDb250cm9sbGVyIiwiX2xvZGFzaCIsIl91dWlkIiwiX3RyaWdnZXJzIiwiX0F1dGgiLCJfQ29udHJvbGxlcnMiLCJfbHJ1Q2FjaGUiLCJfVXNlcnNSb3V0ZXIiLCJfRGF0YWJhc2VDb250cm9sbGVyIiwiX3V0aWwiLCJfZGVlcGNvcHkiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJQYXJzZUxpdmVRdWVyeVNlcnZlciIsImNvbnN0cnVjdG9yIiwic2VydmVyIiwiY29uZmlnIiwicGFyc2VTZXJ2ZXJDb25maWciLCJjbGllbnRzIiwiTWFwIiwic3Vic2NyaXB0aW9ucyIsImFwcElkIiwiUGFyc2UiLCJhcHBsaWNhdGlvbklkIiwibWFzdGVyS2V5Iiwia2V5UGFpcnMiLCJrZXkiLCJPYmplY3QiLCJrZXlzIiwic2V0IiwibG9nZ2VyIiwidmVyYm9zZSIsImRpc2FibGVTaW5nbGVJbnN0YW5jZSIsInNlcnZlclVSTCIsImluaXRpYWxpemUiLCJqYXZhU2NyaXB0S2V5IiwiY2FjaGVDb250cm9sbGVyIiwiZ2V0Q2FjaGVDb250cm9sbGVyIiwiY2FjaGVUaW1lb3V0IiwiYXV0aENhY2hlIiwiTFJVIiwibWF4IiwidHRsIiwicGFyc2VXZWJTb2NrZXRTZXJ2ZXIiLCJQYXJzZVdlYlNvY2tldFNlcnZlciIsInBhcnNlV2Vic29ja2V0IiwiX29uQ29ubmVjdCIsInN1YnNjcmliZXIiLCJQYXJzZVB1YlN1YiIsImNyZWF0ZVN1YnNjcmliZXIiLCJjb25uZWN0IiwiaXNPcGVuIiwiUHJvbWlzZSIsInJlc29sdmUiLCJfY3JlYXRlU3Vic2NyaWJlcnMiLCJzaHV0ZG93biIsImFsbCIsInZhbHVlcyIsIm1hcCIsImNsaWVudCIsInBhcnNlV2ViU29ja2V0Iiwid3MiLCJjbG9zZSIsIkFycmF5IiwiZnJvbSIsInVuc3Vic2NyaWJlIiwicXVpdCIsImVyciIsImVycm9yIiwibWVzc2FnZVJlY2lldmVkIiwiY2hhbm5lbCIsIm1lc3NhZ2VTdHIiLCJtZXNzYWdlIiwiSlNPTiIsInBhcnNlIiwiX2NsZWFyQ2FjaGVkUm9sZXMiLCJ1c2VySWQiLCJfaW5mbGF0ZVBhcnNlT2JqZWN0IiwiX29uQWZ0ZXJTYXZlIiwiX29uQWZ0ZXJEZWxldGUiLCJvbiIsImZpZWxkIiwic3Vic2NyaWJlIiwiY3VycmVudFBhcnNlT2JqZWN0IiwiVXNlclJvdXRlciIsInJlbW92ZUhpZGRlblByb3BlcnRpZXMiLCJjbGFzc05hbWUiLCJwYXJzZU9iamVjdCIsIl9maW5pc2hGZXRjaCIsIm9yaWdpbmFsUGFyc2VPYmplY3QiLCJkZWxldGVkUGFyc2VPYmplY3QiLCJ0b0pTT04iLCJjbGFzc0xldmVsUGVybWlzc2lvbnMiLCJpZCIsInNpemUiLCJjbGFzc1N1YnNjcmlwdGlvbnMiLCJnZXQiLCJkZWJ1ZyIsInN1YnNjcmlwdGlvbiIsImlzU3Vic2NyaXB0aW9uTWF0Y2hlZCIsIl9tYXRjaGVzU3Vic2NyaXB0aW9uIiwiY2xpZW50SWQiLCJyZXF1ZXN0SWRzIiwiXyIsImVudHJpZXMiLCJjbGllbnRSZXF1ZXN0SWRzIiwiZm9yRWFjaCIsInJlcXVlc3RJZCIsImFjbCIsImdldEFDTCIsIm9wIiwiX2dldENMUE9wZXJhdGlvbiIsInF1ZXJ5IiwicmVzIiwiX21hdGNoZXNDTFAiLCJpc01hdGNoZWQiLCJfbWF0Y2hlc0FDTCIsImV2ZW50Iiwic2Vzc2lvblRva2VuIiwib2JqZWN0IiwidXNlTWFzdGVyS2V5IiwiaGFzTWFzdGVyS2V5IiwiaW5zdGFsbGF0aW9uSWQiLCJzZW5kRXZlbnQiLCJ0cmlnZ2VyIiwiZ2V0VHJpZ2dlciIsImF1dGgiLCJnZXRBdXRoRnJvbUNsaWVudCIsInVzZXIiLCJmcm9tSlNPTiIsInJ1blRyaWdnZXIiLCJ0b0pTT053aXRoT2JqZWN0cyIsIl9maWx0ZXJTZW5zaXRpdmVEYXRhIiwicHVzaERlbGV0ZSIsInJlc29sdmVFcnJvciIsIkNsaWVudCIsInB1c2hFcnJvciIsImNvZGUiLCJzdHJpbmdpZnkiLCJpc09yaWdpbmFsU3Vic2NyaXB0aW9uTWF0Y2hlZCIsImlzQ3VycmVudFN1YnNjcmlwdGlvbk1hdGNoZWQiLCJvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSIsIm9yaWdpbmFsQUNMIiwiY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSIsImN1cnJlbnRBQ0wiLCJpc09yaWdpbmFsTWF0Y2hlZCIsImlzQ3VycmVudE1hdGNoZWQiLCJoYXNoIiwidHlwZSIsIndhdGNoRmllbGRzQ2hhbmdlZCIsIl9jaGVja1dhdGNoRmllbGRzIiwib3JpZ2luYWwiLCJmdW5jdGlvbk5hbWUiLCJjaGFyQXQiLCJ0b1VwcGVyQ2FzZSIsInNsaWNlIiwicmVxdWVzdCIsInR2NCIsInZhbGlkYXRlIiwiUmVxdWVzdFNjaGVtYSIsIl9oYW5kbGVDb25uZWN0IiwiX2hhbmRsZVN1YnNjcmliZSIsIl9oYW5kbGVVcGRhdGVTdWJzY3JpcHRpb24iLCJfaGFuZGxlVW5zdWJzY3JpYmUiLCJpbmZvIiwiaGFzIiwicnVuTGl2ZVF1ZXJ5RXZlbnRIYW5kbGVycyIsImRlbGV0ZSIsInN1YnNjcmlwdGlvbkluZm8iLCJzdWJzY3JpcHRpb25JbmZvcyIsImRlbGV0ZUNsaWVudFN1YnNjcmlwdGlvbiIsImhhc1N1YnNjcmliaW5nQ2xpZW50IiwibWF0Y2hlc1F1ZXJ5IiwiZGVlcGNvcHkiLCJ2YWxpZFRva2VucyIsIlF1ZXJ5IiwiU2Vzc2lvbiIsImVxdWFsVG8iLCJVc2VyIiwiY3JlYXRlV2l0aG91dERhdGEiLCJmaW5kIiwidG9rZW4iLCJhdXRoUHJvbWlzZSIsImF1dGgxIiwiYXV0aDIiLCJnZXRBdXRoRm9yU2Vzc2lvblRva2VuIiwiY2xlYXJSb2xlQ2FjaGUiLCJmcm9tQ2FjaGUiLCJ0aGVuIiwiY2F0Y2giLCJyZXN1bHQiLCJFcnJvciIsIklOVkFMSURfU0VTU0lPTl9UT0tFTiIsImdldFN1YnNjcmlwdGlvbkluZm8iLCJhY2xHcm91cCIsInB1c2giLCJTY2hlbWFDb250cm9sbGVyIiwidmFsaWRhdGVQZXJtaXNzaW9uIiwiY2xpZW50QXV0aCIsImZpbHRlciIsIm9iaiIsInByb3RlY3RlZEZpZWxkcyIsImlzQXJyYXkiLCJnZXREYXRhYmFzZUNvbnRyb2xsZXIiLCJhZGRQcm90ZWN0ZWRGaWVsZHMiLCJEYXRhYmFzZUNvbnRyb2xsZXIiLCJmaWx0ZXJTZW5zaXRpdmVEYXRhIiwibGVuZ3RoIiwib2JqZWN0SWQiLCJfdmVyaWZ5QUNMIiwiaXNTdWJzY3JpcHRpb25TZXNzaW9uVG9rZW5NYXRjaGVkIiwiZ2V0UmVhZEFjY2VzcyIsImFjbF9oYXNfcm9sZXMiLCJwZXJtaXNzaW9uc0J5SWQiLCJzb21lIiwic3RhcnRzV2l0aCIsInJvbGVOYW1lcyIsImdldFVzZXJSb2xlcyIsInJvbGUiLCJnZXRTZXNzaW9uRnJvbUNsaWVudCIsIndhdGNoIiwiaXNEZWVwU3RyaWN0RXF1YWwiLCJnZXRQdWJsaWNSZWFkQWNjZXNzIiwic3Vic2NyaXB0aW9uVG9rZW4iLCJjbGllbnRTZXNzaW9uVG9rZW4iLCJfdmFsaWRhdGVLZXlzIiwiX2hhc01hc3RlcktleSIsInV1aWR2NCIsInJlcSIsInVuZGVmaW5lZCIsInB1c2hDb25uZWN0IiwidmFsaWRLZXlQYWlycyIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImlzVmFsaWQiLCJzZWNyZXQiLCJhdXRoQ2FsbGVkIiwicGFyc2VRdWVyeSIsIndpdGhKU09OIiwid2hlcmUiLCJ0b1BvaW50ZXIiLCJtYXN0ZXIiLCJzdWJzY3JpcHRpb25IYXNoIiwicXVlcnlIYXNoIiwiU3Vic2NyaXB0aW9uIiwic3BsaXQiLCJhZGRTdWJzY3JpcHRpb25JbmZvIiwiYWRkQ2xpZW50U3Vic2NyaXB0aW9uIiwicHVzaFN1YnNjcmliZSIsIm5vdGlmeUNsaWVudCIsImRlbGV0ZVN1YnNjcmlwdGlvbkluZm8iLCJwdXNoVW5zdWJzY3JpYmUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL0xpdmVRdWVyeS9QYXJzZUxpdmVRdWVyeVNlcnZlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHY0IGZyb20gJ3R2NCc7XG5pbXBvcnQgUGFyc2UgZnJvbSAncGFyc2Uvbm9kZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICcuL1N1YnNjcmlwdGlvbic7XG5pbXBvcnQgeyBDbGllbnQgfSBmcm9tICcuL0NsaWVudCc7XG5pbXBvcnQgeyBQYXJzZVdlYlNvY2tldFNlcnZlciB9IGZyb20gJy4vUGFyc2VXZWJTb2NrZXRTZXJ2ZXInO1xuLy8gQHRzLWlnbm9yZVxuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IFJlcXVlc3RTY2hlbWEgZnJvbSAnLi9SZXF1ZXN0U2NoZW1hJztcbmltcG9ydCB7IG1hdGNoZXNRdWVyeSwgcXVlcnlIYXNoIH0gZnJvbSAnLi9RdWVyeVRvb2xzJztcbmltcG9ydCB7IFBhcnNlUHViU3ViIH0gZnJvbSAnLi9QYXJzZVB1YlN1Yic7XG5pbXBvcnQgU2NoZW1hQ29udHJvbGxlciBmcm9tICcuLi9Db250cm9sbGVycy9TY2hlbWFDb250cm9sbGVyJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyB2NCBhcyB1dWlkdjQgfSBmcm9tICd1dWlkJztcbmltcG9ydCB7XG4gIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMsXG4gIGdldFRyaWdnZXIsXG4gIHJ1blRyaWdnZXIsXG4gIHJlc29sdmVFcnJvcixcbiAgdG9KU09Od2l0aE9iamVjdHMsXG59IGZyb20gJy4uL3RyaWdnZXJzJztcbmltcG9ydCB7IGdldEF1dGhGb3JTZXNzaW9uVG9rZW4sIEF1dGggfSBmcm9tICcuLi9BdXRoJztcbmltcG9ydCB7IGdldENhY2hlQ29udHJvbGxlciwgZ2V0RGF0YWJhc2VDb250cm9sbGVyIH0gZnJvbSAnLi4vQ29udHJvbGxlcnMnO1xuaW1wb3J0IHsgTFJVQ2FjaGUgYXMgTFJVIH0gZnJvbSAnbHJ1LWNhY2hlJztcbmltcG9ydCBVc2VyUm91dGVyIGZyb20gJy4uL1JvdXRlcnMvVXNlcnNSb3V0ZXInO1xuaW1wb3J0IERhdGFiYXNlQ29udHJvbGxlciBmcm9tICcuLi9Db250cm9sbGVycy9EYXRhYmFzZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgaXNEZWVwU3RyaWN0RXF1YWwgfSBmcm9tICd1dGlsJztcbmltcG9ydCBkZWVwY29weSBmcm9tICdkZWVwY29weSc7XG5cbmNsYXNzIFBhcnNlTGl2ZVF1ZXJ5U2VydmVyIHtcbiAgc2VydmVyOiBhbnk7XG4gIGNvbmZpZzogYW55O1xuICBjbGllbnRzOiBNYXA8c3RyaW5nLCBhbnk+O1xuICAvLyBjbGFzc05hbWUgLT4gKHF1ZXJ5SGFzaCAtPiBzdWJzY3JpcHRpb24pXG4gIHN1YnNjcmlwdGlvbnM6IE1hcDxzdHJpbmcsIGFueT47XG4gIHBhcnNlV2ViU29ja2V0U2VydmVyOiBhbnk7XG4gIGtleVBhaXJzOiBhbnk7XG4gIC8vIFRoZSBzdWJzY3JpYmVyIHdlIHVzZSB0byBnZXQgb2JqZWN0IHVwZGF0ZSBmcm9tIHB1Ymxpc2hlclxuICBzdWJzY3JpYmVyOiBhbnk7XG4gIGF1dGhDYWNoZTogYW55O1xuICBjYWNoZUNvbnRyb2xsZXI6IGFueTtcblxuICBjb25zdHJ1Y3RvcihzZXJ2ZXI6IGFueSwgY29uZmlnOiBhbnkgPSB7fSwgcGFyc2VTZXJ2ZXJDb25maWc6IGFueSA9IHt9KSB7XG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgdGhpcy5jbGllbnRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcblxuICAgIGNvbmZpZy5hcHBJZCA9IGNvbmZpZy5hcHBJZCB8fCBQYXJzZS5hcHBsaWNhdGlvbklkO1xuICAgIGNvbmZpZy5tYXN0ZXJLZXkgPSBjb25maWcubWFzdGVyS2V5IHx8IFBhcnNlLm1hc3RlcktleTtcblxuICAgIC8vIFN0b3JlIGtleXMsIGNvbnZlcnQgb2JqIHRvIG1hcFxuICAgIGNvbnN0IGtleVBhaXJzID0gY29uZmlnLmtleVBhaXJzIHx8IHt9O1xuICAgIHRoaXMua2V5UGFpcnMgPSBuZXcgTWFwKCk7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoa2V5UGFpcnMpKSB7XG4gICAgICB0aGlzLmtleVBhaXJzLnNldChrZXksIGtleVBhaXJzW2tleV0pO1xuICAgIH1cbiAgICBsb2dnZXIudmVyYm9zZSgnU3VwcG9ydCBrZXkgcGFpcnMnLCB0aGlzLmtleVBhaXJzKTtcblxuICAgIC8vIEluaXRpYWxpemUgUGFyc2VcbiAgICBQYXJzZS5PYmplY3QuZGlzYWJsZVNpbmdsZUluc3RhbmNlKCk7XG4gICAgY29uc3Qgc2VydmVyVVJMID0gY29uZmlnLnNlcnZlclVSTCB8fCBQYXJzZS5zZXJ2ZXJVUkw7XG4gICAgUGFyc2Uuc2VydmVyVVJMID0gc2VydmVyVVJMO1xuICAgIFBhcnNlLmluaXRpYWxpemUoY29uZmlnLmFwcElkLCBQYXJzZS5qYXZhU2NyaXB0S2V5LCBjb25maWcubWFzdGVyS2V5KTtcblxuICAgIC8vIFRoZSBjYWNoZSBjb250cm9sbGVyIGlzIGEgcHJvcGVyIGNhY2hlIGNvbnRyb2xsZXJcbiAgICAvLyB3aXRoIGFjY2VzcyB0byBVc2VyIGFuZCBSb2xlc1xuICAgIHRoaXMuY2FjaGVDb250cm9sbGVyID0gZ2V0Q2FjaGVDb250cm9sbGVyKHBhcnNlU2VydmVyQ29uZmlnKTtcblxuICAgIGNvbmZpZy5jYWNoZVRpbWVvdXQgPSBjb25maWcuY2FjaGVUaW1lb3V0IHx8IDUgKiAxMDAwOyAvLyA1c1xuXG4gICAgLy8gVGhpcyBhdXRoIGNhY2hlIHN0b3JlcyB0aGUgcHJvbWlzZXMgZm9yIGVhY2ggYXV0aCByZXNvbHV0aW9uLlxuICAgIC8vIFRoZSBtYWluIGJlbmVmaXQgaXMgdG8gYmUgYWJsZSB0byByZXVzZSB0aGUgc2FtZSB1c2VyIC8gc2Vzc2lvbiB0b2tlbiByZXNvbHV0aW9uLlxuICAgIHRoaXMuYXV0aENhY2hlID0gbmV3IExSVSh7XG4gICAgICBtYXg6IDUwMCwgLy8gNTAwIGNvbmN1cnJlbnRcbiAgICAgIHR0bDogY29uZmlnLmNhY2hlVGltZW91dCxcbiAgICB9KTtcbiAgICAvLyBJbml0aWFsaXplIHdlYnNvY2tldCBzZXJ2ZXJcbiAgICB0aGlzLnBhcnNlV2ViU29ja2V0U2VydmVyID0gbmV3IFBhcnNlV2ViU29ja2V0U2VydmVyKFxuICAgICAgc2VydmVyLFxuICAgICAgcGFyc2VXZWJzb2NrZXQgPT4gdGhpcy5fb25Db25uZWN0KHBhcnNlV2Vic29ja2V0KSxcbiAgICAgIGNvbmZpZ1xuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpYmVyID0gUGFyc2VQdWJTdWIuY3JlYXRlU3Vic2NyaWJlcihjb25maWcpO1xuICAgIGlmICghdGhpcy5zdWJzY3JpYmVyLmNvbm5lY3QpIHtcbiAgICAgIHRoaXMuY29ubmVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGNvbm5lY3QoKSB7XG4gICAgaWYgKHRoaXMuc3Vic2NyaWJlci5pc09wZW4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB0aGlzLnN1YnNjcmliZXIuY29ubmVjdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKHRoaXMuc3Vic2NyaWJlci5jb25uZWN0KCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN1YnNjcmliZXIuaXNPcGVuID0gdHJ1ZTtcbiAgICB9XG4gICAgdGhpcy5fY3JlYXRlU3Vic2NyaWJlcnMoKTtcbiAgfVxuXG4gIGFzeW5jIHNodXRkb3duKCkge1xuICAgIGlmICh0aGlzLnN1YnNjcmliZXIuaXNPcGVuKSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIC4uLlsuLi50aGlzLmNsaWVudHMudmFsdWVzKCldLm1hcChjbGllbnQgPT4gY2xpZW50LnBhcnNlV2ViU29ja2V0LndzLmNsb3NlKCkpLFxuICAgICAgICB0aGlzLnBhcnNlV2ViU29ja2V0U2VydmVyLmNsb3NlPy4oKSxcbiAgICAgICAgLi4uQXJyYXkuZnJvbSh0aGlzLnN1YnNjcmliZXIuc3Vic2NyaXB0aW9ucz8ua2V5cygpIHx8IFtdKS5tYXAoa2V5ID0+XG4gICAgICAgICAgdGhpcy5zdWJzY3JpYmVyLnVuc3Vic2NyaWJlKGtleSlcbiAgICAgICAgKSxcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVyLmNsb3NlPy4oKSxcbiAgICAgIF0pO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHRoaXMuc3Vic2NyaWJlci5xdWl0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnN1YnNjcmliZXIucXVpdCgpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcignUHViU3ViQWRhcHRlciBlcnJvciBvbiBzaHV0ZG93bicsIHsgZXJyb3I6IGVyciB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdWJzY3JpYmVyLmlzT3BlbiA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIF9jcmVhdGVTdWJzY3JpYmVycygpIHtcbiAgICBjb25zdCBtZXNzYWdlUmVjaWV2ZWQgPSAoY2hhbm5lbCwgbWVzc2FnZVN0cikgPT4ge1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoJ1N1YnNjcmliZSBtZXNzYWdlICVqJywgbWVzc2FnZVN0cik7XG4gICAgICBsZXQgbWVzc2FnZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG1lc3NhZ2VTdHIpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ3VuYWJsZSB0byBwYXJzZSBtZXNzYWdlJywgbWVzc2FnZVN0ciwgZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChjaGFubmVsID09PSBQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2NsZWFyQ2FjaGUnKSB7XG4gICAgICAgIHRoaXMuX2NsZWFyQ2FjaGVkUm9sZXMobWVzc2FnZS51c2VySWQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLl9pbmZsYXRlUGFyc2VPYmplY3QobWVzc2FnZSk7XG4gICAgICBpZiAoY2hhbm5lbCA9PT0gUGFyc2UuYXBwbGljYXRpb25JZCArICdhZnRlclNhdmUnKSB7XG4gICAgICAgIHRoaXMuX29uQWZ0ZXJTYXZlKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIGlmIChjaGFubmVsID09PSBQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyRGVsZXRlJykge1xuICAgICAgICB0aGlzLl9vbkFmdGVyRGVsZXRlKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdHZXQgbWVzc2FnZSAlcyBmcm9tIHVua25vd24gY2hhbm5lbCAlaicsIG1lc3NhZ2UsIGNoYW5uZWwpO1xuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5zdWJzY3JpYmVyLm9uKCdtZXNzYWdlJywgKGNoYW5uZWwsIG1lc3NhZ2VTdHIpID0+IG1lc3NhZ2VSZWNpZXZlZChjaGFubmVsLCBtZXNzYWdlU3RyKSk7XG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiBbJ2FmdGVyU2F2ZScsICdhZnRlckRlbGV0ZScsICdjbGVhckNhY2hlJ10pIHtcbiAgICAgIGNvbnN0IGNoYW5uZWwgPSBgJHtQYXJzZS5hcHBsaWNhdGlvbklkfSR7ZmllbGR9YDtcbiAgICAgIHRoaXMuc3Vic2NyaWJlci5zdWJzY3JpYmUoY2hhbm5lbCwgbWVzc2FnZVN0ciA9PiBtZXNzYWdlUmVjaWV2ZWQoY2hhbm5lbCwgbWVzc2FnZVN0cikpO1xuICAgIH1cbiAgfVxuXG4gIC8vIE1lc3NhZ2UgaXMgdGhlIEpTT04gb2JqZWN0IGZyb20gcHVibGlzaGVyLiBNZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdCBpcyB0aGUgUGFyc2VPYmplY3QgSlNPTiBhZnRlciBjaGFuZ2VzLlxuICAvLyBNZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgaXMgdGhlIG9yaWdpbmFsIFBhcnNlT2JqZWN0IEpTT04uXG4gIF9pbmZsYXRlUGFyc2VPYmplY3QobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgLy8gSW5mbGF0ZSBtZXJnZWQgb2JqZWN0XG4gICAgY29uc3QgY3VycmVudFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3Q7XG4gICAgVXNlclJvdXRlci5yZW1vdmVIaWRkZW5Qcm9wZXJ0aWVzKGN1cnJlbnRQYXJzZU9iamVjdCk7XG4gICAgbGV0IGNsYXNzTmFtZSA9IGN1cnJlbnRQYXJzZU9iamVjdC5jbGFzc05hbWU7XG4gICAgbGV0IHBhcnNlT2JqZWN0ID0gbmV3IFBhcnNlLk9iamVjdChjbGFzc05hbWUpO1xuICAgIHBhcnNlT2JqZWN0Ll9maW5pc2hGZXRjaChjdXJyZW50UGFyc2VPYmplY3QpO1xuICAgIG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0ID0gcGFyc2VPYmplY3Q7XG4gICAgLy8gSW5mbGF0ZSBvcmlnaW5hbCBvYmplY3RcbiAgICBjb25zdCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0O1xuICAgIGlmIChvcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBVc2VyUm91dGVyLnJlbW92ZUhpZGRlblByb3BlcnRpZXMob3JpZ2luYWxQYXJzZU9iamVjdCk7XG4gICAgICBjbGFzc05hbWUgPSBvcmlnaW5hbFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICAgIHBhcnNlT2JqZWN0ID0gbmV3IFBhcnNlLk9iamVjdChjbGFzc05hbWUpO1xuICAgICAgcGFyc2VPYmplY3QuX2ZpbmlzaEZldGNoKG9yaWdpbmFsUGFyc2VPYmplY3QpO1xuICAgICAgbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0ID0gcGFyc2VPYmplY3Q7XG4gICAgfVxuICB9XG5cbiAgLy8gTWVzc2FnZSBpcyB0aGUgSlNPTiBvYmplY3QgZnJvbSBwdWJsaXNoZXIgYWZ0ZXIgaW5mbGF0ZWQuIE1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0IGlzIHRoZSBQYXJzZU9iamVjdCBhZnRlciBjaGFuZ2VzLlxuICAvLyBNZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QgaXMgdGhlIG9yaWdpbmFsIFBhcnNlT2JqZWN0LlxuICBhc3luYyBfb25BZnRlckRlbGV0ZShtZXNzYWdlOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyRGVsZXRlIGlzIHRyaWdnZXJlZCcpO1xuXG4gICAgbGV0IGRlbGV0ZWRQYXJzZU9iamVjdCA9IG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0LnRvSlNPTigpO1xuICAgIGNvbnN0IGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyA9IG1lc3NhZ2UuY2xhc3NMZXZlbFBlcm1pc3Npb25zO1xuICAgIGNvbnN0IGNsYXNzTmFtZSA9IGRlbGV0ZWRQYXJzZU9iamVjdC5jbGFzc05hbWU7XG4gICAgbG9nZ2VyLnZlcmJvc2UoJ0NsYXNzTmFtZTogJWogfCBPYmplY3RJZDogJXMnLCBjbGFzc05hbWUsIGRlbGV0ZWRQYXJzZU9iamVjdC5pZCk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgY2xpZW50IG51bWJlciA6ICVkJywgdGhpcy5jbGllbnRzLnNpemUpO1xuXG4gICAgY29uc3QgY2xhc3NTdWJzY3JpcHRpb25zID0gdGhpcy5zdWJzY3JpcHRpb25zLmdldChjbGFzc05hbWUpO1xuICAgIGlmICh0eXBlb2YgY2xhc3NTdWJzY3JpcHRpb25zID09PSAndW5kZWZpbmVkJykge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDYW4gbm90IGZpbmQgc3Vic2NyaXB0aW9ucyB1bmRlciB0aGlzIGNsYXNzICcgKyBjbGFzc05hbWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3Vic2NyaXB0aW9uIG9mIGNsYXNzU3Vic2NyaXB0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgaXNTdWJzY3JpcHRpb25NYXRjaGVkID0gdGhpcy5fbWF0Y2hlc1N1YnNjcmlwdGlvbihkZWxldGVkUGFyc2VPYmplY3QsIHN1YnNjcmlwdGlvbik7XG4gICAgICBpZiAoIWlzU3Vic2NyaXB0aW9uTWF0Y2hlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgW2NsaWVudElkLCByZXF1ZXN0SWRzXSBvZiBfLmVudHJpZXMoc3Vic2NyaXB0aW9uLmNsaWVudFJlcXVlc3RJZHMpKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWQpO1xuICAgICAgICBpZiAodHlwZW9mIGNsaWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICByZXF1ZXN0SWRzLmZvckVhY2goYXN5bmMgcmVxdWVzdElkID0+IHtcbiAgICAgICAgICBjb25zdCBhY2wgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdC5nZXRBQ0woKTtcbiAgICAgICAgICAvLyBDaGVjayBDTFBcbiAgICAgICAgICBjb25zdCBvcCA9IHRoaXMuX2dldENMUE9wZXJhdGlvbihzdWJzY3JpcHRpb24ucXVlcnkpO1xuICAgICAgICAgIGxldCByZXM6IGFueSA9IHt9O1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9tYXRjaGVzQ0xQKFxuICAgICAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgICAgIG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgICBjbGllbnQsXG4gICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgb3BcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBpc01hdGNoZWQgPSBhd2FpdCB0aGlzLl9tYXRjaGVzQUNMKGFjbCwgY2xpZW50LCByZXF1ZXN0SWQpO1xuICAgICAgICAgICAgaWYgKCFpc01hdGNoZWQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMgPSB7XG4gICAgICAgICAgICAgIGV2ZW50OiAnZGVsZXRlJyxcbiAgICAgICAgICAgICAgc2Vzc2lvblRva2VuOiBjbGllbnQuc2Vzc2lvblRva2VuLFxuICAgICAgICAgICAgICBvYmplY3Q6IGRlbGV0ZWRQYXJzZU9iamVjdCxcbiAgICAgICAgICAgICAgY2xpZW50czogdGhpcy5jbGllbnRzLnNpemUsXG4gICAgICAgICAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgICAgICAgICB1c2VNYXN0ZXJLZXk6IGNsaWVudC5oYXNNYXN0ZXJLZXksXG4gICAgICAgICAgICAgIGluc3RhbGxhdGlvbklkOiBjbGllbnQuaW5zdGFsbGF0aW9uSWQsXG4gICAgICAgICAgICAgIHNlbmRFdmVudDogdHJ1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCB0cmlnZ2VyID0gZ2V0VHJpZ2dlcihjbGFzc05hbWUsICdhZnRlckV2ZW50JywgUGFyc2UuYXBwbGljYXRpb25JZCk7XG4gICAgICAgICAgICBpZiAodHJpZ2dlcikge1xuICAgICAgICAgICAgICBjb25zdCBhdXRoID0gYXdhaXQgdGhpcy5nZXRBdXRoRnJvbUNsaWVudChjbGllbnQsIHJlcXVlc3RJZCk7XG4gICAgICAgICAgICAgIGlmIChhdXRoICYmIGF1dGgudXNlcikge1xuICAgICAgICAgICAgICAgIHJlcy51c2VyID0gYXV0aC51c2VyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChyZXMub2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmVzLm9iamVjdCA9IFBhcnNlLk9iamVjdC5mcm9tSlNPTihyZXMub2JqZWN0KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBhd2FpdCBydW5UcmlnZ2VyKHRyaWdnZXIsIGBhZnRlckV2ZW50LiR7Y2xhc3NOYW1lfWAsIHJlcywgYXV0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXJlcy5zZW5kRXZlbnQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlcy5vYmplY3QgJiYgdHlwZW9mIHJlcy5vYmplY3QudG9KU09OID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgIGRlbGV0ZWRQYXJzZU9iamVjdCA9IHRvSlNPTndpdGhPYmplY3RzKHJlcy5vYmplY3QsIHJlcy5vYmplY3QuY2xhc3NOYW1lIHx8IGNsYXNzTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9maWx0ZXJTZW5zaXRpdmVEYXRhKFxuICAgICAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgICAgIHJlcyxcbiAgICAgICAgICAgICAgY2xpZW50LFxuICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgIG9wLFxuICAgICAgICAgICAgICBzdWJzY3JpcHRpb24ucXVlcnlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjbGllbnQucHVzaERlbGV0ZShyZXF1ZXN0SWQsIGRlbGV0ZWRQYXJzZU9iamVjdCk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSByZXNvbHZlRXJyb3IoZSk7XG4gICAgICAgICAgICBDbGllbnQucHVzaEVycm9yKGNsaWVudC5wYXJzZVdlYlNvY2tldCwgZXJyb3IuY29kZSwgZXJyb3IubWVzc2FnZSwgZmFsc2UsIHJlcXVlc3RJZCk7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgIGBGYWlsZWQgcnVubmluZyBhZnRlckxpdmVRdWVyeUV2ZW50IG9uIGNsYXNzICR7Y2xhc3NOYW1lfSBmb3IgZXZlbnQgJHtyZXMuZXZlbnR9IHdpdGggc2Vzc2lvbiAke3Jlcy5zZXNzaW9uVG9rZW59IHdpdGg6XFxuIEVycm9yOiBgICtcbiAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShlcnJvcilcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBNZXNzYWdlIGlzIHRoZSBKU09OIG9iamVjdCBmcm9tIHB1Ymxpc2hlciBhZnRlciBpbmZsYXRlZC4gTWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QgaXMgdGhlIFBhcnNlT2JqZWN0IGFmdGVyIGNoYW5nZXMuXG4gIC8vIE1lc3NhZ2Uub3JpZ2luYWxQYXJzZU9iamVjdCBpcyB0aGUgb3JpZ2luYWwgUGFyc2VPYmplY3QuXG4gIGFzeW5jIF9vbkFmdGVyU2F2ZShtZXNzYWdlOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2dnZXIudmVyYm9zZShQYXJzZS5hcHBsaWNhdGlvbklkICsgJ2FmdGVyU2F2ZSBpcyB0cmlnZ2VyZWQnKTtcblxuICAgIGxldCBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbnVsbDtcbiAgICBpZiAobWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0KSB7XG4gICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0LnRvSlNPTigpO1xuICAgIH1cbiAgICBjb25zdCBjbGFzc0xldmVsUGVybWlzc2lvbnMgPSBtZXNzYWdlLmNsYXNzTGV2ZWxQZXJtaXNzaW9ucztcbiAgICBsZXQgY3VycmVudFBhcnNlT2JqZWN0ID0gbWVzc2FnZS5jdXJyZW50UGFyc2VPYmplY3QudG9KU09OKCk7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gY3VycmVudFBhcnNlT2JqZWN0LmNsYXNzTmFtZTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ2xhc3NOYW1lOiAlcyB8IE9iamVjdElkOiAlcycsIGNsYXNzTmFtZSwgY3VycmVudFBhcnNlT2JqZWN0LmlkKTtcbiAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBjbGllbnQgbnVtYmVyIDogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG5cbiAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgaWYgKHR5cGVvZiBjbGFzc1N1YnNjcmlwdGlvbnMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NhbiBub3QgZmluZCBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MgJyArIGNsYXNzTmFtZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3Qgc3Vic2NyaXB0aW9uIG9mIGNsYXNzU3Vic2NyaXB0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgaXNPcmlnaW5hbFN1YnNjcmlwdGlvbk1hdGNoZWQgPSB0aGlzLl9tYXRjaGVzU3Vic2NyaXB0aW9uKFxuICAgICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICAgICAgICBzdWJzY3JpcHRpb25cbiAgICAgICk7XG4gICAgICBjb25zdCBpc0N1cnJlbnRTdWJzY3JpcHRpb25NYXRjaGVkID0gdGhpcy5fbWF0Y2hlc1N1YnNjcmlwdGlvbihcbiAgICAgICAgY3VycmVudFBhcnNlT2JqZWN0LFxuICAgICAgICBzdWJzY3JpcHRpb25cbiAgICAgICk7XG4gICAgICBmb3IgKGNvbnN0IFtjbGllbnRJZCwgcmVxdWVzdElkc10gb2YgXy5lbnRyaWVzKHN1YnNjcmlwdGlvbi5jbGllbnRSZXF1ZXN0SWRzKSkge1xuICAgICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHMuZ2V0KGNsaWVudElkKTtcbiAgICAgICAgaWYgKHR5cGVvZiBjbGllbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgcmVxdWVzdElkcy5mb3JFYWNoKGFzeW5jIHJlcXVlc3RJZCA9PiB7XG4gICAgICAgICAgLy8gU2V0IG9yaWduYWwgUGFyc2VPYmplY3QgQUNMIGNoZWNraW5nIHByb21pc2UsIGlmIHRoZSBvYmplY3QgZG9lcyBub3QgbWF0Y2hcbiAgICAgICAgICAvLyBzdWJzY3JpcHRpb24sIHdlIGRvIG5vdCBuZWVkIHRvIGNoZWNrIEFDTFxuICAgICAgICAgIGxldCBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZTtcbiAgICAgICAgICBpZiAoIWlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkKSB7XG4gICAgICAgICAgICBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBvcmlnaW5hbEFDTDtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QpIHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxBQ0wgPSBtZXNzYWdlLm9yaWdpbmFsUGFyc2VPYmplY3QuZ2V0QUNMKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSA9IHRoaXMuX21hdGNoZXNBQ0wob3JpZ2luYWxBQ0wsIGNsaWVudCwgcmVxdWVzdElkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gU2V0IGN1cnJlbnQgUGFyc2VPYmplY3QgQUNMIGNoZWNraW5nIHByb21pc2UsIGlmIHRoZSBvYmplY3QgZG9lcyBub3QgbWF0Y2hcbiAgICAgICAgICAvLyBzdWJzY3JpcHRpb24sIHdlIGRvIG5vdCBuZWVkIHRvIGNoZWNrIEFDTFxuICAgICAgICAgIGxldCBjdXJyZW50QUNMQ2hlY2tpbmdQcm9taXNlO1xuICAgICAgICAgIGxldCByZXM6IGFueSA9IHt9O1xuICAgICAgICAgIGlmICghaXNDdXJyZW50U3Vic2NyaXB0aW9uTWF0Y2hlZCkge1xuICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRBQ0wgPSBtZXNzYWdlLmN1cnJlbnRQYXJzZU9iamVjdC5nZXRBQ0woKTtcbiAgICAgICAgICAgIGN1cnJlbnRBQ0xDaGVja2luZ1Byb21pc2UgPSB0aGlzLl9tYXRjaGVzQUNMKGN1cnJlbnRBQ0wsIGNsaWVudCwgcmVxdWVzdElkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IG9wID0gdGhpcy5fZ2V0Q0xQT3BlcmF0aW9uKHN1YnNjcmlwdGlvbi5xdWVyeSk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9tYXRjaGVzQ0xQKFxuICAgICAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgICAgIG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgICBjbGllbnQsXG4gICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgb3BcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBbaXNPcmlnaW5hbE1hdGNoZWQsIGlzQ3VycmVudE1hdGNoZWRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICBvcmlnaW5hbEFDTENoZWNraW5nUHJvbWlzZSxcbiAgICAgICAgICAgICAgY3VycmVudEFDTENoZWNraW5nUHJvbWlzZSxcbiAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgICAgICAgICdPcmlnaW5hbCAlaiB8IEN1cnJlbnQgJWogfCBNYXRjaDogJXMsICVzLCAlcywgJXMgfCBRdWVyeTogJXMnLFxuICAgICAgICAgICAgICBvcmlnaW5hbFBhcnNlT2JqZWN0LFxuICAgICAgICAgICAgICBjdXJyZW50UGFyc2VPYmplY3QsXG4gICAgICAgICAgICAgIGlzT3JpZ2luYWxTdWJzY3JpcHRpb25NYXRjaGVkLFxuICAgICAgICAgICAgICBpc0N1cnJlbnRTdWJzY3JpcHRpb25NYXRjaGVkLFxuICAgICAgICAgICAgICBpc09yaWdpbmFsTWF0Y2hlZCxcbiAgICAgICAgICAgICAgaXNDdXJyZW50TWF0Y2hlZCxcbiAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLmhhc2hcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICAvLyBEZWNpZGUgZXZlbnQgdHlwZVxuICAgICAgICAgICAgbGV0IHR5cGU7XG4gICAgICAgICAgICBpZiAoaXNPcmlnaW5hbE1hdGNoZWQgJiYgaXNDdXJyZW50TWF0Y2hlZCkge1xuICAgICAgICAgICAgICB0eXBlID0gJ3VwZGF0ZSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT3JpZ2luYWxNYXRjaGVkICYmICFpc0N1cnJlbnRNYXRjaGVkKSB7XG4gICAgICAgICAgICAgIHR5cGUgPSAnbGVhdmUnO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghaXNPcmlnaW5hbE1hdGNoZWQgJiYgaXNDdXJyZW50TWF0Y2hlZCkge1xuICAgICAgICAgICAgICBpZiAob3JpZ2luYWxQYXJzZU9iamVjdCkge1xuICAgICAgICAgICAgICAgIHR5cGUgPSAnZW50ZXInO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHR5cGUgPSAnY3JlYXRlJztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCB3YXRjaEZpZWxkc0NoYW5nZWQgPSB0aGlzLl9jaGVja1dhdGNoRmllbGRzKGNsaWVudCwgcmVxdWVzdElkLCBtZXNzYWdlKTtcbiAgICAgICAgICAgIGlmICghd2F0Y2hGaWVsZHNDaGFuZ2VkICYmICh0eXBlID09PSAndXBkYXRlJyB8fCB0eXBlID09PSAnY3JlYXRlJykpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzID0ge1xuICAgICAgICAgICAgICBldmVudDogdHlwZSxcbiAgICAgICAgICAgICAgc2Vzc2lvblRva2VuOiBjbGllbnQuc2Vzc2lvblRva2VuLFxuICAgICAgICAgICAgICBvYmplY3Q6IGN1cnJlbnRQYXJzZU9iamVjdCxcbiAgICAgICAgICAgICAgb3JpZ2luYWw6IG9yaWdpbmFsUGFyc2VPYmplY3QsXG4gICAgICAgICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICAgICAgICBzdWJzY3JpcHRpb25zOiB0aGlzLnN1YnNjcmlwdGlvbnMuc2l6ZSxcbiAgICAgICAgICAgICAgdXNlTWFzdGVyS2V5OiBjbGllbnQuaGFzTWFzdGVyS2V5LFxuICAgICAgICAgICAgICBpbnN0YWxsYXRpb25JZDogY2xpZW50Lmluc3RhbGxhdGlvbklkLFxuICAgICAgICAgICAgICBzZW5kRXZlbnQ6IHRydWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgdHJpZ2dlciA9IGdldFRyaWdnZXIoY2xhc3NOYW1lLCAnYWZ0ZXJFdmVudCcsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xuICAgICAgICAgICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgICAgICAgICAgaWYgKHJlcy5vYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXMub2JqZWN0ID0gUGFyc2UuT2JqZWN0LmZyb21KU09OKHJlcy5vYmplY3QpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChyZXMub3JpZ2luYWwpIHtcbiAgICAgICAgICAgICAgICByZXMub3JpZ2luYWwgPSBQYXJzZS5PYmplY3QuZnJvbUpTT04ocmVzLm9yaWdpbmFsKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb25zdCBhdXRoID0gYXdhaXQgdGhpcy5nZXRBdXRoRnJvbUNsaWVudChjbGllbnQsIHJlcXVlc3RJZCk7XG4gICAgICAgICAgICAgIGlmIChhdXRoICYmIGF1dGgudXNlcikge1xuICAgICAgICAgICAgICAgIHJlcy51c2VyID0gYXV0aC51c2VyO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGF3YWl0IHJ1blRyaWdnZXIodHJpZ2dlciwgYGFmdGVyRXZlbnQuJHtjbGFzc05hbWV9YCwgcmVzLCBhdXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcmVzLnNlbmRFdmVudCkge1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzLm9iamVjdCAmJiB0eXBlb2YgcmVzLm9iamVjdC50b0pTT04gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgY3VycmVudFBhcnNlT2JqZWN0ID0gdG9KU09Od2l0aE9iamVjdHMocmVzLm9iamVjdCwgcmVzLm9iamVjdC5jbGFzc05hbWUgfHwgY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXMub3JpZ2luYWwgJiYgdHlwZW9mIHJlcy5vcmlnaW5hbC50b0pTT04gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgb3JpZ2luYWxQYXJzZU9iamVjdCA9IHRvSlNPTndpdGhPYmplY3RzKFxuICAgICAgICAgICAgICAgIHJlcy5vcmlnaW5hbCxcbiAgICAgICAgICAgICAgICByZXMub3JpZ2luYWwuY2xhc3NOYW1lIHx8IGNsYXNzTmFtZVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZmlsdGVyU2Vuc2l0aXZlRGF0YShcbiAgICAgICAgICAgICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zLFxuICAgICAgICAgICAgICByZXMsXG4gICAgICAgICAgICAgIGNsaWVudCxcbiAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICBvcCxcbiAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLnF1ZXJ5XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgZnVuY3Rpb25OYW1lID0gJ3B1c2gnICsgcmVzLmV2ZW50LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgcmVzLmV2ZW50LnNsaWNlKDEpO1xuICAgICAgICAgICAgaWYgKGNsaWVudFtmdW5jdGlvbk5hbWVdKSB7XG4gICAgICAgICAgICAgIGNsaWVudFtmdW5jdGlvbk5hbWVdKHJlcXVlc3RJZCwgY3VycmVudFBhcnNlT2JqZWN0LCBvcmlnaW5hbFBhcnNlT2JqZWN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHJlc29sdmVFcnJvcihlKTtcbiAgICAgICAgICAgIENsaWVudC5wdXNoRXJyb3IoY2xpZW50LnBhcnNlV2ViU29ja2V0LCBlcnJvci5jb2RlLCBlcnJvci5tZXNzYWdlLCBmYWxzZSwgcmVxdWVzdElkKTtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgYEZhaWxlZCBydW5uaW5nIGFmdGVyTGl2ZVF1ZXJ5RXZlbnQgb24gY2xhc3MgJHtjbGFzc05hbWV9IGZvciBldmVudCAke3Jlcy5ldmVudH0gd2l0aCBzZXNzaW9uICR7cmVzLnNlc3Npb25Ub2tlbn0gd2l0aDpcXG4gRXJyb3I6IGAgK1xuICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGVycm9yKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9vbkNvbm5lY3QocGFyc2VXZWJzb2NrZXQ6IGFueSk6IHZvaWQge1xuICAgIHBhcnNlV2Vic29ja2V0Lm9uKCdtZXNzYWdlJywgcmVxdWVzdCA9PiB7XG4gICAgICBpZiAodHlwZW9mIHJlcXVlc3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVxdWVzdCA9IEpTT04ucGFyc2UocmVxdWVzdCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ3VuYWJsZSB0byBwYXJzZSByZXF1ZXN0JywgcmVxdWVzdCwgZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsb2dnZXIudmVyYm9zZSgnUmVxdWVzdDogJWonLCByZXF1ZXN0KTtcblxuICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGlzIHJlcXVlc3QgaXMgYSB2YWxpZCByZXF1ZXN0LCByZXR1cm4gZXJyb3IgZGlyZWN0bHkgaWYgbm90XG4gICAgICBpZiAoXG4gICAgICAgICF0djQudmFsaWRhdGUocmVxdWVzdCwgUmVxdWVzdFNjaGVtYVsnZ2VuZXJhbCddKSB8fFxuICAgICAgICAhdHY0LnZhbGlkYXRlKHJlcXVlc3QsIFJlcXVlc3RTY2hlbWFbcmVxdWVzdC5vcF0pXG4gICAgICApIHtcbiAgICAgICAgQ2xpZW50LnB1c2hFcnJvcihwYXJzZVdlYnNvY2tldCwgMSwgdHY0LmVycm9yLm1lc3NhZ2UpO1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ0Nvbm5lY3QgbWVzc2FnZSBlcnJvciAlcycsIHR2NC5lcnJvci5tZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzd2l0Y2ggKHJlcXVlc3Qub3ApIHtcbiAgICAgICAgY2FzZSAnY29ubmVjdCc6XG4gICAgICAgICAgdGhpcy5faGFuZGxlQ29ubmVjdChwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3N1YnNjcmliZSc6XG4gICAgICAgICAgdGhpcy5faGFuZGxlU3Vic2NyaWJlKHBhcnNlV2Vic29ja2V0LCByZXF1ZXN0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndXBkYXRlJzpcbiAgICAgICAgICB0aGlzLl9oYW5kbGVVcGRhdGVTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd1bnN1YnNjcmliZSc6XG4gICAgICAgICAgdGhpcy5faGFuZGxlVW5zdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQsIHJlcXVlc3QpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIDMsICdHZXQgdW5rbm93biBvcGVyYXRpb24nKTtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0dldCB1bmtub3duIG9wZXJhdGlvbicsIHJlcXVlc3Qub3ApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcGFyc2VXZWJzb2NrZXQub24oJ2Rpc2Nvbm5lY3QnLCAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgQ2xpZW50IGRpc2Nvbm5lY3Q6ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9YCk7XG4gICAgICBjb25zdCBjbGllbnRJZCA9IHBhcnNlV2Vic29ja2V0LmNsaWVudElkO1xuICAgICAgaWYgKCF0aGlzLmNsaWVudHMuaGFzKGNsaWVudElkKSkge1xuICAgICAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgICAgICBldmVudDogJ3dzX2Rpc2Nvbm5lY3RfZXJyb3InLFxuICAgICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgICAgIGVycm9yOiBgVW5hYmxlIHRvIGZpbmQgY2xpZW50ICR7Y2xpZW50SWR9YCxcbiAgICAgICAgfSk7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgQ2FuIG5vdCBmaW5kIGNsaWVudCAke2NsaWVudElkfSBvbiBkaXNjb25uZWN0YCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gRGVsZXRlIGNsaWVudFxuICAgICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzLmdldChjbGllbnRJZCk7XG4gICAgICB0aGlzLmNsaWVudHMuZGVsZXRlKGNsaWVudElkKTtcblxuICAgICAgLy8gRGVsZXRlIGNsaWVudCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICAgIGZvciAoY29uc3QgW3JlcXVlc3RJZCwgc3Vic2NyaXB0aW9uSW5mb10gb2YgXy5lbnRyaWVzKGNsaWVudC5zdWJzY3JpcHRpb25JbmZvcykpIHtcbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gc3Vic2NyaXB0aW9uSW5mby5zdWJzY3JpcHRpb247XG4gICAgICAgIHN1YnNjcmlwdGlvbi5kZWxldGVDbGllbnRTdWJzY3JpcHRpb24oY2xpZW50SWQsIHJlcXVlc3RJZCk7XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gY2xpZW50IHdoaWNoIGlzIHN1YnNjcmliaW5nIHRoaXMgc3Vic2NyaXB0aW9uLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoc3Vic2NyaXB0aW9uLmNsYXNzTmFtZSk7XG4gICAgICAgIGlmICghc3Vic2NyaXB0aW9uLmhhc1N1YnNjcmliaW5nQ2xpZW50KCkpIHtcbiAgICAgICAgICBjbGFzc1N1YnNjcmlwdGlvbnMuZGVsZXRlKHN1YnNjcmlwdGlvbi5oYXNoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBubyBzdWJzY3JpcHRpb25zIHVuZGVyIHRoaXMgY2xhc3MsIHJlbW92ZSBpdCBmcm9tIHN1YnNjcmlwdGlvbnNcbiAgICAgICAgaWYgKGNsYXNzU3Vic2NyaXB0aW9ucy5zaXplID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmRlbGV0ZShzdWJzY3JpcHRpb24uY2xhc3NOYW1lKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsb2dnZXIudmVyYm9zZSgnQ3VycmVudCBjbGllbnRzICVkJywgdGhpcy5jbGllbnRzLnNpemUpO1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgc3Vic2NyaXB0aW9ucyAlZCcsIHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplKTtcbiAgICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMoe1xuICAgICAgICBldmVudDogJ3dzX2Rpc2Nvbm5lY3QnLFxuICAgICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemUsXG4gICAgICAgIHVzZU1hc3RlcktleTogY2xpZW50Lmhhc01hc3RlcktleSxcbiAgICAgICAgaW5zdGFsbGF0aW9uSWQ6IGNsaWVudC5pbnN0YWxsYXRpb25JZCxcbiAgICAgICAgc2Vzc2lvblRva2VuOiBjbGllbnQuc2Vzc2lvblRva2VuLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgIGV2ZW50OiAnd3NfY29ubmVjdCcsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgIH0pO1xuICB9XG5cbiAgX21hdGNoZXNTdWJzY3JpcHRpb24ocGFyc2VPYmplY3Q6IGFueSwgc3Vic2NyaXB0aW9uOiBhbnkpOiBib29sZWFuIHtcbiAgICAvLyBPYmplY3QgaXMgdW5kZWZpbmVkIG9yIG51bGwsIG5vdCBtYXRjaFxuICAgIGlmICghcGFyc2VPYmplY3QpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoZXNRdWVyeShkZWVwY29weShwYXJzZU9iamVjdCksIHN1YnNjcmlwdGlvbi5xdWVyeSk7XG4gIH1cblxuICBhc3luYyBfY2xlYXJDYWNoZWRSb2xlcyh1c2VySWQ6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB2YWxpZFRva2VucyA9IGF3YWl0IG5ldyBQYXJzZS5RdWVyeShQYXJzZS5TZXNzaW9uKVxuICAgICAgICAuZXF1YWxUbygndXNlcicsIFBhcnNlLlVzZXIuY3JlYXRlV2l0aG91dERhdGEodXNlcklkKSlcbiAgICAgICAgLmZpbmQoeyB1c2VNYXN0ZXJLZXk6IHRydWUgfSk7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgdmFsaWRUb2tlbnMubWFwKGFzeW5jIHRva2VuID0+IHtcbiAgICAgICAgICBjb25zdCBzZXNzaW9uVG9rZW4gPSB0b2tlbi5nZXQoJ3Nlc3Npb25Ub2tlbicpO1xuICAgICAgICAgIGNvbnN0IGF1dGhQcm9taXNlID0gdGhpcy5hdXRoQ2FjaGUuZ2V0KHNlc3Npb25Ub2tlbik7XG4gICAgICAgICAgaWYgKCFhdXRoUHJvbWlzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBbYXV0aDEsIGF1dGgyXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIGF1dGhQcm9taXNlLFxuICAgICAgICAgICAgZ2V0QXV0aEZvclNlc3Npb25Ub2tlbih7IGNhY2hlQ29udHJvbGxlcjogdGhpcy5jYWNoZUNvbnRyb2xsZXIsIHNlc3Npb25Ub2tlbiB9KSxcbiAgICAgICAgICBdKTtcbiAgICAgICAgICBhdXRoMS5hdXRoPy5jbGVhclJvbGVDYWNoZShzZXNzaW9uVG9rZW4pO1xuICAgICAgICAgIGF1dGgyLmF1dGg/LmNsZWFyUm9sZUNhY2hlKHNlc3Npb25Ub2tlbik7XG4gICAgICAgICAgdGhpcy5hdXRoQ2FjaGUuZGVsZXRlKHNlc3Npb25Ub2tlbik7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci52ZXJib3NlKGBDb3VsZCBub3QgY2xlYXIgcm9sZSBjYWNoZS4gJHtlfWApO1xuICAgIH1cbiAgfVxuXG4gIGdldEF1dGhGb3JTZXNzaW9uVG9rZW4oc2Vzc2lvblRva2VuPzogc3RyaW5nKTogUHJvbWlzZTx7IGF1dGg/OiBBdXRoLCB1c2VySWQ/OiBzdHJpbmcgfT4ge1xuICAgIGlmICghc2Vzc2lvblRva2VuKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtcbiAgICB9XG4gICAgY29uc3QgZnJvbUNhY2hlID0gdGhpcy5hdXRoQ2FjaGUuZ2V0KHNlc3Npb25Ub2tlbik7XG4gICAgaWYgKGZyb21DYWNoZSkge1xuICAgICAgcmV0dXJuIGZyb21DYWNoZTtcbiAgICB9XG4gICAgY29uc3QgYXV0aFByb21pc2UgPSBnZXRBdXRoRm9yU2Vzc2lvblRva2VuKHtcbiAgICAgIGNhY2hlQ29udHJvbGxlcjogdGhpcy5jYWNoZUNvbnRyb2xsZXIsXG4gICAgICBzZXNzaW9uVG9rZW46IHNlc3Npb25Ub2tlbixcbiAgICB9KVxuICAgICAgLnRoZW4oYXV0aCA9PiB7XG4gICAgICAgIHJldHVybiB7IGF1dGgsIHVzZXJJZDogYXV0aCAmJiBhdXRoLnVzZXIgJiYgYXV0aC51c2VyLmlkIH07XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgLy8gVGhlcmUgd2FzIGFuIGVycm9yIHdpdGggdGhlIHNlc3Npb24gdG9rZW5cbiAgICAgICAgY29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcbiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLmNvZGUgPT09IFBhcnNlLkVycm9yLklOVkFMSURfU0VTU0lPTl9UT0tFTikge1xuICAgICAgICAgIHJlc3VsdC5lcnJvciA9IGVycm9yO1xuICAgICAgICAgIHRoaXMuYXV0aENhY2hlLnNldChzZXNzaW9uVG9rZW4sIFByb21pc2UucmVzb2x2ZShyZXN1bHQpLCB0aGlzLmNvbmZpZy5jYWNoZVRpbWVvdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuYXV0aENhY2hlLmRlbGV0ZShzZXNzaW9uVG9rZW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB0aGlzLmF1dGhDYWNoZS5zZXQoc2Vzc2lvblRva2VuLCBhdXRoUHJvbWlzZSk7XG4gICAgcmV0dXJuIGF1dGhQcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgX21hdGNoZXNDTFAoXG4gICAgY2xhc3NMZXZlbFBlcm1pc3Npb25zPzogYW55LFxuICAgIG9iamVjdD86IGFueSxcbiAgICBjbGllbnQ/OiBhbnksXG4gICAgcmVxdWVzdElkPzogbnVtYmVyLFxuICAgIG9wPzogc3RyaW5nXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgLy8gdHJ5IHRvIG1hdGNoIG9uIHVzZXIgZmlyc3QsIGxlc3MgZXhwZW5zaXZlIHRoYW4gd2l0aCByb2xlc1xuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGNvbnN0IGFjbEdyb3VwID0gWycqJ107XG4gICAgbGV0IHVzZXJJZDtcbiAgICBpZiAodHlwZW9mIHN1YnNjcmlwdGlvbkluZm8gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjb25zdCB7IHVzZXJJZCB9ID0gYXdhaXQgdGhpcy5nZXRBdXRoRm9yU2Vzc2lvblRva2VuKHN1YnNjcmlwdGlvbkluZm8uc2Vzc2lvblRva2VuKTtcbiAgICAgIGlmICh1c2VySWQpIHtcbiAgICAgICAgYWNsR3JvdXAucHVzaCh1c2VySWQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgU2NoZW1hQ29udHJvbGxlci52YWxpZGF0ZVBlcm1pc3Npb24oXG4gICAgICAgIGNsYXNzTGV2ZWxQZXJtaXNzaW9ucyxcbiAgICAgICAgb2JqZWN0LmNsYXNzTmFtZSxcbiAgICAgICAgYWNsR3JvdXAsXG4gICAgICAgIG9wXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoYEZhaWxlZCBtYXRjaGluZyBDTFAgZm9yICR7b2JqZWN0LmlkfSAke3VzZXJJZH0gJHtlfWApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBUT0RPOiBoYW5kbGUgcm9sZXMgcGVybWlzc2lvbnNcbiAgICAvLyBPYmplY3Qua2V5cyhjbGFzc0xldmVsUGVybWlzc2lvbnMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgIC8vICAgY29uc3QgcGVybSA9IGNsYXNzTGV2ZWxQZXJtaXNzaW9uc1trZXldO1xuICAgIC8vICAgT2JqZWN0LmtleXMocGVybSkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgLy8gICAgIGlmIChrZXkuaW5kZXhPZigncm9sZScpKVxuICAgIC8vICAgfSk7XG4gICAgLy8gfSlcbiAgICAvLyAvLyBpdCdzIHJlamVjdGVkIGhlcmUsIGNoZWNrIHRoZSByb2xlc1xuICAgIC8vIHZhciByb2xlc1F1ZXJ5ID0gbmV3IFBhcnNlLlF1ZXJ5KFBhcnNlLlJvbGUpO1xuICAgIC8vIHJvbGVzUXVlcnkuZXF1YWxUbyhcInVzZXJzXCIsIHVzZXIpO1xuICAgIC8vIHJldHVybiByb2xlc1F1ZXJ5LmZpbmQoe3VzZU1hc3RlcktleTp0cnVlfSk7XG4gIH1cblxuICBhc3luYyBfZmlsdGVyU2Vuc2l0aXZlRGF0YShcbiAgICBjbGFzc0xldmVsUGVybWlzc2lvbnM/OiBhbnksXG4gICAgcmVzPzogYW55LFxuICAgIGNsaWVudD86IGFueSxcbiAgICByZXF1ZXN0SWQ/OiBudW1iZXIsXG4gICAgb3A/OiBzdHJpbmcsXG4gICAgcXVlcnk/OiBhbnlcbiAgKSB7XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSW5mbyA9IGNsaWVudC5nZXRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3RJZCk7XG4gICAgY29uc3QgYWNsR3JvdXAgPSBbJyonXTtcbiAgICBsZXQgY2xpZW50QXV0aDtcbiAgICBpZiAodHlwZW9mIHN1YnNjcmlwdGlvbkluZm8gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjb25zdCB7IHVzZXJJZCwgYXV0aCB9ID0gYXdhaXQgdGhpcy5nZXRBdXRoRm9yU2Vzc2lvblRva2VuKHN1YnNjcmlwdGlvbkluZm8uc2Vzc2lvblRva2VuKTtcbiAgICAgIGlmICh1c2VySWQpIHtcbiAgICAgICAgYWNsR3JvdXAucHVzaCh1c2VySWQpO1xuICAgICAgfVxuICAgICAgY2xpZW50QXV0aCA9IGF1dGg7XG4gICAgfVxuICAgIGNvbnN0IGZpbHRlciA9IG9iaiA9PiB7XG4gICAgICBpZiAoIW9iaikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBsZXQgcHJvdGVjdGVkRmllbGRzID0gY2xhc3NMZXZlbFBlcm1pc3Npb25zPy5wcm90ZWN0ZWRGaWVsZHMgfHwgW107XG4gICAgICBpZiAoIWNsaWVudC5oYXNNYXN0ZXJLZXkgJiYgIUFycmF5LmlzQXJyYXkocHJvdGVjdGVkRmllbGRzKSkge1xuICAgICAgICBwcm90ZWN0ZWRGaWVsZHMgPSBnZXREYXRhYmFzZUNvbnRyb2xsZXIodGhpcy5jb25maWcpLmFkZFByb3RlY3RlZEZpZWxkcyhcbiAgICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgICAgcmVzLm9iamVjdC5jbGFzc05hbWUsXG4gICAgICAgICAgcXVlcnksXG4gICAgICAgICAgYWNsR3JvdXAsXG4gICAgICAgICAgY2xpZW50QXV0aFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIERhdGFiYXNlQ29udHJvbGxlci5maWx0ZXJTZW5zaXRpdmVEYXRhKFxuICAgICAgICBjbGllbnQuaGFzTWFzdGVyS2V5LFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgYWNsR3JvdXAsXG4gICAgICAgIGNsaWVudEF1dGgsXG4gICAgICAgIG9wLFxuICAgICAgICBjbGFzc0xldmVsUGVybWlzc2lvbnMsXG4gICAgICAgIHJlcy5vYmplY3QuY2xhc3NOYW1lLFxuICAgICAgICBwcm90ZWN0ZWRGaWVsZHMsXG4gICAgICAgIG9iaixcbiAgICAgICAgcXVlcnlcbiAgICAgICk7XG4gICAgfTtcbiAgICByZXMub2JqZWN0ID0gZmlsdGVyKHJlcy5vYmplY3QpO1xuICAgIHJlcy5vcmlnaW5hbCA9IGZpbHRlcihyZXMub3JpZ2luYWwpO1xuICB9XG5cbiAgX2dldENMUE9wZXJhdGlvbihxdWVyeTogYW55KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBxdWVyeSA9PT0gJ29iamVjdCcgJiZcbiAgICAgIE9iamVjdC5rZXlzKHF1ZXJ5KS5sZW5ndGggPT0gMSAmJlxuICAgICAgdHlwZW9mIHF1ZXJ5Lm9iamVjdElkID09PSAnc3RyaW5nJ1xuICAgICAgPyAnZ2V0J1xuICAgICAgOiAnZmluZCc7XG4gIH1cblxuICBhc3luYyBfdmVyaWZ5QUNMKGFjbDogYW55LCB0b2tlbjogc3RyaW5nKSB7XG4gICAgaWYgKCF0b2tlbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHsgYXV0aCwgdXNlcklkIH0gPSBhd2FpdCB0aGlzLmdldEF1dGhGb3JTZXNzaW9uVG9rZW4odG9rZW4pO1xuXG4gICAgLy8gR2V0dGluZyB0aGUgc2Vzc2lvbiB0b2tlbiBmYWlsZWRcbiAgICAvLyBUaGlzIG1lYW5zIHRoYXQgbm8gYWRkaXRpb25hbCBhdXRoIGlzIGF2YWlsYWJsZVxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIGp1c3QgYmFpbCBvdXQgYXMgbm8gYWRkaXRpb25hbCB2aXNpYmlsaXR5IGNhbiBiZSBpbmZlcnJlZC5cbiAgICBpZiAoIWF1dGggfHwgIXVzZXJJZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBpc1N1YnNjcmlwdGlvblNlc3Npb25Ub2tlbk1hdGNoZWQgPSBhY2wuZ2V0UmVhZEFjY2Vzcyh1c2VySWQpO1xuICAgIGlmIChpc1N1YnNjcmlwdGlvblNlc3Npb25Ub2tlbk1hdGNoZWQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIHRoZSB1c2VyIGhhcyBhbnkgcm9sZXMgdGhhdCBtYXRjaCB0aGUgQUNMXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIFJlc29sdmUgZmFsc2UgcmlnaHQgYXdheSBpZiB0aGUgYWNsIGRvZXNuJ3QgaGF2ZSBhbnkgcm9sZXNcbiAgICAgICAgY29uc3QgYWNsX2hhc19yb2xlcyA9IE9iamVjdC5rZXlzKGFjbC5wZXJtaXNzaW9uc0J5SWQpLnNvbWUoa2V5ID0+IGtleS5zdGFydHNXaXRoKCdyb2xlOicpKTtcbiAgICAgICAgaWYgKCFhY2xfaGFzX3JvbGVzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJvbGVOYW1lcyA9IGF3YWl0IGF1dGguZ2V0VXNlclJvbGVzKCk7XG4gICAgICAgIC8vIEZpbmFsbHksIHNlZSBpZiBhbnkgb2YgdGhlIHVzZXIncyByb2xlcyBhbGxvdyB0aGVtIHJlYWQgYWNjZXNzXG4gICAgICAgIGZvciAoY29uc3Qgcm9sZSBvZiByb2xlTmFtZXMpIHtcbiAgICAgICAgICAvLyBXZSB1c2UgZ2V0UmVhZEFjY2VzcyBhcyBgcm9sZWAgaXMgaW4gdGhlIGZvcm0gYHJvbGU6cm9sZU5hbWVgXG4gICAgICAgICAgaWYgKGFjbC5nZXRSZWFkQWNjZXNzKHJvbGUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZ2V0QXV0aEZyb21DbGllbnQoY2xpZW50OiBhbnksIHJlcXVlc3RJZDogbnVtYmVyLCBzZXNzaW9uVG9rZW4/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBnZXRTZXNzaW9uRnJvbUNsaWVudCA9ICgpID0+IHtcbiAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgICAgaWYgKHR5cGVvZiBzdWJzY3JpcHRpb25JbmZvID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gY2xpZW50LnNlc3Npb25Ub2tlbjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlbiB8fCBjbGllbnQuc2Vzc2lvblRva2VuO1xuICAgIH07XG4gICAgaWYgKCFzZXNzaW9uVG9rZW4pIHtcbiAgICAgIHNlc3Npb25Ub2tlbiA9IGdldFNlc3Npb25Gcm9tQ2xpZW50KCk7XG4gICAgfVxuICAgIGlmICghc2Vzc2lvblRva2VuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgYXV0aCB9ID0gYXdhaXQgdGhpcy5nZXRBdXRoRm9yU2Vzc2lvblRva2VuKHNlc3Npb25Ub2tlbik7XG4gICAgcmV0dXJuIGF1dGg7XG4gIH1cblxuICBfY2hlY2tXYXRjaEZpZWxkcyhjbGllbnQ6IGFueSwgcmVxdWVzdElkOiBhbnksIG1lc3NhZ2U6IGFueSkge1xuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGNvbnN0IHdhdGNoID0gc3Vic2NyaXB0aW9uSW5mbz8ud2F0Y2g7XG4gICAgaWYgKCF3YXRjaCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IG9iamVjdCA9IG1lc3NhZ2UuY3VycmVudFBhcnNlT2JqZWN0O1xuICAgIGNvbnN0IG9yaWdpbmFsID0gbWVzc2FnZS5vcmlnaW5hbFBhcnNlT2JqZWN0O1xuICAgIHJldHVybiB3YXRjaC5zb21lKGZpZWxkID0+ICFpc0RlZXBTdHJpY3RFcXVhbChvYmplY3QuZ2V0KGZpZWxkKSwgb3JpZ2luYWw/LmdldChmaWVsZCkpKTtcbiAgfVxuXG4gIGFzeW5jIF9tYXRjaGVzQUNMKGFjbDogYW55LCBjbGllbnQ6IGFueSwgcmVxdWVzdElkOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBSZXR1cm4gdHJ1ZSBkaXJlY3RseSBpZiBBQ0wgaXNuJ3QgcHJlc2VudCwgQUNMIGlzIHB1YmxpYyByZWFkLCBvciBjbGllbnQgaGFzIG1hc3RlciBrZXlcbiAgICBpZiAoIWFjbCB8fCBhY2wuZ2V0UHVibGljUmVhZEFjY2VzcygpIHx8IGNsaWVudC5oYXNNYXN0ZXJLZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBDaGVjayBzdWJzY3JpcHRpb24gc2Vzc2lvblRva2VuIG1hdGNoZXMgQUNMIGZpcnN0XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uSW5mbyA9IGNsaWVudC5nZXRTdWJzY3JpcHRpb25JbmZvKHJlcXVlc3RJZCk7XG4gICAgaWYgKHR5cGVvZiBzdWJzY3JpcHRpb25JbmZvID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHN1YnNjcmlwdGlvblRva2VuID0gc3Vic2NyaXB0aW9uSW5mby5zZXNzaW9uVG9rZW47XG4gICAgY29uc3QgY2xpZW50U2Vzc2lvblRva2VuID0gY2xpZW50LnNlc3Npb25Ub2tlbjtcblxuICAgIGlmIChhd2FpdCB0aGlzLl92ZXJpZnlBQ0woYWNsLCBzdWJzY3JpcHRpb25Ub2tlbikpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChhd2FpdCB0aGlzLl92ZXJpZnlBQ0woYWNsLCBjbGllbnRTZXNzaW9uVG9rZW4pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBhc3luYyBfaGFuZGxlQ29ubmVjdChwYXJzZVdlYnNvY2tldDogYW55LCByZXF1ZXN0OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIGlmICghdGhpcy5fdmFsaWRhdGVLZXlzKHJlcXVlc3QsIHRoaXMua2V5UGFpcnMpKSB7XG4gICAgICBDbGllbnQucHVzaEVycm9yKHBhcnNlV2Vic29ja2V0LCA0LCAnS2V5IGluIHJlcXVlc3QgaXMgbm90IHZhbGlkJyk7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0tleSBpbiByZXF1ZXN0IGlzIG5vdCB2YWxpZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBoYXNNYXN0ZXJLZXkgPSB0aGlzLl9oYXNNYXN0ZXJLZXkocmVxdWVzdCwgdGhpcy5rZXlQYWlycyk7XG4gICAgY29uc3QgY2xpZW50SWQgPSB1dWlkdjQoKTtcbiAgICBjb25zdCBjbGllbnQgPSBuZXcgQ2xpZW50KFxuICAgICAgY2xpZW50SWQsXG4gICAgICBwYXJzZVdlYnNvY2tldCxcbiAgICAgIGhhc01hc3RlcktleSxcbiAgICAgIHJlcXVlc3Quc2Vzc2lvblRva2VuLFxuICAgICAgcmVxdWVzdC5pbnN0YWxsYXRpb25JZFxuICAgICk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcSA9IHtcbiAgICAgICAgY2xpZW50LFxuICAgICAgICBldmVudDogJ2Nvbm5lY3QnLFxuICAgICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgICAgc3Vic2NyaXB0aW9uczogdGhpcy5zdWJzY3JpcHRpb25zLnNpemUsXG4gICAgICAgIHNlc3Npb25Ub2tlbjogcmVxdWVzdC5zZXNzaW9uVG9rZW4sXG4gICAgICAgIHVzZU1hc3RlcktleTogY2xpZW50Lmhhc01hc3RlcktleSxcbiAgICAgICAgaW5zdGFsbGF0aW9uSWQ6IHJlcXVlc3QuaW5zdGFsbGF0aW9uSWQsXG4gICAgICAgIHVzZXI6IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgICBjb25zdCB0cmlnZ2VyID0gZ2V0VHJpZ2dlcignQENvbm5lY3QnLCAnYmVmb3JlQ29ubmVjdCcsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xuICAgICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgICAgY29uc3QgYXV0aCA9IGF3YWl0IHRoaXMuZ2V0QXV0aEZyb21DbGllbnQoY2xpZW50LCByZXF1ZXN0LnJlcXVlc3RJZCwgcmVxLnNlc3Npb25Ub2tlbik7XG4gICAgICAgIGlmIChhdXRoICYmIGF1dGgudXNlcikge1xuICAgICAgICAgIHJlcS51c2VyID0gYXV0aC51c2VyO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHJ1blRyaWdnZXIodHJpZ2dlciwgYGJlZm9yZUNvbm5lY3QuQENvbm5lY3RgLCByZXEsIGF1dGgpO1xuICAgICAgfVxuICAgICAgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQgPSBjbGllbnRJZDtcbiAgICAgIHRoaXMuY2xpZW50cy5zZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIGNsaWVudCk7XG4gICAgICBsb2dnZXIuaW5mbyhgQ3JlYXRlIG5ldyBjbGllbnQ6ICR7cGFyc2VXZWJzb2NrZXQuY2xpZW50SWR9YCk7XG4gICAgICBjbGllbnQucHVzaENvbm5lY3QoKTtcbiAgICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMocmVxKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCBlcnJvciA9IHJlc29sdmVFcnJvcihlKTtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IocGFyc2VXZWJzb2NrZXQsIGVycm9yLmNvZGUsIGVycm9yLm1lc3NhZ2UsIGZhbHNlKTtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgYEZhaWxlZCBydW5uaW5nIGJlZm9yZUNvbm5lY3QgZm9yIHNlc3Npb24gJHtyZXF1ZXN0LnNlc3Npb25Ub2tlbn0gd2l0aDpcXG4gRXJyb3I6IGAgK1xuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGVycm9yKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBfaGFzTWFzdGVyS2V5KHJlcXVlc3Q6IGFueSwgdmFsaWRLZXlQYWlyczogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKCF2YWxpZEtleVBhaXJzIHx8IHZhbGlkS2V5UGFpcnMuc2l6ZSA9PSAwIHx8ICF2YWxpZEtleVBhaXJzLmhhcygnbWFzdGVyS2V5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKCFyZXF1ZXN0IHx8ICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVxdWVzdCwgJ21hc3RlcktleScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiByZXF1ZXN0Lm1hc3RlcktleSA9PT0gdmFsaWRLZXlQYWlycy5nZXQoJ21hc3RlcktleScpO1xuICB9XG5cbiAgX3ZhbGlkYXRlS2V5cyhyZXF1ZXN0OiBhbnksIHZhbGlkS2V5UGFpcnM6IGFueSk6IGJvb2xlYW4ge1xuICAgIGlmICghdmFsaWRLZXlQYWlycyB8fCB2YWxpZEtleVBhaXJzLnNpemUgPT0gMCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGxldCBpc1ZhbGlkID0gZmFsc2U7XG4gICAgZm9yIChjb25zdCBba2V5LCBzZWNyZXRdIG9mIHZhbGlkS2V5UGFpcnMpIHtcbiAgICAgIGlmICghcmVxdWVzdFtrZXldIHx8IHJlcXVlc3Rba2V5XSAhPT0gc2VjcmV0KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIGlzVmFsaWQ7XG4gIH1cblxuICBhc3luYyBfaGFuZGxlU3Vic2NyaWJlKHBhcnNlV2Vic29ja2V0OiBhbnksIHJlcXVlc3Q6IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgLy8gSWYgd2UgY2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCByZXR1cm4gZXJyb3IgdG8gY2xpZW50XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocGFyc2VXZWJzb2NrZXQsICdjbGllbnRJZCcpKSB7XG4gICAgICBDbGllbnQucHVzaEVycm9yKFxuICAgICAgICBwYXJzZVdlYnNvY2tldCxcbiAgICAgICAgMixcbiAgICAgICAgJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCwgbWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIHNlcnZlciBiZWZvcmUgc3Vic2NyaWJpbmcnXG4gICAgICApO1xuICAgICAgbG9nZ2VyLmVycm9yKCdDYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIG1ha2Ugc3VyZSB5b3UgY29ubmVjdCB0byBzZXJ2ZXIgYmVmb3JlIHN1YnNjcmliaW5nJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuICAgIGNvbnN0IGNsYXNzTmFtZSA9IHJlcXVlc3QucXVlcnkuY2xhc3NOYW1lO1xuICAgIGxldCBhdXRoQ2FsbGVkID0gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRyaWdnZXIgPSBnZXRUcmlnZ2VyKGNsYXNzTmFtZSwgJ2JlZm9yZVN1YnNjcmliZScsIFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xuICAgICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgICAgY29uc3QgYXV0aCA9IGF3YWl0IHRoaXMuZ2V0QXV0aEZyb21DbGllbnQoY2xpZW50LCByZXF1ZXN0LnJlcXVlc3RJZCwgcmVxdWVzdC5zZXNzaW9uVG9rZW4pO1xuICAgICAgICBhdXRoQ2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgaWYgKGF1dGggJiYgYXV0aC51c2VyKSB7XG4gICAgICAgICAgcmVxdWVzdC51c2VyID0gYXV0aC51c2VyO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFyc2VRdWVyeSA9IG5ldyBQYXJzZS5RdWVyeShjbGFzc05hbWUpO1xuICAgICAgICBwYXJzZVF1ZXJ5LndpdGhKU09OKHJlcXVlc3QucXVlcnkpO1xuICAgICAgICByZXF1ZXN0LnF1ZXJ5ID0gcGFyc2VRdWVyeTtcbiAgICAgICAgYXdhaXQgcnVuVHJpZ2dlcih0cmlnZ2VyLCBgYmVmb3JlU3Vic2NyaWJlLiR7Y2xhc3NOYW1lfWAsIHJlcXVlc3QsIGF1dGgpO1xuXG4gICAgICAgIGNvbnN0IHF1ZXJ5ID0gcmVxdWVzdC5xdWVyeS50b0pTT04oKTtcbiAgICAgICAgcmVxdWVzdC5xdWVyeSA9IHF1ZXJ5O1xuICAgICAgfVxuXG4gICAgICBpZiAoY2xhc3NOYW1lID09PSAnX1Nlc3Npb24nKSB7XG4gICAgICAgIGlmICghYXV0aENhbGxlZCkge1xuICAgICAgICAgIGNvbnN0IGF1dGggPSBhd2FpdCB0aGlzLmdldEF1dGhGcm9tQ2xpZW50KFxuICAgICAgICAgICAgY2xpZW50LFxuICAgICAgICAgICAgcmVxdWVzdC5yZXF1ZXN0SWQsXG4gICAgICAgICAgICByZXF1ZXN0LnNlc3Npb25Ub2tlblxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGF1dGggJiYgYXV0aC51c2VyKSB7XG4gICAgICAgICAgICByZXF1ZXN0LnVzZXIgPSBhdXRoLnVzZXI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChyZXF1ZXN0LnVzZXIpIHtcbiAgICAgICAgICByZXF1ZXN0LnF1ZXJ5LndoZXJlLnVzZXIgPSByZXF1ZXN0LnVzZXIudG9Qb2ludGVyKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXJlcXVlc3QubWFzdGVyKSB7XG4gICAgICAgICAgQ2xpZW50LnB1c2hFcnJvcihcbiAgICAgICAgICAgIHBhcnNlV2Vic29ja2V0LFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9TRVNTSU9OX1RPS0VOLFxuICAgICAgICAgICAgJ0ludmFsaWQgc2Vzc2lvbiB0b2tlbicsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIHJlcXVlc3QucmVxdWVzdElkXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEdldCBzdWJzY3JpcHRpb24gZnJvbSBzdWJzY3JpcHRpb25zLCBjcmVhdGUgb25lIGlmIG5lY2Vzc2FyeVxuICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uSGFzaCA9IHF1ZXJ5SGFzaChyZXF1ZXN0LnF1ZXJ5KTtcbiAgICAgIC8vIEFkZCBjbGFzc05hbWUgdG8gc3Vic2NyaXB0aW9ucyBpZiBuZWNlc3NhcnlcblxuICAgICAgaWYgKCF0aGlzLnN1YnNjcmlwdGlvbnMuaGFzKGNsYXNzTmFtZSkpIHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnNldChjbGFzc05hbWUsIG5ldyBNYXAoKSk7XG4gICAgICB9XG4gICAgICBjb25zdCBjbGFzc1N1YnNjcmlwdGlvbnMgPSB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KGNsYXNzTmFtZSk7XG4gICAgICBsZXQgc3Vic2NyaXB0aW9uO1xuICAgICAgaWYgKGNsYXNzU3Vic2NyaXB0aW9ucy5oYXMoc3Vic2NyaXB0aW9uSGFzaCkpIHtcbiAgICAgICAgc3Vic2NyaXB0aW9uID0gY2xhc3NTdWJzY3JpcHRpb25zLmdldChzdWJzY3JpcHRpb25IYXNoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oY2xhc3NOYW1lLCByZXF1ZXN0LnF1ZXJ5LndoZXJlLCBzdWJzY3JpcHRpb25IYXNoKTtcbiAgICAgICAgY2xhc3NTdWJzY3JpcHRpb25zLnNldChzdWJzY3JpcHRpb25IYXNoLCBzdWJzY3JpcHRpb24pO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgc3Vic2NyaXB0aW9uSW5mbyB0byBjbGllbnRcbiAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm86IGFueSA9IHtcbiAgICAgICAgc3Vic2NyaXB0aW9uOiBzdWJzY3JpcHRpb24sXG4gICAgICB9O1xuICAgICAgLy8gQWRkIHNlbGVjdGVkIGZpZWxkcywgc2Vzc2lvblRva2VuIGFuZCBpbnN0YWxsYXRpb25JZCBmb3IgdGhpcyBzdWJzY3JpcHRpb24gaWYgbmVjZXNzYXJ5XG4gICAgICBpZiAocmVxdWVzdC5xdWVyeS5rZXlzKSB7XG4gICAgICAgIHN1YnNjcmlwdGlvbkluZm8ua2V5cyA9IEFycmF5LmlzQXJyYXkocmVxdWVzdC5xdWVyeS5rZXlzKVxuICAgICAgICAgID8gcmVxdWVzdC5xdWVyeS5rZXlzXG4gICAgICAgICAgOiByZXF1ZXN0LnF1ZXJ5LmtleXMuc3BsaXQoJywnKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXF1ZXN0LnF1ZXJ5LndhdGNoKSB7XG4gICAgICAgIHN1YnNjcmlwdGlvbkluZm8ud2F0Y2ggPSByZXF1ZXN0LnF1ZXJ5LndhdGNoO1xuICAgICAgfVxuICAgICAgaWYgKHJlcXVlc3Quc2Vzc2lvblRva2VuKSB7XG4gICAgICAgIHN1YnNjcmlwdGlvbkluZm8uc2Vzc2lvblRva2VuID0gcmVxdWVzdC5zZXNzaW9uVG9rZW47XG4gICAgICB9XG4gICAgICBjbGllbnQuYWRkU3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0LnJlcXVlc3RJZCwgc3Vic2NyaXB0aW9uSW5mbyk7XG5cbiAgICAgIC8vIEFkZCBjbGllbnRJZCB0byBzdWJzY3JpcHRpb25cbiAgICAgIHN1YnNjcmlwdGlvbi5hZGRDbGllbnRTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQsIHJlcXVlc3QucmVxdWVzdElkKTtcblxuICAgICAgY2xpZW50LnB1c2hTdWJzY3JpYmUocmVxdWVzdC5yZXF1ZXN0SWQpO1xuXG4gICAgICBsb2dnZXIudmVyYm9zZShcbiAgICAgICAgYENyZWF0ZSBjbGllbnQgJHtwYXJzZVdlYnNvY2tldC5jbGllbnRJZH0gbmV3IHN1YnNjcmlwdGlvbjogJHtyZXF1ZXN0LnJlcXVlc3RJZH1gXG4gICAgICApO1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoJ0N1cnJlbnQgY2xpZW50IG51bWJlcjogJWQnLCB0aGlzLmNsaWVudHMuc2l6ZSk7XG4gICAgICBydW5MaXZlUXVlcnlFdmVudEhhbmRsZXJzKHtcbiAgICAgICAgY2xpZW50LFxuICAgICAgICBldmVudDogJ3N1YnNjcmliZScsXG4gICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50cy5zaXplLFxuICAgICAgICBzdWJzY3JpcHRpb25zOiB0aGlzLnN1YnNjcmlwdGlvbnMuc2l6ZSxcbiAgICAgICAgc2Vzc2lvblRva2VuOiByZXF1ZXN0LnNlc3Npb25Ub2tlbixcbiAgICAgICAgdXNlTWFzdGVyS2V5OiBjbGllbnQuaGFzTWFzdGVyS2V5LFxuICAgICAgICBpbnN0YWxsYXRpb25JZDogY2xpZW50Lmluc3RhbGxhdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc3QgZXJyb3IgPSByZXNvbHZlRXJyb3IoZSk7XG4gICAgICBDbGllbnQucHVzaEVycm9yKHBhcnNlV2Vic29ja2V0LCBlcnJvci5jb2RlLCBlcnJvci5tZXNzYWdlLCBmYWxzZSwgcmVxdWVzdC5yZXF1ZXN0SWQpO1xuICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICBgRmFpbGVkIHJ1bm5pbmcgYmVmb3JlU3Vic2NyaWJlIG9uICR7Y2xhc3NOYW1lfSBmb3Igc2Vzc2lvbiAke3JlcXVlc3Quc2Vzc2lvblRva2VufSB3aXRoOlxcbiBFcnJvcjogYCArXG4gICAgICAgICAgSlNPTi5zdHJpbmdpZnkoZXJyb3IpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIF9oYW5kbGVVcGRhdGVTdWJzY3JpcHRpb24ocGFyc2VXZWJzb2NrZXQ6IGFueSwgcmVxdWVzdDogYW55KTogYW55IHtcbiAgICB0aGlzLl9oYW5kbGVVbnN1YnNjcmliZShwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCwgZmFsc2UpO1xuICAgIHRoaXMuX2hhbmRsZVN1YnNjcmliZShwYXJzZVdlYnNvY2tldCwgcmVxdWVzdCk7XG4gIH1cblxuICBfaGFuZGxlVW5zdWJzY3JpYmUocGFyc2VXZWJzb2NrZXQ6IGFueSwgcmVxdWVzdDogYW55LCBub3RpZnlDbGllbnQ6IGJvb2xlYW4gPSB0cnVlKTogYW55IHtcbiAgICAvLyBJZiB3ZSBjYW4gbm90IGZpbmQgdGhpcyBjbGllbnQsIHJldHVybiBlcnJvciB0byBjbGllbnRcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwYXJzZVdlYnNvY2tldCwgJ2NsaWVudElkJykpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IoXG4gICAgICAgIHBhcnNlV2Vic29ja2V0LFxuICAgICAgICAyLFxuICAgICAgICAnQ2FuIG5vdCBmaW5kIHRoaXMgY2xpZW50LCBtYWtlIHN1cmUgeW91IGNvbm5lY3QgdG8gc2VydmVyIGJlZm9yZSB1bnN1YnNjcmliaW5nJ1xuICAgICAgKTtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCwgbWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZydcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHJlcXVlc3RJZCA9IHJlcXVlc3QucmVxdWVzdElkO1xuICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQocGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuICAgIGlmICh0eXBlb2YgY2xpZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgQ2xpZW50LnB1c2hFcnJvcihcbiAgICAgICAgcGFyc2VXZWJzb2NrZXQsXG4gICAgICAgIDIsXG4gICAgICAgICdDYW5ub3QgZmluZCBjbGllbnQgd2l0aCBjbGllbnRJZCAnICtcbiAgICAgICAgICBwYXJzZVdlYnNvY2tldC5jbGllbnRJZCArXG4gICAgICAgICAgJy4gTWFrZSBzdXJlIHlvdSBjb25uZWN0IHRvIGxpdmUgcXVlcnkgc2VydmVyIGJlZm9yZSB1bnN1YnNjcmliaW5nLidcbiAgICAgICk7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0NhbiBub3QgZmluZCB0aGlzIGNsaWVudCAnICsgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkluZm8gPSBjbGllbnQuZ2V0U3Vic2NyaXB0aW9uSW5mbyhyZXF1ZXN0SWQpO1xuICAgIGlmICh0eXBlb2Ygc3Vic2NyaXB0aW9uSW5mbyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIENsaWVudC5wdXNoRXJyb3IoXG4gICAgICAgIHBhcnNlV2Vic29ja2V0LFxuICAgICAgICAyLFxuICAgICAgICAnQ2Fubm90IGZpbmQgc3Vic2NyaXB0aW9uIHdpdGggY2xpZW50SWQgJyArXG4gICAgICAgICAgcGFyc2VXZWJzb2NrZXQuY2xpZW50SWQgK1xuICAgICAgICAgICcgc3Vic2NyaXB0aW9uSWQgJyArXG4gICAgICAgICAgcmVxdWVzdElkICtcbiAgICAgICAgICAnLiBNYWtlIHN1cmUgeW91IHN1YnNjcmliZSB0byBsaXZlIHF1ZXJ5IHNlcnZlciBiZWZvcmUgdW5zdWJzY3JpYmluZy4nXG4gICAgICApO1xuICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAnQ2FuIG5vdCBmaW5kIHN1YnNjcmlwdGlvbiB3aXRoIGNsaWVudElkICcgK1xuICAgICAgICAgIHBhcnNlV2Vic29ja2V0LmNsaWVudElkICtcbiAgICAgICAgICAnIHN1YnNjcmlwdGlvbklkICcgK1xuICAgICAgICAgIHJlcXVlc3RJZFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgc3Vic2NyaXB0aW9uIGZyb20gY2xpZW50XG4gICAgY2xpZW50LmRlbGV0ZVN1YnNjcmlwdGlvbkluZm8ocmVxdWVzdElkKTtcbiAgICAvLyBSZW1vdmUgY2xpZW50IGZyb20gc3Vic2NyaXB0aW9uXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gc3Vic2NyaXB0aW9uSW5mby5zdWJzY3JpcHRpb247XG4gICAgY29uc3QgY2xhc3NOYW1lID0gc3Vic2NyaXB0aW9uLmNsYXNzTmFtZTtcbiAgICBzdWJzY3JpcHRpb24uZGVsZXRlQ2xpZW50U3Vic2NyaXB0aW9uKHBhcnNlV2Vic29ja2V0LmNsaWVudElkLCByZXF1ZXN0SWQpO1xuICAgIC8vIElmIHRoZXJlIGlzIG5vIGNsaWVudCB3aGljaCBpcyBzdWJzY3JpYmluZyB0aGlzIHN1YnNjcmlwdGlvbiwgcmVtb3ZlIGl0IGZyb20gc3Vic2NyaXB0aW9uc1xuICAgIGNvbnN0IGNsYXNzU3Vic2NyaXB0aW9ucyA9IHRoaXMuc3Vic2NyaXB0aW9ucy5nZXQoY2xhc3NOYW1lKTtcbiAgICBpZiAoIXN1YnNjcmlwdGlvbi5oYXNTdWJzY3JpYmluZ0NsaWVudCgpKSB7XG4gICAgICBjbGFzc1N1YnNjcmlwdGlvbnMuZGVsZXRlKHN1YnNjcmlwdGlvbi5oYXNoKTtcbiAgICB9XG4gICAgLy8gSWYgdGhlcmUgaXMgbm8gc3Vic2NyaXB0aW9ucyB1bmRlciB0aGlzIGNsYXNzLCByZW1vdmUgaXQgZnJvbSBzdWJzY3JpcHRpb25zXG4gICAgaWYgKGNsYXNzU3Vic2NyaXB0aW9ucy5zaXplID09PSAwKSB7XG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZGVsZXRlKGNsYXNzTmFtZSk7XG4gICAgfVxuICAgIHJ1bkxpdmVRdWVyeUV2ZW50SGFuZGxlcnMoe1xuICAgICAgY2xpZW50LFxuICAgICAgZXZlbnQ6ICd1bnN1YnNjcmliZScsXG4gICAgICBjbGllbnRzOiB0aGlzLmNsaWVudHMuc2l6ZSxcbiAgICAgIHN1YnNjcmlwdGlvbnM6IHRoaXMuc3Vic2NyaXB0aW9ucy5zaXplLFxuICAgICAgc2Vzc2lvblRva2VuOiBzdWJzY3JpcHRpb25JbmZvLnNlc3Npb25Ub2tlbixcbiAgICAgIHVzZU1hc3RlcktleTogY2xpZW50Lmhhc01hc3RlcktleSxcbiAgICAgIGluc3RhbGxhdGlvbklkOiBjbGllbnQuaW5zdGFsbGF0aW9uSWQsXG4gICAgfSk7XG5cbiAgICBpZiAoIW5vdGlmeUNsaWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNsaWVudC5wdXNoVW5zdWJzY3JpYmUocmVxdWVzdC5yZXF1ZXN0SWQpO1xuXG4gICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICBgRGVsZXRlIGNsaWVudDogJHtwYXJzZVdlYnNvY2tldC5jbGllbnRJZH0gfCBzdWJzY3JpcHRpb246ICR7cmVxdWVzdC5yZXF1ZXN0SWR9YFxuICAgICk7XG4gIH1cbn1cblxuZXhw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
|