@atlasauth/angular 0.1.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.
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +195 -0
- package/dist/esm2022/atlasauth-angular.mjs +5 -0
- package/dist/esm2022/lib/appearance.mjs +92 -0
- package/dist/esm2022/lib/atlas.config.mjs +8 -0
- package/dist/esm2022/lib/atlas.service.mjs +329 -0
- package/dist/esm2022/lib/atlas.ui.mjs +36 -0
- package/dist/esm2022/lib/components/attempt-flow.component.mjs +180 -0
- package/dist/esm2022/lib/components/flow-controller.mjs +88 -0
- package/dist/esm2022/lib/components/organization-profile.component.mjs +56 -0
- package/dist/esm2022/lib/components/organization-switcher.component.mjs +63 -0
- package/dist/esm2022/lib/components/sign-in.component.mjs +59 -0
- package/dist/esm2022/lib/components/sign-up.component.mjs +54 -0
- package/dist/esm2022/lib/components/user-button.component.mjs +94 -0
- package/dist/esm2022/lib/components/user-profile.component.mjs +81 -0
- package/dist/esm2022/lib/directives/atlas-root.directive.mjs +42 -0
- package/dist/esm2022/lib/directives/loaded.directive.mjs +23 -0
- package/dist/esm2022/lib/directives/loading.directive.mjs +23 -0
- package/dist/esm2022/lib/directives/protect.directive.mjs +82 -0
- package/dist/esm2022/lib/directives/signed-in.directive.mjs +29 -0
- package/dist/esm2022/lib/directives/signed-out.directive.mjs +29 -0
- package/dist/esm2022/lib/directives/toggle.directive.mjs +42 -0
- package/dist/esm2022/lib/fapi.mjs +9 -0
- package/dist/esm2022/lib/guards/atlas.guard.mjs +54 -0
- package/dist/esm2022/lib/i18n.mjs +78 -0
- package/dist/esm2022/lib/protect.mjs +9 -0
- package/dist/esm2022/lib/provide-atlas.mjs +85 -0
- package/dist/esm2022/lib/types.mjs +6 -0
- package/dist/esm2022/public-api.mjs +35 -0
- package/dist/fesm2022/atlasauth-angular.mjs +1557 -0
- package/dist/fesm2022/atlasauth-angular.mjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/appearance.d.ts +85 -0
- package/dist/lib/atlas.config.d.ts +31 -0
- package/dist/lib/atlas.service.d.ts +127 -0
- package/dist/lib/atlas.ui.d.ts +22 -0
- package/dist/lib/components/attempt-flow.component.d.ts +48 -0
- package/dist/lib/components/flow-controller.d.ts +34 -0
- package/dist/lib/components/organization-profile.component.d.ts +16 -0
- package/dist/lib/components/organization-switcher.component.d.ts +15 -0
- package/dist/lib/components/sign-in.component.d.ts +21 -0
- package/dist/lib/components/sign-up.component.d.ts +21 -0
- package/dist/lib/components/user-button.component.d.ts +19 -0
- package/dist/lib/components/user-profile.component.d.ts +15 -0
- package/dist/lib/directives/atlas-root.directive.d.ts +26 -0
- package/dist/lib/directives/loaded.directive.d.ts +13 -0
- package/dist/lib/directives/loading.directive.d.ts +12 -0
- package/dist/lib/directives/protect.directive.d.ts +41 -0
- package/dist/lib/directives/signed-in.directive.d.ts +17 -0
- package/dist/lib/directives/signed-out.directive.d.ts +17 -0
- package/dist/lib/directives/toggle.directive.d.ts +25 -0
- package/dist/lib/fapi.d.ts +8 -0
- package/dist/lib/guards/atlas.guard.d.ts +43 -0
- package/dist/lib/i18n.d.ts +23 -0
- package/dist/lib/protect.d.ts +8 -0
- package/dist/lib/provide-atlas.d.ts +46 -0
- package/dist/lib/types.d.ts +48 -0
- package/dist/public-api.d.ts +28 -0
- package/package.json +58 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { Injectable, PLATFORM_ID, computed, inject, } from '@angular/core';
|
|
2
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
3
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { BehaviorSubject, combineLatest } from 'rxjs';
|
|
5
|
+
import { distinctUntilChanged, map } from 'rxjs/operators';
|
|
6
|
+
import { FapiClient, TokenCache, getProviderToken as fetchProviderToken, msUntilRefresh, readExpiry, readRedirectResult, stripRedirectParams, } from '@atlasauth/js';
|
|
7
|
+
import { evaluate } from '@atlasauth/authz';
|
|
8
|
+
import { ATLAS_OPTIONS } from './atlas.config';
|
|
9
|
+
import { cssVariables, resolveTokens } from './appearance';
|
|
10
|
+
import { EN_US, withFallback } from './i18n';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
/**
|
|
13
|
+
* `AtlasService` — the Angular peer of React's `<AtlasProvider>` + hooks.
|
|
14
|
+
*
|
|
15
|
+
* It holds exactly one thing that matters in memory: the short-lived JWT, in a
|
|
16
|
+
* {@link TokenCache}. Not localStorage, not a cookie this code writes — the
|
|
17
|
+
* refresh token is HttpOnly so browser script never touches it, and the JWT
|
|
18
|
+
* lives only as long as the tab. Anything persisted would survive the tab and
|
|
19
|
+
* become the first thing an XSS reads.
|
|
20
|
+
*
|
|
21
|
+
* Reactive auth state is exposed two ways so callers can pick their idiom:
|
|
22
|
+
* - RxJS observables (`user$`, `session$`, `isSignedIn$`, …) — the primary API,
|
|
23
|
+
* the analogue of the React hooks' return values.
|
|
24
|
+
* - Angular signals (`user`, `session`, `isSignedIn`, …) — the same values as
|
|
25
|
+
* `Signal<T>`, for templates and `computed()`.
|
|
26
|
+
*
|
|
27
|
+
* The imperative methods (`signOut`, `getToken`, `getProviderToken`,
|
|
28
|
+
* `setActiveOrganization`, `reload`) mirror the actions the hooks return.
|
|
29
|
+
*/
|
|
30
|
+
export class AtlasService {
|
|
31
|
+
options = inject(ATLAS_OPTIONS);
|
|
32
|
+
platformId = inject(PLATFORM_ID);
|
|
33
|
+
isBrowser = isPlatformBrowser(this.platformId);
|
|
34
|
+
baseUrl;
|
|
35
|
+
publishableKey;
|
|
36
|
+
doFetch;
|
|
37
|
+
cache = new TokenCache();
|
|
38
|
+
fapiClient;
|
|
39
|
+
refreshTimer = null;
|
|
40
|
+
catalog;
|
|
41
|
+
/**
|
|
42
|
+
* A sign-in attempt handed back by an OAuth redirect that still needs a second
|
|
43
|
+
* factor (no session was issued). Null in the ordinary case; the `<atlas-sign-in>`
|
|
44
|
+
* flow seeds itself from this so the user resumes at the 2FA step. Captured
|
|
45
|
+
* once, synchronously, at construction — before any flow component reads it.
|
|
46
|
+
*/
|
|
47
|
+
pendingAttempt;
|
|
48
|
+
// --- Reactive state (source of truth) ---------------------------------------
|
|
49
|
+
_status = new BehaviorSubject('loading');
|
|
50
|
+
_user = new BehaviorSubject(null);
|
|
51
|
+
_session = new BehaviorSubject(null);
|
|
52
|
+
_claims = new BehaviorSubject(null);
|
|
53
|
+
_memberships = new BehaviorSubject([]);
|
|
54
|
+
/** The three-state auth lifecycle: `loading` → `signed_in` | `signed_out`. */
|
|
55
|
+
status$ = this._status.asObservable();
|
|
56
|
+
user$ = this._user.asObservable();
|
|
57
|
+
session$ = this._session.asObservable();
|
|
58
|
+
claims$ = this._claims.asObservable();
|
|
59
|
+
memberships$ = this._memberships.asObservable();
|
|
60
|
+
/**
|
|
61
|
+
* True once the SDK has finished its first boot. Distinguishing "still loading"
|
|
62
|
+
* from "signed out" is what lets a template avoid the flash of a sign-in form
|
|
63
|
+
* on every page load.
|
|
64
|
+
*/
|
|
65
|
+
isLoaded$ = this.status$.pipe(map((s) => s !== 'loading'), distinctUntilChanged());
|
|
66
|
+
isSignedIn$ = this.status$.pipe(map((s) => s === 'signed_in'), distinctUntilChanged());
|
|
67
|
+
/** The active organization membership, derived from the token's `org_id` claim. */
|
|
68
|
+
organization$ = combineLatest([
|
|
69
|
+
this._memberships,
|
|
70
|
+
this._claims,
|
|
71
|
+
]).pipe(map(([memberships, claims]) => memberships.find((m) => m.organization.id === claims?.org_id) ?? null));
|
|
72
|
+
// --- Signal mirror ----------------------------------------------------------
|
|
73
|
+
status = toSignal(this.status$, { initialValue: 'loading' });
|
|
74
|
+
user = toSignal(this.user$, { initialValue: null });
|
|
75
|
+
session = toSignal(this.session$, { initialValue: null });
|
|
76
|
+
claims = toSignal(this.claims$, { initialValue: null });
|
|
77
|
+
memberships = toSignal(this.memberships$, {
|
|
78
|
+
initialValue: [],
|
|
79
|
+
});
|
|
80
|
+
isLoaded = computed(() => this.status() !== 'loading');
|
|
81
|
+
isSignedIn = computed(() => this.status() === 'signed_in');
|
|
82
|
+
organization = computed(() => {
|
|
83
|
+
const orgId = this.claims()?.org_id;
|
|
84
|
+
return this.memberships().find((m) => m.organization.id === orgId) ?? null;
|
|
85
|
+
});
|
|
86
|
+
constructor() {
|
|
87
|
+
const options = this.options;
|
|
88
|
+
this.publishableKey = options.publishableKey;
|
|
89
|
+
this.baseUrl = options.frontendApi ?? '';
|
|
90
|
+
this.doFetch = options.fetchImpl ?? ((...args) => fetch(...args));
|
|
91
|
+
this.catalog = options.localization ? withFallback(options.localization) : EN_US;
|
|
92
|
+
this.fapiClient = new FapiClient({
|
|
93
|
+
publishableKey: this.publishableKey,
|
|
94
|
+
baseUrl: this.baseUrl,
|
|
95
|
+
fetchImpl: this.doFetch,
|
|
96
|
+
});
|
|
97
|
+
// Captured synchronously (not in an async init) so it is available before any
|
|
98
|
+
// flow component reads it: a needs_second_factor redirect carries a status but
|
|
99
|
+
// no ticket, and that is what the 2FA resume seeds from.
|
|
100
|
+
this.pendingAttempt = this.isBrowser ? this.readPendingAttempt() : null;
|
|
101
|
+
// Boot once, browser only. On the server there is no cookie jar to read a
|
|
102
|
+
// session from, so we leave the state at `loading` and let hydration boot it.
|
|
103
|
+
if (this.isBrowser) {
|
|
104
|
+
void this.boot();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
ngOnDestroy() {
|
|
108
|
+
this.clearRefreshTimer();
|
|
109
|
+
this._status.complete();
|
|
110
|
+
this._user.complete();
|
|
111
|
+
this._session.complete();
|
|
112
|
+
this._claims.complete();
|
|
113
|
+
this._memberships.complete();
|
|
114
|
+
}
|
|
115
|
+
// --- Configuration accessors ------------------------------------------------
|
|
116
|
+
get appearance() {
|
|
117
|
+
return this.options.appearance;
|
|
118
|
+
}
|
|
119
|
+
get localization() {
|
|
120
|
+
return this.catalog;
|
|
121
|
+
}
|
|
122
|
+
get frontendApi() {
|
|
123
|
+
return this.baseUrl;
|
|
124
|
+
}
|
|
125
|
+
/** Tokens as CSS custom properties, for a host element to inherit. */
|
|
126
|
+
appearanceVariables() {
|
|
127
|
+
return cssVariables(resolveTokens(this.options.appearance));
|
|
128
|
+
}
|
|
129
|
+
/** A fresh {@link FapiClient} for driving a sign-in/sign-up flow. */
|
|
130
|
+
createFapiClient() {
|
|
131
|
+
return new FapiClient({ publishableKey: this.publishableKey, baseUrl: this.baseUrl });
|
|
132
|
+
}
|
|
133
|
+
// --- Imperative API (mirrors the React hooks' actions) ----------------------
|
|
134
|
+
/**
|
|
135
|
+
* The current session's JWT, always fresh: if the cached token is within 5s of
|
|
136
|
+
* expiry it is refreshed first rather than handed over. Null when signed out.
|
|
137
|
+
*/
|
|
138
|
+
async getToken() {
|
|
139
|
+
const usable = this.cache.get(5_000);
|
|
140
|
+
if (usable)
|
|
141
|
+
return usable.jwt;
|
|
142
|
+
await this.refresh();
|
|
143
|
+
return this.cache.get(5_000)?.jwt ?? null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The signed-in user's OWN live access token at a connected provider (Google,
|
|
147
|
+
* GitHub, …), so the app can call that provider's API from the browser. Null
|
|
148
|
+
* when there is no usable token — no linked account, or the provider granted /
|
|
149
|
+
* kept none. The server refreshes a stale token on read; the refresh token is
|
|
150
|
+
* never exposed.
|
|
151
|
+
*/
|
|
152
|
+
getProviderToken(provider) {
|
|
153
|
+
return fetchProviderToken(this.fapiClient, provider);
|
|
154
|
+
}
|
|
155
|
+
/** Imperative `has()` — the same evaluation `*atlasProtect` renders on. */
|
|
156
|
+
has(condition) {
|
|
157
|
+
return evaluate(this._claims.value, condition).allowed;
|
|
158
|
+
}
|
|
159
|
+
/** Revoke the current session server-side and drop all local auth state. */
|
|
160
|
+
async signOut() {
|
|
161
|
+
const current = this.cache.peek();
|
|
162
|
+
if (current) {
|
|
163
|
+
await this.call(`/v1/client/sessions/${current.sessionId}/revoke`, {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
}).catch(() => undefined);
|
|
166
|
+
}
|
|
167
|
+
this.clearRefreshTimer();
|
|
168
|
+
this.cache.clear();
|
|
169
|
+
this._status.next('signed_out');
|
|
170
|
+
this._user.next(null);
|
|
171
|
+
this._session.next(null);
|
|
172
|
+
this._claims.next(null);
|
|
173
|
+
this._memberships.next([]);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Switch the active organization (or `null` for the personal account). The
|
|
177
|
+
* new token carries the new org claims, so the app's permission checks update
|
|
178
|
+
* without a re-login.
|
|
179
|
+
*/
|
|
180
|
+
async setActiveOrganization(organizationId) {
|
|
181
|
+
const current = this.cache.peek();
|
|
182
|
+
if (!current)
|
|
183
|
+
return;
|
|
184
|
+
const response = await this.call(`/v1/client/sessions/${current.sessionId}/touch`, {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
body: JSON.stringify({ active_organization_id: organizationId }),
|
|
187
|
+
});
|
|
188
|
+
if (!response.ok)
|
|
189
|
+
return;
|
|
190
|
+
const body = (await response.json());
|
|
191
|
+
this.applyToken(body.jwt, current.sessionId);
|
|
192
|
+
await this.reload();
|
|
193
|
+
}
|
|
194
|
+
/** Re-read `/v1/client`: refresh user, session, memberships and status. */
|
|
195
|
+
async reload() {
|
|
196
|
+
try {
|
|
197
|
+
const response = await this.call('/v1/client');
|
|
198
|
+
if (!response.ok)
|
|
199
|
+
throw new Error('boot failed');
|
|
200
|
+
const body = (await response.json());
|
|
201
|
+
if (!body.session || !body.user) {
|
|
202
|
+
this.clearRefreshTimer();
|
|
203
|
+
this.cache.clear();
|
|
204
|
+
this._status.next('signed_out');
|
|
205
|
+
this._user.next(null);
|
|
206
|
+
this._session.next(null);
|
|
207
|
+
this._claims.next(null);
|
|
208
|
+
this._memberships.next([]);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
this._user.next(body.user);
|
|
212
|
+
this._session.next(body.session);
|
|
213
|
+
this._memberships.next(body.organization_memberships ?? []);
|
|
214
|
+
if (body.jwt)
|
|
215
|
+
this.applyToken(body.jwt, body.session.id);
|
|
216
|
+
this._status.next('signed_in');
|
|
217
|
+
this.scheduleRefresh();
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// A failed boot is NOT signed-out. Rendering a sign-in form because the
|
|
221
|
+
// network hiccuped throws away a perfectly good session and forces a
|
|
222
|
+
// needless re-authentication. Only promote loading → signed_out.
|
|
223
|
+
if (this._status.value === 'loading')
|
|
224
|
+
this._status.next('signed_out');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// --- Internals --------------------------------------------------------------
|
|
228
|
+
/**
|
|
229
|
+
* §6.3 step 3: complete a redirect-based sign-in, then boot. An OAuth or
|
|
230
|
+
* hosted-page flow lands back with a one-time ticket in the URL; exchange it
|
|
231
|
+
* for cookies, scrub the URL so a reload cannot replay it, THEN read the
|
|
232
|
+
* session. A redirect carrying only a status (a second factor is still owed)
|
|
233
|
+
* has no ticket, so nothing is exchanged and the app boots signed-out.
|
|
234
|
+
*/
|
|
235
|
+
async boot() {
|
|
236
|
+
const result = readRedirectResult(window.location.search);
|
|
237
|
+
if (result?.ticket) {
|
|
238
|
+
await this.call('/v1/client/tickets/exchange', {
|
|
239
|
+
method: 'POST',
|
|
240
|
+
body: JSON.stringify({ attempt_id: result.attemptId, ticket: result.ticket }),
|
|
241
|
+
}).catch(() => undefined);
|
|
242
|
+
}
|
|
243
|
+
if (result) {
|
|
244
|
+
window.history.replaceState({}, document.title, stripRedirectParams(window.location.href));
|
|
245
|
+
}
|
|
246
|
+
await this.reload();
|
|
247
|
+
}
|
|
248
|
+
readPendingAttempt() {
|
|
249
|
+
const result = readRedirectResult(window.location.search);
|
|
250
|
+
return result?.status && !result.ticket
|
|
251
|
+
? { id: result.attemptId, status: result.status }
|
|
252
|
+
: null;
|
|
253
|
+
}
|
|
254
|
+
call(path, init) {
|
|
255
|
+
return this.doFetch(`${this.baseUrl}${path}`, {
|
|
256
|
+
...init,
|
|
257
|
+
// Cookies carry the session; a request without this is indistinguishable
|
|
258
|
+
// from being signed out.
|
|
259
|
+
credentials: 'include',
|
|
260
|
+
headers: {
|
|
261
|
+
'x-publishable-key': this.publishableKey,
|
|
262
|
+
...(init?.body ? { 'content-type': 'application/json' } : {}),
|
|
263
|
+
...init?.headers,
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
applyToken(jwt, sessionId) {
|
|
268
|
+
const expiresAt = readExpiry(jwt);
|
|
269
|
+
if (!expiresAt)
|
|
270
|
+
return;
|
|
271
|
+
this.cache.set({ jwt, expiresAt, sessionId });
|
|
272
|
+
this._claims.next(decodeClaims(jwt));
|
|
273
|
+
}
|
|
274
|
+
async refresh() {
|
|
275
|
+
const current = this.cache.peek();
|
|
276
|
+
if (!current)
|
|
277
|
+
return;
|
|
278
|
+
try {
|
|
279
|
+
const response = await this.call(`/v1/client/sessions/${current.sessionId}/tokens`, {
|
|
280
|
+
method: 'POST',
|
|
281
|
+
});
|
|
282
|
+
if (!response.ok)
|
|
283
|
+
throw new Error('refresh failed');
|
|
284
|
+
const body = (await response.json());
|
|
285
|
+
this.applyToken(body.jwt, body.session_id);
|
|
286
|
+
this.scheduleRefresh();
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// The session may genuinely be gone. Re-boot rather than guess.
|
|
290
|
+
await this.reload();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** §7.4: proactive, jittered refresh scheduled from the token's own expiry. */
|
|
294
|
+
scheduleRefresh() {
|
|
295
|
+
this.clearRefreshTimer();
|
|
296
|
+
if (this._status.value !== 'signed_in')
|
|
297
|
+
return;
|
|
298
|
+
const token = this.cache.peek();
|
|
299
|
+
if (!token)
|
|
300
|
+
return;
|
|
301
|
+
const delay = msUntilRefresh({ token, now: Date.now() });
|
|
302
|
+
this.refreshTimer = setTimeout(() => void this.refresh(), delay);
|
|
303
|
+
}
|
|
304
|
+
clearRefreshTimer() {
|
|
305
|
+
if (this.refreshTimer) {
|
|
306
|
+
clearTimeout(this.refreshTimer);
|
|
307
|
+
this.refreshTimer = null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
311
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasService, providedIn: 'root' });
|
|
312
|
+
}
|
|
313
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasService, decorators: [{
|
|
314
|
+
type: Injectable,
|
|
315
|
+
args: [{ providedIn: 'root' }]
|
|
316
|
+
}], ctorParameters: () => [] });
|
|
317
|
+
/** Decode a JWT payload without verifying it — a scheduling/UI hint only. */
|
|
318
|
+
function decodeClaims(jwt) {
|
|
319
|
+
const parts = jwt.split('.');
|
|
320
|
+
if (parts.length !== 3)
|
|
321
|
+
return null;
|
|
322
|
+
try {
|
|
323
|
+
return JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRsYXMuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvYXRsYXMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsVUFBVSxFQUVWLFdBQVcsRUFFWCxRQUFRLEVBQ1IsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsZUFBZSxFQUFjLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0QsT0FBTyxFQUNMLFVBQVUsRUFDVixVQUFVLEVBQ1YsZ0JBQWdCLElBQUksa0JBQWtCLEVBQ3RDLGNBQWMsRUFDZCxVQUFVLEVBQ1Ysa0JBQWtCLEVBQ2xCLG1CQUFtQixHQUVwQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUF5QixNQUFNLGtCQUFrQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBbUIsTUFBTSxjQUFjLENBQUM7QUFDNUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQWdCLE1BQU0sUUFBUSxDQUFDOztBQVMzRDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFFSCxNQUFNLE9BQU8sWUFBWTtJQUNOLE9BQU8sR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDaEMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNqQyxTQUFTLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRS9DLE9BQU8sQ0FB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QUFDO3dHQTlVVSxZQUFZOzRHQUFaLFlBQVksY0FEQyxNQUFNOzs0RkFDbkIsWUFBWTtrQkFEeEIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7O0FBa1ZsQyw2RUFBNkU7QUFDN0UsU0FBUyxZQUFZLENBQUMsR0FBVztJQUMvQixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDcEMsSUFBSSxDQUFDO1FBQ0gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUNmLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFFLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQ3JDLENBQUM7SUFDckIsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBJbmplY3RhYmxlLFxuICBPbkRlc3Ryb3ksXG4gIFBMQVRGT1JNX0lELFxuICBTaWduYWwsXG4gIGNvbXB1dGVkLFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgdG9TaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIGNvbWJpbmVMYXRlc3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1xuICBGYXBpQ2xpZW50LFxuICBUb2tlbkNhY2hlLFxuICBnZXRQcm92aWRlclRva2VuIGFzIGZldGNoUHJvdmlkZXJUb2tlbixcbiAgbXNVbnRpbFJlZnJlc2gsXG4gIHJlYWRFeHBpcnksXG4gIHJlYWRSZWRpcmVjdFJlc3VsdCxcbiAgc3RyaXBSZWRpcmVjdFBhcmFtcyxcbiAgdHlwZSBQcm92aWRlclRva2VuLFxufSBmcm9tICdAYXRsYXNhdXRoL2pzJztcbmltcG9ydCB7IGV2YWx1YXRlLCB0eXBlIFByb3RlY3RDb25kaXRpb24gfSBmcm9tICdAYXRsYXNhdXRoL2F1dGh6JztcbmltcG9ydCB7IEFUTEFTX09QVElPTlMgfSBmcm9tICcuL2F0bGFzLmNvbmZpZyc7XG5pbXBvcnQgeyBjc3NWYXJpYWJsZXMsIHJlc29sdmVUb2tlbnMsIHR5cGUgQXBwZWFyYW5jZSB9IGZyb20gJy4vYXBwZWFyYW5jZSc7XG5pbXBvcnQgeyBFTl9VUywgd2l0aEZhbGxiYWNrLCB0eXBlIENhdGFsb2cgfSBmcm9tICcuL2kxOG4nO1xuaW1wb3J0IHR5cGUge1xuICBBdGxhc09yZ2FuaXphdGlvbk1lbWJlcnNoaXAsXG4gIEF0bGFzU2Vzc2lvbixcbiAgQXRsYXNVc2VyLFxuICBBdXRoU3RhdHVzLFxuICBTZXNzaW9uQ2xhaW1zLFxufSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBgQXRsYXNTZXJ2aWNlYCDigJQgdGhlIEFuZ3VsYXIgcGVlciBvZiBSZWFjdCdzIGA8QXRsYXNQcm92aWRlcj5gICsgaG9va3MuXG4gKlxuICogSXQgaG9sZHMgZXhhY3RseSBvbmUgdGhpbmcgdGhhdCBtYXR0ZXJzIGluIG1lbW9yeTogdGhlIHNob3J0LWxpdmVkIEpXVCwgaW4gYVxuICoge0BsaW5rIFRva2VuQ2FjaGV9LiBOb3QgbG9jYWxTdG9yYWdlLCBub3QgYSBjb29raWUgdGhpcyBjb2RlIHdyaXRlcyDigJQgdGhlXG4gKiByZWZyZXNoIHRva2VuIGlzIEh0dHBPbmx5IHNvIGJyb3dzZXIgc2NyaXB0IG5ldmVyIHRvdWNoZXMgaXQsIGFuZCB0aGUgSldUXG4gKiBsaXZlcyBvbmx5IGFzIGxvbmcgYXMgdGhlIHRhYi4gQW55dGhpbmcgcGVyc2lzdGVkIHdvdWxkIHN1cnZpdmUgdGhlIHRhYiBhbmRcbiAqIGJlY29tZSB0aGUgZmlyc3QgdGhpbmcgYW4gWFNTIHJlYWRzLlxuICpcbiAqIFJlYWN0aXZlIGF1dGggc3RhdGUgaXMgZXhwb3NlZCB0d28gd2F5cyBzbyBjYWxsZXJzIGNhbiBwaWNrIHRoZWlyIGlkaW9tOlxuICogIC0gUnhKUyBvYnNlcnZhYmxlcyAoYHVzZXIkYCwgYHNlc3Npb24kYCwgYGlzU2lnbmVkSW4kYCwg4oCmKSDigJQgdGhlIHByaW1hcnkgQVBJLFxuICogICAgdGhlIGFuYWxvZ3VlIG9mIHRoZSBSZWFjdCBob29rcycgcmV0dXJuIHZhbHVlcy5cbiAqICAtIEFuZ3VsYXIgc2lnbmFscyAoYHVzZXJgLCBgc2Vzc2lvbmAsIGBpc1NpZ25lZEluYCwg4oCmKSDigJQgdGhlIHNhbWUgdmFsdWVzIGFzXG4gKiAgICBgU2lnbmFsPFQ+YCwgZm9yIHRlbXBsYXRlcyBhbmQgYGNvbXB1dGVkKClgLlxuICpcbiAqIFRoZSBpbXBlcmF0aXZlIG1ldGhvZHMgKGBzaWduT3V0YCwgYGdldFRva2VuYCwgYGdldFByb3ZpZGVyVG9rZW5gLFxuICogYHNldEFjdGl2ZU9yZ2FuaXphdGlvbmAsIGByZWxvYWRgKSBtaXJyb3IgdGhlIGFjdGlvbnMgdGhlIGhvb2tzIHJldHVybi5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBBdGxhc1NlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnMgPSBpbmplY3QoQVRMQVNfT1BUSU9OUyk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGxhdGZvcm1JZCA9IGluamVjdChQTEFURk9STV9JRCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGJhc2VVcmw6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBwdWJsaXNoYWJsZUtleTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGRvRmV0Y2g6IHR5cGVvZiBmZXRjaDtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNhY2hlID0gbmV3IFRva2VuQ2FjaGUoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBmYXBpQ2xpZW50OiBGYXBpQ2xpZW50O1xuICBwcml2YXRlIHJlZnJlc2hUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNhdGFsb2c6IENhdGFsb2c7XG5cbiAgLyoqXG4gICAqIEEgc2lnbi1pbiBhdHRlbXB0IGhhbmRlZCBiYWNrIGJ5IGFuIE9BdXRoIHJlZGlyZWN0IHRoYXQgc3RpbGwgbmVlZHMgYSBzZWNvbmRcbiAgICogZmFjdG9yIChubyBzZXNzaW9uIHdhcyBpc3N1ZWQpLiBOdWxsIGluIHRoZSBvcmRpbmFyeSBjYXNlOyB0aGUgYDxhdGxhcy1zaWduLWluPmBcbiAgICogZmxvdyBzZWVkcyBpdHNlbGYgZnJvbSB0aGlzIHNvIHRoZSB1c2VyIHJlc3VtZXMgYXQgdGhlIDJGQSBzdGVwLiBDYXB0dXJlZFxuICAgKiBvbmNlLCBzeW5jaHJvbm91c2x5LCBhdCBjb25zdHJ1Y3Rpb24g4oCUIGJlZm9yZSBhbnkgZmxvdyBjb21wb25lbnQgcmVhZHMgaXQuXG4gICAqL1xuICByZWFkb25seSBwZW5kaW5nQXR0ZW1wdDogeyBpZDogc3RyaW5nOyBzdGF0dXM6IHN0cmluZyB9IHwgbnVsbDtcblxuICAvLyAtLS0gUmVhY3RpdmUgc3RhdGUgKHNvdXJjZSBvZiB0cnV0aCkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgcHJpdmF0ZSByZWFkb25seSBfc3RhdHVzID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdXRoU3RhdHVzPignbG9hZGluZycpO1xuICBwcml2YXRlIHJlYWRvbmx5IF91c2VyID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdGxhc1VzZXIgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfc2Vzc2lvbiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QXRsYXNTZXNzaW9uIHwgbnVsbD4obnVsbCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2NsYWltcyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8U2Vzc2lvbkNsYWltcyB8IG51bGw+KG51bGwpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9tZW1iZXJzaGlwcyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QXRsYXNPcmdhbml6YXRpb25NZW1iZXJzaGlwW10+KFtdKTtcblxuICAvKiogVGhlIHRocmVlLXN0YXRlIGF1dGggbGlmZWN5Y2xlOiBgbG9hZGluZ2Ag4oaSIGBzaWduZWRfaW5gIHwgYHNpZ25lZF9vdXRgLiAqL1xuICByZWFkb25seSBzdGF0dXMkOiBPYnNlcnZhYmxlPEF1dGhTdGF0dXM+ID0gdGhpcy5fc3RhdHVzLmFzT2JzZXJ2YWJsZSgpO1xuICByZWFkb25seSB1c2VyJDogT2JzZXJ2YWJsZTxBdGxhc1VzZXIgfCBudWxsPiA9IHRoaXMuX3VzZXIuYXNPYnNlcnZhYmxlKCk7XG4gIHJlYWRvbmx5IHNlc3Npb24kOiBPYnNlcnZhYmxlPEF0bGFzU2Vzc2lvbiB8IG51bGw+ID0gdGhpcy5fc2Vzc2lvbi5hc09ic2VydmFibGUoKTtcbiAgcmVhZG9ubHkgY2xhaW1zJDogT2JzZXJ2YWJsZTxTZXNzaW9uQ2xhaW1zIHwgbnVsbD4gPSB0aGlzLl9jbGFpbXMuYXNPYnNlcnZhYmxlKCk7XG4gIHJlYWRvbmx5IG1lbWJlcnNoaXBzJDogT2JzZXJ2YWJsZTxBdGxhc09yZ2FuaXphdGlvbk1lbWJlcnNoaXBbXT4gPVxuICAgIHRoaXMuX21lbWJlcnNoaXBzLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIC8qKlxuICAgKiBUcnVlIG9uY2UgdGhlIFNESyBoYXMgZmluaXNoZWQgaXRzIGZpcnN0IGJvb3QuIERpc3Rpbmd1aXNoaW5nIFwic3RpbGwgbG9hZGluZ1wiXG4gICAqIGZyb20gXCJzaWduZWQgb3V0XCIgaXMgd2hhdCBsZXRzIGEgdGVtcGxhdGUgYXZvaWQgdGhlIGZsYXNoIG9mIGEgc2lnbi1pbiBmb3JtXG4gICAqIG9uIGV2ZXJ5IHBhZ2UgbG9hZC5cbiAgICovXG4gIHJlYWRvbmx5IGlzTG9hZGVkJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IHRoaXMuc3RhdHVzJC5waXBlKFxuICAgIG1hcCgocykgPT4gcyAhPT0gJ2xvYWRpbmcnKSxcbiAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxuICApO1xuXG4gIHJlYWRvbmx5IGlzU2lnbmVkSW4kOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5zdGF0dXMkLnBpcGUoXG4gICAgbWFwKChzKSA9PiBzID09PSAnc2lnbmVkX2luJyksXG4gICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcbiAgKTtcblxuICAvKiogVGhlIGFjdGl2ZSBvcmdhbml6YXRpb24gbWVtYmVyc2hpcCwgZGVyaXZlZCBmcm9tIHRoZSB0b2tlbidzIGBvcmdfaWRgIGNsYWltLiAqL1xuICByZWFkb25seSBvcmdhbml6YXRpb24kOiBPYnNlcnZhYmxlPEF0bGFzT3JnYW5pemF0aW9uTWVtYmVyc2hpcCB8IG51bGw+ID0gY29tYmluZUxhdGVzdChbXG4gICAgdGhpcy5fbWVtYmVyc2hpcHMsXG4gICAgdGhpcy5fY2xhaW1zLFxuICBdKS5waXBlKFxuICAgIG1hcChcbiAgICAgIChbbWVtYmVyc2hpcHMsIGNsYWltc10pID0+XG4gICAgICAgIG1lbWJlcnNoaXBzLmZpbmQoKG0pID0+IG0ub3JnYW5pemF0aW9uLmlkID09PSBjbGFpbXM/Lm9yZ19pZCkgPz8gbnVsbCxcbiAgICApLFxuICApO1xuXG4gIC8vIC0tLSBTaWduYWwgbWlycm9yIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICByZWFkb25seSBzdGF0dXM6IFNpZ25hbDxBdXRoU3RhdHVzPiA9IHRvU2lnbmFsKHRoaXMuc3RhdHVzJCwgeyBpbml0aWFsVmFsdWU6ICdsb2FkaW5nJyB9KTtcbiAgcmVhZG9ubHkgdXNlcjogU2lnbmFsPEF0bGFzVXNlciB8IG51bGw+ID0gdG9TaWduYWwodGhpcy51c2VyJCwgeyBpbml0aWFsVmFsdWU6IG51bGwgfSk7XG4gIHJlYWRvbmx5IHNlc3Npb246IFNpZ25hbDxBdGxhc1Nlc3Npb24gfCBudWxsPiA9IHRvU2lnbmFsKHRoaXMuc2Vzc2lvbiQsIHsgaW5pdGlhbFZhbHVlOiBudWxsIH0pO1xuICByZWFkb25seSBjbGFpbXM6IFNpZ25hbDxTZXNzaW9uQ2xhaW1zIHwgbnVsbD4gPSB0b1NpZ25hbCh0aGlzLmNsYWltcyQsIHsgaW5pdGlhbFZhbHVlOiBudWxsIH0pO1xuICByZWFkb25seSBtZW1iZXJzaGlwczogU2lnbmFsPEF0bGFzT3JnYW5pemF0aW9uTWVtYmVyc2hpcFtdPiA9IHRvU2lnbmFsKHRoaXMubWVtYmVyc2hpcHMkLCB7XG4gICAgaW5pdGlhbFZhbHVlOiBbXSBhcyBBdGxhc09yZ2FuaXphdGlvbk1lbWJlcnNoaXBbXSxcbiAgfSk7XG4gIHJlYWRvbmx5IGlzTG9hZGVkOiBTaWduYWw8Ym9vbGVhbj4gPSBjb21wdXRlZCgoKSA9PiB0aGlzLnN0YXR1cygpICE9PSAnbG9hZGluZycpO1xuICByZWFkb25seSBpc1NpZ25lZEluOiBTaWduYWw8Ym9vbGVhbj4gPSBjb21wdXRlZCgoKSA9PiB0aGlzLnN0YXR1cygpID09PSAnc2lnbmVkX2luJyk7XG4gIHJlYWRvbmx5IG9yZ2FuaXphdGlvbjogU2lnbmFsPEF0bGFzT3JnYW5pemF0aW9uTWVtYmVyc2hpcCB8IG51bGw+ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IG9yZ0lkID0gdGhpcy5jbGFpbXMoKT8ub3JnX2lkO1xuICAgIHJldHVybiB0aGlzLm1lbWJlcnNoaXBzKCkuZmluZCgobSkgPT4gbS5vcmdhbml6YXRpb24uaWQgPT09IG9yZ0lkKSA/PyBudWxsO1xuICB9KTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgIHRoaXMucHVibGlzaGFibGVLZXkgPSBvcHRpb25zLnB1Ymxpc2hhYmxlS2V5O1xuICAgIHRoaXMuYmFzZVVybCA9IG9wdGlvbnMuZnJvbnRlbmRBcGkgPz8gJyc7XG4gICAgdGhpcy5kb0ZldGNoID0gb3B0aW9ucy5mZXRjaEltcGwgPz8gKCguLi5hcmdzOiBQYXJhbWV0ZXJzPHR5cGVvZiBmZXRjaD4pID0+IGZldGNoKC4uLmFyZ3MpKTtcblxuICAgIHRoaXMuY2F0YWxvZyA9IG9wdGlvbnMubG9jYWxpemF0aW9uID8gd2l0aEZhbGxiYWNrKG9wdGlvbnMubG9jYWxpemF0aW9uKSA6IEVOX1VTO1xuXG4gICAgdGhpcy5mYXBpQ2xpZW50ID0gbmV3IEZhcGlDbGllbnQoe1xuICAgICAgcHVibGlzaGFibGVLZXk6IHRoaXMucHVibGlzaGFibGVLZXksXG4gICAgICBiYXNlVXJsOiB0aGlzLmJhc2VVcmwsXG4gICAgICBmZXRjaEltcGw6IHRoaXMuZG9GZXRjaCxcbiAgICB9KTtcblxuICAgIC8vIENhcHR1cmVkIHN5bmNocm9ub3VzbHkgKG5vdCBpbiBhbiBhc3luYyBpbml0KSBzbyBpdCBpcyBhdmFpbGFibGUgYmVmb3JlIGFueVxuICAgIC8vIGZsb3cgY29tcG9uZW50IHJlYWRzIGl0OiBhIG5lZWRzX3NlY29uZF9mYWN0b3IgcmVkaXJlY3QgY2FycmllcyBhIHN0YXR1cyBidXRcbiAgICAvLyBubyB0aWNrZXQsIGFuZCB0aGF0IGlzIHdoYXQgdGhlIDJGQSByZXN1bWUgc2VlZHMgZnJvbS5cbiAgICB0aGlzLnBlbmRpbmdBdHRlbXB0ID0gdGhpcy5pc0Jyb3dzZXIgPyB0aGlzLnJlYWRQZW5kaW5nQXR0ZW1wdCgpIDogbnVsbDtcblxuICAgIC8vIEJvb3Qgb25jZSwgYnJvd3NlciBvbmx5LiBPbiB0aGUgc2VydmVyIHRoZXJlIGlzIG5vIGNvb2tpZSBqYXIgdG8gcmVhZCBhXG4gICAgLy8gc2Vzc2lvbiBmcm9tLCBzbyB3ZSBsZWF2ZSB0aGUgc3RhdGUgYXQgYGxvYWRpbmdgIGFuZCBsZXQgaHlkcmF0aW9uIGJvb3QgaXQuXG4gICAgaWYgKHRoaXMuaXNCcm93c2VyKSB7XG4gICAgICB2b2lkIHRoaXMuYm9vdCgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuY2xlYXJSZWZyZXNoVGltZXIoKTtcbiAgICB0aGlzLl9zdGF0dXMuY29tcGxldGUoKTtcbiAgICB0aGlzLl91c2VyLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5fc2Vzc2lvbi5jb21wbGV0ZSgpO1xuICAgIHRoaXMuX2NsYWltcy5jb21wbGV0ZSgpO1xuICAgIHRoaXMuX21lbWJlcnNoaXBzLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvLyAtLS0gQ29uZmlndXJhdGlvbiBhY2Nlc3NvcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgZ2V0IGFwcGVhcmFuY2UoKTogQXBwZWFyYW5jZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5hcHBlYXJhbmNlO1xuICB9XG5cbiAgZ2V0IGxvY2FsaXphdGlvbigpOiBDYXRhbG9nIHtcbiAgICByZXR1cm4gdGhpcy5jYXRhbG9nO1xuICB9XG5cbiAgZ2V0IGZyb250ZW5kQXBpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYmFzZVVybDtcbiAgfVxuXG4gIC8qKiBUb2tlbnMgYXMgQ1NTIGN1c3RvbSBwcm9wZXJ0aWVzLCBmb3IgYSBob3N0IGVsZW1lbnQgdG8gaW5oZXJpdC4gKi9cbiAgYXBwZWFyYW5jZVZhcmlhYmxlcygpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICByZXR1cm4gY3NzVmFyaWFibGVzKHJlc29sdmVUb2tlbnModGhpcy5vcHRpb25zLmFwcGVhcmFuY2UpKTtcbiAgfVxuXG4gIC8qKiBBIGZyZXNoIHtAbGluayBGYXBpQ2xpZW50fSBmb3IgZHJpdmluZyBhIHNpZ24taW4vc2lnbi11cCBmbG93LiAqL1xuICBjcmVhdGVGYXBpQ2xpZW50KCk6IEZhcGlDbGllbnQge1xuICAgIHJldHVybiBuZXcgRmFwaUNsaWVudCh7IHB1Ymxpc2hhYmxlS2V5OiB0aGlzLnB1Ymxpc2hhYmxlS2V5LCBiYXNlVXJsOiB0aGlzLmJhc2VVcmwgfSk7XG4gIH1cblxuICAvLyAtLS0gSW1wZXJhdGl2ZSBBUEkgKG1pcnJvcnMgdGhlIFJlYWN0IGhvb2tzJyBhY3Rpb25zKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IHNlc3Npb24ncyBKV1QsIGFsd2F5cyBmcmVzaDogaWYgdGhlIGNhY2hlZCB0b2tlbiBpcyB3aXRoaW4gNXMgb2ZcbiAgICogZXhwaXJ5IGl0IGlzIHJlZnJlc2hlZCBmaXJzdCByYXRoZXIgdGhhbiBoYW5kZWQgb3Zlci4gTnVsbCB3aGVuIHNpZ25lZCBvdXQuXG4gICAqL1xuICBhc3luYyBnZXRUb2tlbigpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICBjb25zdCB1c2FibGUgPSB0aGlzLmNhY2hlLmdldCg1XzAwMCk7XG4gICAgaWYgKHVzYWJsZSkgcmV0dXJuIHVzYWJsZS5qd3Q7XG5cbiAgICBhd2FpdCB0aGlzLnJlZnJlc2goKTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoNV8wMDApPy5qd3QgPz8gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgc2lnbmVkLWluIHVzZXIncyBPV04gbGl2ZSBhY2Nlc3MgdG9rZW4gYXQgYSBjb25uZWN0ZWQgcHJvdmlkZXIgKEdvb2dsZSxcbiAgICogR2l0SHViLCDigKYpLCBzbyB0aGUgYXBwIGNhbiBjYWxsIHRoYXQgcHJvdmlkZXIncyBBUEkgZnJvbSB0aGUgYnJvd3Nlci4gTnVsbFxuICAgKiB3aGVuIHRoZXJlIGlzIG5vIHVzYWJsZSB0b2tlbiDigJQgbm8gbGlua2VkIGFjY291bnQsIG9yIHRoZSBwcm92aWRlciBncmFudGVkIC9cbiAgICoga2VwdCBub25lLiBUaGUgc2VydmVyIHJlZnJlc2hlcyBhIHN0YWxlIHRva2VuIG9uIHJlYWQ7IHRoZSByZWZyZXNoIHRva2VuIGlzXG4gICAqIG5ldmVyIGV4cG9zZWQuXG4gICAqL1xuICBnZXRQcm92aWRlclRva2VuKHByb3ZpZGVyOiBzdHJpbmcpOiBQcm9taXNlPFByb3ZpZGVyVG9rZW4gfCBudWxsPiB7XG4gICAgcmV0dXJuIGZldGNoUHJvdmlkZXJUb2tlbih0aGlzLmZhcGlDbGllbnQsIHByb3ZpZGVyKTtcbiAgfVxuXG4gIC8qKiBJbXBlcmF0aXZlIGBoYXMoKWAg4oCUIHRoZSBzYW1lIGV2YWx1YXRpb24gYCphdGxhc1Byb3RlY3RgIHJlbmRlcnMgb24uICovXG4gIGhhcyhjb25kaXRpb246IFByb3RlY3RDb25kaXRpb24pOiBib29sZWFuIHtcbiAgICByZXR1cm4gZXZhbHVhdGUodGhpcy5fY2xhaW1zLnZhbHVlLCBjb25kaXRpb24pLmFsbG93ZWQ7XG4gIH1cblxuICAvKiogUmV2b2tlIHRoZSBjdXJyZW50IHNlc3Npb24gc2VydmVyLXNpZGUgYW5kIGRyb3AgYWxsIGxvY2FsIGF1dGggc3RhdGUuICovXG4gIGFzeW5jIHNpZ25PdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuY2FjaGUucGVlaygpO1xuICAgIGlmIChjdXJyZW50KSB7XG4gICAgICBhd2FpdCB0aGlzLmNhbGwoYC92MS9jbGllbnQvc2Vzc2lvbnMvJHtjdXJyZW50LnNlc3Npb25JZH0vcmV2b2tlYCwge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIH0pLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIHRoaXMuY2xlYXJSZWZyZXNoVGltZXIoKTtcbiAgICB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5fc3RhdHVzLm5leHQoJ3NpZ25lZF9vdXQnKTtcbiAgICB0aGlzLl91c2VyLm5leHQobnVsbCk7XG4gICAgdGhpcy5fc2Vzc2lvbi5uZXh0KG51bGwpO1xuICAgIHRoaXMuX2NsYWltcy5uZXh0KG51bGwpO1xuICAgIHRoaXMuX21lbWJlcnNoaXBzLm5leHQoW10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN3aXRjaCB0aGUgYWN0aXZlIG9yZ2FuaXphdGlvbiAob3IgYG51bGxgIGZvciB0aGUgcGVyc29uYWwgYWNjb3VudCkuIFRoZVxuICAgKiBuZXcgdG9rZW4gY2FycmllcyB0aGUgbmV3IG9yZyBjbGFpbXMsIHNvIHRoZSBhcHAncyBwZXJtaXNzaW9uIGNoZWNrcyB1cGRhdGVcbiAgICogd2l0aG91dCBhIHJlLWxvZ2luLlxuICAgKi9cbiAgYXN5bmMgc2V0QWN0aXZlT3JnYW5pemF0aW9uKG9yZ2FuaXphdGlvbklkOiBzdHJpbmcgfCBudWxsKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuY2FjaGUucGVlaygpO1xuICAgIGlmICghY3VycmVudCkgcmV0dXJuO1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmNhbGwoYC92MS9jbGllbnQvc2Vzc2lvbnMvJHtjdXJyZW50LnNlc3Npb25JZH0vdG91Y2hgLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgYWN0aXZlX29yZ2FuaXphdGlvbl9pZDogb3JnYW5pemF0aW9uSWQgfSksXG4gICAgfSk7XG4gICAgaWYgKCFyZXNwb25zZS5vaykgcmV0dXJuO1xuXG4gICAgY29uc3QgYm9keSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIHsgand0OiBzdHJpbmcgfTtcbiAgICB0aGlzLmFwcGx5VG9rZW4oYm9keS5qd3QsIGN1cnJlbnQuc2Vzc2lvbklkKTtcbiAgICBhd2FpdCB0aGlzLnJlbG9hZCgpO1xuICB9XG5cbiAgLyoqIFJlLXJlYWQgYC92MS9jbGllbnRgOiByZWZyZXNoIHVzZXIsIHNlc3Npb24sIG1lbWJlcnNoaXBzIGFuZCBzdGF0dXMuICovXG4gIGFzeW5jIHJlbG9hZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmNhbGwoJy92MS9jbGllbnQnKTtcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHRocm93IG5ldyBFcnJvcignYm9vdCBmYWlsZWQnKTtcblxuICAgICAgY29uc3QgYm9keSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIHtcbiAgICAgICAgc2Vzc2lvbjogQXRsYXNTZXNzaW9uIHwgbnVsbDtcbiAgICAgICAgdXNlcjogQXRsYXNVc2VyIHwgbnVsbDtcbiAgICAgICAgand0Pzogc3RyaW5nO1xuICAgICAgICBvcmdhbml6YXRpb25fbWVtYmVyc2hpcHM/OiBBdGxhc09yZ2FuaXphdGlvbk1lbWJlcnNoaXBbXTtcbiAgICAgIH07XG5cbiAgICAgIGlmICghYm9keS5zZXNzaW9uIHx8ICFib2R5LnVzZXIpIHtcbiAgICAgICAgdGhpcy5jbGVhclJlZnJlc2hUaW1lcigpO1xuICAgICAgICB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuX3N0YXR1cy5uZXh0KCdzaWduZWRfb3V0Jyk7XG4gICAgICAgIHRoaXMuX3VzZXIubmV4dChudWxsKTtcbiAgICAgICAgdGhpcy5fc2Vzc2lvbi5uZXh0KG51bGwpO1xuICAgICAgICB0aGlzLl9jbGFpbXMubmV4dChudWxsKTtcbiAgICAgICAgdGhpcy5fbWVtYmVyc2hpcHMubmV4dChbXSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdXNlci5uZXh0KGJvZHkudXNlcik7XG4gICAgICB0aGlzLl9zZXNzaW9uLm5leHQoYm9keS5zZXNzaW9uKTtcbiAgICAgIHRoaXMuX21lbWJlcnNoaXBzLm5leHQoYm9keS5vcmdhbml6YXRpb25fbWVtYmVyc2hpcHMgPz8gW10pO1xuICAgICAgaWYgKGJvZHkuand0KSB0aGlzLmFwcGx5VG9rZW4oYm9keS5qd3QsIGJvZHkuc2Vzc2lvbi5pZCk7XG4gICAgICB0aGlzLl9zdGF0dXMubmV4dCgnc2lnbmVkX2luJyk7XG4gICAgICB0aGlzLnNjaGVkdWxlUmVmcmVzaCgpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gQSBmYWlsZWQgYm9vdCBpcyBOT1Qgc2lnbmVkLW91dC4gUmVuZGVyaW5nIGEgc2lnbi1pbiBmb3JtIGJlY2F1c2UgdGhlXG4gICAgICAvLyBuZXR3b3JrIGhpY2N1cGVkIHRocm93cyBhd2F5IGEgcGVyZmVjdGx5IGdvb2Qgc2Vzc2lvbiBhbmQgZm9yY2VzIGFcbiAgICAgIC8vIG5lZWRsZXNzIHJlLWF1dGhlbnRpY2F0aW9uLiBPbmx5IHByb21vdGUgbG9hZGluZyDihpIgc2lnbmVkX291dC5cbiAgICAgIGlmICh0aGlzLl9zdGF0dXMudmFsdWUgPT09ICdsb2FkaW5nJykgdGhpcy5fc3RhdHVzLm5leHQoJ3NpZ25lZF9vdXQnKTtcbiAgICB9XG4gIH1cblxuICAvLyAtLS0gSW50ZXJuYWxzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIMKnNi4zIHN0ZXAgMzogY29tcGxldGUgYSByZWRpcmVjdC1iYXNlZCBzaWduLWluLCB0aGVuIGJvb3QuIEFuIE9BdXRoIG9yXG4gICAqIGhvc3RlZC1wYWdlIGZsb3cgbGFuZHMgYmFjayB3aXRoIGEgb25lLXRpbWUgdGlja2V0IGluIHRoZSBVUkw7IGV4Y2hhbmdlIGl0XG4gICAqIGZvciBjb29raWVzLCBzY3J1YiB0aGUgVVJMIHNvIGEgcmVsb2FkIGNhbm5vdCByZXBsYXkgaXQsIFRIRU4gcmVhZCB0aGVcbiAgICogc2Vzc2lvbi4gQSByZWRpcmVjdCBjYXJyeWluZyBvbmx5IGEgc3RhdHVzIChhIHNlY29uZCBmYWN0b3IgaXMgc3RpbGwgb3dlZClcbiAgICogaGFzIG5vIHRpY2tldCwgc28gbm90aGluZyBpcyBleGNoYW5nZWQgYW5kIHRoZSBhcHAgYm9vdHMgc2lnbmVkLW91dC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYm9vdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXN1bHQgPSByZWFkUmVkaXJlY3RSZXN1bHQod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG5cbiAgICBpZiAocmVzdWx0Py50aWNrZXQpIHtcbiAgICAgIGF3YWl0IHRoaXMuY2FsbCgnL3YxL2NsaWVudC90aWNrZXRzL2V4Y2hhbmdlJywge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBhdHRlbXB0X2lkOiByZXN1bHQuYXR0ZW1wdElkLCB0aWNrZXQ6IHJlc3VsdC50aWNrZXQgfSksXG4gICAgICB9KS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICBpZiAocmVzdWx0KSB7XG4gICAgICB3aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoe30sIGRvY3VtZW50LnRpdGxlLCBzdHJpcFJlZGlyZWN0UGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5ocmVmKSk7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMucmVsb2FkKCk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRQZW5kaW5nQXR0ZW1wdCgpOiB7IGlkOiBzdHJpbmc7IHN0YXR1czogc3RyaW5nIH0gfCBudWxsIHtcbiAgICBjb25zdCByZXN1bHQgPSByZWFkUmVkaXJlY3RSZXN1bHQod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgcmV0dXJuIHJlc3VsdD8uc3RhdHVzICYmICFyZXN1bHQudGlja2V0XG4gICAgICA/IHsgaWQ6IHJlc3VsdC5hdHRlbXB0SWQsIHN0YXR1czogcmVzdWx0LnN0YXR1cyB9XG4gICAgICA6IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGNhbGwocGF0aDogc3RyaW5nLCBpbml0PzogUmVxdWVzdEluaXQpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIHRoaXMuZG9GZXRjaChgJHt0aGlzLmJhc2VVcmx9JHtwYXRofWAsIHtcbiAgICAgIC4uLmluaXQsXG4gICAgICAvLyBDb29raWVzIGNhcnJ5IHRoZSBzZXNzaW9uOyBhIHJlcXVlc3Qgd2l0aG91dCB0aGlzIGlzIGluZGlzdGluZ3Vpc2hhYmxlXG4gICAgICAvLyBmcm9tIGJlaW5nIHNpZ25lZCBvdXQuXG4gICAgICBjcmVkZW50aWFsczogJ2luY2x1ZGUnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAneC1wdWJsaXNoYWJsZS1rZXknOiB0aGlzLnB1Ymxpc2hhYmxlS2V5LFxuICAgICAgICAuLi4oaW5pdD8uYm9keSA/IHsgJ2NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9IDoge30pLFxuICAgICAgICAuLi5pbml0Py5oZWFkZXJzLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwbHlUb2tlbihqd3Q6IHN0cmluZywgc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBleHBpcmVzQXQgPSByZWFkRXhwaXJ5KGp3dCk7XG4gICAgaWYgKCFleHBpcmVzQXQpIHJldHVybjtcblxuICAgIHRoaXMuY2FjaGUuc2V0KHsgand0LCBleHBpcmVzQXQsIHNlc3Npb25JZCB9KTtcbiAgICB0aGlzLl9jbGFpbXMubmV4dChkZWNvZGVDbGFpbXMoand0KSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZnJlc2goKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuY2FjaGUucGVlaygpO1xuICAgIGlmICghY3VycmVudCkgcmV0dXJuO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jYWxsKGAvdjEvY2xpZW50L3Nlc3Npb25zLyR7Y3VycmVudC5zZXNzaW9uSWR9L3Rva2Vuc2AsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICB9KTtcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHRocm93IG5ldyBFcnJvcigncmVmcmVzaCBmYWlsZWQnKTtcblxuICAgICAgY29uc3QgYm9keSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIHsgand0OiBzdHJpbmc7IHNlc3Npb25faWQ6IHN0cmluZyB9O1xuICAgICAgdGhpcy5hcHBseVRva2VuKGJvZHkuand0LCBib2R5LnNlc3Npb25faWQpO1xuICAgICAgdGhpcy5zY2hlZHVsZVJlZnJlc2goKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFRoZSBzZXNzaW9uIG1heSBnZW51aW5lbHkgYmUgZ29uZS4gUmUtYm9vdCByYXRoZXIgdGhhbiBndWVzcy5cbiAgICAgIGF3YWl0IHRoaXMucmVsb2FkKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIMKnNy40OiBwcm9hY3RpdmUsIGppdHRlcmVkIHJlZnJlc2ggc2NoZWR1bGVkIGZyb20gdGhlIHRva2VuJ3Mgb3duIGV4cGlyeS4gKi9cbiAgcHJpdmF0ZSBzY2hlZHVsZVJlZnJlc2goKTogdm9pZCB7XG4gICAgdGhpcy5jbGVhclJlZnJlc2hUaW1lcigpO1xuICAgIGlmICh0aGlzLl9zdGF0dXMudmFsdWUgIT09ICdzaWduZWRfaW4nKSByZXR1cm47XG5cbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuY2FjaGUucGVlaygpO1xuICAgIGlmICghdG9rZW4pIHJldHVybjtcblxuICAgIGNvbnN0IGRlbGF5ID0gbXNVbnRpbFJlZnJlc2goeyB0b2tlbiwgbm93OiBEYXRlLm5vdygpIH0pO1xuICAgIHRoaXMucmVmcmVzaFRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB2b2lkIHRoaXMucmVmcmVzaCgpLCBkZWxheSk7XG4gIH1cblxuICBwcml2YXRlIGNsZWFyUmVmcmVzaFRpbWVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlZnJlc2hUaW1lcikge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucmVmcmVzaFRpbWVyKTtcbiAgICAgIHRoaXMucmVmcmVzaFRpbWVyID0gbnVsbDtcbiAgICB9XG4gIH1cbn1cblxuLyoqIERlY29kZSBhIEpXVCBwYXlsb2FkIHdpdGhvdXQgdmVyaWZ5aW5nIGl0IOKAlCBhIHNjaGVkdWxpbmcvVUkgaGludCBvbmx5LiAqL1xuZnVuY3Rpb24gZGVjb2RlQ2xhaW1zKGp3dDogc3RyaW5nKTogU2Vzc2lvbkNsYWltcyB8IG51bGwge1xuICBjb25zdCBwYXJ0cyA9IGp3dC5zcGxpdCgnLicpO1xuICBpZiAocGFydHMubGVuZ3RoICE9PSAzKSByZXR1cm4gbnVsbDtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShcbiAgICAgIGF0b2IocGFydHNbMV0hLnJlcGxhY2UoLy0vZywgJysnKS5yZXBsYWNlKC9fL2csICcvJykpLFxuICAgICkgYXMgU2Vzc2lvbkNsYWltcztcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AtlasSignedInDirective } from './directives/signed-in.directive';
|
|
2
|
+
import { AtlasSignedOutDirective } from './directives/signed-out.directive';
|
|
3
|
+
import { AtlasLoadingDirective } from './directives/loading.directive';
|
|
4
|
+
import { AtlasLoadedDirective } from './directives/loaded.directive';
|
|
5
|
+
import { AtlasProtectDirective } from './directives/protect.directive';
|
|
6
|
+
import { AtlasRootDirective } from './directives/atlas-root.directive';
|
|
7
|
+
import { SignInComponent } from './components/sign-in.component';
|
|
8
|
+
import { SignUpComponent } from './components/sign-up.component';
|
|
9
|
+
import { UserButtonComponent } from './components/user-button.component';
|
|
10
|
+
import { OrganizationSwitcherComponent } from './components/organization-switcher.component';
|
|
11
|
+
import { UserProfileComponent } from './components/user-profile.component';
|
|
12
|
+
import { OrganizationProfileComponent } from './components/organization-profile.component';
|
|
13
|
+
/**
|
|
14
|
+
* Every standalone directive and component the SDK ships. Import the array in a
|
|
15
|
+
* standalone component's `imports`, or rely on `AtlasModule` re-exporting it for
|
|
16
|
+
* NgModule-based apps:
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* @Component({ standalone: true, imports: [...ATLAS_UI], template: '…' })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export const ATLAS_UI = [
|
|
23
|
+
AtlasSignedInDirective,
|
|
24
|
+
AtlasSignedOutDirective,
|
|
25
|
+
AtlasLoadingDirective,
|
|
26
|
+
AtlasLoadedDirective,
|
|
27
|
+
AtlasProtectDirective,
|
|
28
|
+
AtlasRootDirective,
|
|
29
|
+
SignInComponent,
|
|
30
|
+
SignUpComponent,
|
|
31
|
+
UserButtonComponent,
|
|
32
|
+
OrganizationSwitcherComponent,
|
|
33
|
+
UserProfileComponent,
|
|
34
|
+
OrganizationProfileComponent,
|
|
35
|
+
];
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRsYXMudWkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2F0bGFzLnVpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNqRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDakUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDekUsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sOENBQThDLENBQUM7QUFDN0YsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDM0UsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFFM0Y7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUc7SUFDdEIsc0JBQXNCO0lBQ3RCLHVCQUF1QjtJQUN2QixxQkFBcUI7SUFDckIsb0JBQW9CO0lBQ3BCLHFCQUFxQjtJQUNyQixrQkFBa0I7SUFDbEIsZUFBZTtJQUNmLGVBQWU7SUFDZixtQkFBbUI7SUFDbkIsNkJBQTZCO0lBQzdCLG9CQUFvQjtJQUNwQiw0QkFBNEI7Q0FDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEF0bGFzU2lnbmVkSW5EaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvc2lnbmVkLWluLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBBdGxhc1NpZ25lZE91dERpcmVjdGl2ZSB9IGZyb20gJy4vZGlyZWN0aXZlcy9zaWduZWQtb3V0LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBBdGxhc0xvYWRpbmdEaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvbG9hZGluZy5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQXRsYXNMb2FkZWREaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvbG9hZGVkLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBBdGxhc1Byb3RlY3REaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvcHJvdGVjdC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQXRsYXNSb290RGlyZWN0aXZlIH0gZnJvbSAnLi9kaXJlY3RpdmVzL2F0bGFzLXJvb3QuZGlyZWN0aXZlJztcbmltcG9ydCB7IFNpZ25JbkNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9zaWduLWluLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduVXBDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvc2lnbi11cC5jb21wb25lbnQnO1xuaW1wb3J0IHsgVXNlckJ1dHRvbkNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy91c2VyLWJ1dHRvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgT3JnYW5pemF0aW9uU3dpdGNoZXJDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvb3JnYW5pemF0aW9uLXN3aXRjaGVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBVc2VyUHJvZmlsZUNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy91c2VyLXByb2ZpbGUuY29tcG9uZW50JztcbmltcG9ydCB7IE9yZ2FuaXphdGlvblByb2ZpbGVDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvb3JnYW5pemF0aW9uLXByb2ZpbGUuY29tcG9uZW50JztcblxuLyoqXG4gKiBFdmVyeSBzdGFuZGFsb25lIGRpcmVjdGl2ZSBhbmQgY29tcG9uZW50IHRoZSBTREsgc2hpcHMuIEltcG9ydCB0aGUgYXJyYXkgaW4gYVxuICogc3RhbmRhbG9uZSBjb21wb25lbnQncyBgaW1wb3J0c2AsIG9yIHJlbHkgb24gYEF0bGFzTW9kdWxlYCByZS1leHBvcnRpbmcgaXQgZm9yXG4gKiBOZ01vZHVsZS1iYXNlZCBhcHBzOlxuICpcbiAqIGBgYHRzXG4gKiBAQ29tcG9uZW50KHsgc3RhbmRhbG9uZTogdHJ1ZSwgaW1wb3J0czogWy4uLkFUTEFTX1VJXSwgdGVtcGxhdGU6ICfigKYnIH0pXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IEFUTEFTX1VJID0gW1xuICBBdGxhc1NpZ25lZEluRGlyZWN0aXZlLFxuICBBdGxhc1NpZ25lZE91dERpcmVjdGl2ZSxcbiAgQXRsYXNMb2FkaW5nRGlyZWN0aXZlLFxuICBBdGxhc0xvYWRlZERpcmVjdGl2ZSxcbiAgQXRsYXNQcm90ZWN0RGlyZWN0aXZlLFxuICBBdGxhc1Jvb3REaXJlY3RpdmUsXG4gIFNpZ25JbkNvbXBvbmVudCxcbiAgU2lnblVwQ29tcG9uZW50LFxuICBVc2VyQnV0dG9uQ29tcG9uZW50LFxuICBPcmdhbml6YXRpb25Td2l0Y2hlckNvbXBvbmVudCxcbiAgVXNlclByb2ZpbGVDb21wb25lbnQsXG4gIE9yZ2FuaXphdGlvblByb2ZpbGVDb21wb25lbnQsXG5dIGFzIGNvbnN0O1xuIl19
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, inject, } from '@angular/core';
|
|
2
|
+
import { nextStep } from '@atlasauth/js';
|
|
3
|
+
import { AtlasService } from '../atlas.service';
|
|
4
|
+
import { classFor } from '../appearance';
|
|
5
|
+
import { translate } from '../i18n';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/**
|
|
8
|
+
* The server-driven flow shell, shared by `<atlas-sign-in>` and
|
|
9
|
+
* `<atlas-sign-up>`. The Angular peer of React's internal `AttemptFlow`.
|
|
10
|
+
*
|
|
11
|
+
* It contains NO decision about what comes next: it renders whatever `status`
|
|
12
|
+
* the server returned, mapped through `nextStep` from `@atlasauth/js` (the same
|
|
13
|
+
* exhaustive mapping the React SDK uses), so adding a step is a server change
|
|
14
|
+
* and an out-of-date client degrades to a visible "please update" message rather
|
|
15
|
+
* than a blank screen.
|
|
16
|
+
*/
|
|
17
|
+
export class AttemptFlowComponent {
|
|
18
|
+
atlas = inject(AtlasService);
|
|
19
|
+
attempt = null;
|
|
20
|
+
busy = false;
|
|
21
|
+
errors = [];
|
|
22
|
+
titleKey = 'signIn.title';
|
|
23
|
+
/** Emits the collected field values when the form is submitted. */
|
|
24
|
+
submitFlow = new EventEmitter();
|
|
25
|
+
values = {};
|
|
26
|
+
t(key, vars) {
|
|
27
|
+
return translate(this.atlas.localization, key, vars);
|
|
28
|
+
}
|
|
29
|
+
cls(key, base) {
|
|
30
|
+
return classFor(key, this.atlas.appearance, base);
|
|
31
|
+
}
|
|
32
|
+
setValue(name, value) {
|
|
33
|
+
this.values = { ...this.values, [name]: value };
|
|
34
|
+
}
|
|
35
|
+
onSubmit(event) {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
this.submitFlow.emit(this.values);
|
|
38
|
+
}
|
|
39
|
+
formErrors() {
|
|
40
|
+
return this.errors.filter((error) => !error.param);
|
|
41
|
+
}
|
|
42
|
+
fieldErrorsFor(name) {
|
|
43
|
+
return this.errors.filter((error) => error.param === name);
|
|
44
|
+
}
|
|
45
|
+
step() {
|
|
46
|
+
return this.attempt ? nextStep(this.attempt) : { kind: 'collect_identifier' };
|
|
47
|
+
}
|
|
48
|
+
showSubmit() {
|
|
49
|
+
const kind = this.step().kind;
|
|
50
|
+
return kind !== 'done' && kind !== 'await_oauth';
|
|
51
|
+
}
|
|
52
|
+
fields() {
|
|
53
|
+
const step = this.step();
|
|
54
|
+
switch (step.kind) {
|
|
55
|
+
case 'collect_identifier':
|
|
56
|
+
return [{ kind: 'input', name: 'identifier', labelKey: 'signIn.identifierLabel', type: 'email' }];
|
|
57
|
+
case 'collect_first_factor':
|
|
58
|
+
return [{ kind: 'input', name: 'password', labelKey: 'signIn.passwordLabel', type: 'password' }];
|
|
59
|
+
case 'collect_second_factor':
|
|
60
|
+
return [{ kind: 'input', name: 'code', labelKey: 'mfa.codeLabel', type: 'text' }];
|
|
61
|
+
case 'enroll_second_factor':
|
|
62
|
+
// Two consecutive codes (§5.6): a phone with a fast clock fails here
|
|
63
|
+
// rather than on every sign-in afterwards.
|
|
64
|
+
return [
|
|
65
|
+
{ kind: 'input', name: 'code', labelKey: 'mfa.enrollFirstCodeLabel', type: 'text' },
|
|
66
|
+
{ kind: 'input', name: 'secondCode', labelKey: 'mfa.enrollSecondCodeLabel', type: 'text' },
|
|
67
|
+
];
|
|
68
|
+
case 'collect_email_code':
|
|
69
|
+
return [{ kind: 'input', name: 'code', labelKey: 'signIn.emailCodeLabel', type: 'text' }];
|
|
70
|
+
case 'collect_new_password':
|
|
71
|
+
return [{ kind: 'input', name: 'password', labelKey: 'reset.newPasswordLabel', type: 'password' }];
|
|
72
|
+
case 'await_oauth':
|
|
73
|
+
return [msg('signIn.magicLinkSent')];
|
|
74
|
+
case 'done':
|
|
75
|
+
return [msg('signIn.checkOtherTab')];
|
|
76
|
+
case 'restart':
|
|
77
|
+
return [msg('error.generic')];
|
|
78
|
+
default:
|
|
79
|
+
// A status this SDK version does not know. An honest message beats a
|
|
80
|
+
// blank login box the user cannot act on.
|
|
81
|
+
return [msg('error.generic')];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AttemptFlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
85
|
+
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" }, outputs: { submitFlow: "submitFlow" }, ngImport: i0, template: `
|
|
86
|
+
<div [class]="cls('card', 'atlas-card')">
|
|
87
|
+
<h1 [class]="cls('headerTitle', 'atlas-title')">{{ t(titleKey) }}</h1>
|
|
88
|
+
|
|
89
|
+
@for (error of formErrors(); track error.code) {
|
|
90
|
+
<p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ error.message }}</p>
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
<form (submit)="onSubmit($event)">
|
|
94
|
+
@for (f of fields(); track $index) {
|
|
95
|
+
@if (f.kind === 'input') {
|
|
96
|
+
<label class="atlas-field">
|
|
97
|
+
<span>{{ t(f.labelKey) }}</span>
|
|
98
|
+
<input
|
|
99
|
+
[class]="cls('formFieldInput', 'atlas-input')"
|
|
100
|
+
[type]="f.type"
|
|
101
|
+
[value]="values[f.name] ?? ''"
|
|
102
|
+
(input)="setValue(f.name, $any($event.target).value)"
|
|
103
|
+
/>
|
|
104
|
+
@for (error of fieldErrorsFor(f.name); track error.code) {
|
|
105
|
+
<span [class]="cls('formFieldError', 'atlas-error')">{{ error.message }}</span>
|
|
106
|
+
}
|
|
107
|
+
</label>
|
|
108
|
+
} @else {
|
|
109
|
+
<p>{{ t(f.labelKey) }}</p>
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@if (showSubmit()) {
|
|
114
|
+
<button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy" type="submit">
|
|
115
|
+
{{ t('signIn.submit') }}
|
|
116
|
+
</button>
|
|
117
|
+
}
|
|
118
|
+
</form>
|
|
119
|
+
</div>
|
|
120
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
121
|
+
}
|
|
122
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AttemptFlowComponent, decorators: [{
|
|
123
|
+
type: Component,
|
|
124
|
+
args: [{
|
|
125
|
+
selector: 'atlas-attempt-flow',
|
|
126
|
+
standalone: true,
|
|
127
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
128
|
+
template: `
|
|
129
|
+
<div [class]="cls('card', 'atlas-card')">
|
|
130
|
+
<h1 [class]="cls('headerTitle', 'atlas-title')">{{ t(titleKey) }}</h1>
|
|
131
|
+
|
|
132
|
+
@for (error of formErrors(); track error.code) {
|
|
133
|
+
<p [class]="cls('formFieldError', 'atlas-error')" role="alert">{{ error.message }}</p>
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
<form (submit)="onSubmit($event)">
|
|
137
|
+
@for (f of fields(); track $index) {
|
|
138
|
+
@if (f.kind === 'input') {
|
|
139
|
+
<label class="atlas-field">
|
|
140
|
+
<span>{{ t(f.labelKey) }}</span>
|
|
141
|
+
<input
|
|
142
|
+
[class]="cls('formFieldInput', 'atlas-input')"
|
|
143
|
+
[type]="f.type"
|
|
144
|
+
[value]="values[f.name] ?? ''"
|
|
145
|
+
(input)="setValue(f.name, $any($event.target).value)"
|
|
146
|
+
/>
|
|
147
|
+
@for (error of fieldErrorsFor(f.name); track error.code) {
|
|
148
|
+
<span [class]="cls('formFieldError', 'atlas-error')">{{ error.message }}</span>
|
|
149
|
+
}
|
|
150
|
+
</label>
|
|
151
|
+
} @else {
|
|
152
|
+
<p>{{ t(f.labelKey) }}</p>
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@if (showSubmit()) {
|
|
157
|
+
<button [class]="cls('formButtonPrimary', 'atlas-button')" [disabled]="busy" type="submit">
|
|
158
|
+
{{ t('signIn.submit') }}
|
|
159
|
+
</button>
|
|
160
|
+
}
|
|
161
|
+
</form>
|
|
162
|
+
</div>
|
|
163
|
+
`,
|
|
164
|
+
}]
|
|
165
|
+
}], propDecorators: { attempt: [{
|
|
166
|
+
type: Input
|
|
167
|
+
}], busy: [{
|
|
168
|
+
type: Input
|
|
169
|
+
}], errors: [{
|
|
170
|
+
type: Input
|
|
171
|
+
}], titleKey: [{
|
|
172
|
+
type: Input
|
|
173
|
+
}], submitFlow: [{
|
|
174
|
+
type: Output
|
|
175
|
+
}] } });
|
|
176
|
+
/** A read-only message row: `labelKey` holds the i18n key of the text to show. */
|
|
177
|
+
function msg(labelKey) {
|
|
178
|
+
return { kind: 'message', name: '', labelKey, type: 'text' };
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZW1wdC1mbG93LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9hdHRlbXB0LWZsb3cuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFxQyxNQUFNLGVBQWUsQ0FBQztBQUM1RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUFlcEM7Ozs7Ozs7OztHQVNHO0FBMENILE1BQU0sT0FBTyxvQkFBb0I7SUFDZCxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXJDLE9BQU8sR0FBdUIsSUFBSSxDQUFDO0lBQ25DLElBQUksR0FBRyxLQUFLLENBQUM7SUFDYixNQUFNLEdBQWlCLEVBQUUsQ0FBQztJQUMxQixRQUFRLEdBQUcsY0FBYyxDQUFDO0lBRW5DLG1FQUFtRTtJQUN6RCxVQUFVLEdBQUcsSUFBSSxZQUFZLEVBQTBCLENBQUM7SUFFeEQsTUFBTSxHQUEyQixFQUFFLENBQUM7SUFFcEMsQ0FBQyxDQUFDLEdBQVcsRUFBRSxJQUE2QjtRQUNwRCxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVTLEdBQUcsQ0FBQyxHQUFlLEVBQUUsSUFBWTtRQUN6QyxPQUFPLFFBQVEsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsSUFBSSxD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LEtBQUssYUFBYTtnQkFDaEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUM7WUFDdkMsS0FBSyxNQUFNO2dCQUNULE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDO1lBQ3ZDLEtBQUssU0FBUztnQkFDWixPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDaEM7Z0JBQ0UscUVBQXFFO2dCQUNyRSwwQ0FBMEM7Z0JBQzFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztRQUNsQyxDQUFDO0lBQ0gsQ0FBQzt3R0E5RVUsb0JBQW9COzRGQUFwQixvQkFBb0IsMk1BckNyQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQ1Q7OzRGQUVVLG9CQUFvQjtrQkF6Q2hDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLG9CQUFvQjtvQkFDOUIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUNUO2lCQUNGOzhCQUlVLE9BQU87c0JBQWYsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0ksVUFBVTtzQkFBbkIsTUFBTTs7QUF3RVQsa0ZBQWtGO0FBQ2xGLFNBQVMsR0FBRyxDQUFDLFFBQWdCO0lBQzNCLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUMvRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgbmV4dFN0ZXAsIHR5cGUgQXR0ZW1wdFZpZXcsIHR5cGUgRmllbGRFcnJvciB9IGZyb20gJ0BhdGxhc2F1dGgvanMnO1xuaW1wb3J0IHsgQXRsYXNTZXJ2aWNlIH0gZnJvbSAnLi4vYXRsYXMuc2VydmljZSc7XG5pbXBvcnQgeyBjbGFzc0ZvciwgdHlwZSBFbGVtZW50S2V5IH0gZnJvbSAnLi4vYXBwZWFyYW5jZSc7XG5pbXBvcnQgeyB0cmFuc2xhdGUgfSBmcm9tICcuLi9pMThuJztcblxuLyoqXG4gKiBPbmUgcmVuZGVyZWQgcm93IG9mIHRoZSBmbG93LiBBIHVuaWZvcm0gc2hhcGUgKHJhdGhlciB0aGFuIGEgZGlzY3JpbWluYXRlZFxuICogdW5pb24pIHNvIHRoZSB0ZW1wbGF0ZSBhY2Nlc3NlcyBvbmx5IGZpZWxkcyB0aGF0IGFsd2F5cyBleGlzdCDigJQgbm8gcmVsaWFuY2Ugb25cbiAqIHRlbXBsYXRlIGNvbnRyb2wtZmxvdyBuYXJyb3dpbmcgb2YgYSBsb29wIHZhcmlhYmxlLCB3aGljaCB2YXJpZXMgYnkgQW5ndWxhclxuICogbWlub3IuIEZvciBhIGBtZXNzYWdlYCByb3csIGBsYWJlbEtleWAgY2FycmllcyB0aGUgbWVzc2FnZSdzIGkxOG4ga2V5LlxuICovXG5pbnRlcmZhY2UgU3RlcEZpZWxkIHtcbiAga2luZDogJ2lucHV0JyB8ICdtZXNzYWdlJztcbiAgbmFtZTogc3RyaW5nO1xuICBsYWJlbEtleTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHNlcnZlci1kcml2ZW4gZmxvdyBzaGVsbCwgc2hhcmVkIGJ5IGA8YXRsYXMtc2lnbi1pbj5gIGFuZFxuICogYDxhdGxhcy1zaWduLXVwPmAuIFRoZSBBbmd1bGFyIHBlZXIgb2YgUmVhY3QncyBpbnRlcm5hbCBgQXR0ZW1wdEZsb3dgLlxuICpcbiAqIEl0IGNvbnRhaW5zIE5PIGRlY2lzaW9uIGFib3V0IHdoYXQgY29tZXMgbmV4dDogaXQgcmVuZGVycyB3aGF0ZXZlciBgc3RhdHVzYFxuICogdGhlIHNlcnZlciByZXR1cm5lZCwgbWFwcGVkIHRocm91Z2ggYG5leHRTdGVwYCBmcm9tIGBAYXRsYXNhdXRoL2pzYCAodGhlIHNhbWVcbiAqIGV4aGF1c3RpdmUgbWFwcGluZyB0aGUgUmVhY3QgU0RLIHVzZXMpLCBzbyBhZGRpbmcgYSBzdGVwIGlzIGEgc2VydmVyIGNoYW5nZVxuICogYW5kIGFuIG91dC1vZi1kYXRlIGNsaWVudCBkZWdyYWRlcyB0byBhIHZpc2libGUgXCJwbGVhc2UgdXBkYXRlXCIgbWVzc2FnZSByYXRoZXJcbiAqIHRoYW4gYSBibGFuayBzY3JlZW4uXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2F0bGFzLWF0dGVtcHQtZmxvdycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNscygnY2FyZCcsICdhdGxhcy1jYXJkJylcIj5cbiAgICAgIDxoMSBbY2xhc3NdPVwiY2xzKCdoZWFkZXJUaXRsZScsICdhdGxhcy10aXRsZScpXCI+e3sgdCh0aXRsZUtleSkgfX08L2gxPlxuXG4gICAgICBAZm9yIChlcnJvciBvZiBmb3JtRXJyb3JzKCk7IHRyYWNrIGVycm9yLmNvZGUpIHtcbiAgICAgICAgPHAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkRXJyb3InLCAnYXRsYXMtZXJyb3InKVwiIHJvbGU9XCJhbGVydFwiPnt7IGVycm9yLm1lc3NhZ2UgfX08L3A+XG4gICAgICB9XG5cbiAgICAgIDxmb3JtIChzdWJtaXQpPVwib25TdWJtaXQoJGV2ZW50KVwiPlxuICAgICAgICBAZm9yIChmIG9mIGZpZWxkcygpOyB0cmFjayAkaW5kZXgpIHtcbiAgICAgICAgICBAaWYgKGYua2luZCA9PT0gJ2lucHV0Jykge1xuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiYXRsYXMtZmllbGRcIj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgdChmLmxhYmVsS2V5KSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgW2NsYXNzXT1cImNscygnZm9ybUZpZWxkSW5wdXQnLCAnYXRsYXMtaW5wdXQnKVwiXG4gICAgICAgICAgICAgICAgW3R5cGVdPVwiZi50eXBlXCJcbiAgICAgICAgICAgICAgICBbdmFsdWVdPVwidmFsdWVzW2YubmFtZV0gPz8gJydcIlxuICAgICAgICAgICAgICAgIChpbnB1dCk9XCJzZXRWYWx1ZShmLm5hbWUsICRhbnkoJGV2ZW50LnRhcmdldCkudmFsdWUpXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgQGZvciAoZXJyb3Igb2YgZmllbGRFcnJvcnNGb3IoZi5uYW1lKTsgdHJhY2sgZXJyb3IuY29kZSkge1xuICAgICAgICAgICAgICAgIDxzcGFuIFtjbGFzc109XCJjbHMoJ2Zvcm1GaWVsZEVycm9yJywgJ2F0bGFzLWVycm9yJylcIj57eyBlcnJvci5tZXNzYWdlIH19PC9zcGFuPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgPHA+e3sgdChmLmxhYmVsS2V5KSB9fTwvcD5cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBAaWYgKHNob3dTdWJtaXQoKSkge1xuICAgICAgICAgIDxidXR0b24gW2NsYXNzXT1cImNscygnZm9ybUJ1dHRvblByaW1hcnknLCAnYXRsYXMtYnV0dG9uJylcIiBbZGlzYWJsZWRdPVwiYnVzeVwiIHR5cGU9XCJzdWJtaXRcIj5cbiAgICAgICAgICAgIHt7IHQoJ3NpZ25Jbi5zdWJtaXQnKSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICA8L2Zvcm0+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEF0dGVtcHRGbG93Q29tcG9uZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhdGxhcyA9IGluamVjdChBdGxhc1NlcnZpY2UpO1xuXG4gIEBJbnB1dCgpIGF0dGVtcHQ6IEF0dGVtcHRWaWV3IHwgbnVsbCA9IG51bGw7XG4gIEBJbnB1dCgpIGJ1c3kgPSBmYWxzZTtcbiAgQElucHV0KCkgZXJyb3JzOiBGaWVsZEVycm9yW10gPSBbXTtcbiAgQElucHV0KCkgdGl0bGVLZXkgPSAnc2lnbkluLnRpdGxlJztcblxuICAvKiogRW1pdHMgdGhlIGNvbGxlY3RlZCBmaWVsZCB2YWx1ZXMgd2hlbiB0aGUgZm9ybSBpcyBzdWJtaXR0ZWQuICovXG4gIEBPdXRwdXQoKSBzdWJtaXRGbG93ID0gbmV3IEV2ZW50RW1pdHRlcjxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PigpO1xuXG4gIHByb3RlY3RlZCB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBwcm90ZWN0ZWQgdChrZXk6IHN0cmluZywgdmFycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcge1xuICAgIHJldHVybiB0cmFuc2xhdGUodGhpcy5hdGxhcy5sb2NhbGl6YXRpb24sIGtleSwgdmFycyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY2xzKGtleTogRWxlbWVudEtleSwgYmFzZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY2xhc3NGb3Ioa2V5LCB0aGlzLmF0bGFzLmFwcGVhcmFuY2UsIGJhc2UpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldFZhbHVlKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudmFsdWVzID0geyAuLi50aGlzLnZhbHVlcywgW25hbWVdOiB2YWx1ZSB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uU3VibWl0KGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgdGhpcy5zdWJtaXRGbG93LmVtaXQodGhpcy52YWx1ZXMpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZvcm1FcnJvcnMoKTogRmllbGRFcnJvcltdIHtcbiAgICByZXR1cm4gdGhpcy5lcnJvcnMuZmlsdGVyKChlcnJvcikgPT4gIWVycm9yLnBhcmFtKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBmaWVsZEVycm9yc0ZvcihuYW1lOiBzdHJpbmcpOiBGaWVsZEVycm9yW10ge1xuICAgIHJldHVybiB0aGlzLmVycm9ycy5maWx0ZXIoKGVycm9yKSA9PiBlcnJvci5wYXJhbSA9PT0gbmFtZSk7XG4gIH1cblxuICBwcml2YXRlIHN0ZXAoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXR0ZW1wdCA/IG5leHRTdGVwKHRoaXMuYXR0ZW1wdCkgOiAoeyBraW5kOiAnY29sbGVjdF9pZGVudGlmaWVyJyB9IGFzIGNvbnN0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG93U3VibWl0KCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGtpbmQgPSB0aGlzLnN0ZXAoKS5raW5kO1xuICAgIHJldHVybiBraW5kICE9PSAnZG9uZScgJiYga2luZCAhPT0gJ2F3YWl0X29hdXRoJztcbiAgfVxuXG4gIHByb3RlY3RlZCBmaWVsZHMoKTogU3RlcEZpZWxkW10ge1xuICAgIGNvbnN0IHN0ZXAgPSB0aGlzLnN0ZXAoKTtcbiAgICBzd2l0Y2ggKHN0ZXAua2luZCkge1xuICAgICAgY2FzZSAnY29sbGVjdF9pZGVudGlmaWVyJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdpZGVudGlmaWVyJywgbGFiZWxLZXk6ICdzaWduSW4uaWRlbnRpZmllckxhYmVsJywgdHlwZTogJ2VtYWlsJyB9XTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfZmlyc3RfZmFjdG9yJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdwYXNzd29yZCcsIGxhYmVsS2V5OiAnc2lnbkluLnBhc3N3b3JkTGFiZWwnLCB0eXBlOiAncGFzc3dvcmQnIH1dO1xuICAgICAgY2FzZSAnY29sbGVjdF9zZWNvbmRfZmFjdG9yJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdjb2RlJywgbGFiZWxLZXk6ICdtZmEuY29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH1dO1xuICAgICAgY2FzZSAnZW5yb2xsX3NlY29uZF9mYWN0b3InOlxuICAgICAgICAvLyBUd28gY29uc2VjdXRpdmUgY29kZXMgKMKnNS42KTogYSBwaG9uZSB3aXRoIGEgZmFzdCBjbG9jayBmYWlscyBoZXJlXG4gICAgICAgIC8vIHJhdGhlciB0aGFuIG9uIGV2ZXJ5IHNpZ24taW4gYWZ0ZXJ3YXJkcy5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICB7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdjb2RlJywgbGFiZWxLZXk6ICdtZmEuZW5yb2xsRmlyc3RDb2RlTGFiZWwnLCB0eXBlOiAndGV4dCcgfSxcbiAgICAgICAgICB7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdzZWNvbmRDb2RlJywgbGFiZWxLZXk6ICdtZmEuZW5yb2xsU2Vjb25kQ29kZUxhYmVsJywgdHlwZTogJ3RleHQnIH0sXG4gICAgICAgIF07XG4gICAgICBjYXNlICdjb2xsZWN0X2VtYWlsX2NvZGUnOlxuICAgICAgICByZXR1cm4gW3sga2luZDogJ2lucHV0JywgbmFtZTogJ2NvZGUnLCBsYWJlbEtleTogJ3NpZ25Jbi5lbWFpbENvZGVMYWJlbCcsIHR5cGU6ICd0ZXh0JyB9XTtcbiAgICAgIGNhc2UgJ2NvbGxlY3RfbmV3X3Bhc3N3b3JkJzpcbiAgICAgICAgcmV0dXJuIFt7IGtpbmQ6ICdpbnB1dCcsIG5hbWU6ICdwYXNzd29yZCcsIGxhYmVsS2V5OiAncmVzZXQubmV3UGFzc3dvcmRMYWJlbCcsIHR5cGU6ICdwYXNzd29yZCcgfV07XG4gICAgICBjYXNlICdhd2FpdF9vYXV0aCc6XG4gICAgICAgIHJldHVybiBbbXNnKCdzaWduSW4ubWFnaWNMaW5rU2VudCcpXTtcbiAgICAgIGNhc2UgJ2RvbmUnOlxuICAgICAgICByZXR1cm4gW21zZygnc2lnbkluLmNoZWNrT3RoZXJUYWInKV07XG4gICAgICBjYXNlICdyZXN0YXJ0JzpcbiAgICAgICAgcmV0dXJuIFttc2coJ2Vycm9yLmdlbmVyaWMnKV07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBBIHN0YXR1cyB0aGlzIFNESyB2ZXJzaW9uIGRvZXMgbm90IGtub3cuIEFuIGhvbmVzdCBtZXNzYWdlIGJlYXRzIGFcbiAgICAgICAgLy8gYmxhbmsgbG9naW4gYm94IHRoZSB1c2VyIGNhbm5vdCBhY3Qgb24uXG4gICAgICAgIHJldHVybiBbbXNnKCdlcnJvci5nZW5lcmljJyldO1xuICAgIH1cbiAgfVxufVxuXG4vKiogQSByZWFkLW9ubHkgbWVzc2FnZSByb3c6IGBsYWJlbEtleWAgaG9sZHMgdGhlIGkxOG4ga2V5IG9mIHRoZSB0ZXh0IHRvIHNob3cuICovXG5mdW5jdGlvbiBtc2cobGFiZWxLZXk6IHN0cmluZyk6IFN0ZXBGaWVsZCB7XG4gIHJldHVybiB7IGtpbmQ6ICdtZXNzYWdlJywgbmFtZTogJycsIGxhYmVsS2V5LCB0eXBlOiAndGV4dCcgfTtcbn1cbiJdfQ==
|