@idea-ionic/auth 6.12.3 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/environment.d.ts +7 -0
  2. package/esm2022/environment.mjs +34 -0
  3. package/esm2022/src/auth.module.mjs +84 -0
  4. package/esm2022/src/auth.service.mjs +479 -0
  5. package/esm2022/src/confirmPassword.page.mjs +70 -0
  6. package/esm2022/src/forgotPassword.page.mjs +41 -0
  7. package/{esm2020 → esm2022}/src/mfaChallenge.page.mjs +5 -5
  8. package/esm2022/src/newPassword.page.mjs +62 -0
  9. package/esm2022/src/passwordPolicy.component.mjs +64 -0
  10. package/esm2022/src/resendLink.page.mjs +47 -0
  11. package/{esm2020 → esm2022}/src/setupMFA/setupMFA.module.mjs +5 -5
  12. package/{esm2020 → esm2022}/src/setupMFA/setupMFAButton.component.mjs +4 -4
  13. package/{esm2020 → esm2022}/src/setupMFA/setupMFAModal.component.mjs +4 -4
  14. package/esm2022/src/setupMFA.page.mjs +24 -0
  15. package/esm2022/src/signIn.page.mjs +82 -0
  16. package/esm2022/src/signUp.page.mjs +79 -0
  17. package/fesm2022/idea-ionic-auth.mjs +1126 -0
  18. package/fesm2022/idea-ionic-auth.mjs.map +1 -0
  19. package/package.json +17 -23
  20. package/src/auth.module.d.ts +8 -7
  21. package/src/auth.service.d.ts +11 -0
  22. package/src/confirmPassword.page.d.ts +12 -3
  23. package/src/newPassword.page.d.ts +12 -3
  24. package/src/passwordPolicy.component.d.ts +13 -0
  25. package/src/setupMFA/setupMFAButton.component.d.ts +1 -1
  26. package/src/signIn.page.d.ts +2 -2
  27. package/src/signUp.page.d.ts +12 -3
  28. package/esm2020/environment.mjs +0 -26
  29. package/esm2020/src/auth.module.mjs +0 -81
  30. package/esm2020/src/auth.service.mjs +0 -443
  31. package/esm2020/src/confirmPassword.page.mjs +0 -53
  32. package/esm2020/src/forgotPassword.page.mjs +0 -41
  33. package/esm2020/src/newPassword.page.mjs +0 -45
  34. package/esm2020/src/resendLink.page.mjs +0 -47
  35. package/esm2020/src/setupMFA.page.mjs +0 -24
  36. package/esm2020/src/signIn.page.mjs +0 -82
  37. package/esm2020/src/signUp.page.mjs +0 -65
  38. package/fesm2015/idea-ionic-auth.mjs +0 -1019
  39. package/fesm2015/idea-ionic-auth.mjs.map +0 -1
  40. package/fesm2020/idea-ionic-auth.mjs +0 -988
  41. package/fesm2020/idea-ionic-auth.mjs.map +0 -1
  42. /package/{esm2020 → esm2022}/idea-ionic-auth.mjs +0 -0
  43. /package/{esm2020 → esm2022}/public-api.mjs +0 -0
@@ -0,0 +1,479 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { AuthenticationDetails, CognitoUser, CognitoUserAttribute, CognitoUserPool, CognitoRefreshToken } from 'amazon-cognito-identity-js';
3
+ import { environment as env } from '@env';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@idea-ionic/common";
6
+ /**
7
+ * The name of the Cognito's user attribute which contains the key of the last device to login in this project.
8
+ */
9
+ const DEVICE_KEY_ATTRIBUTE = 'custom:'.concat(env.idea.project);
10
+ /**
11
+ * Cognito wrapper to manage the authentication flow.
12
+ *
13
+ * Note: in IDEA's Cognito users pools, the email is an alias of the username.
14
+ */
15
+ export class IDEAAuthService {
16
+ constructor(storage) {
17
+ this.storage = storage;
18
+ this.mfaProjectName = env.idea.app.title ?? env.idea.project;
19
+ this.passwordPolicy = env.idea.auth.passwordPolicy;
20
+ this.userPool = new CognitoUserPool({
21
+ UserPoolId: env.aws.cognito.userPoolId,
22
+ ClientId: env.aws.cognito.userPoolClientId
23
+ });
24
+ }
25
+ /**
26
+ * Prepare the necessary structure to get authorized in Cognito.
27
+ */
28
+ prepareAuthDetails(username, pwd) {
29
+ return new AuthenticationDetails({ Username: username, Password: pwd });
30
+ }
31
+ /**
32
+ * Prepare the necessary structure to identify a Cognito user.
33
+ */
34
+ prepareCognitoUser(username) {
35
+ return new CognitoUser({ Username: username, Pool: this.userPool });
36
+ }
37
+ /**
38
+ * Prepare a user attribute (they are all strings) in Cognito's format.
39
+ */
40
+ prepareUserAttribute(name, value) {
41
+ return new CognitoUserAttribute({ Name: name, Value: value });
42
+ }
43
+ /**
44
+ * Perform a login through username and password.
45
+ */
46
+ login(username, password) {
47
+ return new Promise((resolve, reject) => {
48
+ const user = this.prepareCognitoUser(username);
49
+ user.authenticateUser(this.prepareAuthDetails(username, password), {
50
+ onSuccess: () => resolve(env.idea.auth.forceLoginWithMFA ? LoginOutcomeActions.MFA_SETUP : LoginOutcomeActions.NONE),
51
+ onFailure: (err) => reject(err),
52
+ newPasswordRequired: () => {
53
+ this.challengeUsername = username;
54
+ this.challengePassword = password;
55
+ resolve(LoginOutcomeActions.NEW_PASSWORD);
56
+ },
57
+ totpRequired: () => {
58
+ this.challengeUsername = username;
59
+ this.challengePassword = password;
60
+ resolve(LoginOutcomeActions.MFA_CHALLENGE);
61
+ }
62
+ });
63
+ });
64
+ }
65
+ /**
66
+ * Complete the new password flow in the authentication.
67
+ */
68
+ confirmNewPassword(newPassword) {
69
+ return new Promise((resolve, reject) => {
70
+ const user = this.prepareCognitoUser(this.challengeUsername);
71
+ user.authenticateUser(this.prepareAuthDetails(this.challengeUsername, this.challengePassword), {
72
+ onSuccess: () => resolve(),
73
+ onFailure: (err) => reject(err),
74
+ newPasswordRequired: () => user.completeNewPasswordChallenge(newPassword, {}, {
75
+ onSuccess: () => {
76
+ this.challengeUsername = null;
77
+ this.challengePassword = null;
78
+ resolve();
79
+ },
80
+ onFailure: (err) => reject(err)
81
+ })
82
+ });
83
+ });
84
+ }
85
+ /**
86
+ * Complete the MFA challenge flow in the authentication.
87
+ */
88
+ completeMFAChallenge(otpCode) {
89
+ return new Promise((resolve, reject) => {
90
+ const user = this.prepareCognitoUser(this.challengeUsername);
91
+ user.authenticateUser(this.prepareAuthDetails(this.challengeUsername, this.challengePassword), {
92
+ onSuccess: () => resolve(),
93
+ onFailure: (err) => reject(err),
94
+ totpRequired: (challengeName) => user.sendMFACode(otpCode, {
95
+ onSuccess: () => {
96
+ this.challengeUsername = null;
97
+ this.challengePassword = null;
98
+ resolve();
99
+ },
100
+ onFailure: err => reject(err)
101
+ }, challengeName)
102
+ });
103
+ });
104
+ }
105
+ /**
106
+ * Register a new user a set its default attributes.
107
+ */
108
+ register(username, password, attributes) {
109
+ attributes = attributes || {};
110
+ return new Promise((resolve, reject) => {
111
+ // add attributes like the email address and the fullname
112
+ const attrs = [];
113
+ for (const prop in attributes)
114
+ if (attributes[prop])
115
+ attrs.push(this.prepareUserAttribute(prop, attributes[prop]));
116
+ // add the email, which is equal to the username for most of our Pools
117
+ if (!attributes.email)
118
+ attrs.push(this.prepareUserAttribute('email', username));
119
+ // register the new user to the pool
120
+ this.userPool.signUp(username, password, attrs, null, (err, res) => {
121
+ if (err)
122
+ return reject(err);
123
+ this.newAccountJustRegistered = username;
124
+ resolve(res.user);
125
+ });
126
+ });
127
+ }
128
+ /**
129
+ * In case new account has just been registered, return the username.
130
+ */
131
+ getNewAccountJustRegistered() {
132
+ return this.newAccountJustRegistered;
133
+ }
134
+ /**
135
+ * Confirm a new registration through the confirmation code sent by Cognito.
136
+ */
137
+ confirmRegistration(username, code) {
138
+ return new Promise((resolve, reject) => {
139
+ this.prepareCognitoUser(username).confirmRegistration(code, true, (err) => err ? reject(err) : resolve());
140
+ });
141
+ }
142
+ /**
143
+ * Send again a confirmation code for a new registration.
144
+ */
145
+ resendConfirmationCode(username) {
146
+ return new Promise((resolve, reject) => {
147
+ this.prepareCognitoUser(username).resendConfirmationCode((err) => (err ? reject(err) : resolve()));
148
+ });
149
+ }
150
+ /**
151
+ * Logout the currently signed-in user.
152
+ */
153
+ logout(options) {
154
+ options = Object.assign({ global: false }, options);
155
+ return new Promise((resolve, reject) => {
156
+ // remove the refresh token previosly saved
157
+ this.storage.remove('AuthRefreshToken').then(() =>
158
+ // remove the optional auth details
159
+ this.storage.remove('AuthUserDetails').then(() => {
160
+ // get the user and the session
161
+ const user = this.userPool.getCurrentUser();
162
+ user.getSession(async (err) => {
163
+ // if the session is active, run the online sign-out; otherwise, only the local data has been deleted
164
+ if (err)
165
+ return resolve();
166
+ // if a reference to the device was saved, forget it
167
+ if (env.idea.auth.singleSimultaneousSession)
168
+ await this.setCurrentDeviceForProject(null);
169
+ // sign-out from the pool (terminate the current session or all the sessions)
170
+ if (options.global)
171
+ user.globalSignOut({ onSuccess: () => resolve(), onFailure: err => reject(err) });
172
+ else {
173
+ user.signOut();
174
+ resolve();
175
+ }
176
+ });
177
+ }));
178
+ });
179
+ }
180
+ /**
181
+ * Send a password reset request.
182
+ */
183
+ forgotPassword(username) {
184
+ return new Promise((resolve, reject) => {
185
+ this.prepareCognitoUser(username).forgotPassword({
186
+ onSuccess: () => resolve(),
187
+ onFailure: (err) => reject(err)
188
+ });
189
+ });
190
+ }
191
+ /**
192
+ * Confirm a new password after a password reset request.
193
+ */
194
+ confirmPassword(username, code, newPwd) {
195
+ return new Promise((resolve, reject) => {
196
+ this.prepareCognitoUser(username).confirmPassword(code, newPwd, {
197
+ onSuccess: () => resolve(),
198
+ onFailure: (err) => reject(err)
199
+ });
200
+ });
201
+ }
202
+ /**
203
+ * Gets the URL for enabling MFA. This URL can be used to generate a QR Code to read with an authenticator app.
204
+ */
205
+ getURLForEnablingMFA() {
206
+ return new Promise((resolve, reject) => {
207
+ const user = this.userPool.getCurrentUser();
208
+ if (!user)
209
+ return reject();
210
+ user.getSession((err) => {
211
+ if (err)
212
+ return reject(err);
213
+ user.associateSoftwareToken({
214
+ associateSecretCode: (secretCode) => resolve(`otpauth://totp/${encodeURI(this.mfaProjectName)}?secret=${secretCode}`),
215
+ onFailure: (err) => reject(err)
216
+ });
217
+ });
218
+ });
219
+ }
220
+ /**
221
+ * Check whether the user has MFA enabled.
222
+ */
223
+ checkIfUserHasMFAEnabled(bypassCache = false) {
224
+ return new Promise((resolve, reject) => {
225
+ const user = this.userPool.getCurrentUser();
226
+ if (!user)
227
+ return reject();
228
+ user.getSession((err) => {
229
+ if (err)
230
+ return reject(err);
231
+ user.getUserData((err, data) => {
232
+ if (err)
233
+ return reject(err);
234
+ const isMFAEnabled = !!(data.UserMFASettingList && data.UserMFASettingList.includes('SOFTWARE_TOKEN_MFA'));
235
+ resolve(isMFAEnabled);
236
+ }, { bypassCache });
237
+ });
238
+ });
239
+ }
240
+ /**
241
+ * Configure a MFA device for the user.
242
+ */
243
+ setMFADevice(otp, mfaDeviceName, enabled = true, preferred = true) {
244
+ return new Promise((resolve, reject) => {
245
+ const user = this.userPool.getCurrentUser();
246
+ if (!user)
247
+ return reject();
248
+ user.getSession((err) => {
249
+ if (err)
250
+ return reject(err);
251
+ user.verifySoftwareToken(otp, mfaDeviceName, {
252
+ onSuccess: () => user.setUserMfaPreference(null, { Enabled: enabled, PreferredMfa: preferred }, (err) => err ? reject(err) : resolve()),
253
+ onFailure: (err) => reject(err)
254
+ });
255
+ });
256
+ });
257
+ }
258
+ /**
259
+ * Enable a new MFA device for the user by inserting an OTP code generated by it.
260
+ */
261
+ enableMFA(otp, mfaDeviceName = 'default') {
262
+ return this.setMFADevice(otp, mfaDeviceName, true, true);
263
+ }
264
+ /**
265
+ * Disable MFA for a user by inserting an OTP code generated by it.
266
+ */
267
+ disableMFA(otp, mfaDeviceName = 'default') {
268
+ return this.setMFADevice(otp, mfaDeviceName, false, false);
269
+ }
270
+ /**
271
+ * Check if a user is currently authenticated.
272
+ * @param offlineAllowed if set and if offline, skip authentication and retrieve data locally
273
+ * @param getFreshIdTokenOnExp cb function to execute when the idToken is refreshed
274
+ */
275
+ isAuthenticated(offlineAllowed, getFreshIdTokenOnExp) {
276
+ return new Promise((resolve, reject) => {
277
+ if (offlineAllowed && !navigator.onLine) {
278
+ this.storage.get('AuthUserDetails').then(userDetails => resolve({ idToken: null, userDetails }));
279
+ // re-execute the method when back online, so that you can retrieve a token to make requests
280
+ window.addEventListener('online', () => this.isAuthenticated(true, getFreshIdTokenOnExp)
281
+ // set the new token as if it was refreshed
282
+ .then(result => getFreshIdTokenOnExp(result.idToken)));
283
+ }
284
+ else {
285
+ const user = this.userPool.getCurrentUser();
286
+ if (!user)
287
+ return reject();
288
+ user.getSession((err, session) => {
289
+ if (err)
290
+ return reject(err);
291
+ user.getUserData((err, data) => {
292
+ if (err)
293
+ return reject(err);
294
+ const isMFAEnabled = !!(data.UserMFASettingList && data.UserMFASettingList.includes('SOFTWARE_TOKEN_MFA'));
295
+ if (!isMFAEnabled && env.idea.auth.forceLoginWithMFA)
296
+ return reject(new Error(LoginOutcomeActions.MFA_SETUP));
297
+ user.getUserAttributes((e, attributes) => {
298
+ if (e)
299
+ return reject(e);
300
+ // remap user attributes
301
+ const userDetails = {};
302
+ attributes.forEach((a) => (userDetails[a.getName()] = a.getValue()));
303
+ // add the user's groups to the attributes
304
+ const sessionInfo = session.getAccessToken().decodePayload();
305
+ const groups = sessionInfo['cognito:groups'] || [];
306
+ userDetails['groups'] = groups;
307
+ // run some checks considering the user's groups and devices (based on the project's configuration)
308
+ this.runPostAuthChecks(userDetails, err => {
309
+ // in case some check failed, reject the authorisation flow
310
+ if (err)
311
+ return reject(err);
312
+ // (async) save the refresh token so it can be accessed by other procedures
313
+ this.storage.set('AuthRefreshToken', session.getRefreshToken().getToken());
314
+ // set a timer to manage the autorefresh of the idToken (through the refreshToken)
315
+ setTimeout(() => this.refreshSession(user, session.getRefreshToken().getToken(), getFreshIdTokenOnExp), 15 * 60 * 1000); // every 15 minutes
316
+ // (async) if offlineAllowed, save data locally, to use it next time we'll be offline
317
+ if (offlineAllowed)
318
+ this.storage.set('AuthUserDetails', userDetails);
319
+ // return the idToken (to use with API)
320
+ resolve({ idToken: session.getIdToken().getJwtToken(), userDetails });
321
+ });
322
+ });
323
+ }, { bypassCache: true });
324
+ });
325
+ }
326
+ });
327
+ }
328
+ /**
329
+ * Helper to refresh the session every N minutes.
330
+ */
331
+ refreshSession(user, refreshToken, callback) {
332
+ user.refreshSession(new CognitoRefreshToken({ RefreshToken: refreshToken }), (err, session) => {
333
+ if (err) {
334
+ // try again in 1 minute
335
+ setTimeout(() => this.refreshSession(user, refreshToken, callback), 1 * 60 * 1000);
336
+ }
337
+ else {
338
+ // (async) save the refresh token so it can be accessed by other procedures
339
+ this.storage.set('AuthRefreshToken', session.getRefreshToken().getToken());
340
+ // repeat every 15 minutes
341
+ setTimeout(() => this.refreshSession(user, session.getRefreshToken().getToken(), callback), 15 * 60 * 1000);
342
+ // run the callback action, if set
343
+ if (callback)
344
+ callback(session.getIdToken().getJwtToken());
345
+ }
346
+ });
347
+ }
348
+ /**
349
+ * Run some post-auth checks, based on the users groups and on the app's configuration:
350
+ * - users in the Cognito's "admins" grup skip all the following rules.
351
+ * - users in the Cognito's "robots" group can't sign-into front-ends (they serve only back-end purposes).
352
+ * - if `env.idea.auth.singleSimultaneousSession` is on, make sure there is only one active session per user.
353
+ */
354
+ runPostAuthChecks(userDetails, callback) {
355
+ const groups = userDetails['groups'];
356
+ // skip checks if the user is in the "admins" group
357
+ const isAdmin = groups.some(x => x === 'admins');
358
+ if (isAdmin)
359
+ return callback();
360
+ // users in the "robots" group can't sign-into front-ends (they serve only back-end purposes)
361
+ const isRobot = groups.some(x => x === 'robots');
362
+ if (isRobot)
363
+ return callback(new Error('ROBOT_USER'));
364
+ // in case the project limits each account to only one simultaneous session, run a check
365
+ if (env.idea.auth.singleSimultaneousSession)
366
+ return this.checkForSimultaneousSessions(userDetails, callback);
367
+ // otherwise, we're done
368
+ callback();
369
+ }
370
+ /**
371
+ * Check whether the user signed-into multiple devices.
372
+ */
373
+ async checkForSimultaneousSessions(userDetails, callback) {
374
+ // get or create a key for the current device (~random)
375
+ let currentDeviceKey = await this.storage.get('AuthDeviceKey');
376
+ if (!currentDeviceKey) {
377
+ const randomKey = Math.random().toString(36).substring(10);
378
+ currentDeviceKey = randomKey.concat(String(Date.now()));
379
+ await this.storage.set('AuthDeviceKey', currentDeviceKey);
380
+ }
381
+ // check whether the last device to sign-into this project (if any) is the current one
382
+ const lastDeviceToSignIntoThisProject = userDetails[DEVICE_KEY_ATTRIBUTE];
383
+ // if it's the first user's device to sign-in, save the reference in Cognito and resolve
384
+ if (!lastDeviceToSignIntoThisProject) {
385
+ this.setCurrentDeviceForProject(currentDeviceKey)
386
+ .then(() => callback())
387
+ .catch(() => callback(new Error('CANT_SET_DEVICE')));
388
+ // if the device didn't change, resolve
389
+ }
390
+ else if (lastDeviceToSignIntoThisProject === currentDeviceKey)
391
+ callback();
392
+ // othwerwise, report there is more than one simultaneous session
393
+ else
394
+ callback(new Error('SIMULTANEOUS_SESSION'));
395
+ }
396
+ /**
397
+ * Set (or reset) the current user's device (by key) in the current project (stored in Cognito).
398
+ */
399
+ setCurrentDeviceForProject(deviceKey) {
400
+ const attributes = {};
401
+ // note: an empty string will remove the attribute from Cognito
402
+ attributes[DEVICE_KEY_ATTRIBUTE] = deviceKey || '';
403
+ return this.updateUserAttributes(attributes);
404
+ }
405
+ /**
406
+ * Update the currently logged in user's attributes.
407
+ */
408
+ updateUserAttributes(attributes) {
409
+ return new Promise((resolve, reject) => {
410
+ // prepare the attributes we want to change
411
+ const attrs = new Array();
412
+ for (const prop in attributes)
413
+ if (attributes[prop] !== undefined)
414
+ attrs.push(this.prepareUserAttribute(prop, attributes[prop]));
415
+ const user = this.userPool.getCurrentUser();
416
+ if (!user)
417
+ return reject();
418
+ // we need to get the session before to make changes
419
+ user.getSession((err) => {
420
+ if (err)
421
+ reject(err);
422
+ else
423
+ user.updateAttributes(attrs, (e) => (e ? reject(e) : resolve()));
424
+ });
425
+ });
426
+ }
427
+ /**
428
+ * Validate the password against the policy set in the environments configuration.
429
+ * In case there are errors, they are returned as an array of strings.
430
+ */
431
+ validatePasswordAgainstPolicy(password) {
432
+ const errors = [];
433
+ if (password?.trim().length < this.passwordPolicy.minLength)
434
+ errors.push('MIN_LENGTH');
435
+ if (this.passwordPolicy.requireDigits && !/\d/.test(password))
436
+ errors.push('REQUIRE_DIGITS');
437
+ if (this.passwordPolicy.requireLowercase && !/[a-z]/.test(password))
438
+ errors.push('REQUIRE_LOWERCASE');
439
+ if (this.passwordPolicy.requireSymbols && !/[\^\$\*\.\_\~\`\+\=@\!\?\>\<\:\;\\\,\#\%\&]/.test(password))
440
+ errors.push('REQUIRE_SYMBOLS');
441
+ if (this.passwordPolicy.requireUppercase && !/[A-Z]/.test(password))
442
+ errors.push('REQUIRE_UPPERCASE');
443
+ return errors;
444
+ }
445
+ /**
446
+ * Get a complete password policy pattern, based on the environments configuration, to use on password input fields.
447
+ * Note: some of the symbols couldn't be included because unsupported by the input[pattern] attribute.
448
+ */
449
+ getPasswordPolicyPatternForInput() {
450
+ let pattern = '';
451
+ if (this.passwordPolicy.requireDigits)
452
+ pattern += `(?=.*[0-9])`;
453
+ if (this.passwordPolicy.requireLowercase)
454
+ pattern += `(?=.*[a-z])`;
455
+ if (this.passwordPolicy.requireSymbols)
456
+ pattern += `(?=.*[\^\$\*\.\_\~\`\+\=@\!\?\>\<\:\;\\\,\#\%\&])`;
457
+ if (this.passwordPolicy.requireUppercase)
458
+ pattern += `(?=.*[A-Z])`;
459
+ pattern += `.{${this.passwordPolicy.minLength},}`;
460
+ return pattern;
461
+ }
462
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: IDEAAuthService, deps: [{ token: i1.IDEAStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
463
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: IDEAAuthService, providedIn: 'root' }); }
464
+ }
465
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.8", ngImport: i0, type: IDEAAuthService, decorators: [{
466
+ type: Injectable,
467
+ args: [{ providedIn: 'root' }]
468
+ }], ctorParameters: function () { return [{ type: i1.IDEAStorageService }]; } });
469
+ /**
470
+ * The possible actions following a successful login.
471
+ */
472
+ export var LoginOutcomeActions;
473
+ (function (LoginOutcomeActions) {
474
+ LoginOutcomeActions["NONE"] = "none";
475
+ LoginOutcomeActions["NEW_PASSWORD"] = "newPassword";
476
+ LoginOutcomeActions["MFA_CHALLENGE"] = "mfaChallenge";
477
+ LoginOutcomeActions["MFA_SETUP"] = "mfaSetup";
478
+ })(LoginOutcomeActions || (LoginOutcomeActions = {}));
479
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vbW9kdWxlcy9hdXRoL3NyYy9hdXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLFdBQVcsRUFDWCxvQkFBb0IsRUFDcEIsZUFBZSxFQUNmLG1CQUFtQixFQUlwQixNQUFNLDRCQUE0QixDQUFDO0FBR3BDLE9BQU8sRUFBRSxXQUFXLElBQUksR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7QUFFMUM7O0dBRUc7QUFDSCxNQUFNLG9CQUFvQixHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUVoRTs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLGVBQWU7SUFZMUIsWUFBb0IsT0FBMkI7UUFBM0IsWUFBTyxHQUFQLE9BQU8sQ0FBb0I7UUFKdkMsbUJBQWMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7UUFFeEQsbUJBQWMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7UUFHcEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLGVBQWUsQ0FBQztZQUNsQyxVQUFVLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVTtZQUN0QyxRQUFRLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO1NBQzNDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQixDQUFDLFFBQWdCLEVBQUUsR0FBVztRQUN0RCxPQUFPLElBQUkscUJBQXFCLENBQUMsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFF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LDZDQUFzQixDQUFBO0FBQ3hCLENBQUMsRUFMVyxtQkFBbUIsS0FBbkIsbUJBQW1CLFFBSzlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQXV0aGVudGljYXRpb25EZXRhaWxzLFxuICBDb2duaXRvVXNlcixcbiAgQ29nbml0b1VzZXJBdHRyaWJ1dGUsXG4gIENvZ25pdG9Vc2VyUG9vbCxcbiAgQ29nbml0b1JlZnJlc2hUb2tlbixcbiAgQ29nbml0b1VzZXJTZXNzaW9uLFxuICBJU2lnblVwUmVzdWx0LFxuICBDaGFsbGVuZ2VOYW1lXG59IGZyb20gJ2FtYXpvbi1jb2duaXRvLWlkZW50aXR5LWpzJztcbmltcG9ydCB7IElERUFTdG9yYWdlU2VydmljZSB9IGZyb20gJ0BpZGVhLWlvbmljL2NvbW1vbic7XG5cbmltcG9ydCB7IGVudmlyb25tZW50IGFzIGVudiB9IGZyb20gJ0BlbnYnO1xuXG4vKipcbiAqIFRoZSBuYW1lIG9mIHRoZSBDb2duaXRvJ3MgdXNlciBhdHRyaWJ1dGUgd2hpY2ggY29udGFpbnMgdGhlIGtleSBvZiB0aGUgbGFzdCBkZXZpY2UgdG8gbG9naW4gaW4gdGhpcyBwcm9qZWN0LlxuICovXG5jb25zdCBERVZJQ0VfS0VZX0FUVFJJQlVURSA9ICdjdXN0b206Jy5jb25jYXQoZW52LmlkZWEucHJvamVjdCk7XG5cbi8qKlxuICogQ29nbml0byB3cmFwcGVyIHRvIG1hbmFnZSB0aGUgYXV0aGVudGljYXRpb24gZmxvdy5cbiAqXG4gKiBOb3RlOiBpbiBJREVBJ3MgQ29nbml0byB1c2VycyBwb29scywgdGhlIGVtYWlsIGlzIGFuIGFsaWFzIG9mIHRoZSB1c2VybmFtZS5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBJREVBQXV0aFNlcnZpY2Uge1xuICBwcml2YXRlIHVzZXJQb29sOiBDb2duaXRvVXNlclBvb2w7XG5cbiAgY2hhbGxlbmdlVXNlcm5hbWU6IHN0cmluZztcbiAgcHJpdmF0ZSBjaGFsbGVuZ2VQYXNzd29yZDogc3RyaW5nO1xuXG4gIHByaXZhdGUgbmV3QWNjb3VudEp1c3RSZWdpc3RlcmVkOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBtZmFQcm9qZWN0TmFtZSA9IGVudi5pZGVhLmFwcC50aXRsZSA/PyBlbnYuaWRlYS5wcm9qZWN0O1xuXG4gIHByaXZhdGUgcGFzc3dvcmRQb2xpY3kgPSBlbnYuaWRlYS5hdXRoLnBhc3N3b3JkUG9saWN5O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RvcmFnZTogSURFQVN0b3JhZ2VTZXJ2aWNlKSB7XG4gICAgdGhpcy51c2VyUG9vbCA9IG5ldyBDb2duaXRvVXNlclBvb2woe1xuICAgICAgVXNlclBvb2xJZDogZW52LmF3cy5jb2duaXRvLnVzZXJQb29sSWQsXG4gICAgICBDbGllbnRJZDogZW52LmF3cy5jb2duaXRvLnVzZXJQb29sQ2xpZW50SWRcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwYXJlIHRoZSBuZWNlc3Nhcnkgc3RydWN0dXJlIHRvIGdldCBhdXRob3JpemVkIGluIENvZ25pdG8uXG4gICAqL1xuICBwcml2YXRlIHByZXBhcmVBdXRoRGV0YWlscyh1c2VybmFtZTogc3RyaW5nLCBwd2Q6IHN0cmluZyk6IEF1dGhlbnRpY2F0aW9uRGV0YWlscyB7XG4gICAgcmV0dXJuIG5ldyBBdXRoZW50aWNhdGlvbkRldGFpbHMoeyBVc2VybmFtZTogdXNlcm5hbWUsIFBhc3N3b3JkOiBwd2QgfSk7XG4gIH1cbiAgLyoqXG4gICAqIFByZXBhcmUgdGhlIG5lY2Vzc2FyeSBzdHJ1Y3R1cmUgdG8gaWRlbnRpZnkgYSBDb2duaXRvIHVzZXIuXG4gICAqL1xuICBwcmVwYXJlQ29nbml0b1VzZXIodXNlcm5hbWU6IHN0cmluZyk6IENvZ25pdG9Vc2VyIHtcbiAgICByZXR1cm4gbmV3IENvZ25pdG9Vc2VyKHsgVXNlcm5hbWU6IHVzZXJuYW1lLCBQb29sOiB0aGlzLnVzZXJQb29sIH0pO1xuICB9XG4gIC8qKlxuICAgKiBQcmVwYXJlIGEgdXNlciBhdHRyaWJ1dGUgKHRoZXkgYXJlIGFsbCBzdHJpbmdzKSBpbiBDb2duaXRvJ3MgZm9ybWF0LlxuICAgKi9cbiAgcHJpdmF0ZSBwcmVwYXJlVXNlckF0dHJpYnV0ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiBDb2duaXRvVXNlckF0dHJpYnV0ZSB7XG4gICAgcmV0dXJuIG5ldyBDb2duaXRvVXNlckF0dHJpYnV0ZSh7IE5hbWU6IG5hbWUsIFZhbHVlOiB2YWx1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgbG9naW4gdGhyb3VnaCB1c2VybmFtZSBhbmQgcGFzc3dvcmQuXG4gICAqL1xuICBsb2dpbih1c2VybmFtZTogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxMb2dpbk91dGNvbWVBY3Rpb25zPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IHVzZXIgPSB0aGlzLnByZXBhcmVDb2duaXRvVXNlcih1c2VybmFtZSk7XG4gICAgICB1c2VyLmF1dGhlbnRpY2F0ZVVzZXIodGhpcy5wcmVwYXJlQXV0aERldGFpbHModXNlcm5hbWUsIHBhc3N3b3JkKSwge1xuICAgICAgICBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+XG4gICAgICAgICAgcmVzb2x2ZShlbnYuaWRlYS5hdXRoLmZvcmNlTG9naW5XaXRoTUZBID8gTG9naW5PdXRjb21lQWN0aW9ucy5NRkFfU0VUVVAgOiBMb2dpbk91dGNvbWVBY3Rpb25zLk5PTkUpLFxuICAgICAgICBvbkZhaWx1cmU6IChlcnI6IEVycm9yKTogdm9pZCA9PiByZWplY3QoZXJyKSxcbiAgICAgICAgbmV3UGFzc3dvcmRSZXF1aXJlZDogKCk6IHZvaWQgPT4ge1xuICAgICAgICAgIHRoaXMuY2hhbGxlbmdlVXNlcm5hbWUgPSB1c2VybmFtZTtcbiAgICAgICAgICB0aGlzLmNoYWxsZW5nZVBhc3N3b3JkID0gcGFzc3dvcmQ7XG4gICAgICAgICAgcmVzb2x2ZShMb2dpbk91dGNvbWVBY3Rpb25zLk5FV19QQVNTV09SRCk7XG4gICAgICAgIH0sXG4gICAgICAgIHRvdHBSZXF1aXJlZDogKCk6IHZvaWQgPT4ge1xuICAgICAgICAgIHRoaXMuY2hhbGxlbmdlVXNlcm5hbWUgPSB1c2VybmFtZTtcbiAgICAgICAgICB0aGlzLmNoYWxsZW5nZVBhc3N3b3JkID0gcGFzc3dvcmQ7XG4gICAgICAgICAgcmVzb2x2ZShMb2dpbk91dGNvbWVBY3Rpb25zLk1GQV9DSEFMTEVOR0UpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogQ29tcGxldGUgdGhlIG5ldyBwYXNzd29yZCBmbG93IGluIHRoZSBhdXRoZW50aWNhdGlvbi5cbiAgICovXG4gIGNvbmZpcm1OZXdQYXNzd29yZChuZXdQYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IHVzZXIgPSB0aGlzLnByZXBhcmVDb2duaXRvVXNlcih0aGlzLmNoYWxsZW5nZVVzZXJuYW1lKTtcbiAgICAgIHVzZXIuYXV0aGVudGljYXRlVXNlcih0aGlzLnByZXBhcmVBdXRoRGV0YWlscyh0aGlzLmNoYWxsZW5nZVVzZXJuYW1lLCB0aGlzLmNoYWxsZW5nZVBhc3N3b3JkKSwge1xuICAgICAgICBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+IHJlc29sdmUoKSxcbiAgICAgICAgb25GYWlsdXJlOiAoZXJyOiBFcnJvcik6IHZvaWQgPT4gcmVqZWN0KGVyciksXG4gICAgICAgIG5ld1Bhc3N3b3JkUmVxdWlyZWQ6ICgpOiB2b2lkID0+XG4gICAgICAgICAgdXNlci5jb21wbGV0ZU5ld1Bhc3N3b3JkQ2hhbGxlbmdlKFxuICAgICAgICAgICAgbmV3UGFzc3dvcmQsXG4gICAgICAgICAgICB7fSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgb25TdWNjZXNzOiAoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGFsbGVuZ2VVc2VybmFtZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGFsbGVuZ2VQYXNzd29yZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBvbkZhaWx1cmU6IChlcnI6IEVycm9yKTogdm9pZCA9PiByZWplY3QoZXJyKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIClcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiAgQ29tcGxldGUgdGhlIE1GQSBjaGFsbGVuZ2UgZmxvdyBpbiB0aGUgYXV0aGVudGljYXRpb24uXG4gICAqL1xuICBjb21wbGV0ZU1GQUNoYWxsZW5nZShvdHBDb2RlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMucHJlcGFyZUNvZ25pdG9Vc2VyKHRoaXMuY2hhbGxlbmdlVXNlcm5hbWUpO1xuICAgICAgdXNlci5hdXRoZW50aWNhdGVVc2VyKHRoaXMucHJlcGFyZUF1dGhEZXRhaWxzKHRoaXMuY2hhbGxlbmdlVXNlcm5hbWUsIHRoaXMuY2hhbGxlbmdlUGFzc3dvcmQpLCB7XG4gICAgICAgIG9uU3VjY2VzczogKCk6IHZvaWQgPT4gcmVzb2x2ZSgpLFxuICAgICAgICBvbkZhaWx1cmU6IChlcnI6IEVycm9yKTogdm9pZCA9PiByZWplY3QoZXJyKSxcbiAgICAgICAgdG90cFJlcXVpcmVkOiAoY2hhbGxlbmdlTmFtZTogQ2hhbGxlbmdlTmFtZSk6IHZvaWQgPT5cbiAgICAgICAgICB1c2VyLnNlbmRNRkFDb2RlKFxuICAgICAgICAgICAgb3RwQ29kZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgb25TdWNjZXNzOiAoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGFsbGVuZ2VVc2VybmFtZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGFsbGVuZ2VQYXNzd29yZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBvbkZhaWx1cmU6IGVyciA9PiByZWplY3QoZXJyKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNoYWxsZW5nZU5hbWVcbiAgICAgICAgICApXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBuZXcgdXNlciBhIHNldCBpdHMgZGVmYXVsdCBhdHRyaWJ1dGVzLlxuICAgKi9cbiAgcmVnaXN0ZXIodXNlcm5hbWU6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZywgYXR0cmlidXRlcz86IGFueSk6IFByb21pc2U8Q29nbml0b1VzZXI+IHtcbiAgICBhdHRyaWJ1dGVzID0gYXR0cmlidXRlcyB8fCB7fTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgLy8gYWRkIGF0dHJpYnV0ZXMgbGlrZSB0aGUgZW1haWwgYWRkcmVzcyBhbmQgdGhlIGZ1bGxuYW1lXG4gICAgICBjb25zdCBhdHRycyA9IFtdO1xuICAgICAgZm9yIChjb25zdCBwcm9wIGluIGF0dHJpYnV0ZXMpXG4gICAgICAgIGlmIChhdHRyaWJ1dGVzW3Byb3BdKSBhdHRycy5wdXNoKHRoaXMucHJlcGFyZVVzZXJBdHRyaWJ1dGUocHJvcCwgYXR0cmlidXRlc1twcm9wXSkpO1xuICAgICAgLy8gYWRkIHRoZSBlbWFpbCwgd2hpY2ggaXMgZXF1YWwgdG8gdGhlIHVzZXJuYW1lIGZvciBtb3N0IG9mIG91ciBQb29sc1xuICAgICAgaWYgKCFhdHRyaWJ1dGVzLmVtYWlsKSBhdHRycy5wdXNoKHRoaXMucHJlcGFyZVVzZXJBdHRyaWJ1dGUoJ2VtYWlsJywgdXNlcm5hbWUpKTtcbiAgICAgIC8vIHJlZ2lzdGVyIHRoZSBuZXcgdXNlciB0byB0aGUgcG9vbFxuICAgICAgdGhpcy51c2VyUG9vbC5zaWduVXAodXNlcm5hbWUsIHBhc3N3b3JkLCBhdHRycywgbnVsbCwgKGVycjogRXJyb3IsIHJlczogSVNpZ25VcFJlc3VsdCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIHRoaXMubmV3QWNjb3VudEp1c3RSZWdpc3RlcmVkID0gdXNlcm5hbWU7XG4gICAgICAgIHJlc29sdmUocmVzLnVzZXIpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIEluIGNhc2UgIG5ldyBhY2NvdW50IGhhcyBqdXN0IGJlZW4gcmVnaXN0ZXJlZCwgcmV0dXJuIHRoZSB1c2VybmFtZS5cbiAgICovXG4gIGdldE5ld0FjY291bnRKdXN0UmVnaXN0ZXJlZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm5ld0FjY291bnRKdXN0UmVnaXN0ZXJlZDtcbiAgfVxuICAvKipcbiAgICogQ29uZmlybSBhIG5ldyByZWdpc3RyYXRpb24gdGhyb3VnaCB0aGUgY29uZmlybWF0aW9uIGNvZGUgc2VudCBieSBDb2duaXRvLlxuICAgKi9cbiAgY29uZmlybVJlZ2lzdHJhdGlvbih1c2VybmFtZTogc3RyaW5nLCBjb2RlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgdGhpcy5wcmVwYXJlQ29nbml0b1VzZXIodXNlcm5hbWUpLmNvbmZpcm1SZWdpc3RyYXRpb24oY29kZSwgdHJ1ZSwgKGVycjogRXJyb3IpOiB2b2lkID0+XG4gICAgICAgIGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZSgpXG4gICAgICApO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBTZW5kIGFnYWluIGEgY29uZmlybWF0aW9uIGNvZGUgZm9yIGEgbmV3IHJlZ2lzdHJhdGlvbi5cbiAgICovXG4gIHJlc2VuZENvbmZpcm1hdGlvbkNvZGUodXNlcm5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICB0aGlzLnByZXBhcmVDb2duaXRvVXNlcih1c2VybmFtZSkucmVzZW5kQ29uZmlybWF0aW9uQ29kZSgoZXJyOiBFcnJvcik6IHZvaWQgPT4gKGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZSgpKSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIExvZ291dCB0aGUgY3VycmVudGx5IHNpZ25lZC1pbiB1c2VyLlxuICAgKi9cbiAgbG9nb3V0KG9wdGlvbnM/OiB7IGdsb2JhbDogYm9vbGVhbiB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oeyBnbG9iYWw6IGZhbHNlIH0sIG9wdGlvbnMpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICAvLyByZW1vdmUgdGhlIHJlZnJlc2ggdG9rZW4gcHJldmlvc2x5IHNhdmVkXG4gICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCdBdXRoUmVmcmVzaFRva2VuJykudGhlbihcbiAgICAgICAgKCk6IFByb21pc2U8dm9pZD4gPT5cbiAgICAgICAgICAvLyByZW1vdmUgdGhlIG9wdGlvbmFsIGF1dGggZGV0YWlsc1xuICAgICAgICAgIHRoaXMuc3RvcmFnZS5yZW1vdmUoJ0F1dGhVc2VyRGV0YWlscycpLnRoZW4oKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgLy8gZ2V0IHRoZSB1c2VyIGFuZCB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgY29uc3QgdXNlciA9IHRoaXMudXNlclBvb2wuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICAgICAgICAgIHVzZXIuZ2V0U2Vzc2lvbihhc3luYyAoZXJyOiBFcnJvcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAvLyBpZiB0aGUgc2Vzc2lvbiBpcyBhY3RpdmUsIHJ1biB0aGUgb25saW5lIHNpZ24tb3V0OyBvdGhlcndpc2UsIG9ubHkgdGhlIGxvY2FsIGRhdGEgaGFzIGJlZW4gZGVsZXRlZFxuICAgICAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAvLyBpZiBhIHJlZmVyZW5jZSB0byB0aGUgZGV2aWNlIHdhcyBzYXZlZCwgZm9yZ2V0IGl0XG4gICAgICAgICAgICAgIGlmIChlbnYuaWRlYS5hdXRoLnNpbmdsZVNpbXVsdGFuZW91c1Nlc3Npb24pIGF3YWl0IHRoaXMuc2V0Q3VycmVudERldmljZUZvclByb2plY3QobnVsbCk7XG4gICAgICAgICAgICAgIC8vIHNpZ24tb3V0IGZyb20gdGhlIHBvb2wgKHRlcm1pbmF0ZSB0aGUgY3VycmVudCBzZXNzaW9uIG9yIGFsbCB0aGUgc2Vzc2lvbnMpXG4gICAgICAgICAgICAgIGlmIChvcHRpb25zLmdsb2JhbClcbiAgICAgICAgICAgICAgICB1c2VyLmdsb2JhbFNpZ25PdXQoeyBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+IHJlc29sdmUoKSwgb25GYWlsdXJlOiBlcnIgPT4gcmVqZWN0KGVycikgfSk7XG4gICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHVzZXIuc2lnbk91dCgpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIFNlbmQgYSBwYXNzd29yZCByZXNldCByZXF1ZXN0LlxuICAgKi9cbiAgZm9yZ290UGFzc3dvcmQodXNlcm5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICB0aGlzLnByZXBhcmVDb2duaXRvVXNlcih1c2VybmFtZSkuZm9yZ290UGFzc3dvcmQoe1xuICAgICAgICBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+IHJlc29sdmUoKSxcbiAgICAgICAgb25GYWlsdXJlOiAoZXJyOiBFcnJvcik6IHZvaWQgPT4gcmVqZWN0KGVycilcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBDb25maXJtIGEgbmV3IHBhc3N3b3JkIGFmdGVyIGEgcGFzc3dvcmQgcmVzZXQgcmVxdWVzdC5cbiAgICovXG4gIGNvbmZpcm1QYXNzd29yZCh1c2VybmFtZTogc3RyaW5nLCBjb2RlOiBzdHJpbmcsIG5ld1B3ZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIHRoaXMucHJlcGFyZUNvZ25pdG9Vc2VyKHVzZXJuYW1lKS5jb25maXJtUGFzc3dvcmQoY29kZSwgbmV3UHdkLCB7XG4gICAgICAgIG9uU3VjY2VzczogKCk6IHZvaWQgPT4gcmVzb2x2ZSgpLFxuICAgICAgICBvbkZhaWx1cmU6IChlcnI6IEVycm9yKTogdm9pZCA9PiByZWplY3QoZXJyKVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIEdldHMgdGhlIFVSTCBmb3IgZW5hYmxpbmcgTUZBLiBUaGlzIFVSTCBjYW4gYmUgdXNlZCB0byBnZW5lcmF0ZSBhIFFSIENvZGUgdG8gcmVhZCB3aXRoIGFuIGF1dGhlbnRpY2F0b3IgYXBwLlxuICAgKi9cbiAgZ2V0VVJMRm9yRW5hYmxpbmdNRkEoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMudXNlclBvb2wuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICAgIGlmICghdXNlcikgcmV0dXJuIHJlamVjdCgpO1xuICAgICAgdXNlci5nZXRTZXNzaW9uKChlcnI6IEVycm9yKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgdXNlci5hc3NvY2lhdGVTb2Z0d2FyZVRva2VuKHtcbiAgICAgICAgICBhc3NvY2lhdGVTZWNyZXRDb2RlOiAoc2VjcmV0Q29kZTogc3RyaW5nKTogdm9pZCA9PlxuICAgICAgICAgICAgcmVzb2x2ZShgb3RwYXV0aDovL3RvdHAvJHtlbmNvZGVVUkkodGhpcy5tZmFQcm9qZWN0TmFtZSl9P3NlY3JldD0ke3NlY3JldENvZGV9YCksXG4gICAgICAgICAgb25GYWlsdXJlOiAoZXJyOiBhbnkpOiB2b2lkID0+IHJlamVjdChlcnIpXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgdGhlIHVzZXIgaGFzIE1GQSBlbmFibGVkLlxuICAgKi9cbiAgY2hlY2tJZlVzZXJIYXNNRkFFbmFibGVkKGJ5cGFzc0NhY2hlID0gZmFsc2UpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMudXNlclBvb2wuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICAgIGlmICghdXNlcikgcmV0dXJuIHJlamVjdCgpO1xuICAgICAgdXNlci5nZXRTZXNzaW9uKChlcnI6IEVycm9yKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgdXNlci5nZXRVc2VyRGF0YShcbiAgICAgICAgICAoZXJyLCBkYXRhKTogdm9pZCA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgICBjb25zdCBpc01GQUVuYWJsZWQgPSAhIShkYXRhLlVzZXJNRkFTZXR0aW5nTGlzdCAmJiBkYXRhLlVzZXJNRkFTZXR0aW5nTGlzdC5pbmNsdWRlcygnU09GVFdBUkVfVE9LRU5fTUZBJykpO1xuICAgICAgICAgICAgcmVzb2x2ZShpc01GQUVuYWJsZWQpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBieXBhc3NDYWNoZSB9XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogQ29uZmlndXJlIGEgTUZBIGRldmljZSBmb3IgdGhlIHVzZXIuXG4gICAqL1xuICBwcml2YXRlIHNldE1GQURldmljZShvdHA6IHN0cmluZywgbWZhRGV2aWNlTmFtZTogc3RyaW5nLCBlbmFibGVkID0gdHJ1ZSwgcHJlZmVycmVkID0gdHJ1ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyUG9vbC5nZXRDdXJyZW50VXNlcigpO1xuICAgICAgaWYgKCF1c2VyKSByZXR1cm4gcmVqZWN0KCk7XG4gICAgICB1c2VyLmdldFNlc3Npb24oKGVycjogRXJyb3IpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB1c2VyLnZlcmlmeVNvZnR3YXJlVG9rZW4ob3RwLCBtZmFEZXZpY2VOYW1lLCB7XG4gICAgICAgICAgb25TdWNjZXNzOiAoKTogdm9pZCA9PlxuICAgICAgICAgICAgdXNlci5zZXRVc2VyTWZhUHJlZmVyZW5jZShudWxsLCB7IEVuYWJsZWQ6IGVuYWJsZWQsIFByZWZlcnJlZE1mYTogcHJlZmVycmVkIH0sIChlcnI6IEVycm9yKTogdm9pZCA9PlxuICAgICAgICAgICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUoKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICBvbkZhaWx1cmU6IChlcnIpOiB2b2lkID0+IHJlamVjdChlcnIpXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIEVuYWJsZSBhIG5ldyBNRkEgZGV2aWNlIGZvciB0aGUgdXNlciBieSBpbnNlcnRpbmcgYW4gT1RQIGNvZGUgZ2VuZXJhdGVkIGJ5IGl0LlxuICAgKi9cbiAgZW5hYmxlTUZBKG90cDogc3RyaW5nLCBtZmFEZXZpY2VOYW1lID0gJ2RlZmF1bHQnKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc2V0TUZBRGV2aWNlKG90cCwgbWZhRGV2aWNlTmFtZSwgdHJ1ZSwgdHJ1ZSk7XG4gIH1cbiAgLyoqXG4gICAqIERpc2FibGUgTUZBIGZvciBhIHVzZXIgYnkgaW5zZXJ0aW5nIGFuIE9UUCBjb2RlIGdlbmVyYXRlZCBieSBpdC5cbiAgICovXG4gIGRpc2FibGVNRkEob3RwOiBzdHJpbmcsIG1mYURldmljZU5hbWUgPSAnZGVmYXVsdCcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRNRkFEZXZpY2Uob3RwLCBtZmFEZXZpY2VOYW1lLCBmYWxzZSwgZmFsc2UpO1xuICB9XG4gIC8qKlxuICAgKiBDaGVjayBpZiBhIHVzZXIgaXMgY3VycmVudGx5IGF1dGhlbnRpY2F0ZWQuXG4gICAqIEBwYXJhbSBvZmZsaW5lQWxsb3dlZCBpZiBzZXQgYW5kIGlmIG9mZmxpbmUsIHNraXAgYXV0aGVudGljYXRpb24gYW5kIHJldHJpZXZlIGRhdGEgbG9jYWxseVxuICAgKiBAcGFyYW0gZ2V0RnJlc2hJZFRva2VuT25FeHAgY2IgZnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBpZFRva2VuIGlzIHJlZnJlc2hlZFxuICAgKi9cbiAgaXNBdXRoZW50aWNhdGVkKG9mZmxpbmVBbGxvd2VkOiBib29sZWFuLCBnZXRGcmVzaElkVG9rZW5PbkV4cD86IChmcmVzaElkVG9rZW46IHN0cmluZykgPT4gdm9pZCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGlmIChvZmZsaW5lQWxsb3dlZCAmJiAhbmF2aWdhdG9yLm9uTGluZSkge1xuICAgICAgICB0aGlzLnN0b3JhZ2UuZ2V0KCdBdXRoVXNlckRldGFpbHMnKS50aGVuKHVzZXJEZXRhaWxzID0+IHJlc29sdmUoeyBpZFRva2VuOiBudWxsLCB1c2VyRGV0YWlscyB9KSk7XG4gICAgICAgIC8vIHJlLWV4ZWN1dGUgdGhlIG1ldGhvZCB3aGVuIGJhY2sgb25saW5lLCBzbyB0aGF0IHlvdSBjYW4gcmV0cmlldmUgYSB0b2tlbiB0byBtYWtlIHJlcXVlc3RzXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICdvbmxpbmUnLFxuICAgICAgICAgICgpOiBQcm9taXNlPHZvaWQ+ID0+XG4gICAgICAgICAgICB0aGlzLmlzQXV0aGVudGljYXRlZCh0cnVlLCBnZXRGcmVzaElkVG9rZW5PbkV4cClcbiAgICAgICAgICAgICAgLy8gc2V0IHRoZSBuZXcgdG9rZW4gYXMgaWYgaXQgd2FzIHJlZnJlc2hlZFxuICAgICAgICAgICAgICAudGhlbihyZXN1bHQgPT4gZ2V0RnJlc2hJZFRva2VuT25FeHAocmVzdWx0LmlkVG9rZW4pKVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgdXNlciA9IHRoaXMudXNlclBvb2wuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICAgICAgaWYgKCF1c2VyKSByZXR1cm4gcmVqZWN0KCk7XG4gICAgICAgIHVzZXIuZ2V0U2Vzc2lvbigoZXJyOiBFcnJvciwgc2Vzc2lvbjogQ29nbml0b1VzZXJTZXNzaW9uKTogdm9pZCA9PiB7XG4gICAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICAgIHVzZXIuZ2V0VXNlckRhdGEoXG4gICAgICAgICAgICAoZXJyLCBkYXRhKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgY29uc3QgaXNNRkFFbmFibGVkID0gISEoXG4gICAgICAgICAgICAgICAgZGF0YS5Vc2VyTUZBU2V0dGluZ0xpc3QgJiYgZGF0YS5Vc2VyTUZBU2V0dGluZ0xpc3QuaW5jbHVkZXMoJ1NPRlRXQVJFX1RPS0VOX01GQScpXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGlmICghaXNNRkFFbmFibGVkICYmIGVudi5pZGVhLmF1dGguZm9yY2VMb2dpbldpdGhNRkEpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoTG9naW5PdXRjb21lQWN0aW9ucy5NRkFfU0VUVVApKTtcbiAgICAgICAgICAgICAgdXNlci5nZXRVc2VyQXR0cmlidXRlcygoZTogRXJyb3IsIGF0dHJpYnV0ZXM6IENvZ25pdG9Vc2VyQXR0cmlidXRlW10pOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZSkgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgICAgICAgICAvLyByZW1hcCB1c2VyIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBjb25zdCB1c2VyRGV0YWlsczogYW55ID0ge307XG4gICAgICAgICAgICAgICAgYXR0cmlidXRlcy5mb3JFYWNoKChhOiBDb2duaXRvVXNlckF0dHJpYnV0ZSk6IHN0cmluZyA9PiAodXNlckRldGFpbHNbYS5nZXROYW1lKCldID0gYS5nZXRWYWx1ZSgpKSk7XG4gICAgICAgICAgICAgICAgLy8gYWRkIHRoZSB1c2VyJ3MgZ3JvdXBzIHRvIHRoZSBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkluZm8gPSBzZXNzaW9uLmdldEFjY2Vzc1Rva2VuKCkuZGVjb2RlUGF5bG9hZCgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGdyb3Vwczogc3RyaW5nW10gPSBzZXNzaW9uSW5mb1snY29nbml0bzpncm91cHMnXSB8fCBbXTtcbiAgICAgICAgICAgICAgICB1c2VyRGV0YWlsc1snZ3JvdXBzJ10gPSBncm91cHM7XG4gICAgICAgICAgICAgICAgLy8gcnVuIHNvbWUgY2hlY2tzIGNvbnNpZGVyaW5nIHRoZSB1c2VyJ3MgZ3JvdXBzIGFuZCBkZXZpY2VzIChiYXNlZCBvbiB0aGUgcHJvamVjdCdzIGNvbmZpZ3VyYXRpb24pXG4gICAgICAgICAgICAgICAgdGhpcy5ydW5Qb3N0QXV0aENoZWNrcyh1c2VyRGV0YWlscywgZXJyID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIGluIGNhc2Ugc29tZSBjaGVjayBmYWlsZWQsIHJlamVjdCB0aGUgYXV0aG9yaXNhdGlvbiBmbG93XG4gICAgICAgICAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAvLyAoYXN5bmMpIHNhdmUgdGhlIHJlZnJlc2ggdG9rZW4gc28gaXQgY2FuIGJlIGFjY2Vzc2VkIGJ5IG90aGVyIHByb2NlZHVyZXNcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ0F1dGhSZWZyZXNoVG9rZW4nLCBzZXNzaW9uLmdldFJlZnJlc2hUb2tlbigpLmdldFRva2VuKCkpO1xuICAgICAgICAgICAgICAgICAgLy8gc2V0IGEgdGltZXIgdG8gbWFuYWdlIHRoZSBhdXRvcmVmcmVzaCBvZiB0aGUgaWRUb2tlbiAodGhyb3VnaCB0aGUgcmVmcmVzaFRva2VuKVxuICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChcbiAgICAgICAgICAgICAgICAgICAgKCk6IHZvaWQgPT4gdGhpcy5yZWZyZXNoU2Vzc2lvbih1c2VyLCBzZXNzaW9uLmdldFJlZnJlc2hUb2tlbigpLmdldFRva2VuKCksIGdldEZyZXNoSWRUb2tlbk9uRXhwKSxcbiAgICAgICAgICAgICAgICAgICAgMTUgKiA2MCAqIDEwMDBcbiAgICAgICAgICAgICAgICAgICk7IC8vIGV2ZXJ5IDE1IG1pbnV0ZXNcbiAgICAgICAgICAgICAgICAgIC8vIChhc3luYykgaWYgb2ZmbGluZUFsbG93ZWQsIHNhdmUgZGF0YSBsb2NhbGx5LCB0byB1c2UgaXQgbmV4dCB0aW1lIHdlJ2xsIGJlIG9mZmxpbmVcbiAgICAgICAgICAgICAgICAgIGlmIChvZmZsaW5lQWxsb3dlZCkgdGhpcy5zdG9yYWdlLnNldCgnQXV0aFVzZXJEZXRhaWxzJywgdXNlckRldGFpbHMpO1xuICAgICAgICAgICAgICAgICAgLy8gcmV0dXJuIHRoZSBpZFRva2VuICh0byB1c2Ugd2l0aCBBUEkpXG4gICAgICAgICAgICAgICAgICByZXNvbHZlKHsgaWRUb2tlbjogc2Vzc2lvbi5nZXRJZFRva2VuKCkuZ2V0Snd0VG9rZW4oKSwgdXNlckRldGFpbHMgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHsgYnlwYXNzQ2FjaGU6IHRydWUgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBIZWxwZXIgdG8gcmVmcmVzaCB0aGUgc2Vzc2lvbiBldmVyeSBOIG1pbnV0ZXMuXG4gICAqL1xuICBwcml2YXRlIHJlZnJlc2hTZXNzaW9uKHVzZXI6IENvZ25pdG9Vc2VyLCByZWZyZXNoVG9rZW46IHN0cmluZywgY2FsbGJhY2s6IChmcmVzaElkVG9rZW46IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xuICAgIHVzZXIucmVmcmVzaFNlc3Npb24oXG4gICAgICBuZXcgQ29nbml0b1JlZnJlc2hUb2tlbih7IFJlZnJlc2hUb2tlbjogcmVmcmVzaFRva2VuIH0pLFxuICAgICAgKGVycjogRXJyb3IsIHNlc3Npb246IENvZ25pdG9Vc2VyU2Vzc2lvbik6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgLy8gdHJ5IGFnYWluIGluIDEgbWludXRlXG4gICAgICAgICAgc2V0VGltZW91dCgoKTogdm9pZCA9PiB0aGlzLnJlZnJlc2hTZXNzaW9uKHVzZXIsIHJlZnJlc2hUb2tlbiwgY2FsbGJhY2spLCAxICogNjAgKiAxMDAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyAoYXN5bmMpIHNhdmUgdGhlIHJlZnJlc2ggdG9rZW4gc28gaXQgY2FuIGJlIGFjY2Vzc2VkIGJ5IG90aGVyIHByb2NlZHVyZXNcbiAgICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdBdXRoUmVmcmVzaFRva2VuJywgc2Vzc2lvbi5nZXRSZWZyZXNoVG9rZW4oKS5nZXRUb2tlbigpKTtcbiAgICAgICAgICAvLyByZXBlYXQgZXZlcnkgMTUgbWludXRlc1xuICAgICAgICAgIHNldFRpbWVvdXQoXG4gICAgICAgICAgICAoKTogdm9pZCA9PiB0aGlzLnJlZnJlc2hTZXNzaW9uKHVzZXIsIHNlc3Npb24uZ2V0UmVmcmVzaFRva2VuKCkuZ2V0VG9rZW4oKSwgY2FsbGJhY2spLFxuICAgICAgICAgICAgMTUgKiA2MCAqIDEwMDBcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIHJ1biB0aGUgY2FsbGJhY2sgYWN0aW9uLCBpZiBzZXRcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKHNlc3Npb24uZ2V0SWRUb2tlbigpLmdldEp3dFRva2VuKCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgKTtcbiAgfVxuICAvKipcbiAgICogUnVuIHNvbWUgcG9zdC1hdXRoIGNoZWNrcywgYmFzZWQgb24gdGhlIHVzZXJzIGdyb3VwcyBhbmQgb24gdGhlIGFwcCdzIGNvbmZpZ3VyYXRpb246XG4gICAqICAtIHVzZXJzIGluIHRoZSBDb2duaXRvJ3MgXCJhZG1pbnNcIiBncnVwIHNraXAgYWxsIHRoZSBmb2xsb3dpbmcgcnVsZXMuXG4gICAqICAtIHVzZXJzIGluIHRoZSBDb2duaXRvJ3MgXCJyb2JvdHNcIiBncm91cCBjYW4ndCBzaWduLWludG8gZnJvbnQtZW5kcyAodGhleSBzZXJ2ZSBvbmx5IGJhY2stZW5kIHB1cnBvc2VzKS5cbiAgICogIC0gaWYgYGVudi5pZGVhLmF1dGguc2luZ2xlU2ltdWx0YW5lb3VzU2Vzc2lvbmAgaXMgb24sIG1ha2Ugc3VyZSB0aGVyZSBpcyBvbmx5IG9uZSBhY3RpdmUgc2Vzc2lvbiBwZXIgdXNlci5cbiAgICovXG4gIHByaXZhdGUgcnVuUG9zdEF1dGhDaGVja3ModXNlckRldGFpbHM6IGFueSwgY2FsbGJhY2s6IChlcnI/OiBFcnJvcikgPT4gdm9pZCk6IHZvaWQgfCBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBncm91cHM6IHN0cmluZ1tdID0gdXNlckRldGFpbHNbJ2dyb3VwcyddO1xuICAgIC8vIHNraXAgY2hlY2tzIGlmIHRoZSB1c2VyIGlzIGluIHRoZSBcImFkbWluc1wiIGdyb3VwXG4gICAgY29uc3QgaXNBZG1pbiA9IGdyb3Vwcy5zb21lKHggPT4geCA9PT0gJ2FkbWlucycpO1xuICAgIGlmIChpc0FkbWluKSByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAvLyB1c2VycyBpbiB0aGUgXCJyb2JvdHNcIiBncm91cCBjYW4ndCBzaWduLWludG8gZnJvbnQtZW5kcyAodGhleSBzZXJ2ZSBvbmx5IGJhY2stZW5kIHB1cnBvc2VzKVxuICAgIGNvbnN0IGlzUm9ib3QgPSBncm91cHMuc29tZSh4ID0+IHggPT09ICdyb2JvdHMnKTtcbiAgICBpZiAoaXNSb2JvdCkgcmV0dXJuIGNhbGxiYWNrKG5ldyBFcnJvcignUk9CT1RfVVNFUicpKTtcbiAgICAvLyBpbiBjYXNlIHRoZSBwcm9qZWN0IGxpbWl0cyBlYWNoIGFjY291bnQgdG8gb25seSBvbmUgc2ltdWx0YW5lb3VzIHNlc3Npb24sIHJ1biBhIGNoZWNrXG4gICAgaWYgKGVudi5pZGVhLmF1dGguc2luZ2xlU2ltdWx0YW5lb3VzU2Vzc2lvbikgcmV0dXJuIHRoaXMuY2hlY2tGb3JTaW11bHRhbmVvdXNTZXNzaW9ucyh1c2VyRGV0YWlscywgY2FsbGJhY2spO1xuICAgIC8vIG90aGVyd2lzZSwgd2UncmUgZG9uZVxuICAgIGNhbGxiYWNrKCk7XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgdGhlIHVzZXIgc2lnbmVkLWludG8gbXVsdGlwbGUgZGV2aWNlcy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tGb3JTaW11bHRhbmVvdXNTZXNzaW9ucyh1c2VyRGV0YWlsczogYW55LCBjYWxsYmFjazogKGVycj86IEVycm9yKSA9PiB2b2lkKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gZ2V0IG9yIGNyZWF0ZSBhIGtleSBmb3IgdGhlIGN1cnJlbnQgZGV2aWNlICh+cmFuZG9tKVxuICAgIGxldCBjdXJyZW50RGV2aWNlS2V5ID0gYXdhaXQgdGhpcy5zdG9yYWdlLmdldCgnQXV0aERldmljZUtleScpO1xuICAgIGlmICghY3VycmVudERldmljZUtleSkge1xuICAgICAgY29uc3QgcmFuZG9tS2V5ID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDEwKTtcbiAgICAgIGN1cnJlbnREZXZpY2VLZXkgPSByYW5kb21LZXkuY29uY2F0KFN0cmluZyhEYXRlLm5vdygpKSk7XG4gICAgICBhd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0KCdBdXRoRGV2aWNlS2V5JywgY3VycmVudERldmljZUtleSk7XG4gICAgfVxuICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGxhc3QgZGV2aWNlIHRvIHNpZ24taW50byB0aGlzIHByb2plY3QgKGlmIGFueSkgaXMgdGhlIGN1cnJlbnQgb25lXG4gICAgY29uc3QgbGFzdERldmljZVRvU2lnbkludG9UaGlzUHJvamVjdCA9IHVzZXJEZXRhaWxzW0RFVklDRV9LRVlfQVRUUklCVVRFXTtcbiAgICAvLyBpZiBpdCdzIHRoZSBmaXJzdCB1c2VyJ3MgZGV2aWNlIHRvIHNpZ24taW4sIHNhdmUgdGhlIHJlZmVyZW5jZSBpbiBDb2duaXRvIGFuZCByZXNvbHZlXG4gICAgaWYgKCFsYXN0RGV2aWNlVG9TaWduSW50b1RoaXNQcm9qZWN0KSB7XG4gICAgICB0aGlzLnNldEN1cnJlbnREZXZpY2VGb3JQcm9qZWN0KGN1cnJlbnREZXZpY2VLZXkpXG4gICAgICAgIC50aGVuKCgpOiB2b2lkID0+IGNhbGxiYWNrKCkpXG4gICAgICAgIC5jYXRjaCgoKTogdm9pZCA9PiBjYWxsYmFjayhuZXcgRXJyb3IoJ0NBTlRfU0VUX0RFVklDRScpKSk7XG4gICAgICAvLyBpZiB0aGUgZGV2aWNlIGRpZG4ndCBjaGFuZ2UsIHJlc29sdmVcbiAgICB9IGVsc2UgaWYgKGxhc3REZXZpY2VUb1NpZ25JbnRvVGhpc1Byb2plY3QgPT09IGN1cnJlbnREZXZpY2VLZXkpIGNhbGxiYWNrKCk7XG4gICAgLy8gb3Rod2Vyd2lzZSwgcmVwb3J0IHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgc2ltdWx0YW5lb3VzIHNlc3Npb25cbiAgICBlbHNlIGNhbGxiYWNrKG5ldyBFcnJvcignU0lNVUxUQU5FT1VTX1NFU1NJT04nKSk7XG4gIH1cbiAgLyoqXG4gICAqIFNldCAob3IgcmVzZXQpIHRoZSBjdXJyZW50IHVzZXIncyBkZXZpY2UgKGJ5IGtleSkgaW4gdGhlIGN1cnJlbnQgcHJvamVjdCAoc3RvcmVkIGluIENvZ25pdG8pLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXRDdXJyZW50RGV2aWNlRm9yUHJvamVjdChkZXZpY2VLZXk/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhdHRyaWJ1dGVzOiBhbnkgPSB7fTtcbiAgICAvLyBub3RlOiBhbiBlbXB0eSBzdHJpbmcgd2lsbCByZW1vdmUgdGhlIGF0dHJpYnV0ZSBmcm9tIENvZ25pdG9cbiAgICBhdHRyaWJ1dGVzW0RFVklDRV9LRVlfQVRUUklCVVRFXSA9IGRldmljZUtleSB8fCAnJztcbiAgICByZXR1cm4gdGhpcy51cGRhdGVVc2VyQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgfVxuICAvKipcbiAgICogVXBkYXRlIHRoZSBjdXJyZW50bHkgbG9nZ2VkIGluIHVzZXIncyBhdHRyaWJ1dGVzLlxuICAgKi9cbiAgdXBkYXRlVXNlckF0dHJpYnV0ZXMoYXR0cmlidXRlczogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIC8vIHByZXBhcmUgdGhlIGF0dHJpYnV0ZXMgd2Ugd2FudCB0byBjaGFuZ2VcbiAgICAgIGNvbnN0IGF0dHJzID0gbmV3IEFycmF5PGFueT4oKTtcbiAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBhdHRyaWJ1dGVzKVxuICAgICAgICBpZiAoYXR0cmlidXRlc1twcm9wXSAhPT0gdW5kZWZpbmVkKSBhdHRycy5wdXNoKHRoaXMucHJlcGFyZVVzZXJBdHRyaWJ1dGUocHJvcCwgYXR0cmlidXRlc1twcm9wXSkpO1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMudXNlclBvb2wuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICAgIGlmICghdXNlcikgcmV0dXJuIHJlamVjdCgpO1xuICAgICAgLy8gd2UgbmVlZCB0byBnZXQgdGhlIHNlc3Npb24gYmVmb3JlIHRvIG1ha2UgY2hhbmdlc1xuICAgICAgdXNlci5nZXRTZXNzaW9uKChlcnI6IEVycm9yKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChlcnIpIHJlamVjdChlcnIpO1xuICAgICAgICBlbHNlIHVzZXIudXBkYXRlQXR0cmlidXRlcyhhdHRycywgKGU6IEVycm9yKTogdm9pZCA9PiAoZSA/IHJlamVjdChlKSA6IHJlc29sdmUoKSkpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIHBhc3N3b3JkIGFnYWluc3QgdGhlIHBvbGljeSBzZXQgaW4gdGhlIGVudmlyb25tZW50cyBjb25maWd1cmF0aW9uLlxuICAgKiBJbiBjYXNlIHRoZXJlIGFyZSBlcnJvcnMsIHRoZXkgYXJlIHJldHVybmVkIGFzIGFuIGFycmF5IG9mIHN0cmluZ3MuXG4gICAqL1xuICB2YWxpZGF0ZVBhc3N3b3JkQWdhaW5zdFBvbGljeShwYXNzd29yZDogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IFtdO1xuICAgIGlmIChwYXNzd29yZD8udHJpbSgpLmxlbmd0aCA8IHRoaXMucGFzc3dvcmRQb2xpY3kubWluTGVuZ3RoKSBlcnJvcnMucHVzaCgnTUlOX0xFTkdUSCcpO1xuICAgIGlmICh0aGlzLnBhc3N3b3JkUG9saWN5LnJlcXVpcmVEaWdpdHMgJiYgIS9cXGQvLnRlc3QocGFzc3dvcmQpKSBlcnJvcnMucHVzaCgnUkVRVUlSRV9ESUdJVFMnKTtcbiAgICBpZiAodGhpcy5wYXNzd29yZFBvbGljeS5yZXF1aXJlTG93ZXJjYXNlICYmICEvW2Etel0vLnRlc3QocGFzc3dvcmQpKSBlcnJvcnMucHVzaCgnUkVRVUlSRV9MT1dFUkNBU0UnKTtcbiAgICBpZiAodGhpcy5wYXNzd29yZFBvbGljeS5yZXF1aXJlU3ltYm9scyAmJiAhL1tcXF5cXCRcXCpcXC5cXF9cXH5cXGBcXCtcXD1AXFwhXFw/XFw+XFw8XFw6XFw7XFxcXFxcLFxcI1xcJVxcJl0vLnRlc3QocGFzc3dvcmQpKVxuICAgICAgZXJyb3JzLnB1c2goJ1JFUVVJUkVfU1lNQk9MUycpO1xuICAgIGlmICh0aGlzLnBhc3N3b3JkUG9saWN5LnJlcXVpcmVVcHBlcmNhc2UgJiYgIS9bQS1aXS8udGVzdChwYXNzd29yZCkpIGVycm9ycy5wdXNoKCdSRVFVSVJFX1VQUEVSQ0FTRScpO1xuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCBhIGNvbXBsZXRlIHBhc3N3b3JkIHBvbGljeSBwYXR0ZXJuLCBiYXNlZCBvbiB0aGUgZW52aXJvbm1lbnRzIGNvbmZpZ3VyYXRpb24sIHRvIHVzZSBvbiBwYXNzd29yZCBpbnB1dCBmaWVsZHMuXG4gICAqIE5vdGU6IHNvbWUgb2YgdGhlIHN5bWJvbHMgY291bGRuJ3QgYmUgaW5jbHVkZWQgYmVjYXVzZSB1bnN1cHBvcnRlZCBieSB0aGUgaW5wdXRbcGF0dGVybl0gYXR0cmlidXRlLlxuICAgKi9cbiAgZ2V0UGFzc3dvcmRQb2xpY3lQYXR0ZXJuRm9ySW5wdXQoKTogc3RyaW5nIHtcbiAgICBsZXQgcGF0dGVybiA9ICcnO1xuICAgIGlmICh0aGlzLnBhc3N3b3JkUG9saWN5LnJlcXVpcmVEaWdpdHMpIHBhdHRlcm4gKz0gYCg/PS4qWzAtOV0pYDtcbiAgICBpZiAodGhpcy5wYXNzd29yZFBvbGljeS5yZXF1aXJlTG93ZXJjYXNlKSBwYXR0ZXJuICs9IGAoPz0uKlthLXpdKWA7XG4gICAgaWYgKHRoaXMucGFzc3dvcmRQb2xpY3kucmVxdWlyZVN5bWJvbHMpIHBhdHRlcm4gKz0gYCg/PS4qW1xcXlxcJFxcKlxcLlxcX1xcflxcYFxcK1xcPUBcXCFcXD9cXD5cXDxcXDpcXDtcXFxcXFwsXFwjXFwlXFwmXSlgO1xuICAgIGlmICh0aGlzLnBhc3N3b3JkUG9saWN5LnJlcXVpcmVVcHBlcmNhc2UpIHBhdHRlcm4gKz0gYCg/PS4qW0EtWl0pYDtcbiAgICBwYXR0ZXJuICs9IGAueyR7dGhpcy5wYXNzd29yZFBvbGljeS5taW5MZW5ndGh9LH1gO1xuICAgIHJldHVybiBwYXR0ZXJuO1xuICB9XG59XG5cbi8qKlxuICogVGhlIHBvc3NpYmxlIGFjdGlvbnMgZm9sbG93aW5nIGEgc3VjY2Vzc2Z1bCBsb2dpbi5cbiAqL1xuZXhwb3J0IGVudW0gTG9naW5PdXRjb21lQWN0aW9ucyB7XG4gIE5PTkUgPSAnbm9uZScsXG4gIE5FV19QQVNTV09SRCA9ICduZXdQYXNzd29yZCcsXG4gIE1GQV9DSEFMTEVOR0UgPSAnbWZhQ2hhbGxlbmdlJyxcbiAgTUZBX1NFVFVQID0gJ21mYVNldHVwJ1xufVxuIl19