@lifeready/core 6.1.3 → 6.1.4

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.
Files changed (75) hide show
  1. package/bundles/lifeready-core.umd.js +301 -293
  2. package/bundles/lifeready-core.umd.js.map +1 -1
  3. package/bundles/lifeready-core.umd.min.js +1 -1
  4. package/bundles/lifeready-core.umd.min.js.map +1 -1
  5. package/esm2015/lib/auth/auth.config.js +57 -0
  6. package/esm2015/lib/auth/auth.gql.private.js +85 -0
  7. package/esm2015/lib/auth/auth.service.js +602 -0
  8. package/esm2015/lib/auth/auth.types.js +21 -0
  9. package/esm2015/lib/item/item.gql.js +164 -0
  10. package/esm2015/lib/item/item.gql.private.js +23 -0
  11. package/esm2015/lib/item/item.service.js +592 -0
  12. package/esm2015/lib/item/item.types.js +2 -0
  13. package/esm2015/lib/key-exchange/key-exchange.gql.js +174 -0
  14. package/esm2015/lib/key-exchange/key-exchange.service.js +480 -0
  15. package/esm2015/lib/lbop/lbop.service.js +7 -15
  16. package/esm2015/lib/life-ready.module.js +2 -2
  17. package/esm2015/lib/password/password.service.js +1 -1
  18. package/esm2015/lib/plan/plan.gql.js +91 -0
  19. package/esm2015/lib/plan/plan.service.js +191 -0
  20. package/esm2015/lib/plan/plan.types.js +2 -0
  21. package/esm2015/lib/profile/profile.gql.js +2 -2
  22. package/esm2015/lib/profile/profile.service.js +1 -8
  23. package/esm2015/lib/profile/profile.types.js +1 -8
  24. package/esm2015/lib/scenario/scenario.service.js +8 -8
  25. package/esm2015/lib/shared-contact-card/shared-contact-card2.service.js +1 -1
  26. package/esm2015/lib/trusted-party/trusted-party.gql.js +64 -0
  27. package/esm2015/lib/trusted-party/trusted-party.gql.private.js +25 -0
  28. package/esm2015/lib/trusted-party/trusted-party.service.js +240 -0
  29. package/esm2015/lib/trusted-party/trusted-party.types.js +2 -0
  30. package/esm2015/public-api.js +17 -12
  31. package/fesm2015/lifeready-core.js +189 -211
  32. package/fesm2015/lifeready-core.js.map +1 -1
  33. package/lib/{auth2/auth2.service.d.ts → auth/auth.service.d.ts} +2 -2
  34. package/lib/{item2/item2.service.d.ts → item/item.service.d.ts} +39 -39
  35. package/lib/key-exchange/{key-exchange2.service.d.ts → key-exchange.service.d.ts} +2 -2
  36. package/lib/lbop/lbop.service.d.ts +1 -5
  37. package/lib/password/password.service.d.ts +1 -1
  38. package/lib/{plan2/plan2.service.d.ts → plan/plan.service.d.ts} +20 -20
  39. package/lib/profile/profile.service.d.ts +1 -2
  40. package/lib/profile/profile.types.d.ts +2 -15
  41. package/lib/scenario/scenario.service.d.ts +3 -3
  42. package/lib/shared-contact-card/shared-contact-card2.service.d.ts +1 -1
  43. package/lib/trusted-party/{trusted-party2.service.d.ts → trusted-party.service.d.ts} +6 -6
  44. package/lifeready-core.metadata.json +1 -1
  45. package/package.json +1 -1
  46. package/public-api.d.ts +16 -11
  47. package/esm2015/lib/auth2/auth.config.js +0 -57
  48. package/esm2015/lib/auth2/auth2.gql.private.js +0 -85
  49. package/esm2015/lib/auth2/auth2.service.js +0 -602
  50. package/esm2015/lib/auth2/auth2.types.js +0 -21
  51. package/esm2015/lib/item2/item2.gql.js +0 -164
  52. package/esm2015/lib/item2/item2.gql.private.js +0 -23
  53. package/esm2015/lib/item2/item2.service.js +0 -592
  54. package/esm2015/lib/item2/item2.types.js +0 -2
  55. package/esm2015/lib/key-exchange/key-exchange2.gql.js +0 -174
  56. package/esm2015/lib/key-exchange/key-exchange2.service.js +0 -480
  57. package/esm2015/lib/plan2/plan2.gql.js +0 -91
  58. package/esm2015/lib/plan2/plan2.service.js +0 -191
  59. package/esm2015/lib/plan2/plan2.types.js +0 -2
  60. package/esm2015/lib/trusted-party/trusted-party2.gql.js +0 -64
  61. package/esm2015/lib/trusted-party/trusted-party2.gql.private.js +0 -25
  62. package/esm2015/lib/trusted-party/trusted-party2.service.js +0 -240
  63. package/esm2015/lib/trusted-party/trusted-party2.types.js +0 -2
  64. /package/lib/{auth2 → auth}/auth.config.d.ts +0 -0
  65. /package/lib/{auth2/auth2.gql.private.d.ts → auth/auth.gql.private.d.ts} +0 -0
  66. /package/lib/{auth2/auth2.types.d.ts → auth/auth.types.d.ts} +0 -0
  67. /package/lib/{item2/item2.gql.d.ts → item/item.gql.d.ts} +0 -0
  68. /package/lib/{item2/item2.gql.private.d.ts → item/item.gql.private.d.ts} +0 -0
  69. /package/lib/{item2/item2.types.d.ts → item/item.types.d.ts} +0 -0
  70. /package/lib/key-exchange/{key-exchange2.gql.d.ts → key-exchange.gql.d.ts} +0 -0
  71. /package/lib/{plan2/plan2.gql.d.ts → plan/plan.gql.d.ts} +0 -0
  72. /package/lib/{plan2/plan2.types.d.ts → plan/plan.types.d.ts} +0 -0
  73. /package/lib/trusted-party/{trusted-party2.gql.d.ts → trusted-party.gql.d.ts} +0 -0
  74. /package/lib/trusted-party/{trusted-party2.gql.private.d.ts → trusted-party.gql.private.d.ts} +0 -0
  75. /package/lib/trusted-party/{trusted-party2.types.d.ts → trusted-party.types.d.ts} +0 -0
@@ -1,602 +0,0 @@
1
- var Auth2Service_1;
2
- import { __awaiter, __decorate } from "tslib";
3
- import { HttpClient } from '@angular/common/http';
4
- import { Inject, Injectable, Injector, isDevMode, NgZone } from '@angular/core';
5
- import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
6
- import { Hub } from '@aws-amplify/core';
7
- import { JWK } from 'node-jose';
8
- import { LrGraphQLService, LrMutation, LrService } from '../api/lr-graphql';
9
- import { TpClaimState } from '../api/types';
10
- import { EncryptionService } from '../encryption/encryption.service';
11
- import { IdleService } from '../idle/idle.service';
12
- import { KeyFactoryService } from '../key/key-factory.service';
13
- import { KeyGraphService } from '../key/key-graph.service';
14
- import { KeyService } from '../key/key.service';
15
- import { KC_CONFIG } from '../life-ready.config';
16
- import { PasswordService } from '../password/password.service';
17
- import { PersistService } from '../persist/persist.service';
18
- import { TP_PASSWORD_RESET_CLIENT_NONCE_LENGTH, TP_PASSWORD_RESET_USERNAME_SUFFIX, } from '../tp-password-reset/tp-password-reset.constants';
19
- import { TpPasswordResetAssemblyController } from '../tp-password-reset/tp-password-reset.controller';
20
- import { CompleteTpPasswordResetRequestMutation, CreateTpAssemblyKeyChallengeMutation, PreCompleteTpPasswordResetRequestMutation, } from '../tp-password-reset/tp-password-reset.gql';
21
- import { KcBadRequestException, KcBadStateException, KcConcurrentAccessException, KcInternalErrorException, } from '../_common/exceptions';
22
- import { KeyContainer } from '../_common/key';
23
- import { RunOutsideAngular } from '../_common/run-outside-angular';
24
- import { CurrentUserQuery, ResetUserQuery, SetSessionEncryptionKeyMutation, } from './auth2.gql.private';
25
- import { CognitoChallengeName, PasswordChangeStatus, RecoveryStatus, } from './auth2.types';
26
- import * as i0 from "@angular/core";
27
- import * as i1 from "@angular/common/http";
28
- import * as i2 from "@aws-amplify/auth/lib-esm/Auth";
29
- import * as i3 from "../api/lr-graphql/lr-graphql.service";
30
- import * as i4 from "../key/key.service";
31
- import * as i5 from "../key/key-graph.service";
32
- import * as i6 from "../key/key-factory.service";
33
- import * as i7 from "../password/password.service";
34
- import * as i8 from "../idle/idle.service";
35
- import * as i9 from "../persist/persist.service";
36
- import * as i10 from "../encryption/encryption.service";
37
- import * as i11 from "../tp-password-reset/tp-password-reset.controller";
38
- import * as i12 from "../life-ready.config";
39
- let Auth2Service = Auth2Service_1 = class Auth2Service extends LrService {
40
- constructor(ngZone, injector, http, cognito, api, keyService, keyGraphService, keyFactoryService, passwordService, idleService, persistService, encryptionService, assemblyController, kcConfig) {
41
- super(injector);
42
- this.ngZone = ngZone;
43
- this.injector = injector;
44
- this.http = http;
45
- this.cognito = cognito;
46
- this.api = api;
47
- this.keyService = keyService;
48
- this.keyGraphService = keyGraphService;
49
- this.keyFactoryService = keyFactoryService;
50
- this.passwordService = passwordService;
51
- this.idleService = idleService;
52
- this.persistService = persistService;
53
- this.encryptionService = encryptionService;
54
- this.assemblyController = assemblyController;
55
- this.kcConfig = kcConfig;
56
- // Could use rxjs observables here. But trying to have kc-client use as little angular
57
- // features as possible. Rxjs is not used anywhere else in kc-client.
58
- this.logoutListeners = new Set();
59
- // Stores the password for use after mfa verification to decrypt masterKey.
60
- this.password = null;
61
- if (!isDevMode()) {
62
- if (this.kcConfig.debug != null) {
63
- throw new KcBadRequestException('In production mode, "KcConfig.debug" must be set to null');
64
- }
65
- }
66
- }
67
- importPassword(plainPassword) {
68
- return this.keyFactoryService.importPassword(plainPassword);
69
- }
70
- logout() {
71
- var _a;
72
- return __awaiter(this, void 0, void 0, function* () {
73
- // Notify all listeners to clean up.
74
- yield Promise.all([...this.logoutListeners].map((callback) => callback()));
75
- this.user = null;
76
- this.keyService.purgeKeys();
77
- this.keyGraphService.purgeKeys();
78
- // Sign out on both cognito and kc-server
79
- yield Promise.all([this.cognito.signOut(), this.kcLogout()]);
80
- if ((_a = this.kcConfig.debug) === null || _a === void 0 ? void 0 : _a.username) {
81
- this.kcConfig.debug.username = null;
82
- }
83
- });
84
- }
85
- addLogoutListener(callback) {
86
- this.logoutListeners.add(callback);
87
- }
88
- removeLogoutListener(callback) {
89
- this.logoutListeners.delete(callback);
90
- }
91
- login(emailOrPhone, password, { tpPasswordResetAutoComplete = true } = {}) {
92
- var _a;
93
- return __awaiter(this, void 0, void 0, function* () {
94
- let loginResult = yield this.loginImpl(emailOrPhone, password);
95
- // Save the password for use after meeting challenge.
96
- if (loginResult.challenge) {
97
- this.password = new KeyContainer(password, Auth2Service_1.CHALLENGE_TIMEOUT);
98
- return loginResult;
99
- }
100
- if (tpPasswordResetAutoComplete &&
101
- ((_a = loginResult.user.resetUser) === null || _a === void 0 ? void 0 : _a.state) === TpClaimState.APPROVED) {
102
- yield this.completeResetRequest(password);
103
- loginResult = yield this.loginImpl(emailOrPhone, password);
104
- }
105
- return loginResult;
106
- });
107
- }
108
- verifyLogin(options) {
109
- return __awaiter(this, void 0, void 0, function* () {
110
- const { challenge, code, rememberMe } = options;
111
- const VALID_CHALLENGE_NAMES = [
112
- CognitoChallengeName.SMS_MFA,
113
- CognitoChallengeName.SOFTWARE_TOKEN_MFA,
114
- ];
115
- if (!VALID_CHALLENGE_NAMES.includes(challenge.cognitoUser.challengeName)) {
116
- throw new KcBadRequestException(`challengeName must be one of ${VALID_CHALLENGE_NAMES}`);
117
- }
118
- // TODO: this.auth.confirmSignIn() could return another challenge.
119
- const cognitoUser = yield this.cognito.confirmSignIn(challenge.cognitoUser, code, challenge.cognitoUser.challengeName);
120
- yield this.handlePostAuth(challenge.recoveryStatus);
121
- const user = yield this.loadUser(cognitoUser, this.password.pop());
122
- // This is not strictly necessary since the this.password.pop() already clears the
123
- // password inside the container. But doesn't hurt either.
124
- this.password = null;
125
- if (rememberMe) {
126
- cognitoUser.setDeviceStatusRemembered({
127
- onSuccess: () => {
128
- return;
129
- },
130
- onFailure: (e) => console.error(e),
131
- });
132
- }
133
- return {
134
- user,
135
- };
136
- });
137
- }
138
- getUser() {
139
- return __awaiter(this, void 0, void 0, function* () {
140
- if (this.user) {
141
- return this.user;
142
- }
143
- const cognitoUser = yield this.cognito.currentAuthenticatedUser();
144
- return this.loadUser(cognitoUser);
145
- });
146
- }
147
- refreshAccessToken() {
148
- return __awaiter(this, void 0, void 0, function* () {
149
- const cognitoUser = yield this.cognito.currentAuthenticatedUser();
150
- const refreshToken = cognitoUser.getSignInUserSession().getRefreshToken();
151
- console.log('Token refresh...');
152
- return new Promise((resolve, reject) => {
153
- cognitoUser.refreshSession(refreshToken, (err) => {
154
- if (err) {
155
- console.error('Error refreshing token: ', err);
156
- reject(err);
157
- }
158
- else {
159
- console.log('Token refresh complete');
160
- resolve(0);
161
- }
162
- });
163
- });
164
- });
165
- }
166
- // ----------------------------------------------------------------------------------------------------
167
- // Helpers
168
- // ----------------------------------------------------------------------------------------------------
169
- fetchCurrentUser() {
170
- return __awaiter(this, void 0, void 0, function* () {
171
- return (yield this.api.query({
172
- query: CurrentUserQuery,
173
- processorOptions: {
174
- hasKeys: false,
175
- },
176
- })).currentUser;
177
- });
178
- }
179
- fetchResetUser() {
180
- return __awaiter(this, void 0, void 0, function* () {
181
- return (yield this.api.query({
182
- query: ResetUserQuery,
183
- processorOptions: {
184
- hasKeys: false,
185
- },
186
- })).tpPasswordResetUser;
187
- });
188
- }
189
- kcLogout() {
190
- return __awaiter(this, void 0, void 0, function* () {
191
- yield this.http
192
- .post(`${this.kcConfig.authUrl}auth/sign-out/`, null, {
193
- withCredentials: true,
194
- responseType: 'text',
195
- })
196
- .toPromise();
197
- });
198
- }
199
- fetchPassIdpParams(emailOrPhone) {
200
- return __awaiter(this, void 0, void 0, function* () {
201
- return yield this.http
202
- .get(`${this.kcConfig.authUrl}users/pass-idp-params/?login_name=${encodeURIComponent(emailOrPhone)}`)
203
- .toPromise();
204
- });
205
- }
206
- loginImpl(emailOrPhone, password) {
207
- return __awaiter(this, void 0, void 0, function* () {
208
- yield this.logout();
209
- const loginIdpResult = yield this.loginIdp(emailOrPhone, password);
210
- // Can't get the user yet because we still ned to meet MFA challenges
211
- if ([
212
- CognitoChallengeName.SMS_MFA,
213
- CognitoChallengeName.SOFTWARE_TOKEN_MFA,
214
- ].includes(loginIdpResult.cognitoUser.challengeName)) {
215
- return {
216
- challenge: {
217
- cognitoUser: loginIdpResult.cognitoUser,
218
- recoveryStatus: loginIdpResult.recoveryStatus,
219
- },
220
- };
221
- }
222
- yield this.handlePostAuth(loginIdpResult.recoveryStatus);
223
- // There should be no MFA on the TP reset user.
224
- const user = yield this.loadUser(loginIdpResult.cognitoUser, password);
225
- return {
226
- user,
227
- };
228
- });
229
- }
230
- loginIdp(emailOrPhone, password) {
231
- return __awaiter(this, void 0, void 0, function* () {
232
- // Download the salt needed to derive the PassIdp
233
- const passIdpApiResult = yield this.fetchPassIdpParams(emailOrPhone);
234
- if (passIdpApiResult.passwordChangeStatus === PasswordChangeStatus.IN_PROGRESS) {
235
- throw new KcConcurrentAccessException('A password change is in progress');
236
- }
237
- if (passIdpApiResult.passwordChangeStatus === PasswordChangeStatus.RECOVERY) {
238
- console.log('In recovery mode.');
239
- // Let's say we don't know if the password is the new one or the old one. We just have to try both.
240
- try {
241
- const user = {
242
- cognitoUser: yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.newPassIdpParams),
243
- recoveryStatus: RecoveryStatus.NEW_PASSWORD,
244
- };
245
- // New password worked. Let's set to the current password
246
- // --Potential Failure Point 1--
247
- // if changePasswordComplete() doesn't get called, then it should remain
248
- console.log('New password works!');
249
- return user;
250
- }
251
- catch (error) {
252
- // Just bubble up any other type of error.
253
- if (error.code !== 'NotAuthorizedException') {
254
- throw error;
255
- }
256
- // pass, try again assuming it's the old password
257
- }
258
- // Now assume it's the previous password. Any exception is allowed to bubble up.
259
- try {
260
- const user = {
261
- cognitoUser: yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.currentPassIdpParams),
262
- recoveryStatus: RecoveryStatus.OLD_PASSWORD,
263
- };
264
- // Old password worked.
265
- console.log('Old password works!');
266
- return user;
267
- }
268
- catch (error) {
269
- // Just bubble up any other type of error.
270
- throw error.code === 'NotAuthorizedException'
271
- ? new KcBadRequestException('The password change request was interrupted, please try to login with both your new and old password')
272
- : error;
273
- }
274
- }
275
- // Try again as the TP password reset account
276
- if (passIdpApiResult.tpPasswordReset) {
277
- try {
278
- // TP password reset is in process. We need to try the password against both
279
- // original account and the new reset account.
280
- const reset = passIdpApiResult.tpPasswordReset;
281
- const user = {
282
- cognitoUser: yield this.loginIdpImpl(reset.resetUsername, password, reset.passIdpParams),
283
- recoveryStatus: RecoveryStatus.NONE,
284
- };
285
- return user;
286
- }
287
- catch (err) {
288
- // continue, try again as regular user.
289
- }
290
- }
291
- // Login as regular user
292
- const user = {
293
- cognitoUser: yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.currentPassIdpParams),
294
- recoveryStatus: RecoveryStatus.NONE,
295
- };
296
- return user;
297
- });
298
- }
299
- loginIdpImpl(emailOrPhone, password, passIdpParams) {
300
- return __awaiter(this, void 0, void 0, function* () {
301
- const passIdpResult = yield this.keyFactoryService.derivePassIdp(Object.assign({ password }, passIdpParams));
302
- // Use the derived password to signin with cognito
303
- return this.cognito.signIn(emailOrPhone, this.passwordService.getPassIdpString(passIdpResult.jwk));
304
- });
305
- }
306
- handlePostAuth(recoveryStatus) {
307
- return __awaiter(this, void 0, void 0, function* () {
308
- yield this.handlePasswordRecovery(recoveryStatus);
309
- yield this.handleSessionEncryptionKey();
310
- });
311
- }
312
- handlePasswordRecovery(recoveryStatus) {
313
- return __awaiter(this, void 0, void 0, function* () {
314
- if (recoveryStatus !== RecoveryStatus.NONE) {
315
- yield this.passwordService.changePasswordComplete({
316
- useNewPassword: recoveryStatus === RecoveryStatus.NEW_PASSWORD,
317
- });
318
- }
319
- });
320
- }
321
- handleSessionEncryptionKey() {
322
- return __awaiter(this, void 0, void 0, function* () {
323
- if (this.kcConfig.disableSessionEncryptionKey) {
324
- if (!isDevMode()) {
325
- const msg = 'You should not set disableSessionEncryptionKey=True in mode prod. It defaults to false.';
326
- console.error(msg);
327
- throw new KcInternalErrorException(msg);
328
- }
329
- else {
330
- console.warn('You have set disableSessionEncryptionKey=True. Make sure not to do this in prod mode.');
331
- }
332
- }
333
- else {
334
- // Set the session key to a new encryption key for this session
335
- const sessionEncryptionKey = yield this.keyFactoryService.createKey();
336
- yield this.lrGraphQL.lrMutate(new LrMutation({
337
- mutation: SetSessionEncryptionKeyMutation,
338
- variables: {
339
- input: {
340
- sessionEncryptionKey: JSON.stringify(sessionEncryptionKey.toJSON(true)),
341
- },
342
- },
343
- }), {
344
- includeKeyGraph: false,
345
- });
346
- this.persistService.setServerSessionEncryptionKey(sessionEncryptionKey);
347
- }
348
- });
349
- }
350
- getCognitoUserAttribute(attributeName, userAttributes) {
351
- const userAttribute = userAttributes.find((x) => x.getName() === attributeName);
352
- return userAttribute ? userAttribute.getValue() : null;
353
- }
354
- loadUserKeys(options) {
355
- return __awaiter(this, void 0, void 0, function* () {
356
- const { userKeys, password, sessionEncryptionKey } = options;
357
- if (sessionEncryptionKey) {
358
- this.persistService.setServerSessionEncryptionKey(yield JWK.asKey(sessionEncryptionKey));
359
- }
360
- // password is not needed if the master key is already persisted.
361
- if (password) {
362
- const passKey = (yield this.keyFactoryService.derivePassKey(Object.assign({ password }, userKeys.passKey.passKeyParams))).jwk;
363
- yield this.idleService.persistMasterKey(yield this.keyGraphService.unwrapWithPassKey(userKeys.passKey.id, passKey, userKeys.masterKey.id));
364
- }
365
- });
366
- }
367
- loadUser(cognitoUser, password) {
368
- return __awaiter(this, void 0, void 0, function* () {
369
- if (cognitoUser.getUsername().endsWith(TP_PASSWORD_RESET_USERNAME_SUFFIX)) {
370
- this.user = yield this.loadResetUser(cognitoUser, password);
371
- }
372
- else {
373
- this.user = yield this.loadRegularUser(cognitoUser, password);
374
- }
375
- yield this.idleService.start(); // Run idleService whenever user is logged in.
376
- return this.user;
377
- });
378
- }
379
- loadRegularUser(cognitoUser, password) {
380
- return __awaiter(this, void 0, void 0, function* () {
381
- const currentUser = yield this.fetchCurrentUser();
382
- yield this.loadUserKeys({
383
- userKeys: currentUser.currentUserKey,
384
- password,
385
- sessionEncryptionKey: currentUser.sessionEncryptionKey,
386
- });
387
- // Regular user populates all keys
388
- yield this.keyGraphService.populateKeys(currentUser.currentUserKey);
389
- const { username } = currentUser;
390
- const userAttributes = yield this.cognito.userAttributes(cognitoUser);
391
- return {
392
- username,
393
- sub: this.getCognitoUserAttribute('sub', userAttributes),
394
- loginEmail: this.getCognitoUserAttribute('email', userAttributes),
395
- resetUser: null,
396
- };
397
- });
398
- }
399
- loadResetUser(cognitoUser, password) {
400
- return __awaiter(this, void 0, void 0, function* () {
401
- const resetUser = yield this.fetchResetUser();
402
- const userKeys = {
403
- passKey: {
404
- id: resetUser.passKey.id,
405
- passKeyParams: resetUser.passKey.passKeyParams,
406
- },
407
- masterKey: {
408
- id: resetUser.masterKey.id,
409
- },
410
- };
411
- yield this.loadUserKeys({
412
- userKeys,
413
- password,
414
- sessionEncryptionKey: resetUser.sessionEncryptionKey,
415
- });
416
- // Reset user only sets a subset of keys
417
- yield this.keyService.setKeys(userKeys);
418
- const { username } = resetUser;
419
- const userAttributes = yield this.cognito.userAttributes(cognitoUser);
420
- return {
421
- username,
422
- sub: this.getCognitoUserAttribute('sub', userAttributes),
423
- loginEmail: this.getCognitoUserAttribute('email', userAttributes),
424
- resetUser: {
425
- state: resetUser.state,
426
- },
427
- };
428
- });
429
- }
430
- recoverAssemblyKey(resetUser) {
431
- return __awaiter(this, void 0, void 0, function* () {
432
- const prk = yield this.keyGraphService.getKey(resetUser.pxk.id);
433
- const partials = yield Promise.all(resetUser.approvals
434
- .filter((approval) => !!approval.receiverCipherPartialAssemblyKey)
435
- .map((approval) => this.encryptionService.decrypt(prk, approval.receiverCipherPartialAssemblyKey)));
436
- return this.assemblyController.recoverAssemblyKey(partials);
437
- });
438
- }
439
- completeResetRequest(newPassword) {
440
- return __awaiter(this, void 0, void 0, function* () {
441
- const resetUser = yield this.fetchResetUser();
442
- if (resetUser.state !== TpClaimState.APPROVED) {
443
- throw new KcBadStateException('Password reset request has not been approved.');
444
- }
445
- // --------------------------------------------------------------
446
- // Prepare all materials to ensure there are no errors.
447
- // --------------------------------------------------------------
448
- const assemblyKey = yield this.recoverAssemblyKey(resetUser);
449
- const { rootKey } = yield this.encryptionService.decrypt(assemblyKey, resetUser.assemblyCipherData);
450
- // Making sure it's a valid key.
451
- const rootKeyJwk = yield JWK.asKey(rootKey);
452
- const masterKey = yield this.keyGraphService.getKey(resetUser.masterKey.id);
453
- const masterKeyWrappedRootKey = yield this.encryptionService.encryptToString(masterKey.jwk, rootKeyJwk.toJSON(true));
454
- // The new password
455
- const newPassIdpResult = yield this.keyFactoryService.derivePassIdp(Object.assign({ password: newPassword }, resetUser.passKey.passIdpParams));
456
- const newIdpPassword = this.passwordService.getPassIdpString(newPassIdpResult.jwk);
457
- // --------------------------------------------------------------
458
- // Get assembly key challenge
459
- // --------------------------------------------------------------
460
- const challenge = (yield this.lrGraphQL.lrMutate(new LrMutation({
461
- mutation: CreateTpAssemblyKeyChallengeMutation,
462
- variables: {
463
- input: {},
464
- },
465
- }), {
466
- includeKeyGraph: false,
467
- })).createTpAssemblyKeyChallenge.challenge;
468
- // Sign the challenge
469
- // Generate a client side nonce that's no in the server's control.
470
- challenge.clientNonce = this.keyFactoryService.randomString(TP_PASSWORD_RESET_CLIENT_NONCE_LENGTH);
471
- const assemblyKeyVerifierPrk = yield this.encryptionService.decrypt(assemblyKey, resetUser.wrappedAssemblyKeyVerifierPrk);
472
- const signedChallenge = yield this.encryptionService.sign(assemblyKeyVerifierPrk, challenge);
473
- // --------------------------------------------------------------
474
- // Change password for the original user
475
- // --------------------------------------------------------------
476
- const tempIdpPassword = (yield this.lrGraphQL.lrMutate(new LrMutation({
477
- mutation: PreCompleteTpPasswordResetRequestMutation,
478
- variables: {
479
- input: {
480
- signedChallenge: JSON.stringify(signedChallenge),
481
- },
482
- },
483
- }), {
484
- includeKeyGraph: false,
485
- })).preCompleteTpPasswordResetRequest.idpPassword;
486
- // --------------------------------------------------------------
487
- // Login as the original user using new temporary password
488
- // --------------------------------------------------------------
489
- // At this point, the original account's password has been changed
490
- // to a temporary password. It is no longer possible for the user
491
- // to use the original password to login. Any successful login
492
- // can only be using the temporary password. So it's safe to assume
493
- // that we want to "complete" the password reset.
494
- // There maybe 2FA so we listen for the auth event from Amplify.
495
- const retPromise = new Promise((resolve) => {
496
- const listener = (data) => __awaiter(this, void 0, void 0, function* () {
497
- if (data.payload.event !== 'signIn') {
498
- return;
499
- }
500
- Hub.remove('auth', listener);
501
- yield this.cognito.signIn(resetUser.username, newIdpPassword);
502
- // Switch over to the new set of keys
503
- yield this.lrGraphQL.lrMutate(new LrMutation({
504
- mutation: CompleteTpPasswordResetRequestMutation,
505
- variables: {
506
- input: {
507
- masterKeyWrappedRootKey,
508
- masterKeyId: masterKey.id,
509
- },
510
- },
511
- }));
512
- resolve();
513
- });
514
- Hub.listen('auth', listener);
515
- });
516
- // Signin as the original user. Password has been reset to temporary one. It should return
517
- // with NEW_PASSWORD_REQUIRED
518
- let user = yield this.cognito.signIn(resetUser.username, tempIdpPassword, {
519
- noProxy: 'true',
520
- });
521
- if (user.challengeName !== 'NEW_PASSWORD_REQUIRED') {
522
- throw new KcInternalErrorException('Expecting Cognito to have done a password reset after call to PreCompleteTpPasswordResetRequestMutation.');
523
- }
524
- // Set new password on Idp
525
- // the awsFetch() function passes NEW_PASSWORD_REQUIRED directly to AWS without
526
- // going through the proxy.
527
- user = yield this.cognito.completeNewPassword(user, newIdpPassword, {});
528
- return retPromise;
529
- });
530
- }
531
- // ------------------------------------------------------
532
- // Debug utilities
533
- // ------------------------------------------------------
534
- debugLogin(username, password) {
535
- // This will fail if debug is null. But when debug is null, this function
536
- // should not be called.
537
- this.kcConfig.debug.username = username;
538
- return this.debugLoadUser(password);
539
- }
540
- debugLoadUser(password) {
541
- return __awaiter(this, void 0, void 0, function* () {
542
- const currentUser = yield this.fetchCurrentUser();
543
- const { username, currentUserKey } = currentUser;
544
- // Debug mode can not deal with session encryption key yet.
545
- // NO SESSION ENCRYPTION KEY.
546
- const passKey = (yield this.keyFactoryService.derivePassKey(Object.assign({ password }, currentUserKey.passKey.passKeyParams))).jwk;
547
- const masterKey = yield this.keyGraphService.unwrapWithPassKey(currentUserKey.passKey.id, passKey, currentUserKey.masterKey.id);
548
- yield this.idleService.persistMasterKey(masterKey);
549
- yield this.keyGraphService.populateKeys(currentUserKey);
550
- this.user = {
551
- username,
552
- resetUser: null,
553
- sub: 'DEBUG_MODE',
554
- loginEmail: 'DEBUG_MODE',
555
- };
556
- return this.user;
557
- });
558
- }
559
- /**
560
- * Clears the caches user. So we can simulate a page refresh and test getUser().
561
- */
562
- debugClearUser() {
563
- this.user = null;
564
- }
565
- getCurrentUserAttributes() {
566
- return __awaiter(this, void 0, void 0, function* () {
567
- const cognitoUser = yield this.cognito.currentAuthenticatedUser();
568
- const userAttributes = yield this.cognito.userAttributes(cognitoUser);
569
- return userAttributes;
570
- });
571
- }
572
- };
573
- Auth2Service.CHALLENGE_TIMEOUT = 1000 * 60 * 5;
574
- Auth2Service.ɵprov = i0.ɵɵdefineInjectable({ factory: function Auth2Service_Factory() { return new Auth2Service(i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i0.INJECTOR), i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(i2.AuthClass), i0.ɵɵinject(i3.LrGraphQLService), i0.ɵɵinject(i4.KeyService), i0.ɵɵinject(i5.KeyGraphService), i0.ɵɵinject(i6.KeyFactoryService), i0.ɵɵinject(i7.PasswordService), i0.ɵɵinject(i8.IdleService), i0.ɵɵinject(i9.PersistService), i0.ɵɵinject(i10.EncryptionService), i0.ɵɵinject(i11.TpPasswordResetAssemblyController), i0.ɵɵinject(i12.KC_CONFIG)); }, token: Auth2Service, providedIn: "root" });
575
- Auth2Service.decorators = [
576
- { type: Injectable, args: [{
577
- providedIn: 'root',
578
- },] }
579
- ];
580
- Auth2Service.ctorParameters = () => [
581
- { type: NgZone },
582
- { type: Injector },
583
- { type: HttpClient },
584
- { type: AuthClass },
585
- { type: LrGraphQLService },
586
- { type: KeyService },
587
- { type: KeyGraphService },
588
- { type: KeyFactoryService },
589
- { type: PasswordService },
590
- { type: IdleService },
591
- { type: PersistService },
592
- { type: EncryptionService },
593
- { type: TpPasswordResetAssemblyController },
594
- { type: undefined, decorators: [{ type: Inject, args: [KC_CONFIG,] }] }
595
- ];
596
- Auth2Service = Auth2Service_1 = __decorate([
597
- RunOutsideAngular({
598
- ngZoneName: 'ngZone',
599
- })
600
- ], Auth2Service);
601
- export { Auth2Service };
602
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aDIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvcmUvc3JjL2xpYi9hdXRoMi9hdXRoMi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWhGLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUMzRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNoQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDNUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDckUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsVUFBVSxFQUFZLE1BQU0sb0JBQW9CLENBQUM7QUFFMUQsT0FBTyxFQUFZLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzNELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxFQUNMLHFDQUFxQyxFQUNyQyxpQ0FBaUMsR0FD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SUFBSTtnQkFDZixHQUFHLEVBQUUsWUFBWTtnQkFDakIsVUFBVSxFQUFFLFlBQVk7YUFDekIsQ0FBQztZQUVGLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztRQUNuQixDQUFDO0tBQUE7SUFFRDs7T0FFRztJQUNILGNBQWM7UUFDWixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNuQixDQUFDO0lBRUssd0JBQXdCOztZQUM1QixNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUNsRSxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXRFLE9BQU8sY0FBYyxDQUFDO1FBQ3hCLENBQUM7S0FBQTtDQUNGLENBQUE7QUE1dkJRLDhCQUFpQixHQUFHLElBQUksR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDOzs7WUFKMUMsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7WUE3RGlELE1BQU07WUFBM0IsUUFBUTtZQUQ1QixVQUFVO1lBR1YsU0FBUztZQUlULGdCQUFnQjtZQU1oQixVQUFVO1lBRFYsZUFBZTtZQURmLGlCQUFpQjtZQUtqQixlQUFlO1lBTmYsV0FBVztZQU9YLGNBQWM7WUFSZCxpQkFBaUI7WUFhakIsaUNBQWlDOzRDQWlFckMsTUFBTSxTQUFDLFNBQVM7O0FBeEJSLFlBQVk7SUFOeEIsaUJBQWlCLENBQUM7UUFDakIsVUFBVSxFQUFFLFFBQVE7S0FDckIsQ0FBQztHQUlXLFlBQVksQ0E2dkJ4QjtTQTd2QlksWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIEluamVjdG9yLCBpc0Rldk1vZGUsIE5nWm9uZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29nbml0b1VzZXIgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aCc7XG5pbXBvcnQgeyBBdXRoQ2xhc3MgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aC9saWItZXNtL0F1dGgnO1xuaW1wb3J0IHsgSHViIH0gZnJvbSAnQGF3cy1hbXBsaWZ5L2NvcmUnO1xuaW1wb3J0IHsgQ29nbml0b1VzZXJBdHRyaWJ1dGUgfSBmcm9tICdhbWF6b24tY29nbml0by1pZGVudGl0eS1qcyc7XG5pbXBvcnQgeyBKV0sgfSBmcm9tICdub2RlLWpvc2UnO1xuaW1wb3J0IHsgTHJHcmFwaFFMU2VydmljZSwgTHJNdXRhdGlvbiwgTHJTZXJ2aWNlIH0gZnJvbSAnLi4vYXBpL2xyLWdyYXBocWwnO1xuaW1wb3J0IHsgVHBDbGFpbVN0YXRlIH0gZnJvbSAnLi4vYXBpL3R5cGVzJztcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vZW5jcnlwdGlvbi9lbmNyeXB0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgSWRsZVNlcnZpY2UgfSBmcm9tICcuLi9pZGxlL2lkbGUuc2VydmljZSc7XG5pbXBvcnQgeyBLZXlGYWN0b3J5U2VydmljZSB9IGZyb20gJy4uL2tleS9rZXktZmFjdG9yeS5zZXJ2aWNlJztcbmltcG9ydCB7IEtleUdyYXBoU2VydmljZSB9IGZyb20gJy4uL2tleS9rZXktZ3JhcGguc2VydmljZSc7XG5pbXBvcnQgeyBLZXlTZXJ2aWNlLCBVc2VyS2V5cyB9IGZyb20gJy4uL2tleS9rZXkuc2VydmljZSc7XG5pbXBvcnQgeyBQYXNzSWRwUGFyYW1zIH0gZnJvbSAnLi4va2V5L2tleS50eXBlcyc7XG5pbXBvcnQgeyBLY0NvbmZpZywgS0NfQ09ORklHIH0gZnJvbSAnLi4vbGlmZS1yZWFkeS5jb25maWcnO1xuaW1wb3J0IHsgUGFzc3dvcmRTZXJ2aWNlIH0gZnJvbSAnLi4vcGFzc3dvcmQvcGFzc3dvcmQuc2VydmljZSc7XG5pbXBvcnQgeyBQZXJzaXN0U2VydmljZSB9IGZyb20gJy4uL3BlcnNpc3QvcGVyc2lzdC5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIFRQX1BBU1NXT1JEX1JFU0VUX0NMSUVOVF9OT05DRV9MRU5HVEgsXG4gIFRQX1BBU1NXT1JEX1JFU0VUX1VTRVJOQU1FX1NVRkZJWCxcbn0gZnJvbSAnLi4vdHAtcGFzc3dvcmQtcmVzZXQvdHAtcGFzc3dvcmQtcmVzZXQuY29uc3RhbnRzJztcbmltcG9ydCB7IFRwUGFzc3dvcmRSZXNldEFzc2VtYmx5Q29udHJvbGxlciB9IGZyb20gJy4uL3RwLXBhc3N3b3JkLXJlc2V0L3RwLXBhc3N3b3JkLXJlc2V0LmNvbnRyb2xsZXInO1xuaW1wb3J0IHtcbiAgQ29tcGxldGVUcFBhc3N3b3JkUmVzZXRSZXF1ZXN0TXV0YXRpb24sXG4gIENyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2VNdXRhdGlvbixcbiAgUHJlQ29tcGxldGVUcFBhc3N3b3JkUmVzZXRSZXF1ZXN0TXV0YXRpb24sXG59IGZyb20gJy4uL3RwLXBhc3N3b3JkLXJlc2V0L3RwLXBhc3N3b3JkLXJlc2V0LmdxbCc7XG5pbXBvcnQge1xuICBLY0JhZFJlcXVlc3RFeGNlcHRpb24sXG4gIEtjQmFkU3RhdGVFeGNlcHRpb24sXG4gIEtjQ29uY3VycmVudEFjY2Vzc0V4Y2VwdGlvbixcbiAgS2NJbnRlcm5hbEVycm9yRXhjZXB0aW9uLFxufSBmcm9tICcuLi9fY29tbW9uL2V4Y2VwdGlvbnMnO1xuaW1wb3J0IHsgS2V5Q29udGFpbmVyIH0gZnJvbSAnLi4vX2NvbW1vbi9rZXknO1xuaW1wb3J0IHsgUnVuT3V0c2lkZUFuZ3VsYXIgfSBmcm9tICcuLi9fY29tbW9uL3J1bi1vdXRzaWRlLWFuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQ3VycmVudFVzZXJRdWVyeSxcbiAgQ3VycmVudFVzZXJRdWVyeVJlc3VsdCxcbiAgUmVzZXRVc2VyUXVlcnksXG4gIFJlc2V0VXNlclF1ZXJ5UmVzdWx0LFxuICBTZXRTZXNzaW9uRW5jcnlwdGlvbktleU11dGF0aW9uLFxufSBmcm9tICcuL2F1dGgyLmdxbC5wcml2YXRlJztcbmltcG9ydCB7XG4gIEF1dGhVc2VyLFxuICBDb2duaXRvQ2hhbGxlbmdlTmFtZSxcbiAgTG9naW5DaGFsbGVuZ2UsXG4gIExvZ2luT3B0aW9ucyxcbiAgTG9naW5SZXN1bHQsXG4gIExvZ291dExpc3RlbmVyLFxuICBMckNvZ25pdG9Vc2VyLFxuICBMckNvZ25pdG9Vc2VyQXR0cmlidXRlLFxuICBQYXNzSWRwUmVzdWx0LFxuICBQYXNzd29yZENoYW5nZVN0YXR1cyxcbiAgUmVjb3ZlcnlTdGF0dXMsXG59IGZyb20gJy4vYXV0aDIudHlwZXMnO1xuXG5AUnVuT3V0c2lkZUFuZ3VsYXIoe1xuICBuZ1pvbmVOYW1lOiAnbmdab25lJyxcbn0pXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgQXV0aDJTZXJ2aWNlIGV4dGVuZHMgTHJTZXJ2aWNlIHtcbiAgc3RhdGljIENIQUxMRU5HRV9USU1FT1VUID0gMTAwMCAqIDYwICogNTtcblxuICAvLyBDb3VsZCB1c2UgcnhqcyBvYnNlcnZhYmxlcyBoZXJlLiBCdXQgdHJ5aW5nIHRvIGhhdmUga2MtY2xpZW50IHVzZSBhcyBsaXR0bGUgYW5ndWxhclxuICAvLyBmZWF0dXJlcyBhcyBwb3NzaWJsZS4gUnhqcyBpcyBub3QgdXNlZCBhbnl3aGVyZSBlbHNlIGluIGtjLWNsaWVudC5cbiAgcHJpdmF0ZSBsb2dvdXRMaXN0ZW5lcnMgPSBuZXcgU2V0PExvZ291dExpc3RlbmVyPigpO1xuICBwcml2YXRlIHVzZXI6IEF1dGhVc2VyO1xuICAvLyBTdG9yZXMgdGhlIHBhc3N3b3JkIGZvciB1c2UgYWZ0ZXIgbWZhIHZlcmlmaWNhdGlvbiB0byBkZWNyeXB0IG1hc3RlcktleS5cbiAgcHJpdmF0ZSBwYXNzd29yZDogS2V5Q29udGFpbmVyID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG5nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcbiAgICBwcml2YXRlIGNvZ25pdG86IEF1dGhDbGFzcyxcbiAgICBwcml2YXRlIGFwaTogTHJHcmFwaFFMU2VydmljZSxcbiAgICBwcml2YXRlIGtleVNlcnZpY2U6IEtleVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBrZXlHcmFwaFNlcnZpY2U6IEtleUdyYXBoU2VydmljZSxcbiAgICBwcml2YXRlIGtleUZhY3RvcnlTZXJ2aWNlOiBLZXlGYWN0b3J5U2VydmljZSxcbiAgICBwcml2YXRlIHBhc3N3b3JkU2VydmljZTogUGFzc3dvcmRTZXJ2aWNlLFxuICAgIHByaXZhdGUgaWRsZVNlcnZpY2U6IElkbGVTZXJ2aWNlLFxuICAgIHByaXZhdGUgcGVyc2lzdFNlcnZpY2U6IFBlcnNpc3RTZXJ2aWNlLFxuICAgIHByaXZhdGUgZW5jcnlwdGlvblNlcnZpY2U6IEVuY3J5cHRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgYXNzZW1ibHlDb250cm9sbGVyOiBUcFBhc3N3b3JkUmVzZXRBc3NlbWJseUNvbnRyb2xsZXIsXG4gICAgQEluamVjdChLQ19DT05GSUcpIHByaXZhdGUga2NDb25maWc6IEtjQ29uZmlnXG4gICkge1xuICAgIHN1cGVyKGluamVjdG9yKTtcbiAgICBpZiAoIWlzRGV2TW9kZSgpKSB7XG4gICAgICBpZiAodGhpcy5rY0NvbmZpZy5kZWJ1ZyAhPSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBLY0JhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgICAgJ0luIHByb2R1Y3Rpb24gbW9kZSwgXCJLY0NvbmZpZy5kZWJ1Z1wiIG11c3QgYmUgc2V0IHRvIG51bGwnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaW1wb3J0UGFzc3dvcmQocGxhaW5QYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxDcnlwdG9LZXk+IHtcbiAgICByZXR1cm4gdGhpcy5rZXlGYWN0b3J5U2VydmljZS5pbXBvcnRQYXNzd29yZChwbGFpblBhc3N3b3JkKTtcbiAgfVxuXG4gIGFzeW5jIGxvZ291dCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBOb3RpZnkgYWxsIGxpc3RlbmVycyB0byBjbGVhbiB1cC5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChbLi4udGhpcy5sb2dvdXRMaXN0ZW5lcnNdLm1hcCgoY2FsbGJhY2spID0+IGNhbGxiYWNrKCkpKTtcblxuICAgIHRoaXMudXNlciA9IG51bGw7XG4gICAgdGhpcy5rZXlTZXJ2aWNlLnB1cmdlS2V5cygpO1xuICAgIHRoaXMua2V5R3JhcGhTZXJ2aWNlLnB1cmdlS2V5cygpO1xuXG4gICAgLy8gU2lnbiBvdXQgb24gYm90aCBjb2duaXRvIGFuZCBrYy1zZXJ2ZXJcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5jb2duaXRvLnNpZ25PdXQoKSwgdGhpcy5rY0xvZ291dCgpXSk7XG5cbiAgICBpZiAodGhpcy5rY0NvbmZpZy5kZWJ1Zz8udXNlcm5hbWUpIHtcbiAgICAgIHRoaXMua2NDb25maWcuZGVidWcudXNlcm5hbWUgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGFkZExvZ291dExpc3RlbmVyKGNhbGxiYWNrOiBMb2dvdXRMaXN0ZW5lcikge1xuICAgIHRoaXMubG9nb3V0TGlzdGVuZXJzLmFkZChjYWxsYmFjayk7XG4gIH1cblxuICByZW1vdmVMb2dvdXRMaXN0ZW5lcihjYWxsYmFjazogTG9nb3V0TGlzdGVuZXIpIHtcbiAgICB0aGlzLmxvZ291dExpc3RlbmVycy5kZWxldGUoY2FsbGJhY2spO1xuICB9XG5cbiAgYXN5bmMgbG9naW4oXG4gICAgZW1haWxPclBob25lOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IENyeXB0b0tleSxcbiAgICB7IHRwUGFzc3dvcmRSZXNldEF1dG9Db21wbGV0ZSA9IHRydWUgfTogTG9naW5PcHRpb25zID0ge31cbiAgKTogUHJvbWlzZTxMb2dpblJlc3VsdD4ge1xuICAgIGxldCBsb2dpblJlc3VsdDogTG9naW5SZXN1bHQgPSBhd2FpdCB0aGlzLmxvZ2luSW1wbChlbWFpbE9yUGhvbmUsIHBhc3N3b3JkKTtcblxuICAgIC8vIFNhdmUgdGhlIHBhc3N3b3JkIGZvciB1c2UgYWZ0ZXIgbWVldGluZyBjaGFsbGVuZ2UuXG4gICAgaWYgKGxvZ2luUmVzdWx0LmNoYWxsZW5nZSkge1xuICAgICAgdGhpcy5wYXNzd29yZCA9IG5ldyBLZXlDb250YWluZXIoXG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgICBBdXRoMlNlcnZpY2UuQ0hBTExFTkdFX1RJTUVPVVRcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBsb2dpblJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICB0cFBhc3N3b3JkUmVzZXRBdXRvQ29tcGxldGUgJiZcbiAgICAgIGxvZ2luUmVzdWx0LnVzZXIucmVzZXRVc2VyPy5zdGF0ZSA9PT0gVHBDbGFpbVN0YXRlLkFQUFJPVkVEXG4gICAgKSB7XG4gICAgICBhd2FpdCB0aGlzLmNvbXBsZXRlUmVzZXRSZXF1ZXN0KHBhc3N3b3JkKTtcbiAgICAgIGxvZ2luUmVzdWx0ID0gYXdhaXQgdGhpcy5sb2dpbkltcGwoZW1haWxPclBob25lLCBwYXNzd29yZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxvZ2luUmVzdWx0O1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5TG9naW4ob3B0aW9uczoge1xuICAgIGNoYWxsZW5nZTogTG9naW5DaGFsbGVuZ2U7XG4gICAgY29kZTogc3RyaW5nO1xuICAgIHJlbWVtYmVyTWU6IGJvb2xlYW47XG4gIH0pOiBQcm9taXNlPExvZ2luUmVzdWx0PiB7XG4gICAgY29uc3QgeyBjaGFsbGVuZ2UsIGNvZGUsIHJlbWVtYmVyTWUgfSA9IG9wdGlvbnM7XG5cbiAgICBjb25zdCBWQUxJRF9DSEFMTEVOR0VfTkFNRVMgPSBbXG4gICAgICBDb2duaXRvQ2hhbGxlbmdlTmFtZS5TTVNfTUZBLFxuICAgICAgQ29nbml0b0NoYWxsZW5nZU5hbWUuU09GVFdBUkVfVE9LRU5fTUZBLFxuICAgIF07XG5cbiAgICBpZiAoIVZBTElEX0NIQUxMRU5HRV9OQU1FUy5pbmNsdWRlcyhjaGFsbGVuZ2UuY29nbml0b1VzZXIuY2hhbGxlbmdlTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBLY0JhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgIGBjaGFsbGVuZ2VOYW1lIG11c3QgYmUgb25lIG9mICR7VkFMSURfQ0hBTExFTkdFX05BTUVTfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogdGhpcy5hdXRoLmNvbmZpcm1TaWduSW4oKSBjb3VsZCByZXR1cm4gYW5vdGhlciBjaGFsbGVuZ2UuXG4gICAgY29uc3QgY29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmNvZ25pdG8uY29uZmlybVNpZ25JbihcbiAgICAgIGNoYWxsZW5nZS5jb2duaXRvVXNlcixcbiAgICAgIGNvZGUsXG4gICAgICBjaGFsbGVuZ2UuY29nbml0b1VzZXIuY2hhbGxlbmdlTmFtZSBhc1xuICAgICAgICB8IENvZ25pdG9DaGFsbGVuZ2VOYW1lLlNNU19NRkFcbiAgICAgICAgfCBDb2duaXRvQ2hhbGxlbmdlTmFtZS5TT0ZUV0FSRV9UT0tFTl9NRkFcbiAgICApO1xuXG4gICAgYXdhaXQgdGhpcy5oYW5kbGVQb3N0QXV0aChjaGFsbGVuZ2UucmVjb3ZlcnlTdGF0dXMpO1xuXG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMubG9hZFVzZXIoY29nbml0b1VzZXIsIHRoaXMucGFzc3dvcmQucG9wKCkpO1xuXG4gICAgLy8gVGhpcyBpcyBub3Qgc3RyaWN0bHkgbmVjZXNzYXJ5IHNpbmNlIHRoZSB0aGlzLnBhc3N3b3JkLnBvcCgpIGFscmVhZHkgY2xlYXJzIHRoZVxuICAgIC8vIHBhc3N3b3JkIGluc2lkZSB0aGUgY29udGFpbmVyLiBCdXQgZG9lc24ndCBodXJ0IGVpdGhlci5cbiAgICB0aGlzLnBhc3N3b3JkID0gbnVsbDtcblxuICAgIGlmIChyZW1lbWJlck1lKSB7XG4gICAgICBjb2duaXRvVXNlci5zZXREZXZpY2VTdGF0dXNSZW1lbWJlcmVkKHtcbiAgICAgICAgb25TdWNjZXNzOiAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9LFxuICAgICAgICBvbkZhaWx1cmU6IChlKSA9PiBjb25zb2xlLmVycm9yKGUpLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXIsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGdldFVzZXIoKTogUHJvbWlzZTxBdXRoVXNlcj4ge1xuICAgIGlmICh0aGlzLnVzZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLnVzZXI7XG4gICAgfVxuXG4gICAgY29uc3QgY29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmNvZ25pdG8uY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG5cbiAgICByZXR1cm4gdGhpcy5sb2FkVXNlcihjb2duaXRvVXNlcik7XG4gIH1cblxuICBhc3luYyByZWZyZXNoQWNjZXNzVG9rZW4oKSB7XG4gICAgY29uc3QgY29nbml0b1VzZXI6IENvZ25pdG9Vc2VyID1cbiAgICAgIGF3YWl0IHRoaXMuY29nbml0by5jdXJyZW50QXV0aGVudGljYXRlZFVzZXIoKTtcbiAgICBjb25zdCByZWZyZXNoVG9rZW4gPSBjb2duaXRvVXNlci5nZXRTaWduSW5Vc2VyU2Vzc2lvbigpLmdldFJlZnJlc2hUb2tlbigpO1xuXG4gICAgY29uc29sZS5sb2coJ1Rva2VuIHJlZnJlc2guLi4nKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29nbml0b1VzZXIucmVmcmVzaFNlc3Npb24ocmVmcmVzaFRva2VuLCAoZXJyKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciByZWZyZXNoaW5nIHRva2VuOiAnLCBlcnIpO1xuICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdUb2tlbiByZWZyZXNoIGNvbXBsZXRlJyk7XG4gICAgICAgICAgcmVzb2x2ZSgwKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEhlbHBlcnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hDdXJyZW50VXNlcigpIHtcbiAgICByZXR1cm4gKFxuICAgICAgYXdhaXQgdGhpcy5hcGkucXVlcnk8Q3VycmVudFVzZXJRdWVyeVJlc3VsdD4oe1xuICAgICAgICBxdWVyeTogQ3VycmVudFVzZXJRdWVyeSxcbiAgICAgICAgcHJvY2Vzc29yT3B0aW9uczoge1xuICAgICAgICAgIGhhc0tleXM6IGZhbHNlLCAvLyBEb24ndCB0cnkgdG8gZGVjcnlwdCBhbnl0aGluZyBiZWNhdXNlIGtleXMgaGF2ZSBub3QgYmVlbiBzZXR1cCB5ZXRcbiAgICAgICAgfSxcbiAgICAgIH0pXG4gICAgKS5jdXJyZW50VXNlcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hSZXNldFVzZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIGF3YWl0IHRoaXMuYXBpLnF1ZXJ5PFJlc2V0VXNlclF1ZXJ5UmVzdWx0Pih7XG4gICAgICAgIHF1ZXJ5OiBSZXNldFVzZXJRdWVyeSxcbiAgICAgICAgcHJvY2Vzc29yT3B0aW9uczoge1xuICAgICAgICAgIGhhc0tleXM6IGZhbHNlLCAvLyBEb24ndCB0cnkgdG8gZGVjcnlwdCBhbnl0aGluZyBiZWNhdXNlIGtleXMgaGF2ZSBub3QgYmVlbiBzZXR1cCB5ZXRcbiAgICAgICAgfSxcbiAgICAgIH0pXG4gICAgKS50cFBhc3N3b3JkUmVzZXRVc2VyO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBrY0xvZ291dCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmh0dHBcbiAgICAgIC5wb3N0KGAke3RoaXMua2NDb25maWcuYXV0aFVybH1hdXRoL3NpZ24tb3V0L2AsIG51bGwsIHtcbiAgICAgICAgd2l0aENyZWRlbnRpYWxzOiB0cnVlLFxuICAgICAgICByZXNwb25zZVR5cGU6ICd0ZXh0JyxcbiAgICAgIH0pXG4gICAgICAudG9Qcm9taXNlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoUGFzc0lkcFBhcmFtcyhcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZ1xuICApOiBQcm9taXNlPFBhc3NJZHBSZXN1bHQ+IHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5odHRwXG4gICAgICAuZ2V0PFBhc3NJZHBSZXN1bHQ+KFxuICAgICAgICBgJHtcbiAgICAgICAgICB0aGlzLmtjQ29uZmlnLmF1dGhVcmxcbiAgICAgICAgfXVzZXJzL3Bhc3MtaWRwLXBhcmFtcy8/bG9naW5fbmFtZT0ke2VuY29kZVVSSUNvbXBvbmVudChlbWFpbE9yUGhvbmUpfWBcbiAgICAgIClcbiAgICAgIC50b1Byb21pc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9naW5JbXBsKFxuICAgIGVtYWlsT3JQaG9uZTogc3RyaW5nLFxuICAgIHBhc3N3b3JkOiBDcnlwdG9LZXlcbiAgKTogUHJvbWlzZTxMb2dpblJlc3VsdD4ge1xuICAgIGF3YWl0IHRoaXMubG9nb3V0KCk7XG4gICAgY29uc3QgbG9naW5JZHBSZXN1bHQgPSBhd2FpdCB0aGlzLmxvZ2luSWRwKGVtYWlsT3JQaG9uZSwgcGFzc3dvcmQpO1xuXG4gICAgLy8gQ2FuJ3QgZ2V0IHRoZSB1c2VyIHlldCBiZWNhdXNlIHdlIHN0aWxsIG5lZCB0byBtZWV0IE1GQSBjaGFsbGVuZ2VzXG4gICAgaWYgKFxuICAgICAgW1xuICAgICAgICBDb2duaXRvQ2hhbGxlbmdlTmFtZS5TTVNfTUZBLFxuICAgICAgICBDb2duaXRvQ2hhbGxlbmdlTmFtZS5TT0ZUV0FSRV9UT0tFTl9NRkEsXG4gICAgICBdLmluY2x1ZGVzKGxvZ2luSWRwUmVzdWx0LmNvZ25pdG9Vc2VyLmNoYWxsZW5nZU5hbWUpXG4gICAgKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjaGFsbGVuZ2U6IHtcbiAgICAgICAgICBjb2duaXRvVXNlcjogbG9naW5JZHBSZXN1bHQuY29nbml0b1VzZXIsXG4gICAgICAgICAgcmVjb3ZlcnlTdGF0dXM6IGxvZ2luSWRwUmVzdWx0LnJlY292ZXJ5U3RhdHVzLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmhhbmRsZVBvc3RBdXRoKGxvZ2luSWRwUmVzdWx0LnJlY292ZXJ5U3RhdHVzKTtcbiAgICAvLyBUaGVyZSBzaG91bGQgYmUgbm8gTUZBIG9uIHRoZSBUUCByZXNldCB1c2VyLlxuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmxvYWRVc2VyKGxvZ2luSWRwUmVzdWx0LmNvZ25pdG9Vc2VyLCBwYXNzd29yZCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdXNlcixcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2dpbklkcChcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcbiAgICBwYXNzd29yZDogQ3J5cHRvS2V5XG4gICk6IFByb21pc2U8TG9naW5DaGFsbGVuZ2U+IHtcbiAgICAvLyBEb3dubG9hZCB0aGUgc2FsdCBuZWVkZWQgdG8gZGVyaXZlIHRoZSBQYXNzSWRwXG4gICAgY29uc3QgcGFzc0lkcEFwaVJlc3VsdCA9IGF3YWl0IHRoaXMuZmV0Y2hQYXNzSWRwUGFyYW1zKGVtYWlsT3JQaG9uZSk7XG5cbiAgICBpZiAoXG4gICAgICBwYXNzSWRwQXBpUmVzdWx0LnBhc3N3b3JkQ2hhbmdlU3RhdHVzID09PSBQYXNzd29yZENoYW5nZVN0YXR1cy5JTl9QUk9HUkVTU1xuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEtjQ29uY3VycmVudEFjY2Vzc0V4Y2VwdGlvbignQSBwYXNzd29yZCBjaGFuZ2UgaXMgaW4gcHJvZ3Jlc3MnKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBwYXNzSWRwQXBpUmVzdWx0LnBhc3N3b3JkQ2hhbmdlU3RhdHVzID09PSBQYXNzd29yZENoYW5nZVN0YXR1cy5SRUNPVkVSWVxuICAgICkge1xuICAgICAgY29uc29sZS5sb2coJ0luIHJlY292ZXJ5IG1vZGUuJyk7XG5cbiAgICAgIC8vIExldCdzIHNheSB3ZSBkb24ndCBrbm93IGlmIHRoZSBwYXNzd29yZCBpcyB0aGUgbmV3IG9uZSBvciB0aGUgb2xkIG9uZS4gV2UganVzdCBoYXZlIHRvIHRyeSBib3RoLlxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdXNlcjogTG9naW5DaGFsbGVuZ2UgPSB7XG4gICAgICAgICAgY29nbml0b1VzZXI6IGF3YWl0IHRoaXMubG9naW5JZHBJbXBsKFxuICAgICAgICAgICAgZW1haWxPclBob25lLFxuICAgICAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgICAgICBwYXNzSWRwQXBpUmVzdWx0Lm5ld1Bhc3NJZHBQYXJhbXNcbiAgICAgICAgICApLFxuICAgICAgICAgIHJlY292ZXJ5U3RhdHVzOiBSZWNvdmVyeVN0YXR1cy5ORVdfUEFTU1dPUkQsXG4gICAgICAgIH07XG4gICAgICAgIC8vIE5ldyBwYXNzd29yZCB3b3JrZWQuIExldCdzIHNldCB0byB0aGUgY3VycmVudCBwYXNzd29yZFxuXG4gICAgICAgIC8vIC0tUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgMS0tXG4gICAgICAgIC8vIGlmIGNoYW5nZVBhc3N3b3JkQ29tcGxldGUoKSBkb2Vzbid0IGdldCBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIHJlbWFpblxuXG4gICAgICAgIGNvbnNvbGUubG9nKCdOZXcgcGFzc3dvcmQgd29ya3MhJyk7XG5cbiAgICAgICAgcmV0dXJuIHVzZXI7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBKdXN0IGJ1YmJsZSB1cCBhbnkgb3RoZXIgdHlwZSBvZiBlcnJvci5cbiAgICAgICAgaWYgKGVycm9yLmNvZGUgIT09ICdOb3RBdXRob3JpemVkRXhjZXB0aW9uJykge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIC8vIHBhc3MsIHRyeSBhZ2FpbiBhc3N1bWluZyBpdCdzIHRoZSBvbGQgcGFzc3dvcmRcbiAgICAgIH1cblxuICAgICAgLy8gTm93IGFzc3VtZSBpdCdzIHRoZSBwcmV2aW91cyBwYXNzd29yZC4gQW55IGV4Y2VwdGlvbiBpcyBhbGxvd2VkIHRvIGJ1YmJsZSB1cC5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHVzZXI6IExvZ2luQ2hhbGxlbmdlID0ge1xuICAgICAgICAgIGNvZ25pdG9Vc2VyOiBhd2FpdCB0aGlzLmxvZ2luSWRwSW1wbChcbiAgICAgICAgICAgIGVtYWlsT3JQaG9uZSxcbiAgICAgICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAgICAgcGFzc0lkcEFwaVJlc3VsdC5jdXJyZW50UGFzc0lkcFBhcmFtc1xuICAgICAgICAgICksXG4gICAgICAgICAgcmVjb3ZlcnlTdGF0dXM6IFJlY292ZXJ5U3RhdHVzLk9MRF9QQVNTV09SRCxcbiAgICAgICAgfTtcbiAgICAgICAgLy8gT2xkIHBhc3N3b3JkIHdvcmtlZC5cbiAgICAgICAgY29uc29sZS5sb2coJ09sZCBwYXNzd29yZCB3b3JrcyEnKTtcblxuICAgICAgICByZXR1cm4gdXNlcjtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIEp1c3QgYnViYmxlIHVwIGFueSBvdGhlciB0eXBlIG9mIGVycm9yLlxuICAgICAgICB0aHJvdyBlcnJvci5jb2RlID09PSAnTm90QXV0aG9yaXplZEV4Y2VwdGlvbidcbiAgICAgICAgICA/IG5ldyBLY0JhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgICAgICAgICdUaGUgcGFzc3dvcmQgY2hhbmdlIHJlcXVlc3Qgd2FzIGludGVycnVwdGVkLCBwbGVhc2UgdHJ5IHRvIGxvZ2luIHdpdGggYm90aCB5b3VyIG5ldyBhbmQgb2xkIHBhc3N3b3JkJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgIDogZXJyb3I7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVHJ5IGFnYWluIGFzIHRoZSBUUCBwYXNzd29yZCByZXNldCBhY2NvdW50XG4gICAgaWYgKHBhc3NJZHBBcGlSZXN1bHQudHBQYXNzd29yZFJlc2V0KSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBUUCBwYXNzd29yZCByZXNldCBpcyBpbiBwcm9jZXNzLiBXZSBuZWVkIHRvIHRyeSB0aGUgcGFzc3dvcmQgYWdhaW5zdCBib3RoXG4gICAgICAgIC8vIG9yaWdpbmFsIGFjY291bnQgYW5kIHRoZSBuZXcgcmVzZXQgYWNjb3VudC5cbiAgICAgICAgY29uc3QgcmVzZXQgPSBwYXNzSWRwQXBpUmVzdWx0LnRwUGFzc3dvcmRSZXNldDtcbiAgICAgICAgY29uc3QgdXNlcjogTG9naW5DaGFsbGVuZ2UgPSB7XG4gICAgICAgICAgY29nbml0b1VzZXI6IGF3YWl0IHRoaXMubG9naW5JZHBJbXBsKFxuICAgICAgICAgICAgcmVzZXQucmVzZXRVc2VybmFtZSxcbiAgICAgICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAgICAgcmVzZXQucGFzc0lkcFBhcmFtc1xuICAgICAgICAgICksXG4gICAgICAgICAgcmVjb3ZlcnlTdGF0dXM6IFJlY292ZXJ5U3RhdHVzLk5PTkUsXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHVzZXI7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgLy8gY29udGludWUsIHRyeSBhZ2FpbiBhcyByZWd1bGFyIHVzZXIuXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTG9naW4gYXMgcmVndWxhciB1c2VyXG4gICAgY29uc3QgdXNlcjogTG9naW5DaGFsbGVuZ2UgPSB7XG4gICAgICBjb2duaXRvVXNlcjogYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXG4gICAgICAgIGVtYWlsT3JQaG9uZSxcbiAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgIHBhc3NJZHBBcGlSZXN1bHQuY3VycmVudFBhc3NJZHBQYXJhbXNcbiAgICAgICksXG4gICAgICByZWNvdmVyeVN0YXR1czogUmVjb3ZlcnlTdGF0dXMuTk9ORSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHVzZXI7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvZ2luSWRwSW1wbChcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcbiAgICBwYXNzd29yZDogQ3J5cHRvS2V5LFxuICAgIHBhc3NJZHBQYXJhbXM6IFBhc3NJZHBQYXJhbXNcbiAgKTogUHJvbWlzZTxMckNvZ25pdG9Vc2VyPiB7XG4gICAgY29uc3QgcGFzc0lkcFJlc3VsdCA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeVNlcnZpY2UuZGVyaXZlUGFzc0lkcCh7XG4gICAgICBwYXNzd29yZCxcbiAgICAgIC4uLnBhc3NJZHBQYXJhbXMsXG4gICAgfSk7XG5cbiAgICAvLyBVc2UgdGhlIGRlcml2ZWQgcGFzc3dvcmQgdG8gc2lnbmluIHdpdGggY29nbml0b1xuICAgIHJldHVybiB0aGlzLmNvZ25pdG8uc2lnbkluKFxuICAgICAgZW1haWxPclBob25lLFxuICAgICAgdGhpcy5wYXNzd29yZFNlcnZpY2UuZ2V0UGFzc0lkcFN0cmluZyhwYXNzSWRwUmVzdWx0Lmp3aylcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVQb3N0QXV0aChyZWNvdmVyeVN0YXR1czogUmVjb3ZlcnlTdGF0dXMpIHtcbiAgICBhd2FpdCB0aGlzLmhhbmRsZVBhc3N3b3JkUmVjb3ZlcnkocmVjb3ZlcnlTdGF0dXMpO1xuICAgIGF3YWl0IHRoaXMuaGFuZGxlU2Vzc2lvbkVuY3J5cHRpb25LZXkoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlUGFzc3dvcmRSZWNvdmVyeShyZWNvdmVyeVN0YXR1czogUmVjb3ZlcnlTdGF0dXMpIHtcbiAgICBpZiAocmVjb3ZlcnlTdGF0dXMgIT09IFJlY292ZXJ5U3RhdHVzLk5PTkUpIHtcbiAgICAgIGF3YWl0IHRoaXMucGFzc3dvcmRTZXJ2aWNlLmNoYW5nZVBhc3N3b3JkQ29tcGxldGUoe1xuICAgICAgICB1c2VOZXdQYXNzd29yZDogcmVjb3ZlcnlTdGF0dXMgPT09IFJlY292ZXJ5U3RhdHVzLk5FV19QQVNTV09SRCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlU2Vzc2lvbkVuY3J5cHRpb25LZXkoKSB7XG4gICAgaWYgKHRoaXMua2NDb25maWcuZGlzYWJsZVNlc3Npb25FbmNyeXB0aW9uS2V5KSB7XG4gICAgICBpZiAoIWlzRGV2TW9kZSgpKSB7XG4gICAgICAgIGNvbnN0IG1zZyA9XG4gICAgICAgICAgJ1lvdSBzaG91bGQgbm90IHNldCBkaXNhYmxlU2Vzc2lvbkVuY3J5cHRpb25LZXk9VHJ1ZSBpbiBtb2RlIHByb2QuIEl0IGRlZmF1bHRzIHRvIGZhbHNlLic7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IobXNnKTtcbiAgICAgICAgdGhyb3cgbmV3IEtjSW50ZXJuYWxFcnJvckV4Y2VwdGlvbihtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICdZb3UgaGF2ZSBzZXQgZGlzYWJsZVNlc3Npb25FbmNyeXB0aW9uS2V5PVRydWUuIE1ha2Ugc3VyZSBub3QgdG8gZG8gdGhpcyBpbiBwcm9kIG1vZGUuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTZXQgdGhlIHNlc3Npb24ga2V5IHRvIGEgbmV3IGVuY3J5cHRpb24ga2V5IGZvciB0aGlzIHNlc3Npb25cbiAgICAgIGNvbnN0IHNlc3Npb25FbmNyeXB0aW9uS2V5ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5U2VydmljZS5jcmVhdGVLZXkoKTtcbiAgICAgIGF3YWl0IHRoaXMubHJHcmFwaFFMLmxyTXV0YXRlKFxuICAgICAgICBuZXcgTHJNdXRhdGlvbih7XG4gICAgICAgICAgbXV0YXRpb246IFNldFNlc3Npb25FbmNyeXB0aW9uS2V5TXV0YXRpb24sXG4gICAgICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgICAgICBpbnB1dDoge1xuICAgICAgICAgICAgICBzZXNzaW9uRW5jcnlwdGlvbktleTogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgICAgc2Vzc2lvbkVuY3J5cHRpb25LZXkudG9KU09OKHRydWUpXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgICB7XG4gICAgICAgICAgaW5jbHVkZUtleUdyYXBoOiBmYWxzZSxcbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgdGhpcy5wZXJzaXN0U2VydmljZS5zZXRTZXJ2ZXJTZXNzaW9uRW5jcnlwdGlvbktleShzZXNzaW9uRW5jcnlwdGlvbktleSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb2duaXRvVXNlckF0dHJpYnV0ZShcbiAgICBhdHRyaWJ1dGVOYW1lOiBzdHJpbmcsXG4gICAgdXNlckF0dHJpYnV0ZXM6IENvZ25pdG9Vc2VyQXR0cmlidXRlW11cbiAgKSB7XG4gICAgY29uc3QgdXNlckF0dHJpYnV0ZSA9IHVzZXJBdHRyaWJ1dGVzLmZpbmQoXG4gICAgICAoeCkgPT4geC5nZXROYW1lKCkgPT09IGF0dHJpYnV0ZU5hbWVcbiAgICApO1xuXG4gICAgcmV0dXJuIHVzZXJBdHRyaWJ1dGUgPyB1c2VyQXR0cmlidXRlLmdldFZhbHVlKCkgOiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2FkVXNlcktleXMob3B0aW9uczoge1xuICAgIHVzZXJLZXlzOiBVc2VyS2V5cztcbiAgICBwYXNzd29yZD86IENyeXB0b0tleTtcbiAgICBzZXNzaW9uRW5jcnlwdGlvbktleT86IHN0cmluZztcbiAgfSkge1xuICAgIGNvbnN0IHsgdXNlcktleXMsIHBhc3N3b3JkLCBzZXNzaW9uRW5jcnlwdGlvbktleSB9ID0gb3B0aW9ucztcblxuICAgIGlmIChzZXNzaW9uRW5jcnlwdGlvbktleSkge1xuICAgICAgdGhpcy5wZXJzaXN0U2VydmljZS5zZXRTZXJ2ZXJTZXNzaW9uRW5jcnlwdGlvbktleShcbiAgICAgICAgYXdhaXQgSldLLmFzS2V5KHNlc3Npb25FbmNyeXB0aW9uS2V5KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBwYXNzd29yZCBpcyBub3QgbmVlZGVkIGlmIHRoZSBtYXN0ZXIga2V5IGlzIGFscmVhZHkgcGVyc2lzdGVkLlxuICAgIGlmIChwYXNzd29yZCkge1xuICAgICAgY29uc3QgcGFzc0tleSA9IChcbiAgICAgICAgYXdhaXQgdGhpcy5rZXlGYWN0b3J5U2VydmljZS5kZXJpdmVQYXNzS2V5KHtcbiAgICAgICAgICBwYXNzd29yZCxcbiAgICAgICAgICAuLi51c2VyS2V5cy5wYXNzS2V5LnBhc3NLZXlQYXJhbXMsXG4gICAgICAgIH0pXG4gICAgICApLmp3aztcblxuICAgICAgYXdhaXQgdGhpcy5pZGxlU2VydmljZS5wZXJzaXN0TWFzdGVyS2V5KFxuICAgICAgICBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS51bndyYXBXaXRoUGFzc0tleShcbiAgICAgICAgICB1c2VyS2V5cy5wYXNzS2V5LmlkLFxuICAgICAgICAgIHBhc3NLZXksXG4gICAgICAgICAgdXNlcktleXMubWFzdGVyS2V5LmlkXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2FkVXNlcihcbiAgICBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIsXG4gICAgcGFzc3dvcmQ/OiBDcnlwdG9LZXlcbiAgKTogUHJvbWlzZTxBdXRoVXNlcj4ge1xuICAgIGlmIChjb2duaXRvVXNlci5nZXRVc2VybmFtZSgpLmVuZHNXaXRoKFRQX1BBU1NXT1JEX1JFU0VUX1VTRVJOQU1FX1NVRkZJWCkpIHtcbiAgICAgIHRoaXMudXNlciA9IGF3YWl0IHRoaXMubG9hZFJlc2V0VXNlcihjb2duaXRvVXNlciwgcGFzc3dvcmQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVzZXIgPSBhd2FpdCB0aGlzLmxvYWRSZWd1bGFyVXNlcihjb2duaXRvVXNlciwgcGFzc3dvcmQpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2Uuc3RhcnQoKTsgLy8gUnVuIGlkbGVTZXJ2aWNlIHdoZW5ldmVyIHVzZXIgaXMgbG9nZ2VkIGluLlxuXG4gICAgcmV0dXJuIHRoaXMudXNlcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZFJlZ3VsYXJVc2VyKFxuICAgIGNvZ25pdG9Vc2VyOiBDb2duaXRvVXNlcixcbiAgICBwYXNzd29yZD86IENyeXB0b0tleVxuICApOiBQcm9taXNlPEF1dGhVc2VyPiB7XG4gICAgY29uc3QgY3VycmVudFVzZXIgPSBhd2FpdCB0aGlzLmZldGNoQ3VycmVudFVzZXIoKTtcblxuICAgIGF3YWl0IHRoaXMubG9hZFVzZXJLZXlzKHtcbiAgICAgIHVzZXJLZXlzOiBjdXJyZW50VXNlci5jdXJyZW50VXNlcktleSxcbiAgICAgIHBhc3N3b3JkLFxuICAgICAgc2Vzc2lvbkVuY3J5cHRpb25LZXk6IGN1cnJlbnRVc2VyLnNlc3Npb25FbmNyeXB0aW9uS2V5LFxuICAgIH0pO1xuXG4gICAgLy8gUmVndWxhciB1c2VyIHBvcHVsYXRlcyBhbGwga2V5c1xuICAgIGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLnBvcHVsYXRlS2V5cyhjdXJyZW50VXNlci5jdXJyZW50VXNlcktleSk7XG5cbiAgICBjb25zdCB7IHVzZXJuYW1lIH0gPSBjdXJyZW50VXNlcjtcbiAgICBjb25zdCB1c2VyQXR0cmlidXRlcyA9IGF3YWl0IHRoaXMuY29nbml0by51c2VyQXR0cmlidXRlcyhjb2duaXRvVXNlcik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdXNlcm5hbWUsXG4gICAgICBzdWI6IHRoaXMuZ2V0Q29nbml0b1VzZXJBdHRyaWJ1dGUoJ3N1YicsIHVzZXJBdHRyaWJ1dGVzKSxcbiAgICAgIGxvZ2luRW1haWw6IHRoaXMuZ2V0Q29nbml0b1VzZXJBdHRyaWJ1dGUoJ2VtYWlsJywgdXNlckF0dHJpYnV0ZXMpLFxuICAgICAgcmVzZXRVc2VyOiBudWxsLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRSZXNldFVzZXIoXG4gICAgY29nbml0b1VzZXI6IENvZ25pdG9Vc2VyLFxuICAgIHBhc3N3b3JkPzogQ3J5cHRvS2V5XG4gICk6IFByb21pc2U8QXV0aFVzZXI+IHtcbiAgICBjb25zdCByZXNldFVzZXIgPSBhd2FpdCB0aGlzLmZldGNoUmVzZXRVc2VyKCk7XG5cbiAgICBjb25zdCB1c2VyS2V5cyA9IHtcbiAgICAgIHBhc3NLZXk6IHtcbiAgICAgICAgaWQ6IHJlc2V0VXNlci5wYXNzS2V5LmlkLFxuICAgICAgICBwYXNzS2V5UGFyYW1zOiByZXNldFVzZXIucGFzc0tleS5wYXNzS2V5UGFyYW1zLFxuICAgICAgfSxcbiAgICAgIG1hc3RlcktleToge1xuICAgICAgICBpZDogcmVzZXRVc2VyLm1hc3RlcktleS5pZCxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGF3YWl0IHRoaXMubG9hZFVzZXJLZXlzKHtcbiAgICAgIHVzZXJLZXlzLFxuICAgICAgcGFzc3dvcmQsXG4gICAgICBzZXNzaW9uRW5jcnlwdGlvbktleTogcmVzZXRVc2VyLnNlc3Npb25FbmNyeXB0aW9uS2V5LFxuICAgIH0pO1xuXG4gICAgLy8gUmVzZXQgdXNlciBvbmx5IHNldHMgYSBzdWJzZXQgb2Yga2V5c1xuICAgIGF3YWl0IHRoaXMua2V5U2VydmljZS5zZXRLZXlzKHVzZXJLZXlzKTtcblxuICAgIGNvbnN0IHsgdXNlcm5hbWUgfSA9IHJlc2V0VXNlcjtcbiAgICBjb25zdCB1c2VyQXR0cmlidXRlcyA9IGF3YWl0IHRoaXMuY29nbml0by51c2VyQXR0cmlidXRlcyhjb2duaXRvVXNlcik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdXNlcm5hbWUsXG4gICAgICBzdWI6IHRoaXMuZ2V0Q29nbml0b1VzZXJBdHRyaWJ1dGUoJ3N1YicsIHVzZXJBdHRyaWJ1dGVzKSxcbiAgICAgIGxvZ2luRW1haWw6IHRoaXMuZ2V0Q29nbml0b1VzZXJBdHRyaWJ1dGUoJ2VtYWlsJywgdXNlckF0dHJpYnV0ZXMpLFxuICAgICAgcmVzZXRVc2VyOiB7XG4gICAgICAgIHN0YXRlOiByZXNldFVzZXIuc3RhdGUsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlY292ZXJBc3NlbWJseUtleShcbiAgICByZXNldFVzZXI6IFJlc2V0VXNlclF1ZXJ5UmVzdWx0Wyd0cFBhc3N3b3JkUmVzZXRVc2VyJ11cbiAgKTogUHJvbWlzZTxKV0suS2V5PiB7XG4gICAgY29uc3QgcHJrID0gYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UuZ2V0S2V5KHJlc2V0VXNlci5weGsuaWQpO1xuXG4gICAgY29uc3QgcGFydGlhbHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHJlc2V0VXNlci5hcHByb3ZhbHNcbiAgICAgICAgLmZpbHRlcigoYXBwcm92YWwpID0+ICEhYXBwcm92YWwucmVjZWl2ZXJDaXBoZXJQYXJ0aWFsQXNzZW1ibHlLZXkpXG4gICAgICAgIC5tYXAoKGFwcHJvdmFsKSA9PlxuICAgICAgICAgIHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChcbiAgICAgICAgICAgIHByayxcbiAgICAgICAgICAgIGFwcHJvdmFsLnJlY2VpdmVyQ2lwaGVyUGFydGlhbEFzc2VtYmx5S2V5XG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgKTtcblxuICAgIHJldHVybiB0aGlzLmFzc2VtYmx5Q29udHJvbGxlci5yZWNvdmVyQXNzZW1ibHlLZXkocGFydGlhbHMpO1xuICB9XG5cbiAgYXN5bmMgY29tcGxldGVSZXNldFJlcXVlc3QobmV3UGFzc3dvcmQ6IENyeXB0b0tleSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc2V0VXNlciA9IGF3YWl0IHRoaXMuZmV0Y2hSZXNldFVzZXIoKTtcblxuICAgIGlmIChyZXNldFVzZXIuc3RhdGUgIT09IFRwQ2xhaW1TdGF0ZS5BUFBST1ZFRCkge1xuICAgICAgdGhyb3cgbmV3IEtjQmFkU3RhdGVFeGNlcHRpb24oXG4gICAgICAgICdQYXNzd29yZCByZXNldCByZXF1ZXN0IGhhcyBub3QgYmVlbiBhcHByb3ZlZC4nXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gUHJlcGFyZSBhbGwgbWF0ZXJpYWxzIHRvIGVuc3VyZSB0aGVyZSBhcmUgbm8gZXJyb3JzLlxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgYXNzZW1ibHlLZXkgPSBhd2FpdCB0aGlzLnJlY292ZXJBc3NlbWJseUtleShyZXNldFVzZXIpO1xuXG4gICAgY29uc3QgeyByb290S2V5IH0gPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXG4gICAgICBhc3NlbWJseUtleSxcbiAgICAgIHJlc2V0VXNlci5hc3NlbWJseUNpcGhlckRhdGFcbiAgICApO1xuXG4gICAgLy8gTWFraW5nIHN1cmUgaXQncyBhIHZhbGlkIGtleS5cbiAgICBjb25zdCByb290S2V5SndrID0gYXdhaXQgSldLLmFzS2V5KHJvb3RLZXkpO1xuXG4gICAgY29uc3QgbWFzdGVyS2V5ID0gYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UuZ2V0S2V5KHJlc2V0VXNlci5tYXN0ZXJLZXkuaWQpO1xuXG4gICAgY29uc3QgbWFzdGVyS2V5V3JhcHBlZFJvb3RLZXkgPVxuICAgICAgYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0VG9TdHJpbmcoXG4gICAgICAgIG1hc3RlcktleS5qd2ssXG4gICAgICAgIHJvb3RLZXlKd2sudG9KU09OKHRydWUpXG4gICAgICApO1xuXG4gICAgLy8gVGhlIG5ldyBwYXNzd29yZFxuICAgIGNvbnN0IG5ld1Bhc3NJZHBSZXN1bHQgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnlTZXJ2aWNlLmRlcml2ZVBhc3NJZHAoe1xuICAgICAgcGFzc3dvcmQ6IG5ld1Bhc3N3b3JkLFxuICAgICAgLi4ucmVzZXRVc2VyLnBhc3NLZXkucGFzc0lkcFBhcmFtcyxcbiAgICB9KTtcblxuICAgIGNvbnN0IG5ld0lkcFBhc3N3b3JkID0gdGhpcy5wYXNzd29yZFNlcnZpY2UuZ2V0UGFzc0lkcFN0cmluZyhcbiAgICAgIG5ld1Bhc3NJZHBSZXN1bHQuandrXG4gICAgKTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gR2V0IGFzc2VtYmx5IGtleSBjaGFsbGVuZ2VcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IGNoYWxsZW5nZSA9IChcbiAgICAgIGF3YWl0IHRoaXMubHJHcmFwaFFMLmxyTXV0YXRlKFxuICAgICAgICBuZXcgTHJNdXRhdGlvbih7XG4gICAgICAgICAgbXV0YXRpb246IENyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2VNdXRhdGlvbixcbiAgICAgICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgICAgIGlucHV0OiB7fSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIGluY2x1ZGVLZXlHcmFwaDogZmFsc2UsXG4gICAgICAgIH1cbiAgICAgIClcbiAgICApLmNyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2UuY2hhbGxlbmdlO1xuXG4gICAgLy8gU2lnbiB0aGUgY2hhbGxlbmdlXG4gICAgLy8gR2VuZXJhdGUgYSBjbGllbnQgc2lkZSBub25jZSB0aGF0J3Mgbm8gaW4gdGhlIHNlcnZlcidzIGNvbnRyb2wuXG4gICAgY2hhbGxlbmdlLmNsaWVudE5vbmNlID0gdGhpcy5rZXlGYWN0b3J5U2VydmljZS5yYW5kb21TdHJpbmcoXG4gICAgICBUUF9QQVNTV09SRF9SRVNFVF9DTElFTlRfTk9OQ0VfTEVOR1RIXG4gICAgKTtcblxuICAgIGNvbnN0IGFzc2VtYmx5S2V5VmVyaWZpZXJQcmsgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXG4gICAgICBhc3NlbWJseUtleSxcbiAgICAgIHJlc2V0VXNlci53cmFwcGVkQXNzZW1ibHlLZXlWZXJpZmllclBya1xuICAgICk7XG4gICAgY29uc3Qgc2lnbmVkQ2hhbGxlbmdlID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKFxuICAgICAgYXNzZW1ibHlLZXlWZXJpZmllclByayxcbiAgICAgIGNoYWxsZW5nZVxuICAgICk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIENoYW5nZSBwYXNzd29yZCBmb3IgdGhlIG9yaWdpbmFsIHVzZXJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IHRlbXBJZHBQYXNzd29yZCA9IChcbiAgICAgIGF3YWl0IHRoaXMubHJHcmFwaFFMLmxyTXV0YXRlKFxuICAgICAgICBuZXcgTHJNdXRhdGlvbih7XG4gICAgICAgICAgbXV0YXRpb246IFByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLFxuICAgICAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgc2lnbmVkQ2hhbGxlbmdlOiBKU09OLnN0cmluZ2lmeShzaWduZWRDaGFsbGVuZ2UpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIGluY2x1ZGVLZXlHcmFwaDogZmFsc2UsXG4gICAgICAgIH1cbiAgICAgIClcbiAgICApLnByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdC5pZHBQYXNzd29yZDtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gTG9naW4gYXMgdGhlIG9yaWdpbmFsIHVzZXIgdXNpbmcgbmV3IHRlbXBvcmFyeSBwYXNzd29yZFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQXQgdGhpcyBwb2ludCwgdGhlIG9yaWdpbmFsIGFjY291bnQncyBwYXNzd29yZCBoYXMgYmVlbiBjaGFuZ2VkXG4gICAgLy8gdG8gYSB0ZW1wb3JhcnkgcGFzc3dvcmQuIEl0IGlzIG5vIGxvbmdlciBwb3NzaWJsZSBmb3IgdGhlIHVzZXJcbiAgICAvLyB0byB1c2UgdGhlIG9yaWdpbmFsIHBhc3N3b3JkIHRvIGxvZ2luLiBBbnkgc3VjY2Vzc2Z1bCBsb2dpblxuICAgIC8vIGNhbiBvbmx5IGJlIHVzaW5nIHRoZSB0ZW1wb3JhcnkgcGFzc3dvcmQuIFNvIGl0J3Mgc2FmZSB0byBhc3N1bWVcbiAgICAvLyB0aGF0IHdlIHdhbnQgdG8gXCJjb21wbGV0ZVwiIHRoZSBwYXNzd29yZCByZXNldC5cblxuICAgIC8vIFRoZXJlIG1heWJlIDJGQSBzbyB3ZSBsaXN0ZW4gZm9yIHRoZSBhdXRoIGV2ZW50IGZyb20gQW1wbGlmeS5cbiAgICBjb25zdCByZXRQcm9taXNlID0gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgIGNvbnN0IGxpc3RlbmVyID0gYXN5bmMgKGRhdGEpID0+IHtcbiAgICAgICAgaWYgKGRhdGEucGF5bG9hZC5ldmVudCAhPT0gJ3NpZ25JbicpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBIdWIucmVtb3ZlKCdhdXRoJywgbGlzdGVuZXIpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuY29nbml0by5zaWduSW4ocmVzZXRVc2VyLnVzZXJuYW1lLCBuZXdJZHBQYXNzd29yZCk7XG5cbiAgICAgICAgLy8gU3dpdGNoIG92ZXIgdG8gdGhlIG5ldyBzZXQgb2Yga2V5c1xuICAgICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgICBuZXcgTHJNdXRhdGlvbih7XG4gICAgICAgICAgICBtdXRhdGlvbjogQ29tcGxldGVUcFBhc3N3b3JkUmVzZXRSZXF1ZXN0TXV0YXRpb24sXG4gICAgICAgICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgICBtYXN0ZXJLZXlXcmFwcGVkUm9vdEtleSxcbiAgICAgICAgICAgICAgICBtYXN0ZXJLZXlJZDogbWFzdGVyS2V5LmlkLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH07XG5cbiAgICAgIEh1Yi5saXN0ZW4oJ2F1dGgnLCBsaXN0ZW5lcik7XG4gICAgfSk7XG5cbiAgICAvLyBTaWduaW4gYXMgdGhlIG9yaWdpbmFsIHVzZXIuIFBhc3N3b3JkIGhhcyBiZWVuIHJlc2V0IHRvIHRlbXBvcmFyeSBvbmUuIEl0IHNob3VsZCByZXR1cm5cbiAgICAvLyB3aXRoIE5FV19QQVNTV09SRF9SRVFVSVJFRFxuICAgIGxldCB1c2VyID0gYXdhaXQgdGhpcy5jb2duaXRvLnNpZ25JbihyZXNldFVzZXIudXNlcm5hbWUsIHRlbXBJZHBQYXNzd29yZCwge1xuICAgICAgbm9Qcm94eTogJ3RydWUnLFxuICAgIH0pO1xuXG4gICAgaWYgKHVzZXIuY2hhbGxlbmdlTmFtZSAhPT0gJ05FV19QQVNTV09SRF9SRVFVSVJFRCcpIHtcbiAgICAgIHRocm93IG5ldyBLY0ludGVybmFsRXJyb3JFeGNlcHRpb24oXG4gICAgICAgICdFeHBlY3RpbmcgQ29nbml0byB0byBoYXZlIGRvbmUgYSBwYXNzd29yZCByZXNldCBhZnRlciBjYWxsIHRvIFByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gU2V0IG5ldyBwYXNzd29yZCBvbiBJZHBcbiAgICAvLyB0aGUgYXdzRmV0Y2goKSBmdW5jdGlvbiBwYXNzZXMgTkVXX1BBU1NXT1JEX1JFUVVJUkVEIGRpcmVjdGx5IHRvIEFXUyB3aXRob3V0XG4gICAgLy8gZ29pbmcgdGhyb3VnaCB0aGUgcHJveHkuXG4gICAgdXNlciA9IGF3YWl0IHRoaXMuY29nbml0by5jb21wbGV0ZU5ld1Bhc3N3b3JkKHVzZXIsIG5ld0lkcFBhc3N3b3JkLCB7fSk7XG5cbiAgICByZXR1cm4gcmV0UHJvbWlzZTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBEZWJ1ZyB1dGlsaXRpZXNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGRlYnVnTG9naW4odXNlcm5hbWU6IHN0cmluZywgcGFzc3dvcmQ6IENyeXB0b0tleSk6IFByb21pc2U8QXV0aFVzZXI+IHtcbiAgICAvLyBUaGlzIHdpbGwgZmFpbCBpZiBkZWJ1ZyBpcyBudWxsLiBCdXQgd2hlbiBkZWJ1ZyBpcyBudWxsLCB0aGlzIGZ1bmN0aW9uXG4gICAgLy8gc2hvdWxkIG5vdCBiZSBjYWxsZWQuXG4gICAgdGhpcy5rY0NvbmZpZy5kZWJ1Zy51c2VybmFtZSA9IHVzZXJuYW1lO1xuXG4gICAgcmV0dXJuIHRoaXMuZGVidWdMb2FkVXNlcihwYXNzd29yZCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlYnVnTG9hZFVzZXIocGFzc3dvcmQ6IENyeXB0b0tleSk6IFByb21pc2U8QXV0aFVzZXI+IHtcbiAgICBjb25zdCBjdXJyZW50VXNlciA9IGF3YWl0IHRoaXMuZmV0Y2hDdXJyZW50VXNlcigpO1xuXG4gICAgY29uc3QgeyB1c2VybmFtZSwgY3VycmVudFVzZXJLZXkgfSA9IGN1cnJlbnRVc2VyO1xuXG4gICAgLy8gRGVidWcgbW9kZSBjYW4gbm90IGRlYWwgd2l0aCBzZXNzaW9uIGVuY3J5cHRpb24ga2V5IHlldC5cbiAgICAvLyBOTyBTRVNTSU9OIEVOQ1JZUFRJT04gS0VZLlxuXG4gICAgY29uc3QgcGFzc0tleSA9IChcbiAgICAgIGF3YWl0IHRoaXMua2V5RmFjdG9yeVNlcnZpY2UuZGVyaXZlUGFzc0tleSh7XG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAuLi5jdXJyZW50VXNlcktleS5wYXNzS2V5LnBhc3NLZXlQYXJhbXMsXG4gICAgICB9KVxuICAgICkuandrO1xuXG4gICAgY29uc3QgbWFzdGVyS2V5ID0gYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UudW53cmFwV2l0aFBhc3NLZXkoXG4gICAgICBjdXJyZW50VXNlcktleS5wYXNzS2V5LmlkLFxuICAgICAgcGFzc0tleSxcbiAgICAgIGN1cnJlbnRVc2VyS2V5Lm1hc3RlcktleS5pZFxuICAgICk7XG5cbiAgICBhd2FpdCB0aGlzLmlkbGVTZXJ2aWNlLnBlcnNpc3RNYXN0ZXJLZXkobWFzdGVyS2V5KTtcblxuICAgIGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLnBvcHVsYXRlS2V5cyhjdXJyZW50VXNlcktleSk7XG5cbiAgICB0aGlzLnVzZXIgPSB7XG4gICAgICB1c2VybmFtZSxcbiAgICAgIHJlc2V0VXNlcjogbnVsbCxcbiAgICAgIHN1YjogJ0RFQlVHX01PREUnLFxuICAgICAgbG9naW5FbWFpbDogJ0RFQlVHX01PREUnLFxuICAgIH07XG5cbiAgICByZXR1cm4gdGhpcy51c2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFycyB0aGUgY2FjaGVzIHVzZXIuIFNvIHdlIGNhbiBzaW11bGF0ZSBhIHBhZ2UgcmVmcmVzaCBhbmQgdGVzdCBnZXRVc2VyKCkuXG4gICAqL1xuICBkZWJ1Z0NsZWFyVXNlcigpIHtcbiAgICB0aGlzLnVzZXIgPSBudWxsO1xuICB9XG5cbiAgYXN5bmMgZ2V0Q3VycmVudFVzZXJBdHRyaWJ1dGVzKCk6IFByb21pc2U8THJDb2duaXRvVXNlckF0dHJpYnV0ZVtdPiB7XG4gICAgY29uc3QgY29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmNvZ25pdG8uY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG4gICAgY29uc3QgdXNlckF0dHJpYnV0ZXMgPSBhd2FpdCB0aGlzLmNvZ25pdG8udXNlckF0dHJpYnV0ZXMoY29nbml0b1VzZXIpO1xuXG4gICAgcmV0dXJuIHVzZXJBdHRyaWJ1dGVzO1xuICB9XG59XG4iXX0=