@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
@@ -1,443 +0,0 @@
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.userPool = new CognitoUserPool({
20
- UserPoolId: env.aws.cognito.userPoolId,
21
- ClientId: env.aws.cognito.userPoolClientId
22
- });
23
- }
24
- /**
25
- * Prepare the necessary structure to get authorized in Cognito.
26
- */
27
- prepareAuthDetails(username, pwd) {
28
- return new AuthenticationDetails({ Username: username, Password: pwd });
29
- }
30
- /**
31
- * Prepare the necessary structure to identify a Cognito user.
32
- */
33
- prepareCognitoUser(username) {
34
- return new CognitoUser({ Username: username, Pool: this.userPool });
35
- }
36
- /**
37
- * Prepare a user attribute (they are all strings) in Cognito's format.
38
- */
39
- prepareUserAttribute(name, value) {
40
- return new CognitoUserAttribute({ Name: name, Value: value });
41
- }
42
- /**
43
- * Perform a login through username and password.
44
- */
45
- login(username, password) {
46
- return new Promise((resolve, reject) => {
47
- const user = this.prepareCognitoUser(username);
48
- user.authenticateUser(this.prepareAuthDetails(username, password), {
49
- onSuccess: () => resolve(env.idea.auth.forceLoginWithMFA ? LoginOutcomeActions.MFA_SETUP : LoginOutcomeActions.NONE),
50
- onFailure: (err) => reject(err),
51
- newPasswordRequired: () => {
52
- this.challengeUsername = username;
53
- this.challengePassword = password;
54
- resolve(LoginOutcomeActions.NEW_PASSWORD);
55
- },
56
- totpRequired: () => {
57
- this.challengeUsername = username;
58
- this.challengePassword = password;
59
- resolve(LoginOutcomeActions.MFA_CHALLENGE);
60
- }
61
- });
62
- });
63
- }
64
- /**
65
- * Complete the new password flow in the authentication.
66
- */
67
- confirmNewPassword(newPassword) {
68
- return new Promise((resolve, reject) => {
69
- const user = this.prepareCognitoUser(this.challengeUsername);
70
- user.authenticateUser(this.prepareAuthDetails(this.challengeUsername, this.challengePassword), {
71
- onSuccess: () => resolve(),
72
- onFailure: (err) => reject(err),
73
- newPasswordRequired: () => user.completeNewPasswordChallenge(newPassword, {}, {
74
- onSuccess: () => {
75
- this.challengeUsername = null;
76
- this.challengePassword = null;
77
- resolve();
78
- },
79
- onFailure: (err) => reject(err)
80
- })
81
- });
82
- });
83
- }
84
- /**
85
- * Complete the MFA challenge flow in the authentication.
86
- */
87
- completeMFAChallenge(otpCode) {
88
- return new Promise((resolve, reject) => {
89
- const user = this.prepareCognitoUser(this.challengeUsername);
90
- user.authenticateUser(this.prepareAuthDetails(this.challengeUsername, this.challengePassword), {
91
- onSuccess: () => resolve(),
92
- onFailure: (err) => reject(err),
93
- totpRequired: (challengeName) => user.sendMFACode(otpCode, {
94
- onSuccess: () => {
95
- this.challengeUsername = null;
96
- this.challengePassword = null;
97
- resolve();
98
- },
99
- onFailure: err => reject(err)
100
- }, challengeName)
101
- });
102
- });
103
- }
104
- /**
105
- * Register a new user a set its default attributes.
106
- */
107
- register(username, password, attributes) {
108
- attributes = attributes || {};
109
- return new Promise((resolve, reject) => {
110
- // add attributes like the email address and the fullname
111
- const attrs = [];
112
- for (const prop in attributes)
113
- if (attributes[prop])
114
- attrs.push(this.prepareUserAttribute(prop, attributes[prop]));
115
- // add the email, which is equal to the username for most of our Pools
116
- if (!attributes.email)
117
- attrs.push(this.prepareUserAttribute('email', username));
118
- // register the new user to the pool
119
- this.userPool.signUp(username, password, attrs, null, (err, res) => {
120
- if (err)
121
- return reject(err);
122
- this.newAccountJustRegistered = username;
123
- resolve(res.user);
124
- });
125
- });
126
- }
127
- /**
128
- * In case new account has just been registered, return the username.
129
- */
130
- getNewAccountJustRegistered() {
131
- return this.newAccountJustRegistered;
132
- }
133
- /**
134
- * Confirm a new registration through the confirmation code sent by Cognito.
135
- */
136
- confirmRegistration(username, code) {
137
- return new Promise((resolve, reject) => {
138
- this.prepareCognitoUser(username).confirmRegistration(code, true, (err) => err ? reject(err) : resolve());
139
- });
140
- }
141
- /**
142
- * Send again a confirmation code for a new registration.
143
- */
144
- resendConfirmationCode(username) {
145
- return new Promise((resolve, reject) => {
146
- this.prepareCognitoUser(username).resendConfirmationCode((err) => (err ? reject(err) : resolve()));
147
- });
148
- }
149
- /**
150
- * Logout the currently signed-in user.
151
- */
152
- logout(options) {
153
- options = Object.assign({ global: false }, options);
154
- return new Promise((resolve, reject) => {
155
- // remove the refresh token previosly saved
156
- this.storage.remove('AuthRefreshToken').then(() =>
157
- // remove the optional auth details
158
- this.storage.remove('AuthUserDetails').then(() => {
159
- // get the user and the session
160
- const user = this.userPool.getCurrentUser();
161
- user.getSession(async (err) => {
162
- // if the session is active, run the online sign-out; otherwise, only the local data has been deleted
163
- if (err)
164
- return resolve();
165
- // if a reference to the device was saved, forget it
166
- if (env.idea.auth.singleSimultaneousSession)
167
- await this.setCurrentDeviceForProject(null);
168
- // sign-out from the pool (terminate the current session or all the sessions)
169
- if (options.global)
170
- user.globalSignOut({ onSuccess: () => resolve(), onFailure: err => reject(err) });
171
- else {
172
- user.signOut();
173
- resolve();
174
- }
175
- });
176
- }));
177
- });
178
- }
179
- /**
180
- * Send a password reset request.
181
- */
182
- forgotPassword(username) {
183
- return new Promise((resolve, reject) => {
184
- this.prepareCognitoUser(username).forgotPassword({
185
- onSuccess: () => resolve(),
186
- onFailure: (err) => reject(err)
187
- });
188
- });
189
- }
190
- /**
191
- * Confirm a new password after a password reset request.
192
- */
193
- confirmPassword(username, code, newPwd) {
194
- return new Promise((resolve, reject) => {
195
- this.prepareCognitoUser(username).confirmPassword(code, newPwd, {
196
- onSuccess: () => resolve(),
197
- onFailure: (err) => reject(err)
198
- });
199
- });
200
- }
201
- /**
202
- * Gets the URL for enabling MFA. This URL can be used to generate a QR Code to read with an authenticator app.
203
- */
204
- getURLForEnablingMFA() {
205
- return new Promise((resolve, reject) => {
206
- const user = this.userPool.getCurrentUser();
207
- if (!user)
208
- return reject();
209
- user.getSession((err) => {
210
- if (err)
211
- return reject(err);
212
- user.associateSoftwareToken({
213
- associateSecretCode: (secretCode) => resolve(`otpauth://totp/${encodeURI(this.mfaProjectName)}?secret=${secretCode}`),
214
- onFailure: (err) => reject(err)
215
- });
216
- });
217
- });
218
- }
219
- /**
220
- * Check whether the user has MFA enabled.
221
- */
222
- checkIfUserHasMFAEnabled(bypassCache = false) {
223
- return new Promise((resolve, reject) => {
224
- const user = this.userPool.getCurrentUser();
225
- if (!user)
226
- return reject();
227
- user.getSession((err) => {
228
- if (err)
229
- return reject(err);
230
- user.getUserData((err, data) => {
231
- if (err)
232
- return reject(err);
233
- const isMFAEnabled = !!(data.UserMFASettingList && data.UserMFASettingList.includes('SOFTWARE_TOKEN_MFA'));
234
- resolve(isMFAEnabled);
235
- }, { bypassCache });
236
- });
237
- });
238
- }
239
- /**
240
- * Configure a MFA device for the user.
241
- */
242
- setMFADevice(otp, mfaDeviceName, enabled = true, preferred = true) {
243
- return new Promise((resolve, reject) => {
244
- const user = this.userPool.getCurrentUser();
245
- if (!user)
246
- return reject();
247
- user.getSession((err) => {
248
- if (err)
249
- return reject(err);
250
- user.verifySoftwareToken(otp, mfaDeviceName, {
251
- onSuccess: () => user.setUserMfaPreference(null, { Enabled: enabled, PreferredMfa: preferred }, (err) => err ? reject(err) : resolve()),
252
- onFailure: (err) => reject(err)
253
- });
254
- });
255
- });
256
- }
257
- /**
258
- * Enable a new MFA device for the user by inserting an OTP code generated by it.
259
- */
260
- enableMFA(otp, mfaDeviceName = 'default') {
261
- return this.setMFADevice(otp, mfaDeviceName, true, true);
262
- }
263
- /**
264
- * Disable MFA for a user by inserting an OTP code generated by it.
265
- */
266
- disableMFA(otp, mfaDeviceName = 'default') {
267
- return this.setMFADevice(otp, mfaDeviceName, false, false);
268
- }
269
- /**
270
- * Check if a user is currently authenticated.
271
- * @param offlineAllowed if set and if offline, skip authentication and retrieve data locally
272
- * @param getFreshIdTokenOnExp cb function to execute when the idToken is refreshed
273
- */
274
- isAuthenticated(offlineAllowed, getFreshIdTokenOnExp) {
275
- return new Promise((resolve, reject) => {
276
- if (offlineAllowed && !navigator.onLine) {
277
- this.storage.get('AuthUserDetails').then(userDetails => resolve({ idToken: null, userDetails }));
278
- // re-execute the method when back online, so that you can retrieve a token to make requests
279
- window.addEventListener('online', () => this.isAuthenticated(true, getFreshIdTokenOnExp)
280
- // set the new token as if it was refreshed
281
- .then(result => getFreshIdTokenOnExp(result.idToken)));
282
- }
283
- else {
284
- const user = this.userPool.getCurrentUser();
285
- if (!user)
286
- return reject();
287
- user.getSession((err, session) => {
288
- if (err)
289
- return reject(err);
290
- user.getUserData((err, data) => {
291
- if (err)
292
- return reject(err);
293
- const isMFAEnabled = !!(data.UserMFASettingList && data.UserMFASettingList.includes('SOFTWARE_TOKEN_MFA'));
294
- if (!isMFAEnabled && env.idea.auth.forceLoginWithMFA)
295
- return reject(new Error(LoginOutcomeActions.MFA_SETUP));
296
- user.getUserAttributes((e, attributes) => {
297
- if (e)
298
- return reject(e);
299
- // remap user attributes
300
- const userDetails = {};
301
- attributes.forEach((a) => (userDetails[a.getName()] = a.getValue()));
302
- // add the user's groups to the attributes
303
- const sessionInfo = session.getAccessToken().decodePayload();
304
- const groups = sessionInfo['cognito:groups'] || [];
305
- userDetails['groups'] = groups;
306
- // run some checks considering the user's groups and devices (based on the project's configuration)
307
- this.runPostAuthChecks(userDetails, err => {
308
- // in case some check failed, reject the authorisation flow
309
- if (err)
310
- return reject(err);
311
- // (async) save the refresh token so it can be accessed by other procedures
312
- this.storage.set('AuthRefreshToken', session.getRefreshToken().getToken());
313
- // set a timer to manage the autorefresh of the idToken (through the refreshToken)
314
- setTimeout(() => this.refreshSession(user, session.getRefreshToken().getToken(), getFreshIdTokenOnExp), 15 * 60 * 1000); // every 15 minutes
315
- // (async) if offlineAllowed, save data locally, to use it next time we'll be offline
316
- if (offlineAllowed)
317
- this.storage.set('AuthUserDetails', userDetails);
318
- // return the idToken (to use with API)
319
- resolve({ idToken: session.getIdToken().getJwtToken(), userDetails });
320
- });
321
- });
322
- }, { bypassCache: true });
323
- });
324
- }
325
- });
326
- }
327
- /**
328
- * Helper to refresh the session every N minutes.
329
- */
330
- refreshSession(user, refreshToken, callback) {
331
- user.refreshSession(new CognitoRefreshToken({ RefreshToken: refreshToken }), (err, session) => {
332
- if (err) {
333
- // try again in 1 minute
334
- setTimeout(() => this.refreshSession(user, refreshToken, callback), 1 * 60 * 1000);
335
- }
336
- else {
337
- // (async) save the refresh token so it can be accessed by other procedures
338
- this.storage.set('AuthRefreshToken', session.getRefreshToken().getToken());
339
- // repeat every 15 minutes
340
- setTimeout(() => this.refreshSession(user, session.getRefreshToken().getToken(), callback), 15 * 60 * 1000);
341
- // run the callback action, if set
342
- if (callback)
343
- callback(session.getIdToken().getJwtToken());
344
- }
345
- });
346
- }
347
- /**
348
- * Run some post-auth checks, based on the users groups and on the app's configuration:
349
- * - users in the Cognito's "admins" grup skip all the following rules.
350
- * - users in the Cognito's "robots" group can't sign-into front-ends (they serve only back-end purposes).
351
- * - if `env.idea.auth.singleSimultaneousSession` is on, make sure there is only one active session per user.
352
- */
353
- runPostAuthChecks(userDetails, callback) {
354
- const groups = userDetails['groups'];
355
- // skip checks if the user is in the "admins" group
356
- const isAdmin = groups.some(x => x === 'admins');
357
- if (isAdmin)
358
- return callback();
359
- // users in the "robots" group can't sign-into front-ends (they serve only back-end purposes)
360
- const isRobot = groups.some(x => x === 'robots');
361
- if (isRobot)
362
- return callback(new Error('ROBOT_USER'));
363
- // in case the project limits each account to only one simultaneous session, run a check
364
- if (env.idea.auth.singleSimultaneousSession)
365
- return this.checkForSimultaneousSessions(userDetails, callback);
366
- // otherwise, we're done
367
- callback();
368
- }
369
- /**
370
- * Check whether the user signed-into multiple devices.
371
- */
372
- async checkForSimultaneousSessions(userDetails, callback) {
373
- // get or create a key for the current device (~random)
374
- let currentDeviceKey = await this.storage.get('AuthDeviceKey');
375
- if (!currentDeviceKey) {
376
- const randomKey = Math.random().toString(36).substring(10);
377
- currentDeviceKey = randomKey.concat(String(Date.now()));
378
- await this.storage.set('AuthDeviceKey', currentDeviceKey);
379
- }
380
- // check whether the last device to sign-into this project (if any) is the current one
381
- const lastDeviceToSignIntoThisProject = userDetails[DEVICE_KEY_ATTRIBUTE];
382
- // if it's the first user's device to sign-in, save the reference in Cognito and resolve
383
- if (!lastDeviceToSignIntoThisProject) {
384
- this.setCurrentDeviceForProject(currentDeviceKey)
385
- .then(() => callback())
386
- .catch(() => callback(new Error('CANT_SET_DEVICE')));
387
- // if the device didn't change, resolve
388
- }
389
- else if (lastDeviceToSignIntoThisProject === currentDeviceKey)
390
- callback();
391
- // othwerwise, report there is more than one simultaneous session
392
- else
393
- callback(new Error('SIMULTANEOUS_SESSION'));
394
- }
395
- /**
396
- * Set (or reset) the current user's device (by key) in the current project (stored in Cognito).
397
- */
398
- setCurrentDeviceForProject(deviceKey) {
399
- const attributes = {};
400
- // note: an empty string will remove the attribute from Cognito
401
- attributes[DEVICE_KEY_ATTRIBUTE] = deviceKey || '';
402
- return this.updateUserAttributes(attributes);
403
- }
404
- /**
405
- * Update the currently logged in user's attributes.
406
- */
407
- updateUserAttributes(attributes) {
408
- return new Promise((resolve, reject) => {
409
- // prepare the attributes we want to change
410
- const attrs = new Array();
411
- for (const prop in attributes)
412
- if (attributes[prop] !== undefined)
413
- attrs.push(this.prepareUserAttribute(prop, attributes[prop]));
414
- const user = this.userPool.getCurrentUser();
415
- if (!user)
416
- return reject();
417
- // we need to get the session before to make changes
418
- user.getSession((err) => {
419
- if (err)
420
- reject(err);
421
- else
422
- user.updateAttributes(attrs, (e) => (e ? reject(e) : resolve()));
423
- });
424
- });
425
- }
426
- }
427
- IDEAAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: IDEAAuthService, deps: [{ token: i1.IDEAStorageService }], target: i0.ɵɵFactoryTarget.Injectable });
428
- IDEAAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: IDEAAuthService, providedIn: 'root' });
429
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: IDEAAuthService, decorators: [{
430
- type: Injectable,
431
- args: [{ providedIn: 'root' }]
432
- }], ctorParameters: function () { return [{ type: i1.IDEAStorageService }]; } });
433
- /**
434
- * The possible actions following a successful login.
435
- */
436
- export var LoginOutcomeActions;
437
- (function (LoginOutcomeActions) {
438
- LoginOutcomeActions["NONE"] = "none";
439
- LoginOutcomeActions["NEW_PASSWORD"] = "newPassword";
440
- LoginOutcomeActions["MFA_CHALLENGE"] = "mfaChallenge";
441
- LoginOutcomeActions["MFA_SETUP"] = "mfaSetup";
442
- })(LoginOutcomeActions || (LoginOutcomeActions = {}));
443
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vbW9kdWxlcy9hdXRoL3NyYy9hdXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLFdBQVcsRUFDWCxvQkFBb0IsRUFDcEIsZUFBZSxFQUNmLG1CQUFtQixFQUlwQixNQUFNLDRCQUE0QixDQUFDO0FBR3BDLE9BQU8sRUFBRSxXQUFXLElBQUksR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7QUFFMUM7O0dBRUc7QUFDSCxNQUFNLG9CQUFvQixHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUVoRTs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLGVBQWU7SUFVMUIsWUFBb0IsT0FBMkI7UUFBM0IsWUFBTyxHQUFQLE9BQU8sQ0FBb0I7UUFGdkMsbUJBQWMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7UUFHOUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLGVBQWUsQ0FBQztZQUNsQyxVQUFVLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVTtZQUN0QyxRQUFRLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO1NBQzNDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQixDQUFDLFFBQWdCLEVBQUUsR0FBVztRQUN0RCxPQUFPLElBQUkscUJBQXFCLENBQUMsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFDRDs7T0FFRztJQUNI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QUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEcsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsSUFBSTtnQkFBRSxPQUFPLE1BQU0sRUFBRSxDQUFDO1lBQzNCLG9EQUFvRDtZQUNwRCxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBVSxFQUFRLEVBQUU7Z0JBQ25DLElBQUksR0FBRztvQkFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7O29CQUNoQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBUSxFQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDckYsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7OzRHQTVhVSxlQUFlO2dIQUFmLGVBQWUsY0FERixNQUFNOzJGQUNuQixlQUFlO2tCQUQzQixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7QUFnYmxDOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksbUJBS1g7QUFMRCxXQUFZLG1CQUFtQjtJQUM3QixvQ0FBYSxDQUFBO0lBQ2IsbURBQTRCLENBQUE7SUFDNUIscURBQThCLENBQUE7SUFDOUIsNkNBQXNCLENBQUE7QUFDeEIsQ0FBQyxFQUxXLG1CQUFtQixLQUFuQixtQkFBbUIsUUFLOUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBBdXRoZW50aWNhdGlvbkRldGFpbHMsXG4gIENvZ25pdG9Vc2VyLFxuICBDb2duaXRvVXNlckF0dHJpYnV0ZSxcbiAgQ29nbml0b1VzZXJQb29sLFxuICBDb2duaXRvUmVmcmVzaFRva2VuLFxuICBDb2duaXRvVXNlclNlc3Npb24sXG4gIElTaWduVXBSZXN1bHQsXG4gIENoYWxsZW5nZU5hbWVcbn0gZnJvbSAnYW1hem9uLWNvZ25pdG8taWRlbnRpdHktanMnO1xuaW1wb3J0IHsgSURFQVN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnQGlkZWEtaW9uaWMvY29tbW9uJztcblxuaW1wb3J0IHsgZW52aXJvbm1lbnQgYXMgZW52IH0gZnJvbSAnQGVudic7XG5cbi8qKlxuICogVGhlIG5hbWUgb2YgdGhlIENvZ25pdG8ncyB1c2VyIGF0dHJpYnV0ZSB3aGljaCBjb250YWlucyB0aGUga2V5IG9mIHRoZSBsYXN0IGRldmljZSB0byBsb2dpbiBpbiB0aGlzIHByb2plY3QuXG4gKi9cbmNvbnN0IERFVklDRV9LRVlfQVRUUklCVVRFID0gJ2N1c3RvbTonLmNvbmNhdChlbnYuaWRlYS5wcm9qZWN0KTtcblxuLyoqXG4gKiBDb2duaXRvIHdyYXBwZXIgdG8gbWFuYWdlIHRoZSBhdXRoZW50aWNhdGlvbiBmbG93LlxuICpcbiAqIE5vdGU6IGluIElERUEncyBDb2duaXRvIHVzZXJzIHBvb2xzLCB0aGUgZW1haWwgaXMgYW4gYWxpYXMgb2YgdGhlIHVzZXJuYW1lLlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIElERUFBdXRoU2VydmljZSB7XG4gIHByaXZhdGUgdXNlclBvb2w6IENvZ25pdG9Vc2VyUG9vbDtcblxuICBjaGFsbGVuZ2VVc2VybmFtZTogc3RyaW5nO1xuICBwcml2YXRlIGNoYWxsZW5nZVBhc3N3b3JkOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBuZXdBY2NvdW50SnVzdFJlZ2lzdGVyZWQ6IHN0cmluZztcblxuICBwcml2YXRlIG1mYVByb2plY3ROYW1lID0gZW52LmlkZWEuYXBwLnRpdGxlID8/IGVudi5pZGVhLnByb2plY3Q7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzdG9yYWdlOiBJREVBU3RvcmFnZVNlcnZpY2UpIHtcbiAgICB0aGlzLnVzZXJQb29sID0gbmV3IENvZ25pdG9Vc2VyUG9vbCh7XG4gICAgICBVc2VyUG9vbElkOiBlbnYuYXdzLmNvZ25pdG8udXNlclBvb2xJZCxcbiAgICAgIENsaWVudElkOiBlbnYuYXdzLmNvZ25pdG8udXNlclBvb2xDbGllbnRJZFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmUgdGhlIG5lY2Vzc2FyeSBzdHJ1Y3R1cmUgdG8gZ2V0IGF1dGhvcml6ZWQgaW4gQ29nbml0by5cbiAgICovXG4gIHByaXZhdGUgcHJlcGFyZUF1dGhEZXRhaWxzKHVzZXJuYW1lOiBzdHJpbmcsIHB3ZDogc3RyaW5nKTogQXV0aGVudGljYXRpb25EZXRhaWxzIHtcbiAgICByZXR1cm4gbmV3IEF1dGhlbnRpY2F0aW9uRGV0YWlscyh7IFVzZXJuYW1lOiB1c2VybmFtZSwgUGFzc3dvcmQ6IHB3ZCB9KTtcbiAgfVxuICAvKipcbiAgICogUHJlcGFyZSB0aGUgbmVjZXNzYXJ5IHN0cnVjdHVyZSB0byBpZGVudGlmeSBhIENvZ25pdG8gdXNlci5cbiAgICovXG4gIHByZXBhcmVDb2duaXRvVXNlcih1c2VybmFtZTogc3RyaW5nKTogQ29nbml0b1VzZXIge1xuICAgIHJldHVybiBuZXcgQ29nbml0b1VzZXIoeyBVc2VybmFtZTogdXNlcm5hbWUsIFBvb2w6IHRoaXMudXNlclBvb2wgfSk7XG4gIH1cbiAgLyoqXG4gICAqIFByZXBhcmUgYSB1c2VyIGF0dHJpYnV0ZSAodGhleSBhcmUgYWxsIHN0cmluZ3MpIGluIENvZ25pdG8ncyBmb3JtYXQuXG4gICAqL1xuICBwcml2YXRlIHByZXBhcmVVc2VyQXR0cmlidXRlKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IENvZ25pdG9Vc2VyQXR0cmlidXRlIHtcbiAgICByZXR1cm4gbmV3IENvZ25pdG9Vc2VyQXR0cmlidXRlKHsgTmFtZTogbmFtZSwgVmFsdWU6IHZhbHVlIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBsb2dpbiB0aHJvdWdoIHVzZXJuYW1lIGFuZCBwYXNzd29yZC5cbiAgICovXG4gIGxvZ2luKHVzZXJuYW1lOiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPExvZ2luT3V0Y29tZUFjdGlvbnM+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMucHJlcGFyZUNvZ25pdG9Vc2VyKHVzZXJuYW1lKTtcbiAgICAgIHVzZXIuYXV0aGVudGljYXRlVXNlcih0aGlzLnByZXBhcmVBdXRoRGV0YWlscyh1c2VybmFtZSwgcGFzc3dvcmQpLCB7XG4gICAgICAgIG9uU3VjY2VzczogKCk6IHZvaWQgPT5cbiAgICAgICAgICByZXNvbHZlKGVudi5pZGVhLmF1dGguZm9yY2VMb2dpbldpdGhNRkEgPyBMb2dpbk91dGNvbWVBY3Rpb25zLk1GQV9TRVRVUCA6IExvZ2luT3V0Y29tZUFjdGlvbnMuTk9ORSksXG4gICAgICAgIG9uRmFpbHVyZTogKGVycjogRXJyb3IpOiB2b2lkID0+IHJlamVjdChlcnIpLFxuICAgICAgICBuZXdQYXNzd29yZFJlcXVpcmVkOiAoKTogdm9pZCA9PiB7XG4gICAgICAgICAgdGhpcy5jaGFsbGVuZ2VVc2VybmFtZSA9IHVzZXJuYW1lO1xuICAgICAgICAgIHRoaXMuY2hhbGxlbmdlUGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgICAgICAgICByZXNvbHZlKExvZ2luT3V0Y29tZUFjdGlvbnMuTkVXX1BBU1NXT1JEKTtcbiAgICAgICAgfSxcbiAgICAgICAgdG90cFJlcXVpcmVkOiAoKTogdm9pZCA9PiB7XG4gICAgICAgICAgdGhpcy5jaGFsbGVuZ2VVc2VybmFtZSA9IHVzZXJuYW1lO1xuICAgICAgICAgIHRoaXMuY2hhbGxlbmdlUGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgICAgICAgICByZXNvbHZlKExvZ2luT3V0Y29tZUFjdGlvbnMuTUZBX0NIQUxMRU5HRSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBDb21wbGV0ZSB0aGUgbmV3IHBhc3N3b3JkIGZsb3cgaW4gdGhlIGF1dGhlbnRpY2F0aW9uLlxuICAgKi9cbiAgY29uZmlybU5ld1Bhc3N3b3JkKG5ld1Bhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgdXNlciA9IHRoaXMucHJlcGFyZUNvZ25pdG9Vc2VyKHRoaXMuY2hhbGxlbmdlVXNlcm5hbWUpO1xuICAgICAgdXNlci5hdXRoZW50aWNhdGVVc2VyKHRoaXMucHJlcGFyZUF1dGhEZXRhaWxzKHRoaXMuY2hhbGxlbmdlVXNlcm5hbWUsIHRoaXMuY2hhbGxlbmdlUGFzc3dvcmQpLCB7XG4gICAgICAgIG9uU3VjY2VzczogKCk6IHZvaWQgPT4gcmVzb2x2ZSgpLFxuICAgICAgICBvbkZhaWx1cmU6IChlcnI6IEVycm9yKTogdm9pZCA9PiByZWplY3QoZXJyKSxcbiAgICAgICAgbmV3UGFzc3dvcmRSZXF1aXJlZDogKCk6IHZvaWQgPT5cbiAgICAgICAgICB1c2VyLmNvbXBsZXRlTmV3UGFzc3dvcmRDaGFsbGVuZ2UoXG4gICAgICAgICAgICBuZXdQYXNzd29yZCxcbiAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNoYWxsZW5nZVVzZXJuYW1lID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmNoYWxsZW5nZVBhc3N3b3JkID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG9uRmFpbHVyZTogKGVycjogRXJyb3IpOiB2b2lkID0+IHJlamVjdChlcnIpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqICBDb21wbGV0ZSB0aGUgTUZBIGNoYWxsZW5nZSBmbG93IGluIHRoZSBhdXRoZW50aWNhdGlvbi5cbiAgICovXG4gIGNvbXBsZXRlTUZBQ2hhbGxlbmdlKG90cENvZGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICBjb25zdCB1c2VyID0gdGhpcy5wcmVwYXJlQ29nbml0b1VzZXIodGhpcy5jaGFsbGVuZ2VVc2VybmFtZSk7XG4gICAgICB1c2VyLmF1dGhlbnRpY2F0ZVVzZXIodGhpcy5wcmVwYXJlQXV0aERldGFpbHModGhpcy5jaGFsbGVuZ2VVc2VybmFtZSwgdGhpcy5jaGFsbGVuZ2VQYXNzd29yZCksIHtcbiAgICAgICAgb25TdWNjZXNzOiAoKTogdm9pZCA9PiByZXNvbHZlKCksXG4gICAgICAgIG9uRmFpbHVyZTogKGVycjogRXJyb3IpOiB2b2lkID0+IHJlamVjdChlcnIpLFxuICAgICAgICB0b3RwUmVxdWlyZWQ6IChjaGFsbGVuZ2VOYW1lOiBDaGFsbGVuZ2VOYW1lKTogdm9pZCA9PlxuICAgICAgICAgIHVzZXIuc2VuZE1GQUNvZGUoXG4gICAgICAgICAgICBvdHBDb2RlLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNoYWxsZW5nZVVzZXJuYW1lID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmNoYWxsZW5nZVBhc3N3b3JkID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG9uRmFpbHVyZTogZXJyID0+IHJlamVjdChlcnIpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2hhbGxlbmdlTmFtZVxuICAgICAgICAgIClcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIG5ldyB1c2VyIGEgc2V0IGl0cyBkZWZhdWx0IGF0dHJpYnV0ZXMuXG4gICAqL1xuICByZWdpc3Rlcih1c2VybmFtZTogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nLCBhdHRyaWJ1dGVzPzogYW55KTogUHJvbWlzZTxDb2duaXRvVXNlcj4ge1xuICAgIGF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzIHx8IHt9O1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICAvLyBhZGQgYXR0cmlidXRlcyBsaWtlIHRoZSBlbWFpbCBhZGRyZXNzIGFuZCB0aGUgZnVsbG5hbWVcbiAgICAgIGNvbnN0IGF0dHJzID0gW107XG4gICAgICBmb3IgKGNvbnN0IHByb3AgaW4gYXR0cmlidXRlcylcbiAgICAgICAgaWYgKGF0dHJpYnV0ZXNbcHJvcF0pIGF0dHJzLnB1c2godGhpcy5wcmVwYXJlVXNlckF0dHJpYnV0ZShwcm9wLCBhdHRyaWJ1dGVzW3Byb3BdKSk7XG4gICAgICAvLyBhZGQgdGhlIGVtYWlsLCB3aGljaCBpcyBlcXVhbCB0byB0aGUgdXNlcm5hbWUgZm9yIG1vc3Qgb2Ygb3VyIFBvb2xzXG4gICAgICBpZiAoIWF0dHJpYnV0ZXMuZW1haWwpIGF0dHJzLnB1c2godGhpcy5wcmVwYXJlVXNlckF0dHJpYnV0ZSgnZW1haWwnLCB1c2VybmFtZSkpO1xuICAgICAgLy8gcmVnaXN0ZXIgdGhlIG5ldyB1c2VyIHRvIHRoZSBwb29sXG4gICAgICB0aGlzLnVzZXJQb29sLnNpZ25VcCh1c2VybmFtZSwgcGFzc3dvcmQsIGF0dHJzLCBudWxsLCAoZXJyOiBFcnJvciwgcmVzOiBJU2lnblVwUmVzdWx0KTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgdGhpcy5uZXdBY2NvdW50SnVzdFJlZ2lzdGVyZWQgPSB1c2VybmFtZTtcbiAgICAgICAgcmVzb2x2ZShyZXMudXNlcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogSW4gY2FzZSAgbmV3IGFjY291bnQgaGFzIGp1c3QgYmVlbiByZWdpc3RlcmVkLCByZXR1cm4gdGhlIHVzZXJuYW1lLlxuICAgKi9cbiAgZ2V0TmV3QWNjb3VudEp1c3RSZWdpc3RlcmVkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmV3QWNjb3VudEp1c3RSZWdpc3RlcmVkO1xuICB9XG4gIC8qKlxuICAgKiBDb25maXJtIGEgbmV3IHJlZ2lzdHJhdGlvbiB0aHJvdWdoIHRoZSBjb25maXJtYXRpb24gY29kZSBzZW50IGJ5IENvZ25pdG8uXG4gICAqL1xuICBjb25maXJtUmVnaXN0cmF0aW9uKHVzZXJuYW1lOiBzdHJpbmcsIGNvZGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICB0aGlzLnByZXBhcmVDb2duaXRvVXNlcih1c2VybmFtZSkuY29uZmlybVJlZ2lzdHJhdGlvbihjb2RlLCB0cnVlLCAoZXJyOiBFcnJvcik6IHZvaWQgPT5cbiAgICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKClcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIFNlbmQgYWdhaW4gYSBjb25maXJtYXRpb24gY29kZSBmb3IgYSBuZXcgcmVnaXN0cmF0aW9uLlxuICAgKi9cbiAgcmVzZW5kQ29uZmlybWF0aW9uQ29kZSh1c2VybmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIHRoaXMucHJlcGFyZUNvZ25pdG9Vc2VyKHVzZXJuYW1lKS5yZXNlbmRDb25maXJtYXRpb25Db2RlKChlcnI6IEVycm9yKTogdm9pZCA9PiAoZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKCkpKTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogTG9nb3V0IHRoZSBjdXJyZW50bHkgc2lnbmVkLWluIHVzZXIuXG4gICAqL1xuICBsb2dvdXQob3B0aW9ucz86IHsgZ2xvYmFsOiBib29sZWFuIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7IGdsb2JhbDogZmFsc2UgfSwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIC8vIHJlbW92ZSB0aGUgcmVmcmVzaCB0b2tlbiBwcmV2aW9zbHkgc2F2ZWRcbiAgICAgIHRoaXMuc3RvcmFnZS5yZW1vdmUoJ0F1dGhSZWZyZXNoVG9rZW4nKS50aGVuKFxuICAgICAgICAoKTogUHJvbWlzZTx2b2lkPiA9PlxuICAgICAgICAgIC8vIHJlbW92ZSB0aGUgb3B0aW9uYWwgYXV0aCBkZXRhaWxzXG4gICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgnQXV0aFVzZXJEZXRhaWxzJykudGhlbigoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAvLyBnZXQgdGhlIHVzZXIgYW5kIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyUG9vbC5nZXRDdXJyZW50VXNlcigpO1xuICAgICAgICAgICAgdXNlci5nZXRTZXNzaW9uKGFzeW5jIChlcnI6IEVycm9yKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgIC8vIGlmIHRoZSBzZXNzaW9uIGlzIGFjdGl2ZSwgcnVuIHRoZSBvbmxpbmUgc2lnbi1vdXQ7IG90aGVyd2lzZSwgb25seSB0aGUgbG9jYWwgZGF0YSBoYXMgYmVlbiBkZWxldGVkXG4gICAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgIC8vIGlmIGEgcmVmZXJlbmNlIHRvIHRoZSBkZXZpY2Ugd2FzIHNhdmVkLCBmb3JnZXQgaXRcbiAgICAgICAgICAgICAgaWYgKGVudi5pZGVhLmF1dGguc2luZ2xlU2ltdWx0YW5lb3VzU2Vzc2lvbikgYXdhaXQgdGhpcy5zZXRDdXJyZW50RGV2aWNlRm9yUHJvamVjdChudWxsKTtcbiAgICAgICAgICAgICAgLy8gc2lnbi1vdXQgZnJvbSB0aGUgcG9vbCAodGVybWluYXRlIHRoZSBjdXJyZW50IHNlc3Npb24gb3IgYWxsIHRoZSBzZXNzaW9ucylcbiAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZ2xvYmFsKVxuICAgICAgICAgICAgICAgIHVzZXIuZ2xvYmFsU2lnbk91dCh7IG9uU3VjY2VzczogKCk6IHZvaWQgPT4gcmVzb2x2ZSgpLCBvbkZhaWx1cmU6IGVyciA9PiByZWplY3QoZXJyKSB9KTtcbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdXNlci5zaWduT3V0KCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogU2VuZCBhIHBhc3N3b3JkIHJlc2V0IHJlcXVlc3QuXG4gICAqL1xuICBmb3Jnb3RQYXNzd29yZCh1c2VybmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIHRoaXMucHJlcGFyZUNvZ25pdG9Vc2VyKHVzZXJuYW1lKS5mb3Jnb3RQYXNzd29yZCh7XG4gICAgICAgIG9uU3VjY2VzczogKCk6IHZvaWQgPT4gcmVzb2x2ZSgpLFxuICAgICAgICBvbkZhaWx1cmU6IChlcnI6IEVycm9yKTogdm9pZCA9PiByZWplY3QoZXJyKVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIENvbmZpcm0gYSBuZXcgcGFzc3dvcmQgYWZ0ZXIgYSBwYXNzd29yZCByZXNldCByZXF1ZXN0LlxuICAgKi9cbiAgY29uZmlybVBhc3N3b3JkKHVzZXJuYW1lOiBzdHJpbmcsIGNvZGU6IHN0cmluZywgbmV3UHdkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgdGhpcy5wcmVwYXJlQ29nbml0b1VzZXIodXNlcm5hbWUpLmNvbmZpcm1QYXNzd29yZChjb2RlLCBuZXdQd2QsIHtcbiAgICAgICAgb25TdWNjZXNzOiAoKTogdm9pZCA9PiByZXNvbHZlKCksXG4gICAgICAgIG9uRmFpbHVyZTogKGVycjogRXJyb3IpOiB2b2lkID0+IHJlamVjdChlcnIpXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogR2V0cyB0aGUgVVJMIGZvciBlbmFibGluZyBNRkEuIFRoaXMgVVJMIGNhbiBiZSB1c2VkIHRvIGdlbmVyYXRlIGEgUVIgQ29kZSB0byByZWFkIHdpdGggYW4gYXV0aGVudGljYXRvciBhcHAuXG4gICAqL1xuICBnZXRVUkxGb3JFbmFibGluZ01GQSgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyUG9vbC5nZXRDdXJyZW50VXNlcigpO1xuICAgICAgaWYgKCF1c2VyKSByZXR1cm4gcmVqZWN0KCk7XG4gICAgICB1c2VyLmdldFNlc3Npb24oKGVycjogRXJyb3IpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB1c2VyLmFzc29jaWF0ZVNvZnR3YXJlVG9rZW4oe1xuICAgICAgICAgIGFzc29jaWF0ZVNlY3JldENvZGU6IChzZWNyZXRDb2RlOiBzdHJpbmcpOiB2b2lkID0+XG4gICAgICAgICAgICByZXNvbHZlKGBvdHBhdXRoOi8vdG90cC8ke2VuY29kZVVSSSh0aGlzLm1mYVByb2plY3ROYW1lKX0/c2VjcmV0PSR7c2VjcmV0Q29kZX1gKSxcbiAgICAgICAgICBvbkZhaWx1cmU6IChlcnI6IGFueSk6IHZvaWQgPT4gcmVqZWN0KGVycilcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogQ2hlY2sgd2hldGhlciB0aGUgdXNlciBoYXMgTUZBIGVuYWJsZWQuXG4gICAqL1xuICBjaGVja0lmVXNlckhhc01GQUVuYWJsZWQoYnlwYXNzQ2FjaGUgPSBmYWxzZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyUG9vbC5nZXRDdXJyZW50VXNlcigpO1xuICAgICAgaWYgKCF1c2VyKSByZXR1cm4gcmVqZWN0KCk7XG4gICAgICB1c2VyLmdldFNlc3Npb24oKGVycjogRXJyb3IpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB1c2VyLmdldFVzZXJEYXRhKFxuICAgICAgICAgIChlcnIsIGRhdGEpOiB2b2lkID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIGNvbnN0IGlzTUZBRW5hYmxlZCA9ICEhKGRhdGEuVXNlck1GQVNldHRpbmdMaXN0ICYmIGRhdGEuVXNlck1GQVNldHRpbmdMaXN0LmluY2x1ZGVzKCdTT0ZUV0FSRV9UT0tFTl9NRkEnKSk7XG4gICAgICAgICAgICByZXNvbHZlKGlzTUZBRW5hYmxlZCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IGJ5cGFzc0NhY2hlIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBDb25maWd1cmUgYSBNRkEgZGV2aWNlIGZvciB0aGUgdXNlci5cbiAgICovXG4gIHByaXZhdGUgc2V0TUZBRGV2aWNlKG90cDogc3RyaW5nLCBtZmFEZXZpY2VOYW1lOiBzdHJpbmcsIGVuYWJsZWQgPSB0cnVlLCBwcmVmZXJyZWQgPSB0cnVlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IHVzZXIgPSB0aGlzLnVzZXJQb29sLmdldEN1cnJlbnRVc2VyKCk7XG4gICAgICBpZiAoIXVzZXIpIHJldHVybiByZWplY3QoKTtcbiAgICAgIHVzZXIuZ2V0U2Vzc2lvbigoZXJyOiBFcnJvcik6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIHVzZXIudmVyaWZ5U29mdHdhcmVUb2tlbihvdHAsIG1mYURldmljZU5hbWUsIHtcbiAgICAgICAgICBvblN1Y2Nlc3M6ICgpOiB2b2lkID0+XG4gICAgICAgICAgICB1c2VyLnNldFVzZXJNZmFQcmVmZXJlbmNlKG51bGwsIHsgRW5hYmxlZDogZW5hYmxlZCwgUHJlZmVycmVkTWZhOiBwcmVmZXJyZWQgfSwgKGVycjogRXJyb3IpOiB2b2lkID0+XG4gICAgICAgICAgICAgIGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZSgpXG4gICAgICAgICAgICApLFxuICAgICAgICAgIG9uRmFpbHVyZTogKGVycik6IHZvaWQgPT4gcmVqZWN0KGVycilcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogRW5hYmxlIGEgbmV3IE1GQSBkZXZpY2UgZm9yIHRoZSB1c2VyIGJ5IGluc2VydGluZyBhbiBPVFAgY29kZSBnZW5lcmF0ZWQgYnkgaXQuXG4gICAqL1xuICBlbmFibGVNRkEob3RwOiBzdHJpbmcsIG1mYURldmljZU5hbWUgPSAnZGVmYXVsdCcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZXRNRkFEZXZpY2Uob3RwLCBtZmFEZXZpY2VOYW1lLCB0cnVlLCB0cnVlKTtcbiAgfVxuICAvKipcbiAgICogRGlzYWJsZSBNRkEgZm9yIGEgdXNlciBieSBpbnNlcnRpbmcgYW4gT1RQIGNvZGUgZ2VuZXJhdGVkIGJ5IGl0LlxuICAgKi9cbiAgZGlzYWJsZU1GQShvdHA6IHN0cmluZywgbWZhRGV2aWNlTmFtZSA9ICdkZWZhdWx0Jyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnNldE1GQURldmljZShvdHAsIG1mYURldmljZU5hbWUsIGZhbHNlLCBmYWxzZSk7XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgdXNlciBpcyBjdXJyZW50bHkgYXV0aGVudGljYXRlZC5cbiAgICogQHBhcmFtIG9mZmxpbmVBbGxvd2VkIGlmIHNldCBhbmQgaWYgb2ZmbGluZSwgc2tpcCBhdXRoZW50aWNhdGlvbiBhbmQgcmV0cmlldmUgZGF0YSBsb2NhbGx5XG4gICAqIEBwYXJhbSBnZXRGcmVzaElkVG9rZW5PbkV4cCBjYiBmdW5jdGlvbiB0byBleGVjdXRlIHdoZW4gdGhlIGlkVG9rZW4gaXMgcmVmcmVzaGVkXG4gICAqL1xuICBpc0F1dGhlbnRpY2F0ZWQob2ZmbGluZUFsbG93ZWQ6IGJvb2xlYW4sIGdldEZyZXNoSWRUb2tlbk9uRXhwPzogKGZyZXNoSWRUb2tlbjogc3RyaW5nKSA9PiB2b2lkKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKG9mZmxpbmVBbGxvd2VkICYmICFuYXZpZ2F0b3Iub25MaW5lKSB7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5nZXQoJ0F1dGhVc2VyRGV0YWlscycpLnRoZW4odXNlckRldGFpbHMgPT4gcmVzb2x2ZSh7IGlkVG9rZW46IG51bGwsIHVzZXJEZXRhaWxzIH0pKTtcbiAgICAgICAgLy8gcmUtZXhlY3V0ZSB0aGUgbWV0aG9kIHdoZW4gYmFjayBvbmxpbmUsIHNvIHRoYXQgeW91IGNhbiByZXRyaWV2ZSBhIHRva2VuIHRvIG1ha2UgcmVxdWVzdHNcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ29ubGluZScsXG4gICAgICAgICAgKCk6IFByb21pc2U8dm9pZD4gPT5cbiAgICAgICAgICAgIHRoaXMuaXNBdXRoZW50aWNhdGVkKHRydWUsIGdldEZyZXNoSWRUb2tlbk9uRXhwKVxuICAgICAgICAgICAgICAvLyBzZXQgdGhlIG5ldyB0b2tlbiBhcyBpZiBpdCB3YXMgcmVmcmVzaGVkXG4gICAgICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiBnZXRGcmVzaElkVG9rZW5PbkV4cChyZXN1bHQuaWRUb2tlbikpXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyUG9vbC5nZXRDdXJyZW50VXNlcigpO1xuICAgICAgICBpZiAoIXVzZXIpIHJldHVybiByZWplY3QoKTtcbiAgICAgICAgdXNlci5nZXRTZXNzaW9uKChlcnI6IEVycm9yLCBzZXNzaW9uOiBDb2duaXRvVXNlclNlc3Npb24pOiB2b2lkID0+IHtcbiAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgdXNlci5nZXRVc2VyRGF0YShcbiAgICAgICAgICAgIChlcnIsIGRhdGEpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICBjb25zdCBpc01GQUVuYWJsZWQgPSAhIShcbiAgICAgICAgICAgICAgICBkYXRhLlVzZXJNRkFTZXR0aW5nTGlzdCAmJiBkYXRhLlVzZXJNRkFTZXR0aW5nTGlzdC5pbmNsdWRlcygnU09GVFdBUkVfVE9LRU5fTUZBJylcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKCFpc01GQUVuYWJsZWQgJiYgZW52LmlkZWEuYXV0aC5mb3JjZUxvZ2luV2l0aE1GQSlcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihMb2dpbk91dGNvbWVBY3Rpb25zLk1GQV9TRVRVUCkpO1xuICAgICAgICAgICAgICB1c2VyLmdldFVzZXJBdHRyaWJ1dGVzKChlOiBFcnJvciwgYXR0cmlidXRlczogQ29nbml0b1VzZXJBdHRyaWJ1dGVbXSk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlKSByZXR1cm4gcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgIC8vIHJlbWFwIHVzZXIgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGNvbnN0IHVzZXJEZXRhaWxzOiBhbnkgPSB7fTtcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLmZvckVhY2goKGE6IENvZ25pdG9Vc2VyQXR0cmlidXRlKTogc3RyaW5nID0+ICh1c2VyRGV0YWlsc1thLmdldE5hbWUoKV0gPSBhLmdldFZhbHVlKCkpKTtcbiAgICAgICAgICAgICAgICAvLyBhZGQgdGhlIHVzZXIncyBncm91cHMgdG8gdGhlIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uSW5mbyA9IHNlc3Npb24uZ2V0QWNjZXNzVG9rZW4oKS5kZWNvZGVQYXlsb2FkKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBzOiBzdHJpbmdbXSA9IHNlc3Npb25JbmZvWydjb2duaXRvOmdyb3VwcyddIHx8IFtdO1xuICAgICAgICAgICAgICAgIHVzZXJEZXRhaWxzWydncm91cHMnXSA9IGdyb3VwcztcbiAgICAgICAgICAgICAgICAvLyBydW4gc29tZSBjaGVja3MgY29uc2lkZXJpbmcgdGhlIHVzZXIncyBncm91cHMgYW5kIGRldmljZXMgKGJhc2VkIG9uIHRoZSBwcm9qZWN0J3MgY29uZmlndXJhdGlvbilcbiAgICAgICAgICAgICAgICB0aGlzLnJ1blBvc3RBdXRoQ2hlY2tzKHVzZXJEZXRhaWxzLCBlcnIgPT4ge1xuICAgICAgICAgICAgICAgICAgLy8gaW4gY2FzZSBzb21lIGNoZWNrIGZhaWxlZCwgcmVqZWN0IHRoZSBhdXRob3Jpc2F0aW9uIGZsb3dcbiAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgIC8vIChhc3luYykgc2F2ZSB0aGUgcmVmcmVzaCB0b2tlbiBzbyBpdCBjYW4gYmUgYWNjZXNzZWQgYnkgb3RoZXIgcHJvY2VkdXJlc1xuICAgICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnNldCgnQXV0aFJlZnJlc2hUb2tlbicsIHNlc3Npb24uZ2V0UmVmcmVzaFRva2VuKCkuZ2V0VG9rZW4oKSk7XG4gICAgICAgICAgICAgICAgICAvLyBzZXQgYSB0aW1lciB0byBtYW5hZ2UgdGhlIGF1dG9yZWZyZXNoIG9mIHRoZSBpZFRva2VuICh0aHJvdWdoIHRoZSByZWZyZXNoVG9rZW4pXG4gICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgICAgICAgICAoKTogdm9pZCA9PiB0aGlzLnJlZnJlc2hTZXNzaW9uKHVzZXIsIHNlc3Npb24uZ2V0UmVmcmVzaFRva2VuKCkuZ2V0VG9rZW4oKSwgZ2V0RnJlc2hJZFRva2VuT25FeHApLFxuICAgICAgICAgICAgICAgICAgICAxNSAqIDYwICogMTAwMFxuICAgICAgICAgICAgICAgICAgKTsgLy8gZXZlcnkgMTUgbWludXRlc1xuICAgICAgICAgICAgICAgICAgLy8gKGFzeW5jKSBpZiBvZmZsaW5lQWxsb3dlZCwgc2F2ZSBkYXRhIGxvY2FsbHksIHRvIHVzZSBpdCBuZXh0IHRpbWUgd2UnbGwgYmUgb2ZmbGluZVxuICAgICAgICAgICAgICAgICAgaWYgKG9mZmxpbmVBbGxvd2VkKSB0aGlzLnN0b3JhZ2Uuc2V0KCdBdXRoVXNlckRldGFpbHMnLCB1c2VyRGV0YWlscyk7XG4gICAgICAgICAgICAgICAgICAvLyByZXR1cm4gdGhlIGlkVG9rZW4gKHRvIHVzZSB3aXRoIEFQSSlcbiAgICAgICAgICAgICAgICAgIHJlc29sdmUoeyBpZFRva2VuOiBzZXNzaW9uLmdldElkVG9rZW4oKS5nZXRKd3RUb2tlbigpLCB1c2VyRGV0YWlscyB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyBieXBhc3NDYWNoZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIEhlbHBlciB0byByZWZyZXNoIHRoZSBzZXNzaW9uIGV2ZXJ5IE4gbWludXRlcy5cbiAgICovXG4gIHByaXZhdGUgcmVmcmVzaFNlc3Npb24odXNlcjogQ29nbml0b1VzZXIsIHJlZnJlc2hUb2tlbjogc3RyaW5nLCBjYWxsYmFjazogKGZyZXNoSWRUb2tlbjogc3RyaW5nKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdXNlci5yZWZyZXNoU2Vzc2lvbihcbiAgICAgIG5ldyBDb2duaXRvUmVmcmVzaFRva2VuKHsgUmVmcmVzaFRva2VuOiByZWZyZXNoVG9rZW4gfSksXG4gICAgICAoZXJyOiBFcnJvciwgc2Vzc2lvbjogQ29nbml0b1VzZXJTZXNzaW9uKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAvLyB0cnkgYWdhaW4gaW4gMSBtaW51dGVcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpOiB2b2lkID0+IHRoaXMucmVmcmVzaFNlc3Npb24odXNlciwgcmVmcmVzaFRva2VuLCBjYWxsYmFjayksIDEgKiA2MCAqIDEwMDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIChhc3luYykgc2F2ZSB0aGUgcmVmcmVzaCB0b2tlbiBzbyBpdCBjYW4gYmUgYWNjZXNzZWQgYnkgb3RoZXIgcHJvY2VkdXJlc1xuICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ0F1dGhSZWZyZXNoVG9rZW4nLCBzZXNzaW9uLmdldFJlZnJlc2hUb2tlbigpLmdldFRva2VuKCkpO1xuICAgICAgICAgIC8vIHJlcGVhdCBldmVyeSAxNSBtaW51dGVzXG4gICAgICAgICAgc2V0VGltZW91dChcbiAgICAgICAgICAgICgpOiB2b2lkID0+IHRoaXMucmVmcmVzaFNlc3Npb24odXNlciwgc2Vzc2lvbi5nZXRSZWZyZXNoVG9rZW4oKS5nZXRUb2tlbigpLCBjYWxsYmFjayksXG4gICAgICAgICAgICAxNSAqIDYwICogMTAwMFxuICAgICAgICAgICk7XG4gICAgICAgICAgLy8gcnVuIHRoZSBjYWxsYmFjayBhY3Rpb24sIGlmIHNldFxuICAgICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soc2Vzc2lvbi5nZXRJZFRva2VuKCkuZ2V0Snd0VG9rZW4oKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICApO1xuICB9XG4gIC8qKlxuICAgKiBSdW4gc29tZSBwb3N0LWF1dGggY2hlY2tzLCBiYXNlZCBvbiB0aGUgdXNlcnMgZ3JvdXBzIGFuZCBvbiB0aGUgYXBwJ3MgY29uZmlndXJhdGlvbjpcbiAgICogIC0gdXNlcnMgaW4gdGhlIENvZ25pdG8ncyBcImFkbWluc1wiIGdydXAgc2tpcCBhbGwgdGhlIGZvbGxvd2luZyBydWxlcy5cbiAgICogIC0gdXNlcnMgaW4gdGhlIENvZ25pdG8ncyBcInJvYm90c1wiIGdyb3VwIGNhbid0IHNpZ24taW50byBmcm9udC1lbmRzICh0aGV5IHNlcnZlIG9ubHkgYmFjay1lbmQgcHVycG9zZXMpLlxuICAgKiAgLSBpZiBgZW52LmlkZWEuYXV0aC5zaW5nbGVTaW11bHRhbmVvdXNTZXNzaW9uYCBpcyBvbiwgbWFrZSBzdXJlIHRoZXJlIGlzIG9ubHkgb25lIGFjdGl2ZSBzZXNzaW9uIHBlciB1c2VyLlxuICAgKi9cbiAgcHJpdmF0ZSBydW5Qb3N0QXV0aENoZWNrcyh1c2VyRGV0YWlsczogYW55LCBjYWxsYmFjazogKGVycj86IEVycm9yKSA9PiB2b2lkKTogdm9pZCB8IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGdyb3Vwczogc3RyaW5nW10gPSB1c2VyRGV0YWlsc1snZ3JvdXBzJ107XG4gICAgLy8gc2tpcCBjaGVja3MgaWYgdGhlIHVzZXIgaXMgaW4gdGhlIFwiYWRtaW5zXCIgZ3JvdXBcbiAgICBjb25zdCBpc0FkbWluID0gZ3JvdXBzLnNvbWUoeCA9PiB4ID09PSAnYWRtaW5zJyk7XG4gICAgaWYgKGlzQWRtaW4pIHJldHVybiBjYWxsYmFjaygpO1xuICAgIC8vIHVzZXJzIGluIHRoZSBcInJvYm90c1wiIGdyb3VwIGNhbid0IHNpZ24taW50byBmcm9udC1lbmRzICh0aGV5IHNlcnZlIG9ubHkgYmFjay1lbmQgcHVycG9zZXMpXG4gICAgY29uc3QgaXNSb2JvdCA9IGdyb3Vwcy5zb21lKHggPT4geCA9PT0gJ3JvYm90cycpO1xuICAgIGlmIChpc1JvYm90KSByZXR1cm4gY2FsbGJhY2sobmV3IEVycm9yKCdST0JPVF9VU0VSJykpO1xuICAgIC8vIGluIGNhc2UgdGhlIHByb2plY3QgbGltaXRzIGVhY2ggYWNjb3VudCB0byBvbmx5IG9uZSBzaW11bHRhbmVvdXMgc2Vzc2lvbiwgcnVuIGEgY2hlY2tcbiAgICBpZiAoZW52LmlkZWEuYXV0aC5zaW5nbGVTaW11bHRhbmVvdXNTZXNzaW9uKSByZXR1cm4gdGhpcy5jaGVja0ZvclNpbXVsdGFuZW91c1Nlc3Npb25zKHVzZXJEZXRhaWxzLCBjYWxsYmFjayk7XG4gICAgLy8gb3RoZXJ3aXNlLCB3ZSdyZSBkb25lXG4gICAgY2FsbGJhY2soKTtcbiAgfVxuICAvKipcbiAgICogQ2hlY2sgd2hldGhlciB0aGUgdXNlciBzaWduZWQtaW50byBtdWx0aXBsZSBkZXZpY2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0ZvclNpbXVsdGFuZW91c1Nlc3Npb25zKHVzZXJEZXRhaWxzOiBhbnksIGNhbGxiYWNrOiAoZXJyPzogRXJyb3IpID0+IHZvaWQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBnZXQgb3IgY3JlYXRlIGEga2V5IGZvciB0aGUgY3VycmVudCBkZXZpY2UgKH5yYW5kb20pXG4gICAgbGV0IGN1cnJlbnREZXZpY2VLZXkgPSBhd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0KCdBdXRoRGV2aWNlS2V5Jyk7XG4gICAgaWYgKCFjdXJyZW50RGV2aWNlS2V5KSB7XG4gICAgICBjb25zdCByYW5kb21LZXkgPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHJpbmcoMTApO1xuICAgICAgY3VycmVudERldmljZUtleSA9IHJhbmRvbUtleS5jb25jYXQoU3RyaW5nKERhdGUubm93KCkpKTtcbiAgICAgIGF3YWl0IHRoaXMuc3RvcmFnZS5zZXQoJ0F1dGhEZXZpY2VLZXknLCBjdXJyZW50RGV2aWNlS2V5KTtcbiAgICB9XG4gICAgLy8gY2hlY2sgd2hldGhlciB0aGUgbGFzdCBkZXZpY2UgdG8gc2lnbi1pbnRvIHRoaXMgcHJvamVjdCAoaWYgYW55KSBpcyB0aGUgY3VycmVudCBvbmVcbiAgICBjb25zdCBsYXN0RGV2aWNlVG9TaWduSW50b1RoaXNQcm9qZWN0ID0gdXNlckRldGFpbHNbREVWSUNFX0tFWV9BVFRSSUJVVEVdO1xuICAgIC8vIGlmIGl0J3MgdGhlIGZpcnN0IHVzZXIncyBkZXZpY2UgdG8gc2lnbi1pbiwgc2F2ZSB0aGUgcmVmZXJlbmNlIGluIENvZ25pdG8gYW5kIHJlc29sdmVcbiAgICBpZiAoIWxhc3REZXZpY2VUb1NpZ25JbnRvVGhpc1Byb2plY3QpIHtcbiAgICAgIHRoaXMuc2V0Q3VycmVudERldmljZUZvclByb2plY3QoY3VycmVudERldmljZUtleSlcbiAgICAgICAgLnRoZW4oKCk6IHZvaWQgPT4gY2FsbGJhY2soKSlcbiAgICAgICAgLmNhdGNoKCgpOiB2b2lkID0+IGNhbGxiYWNrKG5ldyBFcnJvcignQ0FOVF9TRVRfREVWSUNFJykpKTtcbiAgICAgIC8vIGlmIHRoZSBkZXZpY2UgZGlkbid0IGNoYW5nZSwgcmVzb2x2ZVxuICAgIH0gZWxzZSBpZiAobGFzdERldmljZVRvU2lnbkludG9UaGlzUHJvamVjdCA9PT0gY3VycmVudERldmljZUtleSkgY2FsbGJhY2soKTtcbiAgICAvLyBvdGh3ZXJ3aXNlLCByZXBvcnQgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSBzaW11bHRhbmVvdXMgc2Vzc2lvblxuICAgIGVsc2UgY2FsbGJhY2sobmV3IEVycm9yKCdTSU1VTFRBTkVPVVNfU0VTU0lPTicpKTtcbiAgfVxuICAvKipcbiAgICogU2V0IChvciByZXNldCkgdGhlIGN1cnJlbnQgdXNlcidzIGRldmljZSAoYnkga2V5KSBpbiB0aGUgY3VycmVudCBwcm9qZWN0IChzdG9yZWQgaW4gQ29nbml0bykuXG4gICAqL1xuICBwcml2YXRlIHNldEN1cnJlbnREZXZpY2VGb3JQcm9qZWN0KGRldmljZUtleT86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGF0dHJpYnV0ZXM6IGFueSA9IHt9O1xuICAgIC8vIG5vdGU6IGFuIGVtcHR5IHN0cmluZyB3aWxsIHJlbW92ZSB0aGUgYXR0cmlidXRlIGZyb20gQ29nbml0b1xuICAgIGF0dHJpYnV0ZXNbREVWSUNFX0tFWV9BVFRSSUJVVEVdID0gZGV2aWNlS2V5IHx8ICcnO1xuICAgIHJldHVybiB0aGlzLnVwZGF0ZVVzZXJBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICB9XG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIGN1cnJlbnRseSBsb2dnZWQgaW4gdXNlcidzIGF0dHJpYnV0ZXMuXG4gICAqL1xuICB1cGRhdGVVc2VyQXR0cmlidXRlcyhhdHRyaWJ1dGVzOiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgLy8gcHJlcGFyZSB0aGUgYXR0cmlidXRlcyB3ZSB3YW50IHRvIGNoYW5nZVxuICAgICAgY29uc3QgYXR0cnMgPSBuZXcgQXJyYXk8YW55PigpO1xuICAgICAgZm9yIChjb25zdCBwcm9wIGluIGF0dHJpYnV0ZXMpXG4gICAgICAgIGlmIChhdHRyaWJ1dGVzW3Byb3BdICE9PSB1bmRlZmluZWQpIGF0dHJzLnB1c2godGhpcy5wcmVwYXJlVXNlckF0dHJpYnV0ZShwcm9wLCBhdHRyaWJ1dGVzW3Byb3BdKSk7XG4gICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyUG9vbC5nZXRDdXJyZW50VXNlcigpO1xuICAgICAgaWYgKCF1c2VyKSByZXR1cm4gcmVqZWN0KCk7XG4gICAgICAvLyB3ZSBuZWVkIHRvIGdldCB0aGUgc2Vzc2lvbiBiZWZvcmUgdG8gbWFrZSBjaGFuZ2VzXG4gICAgICB1c2VyLmdldFNlc3Npb24oKGVycjogRXJyb3IpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGVycikgcmVqZWN0KGVycik7XG4gICAgICAgIGVsc2UgdXNlci51cGRhdGVBdHRyaWJ1dGVzKGF0dHJzLCAoZTogRXJyb3IpOiB2b2lkID0+IChlID8gcmVqZWN0KGUpIDogcmVzb2x2ZSgpKSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBwb3NzaWJsZSBhY3Rpb25zIGZvbGxvd2luZyBhIHN1Y2Nlc3NmdWwgbG9naW4uXG4gKi9cbmV4cG9ydCBlbnVtIExvZ2luT3V0Y29tZUFjdGlvbnMge1xuICBOT05FID0gJ25vbmUnLFxuICBORVdfUEFTU1dPUkQgPSAnbmV3UGFzc3dvcmQnLFxuICBNRkFfQ0hBTExFTkdFID0gJ21mYUNoYWxsZW5nZScsXG4gIE1GQV9TRVRVUCA9ICdtZmFTZXR1cCdcbn1cbiJdfQ==
@@ -1,53 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- import * as i1 from "@ionic/angular";
4
- import * as i2 from "@angular/router";
5
- import * as i3 from "@idea-ionic/common";
6
- import * as i4 from "./auth.service";
7
- import * as i5 from "@angular/common";
8
- import * as i6 from "@angular/forms";
9
- export class IDEAConfirmPasswordPage {
10
- constructor(navCtrl, route, message, loading, auth, t) {
11
- this.navCtrl = navCtrl;
12
- this.route = route;
13
- this.message = message;
14
- this.loading = loading;
15
- this.auth = auth;
16
- this.t = t;
17
- }
18
- ngOnInit() {
19
- this.email = this.route.snapshot.queryParamMap.get('email') ?? null;
20
- if (!this.email && this.route.snapshot.queryParams.user)
21
- this.email = decodeURIComponent(this.route.snapshot.queryParams.user);
22
- this.code = this.route.snapshot.queryParams.code;
23
- }
24
- async confirmPassword() {
25
- try {
26
- this.errorMsg = null;
27
- await this.loading.show();
28
- await this.auth.confirmPassword(this.email, this.code, this.newPassword);
29
- this.message.success('IDEA_AUTH.PASSWORD_CHANGED');
30
- this.goToAuth();
31
- }
32
- catch (error) {
33
- this.errorMsg = this.t._('IDEA_AUTH.CONFIRM_PASSWORD_ERROR', { n: 8 });
34
- this.message.error(this.errorMsg, true);
35
- }
36
- finally {
37
- this.loading.hide();
38
- }
39
- }
40
- goToForgotPassword() {
41
- this.navCtrl.navigateBack(['auth/forgot-password']);
42
- }
43
- goToAuth() {
44
- this.navCtrl.navigateBack(['auth']);
45
- }
46
- }
47
- IDEAConfirmPasswordPage.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: IDEAConfirmPasswordPage, deps: [{ token: i1.NavController }, { token: i2.ActivatedRoute }, { token: i3.IDEAMessageService }, { token: i3.IDEALoadingService }, { token: i4.IDEAAuthService }, { token: i3.IDEATranslationsService }], target: i0.ɵɵFactoryTarget.Component });
48
- IDEAConfirmPasswordPage.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: IDEAConfirmPasswordPage, selector: "idea-confirm-password", ngImport: i0, template: "<ion-content>\n <form class=\"flexBox\">\n <ion-card class=\"authCard\">\n <ion-card-header>\n <ion-card-title color=\"primary\">{{ 'IDEA_AUTH.CHANGE_THE_PASSWORD' | translate }}</ion-card-title>\n <ion-card-subtitle>{{ 'IDEA_AUTH.CHANGE_THE_PASSWORD_HINT' | translate: { n: 8 } }}</ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <p class=\"errorBox\" *ngIf=\"errorMsg\">\n <b> {{ 'IDEA_AUTH.ERROR' | translate }}. </b>\n {{ errorMsg }}\n </p>\n <ion-item>\n <ion-label position=\"inline\">\n <ion-icon name=\"person-circle\" color=\"primary\"> </ion-icon>\n </ion-label>\n <ion-input\n type=\"email\"\n inputmode=\"email\"\n pattern=\"[A-Za-z0-9._%+-]{2,}@[a-zA-Z-_.]{2,}[.]{1}[a-zA-Z]{2,}\"\n spellcheck=\"false\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n autocomplete=\"email\"\n [placeholder]=\"'IDEA_AUTH.EMAIL' | translate\"\n [title]=\"'IDEA_AUTH.EMAIL_HINT' | translate\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"email\"\n (keyup.enter)=\"confirmPassword()\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-label position=\"inline\">\n <ion-icon name=\"disc\" color=\"primary\"></ion-icon>\n </ion-label>\n <ion-input\n type=\"text\"\n spellcheck=\"false\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n [placeholder]=\"'IDEA_AUTH.RESET_CODE' | translate\"\n [title]=\"'IDEA_AUTH.RESET_CODE_HINT' | translate\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"code\"\n (keyup.enter)=\"confirmPassword()\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-label position=\"inline\">\n <ion-icon name=\"key\" color=\"primary\"></ion-icon>\n </ion-label>\n <ion-input\n type=\"password\"\n pattern=\".{8,}\"\n spellcheck=\"false\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n autocomplete=\"new-password\"\n [clearOnEdit]=\"false\"\n [placeholder]=\"'IDEA_AUTH.NEW_PASSWORD' | translate\"\n [title]=\"'IDEA_AUTH.CHOOSE_A_PASSWORD' | translate\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"newPassword\"\n (keyup.enter)=\"confirmPassword()\"\n ></ion-input>\n </ion-item>\n <ion-button\n expand=\"block\"\n [title]=\"'IDEA_AUTH.CHANGE_MY_PASSWORD_HINT' | translate\"\n (click)=\"confirmPassword()\"\n >\n {{ 'IDEA_AUTH.CHANGE_MY_PASSWORD' | translate }}\n </ion-button>\n <ion-button\n fill=\"clear\"\n expand=\"block\"\n class=\"smallCaseButton\"\n [title]=\"'IDEA_AUTH.HAVEN_T_RECEIVED_A_RESET_CODE_HINT' | translate\"\n (click)=\"goToForgotPassword()\"\n >\n {{ 'IDEA_AUTH.HAVEN_T_RECEIVED_A_RESET_CODE' | translate }}\n </ion-button>\n <ion-button\n fill=\"clear\"\n expand=\"block\"\n class=\"smallCaseButton\"\n [title]=\"'IDEA_AUTH.BACK_TO_SIGN_IN_HINT' | translate\"\n (click)=\"goToAuth()\"\n >\n {{ 'IDEA_AUTH.BACK_TO_SIGN_IN' | translate }}\n </ion-button>\n </ion-card-content>\n </ion-card>\n </form>\n</ion-content>\n", styles: [".flexBox{background:var(--idea-auth-background-color, var(--ion-color-white-shade))}.authCard{min-width:400px;max-width:550px;margin:0 10px;padding:20px;background-color:var(--idea-auth-card-background-color, var(--ion-color-white));border:1px solid var(--idea-auth-card-border-color, var(--ion-color-light));border-radius:10px;box-shadow:none;text-align:center}.authCard ion-img{width:150px;display:block;margin:0 auto}.authCard ion-card-title{font-family:auth-title;font-size:3em}.authCard ion-card-subtitle{font-family:auth-title;font-size:1.2em}.authCard ion-card-content{padding-top:16px}.authCard ion-card-content .errorBox{padding-left:10px;margin-bottom:20px;text-align:left;border-left:2px solid var(--ion-color-danger)}.authCard ion-card-content ion-item{--ion-item-background: var(--idea-auth-card-background-color, var(--ion-color-white));--border-color: var(--idea-auth-card-border-color, var(--ion-color-light))}.authCard ion-card-content ion-icon{padding-top:4px;padding-right:5px;font-size:1.3em}.authCard ion-card-content .agreementsAcceptanceRow{margin-top:15px;font-size:.9em}.authCard ion-card-content .agreementsAcceptanceRow ion-checkbox{vertical-align:bottom;margin-right:3px}.authCard ion-card-content ion-button{margin-top:15px}.authCard ion-card-content .smallCaseButton{text-transform:none;letter-spacing:normal;font-size:1em}@media only screen and (max-width: 500px){.authCard{background-color:transparent;border:none}}.ideaLogo{width:65px;margin:40px auto 0;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i1.IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: i1.IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i1.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "pipe", type: i3.IDEATranslatePipe, name: "translate" }] });
49
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: IDEAConfirmPasswordPage, decorators: [{
50
- type: Component,
51
- args: [{ selector: 'idea-confirm-password', template: "<ion-content>\n <form class=\"flexBox\">\n <ion-card class=\"authCard\">\n <ion-card-header>\n <ion-card-title color=\"primary\">{{ 'IDEA_AUTH.CHANGE_THE_PASSWORD' | translate }}</ion-card-title>\n <ion-card-subtitle>{{ 'IDEA_AUTH.CHANGE_THE_PASSWORD_HINT' | translate: { n: 8 } }}</ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <p class=\"errorBox\" *ngIf=\"errorMsg\">\n <b> {{ 'IDEA_AUTH.ERROR' | translate }}. </b>\n {{ errorMsg }}\n </p>\n <ion-item>\n <ion-label position=\"inline\">\n <ion-icon name=\"person-circle\" color=\"primary\"> </ion-icon>\n </ion-label>\n <ion-input\n type=\"email\"\n inputmode=\"email\"\n pattern=\"[A-Za-z0-9._%+-]{2,}@[a-zA-Z-_.]{2,}[.]{1}[a-zA-Z]{2,}\"\n spellcheck=\"false\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n autocomplete=\"email\"\n [placeholder]=\"'IDEA_AUTH.EMAIL' | translate\"\n [title]=\"'IDEA_AUTH.EMAIL_HINT' | translate\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"email\"\n (keyup.enter)=\"confirmPassword()\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-label position=\"inline\">\n <ion-icon name=\"disc\" color=\"primary\"></ion-icon>\n </ion-label>\n <ion-input\n type=\"text\"\n spellcheck=\"false\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n [placeholder]=\"'IDEA_AUTH.RESET_CODE' | translate\"\n [title]=\"'IDEA_AUTH.RESET_CODE_HINT' | translate\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"code\"\n (keyup.enter)=\"confirmPassword()\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-label position=\"inline\">\n <ion-icon name=\"key\" color=\"primary\"></ion-icon>\n </ion-label>\n <ion-input\n type=\"password\"\n pattern=\".{8,}\"\n spellcheck=\"false\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n autocomplete=\"new-password\"\n [clearOnEdit]=\"false\"\n [placeholder]=\"'IDEA_AUTH.NEW_PASSWORD' | translate\"\n [title]=\"'IDEA_AUTH.CHOOSE_A_PASSWORD' | translate\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"newPassword\"\n (keyup.enter)=\"confirmPassword()\"\n ></ion-input>\n </ion-item>\n <ion-button\n expand=\"block\"\n [title]=\"'IDEA_AUTH.CHANGE_MY_PASSWORD_HINT' | translate\"\n (click)=\"confirmPassword()\"\n >\n {{ 'IDEA_AUTH.CHANGE_MY_PASSWORD' | translate }}\n </ion-button>\n <ion-button\n fill=\"clear\"\n expand=\"block\"\n class=\"smallCaseButton\"\n [title]=\"'IDEA_AUTH.HAVEN_T_RECEIVED_A_RESET_CODE_HINT' | translate\"\n (click)=\"goToForgotPassword()\"\n >\n {{ 'IDEA_AUTH.HAVEN_T_RECEIVED_A_RESET_CODE' | translate }}\n </ion-button>\n <ion-button\n fill=\"clear\"\n expand=\"block\"\n class=\"smallCaseButton\"\n [title]=\"'IDEA_AUTH.BACK_TO_SIGN_IN_HINT' | translate\"\n (click)=\"goToAuth()\"\n >\n {{ 'IDEA_AUTH.BACK_TO_SIGN_IN' | translate }}\n </ion-button>\n </ion-card-content>\n </ion-card>\n </form>\n</ion-content>\n", styles: [".flexBox{background:var(--idea-auth-background-color, var(--ion-color-white-shade))}.authCard{min-width:400px;max-width:550px;margin:0 10px;padding:20px;background-color:var(--idea-auth-card-background-color, var(--ion-color-white));border:1px solid var(--idea-auth-card-border-color, var(--ion-color-light));border-radius:10px;box-shadow:none;text-align:center}.authCard ion-img{width:150px;display:block;margin:0 auto}.authCard ion-card-title{font-family:auth-title;font-size:3em}.authCard ion-card-subtitle{font-family:auth-title;font-size:1.2em}.authCard ion-card-content{padding-top:16px}.authCard ion-card-content .errorBox{padding-left:10px;margin-bottom:20px;text-align:left;border-left:2px solid var(--ion-color-danger)}.authCard ion-card-content ion-item{--ion-item-background: var(--idea-auth-card-background-color, var(--ion-color-white));--border-color: var(--idea-auth-card-border-color, var(--ion-color-light))}.authCard ion-card-content ion-icon{padding-top:4px;padding-right:5px;font-size:1.3em}.authCard ion-card-content .agreementsAcceptanceRow{margin-top:15px;font-size:.9em}.authCard ion-card-content .agreementsAcceptanceRow ion-checkbox{vertical-align:bottom;margin-right:3px}.authCard ion-card-content ion-button{margin-top:15px}.authCard ion-card-content .smallCaseButton{text-transform:none;letter-spacing:normal;font-size:1em}@media only screen and (max-width: 500px){.authCard{background-color:transparent;border:none}}.ideaLogo{width:65px;margin:40px auto 0;cursor:pointer}\n"] }]
52
- }], ctorParameters: function () { return [{ type: i1.NavController }, { type: i2.ActivatedRoute }, { type: i3.IDEAMessageService }, { type: i3.IDEALoadingService }, { type: i4.IDEAAuthService }, { type: i3.IDEATranslationsService }]; } });
53
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlybVBhc3N3b3JkLnBhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9tb2R1bGVzL2F1dGgvc3JjL2NvbmZpcm1QYXNzd29yZC5wYWdlLnRzIiwiLi4vLi4vLi4vLi4vbW9kdWxlcy9hdXRoL3NyYy9jb25maXJtUGFzc3dvcmQucGFnZS5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxlQUFlLENBQUM7Ozs7Ozs7O0FBWWxELE1BQU0sT0FBTyx1QkFBdUI7SUFNbEMsWUFDVSxPQUFzQixFQUN0QixLQUFxQixFQUNyQixPQUEyQixFQUMzQixPQUEyQixFQUMzQixJQUFxQixFQUNyQixDQUEwQjtRQUwxQixZQUFPLEdBQVAsT0FBTyxDQUFlO1FBQ3RCLFVBQUssR0FBTCxLQUFLLENBQWdCO1FBQ3JCLFlBQU8sR0FBUCxPQUFPLENBQW9CO1FBQzNCLFlBQU8sR0FBUCxPQUFPLENBQW9CO1FBQzNCLFNBQUksR0FBSixJQUFJLENBQWlCO1FBQ3JCLE1BQUMsR0FBRCxDQUFDLENBQXlCO0lBQ2pDLENBQUM7SUFDSixRQUFRO1FBQ04sSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQztRQUNwRSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSTtZQUNyRCxJQUFJLENBQUMsS0FBSyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4RSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7SUFDbkQsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlO1FBQ25CLElBQUk7WUFDRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNyQixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDMUIsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3pFLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLDRCQUE0QixDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1NBQ2pCO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGtDQUFrQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN6QztnQkFBUztZQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDckI7SUFDSCxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFDRCxRQUFRO1FBQ04sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7O29IQXpDVSx1QkFBdUI7d0dBQXZCLHVCQUF1Qiw2RENacEMsMmxIQWdHQTsyRkRwRmEsdUJBQXVCO2tCQUxuQyxTQUFTOytCQUNFLHVCQUF1QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOYXZDb250cm9sbGVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgSURFQU1lc3NhZ2VTZXJ2aWNlLCBJREVBTG9hZGluZ1NlcnZpY2UsIElERUFUcmFuc2xhdGlvbnNTZXJ2aWNlIH0gZnJvbSAnQGlkZWEtaW9uaWMvY29tbW9uJztcblxuaW1wb3J0IHsgSURFQUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9hdXRoLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdpZGVhLWNvbmZpcm0tcGFzc3dvcmQnLFxuICB0ZW1wbGF0ZVVybDogJ2NvbmZpcm1QYXNzd29yZC5wYWdlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnYXV0aC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgSURFQUNvbmZpcm1QYXNzd29yZFBhZ2UgaW1wbGVtZW50cyBPbkluaXQge1xuICBlbWFpbDogc3RyaW5nO1xuICBuZXdQYXNzd29yZDogc3RyaW5nO1xuICBjb2RlOiBzdHJpbmc7XG4gIGVycm9yTXNnOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBuYXZDdHJsOiBOYXZDb250cm9sbGVyLFxuICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgIHByaXZhdGUgbWVzc2FnZTogSURFQU1lc3NhZ2VTZXJ2aWNlLFxuICAgIHByaXZhdGUgbG9hZGluZzogSURFQUxvYWRpbmdTZXJ2aWNlLFxuICAgIHByaXZhdGUgYXV0aDogSURFQUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgdDogSURFQVRyYW5zbGF0aW9uc1NlcnZpY2VcbiAgKSB7fVxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmVtYWlsID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtTWFwLmdldCgnZW1haWwnKSA/PyBudWxsO1xuICAgIGlmICghdGhpcy5lbWFpbCAmJiB0aGlzLnJvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zLnVzZXIpXG4gICAgICB0aGlzLmVtYWlsID0gZGVjb2RlVVJJQ29tcG9uZW50KHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXMudXNlcik7XG4gICAgdGhpcy5jb2RlID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcy5jb2RlO1xuICB9XG5cbiAgYXN5bmMgY29uZmlybVBhc3N3b3JkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmVycm9yTXNnID0gbnVsbDtcbiAgICAgIGF3YWl0IHRoaXMubG9hZGluZy5zaG93KCk7XG4gICAgICBhd2FpdCB0aGlzLmF1dGguY29uZmlybVBhc3N3b3JkKHRoaXMuZW1haWwsIHRoaXMuY29kZSwgdGhpcy5uZXdQYXNzd29yZCk7XG4gICAgICB0aGlzLm1lc3NhZ2Uuc3VjY2VzcygnSURFQV9BVVRILlBBU1NXT1JEX0NIQU5HRUQnKTtcbiAgICAgIHRoaXMuZ29Ub0F1dGgoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5lcnJvck1zZyA9IHRoaXMudC5fKCdJREVBX0FVVEguQ09ORklSTV9QQVNTV09SRF9FUlJPUicsIHsgbjogOCB9KTtcbiAgICAgIHRoaXMubWVzc2FnZS5lcnJvcih0aGlzLmVycm9yTXNnLCB0cnVlKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5sb2FkaW5nLmhpZGUoKTtcbiAgICB9XG4gIH1cblxuICBnb1RvRm9yZ290UGFzc3dvcmQoKTogdm9pZCB7XG4gICAgdGhpcy5uYXZDdHJsLm5hdmlnYXRlQmFjayhbJ2F1dGgvZm9yZ290LXBhc3N3b3JkJ10pO1xuICB9XG4gIGdvVG9BdXRoKCk6IHZvaWQge1xuICAgIHRoaXMubmF2Q3RybC5uYXZpZ2F0ZUJhY2soWydhdXRoJ10pO1xuICB9XG59XG4iLCI8aW9uLWNvbnRlbnQ+XG4gIDxmb3JtIGNsYXNzPVwiZmxleEJveFwiPlxuICAgIDxpb24tY2FyZCBjbGFzcz1cImF1dGhDYXJkXCI+XG4gICAgICA8aW9uLWNhcmQtaGVhZGVyPlxuICAgICAgICA8aW9uLWNhcmQtdGl0bGUgY29sb3I9XCJwcmltYXJ5XCI+e3sgJ0lERUFfQVVUSC5DSEFOR0VfVEhFX1BBU1NXT1JEJyB8IHRyYW5zbGF0ZSB9fTwvaW9uLWNhcmQtdGl0bGU+XG4gICAgICAgIDxpb24tY2FyZC1zdWJ0aXRsZT57eyAnSURFQV9BVVRILkNIQU5HRV9USEVfUEFTU1dPUkRfSElOVCcgfCB0cmFuc2xhdGU6IHsgbjogOCB9IH19PC9pb24tY2FyZC1zdWJ0aXRsZT5cbiAgICAgIDwvaW9uLWNhcmQtaGVhZGVyPlxuICAgICAgPGlvbi1jYXJkLWNvbnRlbnQ+XG4gICAgICAgIDxwIGNsYXNzPVwiZXJyb3JCb3hcIiAqbmdJZj1cImVycm9yTXNnXCI+XG4gICAgICAgICAgPGI+IHt7ICdJREVBX0FVVEguRVJST1InIHwgdHJhbnNsYXRlIH19LiA8L2I+XG4gICAgICAgICAge3sgZXJyb3JNc2cgfX1cbiAgICAgICAgPC9wPlxuICAgICAgICA8aW9uLWl0ZW0+XG4gICAgICAgICAgPGlvbi1sYWJlbCBwb3NpdGlvbj1cImlubGluZVwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJwZXJzb24tY2lyY2xlXCIgY29sb3I9XCJwcmltYXJ5XCI+IDwvaW9uLWljb24+XG4gICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPGlvbi1pbnB1dFxuICAgICAgICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgICAgICAgIGlucHV0bW9kZT1cImVtYWlsXCJcbiAgICAgICAgICAgIHBhdHRlcm49XCJbQS1aYS16MC05Ll8lKy1dezIsfUBbYS16QS1aLV8uXXsyLH1bLl17MX1bYS16QS1aXXsyLH1cIlxuICAgICAgICAgICAgc3BlbGxjaGVjaz1cImZhbHNlXCJcbiAgICAgICAgICAgIGF1dG9jb3JyZWN0PVwib2ZmXCJcbiAgICAgICAgICAgIGF1dG9jYXBpdGFsaXplPVwib2ZmXCJcbiAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInSURFQV9BVVRILkVNQUlMJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbdGl0bGVdPVwiJ0lERUFfQVVUSC5FTUFJTF9ISU5UJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwieyBzdGFuZGFsb25lOiB0cnVlIH1cIlxuICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJlbWFpbFwiXG4gICAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwiY29uZmlybVBhc3N3b3JkKClcIlxuICAgICAgICAgID48L2lvbi1pbnB1dD5cbiAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgPGlvbi1pdGVtPlxuICAgICAgICAgIDxpb24tbGFiZWwgcG9zaXRpb249XCJpbmxpbmVcIj5cbiAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwiZGlzY1wiIGNvbG9yPVwicHJpbWFyeVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPGlvbi1pbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgc3BlbGxjaGVjaz1cImZhbHNlXCJcbiAgICAgICAgICAgIGF1dG9jb3JyZWN0PVwib2ZmXCJcbiAgICAgICAgICAgIGF1dG9jYXBpdGFsaXplPVwib2ZmXCJcbiAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ0lERUFfQVVUSC5SRVNFVF9DT0RFJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbdGl0bGVdPVwiJ0lERUFfQVVUSC5SRVNFVF9DT0RFX0hJTlQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7IHN0YW5kYWxvbmU6IHRydWUgfVwiXG4gICAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvZGVcIlxuICAgICAgICAgICAgKGtleXVwLmVudGVyKT1cImNvbmZpcm1QYXNzd29yZCgpXCJcbiAgICAgICAgICA+PC9pb24taW5wdXQ+XG4gICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgIDxpb24taXRlbT5cbiAgICAgICAgICA8aW9uLWxhYmVsIHBvc2l0aW9uPVwiaW5saW5lXCI+XG4gICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImtleVwiIGNvbG9yPVwicHJpbWFyeVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPGlvbi1pbnB1dFxuICAgICAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgIHBhdHRlcm49XCIuezgsfVwiXG4gICAgICAgICAgICBzcGVsbGNoZWNrPVwiZmFsc2VcIlxuICAgICAgICAgICAgYXV0b2NvcnJlY3Q9XCJvZmZcIlxuICAgICAgICAgICAgYXV0b2NhcGl0YWxpemU9XCJvZmZcIlxuICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwibmV3LXBhc3N3b3JkXCJcbiAgICAgICAgICAgIFtjbGVhck9uRWRpdF09XCJmYWxzZVwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ0lERUFfQVVUSC5ORVdfUEFTU1dPUkQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgIFt0aXRsZV09XCInSURFQV9BVVRILkNIT09TRV9BX1BBU1NXT1JEJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwieyBzdGFuZGFsb25lOiB0cnVlIH1cIlxuICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJuZXdQYXNzd29yZFwiXG4gICAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwiY29uZmlybVBhc3N3b3JkKClcIlxuICAgICAgICAgID48L2lvbi1pbnB1dD5cbiAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgICBleHBhbmQ9XCJibG9ja1wiXG4gICAgICAgICAgW3RpdGxlXT1cIidJREVBX0FVVEguQ0hBTkdFX01ZX1BBU1NXT1JEX0hJTlQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAoY2xpY2spPVwiY29uZmlybVBhc3N3b3JkKClcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ0lERUFfQVVUSC5DSEFOR0VfTVlfUEFTU1dPUkQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgICBmaWxsPVwiY2xlYXJcIlxuICAgICAgICAgIGV4cGFuZD1cImJsb2NrXCJcbiAgICAgICAgICBjbGFzcz1cInNtYWxsQ2FzZUJ1dHRvblwiXG4gICAgICAgICAgW3RpdGxlXT1cIidJREVBX0FVVEguSEFWRU5fVF9SRUNFSVZFRF9BX1JFU0VUX0NPREVfSElOVCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIChjbGljayk9XCJnb1RvRm9yZ290UGFzc3dvcmQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyAnSURFQV9BVVRILkhBVkVOX1RfUkVDRUlWRURfQV9SRVNFVF9DT0RFJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgIDxpb24tYnV0dG9uXG4gICAgICAgICAgZmlsbD1cImNsZWFyXCJcbiAgICAgICAgICBleHBhbmQ9XCJibG9ja1wiXG4gICAgICAgICAgY2xhc3M9XCJzbWFsbENhc2VCdXR0b25cIlxuICAgICAgICAgIFt0aXRsZV09XCInSURFQV9BVVRILkJBQ0tfVE9fU0lHTl9JTl9ISU5UJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgKGNsaWNrKT1cImdvVG9BdXRoKClcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ0lERUFfQVVUSC5CQUNLX1RPX1NJR05fSU4nIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgIDwvaW9uLWNhcmQtY29udGVudD5cbiAgICA8L2lvbi1jYXJkPlxuICA8L2Zvcm0+XG48L2lvbi1jb250ZW50PlxuIl19