@lifeready/core 6.1.3 → 6.1.5
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 +303 -295
- 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/idle/idle.service.js +3 -3
- 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 +191 -213
- package/fesm2015/lifeready-core.js.map +1 -1
- package/lib/{auth2/auth2.service.d.ts → auth/auth.service.d.ts} +2 -2
- package/lib/idle/idle.service.d.ts +9 -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
|
@@ -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=
|