@atlasauth/angular 0.7.0 → 0.9.0

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 (39) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/esm2022/lib/appearance.mjs +1 -1
  3. package/dist/esm2022/lib/atlas.service.mjs +45 -4
  4. package/dist/esm2022/lib/atlas.ui.mjs +3 -1
  5. package/dist/esm2022/lib/components/attempt-flow.component.mjs +398 -8
  6. package/dist/esm2022/lib/components/flow-controller.mjs +127 -7
  7. package/dist/esm2022/lib/components/impersonation-banner.component.mjs +75 -0
  8. package/dist/esm2022/lib/components/organization-audit-log.component.mjs +115 -0
  9. package/dist/esm2022/lib/components/organization-audit-log.mjs +40 -0
  10. package/dist/esm2022/lib/components/organization-profile.component.mjs +602 -27
  11. package/dist/esm2022/lib/components/recovery-codes.component.mjs +122 -0
  12. package/dist/esm2022/lib/components/sign-in.component.mjs +85 -4
  13. package/dist/esm2022/lib/components/sign-up-form.component.mjs +69 -6
  14. package/dist/esm2022/lib/components/sign-up.component.mjs +83 -7
  15. package/dist/esm2022/lib/i18n.mjs +60 -1
  16. package/dist/esm2022/lib/provide-atlas.mjs +3 -2
  17. package/dist/esm2022/lib/types.mjs +1 -1
  18. package/dist/esm2022/lib/version.mjs +2 -2
  19. package/dist/esm2022/public-api.mjs +4 -1
  20. package/dist/fesm2022/atlasauth-angular.mjs +1798 -65
  21. package/dist/fesm2022/atlasauth-angular.mjs.map +1 -1
  22. package/dist/lib/appearance.d.ts +1 -1
  23. package/dist/lib/atlas.service.d.ts +24 -2
  24. package/dist/lib/atlas.ui.d.ts +2 -1
  25. package/dist/lib/components/attempt-flow.component.d.ts +60 -3
  26. package/dist/lib/components/flow-controller.d.ts +65 -2
  27. package/dist/lib/components/impersonation-banner.component.d.ts +27 -0
  28. package/dist/lib/components/organization-audit-log.component.d.ts +34 -0
  29. package/dist/lib/components/organization-audit-log.d.ts +25 -0
  30. package/dist/lib/components/organization-profile.component.d.ts +55 -6
  31. package/dist/lib/components/recovery-codes.component.d.ts +26 -0
  32. package/dist/lib/components/sign-in.component.d.ts +11 -1
  33. package/dist/lib/components/sign-up-form.component.d.ts +11 -1
  34. package/dist/lib/components/sign-up.component.d.ts +13 -0
  35. package/dist/lib/provide-atlas.d.ts +2 -1
  36. package/dist/lib/types.d.ts +6 -0
  37. package/dist/lib/version.d.ts +1 -1
  38. package/dist/public-api.d.ts +4 -0
  39. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, inject, } from '@angular/core';
2
- import { localizedErrorMessage, nextStep, } from '@atlasauth/js';
2
+ import { awaitingSignUpLink, enrollmentSubmitKey, groupSetupKey, localizedErrorMessage, nextStep, } from '@atlasauth/js';
3
3
  import { AtlasService } from '../atlas.service';
4
4
  import { AtlasCaptchaSlotDirective } from '../directives/captcha-slot.directive';
5
5
  import { classFor } from '../appearance';
@@ -20,6 +20,8 @@ export class AttemptFlowComponent {
20
20
  attempt = null;
21
21
  busy = false;
22
22
  errors = [];
23
+ /** `FlowState.sessionKept`: whether this browser kept the session the sign-in created. */
24
+ sessionKept = undefined;
23
25
  titleKey = 'signIn.title';
24
26
  /**
25
27
  * The sign-in captcha, drawn above the submit button on the identifier step
@@ -39,6 +41,38 @@ export class AttemptFlowComponent {
39
41
  submitFlow = new EventEmitter();
40
42
  /** Emits when the user picks a first factor the server must send first (an emailed code). */
41
43
  chooseFactor = new EventEmitter();
44
+ /**
45
+ * Offer "Email me a code instead" at the second factor (the instance's
46
+ * `account.emailSecondFactor`); `emailSecondFactor` asks for it and
47
+ * `emailedSecondFactor` reports how it went.
48
+ */
49
+ offerEmailSecondFactor = false;
50
+ /** `AtlasFlowController.emailSecondFactor()`: in flight, where it went, or why not. */
51
+ emailedSecondFactor = null;
52
+ emailSecondFactor = new EventEmitter();
53
+ /**
54
+ * Offer "Text me a code instead" at the second factor (where the app offers
55
+ * texted codes, `AtlasFlowController.mfaChoices().sms`); `smsSecondFactor`
56
+ * asks for it and `textedSecondFactor` reports how it went.
57
+ */
58
+ offerSmsSecondFactor = false;
59
+ /** `AtlasFlowController.smsSecondFactor()`: in flight, where it went, or why not. */
60
+ textedSecondFactor = null;
61
+ smsSecondFactor = new EventEmitter();
62
+ /**
63
+ * The MFA enrolment step (`AtlasFlowController.enrollment` and
64
+ * `enrollmentState()`): the authenticator app's QR code and setup key, or a
65
+ * texted code. Null: the step asks for two authenticator codes only.
66
+ */
67
+ enrollment = null;
68
+ enrollmentState = null;
69
+ /**
70
+ * The instance's `account.emailVerification`. On `link` a sign-up's
71
+ * verification step has nothing to type: it says to open the emailed link
72
+ * while the flow polls, and offers a resend (`resend`).
73
+ */
74
+ emailVerification = 'code';
75
+ resend = new EventEmitter();
42
76
  values = {};
43
77
  t(key, vars) {
44
78
  return translate(this.atlas.localization, key, vars);
@@ -57,8 +91,45 @@ export class AttemptFlowComponent {
57
91
  }
58
92
  onSubmit(event) {
59
93
  event.preventDefault();
94
+ // Enrolment: text the code to the typed number, or confirm the factor.
95
+ if (this.enrolling() && this.enrollment) {
96
+ void this.enrollment.submit(this.values).then((next) => {
97
+ if (next)
98
+ this.submitFlow.emit(next);
99
+ });
100
+ return;
101
+ }
60
102
  this.submitFlow.emit(this.values);
61
103
  }
104
+ /** The shared enrolment step is drawn (a controller was passed and the flow is enrolling). */
105
+ enrolling() {
106
+ return this.step().kind === 'enroll_second_factor' && !!this.enrollment && !!this.enrollmentState;
107
+ }
108
+ chooseMethod(method) {
109
+ this.values = {};
110
+ void this.enrollment?.choose(method);
111
+ }
112
+ resendEnrollment() {
113
+ void this.enrollment?.resend();
114
+ }
115
+ otherMethods(state) {
116
+ return state.options.filter((m) => m !== state.method);
117
+ }
118
+ setupKey(secret) {
119
+ return groupSetupKey(secret);
120
+ }
121
+ /** The submit button's label key (enrolment: "Text me a code" before the number is sent). */
122
+ submitKey() {
123
+ return (this.enrolling() && this.enrollmentState && enrollmentSubmitKey(this.enrollmentState)) || 'signIn.submit';
124
+ }
125
+ showSmsSecondFactor() {
126
+ return this.offerSmsSecondFactor && this.step().kind === 'collect_second_factor';
127
+ }
128
+ /** Where the texted second-factor code went (masked), once it was sent. */
129
+ smsSecondFactorSentTo() {
130
+ const sent = this.textedSecondFactor?.sentTo;
131
+ return typeof sent === 'string' ? sent || ' ' : null;
132
+ }
62
133
  formErrors() {
63
134
  return this.errors.filter((error) => !error.param);
64
135
  }
@@ -79,6 +150,17 @@ export class AttemptFlowComponent {
79
150
  return [];
80
151
  return this.firstFactors ?? step.strategies;
81
152
  }
153
+ linkOnly() {
154
+ return awaitingSignUpLink(this.attempt, this.emailVerification);
155
+ }
156
+ showEmailSecondFactor() {
157
+ return this.offerEmailSecondFactor && this.step().kind === 'collect_second_factor';
158
+ }
159
+ /** Where the emailed second-factor code went (masked), once it was sent. */
160
+ emailSecondFactorSentTo() {
161
+ const sent = this.emailedSecondFactor?.sentTo;
162
+ return typeof sent === 'string' ? sent || ' ' : null;
163
+ }
82
164
  showEmailCodeOption() {
83
165
  // Before the code is sent: the choice (or the retry of a failed automatic
84
166
  // send). After: "Resend code".
@@ -96,6 +178,11 @@ export class AttemptFlowComponent {
96
178
  // until that code is sent.
97
179
  if (kind === 'collect_first_factor')
98
180
  return this.fields().length > 0;
181
+ if (this.linkOnly())
182
+ return false;
183
+ // Enrolment: nothing to submit while choosing a method or fetching the setup.
184
+ if (this.enrolling() && this.enrollmentState && !enrollmentSubmitKey(this.enrollmentState))
185
+ return false;
99
186
  return kind !== 'done' && kind !== 'await_oauth';
100
187
  }
101
188
  fields() {
@@ -117,6 +204,9 @@ export class AttemptFlowComponent {
117
204
  case 'collect_second_factor':
118
205
  return [{ kind: 'input', name: 'code', labelKey: 'mfa.codeLabel', type: 'text' }];
119
206
  case 'enroll_second_factor':
207
+ // The shared enrolment step draws its own fields (above).
208
+ if (this.enrolling())
209
+ return [];
120
210
  // Two consecutive codes (§5.6): a phone with a fast clock fails here
121
211
  // rather than on every sign-in afterwards.
122
212
  return [
@@ -124,7 +214,7 @@ export class AttemptFlowComponent {
124
214
  { kind: 'input', name: 'secondCode', labelKey: 'mfa.enrollSecondCodeLabel', type: 'text' },
125
215
  ];
126
216
  case 'collect_email_code':
127
- return [{ kind: 'input', name: 'code', labelKey: 'signIn.emailCodeLabel', type: 'text' }];
217
+ return this.linkOnly() ? [] : [{ kind: 'input', name: 'code', labelKey: 'signIn.emailCodeLabel', type: 'text' }];
128
218
  case 'collect_new_password':
129
219
  return [{ kind: 'input', name: 'password', labelKey: 'reset.newPasswordLabel', type: 'password' }];
130
220
  case 'collect_captcha':
@@ -134,6 +224,12 @@ export class AttemptFlowComponent {
134
224
  case 'await_oauth':
135
225
  return [msg('signIn.magicLinkSent')];
136
226
  case 'done':
227
+ // Signed in only when this browser holds the session; a blocked cookie is said
228
+ // plainly. "Check the other tab" is for a sign-in completed on another device.
229
+ if (this.sessionKept === true)
230
+ return [msg('signIn.signedIn')];
231
+ if (this.sessionKept === false)
232
+ return [{ kind: 'alert', name: '', labelKey: 'signIn.sessionNotKept', type: 'text' }];
137
233
  return [msg('signIn.checkOtherTab')];
138
234
  case 'restart':
139
235
  return [msg('error.generic')];
@@ -144,7 +240,7 @@ export class AttemptFlowComponent {
144
240
  }
145
241
  }
146
242
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AttemptFlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
147
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: AttemptFlowComponent, isStandalone: true, selector: "atlas-attempt-flow", inputs: { attempt: "attempt", busy: "busy", errors: "errors", titleKey: "titleKey", captcha: "captcha", firstFactors: "firstFactors", preparedFactor: "preparedFactor" }, outputs: { submitFlow: "submitFlow", chooseFactor: "chooseFactor" }, ngImport: i0, template: `
243
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: AttemptFlowComponent, isStandalone: true, selector: "atlas-attempt-flow", inputs: { attempt: "attempt", busy: "busy", errors: "errors", sessionKept: "sessionKept", titleKey: "titleKey", captcha: "captcha", firstFactors: "firstFactors", preparedFactor: "preparedFactor", offerEmailSecondFactor: "offerEmailSecondFactor", emailedSecondFactor: "emailedSecondFactor", offerSmsSecondFactor: "offerSmsSecondFactor", textedSecondFactor: "textedSecondFactor", enrollment: "enrollment", enrollmentState: "enrollmentState", emailVerification: "emailVerification" }, outputs: { submitFlow: "submitFlow", chooseFactor: "chooseFactor", emailSecondFactor: "emailSecondFactor", smsSecondFactor: "smsSecondFactor", resend: "resend" }, ngImport: i0, template: `
148
244
  <div [class]="cls('card', 'atlas-card')">
149
245
  <h1 [class]="cls('headerTitle', 'atlas-title')">{{ t(titleKey) }}</h1>
150
246
 
@@ -156,6 +252,98 @@ export class AttemptFlowComponent {
156
252
  @if (codeSentText(); as sentText) {
157
253
  <p class="atlas-text" data-atlas-code-sent="">{{ sentText }}</p>
158
254
  }
255
+ @if (linkOnly()) {
256
+ <!-- Nothing to type: the flow polls until the emailed link is opened (anywhere). -->
257
+ <p class="atlas-text" data-atlas-link-sent="" aria-live="polite">
258
+ {{ t('signUp.linkSentTo', { email: attempt?.identifier ?? '' }) }}
259
+ </p>
260
+ <button
261
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
262
+ type="button"
263
+ data-atlas-resend=""
264
+ [disabled]="busy"
265
+ (click)="resend.emit()"
266
+ >
267
+ {{ t('signIn.resendLink') }}
268
+ </button>
269
+ }
270
+ @if (enrolling() && enrollmentState; as enrol) {
271
+ @if (enrol.method === null) {
272
+ <p class="atlas-text">{{ t('mfa.enrollChoose') }}</p>
273
+ @for (m of enrol.options; track m) {
274
+ <button
275
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
276
+ type="button"
277
+ [attr.data-atlas-mfa-method]="m"
278
+ [disabled]="busy || enrol.busy"
279
+ (click)="chooseMethod(m)"
280
+ >
281
+ {{ t(m === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
282
+ </button>
283
+ }
284
+ } @else if (enrol.method === 'totp') {
285
+ @if (enrol.enrollment; as setup) {
286
+ <p class="atlas-text">{{ t('mfa.enrollScan') }}</p>
287
+ @if (setup.qrCode) {
288
+ <img class="atlas-mfa-qr" data-atlas="mfa-qr" [src]="setup.qrCode" [alt]="t('mfa.enrollQrAlt')" width="180" height="180" />
289
+ }
290
+ @if (setup.secret) {
291
+ <p class="atlas-text" data-atlas="mfa-setup-key">{{ t('mfa.enrollSetupKey') }}: <code>{{ setupKey(setup.secret) }}</code></p>
292
+ }
293
+ <label class="atlas-field">
294
+ <span>{{ t('mfa.enrollFirstCodeLabel') }}</span>
295
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="text" name="code" autocomplete="one-time-code" inputmode="numeric" [value]="values['code'] ?? ''" (input)="setValue('code', $any($event.target).value)" />
296
+ </label>
297
+ @if (enrol.totpCodes >= 2) {
298
+ <label class="atlas-field">
299
+ <span>{{ t('mfa.enrollSecondCodeLabel') }}</span>
300
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="text" name="secondCode" autocomplete="one-time-code" inputmode="numeric" [value]="values['secondCode'] ?? ''" (input)="setValue('secondCode', $any($event.target).value)" />
301
+ </label>
302
+ }
303
+ } @else {
304
+ <p class="atlas-text" aria-live="polite">{{ enrol.busy ? t('mfa.enrollPreparing') : '' }}</p>
305
+ }
306
+ } @else {
307
+ @if (enrol.enrollment; as texted) {
308
+ <p class="atlas-text" data-atlas="mfa-code-texted" aria-live="polite">{{ t('mfa.codeTextedTo', { phone: texted.phone ?? '' }) }}</p>
309
+ <label class="atlas-field">
310
+ <span>{{ t('mfa.codeLabel') }}</span>
311
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="text" name="code" autocomplete="one-time-code" inputmode="numeric" [value]="values['code'] ?? ''" (input)="setValue('code', $any($event.target).value)" />
312
+ </label>
313
+ <button
314
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
315
+ type="button"
316
+ data-atlas-resend=""
317
+ [disabled]="busy || enrol.busy"
318
+ (click)="resendEnrollment()"
319
+ >
320
+ {{ t('signIn.resendCode') }}
321
+ </button>
322
+ } @else {
323
+ <label class="atlas-field">
324
+ <span>{{ t('mfa.phoneLabel') }}</span>
325
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="tel" name="phone" autocomplete="tel" [value]="values['phone'] ?? ''" (input)="setValue('phone', $any($event.target).value)" />
326
+ </label>
327
+ <p class="atlas-text">{{ t('mfa.phoneHint') }}</p>
328
+ }
329
+ }
330
+ @for (error of enrol.errors; track $index) {
331
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ error.message }}</p>
332
+ }
333
+ @if (enrol.method !== null && enrol.options.length > 1) {
334
+ @for (other of otherMethods(enrol); track other) {
335
+ <button
336
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
337
+ type="button"
338
+ [attr.data-atlas-mfa-method]="other"
339
+ [disabled]="busy || enrol.busy"
340
+ (click)="chooseMethod(other)"
341
+ >
342
+ {{ t(other === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
343
+ </button>
344
+ }
345
+ }
346
+ }
159
347
  @for (f of fields(); track $index) {
160
348
  @if (f.kind === 'input') {
161
349
  <label class="atlas-field">
@@ -171,6 +359,8 @@ export class AttemptFlowComponent {
171
359
  <span [class]="cls('formFieldError', 'atlas-error')">{{ errorText(error) }}</span>
172
360
  }
173
361
  </label>
362
+ } @else if (f.kind === 'alert') {
363
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ t(f.labelKey) }}</p>
174
364
  } @else {
175
365
  <p>{{ t(f.labelKey) }}</p>
176
366
  }
@@ -181,11 +371,53 @@ export class AttemptFlowComponent {
181
371
  }
182
372
 
183
373
  @if (showSubmit()) {
184
- <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy" type="submit">
185
- {{ t('signIn.submit') }}
374
+ <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy || (enrolling() && !!enrollmentState?.busy)" type="submit">
375
+ {{ t(submitKey()) }}
186
376
  </button>
187
377
  }
188
378
 
379
+ @if (showSmsSecondFactor()) {
380
+ @if (smsSecondFactorSentTo(); as sentTo) {
381
+ <p class="atlas-text" data-atlas="sms-second-factor-sent" aria-live="polite">
382
+ {{ t('mfa.codeTextedTo', { phone: sentTo }) }}
383
+ </p>
384
+ } @else {
385
+ <button
386
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
387
+ type="button"
388
+ data-atlas="sms-second-factor"
389
+ [disabled]="busy || !!textedSecondFactor?.busy"
390
+ (click)="smsSecondFactor.emit()"
391
+ >
392
+ {{ textedSecondFactor?.busy ? t('signIn.sending') : t('mfa.smsCodeOption') }}
393
+ </button>
394
+ @if (textedSecondFactor?.error; as message) {
395
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
396
+ }
397
+ }
398
+ }
399
+
400
+ @if (showEmailSecondFactor()) {
401
+ @if (emailSecondFactorSentTo(); as sentTo) {
402
+ <p class="atlas-text" data-atlas="email-second-factor-sent" aria-live="polite">
403
+ {{ t('signIn.codeSentTo', { email: sentTo }) }}
404
+ </p>
405
+ } @else {
406
+ <button
407
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
408
+ type="button"
409
+ data-atlas="email-second-factor"
410
+ [disabled]="busy || !!emailedSecondFactor?.busy"
411
+ (click)="emailSecondFactor.emit()"
412
+ >
413
+ {{ emailedSecondFactor?.busy ? t('signIn.sending') : t('signIn.emailCodeOption') }}
414
+ </button>
415
+ @if (emailedSecondFactor?.error; as message) {
416
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
417
+ }
418
+ }
419
+ }
420
+
189
421
  @if (showEmailCodeOption()) {
190
422
  <button
191
423
  [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
@@ -221,6 +453,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
221
453
  @if (codeSentText(); as sentText) {
222
454
  <p class="atlas-text" data-atlas-code-sent="">{{ sentText }}</p>
223
455
  }
456
+ @if (linkOnly()) {
457
+ <!-- Nothing to type: the flow polls until the emailed link is opened (anywhere). -->
458
+ <p class="atlas-text" data-atlas-link-sent="" aria-live="polite">
459
+ {{ t('signUp.linkSentTo', { email: attempt?.identifier ?? '' }) }}
460
+ </p>
461
+ <button
462
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
463
+ type="button"
464
+ data-atlas-resend=""
465
+ [disabled]="busy"
466
+ (click)="resend.emit()"
467
+ >
468
+ {{ t('signIn.resendLink') }}
469
+ </button>
470
+ }
471
+ @if (enrolling() && enrollmentState; as enrol) {
472
+ @if (enrol.method === null) {
473
+ <p class="atlas-text">{{ t('mfa.enrollChoose') }}</p>
474
+ @for (m of enrol.options; track m) {
475
+ <button
476
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
477
+ type="button"
478
+ [attr.data-atlas-mfa-method]="m"
479
+ [disabled]="busy || enrol.busy"
480
+ (click)="chooseMethod(m)"
481
+ >
482
+ {{ t(m === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
483
+ </button>
484
+ }
485
+ } @else if (enrol.method === 'totp') {
486
+ @if (enrol.enrollment; as setup) {
487
+ <p class="atlas-text">{{ t('mfa.enrollScan') }}</p>
488
+ @if (setup.qrCode) {
489
+ <img class="atlas-mfa-qr" data-atlas="mfa-qr" [src]="setup.qrCode" [alt]="t('mfa.enrollQrAlt')" width="180" height="180" />
490
+ }
491
+ @if (setup.secret) {
492
+ <p class="atlas-text" data-atlas="mfa-setup-key">{{ t('mfa.enrollSetupKey') }}: <code>{{ setupKey(setup.secret) }}</code></p>
493
+ }
494
+ <label class="atlas-field">
495
+ <span>{{ t('mfa.enrollFirstCodeLabel') }}</span>
496
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="text" name="code" autocomplete="one-time-code" inputmode="numeric" [value]="values['code'] ?? ''" (input)="setValue('code', $any($event.target).value)" />
497
+ </label>
498
+ @if (enrol.totpCodes >= 2) {
499
+ <label class="atlas-field">
500
+ <span>{{ t('mfa.enrollSecondCodeLabel') }}</span>
501
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="text" name="secondCode" autocomplete="one-time-code" inputmode="numeric" [value]="values['secondCode'] ?? ''" (input)="setValue('secondCode', $any($event.target).value)" />
502
+ </label>
503
+ }
504
+ } @else {
505
+ <p class="atlas-text" aria-live="polite">{{ enrol.busy ? t('mfa.enrollPreparing') : '' }}</p>
506
+ }
507
+ } @else {
508
+ @if (enrol.enrollment; as texted) {
509
+ <p class="atlas-text" data-atlas="mfa-code-texted" aria-live="polite">{{ t('mfa.codeTextedTo', { phone: texted.phone ?? '' }) }}</p>
510
+ <label class="atlas-field">
511
+ <span>{{ t('mfa.codeLabel') }}</span>
512
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="text" name="code" autocomplete="one-time-code" inputmode="numeric" [value]="values['code'] ?? ''" (input)="setValue('code', $any($event.target).value)" />
513
+ </label>
514
+ <button
515
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
516
+ type="button"
517
+ data-atlas-resend=""
518
+ [disabled]="busy || enrol.busy"
519
+ (click)="resendEnrollment()"
520
+ >
521
+ {{ t('signIn.resendCode') }}
522
+ </button>
523
+ } @else {
524
+ <label class="atlas-field">
525
+ <span>{{ t('mfa.phoneLabel') }}</span>
526
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="tel" name="phone" autocomplete="tel" [value]="values['phone'] ?? ''" (input)="setValue('phone', $any($event.target).value)" />
527
+ </label>
528
+ <p class="atlas-text">{{ t('mfa.phoneHint') }}</p>
529
+ }
530
+ }
531
+ @for (error of enrol.errors; track $index) {
532
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ error.message }}</p>
533
+ }
534
+ @if (enrol.method !== null && enrol.options.length > 1) {
535
+ @for (other of otherMethods(enrol); track other) {
536
+ <button
537
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
538
+ type="button"
539
+ [attr.data-atlas-mfa-method]="other"
540
+ [disabled]="busy || enrol.busy"
541
+ (click)="chooseMethod(other)"
542
+ >
543
+ {{ t(other === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
544
+ </button>
545
+ }
546
+ }
547
+ }
224
548
  @for (f of fields(); track $index) {
225
549
  @if (f.kind === 'input') {
226
550
  <label class="atlas-field">
@@ -236,6 +560,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
236
560
  <span [class]="cls('formFieldError', 'atlas-error')">{{ errorText(error) }}</span>
237
561
  }
238
562
  </label>
563
+ } @else if (f.kind === 'alert') {
564
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ t(f.labelKey) }}</p>
239
565
  } @else {
240
566
  <p>{{ t(f.labelKey) }}</p>
241
567
  }
@@ -246,11 +572,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
246
572
  }
247
573
 
248
574
  @if (showSubmit()) {
249
- <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy" type="submit">
250
- {{ t('signIn.submit') }}
575
+ <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy || (enrolling() && !!enrollmentState?.busy)" type="submit">
576
+ {{ t(submitKey()) }}
251
577
  </button>
252
578
  }
253
579
 
580
+ @if (showSmsSecondFactor()) {
581
+ @if (smsSecondFactorSentTo(); as sentTo) {
582
+ <p class="atlas-text" data-atlas="sms-second-factor-sent" aria-live="polite">
583
+ {{ t('mfa.codeTextedTo', { phone: sentTo }) }}
584
+ </p>
585
+ } @else {
586
+ <button
587
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
588
+ type="button"
589
+ data-atlas="sms-second-factor"
590
+ [disabled]="busy || !!textedSecondFactor?.busy"
591
+ (click)="smsSecondFactor.emit()"
592
+ >
593
+ {{ textedSecondFactor?.busy ? t('signIn.sending') : t('mfa.smsCodeOption') }}
594
+ </button>
595
+ @if (textedSecondFactor?.error; as message) {
596
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
597
+ }
598
+ }
599
+ }
600
+
601
+ @if (showEmailSecondFactor()) {
602
+ @if (emailSecondFactorSentTo(); as sentTo) {
603
+ <p class="atlas-text" data-atlas="email-second-factor-sent" aria-live="polite">
604
+ {{ t('signIn.codeSentTo', { email: sentTo }) }}
605
+ </p>
606
+ } @else {
607
+ <button
608
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
609
+ type="button"
610
+ data-atlas="email-second-factor"
611
+ [disabled]="busy || !!emailedSecondFactor?.busy"
612
+ (click)="emailSecondFactor.emit()"
613
+ >
614
+ {{ emailedSecondFactor?.busy ? t('signIn.sending') : t('signIn.emailCodeOption') }}
615
+ </button>
616
+ @if (emailedSecondFactor?.error; as message) {
617
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
618
+ }
619
+ }
620
+ }
621
+
254
622
  @if (showEmailCodeOption()) {
255
623
  <button
256
624
  [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
@@ -273,6 +641,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
273
641
  type: Input
274
642
  }], errors: [{
275
643
  type: Input
644
+ }], sessionKept: [{
645
+ type: Input
276
646
  }], titleKey: [{
277
647
  type: Input
278
648
  }], captcha: [{
@@ -285,9 +655,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
285
655
  type: Output
286
656
  }], chooseFactor: [{
287
657
  type: Output
658
+ }], offerEmailSecondFactor: [{
659
+ type: Input
660
+ }], emailedSecondFactor: [{
661
+ type: Input
662
+ }], emailSecondFactor: [{
663
+ type: Output
664
+ }], offerSmsSecondFactor: [{
665
+ type: Input
666
+ }], textedSecondFactor: [{
667
+ type: Input
668
+ }], smsSecondFactor: [{
669
+ type: Output
670
+ }], enrollment: [{
671
+ type: Input
672
+ }], enrollmentState: [{
673
+ type: Input
674
+ }], emailVerification: [{
675
+ type: Input
676
+ }], resend: [{
677
+ type: Output
288
678
  }] } });
289
679
  /** A read-only message row: `labelKey` holds the i18n key of the text to show. */
290
680
  function msg(labelKey) {
291
681
  return { kind: 'message', name: '', labelKey, type: 'text' };
292
682
  }
293
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZW1wdC1mbG93LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9hdHRlbXB0LWZsb3cuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLFFBQVEsR0FJVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDakYsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUFlcEM7Ozs7Ozs7OztHQVNHO0FBZ0VILE1BQU0sT0FBTyxvQkFBb0I7SUFDZCxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXJDLE9BQU8sR0FBdUIsSUFBSSxDQUFDO0lBQ25DLElBQUksR0FBRyxLQUFLLENBQUM7SUFDYixNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUMxQixRQUFRLEdBQUcsY0FBYyxDQUFDO0lBQ25DOzs7O09BSUc7SUFDTSxPQUFPLEdBQTZCLElBQUksQ0FBQztJQUNsRDs7OztPQUlHO0lBQ00sWUFBWSxHQUFvQixJQUFJLENBQUM7SUFDOUMscUdBQXFHO0lBQzVGLGNBQWMsR0FBa0IsSUFBSSxDQUFDO0lBRTlDLG1FQUFtRTtJQUN6RCxVQUFVLEdBQUcsSUFBSSxZQUFZLEVBQTBCLENBQUM7SUFDbEUsNkZBQTZGO0lBQ25GLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBZ0IsQ0FBQztJQUVoRCxNQUFNLEdBQTJC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LEVBQUUsQ0FBQztBQUMvRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgbG9jYWxpemVkRXJyb3JNZXNzYWdlLFxuICBuZXh0U3RlcCxcbiAgdHlwZSBBdHRlbXB0VmlldyxcbiAgdHlwZSBDYXB0Y2hhQ29udHJvbGxlcixcbiAgdHlwZSBGaWVsZEVycm9yLFxufSBmcm9tICdAYXRsYXNhdXRoL2pzJztcbmltcG9ydCB7IEF0bGFzU2VydmljZSB9IGZyb20gJy4uL2F0bGFzLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXRsYXNDYXB0Y2hhU2xvdERpcmVjdGl2ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvY2FwdGNoYS1zbG90LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBjbGFzc0ZvciwgdHlwZSBFbGVtZW50S2V5IH0gZnJvbSAnLi4vYXBwZWFyYW5jZSc7XG5pbXBvcnQgeyB0cmFuc2xhdGUgfSBmcm9tICcuLi9pMThuJztcblxuLyoqXG4gKiBPbmUgcmVuZGVyZWQgcm93IG9mIHRoZSBmbG93LiBBIHVuaWZvcm0gc2hhcGUgKHJhdGhlciB0aGFuIGEgZGlzY3JpbWluYXRlZFxuICogdW5pb24pIHNvIHRoZSB0ZW1wbGF0ZSBhY2Nlc3NlcyBvbmx5IGZpZWxkcyB0aGF0IGFsd2F5cyBleGlzdCDigJQgbm8gcmVsaWFuY2Ugb25cbiAqIHRlbXBsYXRlIGNvbnRyb2wtZmxvdyBuYXJyb3dpbmcgb2YgYSBsb29wIHZhcmlhYmxlLCB3aGljaCB2YXJpZXMgYnkgQW5ndWxhclxuICogbWlub3IuIEZvciBhIGBtZXNzYWdlYCByb3csIGBsYWJlbEtleWAgY2FycmllcyB0aGUgbWVzc2FnZSdzIGkxOG4ga2V5LlxuICovXG5pbnRlcmZhY2UgU3RlcEZpZWxkIHtcbiAga2luZDogJ2lucHV0JyB8ICdtZXNzYWdlJztcbiAgbmFtZTogc3RyaW5nO1xuICBsYWJlbEtleTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHNlcnZlci1kcml2ZW4gZmxvdyBzaGVsbCwgc2hhcmVkIGJ5IGA8YXRsYXMtc2lnbi1pbj5gIGFuZFxuICogYDxhdGxhcy1zaWduLXVwPmAuIFRoZSBBbmd1bGFyIHBlZXIgb2YgUmVhY3QncyBpbnRlcm5hbCBgQXR0ZW1wdEZsb3dgLlxuICpcbiAqIEl0IGNvbnRhaW5zIE5PIGRlY2lzaW9uIGFib3V0IHdoYXQgY29tZXMgbmV4dDogaXQgcmVuZGVycyB3aGF0ZXZlciBgc3RhdHVzYFxuICogdGhlIHNlcnZlciByZXR1cm5lZCwgbWFwcGVkIHRocm91Z2ggYG5leHRTdGVwYCBmcm9tIGBAYXRsYXNhdXRoL2pzYCAodGhlIHNhbWVcbiAqIGV4aGF1c3RpdmUgbWFwcGluZyB0aGUgUmVhY3QgU0RLIHVzZXMpLCBzbyBhZGRpbmcgYSBzdGVwIGlzIGEgc2VydmVyIGNoYW5nZVxuICogYW5kIGFuIG91dC1vZi1kYXRlIGNsaWVudCBkZWdyYWRlcyB0byBhIHZpc2libGUgXCJwbGVhc2UgdXBkYXRlXCIgbWVzc2FnZSByYXRoZXJcbiAqIHRoYW4gYSBibGFuayBzY3JlZW4uXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2F0bGFzLWF0dGVtcHQtZmxvdycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbQXRsYXNDYXB0Y2hhU2xvdERpcmVjdGl2ZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY2xzKCdjYXJkJywgJ2F0bGFzLWNhcmQnKVwiPlxuICAgICAgPGgxIFtjbGFzc109XCJjbHMoJ2hlYWRlclRpdGxlJywgJ2F0bGFzLXRpdGxlJylcIj57eyB0KHRpdGxlS2V5KSB9fTwvaDE+XG5cbiAgICAgIEBmb3IgKGVycm9yIG9mIGZvcm1FcnJvcnMoKTsgdHJhY2sgZXJyb3IuY29kZSkge1xuICAgICAgICA8cCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCIgcm9sZT1cImFsZXJ0XCI+e3sgZXJyb3JUZXh0KGVycm9yKSB9fTwvcD5cbiAgICAgIH1cblxuICAgICAgPGZvcm0gKHN1Ym1pdCk9XCJvblN1Ym1pdCgkZXZlbnQpXCI+XG4gICAgICAgIEBpZiAoY29kZVNlbnRUZXh0KCk7IGFzIHNlbnRUZXh0KSB7XG4gICAgICAgICAgPHAgY2xhc3M9XCJhdGxhcy10ZXh0XCIgZGF0YS1hdGxhcy1jb2RlLXNlbnQ9XCJcIj57eyBzZW50VGV4dCB9fTwvcD5cbiAgICAgICAgfVxuICAgICAgICBAZm9yIChmIG9mIGZpZWxkcygpOyB0cmFjayAkaW5kZXgpIHtcbiAgICAgICAgICBAaWYgKGYua2luZCA9PT0gJ2lucHV0Jykge1xuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiYXRsYXMtZmllbGRcIj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgdChmLmxhYmVsS2V5KSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkSW5wdXQnLCAnYXRsYXMtaW5wdXQnKVwiXG4gICAgICAgICAgICAgICAgW3R5cGVdPVwiZi50eXBlXCJcbiAgICAgICAgICAgICAgICBbYXR0ci5uYW1lXT1cImYubmFtZVwiXG4gICAgICAgICAgICAgICAgW3ZhbHVlXT1cInZhbHVlc1tmLm5hbWVdID8/ICcnXCJcbiAgICAgICAgICAgICAgICAoaW5wdXQpPVwic2V0VmFsdWUoZi5uYW1lLCAkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgIEBmb3IgKGVycm9yIG9mIGZpZWxkRXJyb3JzRm9yKGYubmFtZSk7IHRyYWNrIGVycm9yLmNvZGUpIHtcbiAgICAgICAgICAgICAgICA8c3BhbiBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCI+e3sgZXJyb3JUZXh0KGVycm9yKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxwPnt7IHQoZi5sYWJlbEtleSkgfX08L3A+XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93Q2FwdGNoYSgpKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImF0bGFzLWNhcHRjaGFcIiBkYXRhLWF0bGFzLWNhcHRjaGE9XCJcIiBbYXRsYXNDYXB0Y2hhU2xvdF09XCJjYXB0Y2hhXCI+PC9kaXY+XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dTdWJtaXQoKSkge1xuICAgICAgICAgIDxidXR0b24gW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblByaW1hcnknLCAnYXRsYXMtYnV0dG9uJylcIiBbZGlzYWJsZWRdPVwiYnVzeVwiIHR5cGU9XCJzdWJtaXRcIj5cbiAgICAgICAgICAgIHt7IHQoJ3NpZ25Jbi5zdWJtaXQnKSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93RW1haWxDb2RlT3B0aW9uKCkpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uU2Vjb25kYXJ5JywgJ2F0bGFzLWJ1dHRvbi1zZWNvbmRhcnknKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtc3RyYXRlZ3ldPVwicHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJyA/IG51bGwgOiAnZW1haWxfY29kZSdcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1hdGxhcy1yZXNlbmRdPVwicHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJyA/ICcnIDogbnVsbFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlRmFjdG9yLmVtaXQoJ2VtYWlsX2NvZGUnKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgdChwcmVwYXJlZEZhY3RvciA9PT0gJ2VtYWlsX2NvZGUnID8gJ3NpZ25Jbi5yZXNlbmRDb2RlJyA6ICdzaWduSW4udXNlRW1haWxDb2RlJykgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9mb3JtPlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBBdHRlbXB0Rmxvd0NvbXBvbmVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYXRsYXMgPSBpbmplY3QoQXRsYXNTZXJ2aWNlKTtcblxuICBASW5wdXQoKSBhdHRlbXB0OiBBdHRlbXB0VmlldyB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBidXN5ID0gZmFsc2U7XG4gIEBJbnB1dCgpIGVycm9yczogRmllbGRFcnJvcltdID0gW107XG4gIEBJbnB1dCgpIHRpdGxlS2V5ID0gJ3NpZ25Jbi50aXRsZSc7XG4gIC8qKlxuICAgKiBUaGUgc2lnbi1pbiBjYXB0Y2hhLCBkcmF3biBhYm92ZSB0aGUgc3VibWl0IGJ1dHRvbiBvbiB0aGUgaWRlbnRpZmllciBzdGVwXG4gICAqIChhbiBhbHdheXMtb24gc2lnbi1pbiBjYXB0Y2hhKSBhbmQgb24gdGhlIGNoYWxsZW5nZSBzdGVwIHRoZSBzZXJ2ZXIgZGVtYW5kc1xuICAgKiB3aXRoIGBuZWVkc19jYXB0Y2hhYC4gTnVsbCB3aGVuIHRoZSBmbG93IGRyYXdzIG5vbmUuXG4gICAqL1xuICBASW5wdXQoKSBjYXB0Y2hhOiBDYXB0Y2hhQ29udHJvbGxlciB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogVGhlIGZpcnN0IGZhY3RvcnMgdG8gb2ZmZXIgb24gdGhlIGBuZWVkc19maXJzdF9mYWN0b3JgIHN0ZXAg4oCUIHBhc3NcbiAgICogYEF0bGFzRmxvd0NvbnRyb2xsZXIuZmlyc3RGYWN0b3JzKClgLCB3aGljaCBkcm9wcyBlbWFpbCBjb2RlIC8gbGluayB3aGlsZSB0aGVcbiAgICogYXBwIGNhbm5vdCBkZWxpdmVyIGVtYWlsLiBOdWxsIHVzZXMgdGhlIHNlcnZlcidzIGxpc3QgYXMtaXMuXG4gICAqL1xuICBASW5wdXQoKSBmaXJzdEZhY3RvcnM6IHN0cmluZ1tdIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgZmlyc3QgZmFjdG9yIGFscmVhZHkgc2VudCAoYEF0bGFzRmxvd0NvbnRyb2xsZXIucHJlcGFyZWRGYWN0b3IoKWApOiBpdHMgY29kZSBpcyBjb2xsZWN0ZWQuICovXG4gIEBJbnB1dCgpIHByZXBhcmVkRmFjdG9yOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAvKiogRW1pdHMgdGhlIGNvbGxlY3RlZCBmaWVsZCB2YWx1ZXMgd2hlbiB0aGUgZm9ybSBpcyBzdWJtaXR0ZWQuICovXG4gIEBPdXRwdXQoKSBzdWJtaXRGbG93ID0gbmV3IEV2ZW50RW1pdHRlcjxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PigpO1xuICAvKiogRW1pdHMgd2hlbiB0aGUgdXNlciBwaWNrcyBhIGZpcnN0IGZhY3RvciB0aGUgc2VydmVyIG11c3Qgc2VuZCBmaXJzdCAoYW4gZW1haWxlZCBjb2RlKS4gKi9cbiAgQE91dHB1dCgpIGNob29zZUZhY3RvciA9IG5ldyBFdmVudEVtaXR0ZXI8J2VtYWlsX2NvZGUnPigpO1xuXG4gIHByb3RlY3RlZCB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBwcm90ZWN0ZWQgdChrZXk6IHN0cmluZywgdmFycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcge1xuICAgIHJldHVybiB0cmFuc2xhdGUodGhpcy5hdGxhcy5sb2NhbGl6YXRpb24sIGtleSwgdmFycyk7XG4gIH1cblxuICAvKiogQSBzZXJ2ZXIgZXJyb3IgaW4gdGhlIGFwcCdzIGxhbmd1YWdlIChgZXJyb3IuPHJlYXNvbj5gLCBlbHNlIHRoZSBzZXJ2ZXIncyBtZXNzYWdlKS4gKi9cbiAgcHJvdGVjdGVkIGVycm9yVGV4dChlcnJvcjogRmllbGRFcnJvcik6IHN0cmluZyB7XG4gICAgLy8gYGVycm9yTG9jYWxpemF0aW9uYCBpcyByZWFkIGRlZmVuc2l2ZWx5OiBhIHN0YW5kLWluIHNlcnZpY2UgbWF5IGxhY2sgaXQuXG4gICAgY29uc3QgbGF5ZXIgPSAodGhpcy5hdGxhcyBhcyB7IGVycm9yTG9jYWxpemF0aW9uPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB9KS5lcnJvckxvY2FsaXphdGlvbjtcbiAgICByZXR1cm4gbG9jYWxpemVkRXJyb3JNZXNzYWdlKGVycm9yLCBsYXllciA/PyB0aGlzLmF0bGFzLmxvY2FsaXphdGlvbiwgdGhpcy5hdGxhcy5sb2NhbGl6YXRpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNscyhrZXk6IEVsZW1lbnRLZXksIGJhc2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNsYXNzRm9yKGtleSwgdGhpcy5hdGxhcy5hcHBlYXJhbmNlLCBiYXNlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRWYWx1ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlcyA9IHsgLi4udGhpcy52YWx1ZXMsIFtuYW1lXTogdmFsdWUgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblN1Ym1pdChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMuc3VibWl0Rmxvdy5lbWl0KHRoaXMudmFsdWVzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBmb3JtRXJyb3JzKCk6IEZpZWxkRXJyb3JbXSB7XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JzLmZpbHRlcigoZXJyb3IpID0+ICFlcnJvci5wYXJhbSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRFcnJvcnNGb3IobmFtZTogc3RyaW5nKTogRmllbGRFcnJvcltdIHtcbiAgICByZXR1cm4gdGhpcy5lcnJvcnMuZmlsdGVyKChlcnJvcikgPT4gZXJyb3IucGFyYW0gPT09IG5hbWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGVwKCkge1xuICAgIHJldHVybiB0aGlzLmF0dGVtcHQgPyBuZXh0U3RlcCh0aGlzLmF0dGVtcHQpIDogKHsga2luZDogJ2NvbGxlY3RfaWRlbnRpZmllcicgfSBhcyBjb25zdCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd0NhcHRjaGEoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qga2luZCA9IHRoaXMuc3RlcCgpLmtpbmQ7XG4gICAgcmV0dXJuICEhdGhpcy5jYXB0Y2hhICYmIChraW5kID09PSAnY29sbGVjdF9pZGVudGlmaWVyJyB8fCBraW5kID09PSAnY29sbGVjdF9jYXB0Y2hhJyk7XG4gIH1cblxuICAvKiogVGhlIGZpcnN0IGZhY3RvcnMgb24gb2ZmZXIgYXQgYSBgbmVlZHNfZmlyc3RfZmFjdG9yYCBzdGVwIChlbXB0eSBvbiBhbnkgb3RoZXIpLiAqL1xuICBwcml2YXRlIG9mZmVyZWQoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHN0ZXAgPSB0aGlzLnN0ZXAoKTtcbiAgICBpZiAoc3RlcC5raW5kICE9PSAnY29sbGVjdF9maXJzdF9mYWN0b3InKSByZXR1cm4gW107XG4gICAgcmV0dXJuIHRoaXMuZmlyc3RGYWN0b3JzID8/IHN0ZXAuc3RyYXRlZ2llcztcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG93RW1haWxDb2RlT3B0aW9uKCk6IGJvb2xlYW4ge1xuICAgIC8vIEJlZm9yZSB0aGUgY29kZSBpcyBzZW50OiB0aGUgY2hvaWNlIChvciB0aGUgcmV0cnkgb2YgYSBmYWlsZWQgYXV0b21hdGljXG4gICAgLy8gc2VuZCkuIEFmdGVyOiBcIlJlc2VuZCBjb2RlXCIuXG4gICAgcmV0dXJuIHRoaXMub2ZmZXJlZCgpLmluY2x1ZGVzKCdlbWFpbF9jb2RlJyk7XG4gIH1cblxuICAvKiogVGhlIFwid2Ugc2VudCBhIGNvZGUgdG8g4oCmXCIgbGluZSBvbiB0aGUgY29kZSBzdGVwLiAqL1xuICBwcm90ZWN0ZWQgY29kZVNlbnRUZXh0KCk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICh0aGlzLnN0ZXAoKS5raW5kICE9PSAnY29sbGVjdF9maXJzdF9mYWN0b3InIHx8IHRoaXMucHJlcGFyZWRGYWN0b3IgIT09ICdlbWFpbF9jb2RlJykgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMudCgnc2lnbkluLmNvZGVTZW50VG8nLCB7IGVtYWlsOiB0aGlzLmF0dGVtcHQ/LmlkZW50aWZpZXIgPz8gJycgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd1N1Ym1pdCgpOiBib29sZWFuIHtcbiAgICBjb25zdCBraW5kID0gdGhpcy5zdGVwKCkua2luZDtcbiAgICAvLyBOb3RoaW5nIHRvIHN1Ym1pdCBvbiBhIGZpcnN0LWZhY3RvciBzdGVwIHRoYXQgb25seSBvZmZlcnMgYW4gZW1haWxlZCBjb2RlXG4gICAgLy8gdW50aWwgdGhhdCBjb2RlIGlzIHNlbnQuXG4gICAgaWYgKGtpbmQgPT09ICdjb2xsZWN0X2ZpcnN0X2ZhY3RvcicpIHJldHVybiB0aGlzLmZpZWxkcygpLmxlbmd0aCA+IDA7XG4gICAgcmV0dXJuIGtpbmQgIT09ICdkb25lJyAmJiBraW5kICE9PSAnYXdhaXRfb2F1dGgnO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkcygpOiBTdGVwRmllbGRbXSB7XG4gICAgY29uc3Qgc3RlcCA9IHRoaXMuc3RlcCgpO1xuICAgIHN3aXRjaCAoc3RlcC5raW5kKSB7XG4gICAgICBjYXNlICdjb2xsZWN0X2lkZW50aWZpZXInOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2lkZW50aWZpZXInLCBsYWJlbEtleTogJ3NpZ25Jbi5pZGVudGlmaWVyTGFiZWwnLCB0eXBlOiAnZW1haWwnIH1dO1xuICAgICAgY2FzZSAnY29sbGVjdF9maXJzdF9mYWN0b3InOiB7XG4gICAgICAgIGlmICh0aGlzLnByZXBhcmVkRmFjdG9yID09PSAnZW1haWxfY29kZScpIHtcbiAgICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ3NpZ25Jbi5lbWFpbENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9XTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaGUgcGFzc3dvcmQgZmllbGQgdW5sZXNzIHRoZSBvbmx5IG9mZmVyIGlzIGFuIGVtYWlsZWQgY29kZSAoY2hvc2VuXG4gICAgICAgIC8vIHdpdGggdGhlIGJ1dHRvbiBiZWxvdyB0aGUgZm9ybSkuXG4gICAgICAgIGNvbnN0IG9mZmVyZWQgPSB0aGlzLm9mZmVyZWQoKTtcbiAgICAgICAgcmV0dXJuIG9mZmVyZWQuaW5jbHVkZXMoJ2VtYWlsX2NvZGUnKSAmJiAhb2ZmZXJlZC5pbmNsdWRlcygncGFzc3dvcmQnKVxuICAgICAgICAgID8gW11cbiAgICAgICAgICA6IFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdwYXNzd29yZCcsIGxhYmVsS2V5OiAnc2lnbkluLnBhc3N3b3JkTGFiZWwnLCB0eXBlOiAncGFzc3dvcmQnIH1dO1xuICAgICAgfVxuICAgICAgY2FzZSAnY29sbGVjdF9zZWNvbmRfZmFjdG9yJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdjb2RlJywgbGFiZWxLZXk6ICdtZmEuY29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgY2FzZSAnZW5yb2xsX3NlY29uZF9mYWN0b3InOlxuICAgICAgICAvLyBUd28gY29uc2VjdXRpdmUgY29kZXMgKMKnNS42KTogYSBwaG9uZSB3aXRoIGEgZmFzdCBjbG9jayBmYWlscyBoZXJlXG4gICAgICAgIC8vIHJhdGhlciB0aGFuIG9uIGV2ZXJ5IHNpZ24taW4gYWZ0ZXJ3YXJkcy5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICB7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdjb2RlJywgbGFiZWxLZXk6ICdtZmEuZW5yb2xsRmlyc3RDb2RlTGFiZWwnLCB0eXBlOiAndGV4dCcgfSxcbiAgICAgICAgICB7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdzZWNvbmRDb2RlJywgbGFiZWxLZXk6ICdtZmEuZW5yb2xsU2Vjb25kQ29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH0sXG4gICAgICAgIF07XG4gICAgICBjYXNlICdjb2xsZWN0X2VtYWlsX2NvZGUnOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ3NpZ25Jbi5lbWFpbENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9XTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfbmV3X3Bhc3N3b3JkJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdwYXNzd29yZCcsIGxhYmVsS2V5OiAncmVzZXQubmV3UGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICBjYXNlICdjb2xsZWN0X2NhcHRjaGEnOlxuICAgICAgICAvLyDCpzUgdGhlIHNlcnZlciB3aXRoaGVsZCB0aGUgYXR0ZW1wdCB1bnRpbCBhIGNhcHRjaGEgY2xlYXJzLiBTb2x2aW5nIHRoZVxuICAgICAgICAvLyB3aWRnZXQgcmVzdWJtaXRzIHRoZSBpZGVudGlmaWVyIG9uIGl0cyBvd247IHRoZSBidXR0b24gcmV0cmllcy5cbiAgICAgICAgcmV0dXJuIFttc2coJ2NhcHRjaGEucHJvbXB0JyldO1xuICAgICAgY2FzZSAnYXdhaXRfb2F1dGgnOlxuICAgICAgICByZXR1cm4gW21zZygnc2lnbkluLm1hZ2ljTGlua1NlbnQnKV07XG4gICAgICBjYXNlICdkb25lJzpcbiAgICAgICAgcmV0dXJuIFttc2coJ3NpZ25Jbi5jaGVja090aGVyVGFiJyldO1xuICAgICAgY2FzZSAncmVzdGFydCc6XG4gICAgICAgIHJldHVybiBbbXNnKCdlcnJvci5nZW5lcmljJyldO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gQSBzdGF0dXMgdGhpcyBTREsgdmVyc2lvbiBkb2VzIG5vdCBrbm93LiBBbiBob25lc3QgbWVzc2FnZSBiZWF0cyBhXG4gICAgICAgIC8vIGJsYW5rIGxvZ2luIGJveCB0aGUgdXNlciBjYW5ub3QgYWN0IG9uLlxuICAgICAgICByZXR1cm4gW21zZygnZXJyb3IuZ2VuZXJpYycpXTtcbiAgICB9XG4gIH1cbn1cblxuLyoqIEEgcmVhZC1vbmx5IG1lc3NhZ2Ugcm93OiBgbGFiZWxLZXlgIGhvbGRzIHRoZSBpMThuIGtleSBvZiB0aGUgdGV4dCB0byBzaG93LiAqL1xuZnVuY3Rpb24gbXNnKGxhYmVsS2V5OiBzdHJpbmcpOiBTdGVwRmllbGQge1xuICByZXR1cm4geyBraW5kOiAnbWVzc2FnZScsIG5hbWU6ICcnLCBsYWJlbEtleSwgdHlwZTogJ3RleHQnIH07XG59XG4iXX0=
683
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZW1wdC1mbG93LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9hdHRlbXB0LWZsb3cuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQixhQUFhLEVBQ2IscUJBQXFCLEVBQ3JCLFFBQVEsR0FPVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDakYsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUFlcEM7Ozs7Ozs7OztHQVNHO0FBd01ILE1BQU0sT0FBTyxvQkFBb0I7SUFDZCxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXJDLE9BQU8sR0FBdUIsSUFBSSxDQUFDO0lBQ25DLElBQUksR0FBRyxLQUFLLENBQUM7SUFDYixNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUNuQywwRkFBMEY7SUFDakYsV0FBVyxHQUF3QixTQUFTLENBQUM7SUFDN0MsUUFBUSxHQUFHLGNBQWMsQ0FBQztJQUNuQzs7OztPQUlHO0lBQ00sT0FBTyxHQUE2QixJQUFJLENBQUM7SUFDbEQ7Ozs7T0FJRztJQUNNLFlBQVksR0FBb0IsSUFBSSxDQUFDO0lBQzlDLHFHQUFxRztJQUM1RixjQUFjLEdBQWtCLElBQUksQ0FBQztJQUU5QyxtRUFBbUU7SUFDekQsVUFBVSxHQUFHLElBQUksWUFBWSxF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Z0JBTUcsT0FBTztzQkFBZixLQUFLO2dCQU1HLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsY0FBYztzQkFBdEIsS0FBSztnQkFHSSxVQUFVO3NCQUFuQixNQUFNO2dCQUVHLFlBQVk7c0JBQXJCLE1BQU07Z0JBTUUsc0JBQXNCO3NCQUE5QixLQUFLO2dCQUVHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFDSSxpQkFBaUI7c0JBQTFCLE1BQU07Z0JBTUUsb0JBQW9CO3NCQUE1QixLQUFLO2dCQUVHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDSSxlQUFlO3NCQUF4QixNQUFNO2dCQU1FLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFNRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0ksTUFBTTtzQkFBZixNQUFNOztBQTBMVCxrRkFBa0Y7QUFDbEYsU0FBUyxHQUFHLENBQUMsUUFBZ0I7SUFDM0IsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQy9ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIGluamVjdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBhd2FpdGluZ1NpZ25VcExpbmssXG4gIGVucm9sbG1lbnRTdWJtaXRLZXksXG4gIGdyb3VwU2V0dXBLZXksXG4gIGxvY2FsaXplZEVycm9yTWVzc2FnZSxcbiAgbmV4dFN0ZXAsXG4gIHR5cGUgQXR0ZW1wdFZpZXcsXG4gIHR5cGUgQ2FwdGNoYUNvbnRyb2xsZXIsXG4gIHR5cGUgRmllbGRFcnJvcixcbiAgdHlwZSBNZmFFbnJvbGxtZW50Q29udHJvbGxlcixcbiAgdHlwZSBNZmFFbnJvbGxtZW50U3RhdGUsXG4gIHR5cGUgTWZhRW5yb2xsbWVudFN0cmF0ZWd5LFxufSBmcm9tICdAYXRsYXNhdXRoL2pzJztcbmltcG9ydCB7IEF0bGFzU2VydmljZSB9IGZyb20gJy4uL2F0bGFzLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXRsYXNDYXB0Y2hhU2xvdERpcmVjdGl2ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvY2FwdGNoYS1zbG90LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBjbGFzc0ZvciwgdHlwZSBFbGVtZW50S2V5IH0gZnJvbSAnLi4vYXBwZWFyYW5jZSc7XG5pbXBvcnQgeyB0cmFuc2xhdGUgfSBmcm9tICcuLi9pMThuJztcblxuLyoqXG4gKiBPbmUgcmVuZGVyZWQgcm93IG9mIHRoZSBmbG93LiBBIHVuaWZvcm0gc2hhcGUgKHJhdGhlciB0aGFuIGEgZGlzY3JpbWluYXRlZFxuICogdW5pb24pIHNvIHRoZSB0ZW1wbGF0ZSBhY2Nlc3NlcyBvbmx5IGZpZWxkcyB0aGF0IGFsd2F5cyBleGlzdCDigJQgbm8gcmVsaWFuY2Ugb25cbiAqIHRlbXBsYXRlIGNvbnRyb2wtZmxvdyBuYXJyb3dpbmcgb2YgYSBsb29wIHZhcmlhYmxlLCB3aGljaCB2YXJpZXMgYnkgQW5ndWxhclxuICogbWlub3IuIEZvciBhIGBtZXNzYWdlYCByb3csIGBsYWJlbEtleWAgY2FycmllcyB0aGUgbWVzc2FnZSdzIGkxOG4ga2V5LlxuICovXG5pbnRlcmZhY2UgU3RlcEZpZWxkIHtcbiAga2luZDogJ2lucHV0JyB8ICdtZXNzYWdlJyB8ICdhbGVydCc7XG4gIG5hbWU6IHN0cmluZztcbiAgbGFiZWxLZXk6IHN0cmluZztcbiAgdHlwZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBzZXJ2ZXItZHJpdmVuIGZsb3cgc2hlbGwsIHNoYXJlZCBieSBgPGF0bGFzLXNpZ24taW4+YCBhbmRcbiAqIGA8YXRsYXMtc2lnbi11cD5gLiBUaGUgQW5ndWxhciBwZWVyIG9mIFJlYWN0J3MgaW50ZXJuYWwgYEF0dGVtcHRGbG93YC5cbiAqXG4gKiBJdCBjb250YWlucyBOTyBkZWNpc2lvbiBhYm91dCB3aGF0IGNvbWVzIG5leHQ6IGl0IHJlbmRlcnMgd2hhdGV2ZXIgYHN0YXR1c2BcbiAqIHRoZSBzZXJ2ZXIgcmV0dXJuZWQsIG1hcHBlZCB0aHJvdWdoIGBuZXh0U3RlcGAgZnJvbSBgQGF0bGFzYXV0aC9qc2AgKHRoZSBzYW1lXG4gKiBleGhhdXN0aXZlIG1hcHBpbmcgdGhlIFJlYWN0IFNESyB1c2VzKSwgc28gYWRkaW5nIGEgc3RlcCBpcyBhIHNlcnZlciBjaGFuZ2VcbiAqIGFuZCBhbiBvdXQtb2YtZGF0ZSBjbGllbnQgZGVncmFkZXMgdG8gYSB2aXNpYmxlIFwicGxlYXNlIHVwZGF0ZVwiIG1lc3NhZ2UgcmF0aGVyXG4gKiB0aGFuIGEgYmxhbmsgc2NyZWVuLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhdGxhcy1hdHRlbXB0LWZsb3cnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW0F0bGFzQ2FwdGNoYVNsb3REaXJlY3RpdmVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNscygnY2FyZCcsICdhdGxhcy1jYXJkJylcIj5cbiAgICAgIDxoMSBbY2xhc3NdPVwiY2xzKCdoZWFkZXJUaXRsZScsICdhdGxhcy10aXRsZScpXCI+e3sgdCh0aXRsZUtleSkgfX08L2gxPlxuXG4gICAgICBAZm9yIChlcnJvciBvZiBmb3JtRXJyb3JzKCk7IHRyYWNrIGVycm9yLmNvZGUpIHtcbiAgICAgICAgPHAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiIHJvbGU9XCJhbGVydFwiPnt7IGVycm9yVGV4dChlcnJvcikgfX08L3A+XG4gICAgICB9XG5cbiAgICAgIDxmb3JtIChzdWJtaXQpPVwib25TdWJtaXQoJGV2ZW50KVwiPlxuICAgICAgICBAaWYgKGNvZGVTZW50VGV4dCgpOyBhcyBzZW50VGV4dCkge1xuICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXMtY29kZS1zZW50PVwiXCI+e3sgc2VudFRleHQgfX08L3A+XG4gICAgICAgIH1cbiAgICAgICAgQGlmIChsaW5rT25seSgpKSB7XG4gICAgICAgICAgPCEtLSBOb3RoaW5nIHRvIHR5cGU6IHRoZSBmbG93IHBvbGxzIHVudGlsIHRoZSBlbWFpbGVkIGxpbmsgaXMgb3BlbmVkIChhbnl3aGVyZSkuIC0tPlxuICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXMtbGluay1zZW50PVwiXCIgYXJpYS1saXZlPVwicG9saXRlXCI+XG4gICAgICAgICAgICB7eyB0KCdzaWduVXAubGlua1NlbnRUbycsIHsgZW1haWw6IGF0dGVtcHQ/LmlkZW50aWZpZXIgPz8gJycgfSkgfX1cbiAgICAgICAgICA8L3A+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblNlY29uZGFyeScsICdhdGxhcy1idXR0b24tc2Vjb25kYXJ5JylcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBkYXRhLWF0bGFzLXJlc2VuZD1cIlwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeVwiXG4gICAgICAgICAgICAoY2xpY2spPVwicmVzZW5kLmVtaXQoKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgdCgnc2lnbkluLnJlc2VuZExpbmsnKSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoZW5yb2xsaW5nKCkgJiYgZW5yb2xsbWVudFN0YXRlOyBhcyBlbnJvbCkge1xuICAgICAgICAgIEBpZiAoZW5yb2wubWV0aG9kID09PSBudWxsKSB7XG4gICAgICAgICAgICA8cCBjbGFzcz1cImF0bGFzLXRleHRcIj57eyB0KCdtZmEuZW5yb2xsQ2hvb3NlJykgfX08L3A+XG4gICAgICAgICAgICBAZm9yIChtIG9mIGVucm9sLm9wdGlvbnM7IHRyYWNrIG0pIHtcbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1CdXR0b25TZWNvbmRhcnknLCAnYXRsYXMtYnV0dG9uLXNlY29uZGFyeScpXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBbYXR0ci5kYXRhLWF0bGFzLW1mYS1tZXRob2RdPVwibVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImJ1c3kgfHwgZW5yb2wuYnVzeVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNob29zZU1ldGhvZChtKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyB0KG0gPT09ICd0b3RwJyA/ICdtZmEuZW5yb2xsVG90cE9wdGlvbicgOiAnbWZhLmVucm9sbFNtc09wdGlvbicpIH19XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gQGVsc2UgaWYgKGVucm9sLm1ldGhvZCA9PT0gJ3RvdHAnKSB7XG4gICAgICAgICAgICBAaWYgKGVucm9sLmVucm9sbG1lbnQ7IGFzIHNldHVwKSB7XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiPnt7IHQoJ21mYS5lbnJvbGxTY2FuJykgfX08L3A+XG4gICAgICAgICAgICAgIEBpZiAoc2V0dXAucXJDb2RlKSB7XG4gICAgICAgICAgICAgICAgPGltZyBjbGFzcz1cImF0bGFzLW1mYS1xclwiIGRhdGEtYXRsYXM9XCJtZmEtcXJcIiBbc3JjXT1cInNldHVwLnFyQ29kZVwiIFthbHRdPVwidCgnbWZhLmVucm9sbFFyQWx0JylcIiB3aWR0aD1cIjE4MFwiIGhlaWdodD1cIjE4MFwiIC8+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgQGlmIChzZXR1cC5zZWNyZXQpIHtcbiAgICAgICAgICAgICAgICA8cCBjbGFzcz1cImF0bGFzLXRleHRcIiBkYXRhLWF0bGFzPVwibWZhLXNldHVwLWtleVwiPnt7IHQoJ21mYS5lbnJvbGxTZXR1cEtleScpIH19OiA8Y29kZT57eyBzZXR1cEtleShzZXR1cC5zZWNyZXQpIH19PC9jb2RlPjwvcD5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJhdGxhcy1maWVsZFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IHQoJ21mYS5lbnJvbGxGaXJzdENvZGVMYWJlbCcpIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxpbnB1dCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRJbnB1dCcsICdhdGxhcy1pbnB1dCcpXCIgdHlwZT1cInRleHRcIiBuYW1lPVwiY29kZVwiIGF1dG9jb21wbGV0ZT1cIm9uZS10aW1lLWNvZGVcIiBpbnB1dG1vZGU9XCJudW1lcmljXCIgW3ZhbHVlXT1cInZhbHVlc1snY29kZSddID8/ICcnXCIgKGlucHV0KT1cInNldFZhbHVlKCdjb2RlJywgJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSlcIiAvPlxuICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICBAaWYgKGVucm9sLnRvdHBDb2RlcyA+PSAyKSB7XG4gICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiYXRsYXMtZmllbGRcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuPnt7IHQoJ21mYS5lbnJvbGxTZWNvbmRDb2RlTGFiZWwnKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxpbnB1dCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRJbnB1dCcsICdhdGxhcy1pbnB1dCcpXCIgdHlwZT1cInRleHRcIiBuYW1lPVwic2Vjb25kQ29kZVwiIGF1dG9jb21wbGV0ZT1cIm9uZS10aW1lLWNvZGVcIiBpbnB1dG1vZGU9XCJudW1lcmljXCIgW3ZhbHVlXT1cInZhbHVlc1snc2Vjb25kQ29kZSddID8/ICcnXCIgKGlucHV0KT1cInNldFZhbHVlKCdzZWNvbmRDb2RlJywgJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSlcIiAvPlxuICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8cCBjbGFzcz1cImF0bGFzLXRleHRcIiBhcmlhLWxpdmU9XCJwb2xpdGVcIj57eyBlbnJvbC5idXN5ID8gdCgnbWZhLmVucm9sbFByZXBhcmluZycpIDogJycgfX08L3A+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICBAaWYgKGVucm9sLmVucm9sbG1lbnQ7IGFzIHRleHRlZCkge1xuICAgICAgICAgICAgICA8cCBjbGFzcz1cImF0bGFzLXRleHRcIiBkYXRhLWF0bGFzPVwibWZhLWNvZGUtdGV4dGVkXCIgYXJpYS1saXZlPVwicG9saXRlXCI+e3sgdCgnbWZhLmNvZGVUZXh0ZWRUbycsIHsgcGhvbmU6IHRleHRlZC5waG9uZSA/PyAnJyB9KSB9fTwvcD5cbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiYXRsYXMtZmllbGRcIj5cbiAgICAgICAgICAgICAgICA8c3Bhbj57eyB0KCdtZmEuY29kZUxhYmVsJykgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPGlucHV0IFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZElucHV0JywgJ2F0bGFzLWlucHV0JylcIiB0eXBlPVwidGV4dFwiIG5hbWU9XCJjb2RlXCIgYXV0b2NvbXBsZXRlPVwib25lLXRpbWUtY29kZVwiIGlucHV0bW9kZT1cIm51bWVyaWNcIiBbdmFsdWVdPVwidmFsdWVzWydjb2RlJ10gPz8gJydcIiAoaW5wdXQpPVwic2V0VmFsdWUoJ2NvZGUnLCAkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiIC8+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uU2Vjb25kYXJ5JywgJ2F0bGFzLWJ1dHRvbi1zZWNvbmRhcnknKVwiXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgZGF0YS1hdGxhcy1yZXNlbmQ9XCJcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJidXN5IHx8IGVucm9sLmJ1c3lcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJyZXNlbmRFbnJvbGxtZW50KClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAge3sgdCgnc2lnbkluLnJlc2VuZENvZGUnKSB9fVxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJhdGxhcy1maWVsZFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IHQoJ21mYS5waG9uZUxhYmVsJykgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPGlucHV0IFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZElucHV0JywgJ2F0bGFzLWlucHV0JylcIiB0eXBlPVwidGVsXCIgbmFtZT1cInBob25lXCIgYXV0b2NvbXBsZXRlPVwidGVsXCIgW3ZhbHVlXT1cInZhbHVlc1sncGhvbmUnXSA/PyAnJ1wiIChpbnB1dCk9XCJzZXRWYWx1ZSgncGhvbmUnLCAkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiIC8+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiPnt7IHQoJ21mYS5waG9uZUhpbnQnKSB9fTwvcD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgQGZvciAoZXJyb3Igb2YgZW5yb2wuZXJyb3JzOyB0cmFjayAkaW5kZXgpIHtcbiAgICAgICAgICAgIDxwIFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZEVycm9yJywgJ2F0bGFzLWVycm9yJylcIiByb2xlPVwiYWxlcnRcIj57eyBlcnJvci5tZXNzYWdlIH19PC9wPlxuICAgICAgICAgIH1cbiAgICAgICAgICBAaWYgKGVucm9sLm1ldGhvZCAhPT0gbnVsbCAmJiBlbnJvbC5vcHRpb25zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIEBmb3IgKG90aGVyIG9mIG90aGVyTWV0aG9kcyhlbnJvbCk7IHRyYWNrIG90aGVyKSB7XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uU2Vjb25kYXJ5JywgJ2F0bGFzLWJ1dHRvbi1zZWNvbmRhcnknKVwiXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgW2F0dHIuZGF0YS1hdGxhcy1tZmEtbWV0aG9kXT1cIm90aGVyXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeSB8fCBlbnJvbC5idXN5XCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlTWV0aG9kKG90aGVyKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyB0KG90aGVyID09PSAndG90cCcgPyAnbWZhLmVucm9sbFRvdHBPcHRpb24nIDogJ21mYS5lbnJvbGxTbXNPcHRpb24nKSB9fVxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgQGZvciAoZiBvZiBmaWVsZHMoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgQGlmIChmLmtpbmQgPT09ICdpbnB1dCcpIHtcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImF0bGFzLWZpZWxkXCI+XG4gICAgICAgICAgICAgIDxzcGFuPnt7IHQoZi5sYWJlbEtleSkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZElucHV0JywgJ2F0bGFzLWlucHV0JylcIlxuICAgICAgICAgICAgICAgIFt0eXBlXT1cImYudHlwZVwiXG4gICAgICAgICAgICAgICAgW2F0dHIubmFtZV09XCJmLm5hbWVcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJ2YWx1ZXNbZi5uYW1lXSA/PyAnJ1wiXG4gICAgICAgICAgICAgICAgKGlucHV0KT1cInNldFZhbHVlKGYubmFtZSwgJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSlcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICBAZm9yIChlcnJvciBvZiBmaWVsZEVycm9yc0ZvcihmLm5hbWUpOyB0cmFjayBlcnJvci5jb2RlKSB7XG4gICAgICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiPnt7IGVycm9yVGV4dChlcnJvcikgfX08L3NwYW4+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgfSBAZWxzZSBpZiAoZi5raW5kID09PSAnYWxlcnQnKSB7XG4gICAgICAgICAgICA8cCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCIgcm9sZT1cImFsZXJ0XCI+e3sgdChmLmxhYmVsS2V5KSB9fTwvcD5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxwPnt7IHQoZi5sYWJlbEtleSkgfX08L3A+XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93Q2FwdGNoYSgpKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImF0bGFzLWNhcHRjaGFcIiBkYXRhLWF0bGFzLWNhcHRjaGE9XCJcIiBbYXRsYXNDYXB0Y2hhU2xvdF09XCJjYXB0Y2hhXCI+PC9kaXY+XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dTdWJtaXQoKSkge1xuICAgICAgICAgIDxidXR0b24gW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblByaW1hcnknLCAnYXRsYXMtYnV0dG9uJylcIiBbZGlzYWJsZWRdPVwiYnVzeSB8fCAoZW5yb2xsaW5nKCkgJiYgISFlbnJvbGxtZW50U3RhdGU/LmJ1c3kpXCIgdHlwZT1cInN1Ym1pdFwiPlxuICAgICAgICAgICAge3sgdChzdWJtaXRLZXkoKSkgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuXG4gICAgICAgIEBpZiAoc2hvd1Ntc1NlY29uZEZhY3RvcigpKSB7XG4gICAgICAgICAgQGlmIChzbXNTZWNvbmRGYWN0b3JTZW50VG8oKTsgYXMgc2VudFRvKSB7XG4gICAgICAgICAgICA8cCBjbGFzcz1cImF0bGFzLXRleHRcIiBkYXRhLWF0bGFzPVwic21zLXNlY29uZC1mYWN0b3Itc2VudFwiIGFyaWEtbGl2ZT1cInBvbGl0ZVwiPlxuICAgICAgICAgICAgICB7eyB0KCdtZmEuY29kZVRleHRlZFRvJywgeyBwaG9uZTogc2VudFRvIH0pIH19XG4gICAgICAgICAgICA8L3A+XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1CdXR0b25TZWNvbmRhcnknLCAnYXRsYXMtYnV0dG9uLXNlY29uZGFyeScpXCJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGRhdGEtYXRsYXM9XCJzbXMtc2Vjb25kLWZhY3RvclwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJidXN5IHx8ICEhdGV4dGVkU2Vjb25kRmFjdG9yPy5idXN5XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNtc1NlY29uZEZhY3Rvci5lbWl0KClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyB0ZXh0ZWRTZWNvbmRGYWN0b3I/LmJ1c3kgPyB0KCdzaWduSW4uc2VuZGluZycpIDogdCgnbWZhLnNtc0NvZGVPcHRpb24nKSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICBAaWYgKHRleHRlZFNlY29uZEZhY3Rvcj8uZXJyb3I7IGFzIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgPHAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiIHJvbGU9XCJhbGVydFwiPnt7IG1lc3NhZ2UgfX08L3A+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93RW1haWxTZWNvbmRGYWN0b3IoKSkge1xuICAgICAgICAgIEBpZiAoZW1haWxTZWNvbmRGYWN0b3JTZW50VG8oKTsgYXMgc2VudFRvKSB7XG4gICAgICAgICAgICA8cCBjbGFzcz1cImF0bGFzLXRleHRcIiBkYXRhLWF0bGFzPVwiZW1haWwtc2Vjb25kLWZhY3Rvci1zZW50XCIgYXJpYS1saXZlPVwicG9saXRlXCI+XG4gICAgICAgICAgICAgIHt7IHQoJ3NpZ25Jbi5jb2RlU2VudFRvJywgeyBlbWFpbDogc2VudFRvIH0pIH19XG4gICAgICAgICAgICA8L3A+XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1CdXR0b25TZWNvbmRhcnknLCAnYXRsYXMtYnV0dG9uLXNlY29uZGFyeScpXCJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGRhdGEtYXRsYXM9XCJlbWFpbC1zZWNvbmQtZmFjdG9yXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImJ1c3kgfHwgISFlbWFpbGVkU2Vjb25kRmFjdG9yPy5idXN5XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImVtYWlsU2Vjb25kRmFjdG9yLmVtaXQoKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IGVtYWlsZWRTZWNvbmRGYWN0b3I/LmJ1c3kgPyB0KCdzaWduSW4uc2VuZGluZycpIDogdCgnc2lnbkluLmVtYWlsQ29kZU9wdGlvbicpIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIEBpZiAoZW1haWxlZFNlY29uZEZhY3Rvcj8uZXJyb3I7IGFzIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgPHAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiIHJvbGU9XCJhbGVydFwiPnt7IG1lc3NhZ2UgfX08L3A+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93RW1haWxDb2RlT3B0aW9uKCkpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uU2Vjb25kYXJ5JywgJ2F0bGFzLWJ1dHRvbi1zZWNvbmRhcnknKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtc3RyYXRlZ3ldPVwicHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJyA/IG51bGwgOiAnZW1haWxfY29kZSdcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1hdGxhcy1yZXNlbmRdPVwicHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJyA/ICcnIDogbnVsbFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlRmFjdG9yLmVtaXQoJ2VtYWlsX2NvZGUnKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgdChwcmVwYXJlZEZhY3RvciA9PT0gJ2VtYWlsX2NvZGUnID8gJ3NpZ25Jbi5yZXNlbmRDb2RlJyA6ICdzaWduSW4udXNlRW1haWxDb2RlJykgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9mb3JtPlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBBdHRlbXB0Rmxvd0NvbXBvbmVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYXRsYXMgPSBpbmplY3QoQXRsYXNTZXJ2aWNlKTtcblxuICBASW5wdXQoKSBhdHRlbXB0OiBBdHRlbXB0VmlldyB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBidXN5ID0gZmFsc2U7XG4gIEBJbnB1dCgpIGVycm9yczogRmllbGRFcnJvcltdID0gW107XG4gIC8qKiBgRmxvd1N0YXRlLnNlc3Npb25LZXB0YDogd2hldGhlciB0aGlzIGJyb3dzZXIga2VwdCB0aGUgc2Vzc2lvbiB0aGUgc2lnbi1pbiBjcmVhdGVkLiAqL1xuICBASW5wdXQoKSBzZXNzaW9uS2VwdDogYm9vbGVhbiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgQElucHV0KCkgdGl0bGVLZXkgPSAnc2lnbkluLnRpdGxlJztcbiAgLyoqXG4gICAqIFRoZSBzaWduLWluIGNhcHRjaGEsIGRyYXduIGFib3ZlIHRoZSBzdWJtaXQgYnV0dG9uIG9uIHRoZSBpZGVudGlmaWVyIHN0ZXBcbiAgICogKGFuIGFsd2F5cy1vbiBzaWduLWluIGNhcHRjaGEpIGFuZCBvbiB0aGUgY2hhbGxlbmdlIHN0ZXAgdGhlIHNlcnZlciBkZW1hbmRzXG4gICAqIHdpdGggYG5lZWRzX2NhcHRjaGFgLiBOdWxsIHdoZW4gdGhlIGZsb3cgZHJhd3Mgbm9uZS5cbiAgICovXG4gIEBJbnB1dCgpIGNhcHRjaGE6IENhcHRjaGFDb250cm9sbGVyIHwgbnVsbCA9IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgZmlyc3QgZmFjdG9ycyB0byBvZmZlciBvbiB0aGUgYG5lZWRzX2ZpcnN0X2ZhY3RvcmAgc3RlcCDigJQgcGFzc1xuICAgKiBgQXRsYXNGbG93Q29udHJvbGxlci5maXJzdEZhY3RvcnMoKWAsIHdoaWNoIGRyb3BzIGVtYWlsIGNvZGUgLyBsaW5rIHdoaWxlIHRoZVxuICAgKiBhcHAgY2Fubm90IGRlbGl2ZXIgZW1haWwuIE51bGwgdXNlcyB0aGUgc2VydmVyJ3MgbGlzdCBhcy1pcy5cbiAgICovXG4gIEBJbnB1dCgpIGZpcnN0RmFjdG9yczogc3RyaW5nW10gfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBmaXJzdCBmYWN0b3IgYWxyZWFkeSBzZW50IChgQXRsYXNGbG93Q29udHJvbGxlci5wcmVwYXJlZEZhY3RvcigpYCk6IGl0cyBjb2RlIGlzIGNvbGxlY3RlZC4gKi9cbiAgQElucHV0KCkgcHJlcGFyZWRGYWN0b3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBFbWl0cyB0aGUgY29sbGVjdGVkIGZpZWxkIHZhbHVlcyB3aGVuIHRoZSBmb3JtIGlzIHN1Ym1pdHRlZC4gKi9cbiAgQE91dHB1dCgpIHN1Ym1pdEZsb3cgPSBuZXcgRXZlbnRFbWl0dGVyPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+KCk7XG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHBpY2tzIGEgZmlyc3QgZmFjdG9yIHRoZSBzZXJ2ZXIgbXVzdCBzZW5kIGZpcnN0IChhbiBlbWFpbGVkIGNvZGUpLiAqL1xuICBAT3V0cHV0KCkgY2hvb3NlRmFjdG9yID0gbmV3IEV2ZW50RW1pdHRlcjwnZW1haWxfY29kZSc+KCk7XG4gIC8qKlxuICAgKiBPZmZlciBcIkVtYWlsIG1lIGEgY29kZSBpbnN0ZWFkXCIgYXQgdGhlIHNlY29uZCBmYWN0b3IgKHRoZSBpbnN0YW5jZSdzXG4gICAqIGBhY2NvdW50LmVtYWlsU2Vjb25kRmFjdG9yYCk7IGBlbWFpbFNlY29uZEZhY3RvcmAgYXNrcyBmb3IgaXQgYW5kXG4gICAqIGBlbWFpbGVkU2Vjb25kRmFjdG9yYCByZXBvcnRzIGhvdyBpdCB3ZW50LlxuICAgKi9cbiAgQElucHV0KCkgb2ZmZXJFbWFpbFNlY29uZEZhY3RvciA9IGZhbHNlO1xuICAvKiogYEF0bGFzRmxvd0NvbnRyb2xsZXIuZW1haWxTZWNvbmRGYWN0b3IoKWA6IGluIGZsaWdodCwgd2hlcmUgaXQgd2VudCwgb3Igd2h5IG5vdC4gKi9cbiAgQElucHV0KCkgZW1haWxlZFNlY29uZEZhY3RvcjogeyBidXN5PzogYm9vbGVhbjsgc2VudFRvPzogc3RyaW5nOyBlcnJvcj86IHN0cmluZyB9IHwgbnVsbCA9IG51bGw7XG4gIEBPdXRwdXQoKSBlbWFpbFNlY29uZEZhY3RvciA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqXG4gICAqIE9mZmVyIFwiVGV4dCBtZSBhIGNvZGUgaW5zdGVhZFwiIGF0IHRoZSBzZWNvbmQgZmFjdG9yICh3aGVyZSB0aGUgYXBwIG9mZmVyc1xuICAgKiB0ZXh0ZWQgY29kZXMsIGBBdGxhc0Zsb3dDb250cm9sbGVyLm1mYUNob2ljZXMoKS5zbXNgKTsgYHNtc1NlY29uZEZhY3RvcmBcbiAgICogYXNrcyBmb3IgaXQgYW5kIGB0ZXh0ZWRTZWNvbmRGYWN0b3JgIHJlcG9ydHMgaG93IGl0IHdlbnQuXG4gICAqL1xuICBASW5wdXQoKSBvZmZlclNtc1NlY29uZEZhY3RvciA9IGZhbHNlO1xuICAvKiogYEF0bGFzRmxvd0NvbnRyb2xsZXIuc21zU2Vjb25kRmFjdG9yKClgOiBpbiBmbGlnaHQsIHdoZXJlIGl0IHdlbnQsIG9yIHdoeSBub3QuICovXG4gIEBJbnB1dCgpIHRleHRlZFNlY29uZEZhY3RvcjogeyBidXN5PzogYm9vbGVhbjsgc2VudFRvPzogc3RyaW5nOyBlcnJvcj86IHN0cmluZyB9IHwgbnVsbCA9IG51bGw7XG4gIEBPdXRwdXQoKSBzbXNTZWNvbmRGYWN0b3IgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIC8qKlxuICAgKiBUaGUgTUZBIGVucm9sbWVudCBzdGVwIChgQXRsYXNGbG93Q29udHJvbGxlci5lbnJvbGxtZW50YCBhbmRcbiAgICogYGVucm9sbG1lbnRTdGF0ZSgpYCk6IHRoZSBhdXRoZW50aWNhdG9yIGFwcCdzIFFSIGNvZGUgYW5kIHNldHVwIGtleSwgb3IgYVxuICAgKiB0ZXh0ZWQgY29kZS4gTnVsbDogdGhlIHN0ZXAgYXNrcyBmb3IgdHdvIGF1dGhlbnRpY2F0b3IgY29kZXMgb25seS5cbiAgICovXG4gIEBJbnB1dCgpIGVucm9sbG1lbnQ6IE1mYUVucm9sbG1lbnRDb250cm9sbGVyIHwgbnVsbCA9IG51bGw7XG4gIEBJbnB1dCgpIGVucm9sbG1lbnRTdGF0ZTogTWZhRW5yb2xsbWVudFN0YXRlIHwgbnVsbCA9IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgaW5zdGFuY2UncyBgYWNjb3VudC5lbWFpbFZlcmlmaWNhdGlvbmAuIE9uIGBsaW5rYCBhIHNpZ24tdXAnc1xuICAgKiB2ZXJpZmljYXRpb24gc3RlcCBoYXMgbm90aGluZyB0byB0eXBlOiBpdCBzYXlzIHRvIG9wZW4gdGhlIGVtYWlsZWQgbGlua1xuICAgKiB3aGlsZSB0aGUgZmxvdyBwb2xscywgYW5kIG9mZmVycyBhIHJlc2VuZCAoYHJlc2VuZGApLlxuICAgKi9cbiAgQElucHV0KCkgZW1haWxWZXJpZmljYXRpb246IHN0cmluZyA9ICdjb2RlJztcbiAgQE91dHB1dCgpIHJlc2VuZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBwcm90ZWN0ZWQgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgcHJvdGVjdGVkIHQoa2V5OiBzdHJpbmcsIHZhcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogc3RyaW5nIHtcbiAgICByZXR1cm4gdHJhbnNsYXRlKHRoaXMuYXRsYXMubG9jYWxpemF0aW9uLCBrZXksIHZhcnMpO1xuICB9XG5cbiAgLyoqIEEgc2VydmVyIGVycm9yIGluIHRoZSBhcHAncyBsYW5ndWFnZSAoYGVycm9yLjxyZWFzb24+YCwgZWxzZSB0aGUgc2VydmVyJ3MgbWVzc2FnZSkuICovXG4gIHByb3RlY3RlZCBlcnJvclRleHQoZXJyb3I6IEZpZWxkRXJyb3IpOiBzdHJpbmcge1xuICAgIC8vIGBlcnJvckxvY2FsaXphdGlvbmAgaXMgcmVhZCBkZWZlbnNpdmVseTogYSBzdGFuZC1pbiBzZXJ2aWNlIG1heSBsYWNrIGl0LlxuICAgIGNvbnN0IGxheWVyID0gKHRoaXMuYXRsYXMgYXMgeyBlcnJvckxvY2FsaXphdGlvbj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfSkuZXJyb3JMb2NhbGl6YXRpb247XG4gICAgcmV0dXJuIGxvY2FsaXplZEVycm9yTWVzc2FnZShlcnJvciwgbGF5ZXIgPz8gdGhpcy5hdGxhcy5sb2NhbGl6YXRpb24sIHRoaXMuYXRsYXMubG9jYWxpemF0aW9uKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjbHMoa2V5OiBFbGVtZW50S2V5LCBiYXNlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBjbGFzc0ZvcihrZXksIHRoaXMuYXRsYXMuYXBwZWFyYW5jZSwgYmFzZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0VmFsdWUobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZXMgPSB7IC4uLnRoaXMudmFsdWVzLCBbbmFtZV06IHZhbHVlIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgb25TdWJtaXQoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAvLyBFbnJvbG1lbnQ6IHRleHQgdGhlIGNvZGUgdG8gdGhlIHR5cGVkIG51bWJlciwgb3IgY29uZmlybSB0aGUgZmFjdG9yLlxuICAgIGlmICh0aGlzLmVucm9sbGluZygpICYmIHRoaXMuZW5yb2xsbWVudCkge1xuICAgICAgdm9pZCB0aGlzLmVucm9sbG1lbnQuc3VibWl0KHRoaXMudmFsdWVzKS50aGVuKChuZXh0KSA9PiB7XG4gICAgICAgIGlmIChuZXh0KSB0aGlzLnN1Ym1pdEZsb3cuZW1pdChuZXh0KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnN1Ym1pdEZsb3cuZW1pdCh0aGlzLnZhbHVlcyk7XG4gIH1cblxuICAvKiogVGhlIHNoYXJlZCBlbnJvbG1lbnQgc3RlcCBpcyBkcmF3biAoYSBjb250cm9sbGVyIHdhcyBwYXNzZWQgYW5kIHRoZSBmbG93IGlzIGVucm9sbGluZykuICovXG4gIHByb3RlY3RlZCBlbnJvbGxpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc3RlcCgpLmtpbmQgPT09ICdlbnJvbGxfc2Vjb25kX2ZhY3RvcicgJiYgISF0aGlzLmVucm9sbG1lbnQgJiYgISF0aGlzLmVucm9sbG1lbnRTdGF0ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjaG9vc2VNZXRob2QobWV0aG9kOiBNZmFFbnJvbGxtZW50U3RyYXRlZ3kpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlcyA9IHt9O1xuICAgIHZvaWQgdGhpcy5lbnJvbGxtZW50Py5jaG9vc2UobWV0aG9kKTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZXNlbmRFbnJvbGxtZW50KCk6IHZvaWQge1xuICAgIHZvaWQgdGhpcy5lbnJvbGxtZW50Py5yZXNlbmQoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdGhlck1ldGhvZHMoc3RhdGU6IE1mYUVucm9sbG1lbnRTdGF0ZSk6IE1mYUVucm9sbG1lbnRTdHJhdGVneVtdIHtcbiAgICByZXR1cm4gc3RhdGUub3B0aW9ucy5maWx0ZXIoKG0pID0+IG0gIT09IHN0YXRlLm1ldGhvZCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0dXBLZXkoc2VjcmV0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBncm91cFNldHVwS2V5KHNlY3JldCk7XG4gIH1cblxuICAvKiogVGhlIHN1Ym1pdCBidXR0b24ncyBsYWJlbCBrZXkgKGVucm9sbWVudDogXCJUZXh0IG1lIGEgY29kZVwiIGJlZm9yZSB0aGUgbnVtYmVyIGlzIHNlbnQpLiAqL1xuICBwcm90ZWN0ZWQgc3VibWl0S2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICh0aGlzLmVucm9sbGluZygpICYmIHRoaXMuZW5yb2xsbWVudFN0YXRlICYmIGVucm9sbG1lbnRTdWJtaXRLZXkodGhpcy5lbnJvbGxtZW50U3RhdGUpKSB8fCAnc2lnbkluLnN1Ym1pdCc7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd1Ntc1NlY29uZEZhY3RvcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5vZmZlclNtc1NlY29uZEZhY3RvciAmJiB0aGlzLnN0ZXAoKS5raW5kID09PSAnY29sbGVjdF9zZWNvbmRfZmFjdG9yJztcbiAgfVxuXG4gIC8qKiBXaGVyZSB0aGUgdGV4dGVkIHNlY29uZC1mYWN0b3IgY29kZSB3ZW50IChtYXNrZWQpLCBvbmNlIGl0IHdhcyBzZW50LiAqL1xuICBwcm90ZWN0ZWQgc21zU2Vjb25kRmFjdG9yU2VudFRvKCk6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IHNlbnQgPSB0aGlzLnRleHRlZFNlY29uZEZhY3Rvcj8uc2VudFRvO1xuICAgIHJldHVybiB0eXBlb2Ygc2VudCA9PT0gJ3N0cmluZycgPyBzZW50IHx8ICcgJyA6IG51bGw7XG4gIH1cblxuICBwcm90ZWN0ZWQgZm9ybUVycm9ycygpOiBGaWVsZEVycm9yW10ge1xuICAgIHJldHVybiB0aGlzLmVycm9ycy5maWx0ZXIoKGVycm9yKSA9PiAhZXJyb3IucGFyYW0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkRXJyb3JzRm9yKG5hbWU6IHN0cmluZyk6IEZpZWxkRXJyb3JbXSB7XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JzLmZpbHRlcigoZXJyb3IpID0+IGVycm9yLnBhcmFtID09PSBuYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RlcCgpIHtcbiAgICByZXR1cm4gdGhpcy5hdHRlbXB0ID8gbmV4dFN0ZXAodGhpcy5hdHRlbXB0KSA6ICh7IGtpbmQ6ICdjb2xsZWN0X2lkZW50aWZpZXInIH0gYXMgY29uc3QpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNob3dDYXB0Y2hhKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGtpbmQgPSB0aGlzLnN0ZXAoKS5raW5kO1xuICAgIHJldHVybiAhIXRoaXMuY2FwdGNoYSAmJiAoa2luZCA9PT0gJ2NvbGxlY3RfaWRlbnRpZmllcicgfHwga2luZCA9PT0gJ2NvbGxlY3RfY2FwdGNoYScpO1xuICB9XG5cbiAgLyoqIFRoZSBmaXJzdCBmYWN0b3JzIG9uIG9mZmVyIGF0IGEgYG5lZWRzX2ZpcnN0X2ZhY3RvcmAgc3RlcCAoZW1wdHkgb24gYW55IG90aGVyKS4gKi9cbiAgcHJpdmF0ZSBvZmZlcmVkKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBzdGVwID0gdGhpcy5zdGVwKCk7XG4gICAgaWYgKHN0ZXAua2luZCAhPT0gJ2NvbGxlY3RfZmlyc3RfZmFjdG9yJykgcmV0dXJuIFtdO1xuICAgIHJldHVybiB0aGlzLmZpcnN0RmFjdG9ycyA/PyBzdGVwLnN0cmF0ZWdpZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbGlua09ubHkoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF3YWl0aW5nU2lnblVwTGluayh0aGlzLmF0dGVtcHQsIHRoaXMuZW1haWxWZXJpZmljYXRpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNob3dFbWFpbFNlY29uZEZhY3RvcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5vZmZlckVtYWlsU2Vjb25kRmFjdG9yICYmIHRoaXMuc3RlcCgpLmtpbmQgPT09ICdjb2xsZWN0X3NlY29uZF9mYWN0b3InO1xuICB9XG5cbiAgLyoqIFdoZXJlIHRoZSBlbWFpbGVkIHNlY29uZC1mYWN0b3IgY29kZSB3ZW50IChtYXNrZWQpLCBvbmNlIGl0IHdhcyBzZW50LiAqL1xuICBwcm90ZWN0ZWQgZW1haWxTZWNvbmRGYWN0b3JTZW50VG8oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3Qgc2VudCA9IHRoaXMuZW1haWxlZFNlY29uZEZhY3Rvcj8uc2VudFRvO1xuICAgIHJldHVybiB0eXBlb2Ygc2VudCA9PT0gJ3N0cmluZycgPyBzZW50IHx8ICcgJyA6IG51bGw7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd0VtYWlsQ29kZU9wdGlvbigpOiBib29sZWFuIHtcbiAgICAvLyBCZWZvcmUgdGhlIGNvZGUgaXMgc2VudDogdGhlIGNob2ljZSAob3IgdGhlIHJldHJ5IG9mIGEgZmFpbGVkIGF1dG9tYXRpY1xuICAgIC8vIHNlbmQpLiBBZnRlcjogXCJSZXNlbmQgY29kZVwiLlxuICAgIHJldHVybiB0aGlzLm9mZmVyZWQoKS5pbmNsdWRlcygnZW1haWxfY29kZScpO1xuICB9XG5cbiAgLyoqIFRoZSBcIndlIHNlbnQgYSBjb2RlIHRvIOKAplwiIGxpbmUgb24gdGhlIGNvZGUgc3RlcC4gKi9cbiAgcHJvdGVjdGVkIGNvZGVTZW50VGV4dCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAodGhpcy5zdGVwKCkua2luZCAhPT0gJ2NvbGxlY3RfZmlyc3RfZmFjdG9yJyB8fCB0aGlzLnByZXBhcmVkRmFjdG9yICE9PSAnZW1haWxfY29kZScpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB0aGlzLnQoJ3NpZ25Jbi5jb2RlU2VudFRvJywgeyBlbWFpbDogdGhpcy5hdHRlbXB0Py5pZGVudGlmaWVyID8/ICcnIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNob3dTdWJtaXQoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qga2luZCA9IHRoaXMuc3RlcCgpLmtpbmQ7XG4gICAgLy8gTm90aGluZyB0byBzdWJtaXQgb24gYSBmaXJzdC1mYWN0b3Igc3RlcCB0aGF0IG9ubHkgb2ZmZXJzIGFuIGVtYWlsZWQgY29kZVxuICAgIC8vIHVudGlsIHRoYXQgY29kZSBpcyBzZW50LlxuICAgIGlmIChraW5kID09PSAnY29sbGVjdF9maXJzdF9mYWN0b3InKSByZXR1cm4gdGhpcy5maWVsZHMoKS5sZW5ndGggPiAwO1xuICAgIGlmICh0aGlzLmxpbmtPbmx5KCkpIHJldHVybiBmYWxzZTtcbiAgICAvLyBFbnJvbG1lbnQ6IG5vdGhpbmcgdG8gc3VibWl0IHdoaWxlIGNob29zaW5nIGEgbWV0aG9kIG9yIGZldGNoaW5nIHRoZSBzZXR1cC5cbiAgICBpZiAodGhpcy5lbnJvbGxpbmcoKSAmJiB0aGlzLmVucm9sbG1lbnRTdGF0ZSAmJiAhZW5yb2xsbWVudFN1Ym1pdEtleSh0aGlzLmVucm9sbG1lbnRTdGF0ZSkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4ga2luZCAhPT0gJ2RvbmUnICYmIGtpbmQgIT09ICdhd2FpdF9vYXV0aCc7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRzKCk6IFN0ZXBGaWVsZFtdIHtcbiAgICBjb25zdCBzdGVwID0gdGhpcy5zdGVwKCk7XG4gICAgc3dpdGNoIChzdGVwLmtpbmQpIHtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfaWRlbnRpZmllcic6XG4gICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnaWRlbnRpZmllcicsIGxhYmVsS2V5OiAnc2lnbkluLmlkZW50aWZpZXJMYWJlbCcsIHR5cGU6ICdlbWFpbCcgfV07XG4gICAgICBjYXNlICdjb2xsZWN0X2ZpcnN0X2ZhY3Rvcic6IHtcbiAgICAgICAgaWYgKHRoaXMucHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJykge1xuICAgICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnY29kZScsIGxhYmVsS2V5OiAnc2lnbkluLmVtYWlsQ29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBwYXNzd29yZCBmaWVsZCB1bmxlc3MgdGhlIG9ubHkgb2ZmZXIgaXMgYW4gZW1haWxlZCBjb2RlIChjaG9zZW5cbiAgICAgICAgLy8gd2l0aCB0aGUgYnV0dG9uIGJlbG93IHRoZSBmb3JtKS5cbiAgICAgICAgY29uc3Qgb2ZmZXJlZCA9IHRoaXMub2ZmZXJlZCgpO1xuICAgICAgICByZXR1cm4gb2ZmZXJlZC5pbmNsdWRlcygnZW1haWxfY29kZScpICYmICFvZmZlcmVkLmluY2x1ZGVzKCdwYXNzd29yZCcpXG4gICAgICAgICAgPyBbXVxuICAgICAgICAgIDogW3sga2luZDogJ2lucHV0JywgbmFtZTogJ3Bhc3N3b3JkJywgbGFiZWxLZXk6ICdzaWduSW4ucGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICB9XG4gICAgICBjYXNlICdjb2xsZWN0X3NlY29uZF9mYWN0b3InOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ21mYS5jb2RlTGFiZWwnLCB0eXBlOiAndGV4dCcgfV07XG4gICAgICBjYXNlICdlbnJvbGxfc2Vjb25kX2ZhY3Rvcic6XG4gICAgICAgIC8vIFRoZSBzaGFyZWQgZW5yb2xtZW50IHN0ZXAgZHJhd3MgaXRzIG93biBmaWVsZHMgKGFib3ZlKS5cbiAgICAgICAgaWYgKHRoaXMuZW5yb2xsaW5nKCkpIHJldHVybiBbXTtcbiAgICAgICAgLy8gVHdvIGNvbnNlY3V0aXZlIGNvZGVzICjCpzUuNik6IGEgcGhvbmUgd2l0aCBhIGZhc3QgY2xvY2sgZmFpbHMgaGVyZVxuICAgICAgICAvLyByYXRoZXIgdGhhbiBvbiBldmVyeSBzaWduLWluIGFmdGVyd2FyZHMuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnY29kZScsIGxhYmVsS2V5OiAnbWZhLmVucm9sbEZpcnN0Q29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH0sXG4gICAgICAgICAgeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnc2Vjb25kQ29kZScsIGxhYmVsS2V5OiAnbWZhLmVucm9sbFNlY29uZENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9LFxuICAgICAgICBdO1xuICAgICAgY2FzZSAnY29sbGVjdF9lbWFpbF9jb2RlJzpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlua09ubHkoKSA/IFtdIDogW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ3NpZ25Jbi5lbWFpbENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9XTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfbmV3X3Bhc3N3b3JkJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdwYXNzd29yZCcsIGxhYmVsS2V5OiAncmVzZXQubmV3UGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICBjYXNlICdjb2xsZWN0X2NhcHRjaGEnOlxuICAgICAgICAvLyDCpzUgdGhlIHNlcnZlciB3aXRoaGVsZCB0aGUgYXR0ZW1wdCB1bnRpbCBhIGNhcHRjaGEgY2xlYXJzLiBTb2x2aW5nIHRoZVxuICAgICAgICAvLyB3aWRnZXQgcmVzdWJtaXRzIHRoZSBpZGVudGlmaWVyIG9uIGl0cyBvd247IHRoZSBidXR0b24gcmV0cmllcy5cbiAgICAgICAgcmV0dXJuIFttc2coJ2NhcHRjaGEucHJvbXB0JyldO1xuICAgICAgY2FzZSAnYXdhaXRfb2F1dGgnOlxuICAgICAgICByZXR1cm4gW21zZygnc2lnbkluLm1hZ2ljTGlua1NlbnQnKV07XG4gICAgICBjYXNlICdkb25lJzpcbiAgICAgICAgLy8gU2lnbmVkIGluIG9ubHkgd2hlbiB0aGlzIGJyb3dzZXIgaG9sZHMgdGhlIHNlc3Npb247IGEgYmxvY2tlZCBjb29raWUgaXMgc2FpZFxuICAgICAgICAvLyBwbGFpbmx5LiBcIkNoZWNrIHRoZSBvdGhlciB0YWJcIiBpcyBmb3IgYSBzaWduLWluIGNvbXBsZXRlZCBvbiBhbm90aGVyIGRldmljZS5cbiAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbktlcHQgPT09IHRydWUpIHJldHVybiBbbXNnKCdzaWduSW4uc2lnbmVkSW4nKV07XG4gICAgICAgIGlmICh0aGlzLnNlc3Npb25LZXB0ID09PSBmYWxzZSkgcmV0dXJuIFt7IGtpbmQ6ICdhbGVydCcsIG5hbWU6ICcnLCBsYWJlbEtleTogJ3NpZ25Jbi5zZXNzaW9uTm90S2VwdCcsIHR5cGU6ICd0ZXh0JyB9XTtcbiAgICAgICAgcmV0dXJuIFttc2coJ3NpZ25Jbi5jaGVja090aGVyVGFiJyldO1xuICAgICAgY2FzZSAncmVzdGFydCc6XG4gICAgICAgIHJldHVybiBbbXNnKCdlcnJvci5nZW5lcmljJyldO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gQSBzdGF0dXMgdGhpcyBTREsgdmVyc2lvbiBkb2VzIG5vdCBrbm93LiBBbiBob25lc3QgbWVzc2FnZSBiZWF0cyBhXG4gICAgICAgIC8vIGJsYW5rIGxvZ2luIGJveCB0aGUgdXNlciBjYW5ub3QgYWN0IG9uLlxuICAgICAgICByZXR1cm4gW21zZygnZXJyb3IuZ2VuZXJpYycpXTtcbiAgICB9XG4gIH1cbn1cblxuLyoqIEEgcmVhZC1vbmx5IG1lc3NhZ2Ugcm93OiBgbGFiZWxLZXlgIGhvbGRzIHRoZSBpMThuIGtleSBvZiB0aGUgdGV4dCB0byBzaG93LiAqL1xuZnVuY3Rpb24gbXNnKGxhYmVsS2V5OiBzdHJpbmcpOiBTdGVwRmllbGQge1xuICByZXR1cm4geyBraW5kOiAnbWVzc2FnZScsIG5hbWU6ICcnLCBsYWJlbEtleSwgdHlwZTogJ3RleHQnIH07XG59XG4iXX0=