@atlasauth/angular 0.8.0 → 0.10.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 (41) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/esm2022/lib/appearance.mjs +1 -1
  3. package/dist/esm2022/lib/atlas.service.mjs +40 -3
  4. package/dist/esm2022/lib/atlas.ui.mjs +7 -1
  5. package/dist/esm2022/lib/components/attempt-flow.component.mjs +419 -11
  6. package/dist/esm2022/lib/components/flow-controller.mjs +132 -2
  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/policy-host.mjs +254 -0
  12. package/dist/esm2022/lib/components/recovery-codes.component.mjs +122 -0
  13. package/dist/esm2022/lib/components/sign-in.component.mjs +47 -4
  14. package/dist/esm2022/lib/components/sign-up-form.component.mjs +136 -10
  15. package/dist/esm2022/lib/components/sign-up.component.mjs +86 -8
  16. package/dist/esm2022/lib/i18n.mjs +61 -1
  17. package/dist/esm2022/lib/provide-atlas.mjs +4 -2
  18. package/dist/esm2022/lib/types.mjs +1 -1
  19. package/dist/esm2022/lib/version.mjs +2 -2
  20. package/dist/esm2022/public-api.mjs +6 -1
  21. package/dist/fesm2022/atlasauth-angular.mjs +2129 -95
  22. package/dist/fesm2022/atlasauth-angular.mjs.map +1 -1
  23. package/dist/lib/appearance.d.ts +1 -1
  24. package/dist/lib/atlas.service.d.ts +23 -1
  25. package/dist/lib/atlas.ui.d.ts +3 -1
  26. package/dist/lib/components/attempt-flow.component.d.ts +61 -2
  27. package/dist/lib/components/flow-controller.d.ts +73 -1
  28. package/dist/lib/components/impersonation-banner.component.d.ts +27 -0
  29. package/dist/lib/components/organization-audit-log.component.d.ts +34 -0
  30. package/dist/lib/components/organization-audit-log.d.ts +25 -0
  31. package/dist/lib/components/organization-profile.component.d.ts +55 -6
  32. package/dist/lib/components/policy-host.d.ts +88 -0
  33. package/dist/lib/components/recovery-codes.component.d.ts +26 -0
  34. package/dist/lib/components/sign-in.component.d.ts +2 -0
  35. package/dist/lib/components/sign-up-form.component.d.ts +22 -4
  36. package/dist/lib/components/sign-up.component.d.ts +13 -0
  37. package/dist/lib/provide-atlas.d.ts +3 -1
  38. package/dist/lib/types.d.ts +6 -0
  39. package/dist/lib/version.d.ts +1 -1
  40. package/dist/public-api.d.ts +5 -0
  41. package/package.json +3 -3
@@ -1,7 +1,8 @@
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
+ import { PolicyAcceptStepComponent } from './policy-host';
5
6
  import { classFor } from '../appearance';
6
7
  import { translate } from '../i18n';
7
8
  import * as i0 from "@angular/core";
@@ -41,6 +42,40 @@ export class AttemptFlowComponent {
41
42
  submitFlow = new EventEmitter();
42
43
  /** Emits when the user picks a first factor the server must send first (an emailed code). */
43
44
  chooseFactor = new EventEmitter();
45
+ /**
46
+ * Offer "Email me a code instead" at the second factor (the instance's
47
+ * `account.emailSecondFactor`); `emailSecondFactor` asks for it and
48
+ * `emailedSecondFactor` reports how it went.
49
+ */
50
+ offerEmailSecondFactor = false;
51
+ /** `AtlasFlowController.emailSecondFactor()`: in flight, where it went, or why not. */
52
+ emailedSecondFactor = null;
53
+ emailSecondFactor = new EventEmitter();
54
+ /**
55
+ * Offer "Text me a code instead" at the second factor (where the app offers
56
+ * texted codes, `AtlasFlowController.mfaChoices().sms`); `smsSecondFactor`
57
+ * asks for it and `textedSecondFactor` reports how it went.
58
+ */
59
+ offerSmsSecondFactor = false;
60
+ /** `AtlasFlowController.smsSecondFactor()`: in flight, where it went, or why not. */
61
+ textedSecondFactor = null;
62
+ smsSecondFactor = new EventEmitter();
63
+ /**
64
+ * The MFA enrolment step (`AtlasFlowController.enrollment` and
65
+ * `enrollmentState()`): the authenticator app's QR code and setup key, or a
66
+ * texted code. Null: the step asks for two authenticator codes only.
67
+ */
68
+ enrollment = null;
69
+ enrollmentState = null;
70
+ /**
71
+ * The instance's `account.emailVerification`. On `link` a sign-up's
72
+ * verification step has nothing to type: it says to open the emailed link
73
+ * while the flow polls, and offers a resend (`resend`).
74
+ */
75
+ emailVerification = 'code';
76
+ resend = new EventEmitter();
77
+ /** The user declined a policy the sign-in was waiting on (`needs_policy_acceptance`): cancel the attempt. */
78
+ policyDeclined = new EventEmitter();
44
79
  values = {};
45
80
  t(key, vars) {
46
81
  return translate(this.atlas.localization, key, vars);
@@ -59,8 +94,45 @@ export class AttemptFlowComponent {
59
94
  }
60
95
  onSubmit(event) {
61
96
  event.preventDefault();
97
+ // Enrolment: text the code to the typed number, or confirm the factor.
98
+ if (this.enrolling() && this.enrollment) {
99
+ void this.enrollment.submit(this.values).then((next) => {
100
+ if (next)
101
+ this.submitFlow.emit(next);
102
+ });
103
+ return;
104
+ }
62
105
  this.submitFlow.emit(this.values);
63
106
  }
107
+ /** The shared enrolment step is drawn (a controller was passed and the flow is enrolling). */
108
+ enrolling() {
109
+ return this.step().kind === 'enroll_second_factor' && !!this.enrollment && !!this.enrollmentState;
110
+ }
111
+ chooseMethod(method) {
112
+ this.values = {};
113
+ void this.enrollment?.choose(method);
114
+ }
115
+ resendEnrollment() {
116
+ void this.enrollment?.resend();
117
+ }
118
+ otherMethods(state) {
119
+ return state.options.filter((m) => m !== state.method);
120
+ }
121
+ setupKey(secret) {
122
+ return groupSetupKey(secret);
123
+ }
124
+ /** The submit button's label key (enrolment: "Text me a code" before the number is sent). */
125
+ submitKey() {
126
+ return (this.enrolling() && this.enrollmentState && enrollmentSubmitKey(this.enrollmentState)) || 'signIn.submit';
127
+ }
128
+ showSmsSecondFactor() {
129
+ return this.offerSmsSecondFactor && this.step().kind === 'collect_second_factor';
130
+ }
131
+ /** Where the texted second-factor code went (masked), once it was sent. */
132
+ smsSecondFactorSentTo() {
133
+ const sent = this.textedSecondFactor?.sentTo;
134
+ return typeof sent === 'string' ? sent || ' ' : null;
135
+ }
64
136
  formErrors() {
65
137
  return this.errors.filter((error) => !error.param);
66
138
  }
@@ -81,6 +153,17 @@ export class AttemptFlowComponent {
81
153
  return [];
82
154
  return this.firstFactors ?? step.strategies;
83
155
  }
156
+ linkOnly() {
157
+ return awaitingSignUpLink(this.attempt, this.emailVerification);
158
+ }
159
+ showEmailSecondFactor() {
160
+ return this.offerEmailSecondFactor && this.step().kind === 'collect_second_factor';
161
+ }
162
+ /** Where the emailed second-factor code went (masked), once it was sent. */
163
+ emailSecondFactorSentTo() {
164
+ const sent = this.emailedSecondFactor?.sentTo;
165
+ return typeof sent === 'string' ? sent || ' ' : null;
166
+ }
84
167
  showEmailCodeOption() {
85
168
  // Before the code is sent: the choice (or the retry of a failed automatic
86
169
  // send). After: "Resend code".
@@ -92,13 +175,22 @@ export class AttemptFlowComponent {
92
175
  return null;
93
176
  return this.t('signIn.codeSentTo', { email: this.attempt?.identifier ?? '' });
94
177
  }
178
+ /** The attempt is `needs_policy_acceptance`. */
179
+ awaitingPolicies() {
180
+ return this.step().kind === 'accept_policies';
181
+ }
95
182
  showSubmit() {
96
183
  const kind = this.step().kind;
97
184
  // Nothing to submit on a first-factor step that only offers an emailed code
98
185
  // until that code is sent.
99
186
  if (kind === 'collect_first_factor')
100
187
  return this.fields().length > 0;
101
- return kind !== 'done' && kind !== 'await_oauth';
188
+ if (this.linkOnly())
189
+ return false;
190
+ // Enrolment: nothing to submit while choosing a method or fetching the setup.
191
+ if (this.enrolling() && this.enrollmentState && !enrollmentSubmitKey(this.enrollmentState))
192
+ return false;
193
+ return kind !== 'done' && kind !== 'await_oauth' && kind !== 'accept_policies';
102
194
  }
103
195
  fields() {
104
196
  const step = this.step();
@@ -119,6 +211,9 @@ export class AttemptFlowComponent {
119
211
  case 'collect_second_factor':
120
212
  return [{ kind: 'input', name: 'code', labelKey: 'mfa.codeLabel', type: 'text' }];
121
213
  case 'enroll_second_factor':
214
+ // The shared enrolment step draws its own fields (above).
215
+ if (this.enrolling())
216
+ return [];
122
217
  // Two consecutive codes (§5.6): a phone with a fast clock fails here
123
218
  // rather than on every sign-in afterwards.
124
219
  return [
@@ -126,9 +221,12 @@ export class AttemptFlowComponent {
126
221
  { kind: 'input', name: 'secondCode', labelKey: 'mfa.enrollSecondCodeLabel', type: 'text' },
127
222
  ];
128
223
  case 'collect_email_code':
129
- return [{ kind: 'input', name: 'code', labelKey: 'signIn.emailCodeLabel', type: 'text' }];
224
+ return this.linkOnly() ? [] : [{ kind: 'input', name: 'code', labelKey: 'signIn.emailCodeLabel', type: 'text' }];
130
225
  case 'collect_new_password':
131
226
  return [{ kind: 'input', name: 'password', labelKey: 'reset.newPasswordLabel', type: 'password' }];
227
+ case 'accept_policies':
228
+ // Drawn by <atlas-policy-accept-step> above.
229
+ return [];
132
230
  case 'collect_captcha':
133
231
  // §5 the server withheld the attempt until a captcha clears. Solving the
134
232
  // widget resubmits the identifier on its own; the button retries.
@@ -152,7 +250,7 @@ export class AttemptFlowComponent {
152
250
  }
153
251
  }
154
252
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AttemptFlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
155
- 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" }, outputs: { submitFlow: "submitFlow", chooseFactor: "chooseFactor" }, ngImport: i0, template: `
253
+ 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", policyDeclined: "policyDeclined" }, ngImport: i0, template: `
156
254
  <div [class]="cls('card', 'atlas-card')">
157
255
  <h1 [class]="cls('headerTitle', 'atlas-title')">{{ t(titleKey) }}</h1>
158
256
 
@@ -164,6 +262,98 @@ export class AttemptFlowComponent {
164
262
  @if (codeSentText(); as sentText) {
165
263
  <p class="atlas-text" data-atlas-code-sent="">{{ sentText }}</p>
166
264
  }
265
+ @if (linkOnly()) {
266
+ <!-- Nothing to type: the flow polls until the emailed link is opened (anywhere). -->
267
+ <p class="atlas-text" data-atlas-link-sent="" aria-live="polite">
268
+ {{ t('signUp.linkSentTo', { email: attempt?.identifier ?? '' }) }}
269
+ </p>
270
+ <button
271
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
272
+ type="button"
273
+ data-atlas-resend=""
274
+ [disabled]="busy"
275
+ (click)="resend.emit()"
276
+ >
277
+ {{ t('signIn.resendLink') }}
278
+ </button>
279
+ }
280
+ @if (enrolling() && enrollmentState; as enrol) {
281
+ @if (enrol.method === null) {
282
+ <p class="atlas-text">{{ t('mfa.enrollChoose') }}</p>
283
+ @for (m of enrol.options; track m) {
284
+ <button
285
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
286
+ type="button"
287
+ [attr.data-atlas-mfa-method]="m"
288
+ [disabled]="busy || enrol.busy"
289
+ (click)="chooseMethod(m)"
290
+ >
291
+ {{ t(m === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
292
+ </button>
293
+ }
294
+ } @else if (enrol.method === 'totp') {
295
+ @if (enrol.enrollment; as setup) {
296
+ <p class="atlas-text">{{ t('mfa.enrollScan') }}</p>
297
+ @if (setup.qrCode) {
298
+ <img class="atlas-mfa-qr" data-atlas="mfa-qr" [src]="setup.qrCode" [alt]="t('mfa.enrollQrAlt')" width="180" height="180" />
299
+ }
300
+ @if (setup.secret) {
301
+ <p class="atlas-text" data-atlas="mfa-setup-key">{{ t('mfa.enrollSetupKey') }}: <code>{{ setupKey(setup.secret) }}</code></p>
302
+ }
303
+ <label class="atlas-field">
304
+ <span>{{ t('mfa.enrollFirstCodeLabel') }}</span>
305
+ <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)" />
306
+ </label>
307
+ @if (enrol.totpCodes >= 2) {
308
+ <label class="atlas-field">
309
+ <span>{{ t('mfa.enrollSecondCodeLabel') }}</span>
310
+ <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)" />
311
+ </label>
312
+ }
313
+ } @else {
314
+ <p class="atlas-text" aria-live="polite">{{ enrol.busy ? t('mfa.enrollPreparing') : '' }}</p>
315
+ }
316
+ } @else {
317
+ @if (enrol.enrollment; as texted) {
318
+ <p class="atlas-text" data-atlas="mfa-code-texted" aria-live="polite">{{ t('mfa.codeTextedTo', { phone: texted.phone ?? '' }) }}</p>
319
+ <label class="atlas-field">
320
+ <span>{{ t('mfa.codeLabel') }}</span>
321
+ <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)" />
322
+ </label>
323
+ <button
324
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
325
+ type="button"
326
+ data-atlas-resend=""
327
+ [disabled]="busy || enrol.busy"
328
+ (click)="resendEnrollment()"
329
+ >
330
+ {{ t('signIn.resendCode') }}
331
+ </button>
332
+ } @else {
333
+ <label class="atlas-field">
334
+ <span>{{ t('mfa.phoneLabel') }}</span>
335
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="tel" name="phone" autocomplete="tel" [value]="values['phone'] ?? ''" (input)="setValue('phone', $any($event.target).value)" />
336
+ </label>
337
+ <p class="atlas-text">{{ t('mfa.phoneHint') }}</p>
338
+ }
339
+ }
340
+ @for (error of enrol.errors; track $index) {
341
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ error.message }}</p>
342
+ }
343
+ @if (enrol.method !== null && enrol.options.length > 1) {
344
+ @for (other of otherMethods(enrol); track other) {
345
+ <button
346
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
347
+ type="button"
348
+ [attr.data-atlas-mfa-method]="other"
349
+ [disabled]="busy || enrol.busy"
350
+ (click)="chooseMethod(other)"
351
+ >
352
+ {{ t(other === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
353
+ </button>
354
+ }
355
+ }
356
+ }
167
357
  @for (f of fields(); track $index) {
168
358
  @if (f.kind === 'input') {
169
359
  <label class="atlas-field">
@@ -186,16 +376,68 @@ export class AttemptFlowComponent {
186
376
  }
187
377
  }
188
378
 
379
+ @if (awaitingPolicies()) {
380
+ <!-- A required policy changed: scroll-mode ones in their dialog, the rest as checkboxes. -->
381
+ <atlas-policy-accept-step
382
+ [attempt]="attempt"
383
+ [busy]="busy"
384
+ (submitFlow)="submitFlow.emit($event)"
385
+ (declined)="policyDeclined.emit($event)"
386
+ ></atlas-policy-accept-step>
387
+ }
388
+
189
389
  @if (showCaptcha()) {
190
390
  <div class="atlas-captcha" data-atlas-captcha="" [atlasCaptchaSlot]="captcha"></div>
191
391
  }
192
392
 
193
393
  @if (showSubmit()) {
194
- <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy" type="submit">
195
- {{ t('signIn.submit') }}
394
+ <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy || (enrolling() && !!enrollmentState?.busy)" type="submit">
395
+ {{ t(submitKey()) }}
196
396
  </button>
197
397
  }
198
398
 
399
+ @if (showSmsSecondFactor()) {
400
+ @if (smsSecondFactorSentTo(); as sentTo) {
401
+ <p class="atlas-text" data-atlas="sms-second-factor-sent" aria-live="polite">
402
+ {{ t('mfa.codeTextedTo', { phone: sentTo }) }}
403
+ </p>
404
+ } @else {
405
+ <button
406
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
407
+ type="button"
408
+ data-atlas="sms-second-factor"
409
+ [disabled]="busy || !!textedSecondFactor?.busy"
410
+ (click)="smsSecondFactor.emit()"
411
+ >
412
+ {{ textedSecondFactor?.busy ? t('signIn.sending') : t('mfa.smsCodeOption') }}
413
+ </button>
414
+ @if (textedSecondFactor?.error; as message) {
415
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
416
+ }
417
+ }
418
+ }
419
+
420
+ @if (showEmailSecondFactor()) {
421
+ @if (emailSecondFactorSentTo(); as sentTo) {
422
+ <p class="atlas-text" data-atlas="email-second-factor-sent" aria-live="polite">
423
+ {{ t('signIn.codeSentTo', { email: sentTo }) }}
424
+ </p>
425
+ } @else {
426
+ <button
427
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
428
+ type="button"
429
+ data-atlas="email-second-factor"
430
+ [disabled]="busy || !!emailedSecondFactor?.busy"
431
+ (click)="emailSecondFactor.emit()"
432
+ >
433
+ {{ emailedSecondFactor?.busy ? t('signIn.sending') : t('signIn.emailCodeOption') }}
434
+ </button>
435
+ @if (emailedSecondFactor?.error; as message) {
436
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
437
+ }
438
+ }
439
+ }
440
+
199
441
  @if (showEmailCodeOption()) {
200
442
  <button
201
443
  [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
@@ -210,7 +452,7 @@ export class AttemptFlowComponent {
210
452
  }
211
453
  </form>
212
454
  </div>
213
- `, isInline: true, dependencies: [{ kind: "directive", type: AtlasCaptchaSlotDirective, selector: "[atlasCaptchaSlot]", inputs: ["atlasCaptchaSlot"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
455
+ `, isInline: true, dependencies: [{ kind: "directive", type: AtlasCaptchaSlotDirective, selector: "[atlasCaptchaSlot]", inputs: ["atlasCaptchaSlot"] }, { kind: "component", type: PolicyAcceptStepComponent, selector: "atlas-policy-accept-step", inputs: ["attempt", "busy"], outputs: ["submitFlow", "declined"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
214
456
  }
215
457
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AttemptFlowComponent, decorators: [{
216
458
  type: Component,
@@ -218,7 +460,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
218
460
  selector: 'atlas-attempt-flow',
219
461
  standalone: true,
220
462
  changeDetection: ChangeDetectionStrategy.OnPush,
221
- imports: [AtlasCaptchaSlotDirective],
463
+ imports: [AtlasCaptchaSlotDirective, PolicyAcceptStepComponent],
222
464
  template: `
223
465
  <div [class]="cls('card', 'atlas-card')">
224
466
  <h1 [class]="cls('headerTitle', 'atlas-title')">{{ t(titleKey) }}</h1>
@@ -231,6 +473,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
231
473
  @if (codeSentText(); as sentText) {
232
474
  <p class="atlas-text" data-atlas-code-sent="">{{ sentText }}</p>
233
475
  }
476
+ @if (linkOnly()) {
477
+ <!-- Nothing to type: the flow polls until the emailed link is opened (anywhere). -->
478
+ <p class="atlas-text" data-atlas-link-sent="" aria-live="polite">
479
+ {{ t('signUp.linkSentTo', { email: attempt?.identifier ?? '' }) }}
480
+ </p>
481
+ <button
482
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
483
+ type="button"
484
+ data-atlas-resend=""
485
+ [disabled]="busy"
486
+ (click)="resend.emit()"
487
+ >
488
+ {{ t('signIn.resendLink') }}
489
+ </button>
490
+ }
491
+ @if (enrolling() && enrollmentState; as enrol) {
492
+ @if (enrol.method === null) {
493
+ <p class="atlas-text">{{ t('mfa.enrollChoose') }}</p>
494
+ @for (m of enrol.options; track m) {
495
+ <button
496
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
497
+ type="button"
498
+ [attr.data-atlas-mfa-method]="m"
499
+ [disabled]="busy || enrol.busy"
500
+ (click)="chooseMethod(m)"
501
+ >
502
+ {{ t(m === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
503
+ </button>
504
+ }
505
+ } @else if (enrol.method === 'totp') {
506
+ @if (enrol.enrollment; as setup) {
507
+ <p class="atlas-text">{{ t('mfa.enrollScan') }}</p>
508
+ @if (setup.qrCode) {
509
+ <img class="atlas-mfa-qr" data-atlas="mfa-qr" [src]="setup.qrCode" [alt]="t('mfa.enrollQrAlt')" width="180" height="180" />
510
+ }
511
+ @if (setup.secret) {
512
+ <p class="atlas-text" data-atlas="mfa-setup-key">{{ t('mfa.enrollSetupKey') }}: <code>{{ setupKey(setup.secret) }}</code></p>
513
+ }
514
+ <label class="atlas-field">
515
+ <span>{{ t('mfa.enrollFirstCodeLabel') }}</span>
516
+ <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)" />
517
+ </label>
518
+ @if (enrol.totpCodes >= 2) {
519
+ <label class="atlas-field">
520
+ <span>{{ t('mfa.enrollSecondCodeLabel') }}</span>
521
+ <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)" />
522
+ </label>
523
+ }
524
+ } @else {
525
+ <p class="atlas-text" aria-live="polite">{{ enrol.busy ? t('mfa.enrollPreparing') : '' }}</p>
526
+ }
527
+ } @else {
528
+ @if (enrol.enrollment; as texted) {
529
+ <p class="atlas-text" data-atlas="mfa-code-texted" aria-live="polite">{{ t('mfa.codeTextedTo', { phone: texted.phone ?? '' }) }}</p>
530
+ <label class="atlas-field">
531
+ <span>{{ t('mfa.codeLabel') }}</span>
532
+ <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)" />
533
+ </label>
534
+ <button
535
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
536
+ type="button"
537
+ data-atlas-resend=""
538
+ [disabled]="busy || enrol.busy"
539
+ (click)="resendEnrollment()"
540
+ >
541
+ {{ t('signIn.resendCode') }}
542
+ </button>
543
+ } @else {
544
+ <label class="atlas-field">
545
+ <span>{{ t('mfa.phoneLabel') }}</span>
546
+ <input [class]="cls('formFieldInput', 'atlas-input')" type="tel" name="phone" autocomplete="tel" [value]="values['phone'] ?? ''" (input)="setValue('phone', $any($event.target).value)" />
547
+ </label>
548
+ <p class="atlas-text">{{ t('mfa.phoneHint') }}</p>
549
+ }
550
+ }
551
+ @for (error of enrol.errors; track $index) {
552
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ error.message }}</p>
553
+ }
554
+ @if (enrol.method !== null && enrol.options.length > 1) {
555
+ @for (other of otherMethods(enrol); track other) {
556
+ <button
557
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
558
+ type="button"
559
+ [attr.data-atlas-mfa-method]="other"
560
+ [disabled]="busy || enrol.busy"
561
+ (click)="chooseMethod(other)"
562
+ >
563
+ {{ t(other === 'totp' ? 'mfa.enrollTotpOption' : 'mfa.enrollSmsOption') }}
564
+ </button>
565
+ }
566
+ }
567
+ }
234
568
  @for (f of fields(); track $index) {
235
569
  @if (f.kind === 'input') {
236
570
  <label class="atlas-field">
@@ -253,16 +587,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
253
587
  }
254
588
  }
255
589
 
590
+ @if (awaitingPolicies()) {
591
+ <!-- A required policy changed: scroll-mode ones in their dialog, the rest as checkboxes. -->
592
+ <atlas-policy-accept-step
593
+ [attempt]="attempt"
594
+ [busy]="busy"
595
+ (submitFlow)="submitFlow.emit($event)"
596
+ (declined)="policyDeclined.emit($event)"
597
+ ></atlas-policy-accept-step>
598
+ }
599
+
256
600
  @if (showCaptcha()) {
257
601
  <div class="atlas-captcha" data-atlas-captcha="" [atlasCaptchaSlot]="captcha"></div>
258
602
  }
259
603
 
260
604
  @if (showSubmit()) {
261
- <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy" type="submit">
262
- {{ t('signIn.submit') }}
605
+ <button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy || (enrolling() && !!enrollmentState?.busy)" type="submit">
606
+ {{ t(submitKey()) }}
263
607
  </button>
264
608
  }
265
609
 
610
+ @if (showSmsSecondFactor()) {
611
+ @if (smsSecondFactorSentTo(); as sentTo) {
612
+ <p class="atlas-text" data-atlas="sms-second-factor-sent" aria-live="polite">
613
+ {{ t('mfa.codeTextedTo', { phone: sentTo }) }}
614
+ </p>
615
+ } @else {
616
+ <button
617
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
618
+ type="button"
619
+ data-atlas="sms-second-factor"
620
+ [disabled]="busy || !!textedSecondFactor?.busy"
621
+ (click)="smsSecondFactor.emit()"
622
+ >
623
+ {{ textedSecondFactor?.busy ? t('signIn.sending') : t('mfa.smsCodeOption') }}
624
+ </button>
625
+ @if (textedSecondFactor?.error; as message) {
626
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
627
+ }
628
+ }
629
+ }
630
+
631
+ @if (showEmailSecondFactor()) {
632
+ @if (emailSecondFactorSentTo(); as sentTo) {
633
+ <p class="atlas-text" data-atlas="email-second-factor-sent" aria-live="polite">
634
+ {{ t('signIn.codeSentTo', { email: sentTo }) }}
635
+ </p>
636
+ } @else {
637
+ <button
638
+ [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
639
+ type="button"
640
+ data-atlas="email-second-factor"
641
+ [disabled]="busy || !!emailedSecondFactor?.busy"
642
+ (click)="emailSecondFactor.emit()"
643
+ >
644
+ {{ emailedSecondFactor?.busy ? t('signIn.sending') : t('signIn.emailCodeOption') }}
645
+ </button>
646
+ @if (emailedSecondFactor?.error; as message) {
647
+ <p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ message }}</p>
648
+ }
649
+ }
650
+ }
651
+
266
652
  @if (showEmailCodeOption()) {
267
653
  <button
268
654
  [class]="cls('formButtonSecondary', 'atlas-button-secondary')"
@@ -299,9 +685,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
299
685
  type: Output
300
686
  }], chooseFactor: [{
301
687
  type: Output
688
+ }], offerEmailSecondFactor: [{
689
+ type: Input
690
+ }], emailedSecondFactor: [{
691
+ type: Input
692
+ }], emailSecondFactor: [{
693
+ type: Output
694
+ }], offerSmsSecondFactor: [{
695
+ type: Input
696
+ }], textedSecondFactor: [{
697
+ type: Input
698
+ }], smsSecondFactor: [{
699
+ type: Output
700
+ }], enrollment: [{
701
+ type: Input
702
+ }], enrollmentState: [{
703
+ type: Input
704
+ }], emailVerification: [{
705
+ type: Input
706
+ }], resend: [{
707
+ type: Output
708
+ }], policyDeclined: [{
709
+ type: Output
302
710
  }] } });
303
711
  /** A read-only message row: `labelKey` holds the i18n key of the text to show. */
304
712
  function msg(labelKey) {
305
713
  return { kind: 'message', name: '', labelKey, type: 'text' };
306
714
  }
307
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZW1wdC1mbG93LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9hdHRlbXB0LWZsb3cuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLFFBQVEsR0FJVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDakYsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUFlcEM7Ozs7Ozs7OztHQVNHO0FBa0VILE1BQU0sT0FBTyxvQkFBb0I7SUFDZCxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXJDLE9BQU8sR0FBdUIsSUFBSSxDQUFDO0lBQ25DLElBQUksR0FBRyxLQUFLLENBQUM7SUFDYixNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUNuQywwRkFBMEY7SUFDakYsV0FBVyxHQUF3QixTQUFTLENBQUM7SUFDN0MsUUFBUSxHQUFHLGNBQWMsQ0FBQztJQUNuQzs7OztPQUlHO0lBQ00sT0FBTyxHQUE2QixJQUFJLENBQUM7SUFDbEQ7Ozs7T0FJRztJQUNNLFlBQVksR0FBb0IsSUFBSSxDQUFDO0lBQzlDLHFHQUFxRztJQUM1RixjQUFjLEdBQWtCLElBQUksQ0FBQztJQUU5QyxtRUFBbUU7SUFDekQsVUFBVSxHQUFHLElBQUksWUFBWSxFQUEwQixDQUFDO0lBQ2xFLDZGQUE2RjtJQUNuRixZQUFZLEdB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S0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFNRyxPQUFPO3NCQUFmLEtBQUs7Z0JBTUcsWUFBWTtzQkFBcEIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUdJLFVBQVU7c0JBQW5CLE1BQU07Z0JBRUcsWUFBWTtzQkFBckIsTUFBTTs7QUEySFQsa0ZBQWtGO0FBQ2xGLFNBQVMsR0FBRyxDQUFDLFFBQWdCO0lBQzNCLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUMvRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgbG9jYWxpemVkRXJyb3JNZXNzYWdlLFxuICBuZXh0U3RlcCxcbiAgdHlwZSBBdHRlbXB0VmlldyxcbiAgdHlwZSBDYXB0Y2hhQ29udHJvbGxlcixcbiAgdHlwZSBGaWVsZEVycm9yLFxufSBmcm9tICdAYXRsYXNhdXRoL2pzJztcbmltcG9ydCB7IEF0bGFzU2VydmljZSB9IGZyb20gJy4uL2F0bGFzLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXRsYXNDYXB0Y2hhU2xvdERpcmVjdGl2ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvY2FwdGNoYS1zbG90LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBjbGFzc0ZvciwgdHlwZSBFbGVtZW50S2V5IH0gZnJvbSAnLi4vYXBwZWFyYW5jZSc7XG5pbXBvcnQgeyB0cmFuc2xhdGUgfSBmcm9tICcuLi9pMThuJztcblxuLyoqXG4gKiBPbmUgcmVuZGVyZWQgcm93IG9mIHRoZSBmbG93LiBBIHVuaWZvcm0gc2hhcGUgKHJhdGhlciB0aGFuIGEgZGlzY3JpbWluYXRlZFxuICogdW5pb24pIHNvIHRoZSB0ZW1wbGF0ZSBhY2Nlc3NlcyBvbmx5IGZpZWxkcyB0aGF0IGFsd2F5cyBleGlzdCDigJQgbm8gcmVsaWFuY2Ugb25cbiAqIHRlbXBsYXRlIGNvbnRyb2wtZmxvdyBuYXJyb3dpbmcgb2YgYSBsb29wIHZhcmlhYmxlLCB3aGljaCB2YXJpZXMgYnkgQW5ndWxhclxuICogbWlub3IuIEZvciBhIGBtZXNzYWdlYCByb3csIGBsYWJlbEtleWAgY2FycmllcyB0aGUgbWVzc2FnZSdzIGkxOG4ga2V5LlxuICovXG5pbnRlcmZhY2UgU3RlcEZpZWxkIHtcbiAga2luZDogJ2lucHV0JyB8ICdtZXNzYWdlJyB8ICdhbGVydCc7XG4gIG5hbWU6IHN0cmluZztcbiAgbGFiZWxLZXk6IHN0cmluZztcbiAgdHlwZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBzZXJ2ZXItZHJpdmVuIGZsb3cgc2hlbGwsIHNoYXJlZCBieSBgPGF0bGFzLXNpZ24taW4+YCBhbmRcbiAqIGA8YXRsYXMtc2lnbi11cD5gLiBUaGUgQW5ndWxhciBwZWVyIG9mIFJlYWN0J3MgaW50ZXJuYWwgYEF0dGVtcHRGbG93YC5cbiAqXG4gKiBJdCBjb250YWlucyBOTyBkZWNpc2lvbiBhYm91dCB3aGF0IGNvbWVzIG5leHQ6IGl0IHJlbmRlcnMgd2hhdGV2ZXIgYHN0YXR1c2BcbiAqIHRoZSBzZXJ2ZXIgcmV0dXJuZWQsIG1hcHBlZCB0aHJvdWdoIGBuZXh0U3RlcGAgZnJvbSBgQGF0bGFzYXV0aC9qc2AgKHRoZSBzYW1lXG4gKiBleGhhdXN0aXZlIG1hcHBpbmcgdGhlIFJlYWN0IFNESyB1c2VzKSwgc28gYWRkaW5nIGEgc3RlcCBpcyBhIHNlcnZlciBjaGFuZ2VcbiAqIGFuZCBhbiBvdXQtb2YtZGF0ZSBjbGllbnQgZGVncmFkZXMgdG8gYSB2aXNpYmxlIFwicGxlYXNlIHVwZGF0ZVwiIG1lc3NhZ2UgcmF0aGVyXG4gKiB0aGFuIGEgYmxhbmsgc2NyZWVuLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhdGxhcy1hdHRlbXB0LWZsb3cnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW0F0bGFzQ2FwdGNoYVNsb3REaXJlY3RpdmVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNscygnY2FyZCcsICdhdGxhcy1jYXJkJylcIj5cbiAgICAgIDxoMSBbY2xhc3NdPVwiY2xzKCdoZWFkZXJUaXRsZScsICdhdGxhcy10aXRsZScpXCI+e3sgdCh0aXRsZUtleSkgfX08L2gxPlxuXG4gICAgICBAZm9yIChlcnJvciBvZiBmb3JtRXJyb3JzKCk7IHRyYWNrIGVycm9yLmNvZGUpIHtcbiAgICAgICAgPHAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiIHJvbGU9XCJhbGVydFwiPnt7IGVycm9yVGV4dChlcnJvcikgfX08L3A+XG4gICAgICB9XG5cbiAgICAgIDxmb3JtIChzdWJtaXQpPVwib25TdWJtaXQoJGV2ZW50KVwiPlxuICAgICAgICBAaWYgKGNvZGVTZW50VGV4dCgpOyBhcyBzZW50VGV4dCkge1xuICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXMtY29kZS1zZW50PVwiXCI+e3sgc2VudFRleHQgfX08L3A+XG4gICAgICAgIH1cbiAgICAgICAgQGZvciAoZiBvZiBmaWVsZHMoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgQGlmIChmLmtpbmQgPT09ICdpbnB1dCcpIHtcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImF0bGFzLWZpZWxkXCI+XG4gICAgICAgICAgICAgIDxzcGFuPnt7IHQoZi5sYWJlbEtleSkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZElucHV0JywgJ2F0bGFzLWlucHV0JylcIlxuICAgICAgICAgICAgICAgIFt0eXBlXT1cImYudHlwZVwiXG4gICAgICAgICAgICAgICAgW2F0dHIubmFtZV09XCJmLm5hbWVcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJ2YWx1ZXNbZi5uYW1lXSA/PyAnJ1wiXG4gICAgICAgICAgICAgICAgKGlucHV0KT1cInNldFZhbHVlKGYubmFtZSwgJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSlcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICBAZm9yIChlcnJvciBvZiBmaWVsZEVycm9yc0ZvcihmLm5hbWUpOyB0cmFjayBlcnJvci5jb2RlKSB7XG4gICAgICAgICAgICAgICAgPHNwYW4gW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiPnt7IGVycm9yVGV4dChlcnJvcikgfX08L3NwYW4+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgfSBAZWxzZSBpZiAoZi5raW5kID09PSAnYWxlcnQnKSB7XG4gICAgICAgICAgICA8cCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCIgcm9sZT1cImFsZXJ0XCI+e3sgdChmLmxhYmVsS2V5KSB9fTwvcD5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxwPnt7IHQoZi5sYWJlbEtleSkgfX08L3A+XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93Q2FwdGNoYSgpKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImF0bGFzLWNhcHRjaGFcIiBkYXRhLWF0bGFzLWNhcHRjaGE9XCJcIiBbYXRsYXNDYXB0Y2hhU2xvdF09XCJjYXB0Y2hhXCI+PC9kaXY+XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dTdWJtaXQoKSkge1xuICAgICAgICAgIDxidXR0b24gW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblByaW1hcnknLCAnYXRsYXMtYnV0dG9uJylcIiBbZGlzYWJsZWRdPVwiYnVzeVwiIHR5cGU9XCJzdWJtaXRcIj5cbiAgICAgICAgICAgIHt7IHQoJ3NpZ25Jbi5zdWJtaXQnKSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93RW1haWxDb2RlT3B0aW9uKCkpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uU2Vjb25kYXJ5JywgJ2F0bGFzLWJ1dHRvbi1zZWNvbmRhcnknKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtc3RyYXRlZ3ldPVwicHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJyA/IG51bGwgOiAnZW1haWxfY29kZSdcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1hdGxhcy1yZXNlbmRdPVwicHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJyA/ICcnIDogbnVsbFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlRmFjdG9yLmVtaXQoJ2VtYWlsX2NvZGUnKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgdChwcmVwYXJlZEZhY3RvciA9PT0gJ2VtYWlsX2NvZGUnID8gJ3NpZ25Jbi5yZXNlbmRDb2RlJyA6ICdzaWduSW4udXNlRW1haWxDb2RlJykgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9mb3JtPlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBBdHRlbXB0Rmxvd0NvbXBvbmVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYXRsYXMgPSBpbmplY3QoQXRsYXNTZXJ2aWNlKTtcblxuICBASW5wdXQoKSBhdHRlbXB0OiBBdHRlbXB0VmlldyB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBidXN5ID0gZmFsc2U7XG4gIEBJbnB1dCgpIGVycm9yczogRmllbGRFcnJvcltdID0gW107XG4gIC8qKiBgRmxvd1N0YXRlLnNlc3Npb25LZXB0YDogd2hldGhlciB0aGlzIGJyb3dzZXIga2VwdCB0aGUgc2Vzc2lvbiB0aGUgc2lnbi1pbiBjcmVhdGVkLiAqL1xuICBASW5wdXQoKSBzZXNzaW9uS2VwdDogYm9vbGVhbiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgQElucHV0KCkgdGl0bGVLZXkgPSAnc2lnbkluLnRpdGxlJztcbiAgLyoqXG4gICAqIFRoZSBzaWduLWluIGNhcHRjaGEsIGRyYXduIGFib3ZlIHRoZSBzdWJtaXQgYnV0dG9uIG9uIHRoZSBpZGVudGlmaWVyIHN0ZXBcbiAgICogKGFuIGFsd2F5cy1vbiBzaWduLWluIGNhcHRjaGEpIGFuZCBvbiB0aGUgY2hhbGxlbmdlIHN0ZXAgdGhlIHNlcnZlciBkZW1hbmRzXG4gICAqIHdpdGggYG5lZWRzX2NhcHRjaGFgLiBOdWxsIHdoZW4gdGhlIGZsb3cgZHJhd3Mgbm9uZS5cbiAgICovXG4gIEBJbnB1dCgpIGNhcHRjaGE6IENhcHRjaGFDb250cm9sbGVyIHwgbnVsbCA9IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgZmlyc3QgZmFjdG9ycyB0byBvZmZlciBvbiB0aGUgYG5lZWRzX2ZpcnN0X2ZhY3RvcmAgc3RlcCDigJQgcGFzc1xuICAgKiBgQXRsYXNGbG93Q29udHJvbGxlci5maXJzdEZhY3RvcnMoKWAsIHdoaWNoIGRyb3BzIGVtYWlsIGNvZGUgLyBsaW5rIHdoaWxlIHRoZVxuICAgKiBhcHAgY2Fubm90IGRlbGl2ZXIgZW1haWwuIE51bGwgdXNlcyB0aGUgc2VydmVyJ3MgbGlzdCBhcy1pcy5cbiAgICovXG4gIEBJbnB1dCgpIGZpcnN0RmFjdG9yczogc3RyaW5nW10gfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBmaXJzdCBmYWN0b3IgYWxyZWFkeSBzZW50IChgQXRsYXNGbG93Q29udHJvbGxlci5wcmVwYXJlZEZhY3RvcigpYCk6IGl0cyBjb2RlIGlzIGNvbGxlY3RlZC4gKi9cbiAgQElucHV0KCkgcHJlcGFyZWRGYWN0b3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBFbWl0cyB0aGUgY29sbGVjdGVkIGZpZWxkIHZhbHVlcyB3aGVuIHRoZSBmb3JtIGlzIHN1Ym1pdHRlZC4gKi9cbiAgQE91dHB1dCgpIHN1Ym1pdEZsb3cgPSBuZXcgRXZlbnRFbWl0dGVyPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+KCk7XG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHBpY2tzIGEgZmlyc3QgZmFjdG9yIHRoZSBzZXJ2ZXIgbXVzdCBzZW5kIGZpcnN0IChhbiBlbWFpbGVkIGNvZGUpLiAqL1xuICBAT3V0cHV0KCkgY2hvb3NlRmFjdG9yID0gbmV3IEV2ZW50RW1pdHRlcjwnZW1haWxfY29kZSc+KCk7XG5cbiAgcHJvdGVjdGVkIHZhbHVlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIHByb3RlY3RlZCB0KGtleTogc3RyaW5nLCB2YXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRyYW5zbGF0ZSh0aGlzLmF0bGFzLmxvY2FsaXphdGlvbiwga2V5LCB2YXJzKTtcbiAgfVxuXG4gIC8qKiBBIHNlcnZlciBlcnJvciBpbiB0aGUgYXBwJ3MgbGFuZ3VhZ2UgKGBlcnJvci48cmVhc29uPmAsIGVsc2UgdGhlIHNlcnZlcidzIG1lc3NhZ2UpLiAqL1xuICBwcm90ZWN0ZWQgZXJyb3JUZXh0KGVycm9yOiBGaWVsZEVycm9yKTogc3RyaW5nIHtcbiAgICAvLyBgZXJyb3JMb2NhbGl6YXRpb25gIGlzIHJlYWQgZGVmZW5zaXZlbHk6IGEgc3RhbmQtaW4gc2VydmljZSBtYXkgbGFjayBpdC5cbiAgICBjb25zdCBsYXllciA9ICh0aGlzLmF0bGFzIGFzIHsgZXJyb3JMb2NhbGl6YXRpb24/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IH0pLmVycm9yTG9jYWxpemF0aW9uO1xuICAgIHJldHVybiBsb2NhbGl6ZWRFcnJvck1lc3NhZ2UoZXJyb3IsIGxheWVyID8/IHRoaXMuYXRsYXMubG9jYWxpemF0aW9uLCB0aGlzLmF0bGFzLmxvY2FsaXphdGlvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgY2xzKGtleTogRWxlbWVudEtleSwgYmFzZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY2xhc3NGb3Ioa2V5LCB0aGlzLmF0bGFzLmFwcGVhcmFuY2UsIGJhc2UpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldFZhbHVlKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudmFsdWVzID0geyAuLi50aGlzLnZhbHVlcywgW25hbWVdOiB2YWx1ZSB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uU3VibWl0KGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgdGhpcy5zdWJtaXRGbG93LmVtaXQodGhpcy52YWx1ZXMpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZvcm1FcnJvcnMoKTogRmllbGRFcnJvcltdIHtcbiAgICByZXR1cm4gdGhpcy5lcnJvcnMuZmlsdGVyKChlcnJvcikgPT4gIWVycm9yLnBhcmFtKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBmaWVsZEVycm9yc0ZvcihuYW1lOiBzdHJpbmcpOiBGaWVsZEVycm9yW10ge1xuICAgIHJldHVybiB0aGlzLmVycm9ycy5maWx0ZXIoKGVycm9yKSA9PiBlcnJvci5wYXJhbSA9PT0gbmFtZSk7XG4gIH1cblxuICBwcml2YXRlIHN0ZXAoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXR0ZW1wdCA/IG5leHRTdGVwKHRoaXMuYXR0ZW1wdCkgOiAoeyBraW5kOiAnY29sbGVjdF9pZGVudGlmaWVyJyB9IGFzIGNvbnN0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG93Q2FwdGNoYSgpOiBib29sZWFuIHtcbiAgICBjb25zdCBraW5kID0gdGhpcy5zdGVwKCkua2luZDtcbiAgICByZXR1cm4gISF0aGlzLmNhcHRjaGEgJiYgKGtpbmQgPT09ICdjb2xsZWN0X2lkZW50aWZpZXInIHx8IGtpbmQgPT09ICdjb2xsZWN0X2NhcHRjaGEnKTtcbiAgfVxuXG4gIC8qKiBUaGUgZmlyc3QgZmFjdG9ycyBvbiBvZmZlciBhdCBhIGBuZWVkc19maXJzdF9mYWN0b3JgIHN0ZXAgKGVtcHR5IG9uIGFueSBvdGhlcikuICovXG4gIHByaXZhdGUgb2ZmZXJlZCgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgc3RlcCA9IHRoaXMuc3RlcCgpO1xuICAgIGlmIChzdGVwLmtpbmQgIT09ICdjb2xsZWN0X2ZpcnN0X2ZhY3RvcicpIHJldHVybiBbXTtcbiAgICByZXR1cm4gdGhpcy5maXJzdEZhY3RvcnMgPz8gc3RlcC5zdHJhdGVnaWVzO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNob3dFbWFpbENvZGVPcHRpb24oKTogYm9vbGVhbiB7XG4gICAgLy8gQmVmb3JlIHRoZSBjb2RlIGlzIHNlbnQ6IHRoZSBjaG9pY2UgKG9yIHRoZSByZXRyeSBvZiBhIGZhaWxlZCBhdXRvbWF0aWNcbiAgICAvLyBzZW5kKS4gQWZ0ZXI6IFwiUmVzZW5kIGNvZGVcIi5cbiAgICByZXR1cm4gdGhpcy5vZmZlcmVkKCkuaW5jbHVkZXMoJ2VtYWlsX2NvZGUnKTtcbiAgfVxuXG4gIC8qKiBUaGUgXCJ3ZSBzZW50IGEgY29kZSB0byDigKZcIiBsaW5lIG9uIHRoZSBjb2RlIHN0ZXAuICovXG4gIHByb3RlY3RlZCBjb2RlU2VudFRleHQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuc3RlcCgpLmtpbmQgIT09ICdjb2xsZWN0X2ZpcnN0X2ZhY3RvcicgfHwgdGhpcy5wcmVwYXJlZEZhY3RvciAhPT0gJ2VtYWlsX2NvZGUnKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdGhpcy50KCdzaWduSW4uY29kZVNlbnRUbycsIHsgZW1haWw6IHRoaXMuYXR0ZW1wdD8uaWRlbnRpZmllciA/PyAnJyB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG93U3VibWl0KCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGtpbmQgPSB0aGlzLnN0ZXAoKS5raW5kO1xuICAgIC8vIE5vdGhpbmcgdG8gc3VibWl0IG9uIGEgZmlyc3QtZmFjdG9yIHN0ZXAgdGhhdCBvbmx5IG9mZmVycyBhbiBlbWFpbGVkIGNvZGVcbiAgICAvLyB1bnRpbCB0aGF0IGNvZGUgaXMgc2VudC5cbiAgICBpZiAoa2luZCA9PT0gJ2NvbGxlY3RfZmlyc3RfZmFjdG9yJykgcmV0dXJuIHRoaXMuZmllbGRzKCkubGVuZ3RoID4gMDtcbiAgICByZXR1cm4ga2luZCAhPT0gJ2RvbmUnICYmIGtpbmQgIT09ICdhd2FpdF9vYXV0aCc7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRzKCk6IFN0ZXBGaWVsZFtdIHtcbiAgICBjb25zdCBzdGVwID0gdGhpcy5zdGVwKCk7XG4gICAgc3dpdGNoIChzdGVwLmtpbmQpIHtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfaWRlbnRpZmllcic6XG4gICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnaWRlbnRpZmllcicsIGxhYmVsS2V5OiAnc2lnbkluLmlkZW50aWZpZXJMYWJlbCcsIHR5cGU6ICdlbWFpbCcgfV07XG4gICAgICBjYXNlICdjb2xsZWN0X2ZpcnN0X2ZhY3Rvcic6IHtcbiAgICAgICAgaWYgKHRoaXMucHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJykge1xuICAgICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnY29kZScsIGxhYmVsS2V5OiAnc2lnbkluLmVtYWlsQ29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBwYXNzd29yZCBmaWVsZCB1bmxlc3MgdGhlIG9ubHkgb2ZmZXIgaXMgYW4gZW1haWxlZCBjb2RlIChjaG9zZW5cbiAgICAgICAgLy8gd2l0aCB0aGUgYnV0dG9uIGJlbG93IHRoZSBmb3JtKS5cbiAgICAgICAgY29uc3Qgb2ZmZXJlZCA9IHRoaXMub2ZmZXJlZCgpO1xuICAgICAgICByZXR1cm4gb2ZmZXJlZC5pbmNsdWRlcygnZW1haWxfY29kZScpICYmICFvZmZlcmVkLmluY2x1ZGVzKCdwYXNzd29yZCcpXG4gICAgICAgICAgPyBbXVxuICAgICAgICAgIDogW3sga2luZDogJ2lucHV0JywgbmFtZTogJ3Bhc3N3b3JkJywgbGFiZWxLZXk6ICdzaWduSW4ucGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICB9XG4gICAgICBjYXNlICdjb2xsZWN0X3NlY29uZF9mYWN0b3InOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ21mYS5jb2RlTGFiZWwnLCB0eXBlOiAndGV4dCcgfV07XG4gICAgICBjYXNlICdlbnJvbGxfc2Vjb25kX2ZhY3Rvcic6XG4gICAgICAgIC8vIFR3byBjb25zZWN1dGl2ZSBjb2RlcyAowqc1LjYpOiBhIHBob25lIHdpdGggYSBmYXN0IGNsb2NrIGZhaWxzIGhlcmVcbiAgICAgICAgLy8gcmF0aGVyIHRoYW4gb24gZXZlcnkgc2lnbi1pbiBhZnRlcndhcmRzLlxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIHsga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ21mYS5lbnJvbGxGaXJzdENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9LFxuICAgICAgICAgIHsga2luZDogJ2lucHV0JywgbmFtZTogJ3NlY29uZENvZGUnLCBsYWJlbEtleTogJ21mYS5lbnJvbGxTZWNvbmRDb2RlTGFiZWwnLCB0eXBlOiAndGV4dCcgfSxcbiAgICAgICAgXTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfZW1haWxfY29kZSc6XG4gICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnY29kZScsIGxhYmVsS2V5OiAnc2lnbkluLmVtYWlsQ29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgY2FzZSAnY29sbGVjdF9uZXdfcGFzc3dvcmQnOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ3Bhc3N3b3JkJywgbGFiZWxLZXk6ICdyZXNldC5uZXdQYXNzd29yZExhYmVsJywgdHlwZTogJ3Bhc3N3b3JkJyB9XTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfY2FwdGNoYSc6XG4gICAgICAgIC8vIMKnNSB0aGUgc2VydmVyIHdpdGhoZWxkIHRoZSBhdHRlbXB0IHVudGlsIGEgY2FwdGNoYSBjbGVhcnMuIFNvbHZpbmcgdGhlXG4gICAgICAgIC8vIHdpZGdldCByZXN1Ym1pdHMgdGhlIGlkZW50aWZpZXIgb24gaXRzIG93bjsgdGhlIGJ1dHRvbiByZXRyaWVzLlxuICAgICAgICByZXR1cm4gW21zZygnY2FwdGNoYS5wcm9tcHQnKV07XG4gICAgICBjYXNlICdhd2FpdF9vYXV0aCc6XG4gICAgICAgIHJldHVybiBbbXNnKCdzaWduSW4ubWFnaWNMaW5rU2VudCcpXTtcbiAgICAgIGNhc2UgJ2RvbmUnOlxuICAgICAgICAvLyBTaWduZWQgaW4gb25seSB3aGVuIHRoaXMgYnJvd3NlciBob2xkcyB0aGUgc2Vzc2lvbjsgYSBibG9ja2VkIGNvb2tpZSBpcyBzYWlkXG4gICAgICAgIC8vIHBsYWlubHkuIFwiQ2hlY2sgdGhlIG90aGVyIHRhYlwiIGlzIGZvciBhIHNpZ24taW4gY29tcGxldGVkIG9uIGFub3RoZXIgZGV2aWNlLlxuICAgICAgICBpZiAodGhpcy5zZXNzaW9uS2VwdCA9PT0gdHJ1ZSkgcmV0dXJuIFttc2coJ3NpZ25Jbi5zaWduZWRJbicpXTtcbiAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbktlcHQgPT09IGZhbHNlKSByZXR1cm4gW3sga2luZDogJ2FsZXJ0JywgbmFtZTogJycsIGxhYmVsS2V5OiAnc2lnbkluLnNlc3Npb25Ob3RLZXB0JywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgICByZXR1cm4gW21zZygnc2lnbkluLmNoZWNrT3RoZXJUYWInKV07XG4gICAgICBjYXNlICdyZXN0YXJ0JzpcbiAgICAgICAgcmV0dXJuIFttc2coJ2Vycm9yLmdlbmVyaWMnKV07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBBIHN0YXR1cyB0aGlzIFNESyB2ZXJzaW9uIGRvZXMgbm90IGtub3cuIEFuIGhvbmVzdCBtZXNzYWdlIGJlYXRzIGFcbiAgICAgICAgLy8gYmxhbmsgbG9naW4gYm94IHRoZSB1c2VyIGNhbm5vdCBhY3Qgb24uXG4gICAgICAgIHJldHVybiBbbXNnKCdlcnJvci5nZW5lcmljJyldO1xuICAgIH1cbiAgfVxufVxuXG4vKiogQSByZWFkLW9ubHkgbWVzc2FnZSByb3c6IGBsYWJlbEtleWAgaG9sZHMgdGhlIGkxOG4ga2V5IG9mIHRoZSB0ZXh0IHRvIHNob3cuICovXG5mdW5jdGlvbiBtc2cobGFiZWxLZXk6IHN0cmluZyk6IFN0ZXBGaWVsZCB7XG4gIHJldHVybiB7IGtpbmQ6ICdtZXNzYWdlJywgbmFtZTogJycsIGxhYmVsS2V5LCB0eXBlOiAndGV4dCcgfTtcbn1cbiJdfQ==
715
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZW1wdC1mbG93LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9hdHRlbXB0LWZsb3cuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQixhQUFhLEVBQ2IscUJBQXFCLEVBQ3JCLFFBQVEsR0FPVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDakYsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFELE9BQU8sRUFBRSxRQUFRLEVBQW1CLE1BQU0sZUFBZSxDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7O0FBZXBDOzs7Ozs7Ozs7R0FTRztBQWtOSCxNQUFNLE9BQU8sb0JBQW9CO0lBQ2QsS0FBSyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUVyQyxPQUFPLEdBQXVCLElBQUksQ0FBQztJQUNuQyxJQUFJLEdBQUcsS0FBSyxDQUFDO0lBQ2IsTUFBTSxHQUFpQixFQUFFLENBQUM7SUFDbkMsMEZBQTBGO0lBQ2pGLFdBQVcsR0FBd0IsU0FBUyxDQUFDO0lBQzdDLFFBQVEsR0FBRyxjQUFjLENBQUM7SUFDbkM7Ozs7T0FJRztJQUNNLE9BQU8sR0FBNkIsSUFBSSxDQUFDO0lBQ2xEOzs7O09BSUc7SUFDTSxZQUFZLEdBQW9CLElBQUksQ0FBQztJQUM5QyxxR0FBcUc7SUFDNUYsY0FBYyxHQUFrQixJQUFJLENB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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBNVDtpQkFDRjs4QkFJVSxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBTUcsT0FBTztzQkFBZixLQUFLO2dCQU1HLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsY0FBYztzQkFBdEIsS0FBSztnQkFHSSxVQUFVO3NCQUFuQixNQUFNO2dCQUVHLFlBQVk7c0JBQXJCLE1BQU07Z0JBTUUsc0JBQXNCO3NCQUE5QixLQUFLO2dCQUVHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFDSSxpQkFBaUI7c0JBQTFCLE1BQU07Z0JBTUUsb0JBQW9CO3NCQUE1QixLQUFLO2dCQUVHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDSSxlQUFlO3NCQUF4QixNQUFNO2dCQU1FLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFNRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0ksTUFBTTtzQkFBZixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU07O0FBa01ULGtGQUFrRjtBQUNsRixTQUFTLEdBQUcsQ0FBQyxRQUFnQjtJQUMzQixPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7QUFDL0QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIGF3YWl0aW5nU2lnblVwTGluayxcbiAgZW5yb2xsbWVudFN1Ym1pdEtleSxcbiAgZ3JvdXBTZXR1cEtleSxcbiAgbG9jYWxpemVkRXJyb3JNZXNzYWdlLFxuICBuZXh0U3RlcCxcbiAgdHlwZSBBdHRlbXB0VmlldyxcbiAgdHlwZSBDYXB0Y2hhQ29udHJvbGxlcixcbiAgdHlwZSBGaWVsZEVycm9yLFxuICB0eXBlIE1mYUVucm9sbG1lbnRDb250cm9sbGVyLFxuICB0eXBlIE1mYUVucm9sbG1lbnRTdGF0ZSxcbiAgdHlwZSBNZmFFbnJvbGxtZW50U3RyYXRlZ3ksXG59IGZyb20gJ0BhdGxhc2F1dGgvanMnO1xuaW1wb3J0IHsgQXRsYXNTZXJ2aWNlIH0gZnJvbSAnLi4vYXRsYXMuc2VydmljZSc7XG5pbXBvcnQgeyBBdGxhc0NhcHRjaGFTbG90RGlyZWN0aXZlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9jYXB0Y2hhLXNsb3QuZGlyZWN0aXZlJztcbmltcG9ydCB7IFBvbGljeUFjY2VwdFN0ZXBDb21wb25lbnQgfSBmcm9tICcuL3BvbGljeS1ob3N0JztcbmltcG9ydCB7IGNsYXNzRm9yLCB0eXBlIEVsZW1lbnRLZXkgfSBmcm9tICcuLi9hcHBlYXJhbmNlJztcbmltcG9ydCB7IHRyYW5zbGF0ZSB9IGZyb20gJy4uL2kxOG4nO1xuXG4vKipcbiAqIE9uZSByZW5kZXJlZCByb3cgb2YgdGhlIGZsb3cuIEEgdW5pZm9ybSBzaGFwZSAocmF0aGVyIHRoYW4gYSBkaXNjcmltaW5hdGVkXG4gKiB1bmlvbikgc28gdGhlIHRlbXBsYXRlIGFjY2Vzc2VzIG9ubHkgZmllbGRzIHRoYXQgYWx3YXlzIGV4aXN0IOKAlCBubyByZWxpYW5jZSBvblxuICogdGVtcGxhdGUgY29udHJvbC1mbG93IG5hcnJvd2luZyBvZiBhIGxvb3AgdmFyaWFibGUsIHdoaWNoIHZhcmllcyBieSBBbmd1bGFyXG4gKiBtaW5vci4gRm9yIGEgYG1lc3NhZ2VgIHJvdywgYGxhYmVsS2V5YCBjYXJyaWVzIHRoZSBtZXNzYWdlJ3MgaTE4biBrZXkuXG4gKi9cbmludGVyZmFjZSBTdGVwRmllbGQge1xuICBraW5kOiAnaW5wdXQnIHwgJ21lc3NhZ2UnIHwgJ2FsZXJ0JztcbiAgbmFtZTogc3RyaW5nO1xuICBsYWJlbEtleTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHNlcnZlci1kcml2ZW4gZmxvdyBzaGVsbCwgc2hhcmVkIGJ5IGA8YXRsYXMtc2lnbi1pbj5gIGFuZFxuICogYDxhdGxhcy1zaWduLXVwPmAuIFRoZSBBbmd1bGFyIHBlZXIgb2YgUmVhY3QncyBpbnRlcm5hbCBgQXR0ZW1wdEZsb3dgLlxuICpcbiAqIEl0IGNvbnRhaW5zIE5PIGRlY2lzaW9uIGFib3V0IHdoYXQgY29tZXMgbmV4dDogaXQgcmVuZGVycyB3aGF0ZXZlciBgc3RhdHVzYFxuICogdGhlIHNlcnZlciByZXR1cm5lZCwgbWFwcGVkIHRocm91Z2ggYG5leHRTdGVwYCBmcm9tIGBAYXRsYXNhdXRoL2pzYCAodGhlIHNhbWVcbiAqIGV4aGF1c3RpdmUgbWFwcGluZyB0aGUgUmVhY3QgU0RLIHVzZXMpLCBzbyBhZGRpbmcgYSBzdGVwIGlzIGEgc2VydmVyIGNoYW5nZVxuICogYW5kIGFuIG91dC1vZi1kYXRlIGNsaWVudCBkZWdyYWRlcyB0byBhIHZpc2libGUgXCJwbGVhc2UgdXBkYXRlXCIgbWVzc2FnZSByYXRoZXJcbiAqIHRoYW4gYSBibGFuayBzY3JlZW4uXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2F0bGFzLWF0dGVtcHQtZmxvdycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbQXRsYXNDYXB0Y2hhU2xvdERpcmVjdGl2ZSwgUG9saWN5QWNjZXB0U3RlcENvbXBvbmVudF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY2xzKCdjYXJkJywgJ2F0bGFzLWNhcmQnKVwiPlxuICAgICAgPGgxIFtjbGFzc109XCJjbHMoJ2hlYWRlclRpdGxlJywgJ2F0bGFzLXRpdGxlJylcIj57eyB0KHRpdGxlS2V5KSB9fTwvaDE+XG5cbiAgICAgIEBmb3IgKGVycm9yIG9mIGZvcm1FcnJvcnMoKTsgdHJhY2sgZXJyb3IuY29kZSkge1xuICAgICAgICA8cCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCIgcm9sZT1cImFsZXJ0XCI+e3sgZXJyb3JUZXh0KGVycm9yKSB9fTwvcD5cbiAgICAgIH1cblxuICAgICAgPGZvcm0gKHN1Ym1pdCk9XCJvblN1Ym1pdCgkZXZlbnQpXCI+XG4gICAgICAgIEBpZiAoY29kZVNlbnRUZXh0KCk7IGFzIHNlbnRUZXh0KSB7XG4gICAgICAgICAgPHAgY2xhc3M9XCJhdGxhcy10ZXh0XCIgZGF0YS1hdGxhcy1jb2RlLXNlbnQ9XCJcIj57eyBzZW50VGV4dCB9fTwvcD5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGxpbmtPbmx5KCkpIHtcbiAgICAgICAgICA8IS0tIE5vdGhpbmcgdG8gdHlwZTogdGhlIGZsb3cgcG9sbHMgdW50aWwgdGhlIGVtYWlsZWQgbGluayBpcyBvcGVuZWQgKGFueXdoZXJlKS4gLS0+XG4gICAgICAgICAgPHAgY2xhc3M9XCJhdGxhcy10ZXh0XCIgZGF0YS1hdGxhcy1saW5rLXNlbnQ9XCJcIiBhcmlhLWxpdmU9XCJwb2xpdGVcIj5cbiAgICAgICAgICAgIHt7IHQoJ3NpZ25VcC5saW5rU2VudFRvJywgeyBlbWFpbDogYXR0ZW1wdD8uaWRlbnRpZmllciA/PyAnJyB9KSB9fVxuICAgICAgICAgIDwvcD5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uU2Vjb25kYXJ5JywgJ2F0bGFzLWJ1dHRvbi1zZWNvbmRhcnknKVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGRhdGEtYXRsYXMtcmVzZW5kPVwiXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJidXN5XCJcbiAgICAgICAgICAgIChjbGljayk9XCJyZXNlbmQuZW1pdCgpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7eyB0KCdzaWduSW4ucmVzZW5kTGluaycpIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIH1cbiAgICAgICAgQGlmIChlbnJvbGxpbmcoKSAmJiBlbnJvbGxtZW50U3RhdGU7IGFzIGVucm9sKSB7XG4gICAgICAgICAgQGlmIChlbnJvbC5tZXRob2QgPT09IG51bGwpIHtcbiAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiPnt7IHQoJ21mYS5lbnJvbGxDaG9vc2UnKSB9fTwvcD5cbiAgICAgICAgICAgIEBmb3IgKG0gb2YgZW5yb2wub3B0aW9uczsgdHJhY2sgbSkge1xuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblNlY29uZGFyeScsICdhdGxhcy1idXR0b24tc2Vjb25kYXJ5JylcIlxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIFthdHRyLmRhdGEtYXRsYXMtbWZhLW1ldGhvZF09XCJtXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeSB8fCBlbnJvbC5idXN5XCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlTWV0aG9kKG0pXCJcbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHt7IHQobSA9PT0gJ3RvdHAnID8gJ21mYS5lbnJvbGxUb3RwT3B0aW9uJyA6ICdtZmEuZW5yb2xsU21zT3B0aW9uJykgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBAZWxzZSBpZiAoZW5yb2wubWV0aG9kID09PSAndG90cCcpIHtcbiAgICAgICAgICAgIEBpZiAoZW5yb2wuZW5yb2xsbWVudDsgYXMgc2V0dXApIHtcbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJhdGxhcy10ZXh0XCI+e3sgdCgnbWZhLmVucm9sbFNjYW4nKSB9fTwvcD5cbiAgICAgICAgICAgICAgQGlmIChzZXR1cC5xckNvZGUpIHtcbiAgICAgICAgICAgICAgICA8aW1nIGNsYXNzPVwiYXRsYXMtbWZhLXFyXCIgZGF0YS1hdGxhcz1cIm1mYS1xclwiIFtzcmNdPVwic2V0dXAucXJDb2RlXCIgW2FsdF09XCJ0KCdtZmEuZW5yb2xsUXJBbHQnKVwiIHdpZHRoPVwiMTgwXCIgaGVpZ2h0PVwiMTgwXCIgLz5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBAaWYgKHNldHVwLnNlY3JldCkge1xuICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXM9XCJtZmEtc2V0dXAta2V5XCI+e3sgdCgnbWZhLmVucm9sbFNldHVwS2V5JykgfX06IDxjb2RlPnt7IHNldHVwS2V5KHNldHVwLnNlY3JldCkgfX08L2NvZGU+PC9wPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImF0bGFzLWZpZWxkXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4+e3sgdCgnbWZhLmVucm9sbEZpcnN0Q29kZUxhYmVsJykgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPGlucHV0IFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZElucHV0JywgJ2F0bGFzLWlucHV0JylcIiB0eXBlPVwidGV4dFwiIG5hbWU9XCJjb2RlXCIgYXV0b2NvbXBsZXRlPVwib25lLXRpbWUtY29kZVwiIGlucHV0bW9kZT1cIm51bWVyaWNcIiBbdmFsdWVdPVwidmFsdWVzWydjb2RlJ10gPz8gJydcIiAoaW5wdXQpPVwic2V0VmFsdWUoJ2NvZGUnLCAkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiIC8+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgIEBpZiAoZW5yb2wudG90cENvZGVzID49IDIpIHtcbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJhdGxhcy1maWVsZFwiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgdCgnbWZhLmVucm9sbFNlY29uZENvZGVMYWJlbCcpIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPGlucHV0IFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZElucHV0JywgJ2F0bGFzLWlucHV0JylcIiB0eXBlPVwidGV4dFwiIG5hbWU9XCJzZWNvbmRDb2RlXCIgYXV0b2NvbXBsZXRlPVwib25lLXRpbWUtY29kZVwiIGlucHV0bW9kZT1cIm51bWVyaWNcIiBbdmFsdWVdPVwidmFsdWVzWydzZWNvbmRDb2RlJ10gPz8gJydcIiAoaW5wdXQpPVwic2V0VmFsdWUoJ3NlY29uZENvZGUnLCAkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiIC8+XG4gICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGFyaWEtbGl2ZT1cInBvbGl0ZVwiPnt7IGVucm9sLmJ1c3kgPyB0KCdtZmEuZW5yb2xsUHJlcGFyaW5nJykgOiAnJyB9fTwvcD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIEBpZiAoZW5yb2wuZW5yb2xsbWVudDsgYXMgdGV4dGVkKSB7XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXM9XCJtZmEtY29kZS10ZXh0ZWRcIiBhcmlhLWxpdmU9XCJwb2xpdGVcIj57eyB0KCdtZmEuY29kZVRleHRlZFRvJywgeyBwaG9uZTogdGV4dGVkLnBob25lID8/ICcnIH0pIH19PC9wPlxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJhdGxhcy1maWVsZFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IHQoJ21mYS5jb2RlTGFiZWwnKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkSW5wdXQnLCAnYXRsYXMtaW5wdXQnKVwiIHR5cGU9XCJ0ZXh0XCIgbmFtZT1cImNvZGVcIiBhdXRvY29tcGxldGU9XCJvbmUtdGltZS1jb2RlXCIgaW5wdXRtb2RlPVwibnVtZXJpY1wiIFt2YWx1ZV09XCJ2YWx1ZXNbJ2NvZGUnXSA/PyAnJ1wiIChpbnB1dCk9XCJzZXRWYWx1ZSgnY29kZScsICRhbnkoJGV2ZW50LnRhcmdldCkudmFsdWUpXCIgLz5cbiAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1CdXR0b25TZWNvbmRhcnknLCAnYXRsYXMtYnV0dG9uLXNlY29uZGFyeScpXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBkYXRhLWF0bGFzLXJlc2VuZD1cIlwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImJ1c3kgfHwgZW5yb2wuYnVzeVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlc2VuZEVucm9sbG1lbnQoKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyB0KCdzaWduSW4ucmVzZW5kQ29kZScpIH19XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImF0bGFzLWZpZWxkXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4+e3sgdCgnbWZhLnBob25lTGFiZWwnKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkSW5wdXQnLCAnYXRsYXMtaW5wdXQnKVwiIHR5cGU9XCJ0ZWxcIiBuYW1lPVwicGhvbmVcIiBhdXRvY29tcGxldGU9XCJ0ZWxcIiBbdmFsdWVdPVwidmFsdWVzWydwaG9uZSddID8/ICcnXCIgKGlucHV0KT1cInNldFZhbHVlKCdwaG9uZScsICRhbnkoJGV2ZW50LnRhcmdldCkudmFsdWUpXCIgLz5cbiAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJhdGxhcy10ZXh0XCI+e3sgdCgnbWZhLnBob25lSGludCcpIH19PC9wPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBAZm9yIChlcnJvciBvZiBlbnJvbC5lcnJvcnM7IHRyYWNrICRpbmRleCkge1xuICAgICAgICAgICAgPHAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiIHJvbGU9XCJhbGVydFwiPnt7IGVycm9yLm1lc3NhZ2UgfX08L3A+XG4gICAgICAgICAgfVxuICAgICAgICAgIEBpZiAoZW5yb2wubWV0aG9kICE9PSBudWxsICYmIGVucm9sLm9wdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgQGZvciAob3RoZXIgb2Ygb3RoZXJNZXRob2RzKGVucm9sKTsgdHJhY2sgb3RoZXIpIHtcbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1CdXR0b25TZWNvbmRhcnknLCAnYXRsYXMtYnV0dG9uLXNlY29uZGFyeScpXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBbYXR0ci5kYXRhLWF0bGFzLW1mYS1tZXRob2RdPVwib3RoZXJcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJidXN5IHx8IGVucm9sLmJ1c3lcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjaG9vc2VNZXRob2Qob3RoZXIpXCJcbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHt7IHQob3RoZXIgPT09ICd0b3RwJyA/ICdtZmEuZW5yb2xsVG90cE9wdGlvbicgOiAnbWZhLmVucm9sbFNtc09wdGlvbicpIH19XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBAZm9yIChmIG9mIGZpZWxkcygpOyB0cmFjayAkaW5kZXgpIHtcbiAgICAgICAgICBAaWYgKGYua2luZCA9PT0gJ2lucHV0Jykge1xuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiYXRsYXMtZmllbGRcIj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgdChmLmxhYmVsS2V5KSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkSW5wdXQnLCAnYXRsYXMtaW5wdXQnKVwiXG4gICAgICAgICAgICAgICAgW3R5cGVdPVwiZi50eXBlXCJcbiAgICAgICAgICAgICAgICBbYXR0ci5uYW1lXT1cImYubmFtZVwiXG4gICAgICAgICAgICAgICAgW3ZhbHVlXT1cInZhbHVlc1tmLm5hbWVdID8/ICcnXCJcbiAgICAgICAgICAgICAgICAoaW5wdXQpPVwic2V0VmFsdWUoZi5uYW1lLCAkYW55KCRldmVudC50YXJnZXQpLnZhbHVlKVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgIEBmb3IgKGVycm9yIG9mIGZpZWxkRXJyb3JzRm9yKGYubmFtZSk7IHRyYWNrIGVycm9yLmNvZGUpIHtcbiAgICAgICAgICAgICAgICA8c3BhbiBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCI+e3sgZXJyb3JUZXh0KGVycm9yKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICB9IEBlbHNlIGlmIChmLmtpbmQgPT09ICdhbGVydCcpIHtcbiAgICAgICAgICAgIDxwIFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZEVycm9yJywgJ2F0bGFzLWVycm9yJylcIiByb2xlPVwiYWxlcnRcIj57eyB0KGYubGFiZWxLZXkpIH19PC9wPlxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgPHA+e3sgdChmLmxhYmVsS2V5KSB9fTwvcD5cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKGF3YWl0aW5nUG9saWNpZXMoKSkge1xuICAgICAgICAgIDwhLS0gQSByZXF1aXJlZCBwb2xpY3kgY2hhbmdlZDogc2Nyb2xsLW1vZGUgb25lcyBpbiB0aGVpciBkaWFsb2csIHRoZSByZXN0IGFzIGNoZWNrYm94ZXMuIC0tPlxuICAgICAgICAgIDxhdGxhcy1wb2xpY3ktYWNjZXB0LXN0ZXBcbiAgICAgICAgICAgIFthdHRlbXB0XT1cImF0dGVtcHRcIlxuICAgICAgICAgICAgW2J1c3ldPVwiYnVzeVwiXG4gICAgICAgICAgICAoc3VibWl0Rmxvdyk9XCJzdWJtaXRGbG93LmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAoZGVjbGluZWQpPVwicG9saWN5RGVjbGluZWQuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICA+PC9hdGxhcy1wb2xpY3ktYWNjZXB0LXN0ZXA+XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dDYXB0Y2hhKCkpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYXRsYXMtY2FwdGNoYVwiIGRhdGEtYXRsYXMtY2FwdGNoYT1cIlwiIFthdGxhc0NhcHRjaGFTbG90XT1cImNhcHRjaGFcIj48L2Rpdj5cbiAgICAgICAgfVxuXG4gICAgICAgIEBpZiAoc2hvd1N1Ym1pdCgpKSB7XG4gICAgICAgICAgPGJ1dHRvbiBbY2xhc3NdPVwiY2xzKCdmb3JtQnV0dG9uUHJpbWFyeScsICdhdGxhcy1idXR0b24nKVwiIFtkaXNhYmxlZF09XCJidXN5IHx8IChlbnJvbGxpbmcoKSAmJiAhIWVucm9sbG1lbnRTdGF0ZT8uYnVzeSlcIiB0eXBlPVwic3VibWl0XCI+XG4gICAgICAgICAgICB7eyB0KHN1Ym1pdEtleSgpKSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChzaG93U21zU2Vjb25kRmFjdG9yKCkpIHtcbiAgICAgICAgICBAaWYgKHNtc1NlY29uZEZhY3RvclNlbnRUbygpOyBhcyBzZW50VG8pIHtcbiAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXM9XCJzbXMtc2Vjb25kLWZhY3Rvci1zZW50XCIgYXJpYS1saXZlPVwicG9saXRlXCI+XG4gICAgICAgICAgICAgIHt7IHQoJ21mYS5jb2RlVGV4dGVkVG8nLCB7IHBob25lOiBzZW50VG8gfSkgfX1cbiAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblNlY29uZGFyeScsICdhdGxhcy1idXR0b24tc2Vjb25kYXJ5JylcIlxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgZGF0YS1hdGxhcz1cInNtcy1zZWNvbmQtZmFjdG9yXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImJ1c3kgfHwgISF0ZXh0ZWRTZWNvbmRGYWN0b3I/LmJ1c3lcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic21zU2Vjb25kRmFjdG9yLmVtaXQoKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IHRleHRlZFNlY29uZEZhY3Rvcj8uYnVzeSA/IHQoJ3NpZ25Jbi5zZW5kaW5nJykgOiB0KCdtZmEuc21zQ29kZU9wdGlvbicpIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIEBpZiAodGV4dGVkU2Vjb25kRmFjdG9yPy5lcnJvcjsgYXMgbWVzc2FnZSkge1xuICAgICAgICAgICAgICA8cCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCIgcm9sZT1cImFsZXJ0XCI+e3sgbWVzc2FnZSB9fTwvcD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dFbWFpbFNlY29uZEZhY3RvcigpKSB7XG4gICAgICAgICAgQGlmIChlbWFpbFNlY29uZEZhY3RvclNlbnRUbygpOyBhcyBzZW50VG8pIHtcbiAgICAgICAgICAgIDxwIGNsYXNzPVwiYXRsYXMtdGV4dFwiIGRhdGEtYXRsYXM9XCJlbWFpbC1zZWNvbmQtZmFjdG9yLXNlbnRcIiBhcmlhLWxpdmU9XCJwb2xpdGVcIj5cbiAgICAgICAgICAgICAge3sgdCgnc2lnbkluLmNvZGVTZW50VG8nLCB7IGVtYWlsOiBzZW50VG8gfSkgfX1cbiAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblNlY29uZGFyeScsICdhdGxhcy1idXR0b24tc2Vjb25kYXJ5JylcIlxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgZGF0YS1hdGxhcz1cImVtYWlsLXNlY29uZC1mYWN0b3JcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYnVzeSB8fCAhIWVtYWlsZWRTZWNvbmRGYWN0b3I/LmJ1c3lcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiZW1haWxTZWNvbmRGYWN0b3IuZW1pdCgpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAge3sgZW1haWxlZFNlY29uZEZhY3Rvcj8uYnVzeSA/IHQoJ3NpZ25Jbi5zZW5kaW5nJykgOiB0KCdzaWduSW4uZW1haWxDb2RlT3B0aW9uJykgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgQGlmIChlbWFpbGVkU2Vjb25kRmFjdG9yPy5lcnJvcjsgYXMgbWVzc2FnZSkge1xuICAgICAgICAgICAgICA8cCBbY2xhc3NdPVwiY2xzKCdmb3JtRmllbGRFcnJvcicsICdhdGxhcy1lcnJvcicpXCIgcm9sZT1cImFsZXJ0XCI+e3sgbWVzc2FnZSB9fTwvcD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dFbWFpbENvZGVPcHRpb24oKSkge1xuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2Zvcm1CdXR0b25TZWNvbmRhcnknLCAnYXRsYXMtYnV0dG9uLXNlY29uZGFyeScpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJidXN5XCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1zdHJhdGVneV09XCJwcmVwYXJlZEZhY3RvciA9PT0gJ2VtYWlsX2NvZGUnID8gbnVsbCA6ICdlbWFpbF9jb2RlJ1wiXG4gICAgICAgICAgICBbYXR0ci5kYXRhLWF0bGFzLXJlc2VuZF09XCJwcmVwYXJlZEZhY3RvciA9PT0gJ2VtYWlsX2NvZGUnID8gJycgOiBudWxsXCJcbiAgICAgICAgICAgIChjbGljayk9XCJjaG9vc2VGYWN0b3IuZW1pdCgnZW1haWxfY29kZScpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7eyB0KHByZXBhcmVkRmFjdG9yID09PSAnZW1haWxfY29kZScgPyAnc2lnbkluLnJlc2VuZENvZGUnIDogJ3NpZ25Jbi51c2VFbWFpbENvZGUnKSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICA8L2Zvcm0+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEF0dGVtcHRGbG93Q29tcG9uZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhdGxhcyA9IGluamVjdChBdGxhc1NlcnZpY2UpO1xuXG4gIEBJbnB1dCgpIGF0dGVtcHQ6IEF0dGVtcHRWaWV3IHwgbnVsbCA9IG51bGw7XG4gIEBJbnB1dCgpIGJ1c3kgPSBmYWxzZTtcbiAgQElucHV0KCkgZXJyb3JzOiBGaWVsZEVycm9yW10gPSBbXTtcbiAgLyoqIGBGbG93U3RhdGUuc2Vzc2lvbktlcHRgOiB3aGV0aGVyIHRoaXMgYnJvd3NlciBrZXB0IHRoZSBzZXNzaW9uIHRoZSBzaWduLWluIGNyZWF0ZWQuICovXG4gIEBJbnB1dCgpIHNlc3Npb25LZXB0OiBib29sZWFuIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBASW5wdXQoKSB0aXRsZUtleSA9ICdzaWduSW4udGl0bGUnO1xuICAvKipcbiAgICogVGhlIHNpZ24taW4gY2FwdGNoYSwgZHJhd24gYWJvdmUgdGhlIHN1Ym1pdCBidXR0b24gb24gdGhlIGlkZW50aWZpZXIgc3RlcFxuICAgKiAoYW4gYWx3YXlzLW9uIHNpZ24taW4gY2FwdGNoYSkgYW5kIG9uIHRoZSBjaGFsbGVuZ2Ugc3RlcCB0aGUgc2VydmVyIGRlbWFuZHNcbiAgICogd2l0aCBgbmVlZHNfY2FwdGNoYWAuIE51bGwgd2hlbiB0aGUgZmxvdyBkcmF3cyBub25lLlxuICAgKi9cbiAgQElucHV0KCkgY2FwdGNoYTogQ2FwdGNoYUNvbnRyb2xsZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIFRoZSBmaXJzdCBmYWN0b3JzIHRvIG9mZmVyIG9uIHRoZSBgbmVlZHNfZmlyc3RfZmFjdG9yYCBzdGVwIOKAlCBwYXNzXG4gICAqIGBBdGxhc0Zsb3dDb250cm9sbGVyLmZpcnN0RmFjdG9ycygpYCwgd2hpY2ggZHJvcHMgZW1haWwgY29kZSAvIGxpbmsgd2hpbGUgdGhlXG4gICAqIGFwcCBjYW5ub3QgZGVsaXZlciBlbWFpbC4gTnVsbCB1c2VzIHRoZSBzZXJ2ZXIncyBsaXN0IGFzLWlzLlxuICAgKi9cbiAgQElucHV0KCkgZmlyc3RGYWN0b3JzOiBzdHJpbmdbXSB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGZpcnN0IGZhY3RvciBhbHJlYWR5IHNlbnQgKGBBdGxhc0Zsb3dDb250cm9sbGVyLnByZXBhcmVkRmFjdG9yKClgKTogaXRzIGNvZGUgaXMgY29sbGVjdGVkLiAqL1xuICBASW5wdXQoKSBwcmVwYXJlZEZhY3Rvcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIEVtaXRzIHRoZSBjb2xsZWN0ZWQgZmllbGQgdmFsdWVzIHdoZW4gdGhlIGZvcm0gaXMgc3VibWl0dGVkLiAqL1xuICBAT3V0cHV0KCkgc3VibWl0RmxvdyA9IG5ldyBFdmVudEVtaXR0ZXI8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4oKTtcbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHVzZXIgcGlja3MgYSBmaXJzdCBmYWN0b3IgdGhlIHNlcnZlciBtdXN0IHNlbmQgZmlyc3QgKGFuIGVtYWlsZWQgY29kZSkuICovXG4gIEBPdXRwdXQoKSBjaG9vc2VGYWN0b3IgPSBuZXcgRXZlbnRFbWl0dGVyPCdlbWFpbF9jb2RlJz4oKTtcbiAgLyoqXG4gICAqIE9mZmVyIFwiRW1haWwgbWUgYSBjb2RlIGluc3RlYWRcIiBhdCB0aGUgc2Vjb25kIGZhY3RvciAodGhlIGluc3RhbmNlJ3NcbiAgICogYGFjY291bnQuZW1haWxTZWNvbmRGYWN0b3JgKTsgYGVtYWlsU2Vjb25kRmFjdG9yYCBhc2tzIGZvciBpdCBhbmRcbiAgICogYGVtYWlsZWRTZWNvbmRGYWN0b3JgIHJlcG9ydHMgaG93IGl0IHdlbnQuXG4gICAqL1xuICBASW5wdXQoKSBvZmZlckVtYWlsU2Vjb25kRmFjdG9yID0gZmFsc2U7XG4gIC8qKiBgQXRsYXNGbG93Q29udHJvbGxlci5lbWFpbFNlY29uZEZhY3RvcigpYDogaW4gZmxpZ2h0LCB3aGVyZSBpdCB3ZW50LCBvciB3aHkgbm90LiAqL1xuICBASW5wdXQoKSBlbWFpbGVkU2Vjb25kRmFjdG9yOiB7IGJ1c3k/OiBib29sZWFuOyBzZW50VG8/OiBzdHJpbmc7IGVycm9yPzogc3RyaW5nIH0gfCBudWxsID0gbnVsbDtcbiAgQE91dHB1dCgpIGVtYWlsU2Vjb25kRmFjdG9yID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICAvKipcbiAgICogT2ZmZXIgXCJUZXh0IG1lIGEgY29kZSBpbnN0ZWFkXCIgYXQgdGhlIHNlY29uZCBmYWN0b3IgKHdoZXJlIHRoZSBhcHAgb2ZmZXJzXG4gICAqIHRleHRlZCBjb2RlcywgYEF0bGFzRmxvd0NvbnRyb2xsZXIubWZhQ2hvaWNlcygpLnNtc2ApOyBgc21zU2Vjb25kRmFjdG9yYFxuICAgKiBhc2tzIGZvciBpdCBhbmQgYHRleHRlZFNlY29uZEZhY3RvcmAgcmVwb3J0cyBob3cgaXQgd2VudC5cbiAgICovXG4gIEBJbnB1dCgpIG9mZmVyU21zU2Vjb25kRmFjdG9yID0gZmFsc2U7XG4gIC8qKiBgQXRsYXNGbG93Q29udHJvbGxlci5zbXNTZWNvbmRGYWN0b3IoKWA6IGluIGZsaWdodCwgd2hlcmUgaXQgd2VudCwgb3Igd2h5IG5vdC4gKi9cbiAgQElucHV0KCkgdGV4dGVkU2Vjb25kRmFjdG9yOiB7IGJ1c3k/OiBib29sZWFuOyBzZW50VG8/OiBzdHJpbmc7IGVycm9yPzogc3RyaW5nIH0gfCBudWxsID0gbnVsbDtcbiAgQE91dHB1dCgpIHNtc1NlY29uZEZhY3RvciA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqXG4gICAqIFRoZSBNRkEgZW5yb2xtZW50IHN0ZXAgKGBBdGxhc0Zsb3dDb250cm9sbGVyLmVucm9sbG1lbnRgIGFuZFxuICAgKiBgZW5yb2xsbWVudFN0YXRlKClgKTogdGhlIGF1dGhlbnRpY2F0b3IgYXBwJ3MgUVIgY29kZSBhbmQgc2V0dXAga2V5LCBvciBhXG4gICAqIHRleHRlZCBjb2RlLiBOdWxsOiB0aGUgc3RlcCBhc2tzIGZvciB0d28gYXV0aGVudGljYXRvciBjb2RlcyBvbmx5LlxuICAgKi9cbiAgQElucHV0KCkgZW5yb2xsbWVudDogTWZhRW5yb2xsbWVudENvbnRyb2xsZXIgfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgZW5yb2xsbWVudFN0YXRlOiBNZmFFbnJvbGxtZW50U3RhdGUgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIFRoZSBpbnN0YW5jZSdzIGBhY2NvdW50LmVtYWlsVmVyaWZpY2F0aW9uYC4gT24gYGxpbmtgIGEgc2lnbi11cCdzXG4gICAqIHZlcmlmaWNhdGlvbiBzdGVwIGhhcyBub3RoaW5nIHRvIHR5cGU6IGl0IHNheXMgdG8gb3BlbiB0aGUgZW1haWxlZCBsaW5rXG4gICAqIHdoaWxlIHRoZSBmbG93IHBvbGxzLCBhbmQgb2ZmZXJzIGEgcmVzZW5kIChgcmVzZW5kYCkuXG4gICAqL1xuICBASW5wdXQoKSBlbWFpbFZlcmlmaWNhdGlvbjogc3RyaW5nID0gJ2NvZGUnO1xuICBAT3V0cHV0KCkgcmVzZW5kID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICAvKiogVGhlIHVzZXIgZGVjbGluZWQgYSBwb2xpY3kgdGhlIHNpZ24taW4gd2FzIHdhaXRpbmcgb24gKGBuZWVkc19wb2xpY3lfYWNjZXB0YW5jZWApOiBjYW5jZWwgdGhlIGF0dGVtcHQuICovXG4gIEBPdXRwdXQoKSBwb2xpY3lEZWNsaW5lZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIHByb3RlY3RlZCB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBwcm90ZWN0ZWQgdChrZXk6IHN0cmluZywgdmFycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcge1xuICAgIHJldHVybiB0cmFuc2xhdGUodGhpcy5hdGxhcy5sb2NhbGl6YXRpb24sIGtleSwgdmFycyk7XG4gIH1cblxuICAvKiogQSBzZXJ2ZXIgZXJyb3IgaW4gdGhlIGFwcCdzIGxhbmd1YWdlIChgZXJyb3IuPHJlYXNvbj5gLCBlbHNlIHRoZSBzZXJ2ZXIncyBtZXNzYWdlKS4gKi9cbiAgcHJvdGVjdGVkIGVycm9yVGV4dChlcnJvcjogRmllbGRFcnJvcik6IHN0cmluZyB7XG4gICAgLy8gYGVycm9yTG9jYWxpemF0aW9uYCBpcyByZWFkIGRlZmVuc2l2ZWx5OiBhIHN0YW5kLWluIHNlcnZpY2UgbWF5IGxhY2sgaXQuXG4gICAgY29uc3QgbGF5ZXIgPSAodGhpcy5hdGxhcyBhcyB7IGVycm9yTG9jYWxpemF0aW9uPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB9KS5lcnJvckxvY2FsaXphdGlvbjtcbiAgICByZXR1cm4gbG9jYWxpemVkRXJyb3JNZXNzYWdlKGVycm9yLCBsYXllciA/PyB0aGlzLmF0bGFzLmxvY2FsaXphdGlvbiwgdGhpcy5hdGxhcy5sb2NhbGl6YXRpb24pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNscyhrZXk6IEVsZW1lbnRLZXksIGJhc2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNsYXNzRm9yKGtleSwgdGhpcy5hdGxhcy5hcHBlYXJhbmNlLCBiYXNlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRWYWx1ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlcyA9IHsgLi4udGhpcy52YWx1ZXMsIFtuYW1lXTogdmFsdWUgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblN1Ym1pdChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIC8vIEVucm9sbWVudDogdGV4dCB0aGUgY29kZSB0byB0aGUgdHlwZWQgbnVtYmVyLCBvciBjb25maXJtIHRoZSBmYWN0b3IuXG4gICAgaWYgKHRoaXMuZW5yb2xsaW5nKCkgJiYgdGhpcy5lbnJvbGxtZW50KSB7XG4gICAgICB2b2lkIHRoaXMuZW5yb2xsbWVudC5zdWJtaXQodGhpcy52YWx1ZXMpLnRoZW4oKG5leHQpID0+IHtcbiAgICAgICAgaWYgKG5leHQpIHRoaXMuc3VibWl0Rmxvdy5lbWl0KG5leHQpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3VibWl0Rmxvdy5lbWl0KHRoaXMudmFsdWVzKTtcbiAgfVxuXG4gIC8qKiBUaGUgc2hhcmVkIGVucm9sbWVudCBzdGVwIGlzIGRyYXduIChhIGNvbnRyb2xsZXIgd2FzIHBhc3NlZCBhbmQgdGhlIGZsb3cgaXMgZW5yb2xsaW5nKS4gKi9cbiAgcHJvdGVjdGVkIGVucm9sbGluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGVwKCkua2luZCA9PT0gJ2Vucm9sbF9zZWNvbmRfZmFjdG9yJyAmJiAhIXRoaXMuZW5yb2xsbWVudCAmJiAhIXRoaXMuZW5yb2xsbWVudFN0YXRlO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNob29zZU1ldGhvZChtZXRob2Q6IE1mYUVucm9sbG1lbnRTdHJhdGVneSk6IHZvaWQge1xuICAgIHRoaXMudmFsdWVzID0ge307XG4gICAgdm9pZCB0aGlzLmVucm9sbG1lbnQ/LmNob29zZShtZXRob2QpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlc2VuZEVucm9sbG1lbnQoKTogdm9pZCB7XG4gICAgdm9pZCB0aGlzLmVucm9sbG1lbnQ/LnJlc2VuZCgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG90aGVyTWV0aG9kcyhzdGF0ZTogTWZhRW5yb2xsbWVudFN0YXRlKTogTWZhRW5yb2xsbWVudFN0cmF0ZWd5W10ge1xuICAgIHJldHVybiBzdGF0ZS5vcHRpb25zLmZpbHRlcigobSkgPT4gbSAhPT0gc3RhdGUubWV0aG9kKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXR1cEtleShzZWNyZXQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdyb3VwU2V0dXBLZXkoc2VjcmV0KTtcbiAgfVxuXG4gIC8qKiBUaGUgc3VibWl0IGJ1dHRvbidzIGxhYmVsIGtleSAoZW5yb2xtZW50OiBcIlRleHQgbWUgYSBjb2RlXCIgYmVmb3JlIHRoZSBudW1iZXIgaXMgc2VudCkuICovXG4gIHByb3RlY3RlZCBzdWJtaXRLZXkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gKHRoaXMuZW5yb2xsaW5nKCkgJiYgdGhpcy5lbnJvbGxtZW50U3RhdGUgJiYgZW5yb2xsbWVudFN1Ym1pdEtleSh0aGlzLmVucm9sbG1lbnRTdGF0ZSkpIHx8ICdzaWduSW4uc3VibWl0JztcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG93U21zU2Vjb25kRmFjdG9yKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm9mZmVyU21zU2Vjb25kRmFjdG9yICYmIHRoaXMuc3RlcCgpLmtpbmQgPT09ICdjb2xsZWN0X3NlY29uZF9mYWN0b3InO1xuICB9XG5cbiAgLyoqIFdoZXJlIHRoZSB0ZXh0ZWQgc2Vjb25kLWZhY3RvciBjb2RlIHdlbnQgKG1hc2tlZCksIG9uY2UgaXQgd2FzIHNlbnQuICovXG4gIHByb3RlY3RlZCBzbXNTZWNvbmRGYWN0b3JTZW50VG8oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3Qgc2VudCA9IHRoaXMudGV4dGVkU2Vjb25kRmFjdG9yPy5zZW50VG87XG4gICAgcmV0dXJuIHR5cGVvZiBzZW50ID09PSAnc3RyaW5nJyA/IHNlbnQgfHwgJyAnIDogbnVsbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBmb3JtRXJyb3JzKCk6IEZpZWxkRXJyb3JbXSB7XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JzLmZpbHRlcigoZXJyb3IpID0+ICFlcnJvci5wYXJhbSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRFcnJvcnNGb3IobmFtZTogc3RyaW5nKTogRmllbGRFcnJvcltdIHtcbiAgICByZXR1cm4gdGhpcy5lcnJvcnMuZmlsdGVyKChlcnJvcikgPT4gZXJyb3IucGFyYW0gPT09IG5hbWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGVwKCkge1xuICAgIHJldHVybiB0aGlzLmF0dGVtcHQgPyBuZXh0U3RlcCh0aGlzLmF0dGVtcHQpIDogKHsga2luZDogJ2NvbGxlY3RfaWRlbnRpZmllcicgfSBhcyBjb25zdCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd0NhcHRjaGEoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qga2luZCA9IHRoaXMuc3RlcCgpLmtpbmQ7XG4gICAgcmV0dXJuICEhdGhpcy5jYXB0Y2hhICYmIChraW5kID09PSAnY29sbGVjdF9pZGVudGlmaWVyJyB8fCBraW5kID09PSAnY29sbGVjdF9jYXB0Y2hhJyk7XG4gIH1cblxuICAvKiogVGhlIGZpcnN0IGZhY3RvcnMgb24gb2ZmZXIgYXQgYSBgbmVlZHNfZmlyc3RfZmFjdG9yYCBzdGVwIChlbXB0eSBvbiBhbnkgb3RoZXIpLiAqL1xuICBwcml2YXRlIG9mZmVyZWQoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHN0ZXAgPSB0aGlzLnN0ZXAoKTtcbiAgICBpZiAoc3RlcC5raW5kICE9PSAnY29sbGVjdF9maXJzdF9mYWN0b3InKSByZXR1cm4gW107XG4gICAgcmV0dXJuIHRoaXMuZmlyc3RGYWN0b3JzID8/IHN0ZXAuc3RyYXRlZ2llcztcbiAgfVxuXG4gIHByb3RlY3RlZCBsaW5rT25seSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gYXdhaXRpbmdTaWduVXBMaW5rKHRoaXMuYXR0ZW1wdCwgdGhpcy5lbWFpbFZlcmlmaWNhdGlvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd0VtYWlsU2Vjb25kRmFjdG9yKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm9mZmVyRW1haWxTZWNvbmRGYWN0b3IgJiYgdGhpcy5zdGVwKCkua2luZCA9PT0gJ2NvbGxlY3Rfc2Vjb25kX2ZhY3Rvcic7XG4gIH1cblxuICAvKiogV2hlcmUgdGhlIGVtYWlsZWQgc2Vjb25kLWZhY3RvciBjb2RlIHdlbnQgKG1hc2tlZCksIG9uY2UgaXQgd2FzIHNlbnQuICovXG4gIHByb3RlY3RlZCBlbWFpbFNlY29uZEZhY3RvclNlbnRUbygpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBzZW50ID0gdGhpcy5lbWFpbGVkU2Vjb25kRmFjdG9yPy5zZW50VG87XG4gICAgcmV0dXJuIHR5cGVvZiBzZW50ID09PSAnc3RyaW5nJyA/IHNlbnQgfHwgJyAnIDogbnVsbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG93RW1haWxDb2RlT3B0aW9uKCk6IGJvb2xlYW4ge1xuICAgIC8vIEJlZm9yZSB0aGUgY29kZSBpcyBzZW50OiB0aGUgY2hvaWNlIChvciB0aGUgcmV0cnkgb2YgYSBmYWlsZWQgYXV0b21hdGljXG4gICAgLy8gc2VuZCkuIEFmdGVyOiBcIlJlc2VuZCBjb2RlXCIuXG4gICAgcmV0dXJuIHRoaXMub2ZmZXJlZCgpLmluY2x1ZGVzKCdlbWFpbF9jb2RlJyk7XG4gIH1cblxuICAvKiogVGhlIFwid2Ugc2VudCBhIGNvZGUgdG8g4oCmXCIgbGluZSBvbiB0aGUgY29kZSBzdGVwLiAqL1xuICBwcm90ZWN0ZWQgY29kZVNlbnRUZXh0KCk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICh0aGlzLnN0ZXAoKS5raW5kICE9PSAnY29sbGVjdF9maXJzdF9mYWN0b3InIHx8IHRoaXMucHJlcGFyZWRGYWN0b3IgIT09ICdlbWFpbF9jb2RlJykgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMudCgnc2lnbkluLmNvZGVTZW50VG8nLCB7IGVtYWlsOiB0aGlzLmF0dGVtcHQ/LmlkZW50aWZpZXIgPz8gJycgfSk7XG4gIH1cblxuICAvKiogVGhlIGF0dGVtcHQgaXMgYG5lZWRzX3BvbGljeV9hY2NlcHRhbmNlYC4gKi9cbiAgcHJvdGVjdGVkIGF3YWl0aW5nUG9saWNpZXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc3RlcCgpLmtpbmQgPT09ICdhY2NlcHRfcG9saWNpZXMnO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNob3dTdWJtaXQoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qga2luZCA9IHRoaXMuc3RlcCgpLmtpbmQ7XG4gICAgLy8gTm90aGluZyB0byBzdWJtaXQgb24gYSBmaXJzdC1mYWN0b3Igc3RlcCB0aGF0IG9ubHkgb2ZmZXJzIGFuIGVtYWlsZWQgY29kZVxuICAgIC8vIHVudGlsIHRoYXQgY29kZSBpcyBzZW50LlxuICAgIGlmIChraW5kID09PSAnY29sbGVjdF9maXJzdF9mYWN0b3InKSByZXR1cm4gdGhpcy5maWVsZHMoKS5sZW5ndGggPiAwO1xuICAgIGlmICh0aGlzLmxpbmtPbmx5KCkpIHJldHVybiBmYWxzZTtcbiAgICAvLyBFbnJvbG1lbnQ6IG5vdGhpbmcgdG8gc3VibWl0IHdoaWxlIGNob29zaW5nIGEgbWV0aG9kIG9yIGZldGNoaW5nIHRoZSBzZXR1cC5cbiAgICBpZiAodGhpcy5lbnJvbGxpbmcoKSAmJiB0aGlzLmVucm9sbG1lbnRTdGF0ZSAmJiAhZW5yb2xsbWVudFN1Ym1pdEtleSh0aGlzLmVucm9sbG1lbnRTdGF0ZSkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4ga2luZCAhPT0gJ2RvbmUnICYmIGtpbmQgIT09ICdhd2FpdF9vYXV0aCcgJiYga2luZCAhPT0gJ2FjY2VwdF9wb2xpY2llcyc7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRzKCk6IFN0ZXBGaWVsZFtdIHtcbiAgICBjb25zdCBzdGVwID0gdGhpcy5zdGVwKCk7XG4gICAgc3dpdGNoIChzdGVwLmtpbmQpIHtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfaWRlbnRpZmllcic6XG4gICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnaWRlbnRpZmllcicsIGxhYmVsS2V5OiAnc2lnbkluLmlkZW50aWZpZXJMYWJlbCcsIHR5cGU6ICdlbWFpbCcgfV07XG4gICAgICBjYXNlICdjb2xsZWN0X2ZpcnN0X2ZhY3Rvcic6IHtcbiAgICAgICAgaWYgKHRoaXMucHJlcGFyZWRGYWN0b3IgPT09ICdlbWFpbF9jb2RlJykge1xuICAgICAgICAgIHJldHVybiBbeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnY29kZScsIGxhYmVsS2V5OiAnc2lnbkluLmVtYWlsQ29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBwYXNzd29yZCBmaWVsZCB1bmxlc3MgdGhlIG9ubHkgb2ZmZXIgaXMgYW4gZW1haWxlZCBjb2RlIChjaG9zZW5cbiAgICAgICAgLy8gd2l0aCB0aGUgYnV0dG9uIGJlbG93IHRoZSBmb3JtKS5cbiAgICAgICAgY29uc3Qgb2ZmZXJlZCA9IHRoaXMub2ZmZXJlZCgpO1xuICAgICAgICByZXR1cm4gb2ZmZXJlZC5pbmNsdWRlcygnZW1haWxfY29kZScpICYmICFvZmZlcmVkLmluY2x1ZGVzKCdwYXNzd29yZCcpXG4gICAgICAgICAgPyBbXVxuICAgICAgICAgIDogW3sga2luZDogJ2lucHV0JywgbmFtZTogJ3Bhc3N3b3JkJywgbGFiZWxLZXk6ICdzaWduSW4ucGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICB9XG4gICAgICBjYXNlICdjb2xsZWN0X3NlY29uZF9mYWN0b3InOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ21mYS5jb2RlTGFiZWwnLCB0eXBlOiAndGV4dCcgfV07XG4gICAgICBjYXNlICdlbnJvbGxfc2Vjb25kX2ZhY3Rvcic6XG4gICAgICAgIC8vIFRoZSBzaGFyZWQgZW5yb2xtZW50IHN0ZXAgZHJhd3MgaXRzIG93biBmaWVsZHMgKGFib3ZlKS5cbiAgICAgICAgaWYgKHRoaXMuZW5yb2xsaW5nKCkpIHJldHVybiBbXTtcbiAgICAgICAgLy8gVHdvIGNvbnNlY3V0aXZlIGNvZGVzICjCpzUuNik6IGEgcGhvbmUgd2l0aCBhIGZhc3QgY2xvY2sgZmFpbHMgaGVyZVxuICAgICAgICAvLyByYXRoZXIgdGhhbiBvbiBldmVyeSBzaWduLWluIGFmdGVyd2FyZHMuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnY29kZScsIGxhYmVsS2V5OiAnbWZhLmVucm9sbEZpcnN0Q29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH0sXG4gICAgICAgICAgeyBraW5kOiAnaW5wdXQnLCBuYW1lOiAnc2Vjb25kQ29kZScsIGxhYmVsS2V5OiAnbWZhLmVucm9sbFNlY29uZENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9LFxuICAgICAgICBdO1xuICAgICAgY2FzZSAnY29sbGVjdF9lbWFpbF9jb2RlJzpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlua09ubHkoKSA/IFtdIDogW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ3NpZ25Jbi5lbWFpbENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9XTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfbmV3X3Bhc3N3b3JkJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdwYXNzd29yZCcsIGxhYmVsS2V5OiAncmVzZXQubmV3UGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICBjYXNlICdhY2NlcHRfcG9saWNpZXMnOlxuICAgICAgICAvLyBEcmF3biBieSA8YXRsYXMtcG9saWN5LWFjY2VwdC1zdGVwPiBhYm92ZS5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgY2FzZSAnY29sbGVjdF9jYXB0Y2hhJzpcbiAgICAgICAgLy8gwqc1IHRoZSBzZXJ2ZXIgd2l0aGhlbGQgdGhlIGF0dGVtcHQgdW50aWwgYSBjYXB0Y2hhIGNsZWFycy4gU29sdmluZyB0aGVcbiAgICAgICAgLy8gd2lkZ2V0IHJlc3VibWl0cyB0aGUgaWRlbnRpZmllciBvbiBpdHMgb3duOyB0aGUgYnV0dG9uIHJldHJpZXMuXG4gICAgICAgIHJldHVybiBbbXNnKCdjYXB0Y2hhLnByb21wdCcpXTtcbiAgICAgIGNhc2UgJ2F3YWl0X29hdXRoJzpcbiAgICAgICAgcmV0dXJuIFttc2coJ3NpZ25Jbi5tYWdpY0xpbmtTZW50JyldO1xuICAgICAgY2FzZSAnZG9uZSc6XG4gICAgICAgIC8vIFNpZ25lZCBpbiBvbmx5IHdoZW4gdGhpcyBicm93c2VyIGhvbGRzIHRoZSBzZXNzaW9uOyBhIGJsb2NrZWQgY29va2llIGlzIHNhaWRcbiAgICAgICAgLy8gcGxhaW5seS4gXCJDaGVjayB0aGUgb3RoZXIgdGFiXCIgaXMgZm9yIGEgc2lnbi1pbiBjb21wbGV0ZWQgb24gYW5vdGhlciBkZXZpY2UuXG4gICAgICAgIGlmICh0aGlzLnNlc3Npb25LZXB0ID09PSB0cnVlKSByZXR1cm4gW21zZygnc2lnbkluLnNpZ25lZEluJyldO1xuICAgICAgICBpZiAodGhpcy5zZXNzaW9uS2VwdCA9PT0gZmFsc2UpIHJldHVybiBbeyBraW5kOiAnYWxlcnQnLCBuYW1lOiAnJywgbGFiZWxLZXk6ICdzaWduSW4uc2Vzc2lvbk5vdEtlcHQnLCB0eXBlOiAndGV4dCcgfV07XG4gICAgICAgIHJldHVybiBbbXNnKCdzaWduSW4uY2hlY2tPdGhlclRhYicpXTtcbiAgICAgIGNhc2UgJ3Jlc3RhcnQnOlxuICAgICAgICByZXR1cm4gW21zZygnZXJyb3IuZ2VuZXJpYycpXTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIC8vIEEgc3RhdHVzIHRoaXMgU0RLIHZlcnNpb24gZG9lcyBub3Qga25vdy4gQW4gaG9uZXN0IG1lc3NhZ2UgYmVhdHMgYVxuICAgICAgICAvLyBibGFuayBsb2dpbiBib3ggdGhlIHVzZXIgY2Fubm90IGFjdCBvbi5cbiAgICAgICAgcmV0dXJuIFttc2coJ2Vycm9yLmdlbmVyaWMnKV07XG4gICAgfVxuICB9XG59XG5cbi8qKiBBIHJlYWQtb25seSBtZXNzYWdlIHJvdzogYGxhYmVsS2V5YCBob2xkcyB0aGUgaTE4biBrZXkgb2YgdGhlIHRleHQgdG8gc2hvdy4gKi9cbmZ1bmN0aW9uIG1zZyhsYWJlbEtleTogc3RyaW5nKTogU3RlcEZpZWxkIHtcbiAgcmV0dXJuIHsga2luZDogJ21lc3NhZ2UnLCBuYW1lOiAnJywgbGFiZWxLZXksIHR5cGU6ICd0ZXh0JyB9O1xufVxuIl19