@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.
- package/bundles/lifeready-core.umd.js +301 -293
- package/bundles/lifeready-core.umd.js.map +1 -1
- package/bundles/lifeready-core.umd.min.js +1 -1
- package/bundles/lifeready-core.umd.min.js.map +1 -1
- package/esm2015/lib/auth/auth.config.js +57 -0
- package/esm2015/lib/auth/auth.gql.private.js +85 -0
- package/esm2015/lib/auth/auth.service.js +602 -0
- package/esm2015/lib/auth/auth.types.js +21 -0
- package/esm2015/lib/item/item.gql.js +164 -0
- package/esm2015/lib/item/item.gql.private.js +23 -0
- package/esm2015/lib/item/item.service.js +592 -0
- package/esm2015/lib/item/item.types.js +2 -0
- package/esm2015/lib/key-exchange/key-exchange.gql.js +174 -0
- package/esm2015/lib/key-exchange/key-exchange.service.js +480 -0
- package/esm2015/lib/lbop/lbop.service.js +7 -15
- package/esm2015/lib/life-ready.module.js +2 -2
- package/esm2015/lib/password/password.service.js +1 -1
- package/esm2015/lib/plan/plan.gql.js +91 -0
- package/esm2015/lib/plan/plan.service.js +191 -0
- package/esm2015/lib/plan/plan.types.js +2 -0
- package/esm2015/lib/profile/profile.gql.js +2 -2
- package/esm2015/lib/profile/profile.service.js +1 -8
- package/esm2015/lib/profile/profile.types.js +1 -8
- package/esm2015/lib/scenario/scenario.service.js +8 -8
- package/esm2015/lib/shared-contact-card/shared-contact-card2.service.js +1 -1
- package/esm2015/lib/trusted-party/trusted-party.gql.js +64 -0
- package/esm2015/lib/trusted-party/trusted-party.gql.private.js +25 -0
- package/esm2015/lib/trusted-party/trusted-party.service.js +240 -0
- package/esm2015/lib/trusted-party/trusted-party.types.js +2 -0
- package/esm2015/public-api.js +17 -12
- package/fesm2015/lifeready-core.js +189 -211
- package/fesm2015/lifeready-core.js.map +1 -1
- package/lib/{auth2/auth2.service.d.ts → auth/auth.service.d.ts} +2 -2
- package/lib/{item2/item2.service.d.ts → item/item.service.d.ts} +39 -39
- package/lib/key-exchange/{key-exchange2.service.d.ts → key-exchange.service.d.ts} +2 -2
- package/lib/lbop/lbop.service.d.ts +1 -5
- package/lib/password/password.service.d.ts +1 -1
- package/lib/{plan2/plan2.service.d.ts → plan/plan.service.d.ts} +20 -20
- package/lib/profile/profile.service.d.ts +1 -2
- package/lib/profile/profile.types.d.ts +2 -15
- package/lib/scenario/scenario.service.d.ts +3 -3
- package/lib/shared-contact-card/shared-contact-card2.service.d.ts +1 -1
- package/lib/trusted-party/{trusted-party2.service.d.ts → trusted-party.service.d.ts} +6 -6
- package/lifeready-core.metadata.json +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +16 -11
- package/esm2015/lib/auth2/auth.config.js +0 -57
- package/esm2015/lib/auth2/auth2.gql.private.js +0 -85
- package/esm2015/lib/auth2/auth2.service.js +0 -602
- package/esm2015/lib/auth2/auth2.types.js +0 -21
- package/esm2015/lib/item2/item2.gql.js +0 -164
- package/esm2015/lib/item2/item2.gql.private.js +0 -23
- package/esm2015/lib/item2/item2.service.js +0 -592
- package/esm2015/lib/item2/item2.types.js +0 -2
- package/esm2015/lib/key-exchange/key-exchange2.gql.js +0 -174
- package/esm2015/lib/key-exchange/key-exchange2.service.js +0 -480
- package/esm2015/lib/plan2/plan2.gql.js +0 -91
- package/esm2015/lib/plan2/plan2.service.js +0 -191
- package/esm2015/lib/plan2/plan2.types.js +0 -2
- package/esm2015/lib/trusted-party/trusted-party2.gql.js +0 -64
- package/esm2015/lib/trusted-party/trusted-party2.gql.private.js +0 -25
- package/esm2015/lib/trusted-party/trusted-party2.service.js +0 -240
- package/esm2015/lib/trusted-party/trusted-party2.types.js +0 -2
- /package/lib/{auth2 → auth}/auth.config.d.ts +0 -0
- /package/lib/{auth2/auth2.gql.private.d.ts → auth/auth.gql.private.d.ts} +0 -0
- /package/lib/{auth2/auth2.types.d.ts → auth/auth.types.d.ts} +0 -0
- /package/lib/{item2/item2.gql.d.ts → item/item.gql.d.ts} +0 -0
- /package/lib/{item2/item2.gql.private.d.ts → item/item.gql.private.d.ts} +0 -0
- /package/lib/{item2/item2.types.d.ts → item/item.types.d.ts} +0 -0
- /package/lib/key-exchange/{key-exchange2.gql.d.ts → key-exchange.gql.d.ts} +0 -0
- /package/lib/{plan2/plan2.gql.d.ts → plan/plan.gql.d.ts} +0 -0
- /package/lib/{plan2/plan2.types.d.ts → plan/plan.types.d.ts} +0 -0
- /package/lib/trusted-party/{trusted-party2.gql.d.ts → trusted-party.gql.d.ts} +0 -0
- /package/lib/trusted-party/{trusted-party2.gql.private.d.ts → trusted-party.gql.private.d.ts} +0 -0
- /package/lib/trusted-party/{trusted-party2.types.d.ts → trusted-party.types.d.ts} +0 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
var AuthService_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 './auth.gql.private';
|
|
25
|
+
import { CognitoChallengeName, PasswordChangeStatus, RecoveryStatus, } from './auth.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 AuthService = AuthService_1 = class AuthService 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, AuthService_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
|
+
AuthService.CHALLENGE_TIMEOUT = 1000 * 60 * 5;
|
|
574
|
+
AuthService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AuthService_Factory() { return new AuthService(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: AuthService, providedIn: "root" });
|
|
575
|
+
AuthService.decorators = [
|
|
576
|
+
{ type: Injectable, args: [{
|
|
577
|
+
providedIn: 'root',
|
|
578
|
+
},] }
|
|
579
|
+
];
|
|
580
|
+
AuthService.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
|
+
AuthService = AuthService_1 = __decorate([
|
|
597
|
+
RunOutsideAngular({
|
|
598
|
+
ngZoneName: 'ngZone',
|
|
599
|
+
})
|
|
600
|
+
], AuthService);
|
|
601
|
+
export { AuthService };
|
|
602
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29yZS9zcmMvbGliL2F1dGgvYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWhGLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUMzRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNoQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDNUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDckUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsVUFBVSxFQUFZLE1BQU0sb0JBQW9CLENBQUM7QUFFMUQsT0FBTyxFQUFZLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzNELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxFQUNMLHFDQUFxQyxFQUNyQyxpQ0FBaUMsR0FDbEMs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O2dCQUNmLEdBQUcsRUFBRSxZQUFZO2dCQUNqQixVQUFVLEVBQUUsWUFBWTthQUN6QixDQUFDO1lBRUYsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ25CLENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0gsY0FBYztRQUNaLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ25CLENBQUM7SUFFSyx3QkFBd0I7O1lBQzVCLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1lBQ2xFLE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFdEUsT0FBTyxjQUFjLENBQUM7UUFDeEIsQ0FBQztLQUFBO0NBQ0YsQ0FBQTtBQXp2QlEsNkJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7OztZQUoxQyxVQUFVLFNBQUM7Z0JBQ1YsVUFBVSxFQUFFLE1BQU07YUFDbkI7OztZQTdEaUQsTUFBTTtZQUEzQixRQUFRO1lBRDVCLFVBQVU7WUFHVixTQUFTO1lBSVQsZ0JBQWdCO1lBTWhCLFVBQVU7WUFEVixlQUFlO1lBRGYsaUJBQWlCO1lBS2pCLGVBQWU7WUFOZixXQUFXO1lBT1gsY0FBYztZQVJkLGlCQUFpQjtZQWFqQixpQ0FBaUM7NENBaUVyQyxNQUFNLFNBQUMsU0FBUzs7QUF4QlIsV0FBVztJQU52QixpQkFBaUIsQ0FBQztRQUNqQixVQUFVLEVBQUUsUUFBUTtLQUNyQixDQUFDO0dBSVcsV0FBVyxDQTB2QnZCO1NBMXZCWSxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIGlzRGV2TW9kZSwgTmdab25lIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb2duaXRvVXNlciB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9hdXRoJztcbmltcG9ydCB7IEF1dGhDbGFzcyB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9hdXRoL2xpYi1lc20vQXV0aCc7XG5pbXBvcnQgeyBIdWIgfSBmcm9tICdAYXdzLWFtcGxpZnkvY29yZSc7XG5pbXBvcnQgeyBDb2duaXRvVXNlckF0dHJpYnV0ZSB9IGZyb20gJ2FtYXpvbi1jb2duaXRvLWlkZW50aXR5LWpzJztcbmltcG9ydCB7IEpXSyB9IGZyb20gJ25vZGUtam9zZSc7XG5pbXBvcnQgeyBMckdyYXBoUUxTZXJ2aWNlLCBMck11dGF0aW9uLCBMclNlcnZpY2UgfSBmcm9tICcuLi9hcGkvbHItZ3JhcGhxbCc7XG5pbXBvcnQgeyBUcENsYWltU3RhdGUgfSBmcm9tICcuLi9hcGkvdHlwZXMnO1xuaW1wb3J0IHsgRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tICcuLi9lbmNyeXB0aW9uL2VuY3J5cHRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBJZGxlU2VydmljZSB9IGZyb20gJy4uL2lkbGUvaWRsZS5zZXJ2aWNlJztcbmltcG9ydCB7IEtleUZhY3RvcnlTZXJ2aWNlIH0gZnJvbSAnLi4va2V5L2tleS1mYWN0b3J5LnNlcnZpY2UnO1xuaW1wb3J0IHsgS2V5R3JhcGhTZXJ2aWNlIH0gZnJvbSAnLi4va2V5L2tleS1ncmFwaC5zZXJ2aWNlJztcbmltcG9ydCB7IEtleVNlcnZpY2UsIFVzZXJLZXlzIH0gZnJvbSAnLi4va2V5L2tleS5zZXJ2aWNlJztcbmltcG9ydCB7IFBhc3NJZHBQYXJhbXMgfSBmcm9tICcuLi9rZXkva2V5LnR5cGVzJztcbmltcG9ydCB7IEtjQ29uZmlnLCBLQ19DT05GSUcgfSBmcm9tICcuLi9saWZlLXJlYWR5LmNvbmZpZyc7XG5pbXBvcnQgeyBQYXNzd29yZFNlcnZpY2UgfSBmcm9tICcuLi9wYXNzd29yZC9wYXNzd29yZC5zZXJ2aWNlJztcbmltcG9ydCB7IFBlcnNpc3RTZXJ2aWNlIH0gZnJvbSAnLi4vcGVyc2lzdC9wZXJzaXN0LnNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgVFBfUEFTU1dPUkRfUkVTRVRfQ0xJRU5UX05PTkNFX0xFTkdUSCxcbiAgVFBfUEFTU1dPUkRfUkVTRVRfVVNFUk5BTUVfU1VGRklYLFxufSBmcm9tICcuLi90cC1wYXNzd29yZC1yZXNldC90cC1wYXNzd29yZC1yZXNldC5jb25zdGFudHMnO1xuaW1wb3J0IHsgVHBQYXNzd29yZFJlc2V0QXNzZW1ibHlDb250cm9sbGVyIH0gZnJvbSAnLi4vdHAtcGFzc3dvcmQtcmVzZXQvdHAtcGFzc3dvcmQtcmVzZXQuY29udHJvbGxlcic7XG5pbXBvcnQge1xuICBDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3RNdXRhdGlvbixcbiAgQ3JlYXRlVHBBc3NlbWJseUtleUNoYWxsZW5nZU11dGF0aW9uLFxuICBQcmVDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3RNdXRhdGlvbixcbn0gZnJvbSAnLi4vdHAtcGFzc3dvcmQtcmVzZXQvdHAtcGFzc3dvcmQtcmVzZXQuZ3FsJztcbmltcG9ydCB7XG4gIEtjQmFkUmVxdWVzdEV4Y2VwdGlvbixcbiAgS2NCYWRTdGF0ZUV4Y2VwdGlvbixcbiAgS2NDb25jdXJyZW50QWNjZXNzRXhjZXB0aW9uLFxuICBLY0ludGVybmFsRXJyb3JFeGNlcHRpb24sXG59IGZyb20gJy4uL19jb21tb24vZXhjZXB0aW9ucyc7XG5pbXBvcnQgeyBLZXlDb250YWluZXIgfSBmcm9tICcuLi9fY29tbW9uL2tleSc7XG5pbXBvcnQgeyBSdW5PdXRzaWRlQW5ndWxhciB9IGZyb20gJy4uL19jb21tb24vcnVuLW91dHNpZGUtYW5ndWxhcic7XG5pbXBvcnQge1xuICBDdXJyZW50VXNlclF1ZXJ5LFxuICBDdXJyZW50VXNlclF1ZXJ5UmVzdWx0LFxuICBSZXNldFVzZXJRdWVyeSxcbiAgUmVzZXRVc2VyUXVlcnlSZXN1bHQsXG4gIFNldFNlc3Npb25FbmNyeXB0aW9uS2V5TXV0YXRpb24sXG59IGZyb20gJy4vYXV0aC5ncWwucHJpdmF0ZSc7XG5pbXBvcnQge1xuICBBdXRoVXNlcixcbiAgQ29nbml0b0NoYWxsZW5nZU5hbWUsXG4gIExvZ2luQ2hhbGxlbmdlLFxuICBMb2dpbk9wdGlvbnMsXG4gIExvZ2luUmVzdWx0LFxuICBMb2dvdXRMaXN0ZW5lcixcbiAgTHJDb2duaXRvVXNlcixcbiAgTHJDb2duaXRvVXNlckF0dHJpYnV0ZSxcbiAgUGFzc0lkcFJlc3VsdCxcbiAgUGFzc3dvcmRDaGFuZ2VTdGF0dXMsXG4gIFJlY292ZXJ5U3RhdHVzLFxufSBmcm9tICcuL2F1dGgudHlwZXMnO1xuXG5AUnVuT3V0c2lkZUFuZ3VsYXIoe1xuICBuZ1pvbmVOYW1lOiAnbmdab25lJyxcbn0pXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFNlcnZpY2UgZXh0ZW5kcyBMclNlcnZpY2Uge1xuICBzdGF0aWMgQ0hBTExFTkdFX1RJTUVPVVQgPSAxMDAwICogNjAgKiA1O1xuXG4gIC8vIENvdWxkIHVzZSByeGpzIG9ic2VydmFibGVzIGhlcmUuIEJ1dCB0cnlpbmcgdG8gaGF2ZSBrYy1jbGllbnQgdXNlIGFzIGxpdHRsZSBhbmd1bGFyXG4gIC8vIGZlYXR1cmVzIGFzIHBvc3NpYmxlLiBSeGpzIGlzIG5vdCB1c2VkIGFueXdoZXJlIGVsc2UgaW4ga2MtY2xpZW50LlxuICBwcml2YXRlIGxvZ291dExpc3RlbmVycyA9IG5ldyBTZXQ8TG9nb3V0TGlzdGVuZXI+KCk7XG4gIHByaXZhdGUgdXNlcjogQXV0aFVzZXI7XG4gIC8vIFN0b3JlcyB0aGUgcGFzc3dvcmQgZm9yIHVzZSBhZnRlciBtZmEgdmVyaWZpY2F0aW9uIHRvIGRlY3J5cHQgbWFzdGVyS2V5LlxuICBwcml2YXRlIHBhc3N3b3JkOiBLZXlDb250YWluZXIgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxuICAgIHByaXZhdGUgY29nbml0bzogQXV0aENsYXNzLFxuICAgIHByaXZhdGUgYXBpOiBMckdyYXBoUUxTZXJ2aWNlLFxuICAgIHByaXZhdGUga2V5U2VydmljZTogS2V5U2VydmljZSxcbiAgICBwcml2YXRlIGtleUdyYXBoU2VydmljZTogS2V5R3JhcGhTZXJ2aWNlLFxuICAgIHByaXZhdGUga2V5RmFjdG9yeVNlcnZpY2U6IEtleUZhY3RvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgcGFzc3dvcmRTZXJ2aWNlOiBQYXNzd29yZFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBpZGxlU2VydmljZTogSWRsZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwZXJzaXN0U2VydmljZTogUGVyc2lzdFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBlbmNyeXB0aW9uU2VydmljZTogRW5jcnlwdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhc3NlbWJseUNvbnRyb2xsZXI6IFRwUGFzc3dvcmRSZXNldEFzc2VtYmx5Q29udHJvbGxlcixcbiAgICBASW5qZWN0KEtDX0NPTkZJRykgcHJpdmF0ZSBrY0NvbmZpZzogS2NDb25maWdcbiAgKSB7XG4gICAgc3VwZXIoaW5qZWN0b3IpO1xuICAgIGlmICghaXNEZXZNb2RlKCkpIHtcbiAgICAgIGlmICh0aGlzLmtjQ29uZmlnLmRlYnVnICE9IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEtjQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgICAgICAnSW4gcHJvZHVjdGlvbiBtb2RlLCBcIktjQ29uZmlnLmRlYnVnXCIgbXVzdCBiZSBzZXQgdG8gbnVsbCdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpbXBvcnRQYXNzd29yZChwbGFpblBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPENyeXB0b0tleT4ge1xuICAgIHJldHVybiB0aGlzLmtleUZhY3RvcnlTZXJ2aWNlLmltcG9ydFBhc3N3b3JkKHBsYWluUGFzc3dvcmQpO1xuICB9XG5cbiAgYXN5bmMgbG9nb3V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIE5vdGlmeSBhbGwgbGlzdGVuZXJzIHRvIGNsZWFuIHVwLlxuICAgIGF3YWl0IFByb21pc2UuYWxsKFsuLi50aGlzLmxvZ291dExpc3RlbmVyc10ubWFwKChjYWxsYmFjaykgPT4gY2FsbGJhY2soKSkpO1xuXG4gICAgdGhpcy51c2VyID0gbnVsbDtcbiAgICB0aGlzLmtleVNlcnZpY2UucHVyZ2VLZXlzKCk7XG4gICAgdGhpcy5rZXlHcmFwaFNlcnZpY2UucHVyZ2VLZXlzKCk7XG5cbiAgICAvLyBTaWduIG91dCBvbiBib3RoIGNvZ25pdG8gYW5kIGtjLXNlcnZlclxuICAgIGF3YWl0IFByb21pc2UuYWxsKFt0aGlzLmNvZ25pdG8uc2lnbk91dCgpLCB0aGlzLmtjTG9nb3V0KCldKTtcblxuICAgIGlmICh0aGlzLmtjQ29uZmlnLmRlYnVnPy51c2VybmFtZSkge1xuICAgICAgdGhpcy5rY0NvbmZpZy5kZWJ1Zy51c2VybmFtZSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgYWRkTG9nb3V0TGlzdGVuZXIoY2FsbGJhY2s6IExvZ291dExpc3RlbmVyKSB7XG4gICAgdGhpcy5sb2dvdXRMaXN0ZW5lcnMuYWRkKGNhbGxiYWNrKTtcbiAgfVxuXG4gIHJlbW92ZUxvZ291dExpc3RlbmVyKGNhbGxiYWNrOiBMb2dvdXRMaXN0ZW5lcikge1xuICAgIHRoaXMubG9nb3V0TGlzdGVuZXJzLmRlbGV0ZShjYWxsYmFjayk7XG4gIH1cblxuICBhc3luYyBsb2dpbihcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcbiAgICBwYXNzd29yZDogQ3J5cHRvS2V5LFxuICAgIHsgdHBQYXNzd29yZFJlc2V0QXV0b0NvbXBsZXRlID0gdHJ1ZSB9OiBMb2dpbk9wdGlvbnMgPSB7fVxuICApOiBQcm9taXNlPExvZ2luUmVzdWx0PiB7XG4gICAgbGV0IGxvZ2luUmVzdWx0OiBMb2dpblJlc3VsdCA9IGF3YWl0IHRoaXMubG9naW5JbXBsKGVtYWlsT3JQaG9uZSwgcGFzc3dvcmQpO1xuXG4gICAgLy8gU2F2ZSB0aGUgcGFzc3dvcmQgZm9yIHVzZSBhZnRlciBtZWV0aW5nIGNoYWxsZW5nZS5cbiAgICBpZiAobG9naW5SZXN1bHQuY2hhbGxlbmdlKSB7XG4gICAgICB0aGlzLnBhc3N3b3JkID0gbmV3IEtleUNvbnRhaW5lcihwYXNzd29yZCwgQXV0aFNlcnZpY2UuQ0hBTExFTkdFX1RJTUVPVVQpO1xuXG4gICAgICByZXR1cm4gbG9naW5SZXN1bHQ7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdHBQYXNzd29yZFJlc2V0QXV0b0NvbXBsZXRlICYmXG4gICAgICBsb2dpblJlc3VsdC51c2VyLnJlc2V0VXNlcj8uc3RhdGUgPT09IFRwQ2xhaW1TdGF0ZS5BUFBST1ZFRFxuICAgICkge1xuICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZVJlc2V0UmVxdWVzdChwYXNzd29yZCk7XG4gICAgICBsb2dpblJlc3VsdCA9IGF3YWl0IHRoaXMubG9naW5JbXBsKGVtYWlsT3JQaG9uZSwgcGFzc3dvcmQpO1xuICAgIH1cblxuICAgIHJldHVybiBsb2dpblJlc3VsdDtcbiAgfVxuXG4gIGFzeW5jIHZlcmlmeUxvZ2luKG9wdGlvbnM6IHtcbiAgICBjaGFsbGVuZ2U6IExvZ2luQ2hhbGxlbmdlO1xuICAgIGNvZGU6IHN0cmluZztcbiAgICByZW1lbWJlck1lOiBib29sZWFuO1xuICB9KTogUHJvbWlzZTxMb2dpblJlc3VsdD4ge1xuICAgIGNvbnN0IHsgY2hhbGxlbmdlLCBjb2RlLCByZW1lbWJlck1lIH0gPSBvcHRpb25zO1xuXG4gICAgY29uc3QgVkFMSURfQ0hBTExFTkdFX05BTUVTID0gW1xuICAgICAgQ29nbml0b0NoYWxsZW5nZU5hbWUuU01TX01GQSxcbiAgICAgIENvZ25pdG9DaGFsbGVuZ2VOYW1lLlNPRlRXQVJFX1RPS0VOX01GQSxcbiAgICBdO1xuXG4gICAgaWYgKCFWQUxJRF9DSEFMTEVOR0VfTkFNRVMuaW5jbHVkZXMoY2hhbGxlbmdlLmNvZ25pdG9Vc2VyLmNoYWxsZW5nZU5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgS2NCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgICBgY2hhbGxlbmdlTmFtZSBtdXN0IGJlIG9uZSBvZiAke1ZBTElEX0NIQUxMRU5HRV9OQU1FU31gXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFRPRE86IHRoaXMuYXV0aC5jb25maXJtU2lnbkluKCkgY291bGQgcmV0dXJuIGFub3RoZXIgY2hhbGxlbmdlLlxuICAgIGNvbnN0IGNvZ25pdG9Vc2VyID0gYXdhaXQgdGhpcy5jb2duaXRvLmNvbmZpcm1TaWduSW4oXG4gICAgICBjaGFsbGVuZ2UuY29nbml0b1VzZXIsXG4gICAgICBjb2RlLFxuICAgICAgY2hhbGxlbmdlLmNvZ25pdG9Vc2VyLmNoYWxsZW5nZU5hbWUgYXNcbiAgICAgICAgfCBDb2duaXRvQ2hhbGxlbmdlTmFtZS5TTVNfTUZBXG4gICAgICAgIHwgQ29nbml0b0NoYWxsZW5nZU5hbWUuU09GVFdBUkVfVE9LRU5fTUZBXG4gICAgKTtcblxuICAgIGF3YWl0IHRoaXMuaGFuZGxlUG9zdEF1dGgoY2hhbGxlbmdlLnJlY292ZXJ5U3RhdHVzKTtcblxuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmxvYWRVc2VyKGNvZ25pdG9Vc2VyLCB0aGlzLnBhc3N3b3JkLnBvcCgpKTtcblxuICAgIC8vIFRoaXMgaXMgbm90IHN0cmljdGx5IG5lY2Vzc2FyeSBzaW5jZSB0aGUgdGhpcy5wYXNzd29yZC5wb3AoKSBhbHJlYWR5IGNsZWFycyB0aGVcbiAgICAvLyBwYXNzd29yZCBpbnNpZGUgdGhlIGNvbnRhaW5lci4gQnV0IGRvZXNuJ3QgaHVydCBlaXRoZXIuXG4gICAgdGhpcy5wYXNzd29yZCA9IG51bGw7XG5cbiAgICBpZiAocmVtZW1iZXJNZSkge1xuICAgICAgY29nbml0b1VzZXIuc2V0RGV2aWNlU3RhdHVzUmVtZW1iZXJlZCh7XG4gICAgICAgIG9uU3VjY2VzczogKCkgPT4ge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSxcbiAgICAgICAgb25GYWlsdXJlOiAoZSkgPT4gY29uc29sZS5lcnJvcihlKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB1c2VyLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBnZXRVc2VyKCk6IFByb21pc2U8QXV0aFVzZXI+IHtcbiAgICBpZiAodGhpcy51c2VyKSB7XG4gICAgICByZXR1cm4gdGhpcy51c2VyO1xuICAgIH1cblxuICAgIGNvbnN0IGNvZ25pdG9Vc2VyID0gYXdhaXQgdGhpcy5jb2duaXRvLmN1cnJlbnRBdXRoZW50aWNhdGVkVXNlcigpO1xuXG4gICAgcmV0dXJuIHRoaXMubG9hZFVzZXIoY29nbml0b1VzZXIpO1xuICB9XG5cbiAgYXN5bmMgcmVmcmVzaEFjY2Vzc1Rva2VuKCkge1xuICAgIGNvbnN0IGNvZ25pdG9Vc2VyOiBDb2duaXRvVXNlciA9XG4gICAgICBhd2FpdCB0aGlzLmNvZ25pdG8uY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG4gICAgY29uc3QgcmVmcmVzaFRva2VuID0gY29nbml0b1VzZXIuZ2V0U2lnbkluVXNlclNlc3Npb24oKS5nZXRSZWZyZXNoVG9rZW4oKTtcblxuICAgIGNvbnNvbGUubG9nKCdUb2tlbiByZWZyZXNoLi4uJyk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvZ25pdG9Vc2VyLnJlZnJlc2hTZXNzaW9uKHJlZnJlc2hUb2tlbiwgKGVycikgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgcmVmcmVzaGluZyB0b2tlbjogJywgZXJyKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnVG9rZW4gcmVmcmVzaCBjb21wbGV0ZScpO1xuICAgICAgICAgIHJlc29sdmUoMCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBIZWxwZXJzXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoQ3VycmVudFVzZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIGF3YWl0IHRoaXMuYXBpLnF1ZXJ5PEN1cnJlbnRVc2VyUXVlcnlSZXN1bHQ+KHtcbiAgICAgICAgcXVlcnk6IEN1cnJlbnRVc2VyUXVlcnksXG4gICAgICAgIHByb2Nlc3Nvck9wdGlvbnM6IHtcbiAgICAgICAgICBoYXNLZXlzOiBmYWxzZSwgLy8gRG9uJ3QgdHJ5IHRvIGRlY3J5cHQgYW55dGhpbmcgYmVjYXVzZSBrZXlzIGhhdmUgbm90IGJlZW4gc2V0dXAgeWV0XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICkuY3VycmVudFVzZXI7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoUmVzZXRVc2VyKCkge1xuICAgIHJldHVybiAoXG4gICAgICBhd2FpdCB0aGlzLmFwaS5xdWVyeTxSZXNldFVzZXJRdWVyeVJlc3VsdD4oe1xuICAgICAgICBxdWVyeTogUmVzZXRVc2VyUXVlcnksXG4gICAgICAgIHByb2Nlc3Nvck9wdGlvbnM6IHtcbiAgICAgICAgICBoYXNLZXlzOiBmYWxzZSwgLy8gRG9uJ3QgdHJ5IHRvIGRlY3J5cHQgYW55dGhpbmcgYmVjYXVzZSBrZXlzIGhhdmUgbm90IGJlZW4gc2V0dXAgeWV0XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICkudHBQYXNzd29yZFJlc2V0VXNlcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMga2NMb2dvdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5odHRwXG4gICAgICAucG9zdChgJHt0aGlzLmtjQ29uZmlnLmF1dGhVcmx9YXV0aC9zaWduLW91dC9gLCBudWxsLCB7XG4gICAgICAgIHdpdGhDcmVkZW50aWFsczogdHJ1ZSxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgICB9KVxuICAgICAgLnRvUHJvbWlzZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaFBhc3NJZHBQYXJhbXMoXG4gICAgZW1haWxPclBob25lOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxQYXNzSWRwUmVzdWx0PiB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuaHR0cFxuICAgICAgLmdldDxQYXNzSWRwUmVzdWx0PihcbiAgICAgICAgYCR7XG4gICAgICAgICAgdGhpcy5rY0NvbmZpZy5hdXRoVXJsXG4gICAgICAgIH11c2Vycy9wYXNzLWlkcC1wYXJhbXMvP2xvZ2luX25hbWU9JHtlbmNvZGVVUklDb21wb25lbnQoZW1haWxPclBob25lKX1gXG4gICAgICApXG4gICAgICAudG9Qcm9taXNlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvZ2luSW1wbChcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcbiAgICBwYXNzd29yZDogQ3J5cHRvS2V5XG4gICk6IFByb21pc2U8TG9naW5SZXN1bHQ+IHtcbiAgICBhd2FpdCB0aGlzLmxvZ291dCgpO1xuICAgIGNvbnN0IGxvZ2luSWRwUmVzdWx0ID0gYXdhaXQgdGhpcy5sb2dpbklkcChlbWFpbE9yUGhvbmUsIHBhc3N3b3JkKTtcblxuICAgIC8vIENhbid0IGdldCB0aGUgdXNlciB5ZXQgYmVjYXVzZSB3ZSBzdGlsbCBuZWQgdG8gbWVldCBNRkEgY2hhbGxlbmdlc1xuICAgIGlmIChcbiAgICAgIFtcbiAgICAgICAgQ29nbml0b0NoYWxsZW5nZU5hbWUuU01TX01GQSxcbiAgICAgICAgQ29nbml0b0NoYWxsZW5nZU5hbWUuU09GVFdBUkVfVE9LRU5fTUZBLFxuICAgICAgXS5pbmNsdWRlcyhsb2dpbklkcFJlc3VsdC5jb2duaXRvVXNlci5jaGFsbGVuZ2VOYW1lKVxuICAgICkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2hhbGxlbmdlOiB7XG4gICAgICAgICAgY29nbml0b1VzZXI6IGxvZ2luSWRwUmVzdWx0LmNvZ25pdG9Vc2VyLFxuICAgICAgICAgIHJlY292ZXJ5U3RhdHVzOiBsb2dpbklkcFJlc3VsdC5yZWNvdmVyeVN0YXR1cyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5oYW5kbGVQb3N0QXV0aChsb2dpbklkcFJlc3VsdC5yZWNvdmVyeVN0YXR1cyk7XG4gICAgLy8gVGhlcmUgc2hvdWxkIGJlIG5vIE1GQSBvbiB0aGUgVFAgcmVzZXQgdXNlci5cbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5sb2FkVXNlcihsb2dpbklkcFJlc3VsdC5jb2duaXRvVXNlciwgcGFzc3dvcmQpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXIsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9naW5JZHAoXG4gICAgZW1haWxPclBob25lOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IENyeXB0b0tleVxuICApOiBQcm9taXNlPExvZ2luQ2hhbGxlbmdlPiB7XG4gICAgLy8gRG93bmxvYWQgdGhlIHNhbHQgbmVlZGVkIHRvIGRlcml2ZSB0aGUgUGFzc0lkcFxuICAgIGNvbnN0IHBhc3NJZHBBcGlSZXN1bHQgPSBhd2FpdCB0aGlzLmZldGNoUGFzc0lkcFBhcmFtcyhlbWFpbE9yUGhvbmUpO1xuXG4gICAgaWYgKFxuICAgICAgcGFzc0lkcEFwaVJlc3VsdC5wYXNzd29yZENoYW5nZVN0YXR1cyA9PT0gUGFzc3dvcmRDaGFuZ2VTdGF0dXMuSU5fUFJPR1JFU1NcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBLY0NvbmN1cnJlbnRBY2Nlc3NFeGNlcHRpb24oJ0EgcGFzc3dvcmQgY2hhbmdlIGlzIGluIHByb2dyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgcGFzc0lkcEFwaVJlc3VsdC5wYXNzd29yZENoYW5nZVN0YXR1cyA9PT0gUGFzc3dvcmRDaGFuZ2VTdGF0dXMuUkVDT1ZFUllcbiAgICApIHtcbiAgICAgIGNvbnNvbGUubG9nKCdJbiByZWNvdmVyeSBtb2RlLicpO1xuXG4gICAgICAvLyBMZXQncyBzYXkgd2UgZG9uJ3Qga25vdyBpZiB0aGUgcGFzc3dvcmQgaXMgdGhlIG5ldyBvbmUgb3IgdGhlIG9sZCBvbmUuIFdlIGp1c3QgaGF2ZSB0byB0cnkgYm90aC5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHVzZXI6IExvZ2luQ2hhbGxlbmdlID0ge1xuICAgICAgICAgIGNvZ25pdG9Vc2VyOiBhd2FpdCB0aGlzLmxvZ2luSWRwSW1wbChcbiAgICAgICAgICAgIGVtYWlsT3JQaG9uZSxcbiAgICAgICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAgICAgcGFzc0lkcEFwaVJlc3VsdC5uZXdQYXNzSWRwUGFyYW1zXG4gICAgICAgICAgKSxcbiAgICAgICAgICByZWNvdmVyeVN0YXR1czogUmVjb3ZlcnlTdGF0dXMuTkVXX1BBU1NXT1JELFxuICAgICAgICB9O1xuICAgICAgICAvLyBOZXcgcGFzc3dvcmQgd29ya2VkLiBMZXQncyBzZXQgdG8gdGhlIGN1cnJlbnQgcGFzc3dvcmRcblxuICAgICAgICAvLyAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDEtLVxuICAgICAgICAvLyBpZiBjaGFuZ2VQYXNzd29yZENvbXBsZXRlKCkgZG9lc24ndCBnZXQgY2FsbGVkLCB0aGVuIGl0IHNob3VsZCByZW1haW5cblxuICAgICAgICBjb25zb2xlLmxvZygnTmV3IHBhc3N3b3JkIHdvcmtzIScpO1xuXG4gICAgICAgIHJldHVybiB1c2VyO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gSnVzdCBidWJibGUgdXAgYW55IG90aGVyIHR5cGUgb2YgZXJyb3IuXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSAnTm90QXV0aG9yaXplZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwYXNzLCB0cnkgYWdhaW4gYXNzdW1pbmcgaXQncyB0aGUgb2xkIHBhc3N3b3JkXG4gICAgICB9XG5cbiAgICAgIC8vIE5vdyBhc3N1bWUgaXQncyB0aGUgcHJldmlvdXMgcGFzc3dvcmQuIEFueSBleGNlcHRpb24gaXMgYWxsb3dlZCB0byBidWJibGUgdXAuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB1c2VyOiBMb2dpbkNoYWxsZW5nZSA9IHtcbiAgICAgICAgICBjb2duaXRvVXNlcjogYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXG4gICAgICAgICAgICBlbWFpbE9yUGhvbmUsXG4gICAgICAgICAgICBwYXNzd29yZCxcbiAgICAgICAgICAgIHBhc3NJZHBBcGlSZXN1bHQuY3VycmVudFBhc3NJZHBQYXJhbXNcbiAgICAgICAgICApLFxuICAgICAgICAgIHJlY292ZXJ5U3RhdHVzOiBSZWNvdmVyeVN0YXR1cy5PTERfUEFTU1dPUkQsXG4gICAgICAgIH07XG4gICAgICAgIC8vIE9sZCBwYXNzd29yZCB3b3JrZWQuXG4gICAgICAgIGNvbnNvbGUubG9nKCdPbGQgcGFzc3dvcmQgd29ya3MhJyk7XG5cbiAgICAgICAgcmV0dXJuIHVzZXI7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBKdXN0IGJ1YmJsZSB1cCBhbnkgb3RoZXIgdHlwZSBvZiBlcnJvci5cbiAgICAgICAgdGhyb3cgZXJyb3IuY29kZSA9PT0gJ05vdEF1dGhvcml6ZWRFeGNlcHRpb24nXG4gICAgICAgICAgPyBuZXcgS2NCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgICAgICAgICAnVGhlIHBhc3N3b3JkIGNoYW5nZSByZXF1ZXN0IHdhcyBpbnRlcnJ1cHRlZCwgcGxlYXNlIHRyeSB0byBsb2dpbiB3aXRoIGJvdGggeW91ciBuZXcgYW5kIG9sZCBwYXNzd29yZCdcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IGVycm9yO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRyeSBhZ2FpbiBhcyB0aGUgVFAgcGFzc3dvcmQgcmVzZXQgYWNjb3VudFxuICAgIGlmIChwYXNzSWRwQXBpUmVzdWx0LnRwUGFzc3dvcmRSZXNldCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gVFAgcGFzc3dvcmQgcmVzZXQgaXMgaW4gcHJvY2Vzcy4gV2UgbmVlZCB0byB0cnkgdGhlIHBhc3N3b3JkIGFnYWluc3QgYm90aFxuICAgICAgICAvLyBvcmlnaW5hbCBhY2NvdW50IGFuZCB0aGUgbmV3IHJlc2V0IGFjY291bnQuXG4gICAgICAgIGNvbnN0IHJlc2V0ID0gcGFzc0lkcEFwaVJlc3VsdC50cFBhc3N3b3JkUmVzZXQ7XG4gICAgICAgIGNvbnN0IHVzZXI6IExvZ2luQ2hhbGxlbmdlID0ge1xuICAgICAgICAgIGNvZ25pdG9Vc2VyOiBhd2FpdCB0aGlzLmxvZ2luSWRwSW1wbChcbiAgICAgICAgICAgIHJlc2V0LnJlc2V0VXNlcm5hbWUsXG4gICAgICAgICAgICBwYXNzd29yZCxcbiAgICAgICAgICAgIHJlc2V0LnBhc3NJZHBQYXJhbXNcbiAgICAgICAgICApLFxuICAgICAgICAgIHJlY292ZXJ5U3RhdHVzOiBSZWNvdmVyeVN0YXR1cy5OT05FLFxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB1c2VyO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIC8vIGNvbnRpbnVlLCB0cnkgYWdhaW4gYXMgcmVndWxhciB1c2VyLlxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIExvZ2luIGFzIHJlZ3VsYXIgdXNlclxuICAgIGNvbnN0IHVzZXI6IExvZ2luQ2hhbGxlbmdlID0ge1xuICAgICAgY29nbml0b1VzZXI6IGF3YWl0IHRoaXMubG9naW5JZHBJbXBsKFxuICAgICAgICBlbWFpbE9yUGhvbmUsXG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgICBwYXNzSWRwQXBpUmVzdWx0LmN1cnJlbnRQYXNzSWRwUGFyYW1zXG4gICAgICApLFxuICAgICAgcmVjb3ZlcnlTdGF0dXM6IFJlY292ZXJ5U3RhdHVzLk5PTkUsXG4gICAgfTtcblxuICAgIHJldHVybiB1c2VyO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2dpbklkcEltcGwoXG4gICAgZW1haWxPclBob25lOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IENyeXB0b0tleSxcbiAgICBwYXNzSWRwUGFyYW1zOiBQYXNzSWRwUGFyYW1zXG4gICk6IFByb21pc2U8THJDb2duaXRvVXNlcj4ge1xuICAgIGNvbnN0IHBhc3NJZHBSZXN1bHQgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnlTZXJ2aWNlLmRlcml2ZVBhc3NJZHAoe1xuICAgICAgcGFzc3dvcmQsXG4gICAgICAuLi5wYXNzSWRwUGFyYW1zLFxuICAgIH0pO1xuXG4gICAgLy8gVXNlIHRoZSBkZXJpdmVkIHBhc3N3b3JkIHRvIHNpZ25pbiB3aXRoIGNvZ25pdG9cbiAgICByZXR1cm4gdGhpcy5jb2duaXRvLnNpZ25JbihcbiAgICAgIGVtYWlsT3JQaG9uZSxcbiAgICAgIHRoaXMucGFzc3dvcmRTZXJ2aWNlLmdldFBhc3NJZHBTdHJpbmcocGFzc0lkcFJlc3VsdC5qd2spXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlUG9zdEF1dGgocmVjb3ZlcnlTdGF0dXM6IFJlY292ZXJ5U3RhdHVzKSB7XG4gICAgYXdhaXQgdGhpcy5oYW5kbGVQYXNzd29yZFJlY292ZXJ5KHJlY292ZXJ5U3RhdHVzKTtcbiAgICBhd2FpdCB0aGlzLmhhbmRsZVNlc3Npb25FbmNyeXB0aW9uS2V5KCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhbmRsZVBhc3N3b3JkUmVjb3ZlcnkocmVjb3ZlcnlTdGF0dXM6IFJlY292ZXJ5U3RhdHVzKSB7XG4gICAgaWYgKHJlY292ZXJ5U3RhdHVzICE9PSBSZWNvdmVyeVN0YXR1cy5OT05FKSB7XG4gICAgICBhd2FpdCB0aGlzLnBhc3N3b3JkU2VydmljZS5jaGFuZ2VQYXNzd29yZENvbXBsZXRlKHtcbiAgICAgICAgdXNlTmV3UGFzc3dvcmQ6IHJlY292ZXJ5U3RhdHVzID09PSBSZWNvdmVyeVN0YXR1cy5ORVdfUEFTU1dPUkQsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhbmRsZVNlc3Npb25FbmNyeXB0aW9uS2V5KCkge1xuICAgIGlmICh0aGlzLmtjQ29uZmlnLmRpc2FibGVTZXNzaW9uRW5jcnlwdGlvbktleSkge1xuICAgICAgaWYgKCFpc0Rldk1vZGUoKSkge1xuICAgICAgICBjb25zdCBtc2cgPVxuICAgICAgICAgICdZb3Ugc2hvdWxkIG5vdCBzZXQgZGlzYWJsZVNlc3Npb25FbmNyeXB0aW9uS2V5PVRydWUgaW4gbW9kZSBwcm9kLiBJdCBkZWZhdWx0cyB0byBmYWxzZS4nO1xuICAgICAgICBjb25zb2xlLmVycm9yKG1zZyk7XG4gICAgICAgIHRocm93IG5ldyBLY0ludGVybmFsRXJyb3JFeGNlcHRpb24obXNnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAnWW91IGhhdmUgc2V0IGRpc2FibGVTZXNzaW9uRW5jcnlwdGlvbktleT1UcnVlLiBNYWtlIHN1cmUgbm90IHRvIGRvIHRoaXMgaW4gcHJvZCBtb2RlLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU2V0IHRoZSBzZXNzaW9uIGtleSB0byBhIG5ldyBlbmNyeXB0aW9uIGtleSBmb3IgdGhpcyBzZXNzaW9uXG4gICAgICBjb25zdCBzZXNzaW9uRW5jcnlwdGlvbktleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeVNlcnZpY2UuY3JlYXRlS2V5KCk7XG4gICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xuICAgICAgICAgIG11dGF0aW9uOiBTZXRTZXNzaW9uRW5jcnlwdGlvbktleU11dGF0aW9uLFxuICAgICAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgc2Vzc2lvbkVuY3J5cHRpb25LZXk6IEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAgICAgIHNlc3Npb25FbmNyeXB0aW9uS2V5LnRvSlNPTih0cnVlKVxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIGluY2x1ZGVLZXlHcmFwaDogZmFsc2UsXG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIHRoaXMucGVyc2lzdFNlcnZpY2Uuc2V0U2VydmVyU2Vzc2lvbkVuY3J5cHRpb25LZXkoc2Vzc2lvbkVuY3J5cHRpb25LZXkpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29nbml0b1VzZXJBdHRyaWJ1dGUoXG4gICAgYXR0cmlidXRlTmFtZTogc3RyaW5nLFxuICAgIHVzZXJBdHRyaWJ1dGVzOiBDb2duaXRvVXNlckF0dHJpYnV0ZVtdXG4gICkge1xuICAgIGNvbnN0IHVzZXJBdHRyaWJ1dGUgPSB1c2VyQXR0cmlidXRlcy5maW5kKFxuICAgICAgKHgpID0+IHguZ2V0TmFtZSgpID09PSBhdHRyaWJ1dGVOYW1lXG4gICAgKTtcblxuICAgIHJldHVybiB1c2VyQXR0cmlidXRlID8gdXNlckF0dHJpYnV0ZS5nZXRWYWx1ZSgpIDogbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZFVzZXJLZXlzKG9wdGlvbnM6IHtcbiAgICB1c2VyS2V5czogVXNlcktleXM7XG4gICAgcGFzc3dvcmQ/OiBDcnlwdG9LZXk7XG4gICAgc2Vzc2lvbkVuY3J5cHRpb25LZXk/OiBzdHJpbmc7XG4gIH0pIHtcbiAgICBjb25zdCB7IHVzZXJLZXlzLCBwYXNzd29yZCwgc2Vzc2lvbkVuY3J5cHRpb25LZXkgfSA9IG9wdGlvbnM7XG5cbiAgICBpZiAoc2Vzc2lvbkVuY3J5cHRpb25LZXkpIHtcbiAgICAgIHRoaXMucGVyc2lzdFNlcnZpY2Uuc2V0U2VydmVyU2Vzc2lvbkVuY3J5cHRpb25LZXkoXG4gICAgICAgIGF3YWl0IEpXSy5hc0tleShzZXNzaW9uRW5jcnlwdGlvbktleSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gcGFzc3dvcmQgaXMgbm90IG5lZWRlZCBpZiB0aGUgbWFzdGVyIGtleSBpcyBhbHJlYWR5IHBlcnNpc3RlZC5cbiAgICBpZiAocGFzc3dvcmQpIHtcbiAgICAgIGNvbnN0IHBhc3NLZXkgPSAoXG4gICAgICAgIGF3YWl0IHRoaXMua2V5RmFjdG9yeVNlcnZpY2UuZGVyaXZlUGFzc0tleSh7XG4gICAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgICAgLi4udXNlcktleXMucGFzc0tleS5wYXNzS2V5UGFyYW1zLFxuICAgICAgICB9KVxuICAgICAgKS5qd2s7XG5cbiAgICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2UucGVyc2lzdE1hc3RlcktleShcbiAgICAgICAgYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UudW53cmFwV2l0aFBhc3NLZXkoXG4gICAgICAgICAgdXNlcktleXMucGFzc0tleS5pZCxcbiAgICAgICAgICBwYXNzS2V5LFxuICAgICAgICAgIHVzZXJLZXlzLm1hc3RlcktleS5pZFxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZFVzZXIoXG4gICAgY29nbml0b1VzZXI6IENvZ25pdG9Vc2VyLFxuICAgIHBhc3N3b3JkPzogQ3J5cHRvS2V5XG4gICk6IFByb21pc2U8QXV0aFVzZXI+IHtcbiAgICBpZiAoY29nbml0b1VzZXIuZ2V0VXNlcm5hbWUoKS5lbmRzV2l0aChUUF9QQVNTV09SRF9SRVNFVF9VU0VSTkFNRV9TVUZGSVgpKSB7XG4gICAgICB0aGlzLnVzZXIgPSBhd2FpdCB0aGlzLmxvYWRSZXNldFVzZXIoY29nbml0b1VzZXIsIHBhc3N3b3JkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy51c2VyID0gYXdhaXQgdGhpcy5sb2FkUmVndWxhclVzZXIoY29nbml0b1VzZXIsIHBhc3N3b3JkKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmlkbGVTZXJ2aWNlLnN0YXJ0KCk7IC8vIFJ1biBpZGxlU2VydmljZSB3aGVuZXZlciB1c2VyIGlzIGxvZ2dlZCBpbi5cblxuICAgIHJldHVybiB0aGlzLnVzZXI7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRSZWd1bGFyVXNlcihcbiAgICBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIsXG4gICAgcGFzc3dvcmQ/OiBDcnlwdG9LZXlcbiAgKTogUHJvbWlzZTxBdXRoVXNlcj4ge1xuICAgIGNvbnN0IGN1cnJlbnRVc2VyID0gYXdhaXQgdGhpcy5mZXRjaEN1cnJlbnRVc2VyKCk7XG5cbiAgICBhd2FpdCB0aGlzLmxvYWRVc2VyS2V5cyh7XG4gICAgICB1c2VyS2V5czogY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXksXG4gICAgICBwYXNzd29yZCxcbiAgICAgIHNlc3Npb25FbmNyeXB0aW9uS2V5OiBjdXJyZW50VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSxcbiAgICB9KTtcblxuICAgIC8vIFJlZ3VsYXIgdXNlciBwb3B1bGF0ZXMgYWxsIGtleXNcbiAgICBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS5wb3B1bGF0ZUtleXMoY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkpO1xuXG4gICAgY29uc3QgeyB1c2VybmFtZSB9ID0gY3VycmVudFVzZXI7XG4gICAgY29uc3QgdXNlckF0dHJpYnV0ZXMgPSBhd2FpdCB0aGlzLmNvZ25pdG8udXNlckF0dHJpYnV0ZXMoY29nbml0b1VzZXIpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXJuYW1lLFxuICAgICAgc3ViOiB0aGlzLmdldENvZ25pdG9Vc2VyQXR0cmlidXRlKCdzdWInLCB1c2VyQXR0cmlidXRlcyksXG4gICAgICBsb2dpbkVtYWlsOiB0aGlzLmdldENvZ25pdG9Vc2VyQXR0cmlidXRlKCdlbWFpbCcsIHVzZXJBdHRyaWJ1dGVzKSxcbiAgICAgIHJlc2V0VXNlcjogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2FkUmVzZXRVc2VyKFxuICAgIGNvZ25pdG9Vc2VyOiBDb2duaXRvVXNlcixcbiAgICBwYXNzd29yZD86IENyeXB0b0tleVxuICApOiBQcm9taXNlPEF1dGhVc2VyPiB7XG4gICAgY29uc3QgcmVzZXRVc2VyID0gYXdhaXQgdGhpcy5mZXRjaFJlc2V0VXNlcigpO1xuXG4gICAgY29uc3QgdXNlcktleXMgPSB7XG4gICAgICBwYXNzS2V5OiB7XG4gICAgICAgIGlkOiByZXNldFVzZXIucGFzc0tleS5pZCxcbiAgICAgICAgcGFzc0tleVBhcmFtczogcmVzZXRVc2VyLnBhc3NLZXkucGFzc0tleVBhcmFtcyxcbiAgICAgIH0sXG4gICAgICBtYXN0ZXJLZXk6IHtcbiAgICAgICAgaWQ6IHJlc2V0VXNlci5tYXN0ZXJLZXkuaWQsXG4gICAgICB9LFxuICAgIH07XG5cbiAgICBhd2FpdCB0aGlzLmxvYWRVc2VyS2V5cyh7XG4gICAgICB1c2VyS2V5cyxcbiAgICAgIHBhc3N3b3JkLFxuICAgICAgc2Vzc2lvbkVuY3J5cHRpb25LZXk6IHJlc2V0VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSxcbiAgICB9KTtcblxuICAgIC8vIFJlc2V0IHVzZXIgb25seSBzZXRzIGEgc3Vic2V0IG9mIGtleXNcbiAgICBhd2FpdCB0aGlzLmtleVNlcnZpY2Uuc2V0S2V5cyh1c2VyS2V5cyk7XG5cbiAgICBjb25zdCB7IHVzZXJuYW1lIH0gPSByZXNldFVzZXI7XG4gICAgY29uc3QgdXNlckF0dHJpYnV0ZXMgPSBhd2FpdCB0aGlzLmNvZ25pdG8udXNlckF0dHJpYnV0ZXMoY29nbml0b1VzZXIpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXJuYW1lLFxuICAgICAgc3ViOiB0aGlzLmdldENvZ25pdG9Vc2VyQXR0cmlidXRlKCdzdWInLCB1c2VyQXR0cmlidXRlcyksXG4gICAgICBsb2dpbkVtYWlsOiB0aGlzLmdldENvZ25pdG9Vc2VyQXR0cmlidXRlKCdlbWFpbCcsIHVzZXJBdHRyaWJ1dGVzKSxcbiAgICAgIHJlc2V0VXNlcjoge1xuICAgICAgICBzdGF0ZTogcmVzZXRVc2VyLnN0YXRlLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWNvdmVyQXNzZW1ibHlLZXkoXG4gICAgcmVzZXRVc2VyOiBSZXNldFVzZXJRdWVyeVJlc3VsdFsndHBQYXNzd29yZFJlc2V0VXNlciddXG4gICk6IFByb21pc2U8SldLLktleT4ge1xuICAgIGNvbnN0IHByayA9IGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLmdldEtleShyZXNldFVzZXIucHhrLmlkKTtcblxuICAgIGNvbnN0IHBhcnRpYWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICByZXNldFVzZXIuYXBwcm92YWxzXG4gICAgICAgIC5maWx0ZXIoKGFwcHJvdmFsKSA9PiAhIWFwcHJvdmFsLnJlY2VpdmVyQ2lwaGVyUGFydGlhbEFzc2VtYmx5S2V5KVxuICAgICAgICAubWFwKChhcHByb3ZhbCkgPT5cbiAgICAgICAgICB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXG4gICAgICAgICAgICBwcmssXG4gICAgICAgICAgICBhcHByb3ZhbC5yZWNlaXZlckNpcGhlclBhcnRpYWxBc3NlbWJseUtleVxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICByZXR1cm4gdGhpcy5hc3NlbWJseUNvbnRyb2xsZXIucmVjb3ZlckFzc2VtYmx5S2V5KHBhcnRpYWxzKTtcbiAgfVxuXG4gIGFzeW5jIGNvbXBsZXRlUmVzZXRSZXF1ZXN0KG5ld1Bhc3N3b3JkOiBDcnlwdG9LZXkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXNldFVzZXIgPSBhd2FpdCB0aGlzLmZldGNoUmVzZXRVc2VyKCk7XG5cbiAgICBpZiAocmVzZXRVc2VyLnN0YXRlICE9PSBUcENsYWltU3RhdGUuQVBQUk9WRUQpIHtcbiAgICAgIHRocm93IG5ldyBLY0JhZFN0YXRlRXhjZXB0aW9uKFxuICAgICAgICAnUGFzc3dvcmQgcmVzZXQgcmVxdWVzdCBoYXMgbm90IGJlZW4gYXBwcm92ZWQuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFByZXBhcmUgYWxsIG1hdGVyaWFscyB0byBlbnN1cmUgdGhlcmUgYXJlIG5vIGVycm9ycy5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IGFzc2VtYmx5S2V5ID0gYXdhaXQgdGhpcy5yZWNvdmVyQXNzZW1ibHlLZXkocmVzZXRVc2VyKTtcblxuICAgIGNvbnN0IHsgcm9vdEtleSB9ID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxuICAgICAgYXNzZW1ibHlLZXksXG4gICAgICByZXNldFVzZXIuYXNzZW1ibHlDaXBoZXJEYXRhXG4gICAgKTtcblxuICAgIC8vIE1ha2luZyBzdXJlIGl0J3MgYSB2YWxpZCBrZXkuXG4gICAgY29uc3Qgcm9vdEtleUp3ayA9IGF3YWl0IEpXSy5hc0tleShyb290S2V5KTtcblxuICAgIGNvbnN0IG1hc3RlcktleSA9IGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLmdldEtleShyZXNldFVzZXIubWFzdGVyS2V5LmlkKTtcblxuICAgIGNvbnN0IG1hc3RlcktleVdyYXBwZWRSb290S2V5ID1cbiAgICAgIGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdFRvU3RyaW5nKFxuICAgICAgICBtYXN0ZXJLZXkuandrLFxuICAgICAgICByb290S2V5SndrLnRvSlNPTih0cnVlKVxuICAgICAgKTtcblxuICAgIC8vIFRoZSBuZXcgcGFzc3dvcmRcbiAgICBjb25zdCBuZXdQYXNzSWRwUmVzdWx0ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5U2VydmljZS5kZXJpdmVQYXNzSWRwKHtcbiAgICAgIHBhc3N3b3JkOiBuZXdQYXNzd29yZCxcbiAgICAgIC4uLnJlc2V0VXNlci5wYXNzS2V5LnBhc3NJZHBQYXJhbXMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBuZXdJZHBQYXNzd29yZCA9IHRoaXMucGFzc3dvcmRTZXJ2aWNlLmdldFBhc3NJZHBTdHJpbmcoXG4gICAgICBuZXdQYXNzSWRwUmVzdWx0Lmp3a1xuICAgICk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEdldCBhc3NlbWJseSBrZXkgY2hhbGxlbmdlXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBjaGFsbGVuZ2UgPSAoXG4gICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xuICAgICAgICAgIG11dGF0aW9uOiBDcmVhdGVUcEFzc2VtYmx5S2V5Q2hhbGxlbmdlTXV0YXRpb24sXG4gICAgICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgICAgICBpbnB1dDoge30sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBpbmNsdWRlS2V5R3JhcGg6IGZhbHNlLFxuICAgICAgICB9XG4gICAgICApXG4gICAgKS5jcmVhdGVUcEFzc2VtYmx5S2V5Q2hhbGxlbmdlLmNoYWxsZW5nZTtcblxuICAgIC8vIFNpZ24gdGhlIGNoYWxsZW5nZVxuICAgIC8vIEdlbmVyYXRlIGEgY2xpZW50IHNpZGUgbm9uY2UgdGhhdCdzIG5vIGluIHRoZSBzZXJ2ZXIncyBjb250cm9sLlxuICAgIGNoYWxsZW5nZS5jbGllbnROb25jZSA9IHRoaXMua2V5RmFjdG9yeVNlcnZpY2UucmFuZG9tU3RyaW5nKFxuICAgICAgVFBfUEFTU1dPUkRfUkVTRVRfQ0xJRU5UX05PTkNFX0xFTkdUSFxuICAgICk7XG5cbiAgICBjb25zdCBhc3NlbWJseUtleVZlcmlmaWVyUHJrID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxuICAgICAgYXNzZW1ibHlLZXksXG4gICAgICByZXNldFVzZXIud3JhcHBlZEFzc2VtYmx5S2V5VmVyaWZpZXJQcmtcbiAgICApO1xuICAgIGNvbnN0IHNpZ25lZENoYWxsZW5nZSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2Uuc2lnbihcbiAgICAgIGFzc2VtYmx5S2V5VmVyaWZpZXJQcmssXG4gICAgICBjaGFsbGVuZ2VcbiAgICApO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBDaGFuZ2UgcGFzc3dvcmQgZm9yIHRoZSBvcmlnaW5hbCB1c2VyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCB0ZW1wSWRwUGFzc3dvcmQgPSAoXG4gICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xuICAgICAgICAgIG11dGF0aW9uOiBQcmVDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3RNdXRhdGlvbixcbiAgICAgICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgICAgIGlucHV0OiB7XG4gICAgICAgICAgICAgIHNpZ25lZENoYWxsZW5nZTogSlNPTi5zdHJpbmdpZnkoc2lnbmVkQ2hhbGxlbmdlKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBpbmNsdWRlS2V5R3JhcGg6IGZhbHNlLFxuICAgICAgICB9XG4gICAgICApXG4gICAgKS5wcmVDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3QuaWRwUGFzc3dvcmQ7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIExvZ2luIGFzIHRoZSBvcmlnaW5hbCB1c2VyIHVzaW5nIG5ldyB0ZW1wb3JhcnkgcGFzc3dvcmRcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHRoZSBvcmlnaW5hbCBhY2NvdW50J3MgcGFzc3dvcmQgaGFzIGJlZW4gY2hhbmdlZFxuICAgIC8vIHRvIGEgdGVtcG9yYXJ5IHBhc3N3b3JkLiBJdCBpcyBubyBsb25nZXIgcG9zc2libGUgZm9yIHRoZSB1c2VyXG4gICAgLy8gdG8gdXNlIHRoZSBvcmlnaW5hbCBwYXNzd29yZCB0byBsb2dpbi4gQW55IHN1Y2Nlc3NmdWwgbG9naW5cbiAgICAvLyBjYW4gb25seSBiZSB1c2luZyB0aGUgdGVtcG9yYXJ5IHBhc3N3b3JkLiBTbyBpdCdzIHNhZmUgdG8gYXNzdW1lXG4gICAgLy8gdGhhdCB3ZSB3YW50IHRvIFwiY29tcGxldGVcIiB0aGUgcGFzc3dvcmQgcmVzZXQuXG5cbiAgICAvLyBUaGVyZSBtYXliZSAyRkEgc28gd2UgbGlzdGVuIGZvciB0aGUgYXV0aCBldmVudCBmcm9tIEFtcGxpZnkuXG4gICAgY29uc3QgcmV0UHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBsaXN0ZW5lciA9IGFzeW5jIChkYXRhKSA9PiB7XG4gICAgICAgIGlmIChkYXRhLnBheWxvYWQuZXZlbnQgIT09ICdzaWduSW4nKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgSHViLnJlbW92ZSgnYXV0aCcsIGxpc3RlbmVyKTtcblxuICAgICAgICBhd2FpdCB0aGlzLmNvZ25pdG8uc2lnbkluKHJlc2V0VXNlci51c2VybmFtZSwgbmV3SWRwUGFzc3dvcmQpO1xuXG4gICAgICAgIC8vIFN3aXRjaCBvdmVyIHRvIHRoZSBuZXcgc2V0IG9mIGtleXNcbiAgICAgICAgYXdhaXQgdGhpcy5sckdyYXBoUUwubHJNdXRhdGUoXG4gICAgICAgICAgbmV3IExyTXV0YXRpb24oe1xuICAgICAgICAgICAgbXV0YXRpb246IENvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLFxuICAgICAgICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgICAgICAgIGlucHV0OiB7XG4gICAgICAgICAgICAgICAgbWFzdGVyS2V5V3JhcHBlZFJvb3RLZXksXG4gICAgICAgICAgICAgICAgbWFzdGVyS2V5SWQ6IG1hc3RlcktleS5pZCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9O1xuXG4gICAgICBIdWIubGlzdGVuKCdhdXRoJywgbGlzdGVuZXIpO1xuICAgIH0pO1xuXG4gICAgLy8gU2lnbmluIGFzIHRoZSBvcmlnaW5hbCB1c2VyLiBQYXNzd29yZCBoYXMgYmVlbiByZXNldCB0byB0ZW1wb3Jhcnkgb25lLiBJdCBzaG91bGQgcmV0dXJuXG4gICAgLy8gd2l0aCBORVdfUEFTU1dPUkRfUkVRVUlSRURcbiAgICBsZXQgdXNlciA9IGF3YWl0IHRoaXMuY29nbml0by5zaWduSW4ocmVzZXRVc2VyLnVzZXJuYW1lLCB0ZW1wSWRwUGFzc3dvcmQsIHtcbiAgICAgIG5vUHJveHk6ICd0cnVlJyxcbiAgICB9KTtcblxuICAgIGlmICh1c2VyLmNoYWxsZW5nZU5hbWUgIT09ICdORVdfUEFTU1dPUkRfUkVRVUlSRUQnKSB7XG4gICAgICB0aHJvdyBuZXcgS2NJbnRlcm5hbEVycm9yRXhjZXB0aW9uKFxuICAgICAgICAnRXhwZWN0aW5nIENvZ25pdG8gdG8gaGF2ZSBkb25lIGEgcGFzc3dvcmQgcmVzZXQgYWZ0ZXIgY2FsbCB0byBQcmVDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3RNdXRhdGlvbi4nXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFNldCBuZXcgcGFzc3dvcmQgb24gSWRwXG4gICAgLy8gdGhlIGF3c0ZldGNoKCkgZnVuY3Rpb24gcGFzc2VzIE5FV19QQVNTV09SRF9SRVFVSVJFRCBkaXJlY3RseSB0byBBV1Mgd2l0aG91dFxuICAgIC8vIGdvaW5nIHRocm91Z2ggdGhlIHByb3h5LlxuICAgIHVzZXIgPSBhd2FpdCB0aGlzLmNvZ25pdG8uY29tcGxldGVOZXdQYXNzd29yZCh1c2VyLCBuZXdJZHBQYXNzd29yZCwge30pO1xuXG4gICAgcmV0dXJuIHJldFByb21pc2U7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gRGVidWcgdXRpbGl0aWVzXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZWJ1Z0xvZ2luKHVzZXJuYW1lOiBzdHJpbmcsIHBhc3N3b3JkOiBDcnlwdG9LZXkpOiBQcm9taXNlPEF1dGhVc2VyPiB7XG4gICAgLy8gVGhpcyB3aWxsIGZhaWwgaWYgZGVidWcgaXMgbnVsbC4gQnV0IHdoZW4gZGVidWcgaXMgbnVsbCwgdGhpcyBmdW5jdGlvblxuICAgIC8vIHNob3VsZCBub3QgYmUgY2FsbGVkLlxuICAgIHRoaXMua2NDb25maWcuZGVidWcudXNlcm5hbWUgPSB1c2VybmFtZTtcblxuICAgIHJldHVybiB0aGlzLmRlYnVnTG9hZFVzZXIocGFzc3dvcmQpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkZWJ1Z0xvYWRVc2VyKHBhc3N3b3JkOiBDcnlwdG9LZXkpOiBQcm9taXNlPEF1dGhVc2VyPiB7XG4gICAgY29uc3QgY3VycmVudFVzZXIgPSBhd2FpdCB0aGlzLmZldGNoQ3VycmVudFVzZXIoKTtcblxuICAgIGNvbnN0IHsgdXNlcm5hbWUsIGN1cnJlbnRVc2VyS2V5IH0gPSBjdXJyZW50VXNlcjtcblxuICAgIC8vIERlYnVnIG1vZGUgY2FuIG5vdCBkZWFsIHdpdGggc2Vzc2lvbiBlbmNyeXB0aW9uIGtleSB5ZXQuXG4gICAgLy8gTk8gU0VTU0lPTiBFTkNSWVBUSU9OIEtFWS5cblxuICAgIGNvbnN0IHBhc3NLZXkgPSAoXG4gICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnlTZXJ2aWNlLmRlcml2ZVBhc3NLZXkoe1xuICAgICAgICBwYXNzd29yZCxcbiAgICAgICAgLi4uY3VycmVudFVzZXJLZXkucGFzc0tleS5wYXNzS2V5UGFyYW1zLFxuICAgICAgfSlcbiAgICApLmp3aztcblxuICAgIGNvbnN0IG1hc3RlcktleSA9IGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLnVud3JhcFdpdGhQYXNzS2V5KFxuICAgICAgY3VycmVudFVzZXJLZXkucGFzc0tleS5pZCxcbiAgICAgIHBhc3NLZXksXG4gICAgICBjdXJyZW50VXNlcktleS5tYXN0ZXJLZXkuaWRcbiAgICApO1xuXG4gICAgYXdhaXQgdGhpcy5pZGxlU2VydmljZS5wZXJzaXN0TWFzdGVyS2V5KG1hc3RlcktleSk7XG5cbiAgICBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS5wb3B1bGF0ZUtleXMoY3VycmVudFVzZXJLZXkpO1xuXG4gICAgdGhpcy51c2VyID0ge1xuICAgICAgdXNlcm5hbWUsXG4gICAgICByZXNldFVzZXI6IG51bGwsXG4gICAgICBzdWI6ICdERUJVR19NT0RFJyxcbiAgICAgIGxvZ2luRW1haWw6ICdERUJVR19NT0RFJyxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMudXNlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhcnMgdGhlIGNhY2hlcyB1c2VyLiBTbyB3ZSBjYW4gc2ltdWxhdGUgYSBwYWdlIHJlZnJlc2ggYW5kIHRlc3QgZ2V0VXNlcigpLlxuICAgKi9cbiAgZGVidWdDbGVhclVzZXIoKSB7XG4gICAgdGhpcy51c2VyID0gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGdldEN1cnJlbnRVc2VyQXR0cmlidXRlcygpOiBQcm9taXNlPExyQ29nbml0b1VzZXJBdHRyaWJ1dGVbXT4ge1xuICAgIGNvbnN0IGNvZ25pdG9Vc2VyID0gYXdhaXQgdGhpcy5jb2duaXRvLmN1cnJlbnRBdXRoZW50aWNhdGVkVXNlcigpO1xuICAgIGNvbnN0IHVzZXJBdHRyaWJ1dGVzID0gYXdhaXQgdGhpcy5jb2duaXRvLnVzZXJBdHRyaWJ1dGVzKGNvZ25pdG9Vc2VyKTtcblxuICAgIHJldHVybiB1c2VyQXR0cmlidXRlcztcbiAgfVxufVxuIl19
|