UNPKG

66.6 kBJavaScriptView Raw
1import { __decorate, __metadata, __awaiter } from 'tslib';
2import { forwardRef, Injectable, InjectionToken, Component, NgModule } from '@angular/core';
3import { Type, plainToClass } from 'class-transformer';
4import { Router, ActivatedRoute, RouterModule } from '@angular/router';
5import { Storage, UbudStorageModule } from '@ubud/storage';
6import { forkJoin, Observable, of } from 'rxjs';
7import { fromPromise } from 'rxjs/internal/observable/fromPromise';
8import { catchError, map, switchMap, tap, first } from 'rxjs/internal/operators';
9import { HttpClient } from '@angular/common/http';
10import { Location } from '@angular/common';
11import { ErrorObservable } from 'rxjs-compat/observable/ErrorObservable';
12
13/**
14 * @fileoverview added by tsickle
15 * @suppress {checkTypes} checked by tsc
16 */
17class Config {
18 /**
19 * @param {?=} data
20 */
21 constructor(data) {
22 this.endpoint = 'https://account.kemnaker.go.id';
23 Object.assign(this, data);
24 }
25}
26
27/**
28 * @fileoverview added by tsickle
29 * @suppress {checkTypes} checked by tsc
30 */
31class User {
32}
33__decorate([
34 Type(/** @type {?} */ (forwardRef(() => Date))),
35 __metadata("design:type", Date)
36], User.prototype, "updatedAt", void 0);
37
38/**
39 * @fileoverview added by tsickle
40 * @suppress {checkTypes} checked by tsc
41 */
42class NacoService {
43 /**
44 * @param {?} config
45 * @param {?} router
46 * @param {?} storage
47 * @param {?} http
48 * @param {?} location
49 */
50 constructor(config, router, storage, http, location) {
51 this.config = config;
52 this.router = router;
53 this.storage = storage;
54 this.http = http;
55 this.location = location;
56 this.VERSION = 'v1';
57 this.signature = null;
58 this.user = null;
59 this.refreshToken = null;
60 this.clientSecret = null;
61 }
62 /**
63 * @param {?} user
64 * @return {?}
65 */
66 setUser(user) {
67 this.user = user;
68 this.storage.set('user', user);
69 }
70 /**
71 * @return {?}
72 */
73 getUser() {
74 if (null !== this.user) {
75 return of(this.user);
76 }
77 return fromPromise(this.storage.get('user')).pipe(switchMap((user) => {
78 if (user) {
79 return of(user);
80 }
81 const /** @type {?} */ uri = this.getUri('/users/me');
82 return fromPromise(this.getSignature()).pipe(switchMap((signature) => {
83 if (null === signature) {
84 return this.refreshUser();
85 }
86 const /** @type {?} */ options = {
87 headers: {
88 Authorization: `${signature.type} ${signature.token}`,
89 },
90 };
91 return this.http.get(uri, options).pipe(map((res) => {
92 if (res.data) {
93 return res.data;
94 }
95 throw new Error('There are no body to be transformed');
96 }), map((data) => {
97 const /** @type {?} */ authUser = plainToClass(User, data);
98 this.setUser(authUser);
99 return authUser;
100 }), catchError((e) => {
101 if (401 === e.status) {
102 return this.refreshUser().pipe(switchMap((refreshUser) => {
103 if (refreshUser) {
104 return of(refreshUser);
105 }
106 return ErrorObservable.create(e);
107 }));
108 }
109 return ErrorObservable.create(e);
110 }));
111 }));
112 }));
113 }
114 /**
115 * @return {?}
116 */
117 getSignature() {
118 if (this.signature) {
119 return Promise.resolve(this.signature);
120 }
121 return this.storage.get('signature');
122 }
123 /**
124 * @param {?} signature
125 * @return {?}
126 */
127 setSignature(signature) {
128 this.signature = signature;
129 this.storage.set('signature', signature);
130 }
131 /**
132 * @param {?} secret
133 * @return {?}
134 */
135 setClientSecret(secret) {
136 this.clientSecret = secret;
137 this.storage.set('client_secret', secret);
138 }
139 /**
140 * @param {?} refreshToken
141 * @return {?}
142 */
143 setRefreshToken(refreshToken) {
144 this.refreshToken = refreshToken;
145 this.storage.set('refresh_token', refreshToken);
146 }
147 /**
148 * @param {?=} scopes
149 * @return {?}
150 */
151 refreshUser(scopes) {
152 this.setUser(null);
153 this.setSignature(null);
154 return forkJoin(this.getRefreshToken(), this.getClientSecret()).pipe(switchMap((results) => {
155 const /** @type {?} */ refreshToken = results[0];
156 const /** @type {?} */ clientSecret = results[1];
157 if (refreshToken && clientSecret) {
158 return this.refreshWithRefreshToken(clientSecret, refreshToken.token, scopes);
159 }
160 return this.refreshWithSilentAuth();
161 }));
162 }
163 /**
164 * @param {?} clientSecret
165 * @param {?} refreshToken
166 * @param {?=} scopes
167 * @return {?}
168 */
169 refreshWithRefreshToken(clientSecret, refreshToken, scopes) {
170 const /** @type {?} */ request = this.http.post(this.getUri('/tokens'), {
171 grant_type: 'refresh_token',
172 scopes: scopes || 'basic email',
173 client_id: this.config.clientId,
174 client_secret: clientSecret,
175 refresh_token: refreshToken,
176 });
177 return request.pipe(tap((tokens) => {
178 if (tokens && tokens.data) {
179 this.setSignature({
180 expiresIn: tokens.data.expires_in,
181 type: tokens.data.token_type,
182 token: tokens.data.access_token,
183 });
184 this.setRefreshToken({
185 type: tokens.data.token_type,
186 token: tokens.data.refresh_token,
187 });
188 }
189 }), map((tokens) => tokens && tokens.data), switchMap((hasToken) => {
190 if (hasToken) {
191 return this.getUser();
192 }
193 return of(null);
194 }));
195 }
196 /**
197 * @return {?}
198 */
199 refreshWithSilentAuth() {
200 return new Observable((observer) => {
201 const /** @type {?} */ redirectUri = this.getCurrentOrigin('auth/silent');
202 const /** @type {?} */ uri = this.login('basic email', redirectUri);
203 const /** @type {?} */ iframe = document.createElement('iframe');
204 iframe.setAttribute('src', uri);
205 iframe.style.display = 'none';
206 iframe.addEventListener('load', () => __awaiter(this, void 0, void 0, function* () {
207 try {
208 const /** @type {?} */ queryString = iframe.contentWindow.location.search.substring(1);
209 iframe.parentNode.removeChild(iframe);
210 if (queryString) {
211 const /** @type {?} */ queryParts = queryString.split('&');
212 const /** @type {?} */ params = {};
213 for (const /** @type {?} */ item of queryParts) {
214 const /** @type {?} */ itemParts = item.split('=');
215 params[itemParts[0]] = itemParts[1];
216 }
217 if (params.hasOwnProperty('access_token')) {
218 const /** @type {?} */ state = params['state'] || null;
219 if (state !== (yield this.getState())) {
220 observer.next(null);
221 return;
222 }
223 this.setSignature({
224 token: params['access_token'],
225 type: params['token_type'],
226 expiresIn: params['ttl'],
227 });
228 const /** @type {?} */ user = yield this.getUser().toPromise();
229 if (user) {
230 this.setUser(user);
231 }
232 observer.next(user);
233 }
234 else {
235 observer.next(null);
236 }
237 return;
238 }
239 observer.next(null);
240 }
241 catch (/** @type {?} */ e) {
242 observer.next(null);
243 }
244 }), false);
245 document.body.appendChild(iframe);
246 });
247 }
248 /**
249 * @param {?} scopes
250 * @param {?=} redirectUri
251 * @return {?}
252 */
253 login(scopes, redirectUri) {
254 if (!redirectUri) {
255 redirectUri = this.router.url;
256 }
257 const /** @type {?} */ state = this.generateState();
258 this.storage.set('state', state);
259 const /** @type {?} */ query = this.buildQueryString({
260 'response_type': 'token',
261 'scopes': scopes,
262 'client': this.config.clientId,
263 'state': state,
264 'continue': encodeURIComponent(redirectUri),
265 });
266 return this.config.endpoint + '/auth?' + query;
267 }
268 /**
269 * @param {?=} redirectUri
270 * @return {?}
271 */
272 logout(redirectUri) {
273 this.signature = null;
274 this.user = null;
275 return new Promise(resolve => {
276 Promise.all([
277 this.storage.remove('signature'),
278 this.storage.remove('user'),
279 ]).then(() => {
280 let /** @type {?} */ endpoint = this.config.endpoint + '/auth/logout';
281 if (redirectUri) {
282 endpoint += '?continue=' + encodeURIComponent(redirectUri);
283 }
284 resolve(endpoint);
285 });
286 });
287 }
288 /**
289 * @return {?}
290 */
291 getState() {
292 return this.storage.get('state');
293 }
294 /**
295 * @param {?} route
296 * @return {?}
297 */
298 buildNestedUri(route) {
299 let /** @type {?} */ uri = '';
300 if (route.routeConfig && route.routeConfig.path) {
301 uri += '/' + route.routeConfig.path;
302 }
303 if (route.children) {
304 route.children.forEach((item) => {
305 uri += this.buildNestedUri(item);
306 });
307 }
308 return uri;
309 }
310 /**
311 * @return {?}
312 */
313 getRefreshToken() {
314 if (null !== this.refreshToken) {
315 return Promise.resolve(this.refreshToken);
316 }
317 return this.storage.get('refresh_token');
318 }
319 /**
320 * @return {?}
321 */
322 getClientSecret() {
323 if (null !== this.clientSecret) {
324 return Promise.resolve(this.clientSecret);
325 }
326 return this.storage.get('client_secret');
327 }
328 /**
329 * @param {?} path
330 * @return {?}
331 */
332 getUri(path) {
333 return this.config.endpoint + '/api/' + this.VERSION + path;
334 }
335 /**
336 * @param {?=} path
337 * @return {?}
338 */
339 getCurrentOrigin(path) {
340 return window.location.origin + this.location.prepareExternalUrl(path || '');
341 }
342 /**
343 * @return {?}
344 */
345 generateState() {
346 const /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
347 let /** @type {?} */ text = '';
348 for (let /** @type {?} */ i = 0; i < 5; i++) {
349 text += possible.charAt(Math.floor(Math.random() * possible.length));
350 }
351 return text;
352 }
353 /**
354 * @param {?} params
355 * @return {?}
356 */
357 buildQueryString(params) {
358 const /** @type {?} */ queryParams = Object.keys(params).map((key) => {
359 return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
360 });
361 return queryParams.join('&');
362 }
363}
364NacoService.decorators = [
365 { type: Injectable },
366];
367/** @nocollapse */
368NacoService.ctorParameters = () => [
369 { type: Config },
370 { type: Router },
371 { type: Storage },
372 { type: HttpClient },
373 { type: Location }
374];
375
376/**
377 * @fileoverview added by tsickle
378 * @suppress {checkTypes} checked by tsc
379 */
380class Signature {
381}
382
383/**
384 * @fileoverview added by tsickle
385 * @suppress {checkTypes} checked by tsc
386 */
387class AuthenticatedGuard {
388 /**
389 * @param {?} naco
390 * @param {?} storage
391 */
392 constructor(naco, storage) {
393 this.naco = naco;
394 this.storage = storage;
395 }
396 /**
397 * @param {?} route
398 * @return {?}
399 */
400 canActivate(route) {
401 return this.naco.getUser().pipe(first(), map((user) => {
402 if (null === user) {
403 const /** @type {?} */ uri = this.naco.buildNestedUri(route.root);
404 const /** @type {?} */ next = this.naco.getCurrentOrigin('/' + this.ltrim(uri));
405 this.storage.set('naco_intended_url', next).then(() => {
406 window.location.href = this.naco.login('basic email', this.naco.getCurrentOrigin('/auth'));
407 });
408 }
409 return !!user;
410 }));
411 }
412 /**
413 * @param {?} route
414 * @return {?}
415 */
416 canActivateChild(route) {
417 return this.canActivate(route);
418 }
419 /**
420 * @param {?} text
421 * @return {?}
422 */
423 ltrim(text) {
424 return text.replace(/^\/+/, '');
425 }
426 /**
427 * @param {?} text
428 * @return {?}
429 */
430 rtrim(text) {
431 return text.replace(/\/+$/, '');
432 }
433}
434AuthenticatedGuard.decorators = [
435 { type: Injectable },
436];
437/** @nocollapse */
438AuthenticatedGuard.ctorParameters = () => [
439 { type: NacoService },
440 { type: Storage }
441];
442
443/**
444 * @fileoverview added by tsickle
445 * @suppress {checkTypes} checked by tsc
446 */
447class AuthInterceptor {
448 /**
449 * @param {?} naco
450 */
451 constructor(naco) {
452 this.naco = naco;
453 }
454 /**
455 * @param {?} req
456 * @param {?} next
457 * @return {?}
458 */
459 intercept(req, next) {
460 return fromPromise(this.naco.getSignature()).pipe(switchMap((signature) => {
461 if (!signature) {
462 return next.handle(req);
463 }
464 return next
465 .handle(req.clone({
466 setHeaders: {
467 Authorization: `${signature.type} ${signature.token}`,
468 },
469 }))
470 .pipe(catchError((error) => {
471 if (error.status === 401) {
472 return this.naco.refreshUser().pipe(switchMap((user) => {
473 if (user) {
474 return fromPromise(this.naco.getSignature()).pipe(switchMap((newSignature) => {
475 return next.handle(req.clone({
476 setHeaders: {
477 Authorization: `${newSignature.type} ${newSignature.token}`,
478 },
479 }));
480 }));
481 }
482 return ErrorObservable.create(error);
483 }));
484 }
485 return ErrorObservable.create(error);
486 }));
487 }));
488 }
489}
490AuthInterceptor.decorators = [
491 { type: Injectable },
492];
493/** @nocollapse */
494AuthInterceptor.ctorParameters = () => [
495 { type: NacoService }
496];
497
498/**
499 * @fileoverview added by tsickle
500 * @suppress {checkTypes} checked by tsc
501 */
502/**
503 * @param {?} config
504 * @param {?} router
505 * @param {?} storage
506 * @param {?} http
507 * @param {?} location
508 * @return {?}
509 */
510function nacoFactory(config, router, storage, http, location) {
511 return new NacoService(new Config(Object.assign({}, config)), router, storage, http, location);
512}
513const /** @type {?} */ NACO_CONFIG = new InjectionToken('NACO_CONFIG');
514
515/**
516 * @fileoverview added by tsickle
517 * @suppress {checkTypes} checked by tsc
518 */
519class AuthPage {
520 /**
521 * @param {?} route
522 * @param {?} naco
523 * @param {?} storage
524 */
525 constructor(route, naco, storage) {
526 this.route = route;
527 this.naco = naco;
528 this.storage = storage;
529 this.message = 'Authenticating...';
530 this.route.queryParams.subscribe((params) => this.handle(params));
531 }
532 /**
533 * @param {?} params
534 * @return {?}
535 */
536 handle(params) {
537 if (params["state"]) {
538 this.naco.getState().then((state) => {
539 if (state !== params["state"]) {
540 this.message = 'Invalid CSRF';
541 return;
542 }
543 this.authenticate(params);
544 });
545 }
546 else {
547 this.authenticate(params);
548 }
549 }
550 /**
551 * @param {?} params
552 * @return {?}
553 */
554 authenticate(params) {
555 const /** @type {?} */ signature = {
556 expiresIn: params["expires_in"],
557 type: params["token_type"],
558 token: params["access_token"],
559 };
560 this.naco.setUser(null);
561 this.naco.setSignature(signature);
562 this.naco.getUser().subscribe((user) => {
563 if (null !== user) {
564 this.storage.get('naco_intended_url').then((url) => {
565 this.storage.remove('naco_intended_url').then(() => {
566 window.location.href = url ? url : '/';
567 });
568 });
569 return;
570 }
571 this.message = 'Unauthenticated!';
572 });
573 }
574}
575AuthPage.decorators = [
576 { type: Component, args: [{
577 selector: 'naker-auth-page',
578 template: '{{ message }}',
579 },] },
580];
581/** @nocollapse */
582AuthPage.ctorParameters = () => [
583 { type: ActivatedRoute },
584 { type: NacoService },
585 { type: Storage }
586];
587
588/**
589 * @fileoverview added by tsickle
590 * @suppress {checkTypes} checked by tsc
591 */
592class AuthSilentPage {
593}
594AuthSilentPage.decorators = [
595 { type: Component, args: [{
596 selector: 'naker-auth-silent',
597 template: 'Processing silent auth...',
598 },] },
599];
600
601/**
602 * @fileoverview added by tsickle
603 * @suppress {checkTypes} checked by tsc
604 */
605const /** @type {?} */ routes = [
606 {
607 path: 'auth',
608 component: AuthPage
609 },
610 {
611 path: 'auth/silent',
612 component: AuthSilentPage
613 },
614];
615const /** @type {?} */ AUTH_ROUTING = RouterModule.forChild(routes);
616
617/**
618 * @fileoverview added by tsickle
619 * @suppress {checkTypes} checked by tsc
620 */
621class NacoViewModule {
622}
623NacoViewModule.decorators = [
624 { type: NgModule, args: [{
625 imports: [
626 AUTH_ROUTING,
627 ],
628 declarations: [
629 AuthPage,
630 AuthSilentPage,
631 ],
632 },] },
633];
634
635/**
636 * @fileoverview added by tsickle
637 * @suppress {checkTypes} checked by tsc
638 */
639class NacoModule {
640 /**
641 * @param {?} config
642 * @return {?}
643 */
644 static forRoot(config) {
645 return {
646 ngModule: NacoModule,
647 providers: [
648 {
649 provide: NACO_CONFIG,
650 useValue: config,
651 },
652 {
653 provide: NacoService,
654 useFactory: nacoFactory,
655 deps: [NACO_CONFIG, Router, Storage, HttpClient, Location],
656 },
657 AuthenticatedGuard,
658 ],
659 };
660 }
661}
662NacoModule.decorators = [
663 { type: NgModule, args: [{
664 imports: [
665 UbudStorageModule,
666 NacoViewModule,
667 ],
668 },] },
669];
670
671/**
672 * @fileoverview added by tsickle
673 * @suppress {checkTypes} checked by tsc
674 */
675
676/**
677 * @fileoverview added by tsickle
678 * @suppress {checkTypes} checked by tsc
679 */
680
681export { NacoService, User, Signature, Config, AuthenticatedGuard, AuthInterceptor, NacoModule, NACO_CONFIG as ɵf, nacoFactory as ɵe, NacoViewModule as ɵa, AuthSilentPage as ɵd, AuthPage as ɵc, AUTH_ROUTING as ɵb };
682
683//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFrZXItbmFjby5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvY29uZmlnLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL21vZGVscy91c2VyLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyIsIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvc2lnbmF0dXJlLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZC50cyIsIm5nOi8vQG5ha2VyL25hY28vaW50ZXJjZXB0b3JzL2F1dGguaW50ZXJjZXB0b3IudHMiLCJuZzovL0BuYWtlci9uYWNvL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnkudHMiLCJuZzovL0BuYWtlci9uYWNvL3ZpZXdzL3BhZ2VzL2F1dGgucGFnZS50cyIsIm5nOi8vQG5ha2VyL25hY28vdmlld3MvcGFnZXMvYXV0aC1zaWxlbnQucGFnZS50cyIsIm5nOi8vQG5ha2VyL25hY28vdmlld3Mvcm91dGVzLnRzIiwibmc6Ly9AbmFrZXIvbmFjby92aWV3cy9tb2R1bGUudHMiLCJuZzovL0BuYWtlci9uYWNvL25hY28ubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBDb25maWcge1xuICAgIHB1YmxpYyBlbmRwb2ludDogc3RyaW5nID0gJ2h0dHBzOi8vYWNjb3VudC5rZW1uYWtlci5nby5pZCc7XG4gICAgcHVibGljIGNsaWVudElkOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoZGF0YT86IFBhcnRpYWw8Q29uZmlnPikge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGRhdGEpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IGZvcndhcmRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFR5cGUgfSBmcm9tICdjbGFzcy10cmFuc2Zvcm1lcic7XG5cbmV4cG9ydCBjbGFzcyBVc2VyIHtcbiAgICBwdWJsaWMgaWQ6IHN0cmluZztcbiAgICBwdWJsaWMgdXNlcm5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgZW1haWw/OiBzdHJpbmc7XG4gICAgcHVibGljIG5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgc3RhdHVzOiBudW1iZXI7XG5cbiAgICBAVHlwZShmb3J3YXJkUmVmKCgpID0+IERhdGUpIGFzIGFueSlcbiAgICBwdWJsaWMgdXBkYXRlZEF0OiBEYXRlO1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL21vZGVscy91c2VyJztcbmltcG9ydCB7IGZvcmtKb2luLCBPYnNlcnZhYmxlLCBPYnNlcnZlciwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFNpZ25hdHVyZSB9IGZyb20gJy4uL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgZnJvbVByb21pc2UgfSBmcm9tICdyeGpzL2ludGVybmFsL29ic2VydmFibGUvZnJvbVByb21pc2UnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgbWFwLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb3BlcmF0b3JzJztcbmltcG9ydCB7IHBsYWluVG9DbGFzcyB9IGZyb20gJ2NsYXNzLXRyYW5zZm9ybWVyJztcbmltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRXJyb3JPYnNlcnZhYmxlIH0gZnJvbSAncnhqcy1jb21wYXQvb2JzZXJ2YWJsZS9FcnJvck9ic2VydmFibGUnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTmFjb1NlcnZpY2Uge1xuICAgIHB1YmxpYyByZWFkb25seSBWRVJTSU9OID0gJ3YxJztcblxuICAgIHByaXZhdGUgc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIHVzZXI6IFVzZXIgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBjbGllbnRTZWNyZXQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgY29uZmlnOiBDb25maWcsIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsIHByaXZhdGUgc3RvcmFnZTogU3RvcmFnZSwgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LCBwcml2YXRlIGxvY2F0aW9uOiBMb2NhdGlvbikge1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRVc2VyKHVzZXI6IFVzZXIgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3VzZXInLCB1c2VyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0VXNlcigpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnVzZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBvZih0aGlzLnVzZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuc3RvcmFnZS5nZXQoJ3VzZXInKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgodXNlcjogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHVzZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKHVzZXIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHVyaSA9IHRoaXMuZ2V0VXJpKCcvdXNlcnMvbWUnKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBmcm9tUHJvbWlzZSh0aGlzLmdldFNpZ25hdHVyZSgpKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG51bGwgPT09IHNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlZnJlc2hVc2VyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgJHtzaWduYXR1cmUudHlwZX0gJHtzaWduYXR1cmUudG9rZW59YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8YW55Pih1cmksIG9wdGlvbnMpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXMuZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgYXJlIG5vIGJvZHkgdG8gYmUgdHJhbnNmb3JtZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhdXRoVXNlcjogYW55ID0gcGxhaW5Ub0NsYXNzKFVzZXIsIGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0VXNlcihhdXRoVXNlcik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF1dGhVc2VyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKGU6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICg0MDEgPT09IGUuc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoVXNlcigpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoTWFwKChyZWZyZXNoVXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hVc2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YocmVmcmVzaFVzZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEVycm9yT2JzZXJ2YWJsZS5jcmVhdGUoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEVycm9yT2JzZXJ2YWJsZS5jcmVhdGUoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNpZ25hdHVyZSgpOiBQcm9taXNlPFNpZ25hdHVyZSB8IG51bGw+IHtcbiAgICAgICAgaWYgKHRoaXMuc2lnbmF0dXJlKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuc2lnbmF0dXJlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0KCdzaWduYXR1cmUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0U2lnbmF0dXJlKHNpZ25hdHVyZTogU2lnbmF0dXJlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdzaWduYXR1cmUnLCBzaWduYXR1cmUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRDbGllbnRTZWNyZXQoc2VjcmV0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jbGllbnRTZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ2NsaWVudF9zZWNyZXQnLCBzZWNyZXQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRSZWZyZXNoVG9rZW4ocmVmcmVzaFRva2VuOiBTaWduYXR1cmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoVG9rZW4gPSByZWZyZXNoVG9rZW47XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3JlZnJlc2hfdG9rZW4nLCByZWZyZXNoVG9rZW4pO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZyZXNoVXNlcihzY29wZXM/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIHRoaXMuc2V0VXNlcihudWxsKTtcbiAgICAgICAgdGhpcy5zZXRTaWduYXR1cmUobnVsbCk7XG5cbiAgICAgICAgcmV0dXJuIGZvcmtKb2luKHRoaXMuZ2V0UmVmcmVzaFRva2VuKCksIHRoaXMuZ2V0Q2xpZW50U2VjcmV0KCkpLnBpcGUoXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKHJlc3VsdHM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlID0gcmVzdWx0c1swXTtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGllbnRTZWNyZXQ6IHN0cmluZyA9IHJlc3VsdHNbMV07XG5cbiAgICAgICAgICAgICAgICBpZiAocmVmcmVzaFRva2VuICYmIGNsaWVudFNlY3JldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoV2l0aFJlZnJlc2hUb2tlbihjbGllbnRTZWNyZXQsIHJlZnJlc2hUb2tlbi50b2tlbiwgc2NvcGVzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoV2l0aFNpbGVudEF1dGgoKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZyZXNoV2l0aFJlZnJlc2hUb2tlbihjbGllbnRTZWNyZXQ6IHN0cmluZywgcmVmcmVzaFRva2VuOiBzdHJpbmcsIHNjb3Blcz86IHN0cmluZyk6IE9ic2VydmFibGU8VXNlciB8IG51bGw+IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuaHR0cC5wb3N0KHRoaXMuZ2V0VXJpKCcvdG9rZW5zJyksIHtcbiAgICAgICAgICAgIGdyYW50X3R5cGU6ICdyZWZyZXNoX3Rva2VuJyxcbiAgICAgICAgICAgIHNjb3Blczogc2NvcGVzIHx8ICdiYXNpYyBlbWFpbCcsXG4gICAgICAgICAgICBjbGllbnRfaWQ6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgY2xpZW50X3NlY3JldDogY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVxdWVzdC5waXBlKFxuICAgICAgICAgICAgdGFwKCh0b2tlbnM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0b2tlbnMgJiYgdG9rZW5zLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTaWduYXR1cmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0luOiB0b2tlbnMuZGF0YS5leHBpcmVzX2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogdG9rZW5zLmRhdGEudG9rZW5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbnMuZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UmVmcmVzaFRva2VuKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHRva2Vucy5kYXRhLnRva2VuX3R5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogdG9rZW5zLmRhdGEucmVmcmVzaF90b2tlbixcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBtYXAoKHRva2VuczogYW55KSA9PiB0b2tlbnMgJiYgdG9rZW5zLmRhdGEpLFxuICAgICAgICAgICAgc3dpdGNoTWFwKChoYXNUb2tlbjogYm9vbGVhbikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChoYXNUb2tlbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRVc2VyKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZnJlc2hXaXRoU2lsZW50QXV0aCgpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4oKG9ic2VydmVyOiBPYnNlcnZlcjxVc2VyIHwgbnVsbD4pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlZGlyZWN0VXJpID0gdGhpcy5nZXRDdXJyZW50T3JpZ2luKCdhdXRoL3NpbGVudCcpO1xuICAgICAgICAgICAgY29uc3QgdXJpID0gdGhpcy5sb2dpbignYmFzaWMgZW1haWwnLCByZWRpcmVjdFVyaSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgICAgICAgICAgaWZyYW1lLnNldEF0dHJpYnV0ZSgnc3JjJywgdXJpKTtcbiAgICAgICAgICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICAgICAgICBpZnJhbWUuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWVyeVN0cmluZyA9IGlmcmFtZS5jb250ZW50V2luZG93LmxvY2F0aW9uLnNlYXJjaC5zdWJzdHJpbmcoMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWZyYW1lLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaWZyYW1lKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHF1ZXJ5UGFydHMgPSBxdWVyeVN0cmluZy5zcGxpdCgnJicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyYW1zID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBxdWVyeVBhcnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRlbVBhcnRzID0gaXRlbS5zcGxpdCgnPScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zW2l0ZW1QYXJ0c1swXV0gPSBpdGVtUGFydHNbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbXMuaGFzT3duUHJvcGVydHkoJ2FjY2Vzc190b2tlbicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdGUgPSBwYXJhbXNbJ3N0YXRlJ10gfHwgbnVsbDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZSAhPT0gYXdhaXQgdGhpcy5nZXRTdGF0ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQobnVsbCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46IHBhcmFtc1snYWNjZXNzX3Rva2VuJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHBhcmFtc1sndG9rZW5fdHlwZSddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBpcmVzSW46IHBhcmFtc1sndHRsJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5nZXRVc2VyKCkudG9Qcm9taXNlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIodXNlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCh1c2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgZmFsc2UpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGlmcmFtZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dpbihzY29wZXM6IHN0cmluZywgcmVkaXJlY3RVcmk/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICByZWRpcmVjdFVyaSA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5nZW5lcmF0ZVN0YXRlKCk7XG5cbiAgICAgICAgdGhpcy5zdG9yYWdlLnNldCgnc3RhdGUnLCBzdGF0ZSk7XG5cbiAgICAgICAgY29uc3QgcXVlcnk6IHN0cmluZyA9IHRoaXMuYnVpbGRRdWVyeVN0cmluZyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAncmVzcG9uc2VfdHlwZSc6ICd0b2tlbicsXG4gICAgICAgICAgICAgICAgJ3Njb3Blcyc6IHNjb3BlcyxcbiAgICAgICAgICAgICAgICAnY2xpZW50JzogdGhpcy5jb25maWcuY2xpZW50SWQsXG4gICAgICAgICAgICAgICAgJ3N0YXRlJzogc3RhdGUsXG4gICAgICAgICAgICAgICAgJ2NvbnRpbnVlJzogZW5jb2RlVVJJQ29tcG9uZW50KHJlZGlyZWN0VXJpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmVuZHBvaW50ICsgJy9hdXRoPycgKyBxdWVyeTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbG9nb3V0KHJlZGlyZWN0VXJpPzogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgdGhpcy5zaWduYXR1cmUgPSBudWxsO1xuICAgICAgICB0aGlzLnVzZXIgPSBudWxsO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICAgIFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCdzaWduYXR1cmUnKSxcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCd1c2VyJyksXG4gICAgICAgICAgICBdKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgZW5kcG9pbnQgPSB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aC9sb2dvdXQnO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVuZHBvaW50ICs9ICc/Y29udGludWU9JyArIGVuY29kZVVSSUNvbXBvbmVudChyZWRpcmVjdFVyaSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbmRwb2ludCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFN0YXRlKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgnc3RhdGUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYnVpbGROZXN0ZWRVcmkocm91dGU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QpOiBzdHJpbmcge1xuICAgICAgICBsZXQgdXJpID0gJyc7XG5cbiAgICAgICAgaWYgKHJvdXRlLnJvdXRlQ29uZmlnICYmIHJvdXRlLnJvdXRlQ29uZmlnLnBhdGgpIHtcbiAgICAgICAgICAgIHVyaSArPSAnLycgKyByb3V0ZS5yb3V0ZUNvbmZpZy5wYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJvdXRlLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICByb3V0ZS5jaGlsZHJlbi5mb3JFYWNoKChpdGVtOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gICAgICAgICAgICAgICAgdXJpICs9IHRoaXMuYnVpbGROZXN0ZWRVcmkoaXRlbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1cmk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWZyZXNoVG9rZW4oKTogUHJvbWlzZTxTaWduYXR1cmUgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLnJlZnJlc2hUb2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgncmVmcmVzaF90b2tlbicpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q2xpZW50U2VjcmV0KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy5jbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5jbGllbnRTZWNyZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ2NsaWVudF9zZWNyZXQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFVyaShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2FwaS8nICsgdGhpcy5WRVJTSU9OICsgcGF0aDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Q3VycmVudE9yaWdpbihwYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB0aGlzLmxvY2F0aW9uLnByZXBhcmVFeHRlcm5hbFVybChwYXRoIHx8ICcnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU3RhdGUoKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcG9zc2libGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICAgICAgICBsZXQgdGV4dCA9ICcnO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICB0ZXh0ICs9IHBvc3NpYmxlLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBwb3NzaWJsZS5sZW5ndGgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRRdWVyeVN0cmluZyhwYXJhbXM6IG9iamVjdCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocGFyYW1zKS5tYXAoKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXMuam9pbignJicpO1xuICAgIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBTaWduYXR1cmUge1xuICAgIHB1YmxpYyBleHBpcmVzSW4/OiBudW1iZXI7XG4gICAgcHVibGljIHRva2VuOiBzdHJpbmc7XG4gICAgcHVibGljIHR5cGU6IHN0cmluZztcbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENhbkFjdGl2YXRlLCBDYW5BY3RpdmF0ZUNoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE5hY29TZXJ2aWNlIH0gZnJvbSAnLi4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgZmlyc3QsIG1hcCB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb3BlcmF0b3JzJztcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi9kb21haW5zL21vZGVscy91c2VyJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlU25hcHNob3QgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXIvc3JjL3JvdXRlcl9zdGF0ZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdXRoZW50aWNhdGVkR3VhcmQgaW1wbGVtZW50cyBDYW5BY3RpdmF0ZSwgQ2FuQWN0aXZhdGVDaGlsZCB7XG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgbmFjbzogTmFjb1NlcnZpY2UsIHByaXZhdGUgc3RvcmFnZTogU3RvcmFnZSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5BY3RpdmF0ZShyb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5uYWNvLmdldFVzZXIoKS5waXBlKFxuICAgICAgICAgICAgZmlyc3QoKSxcbiAgICAgICAgICAgIG1hcCgodXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobnVsbCA9PT0gdXNlcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmkgPSB0aGlzLm5hY28uYnVpbGROZXN0ZWRVcmkocm91dGUucm9vdCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLm5hY28uZ2V0Q3VycmVudE9yaWdpbignLycgKyB0aGlzLmx0cmltKHVyaSkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ25hY29faW50ZW5kZWRfdXJsJywgbmV4dCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHRoaXMubmFjby5sb2dpbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYmFzaWMgZW1haWwnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmFjby5nZXRDdXJyZW50T3JpZ2luKCcvYXV0aCcpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuICEhdXNlcjtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5BY3RpdmF0ZUNoaWxkKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbkFjdGl2YXRlKHJvdXRlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGx0cmltKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoL15cXC8rLywnJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBydHJpbSh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC9cXC8rJC8sJycpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEh0dHBFcnJvclJlc3BvbnNlLCBIdHRwRXZlbnQsIEh0dHBIYW5kbGVyLCBIdHRwSW50ZXJjZXB0b3IsIEh0dHBSZXF1ZXN0IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBmcm9tUHJvbWlzZSB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb2JzZXJ2YWJsZS9mcm9tUHJvbWlzZSc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi9kb21haW5zL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRXJyb3JPYnNlcnZhYmxlIH0gZnJvbSAncnhqcy1jb21wYXQvb2JzZXJ2YWJsZS9FcnJvck9ic2VydmFibGUnO1xuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aEludGVyY2VwdG9yIGltcGxlbWVudHMgSHR0cEludGVyY2VwdG9yIHtcbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSBuYWNvOiBOYWNvU2VydmljZSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBpbnRlcmNlcHQocmVxOiBIdHRwUmVxdWVzdDxhbnk+LCBuZXh0OiBIdHRwSGFuZGxlcik6IE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+IHtcbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMubmFjby5nZXRTaWduYXR1cmUoKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFzaWduYXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5leHRcbiAgICAgICAgICAgICAgICAgICAgLmhhbmRsZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcS5jbG9uZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0SGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgJHtzaWduYXR1cmUudHlwZX0gJHtzaWduYXR1cmUudG9rZW59YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaEVycm9yKChlcnJvcjogSHR0cEVycm9yUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFjby5yZWZyZXNoVXNlcigpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHVzZXI6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmcm9tUHJvbWlzZSh0aGlzLm5hY28uZ2V0U2lnbmF0dXJlKCkpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKG5ld1NpZ25hdHVyZTogU2lnbmF0dXJlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXEuY2xvbmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0SGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGAke25ld1NpZ25hdHVyZS50eXBlfSAke25ld1NpZ25hdHVyZS50b2tlbn1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBFcnJvck9ic2VydmFibGUuY3JlYXRlKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBFcnJvck9ic2VydmFibGUuY3JlYXRlKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBDb25maWcgfSBmcm9tICcuLi9kb21haW5zL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5leHBvcnQgZnVuY3Rpb24gbmFjb0ZhY3RvcnkoY29uZmlnOiBvYmplY3QsIHJvdXRlcjogUm91dGVyLCBzdG9yYWdlOiBTdG9yYWdlLCBodHRwOiBIdHRwQ2xpZW50LCBsb2NhdGlvbjogTG9jYXRpb24pIHtcbiAgICByZXR1cm4gbmV3IE5hY29TZXJ2aWNlKFxuICAgICAgICBuZXcgQ29uZmlnKHsgLi4uY29uZmlnIH0pLFxuICAgICAgICByb3V0ZXIsXG4gICAgICAgIHN0b3JhZ2UsXG4gICAgICAgIGh0dHAsXG4gICAgICAgIGxvY2F0aW9uXG4gICAgKTtcbn1cblxuZXhwb3J0IGNvbnN0IE5BQ09fQ09ORklHID0gbmV3IEluamVjdGlvblRva2VuPG9iamVjdD4oJ05BQ09fQ09ORklHJyk7XG4iLCJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBQYXJhbXMgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi8uLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi8uLi9kb21haW5zL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uLy4uL2RvbWFpbnMvbW9kZWxzL3VzZXInO1xuaW1wb3J0IHsgU3RvcmFnZSB9IGZyb20gJ0B1YnVkL3N0b3JhZ2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ25ha2VyLWF1dGgtcGFnZScsXG4gICAgdGVtcGxhdGU6ICd7eyBtZXNzYWdlIH19Jyxcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFBhZ2Uge1xuICAgIHB1YmxpYyBtZXNzYWdlOiBzdHJpbmcgPSAnQXV0aGVudGljYXRpbmcuLi4nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLCBwcml2YXRlIG5hY286IE5hY29TZXJ2aWNlLCBwcml2YXRlIHN0b3JhZ2U6IFN0b3JhZ2UpIHtcbiAgICAgICAgdGhpcy5yb3V0ZS5xdWVyeVBhcmFtcy5zdWJzY3JpYmUoKHBhcmFtczogUGFyYW1zKSA9PiB0aGlzLmhhbmRsZShwYXJhbXMpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGFuZGxlKHBhcmFtczogUGFyYW1zKTogdm9pZCB7XG4gICAgICAgIGlmIChwYXJhbXMuc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMubmFjby5nZXRTdGF0ZSgpLnRoZW4oKHN0YXRlOiBzdHJpbmcgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlICE9PSBwYXJhbXMuc3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gJ0ludmFsaWQgQ1NSRic7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuYXV0aGVudGljYXRlKHBhcmFtcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYXV0aGVudGljYXRlKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGF1dGhlbnRpY2F0ZShwYXJhbXM6IFBhcmFtcyk6IHZvaWQge1xuICAgICAgICBjb25zdCBzaWduYXR1cmU6IFNpZ25hdHVyZSA9IHtcbiAgICAgICAgICAgIGV4cGlyZXNJbjogcGFyYW1zLmV4cGlyZXNfaW4sXG4gICAgICAgICAgICB0eXBlOiBwYXJhbXMudG9rZW5fdHlwZSxcbiAgICAgICAgICAgIHRva2VuOiBwYXJhbXMuYWNjZXNzX3Rva2VuLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMubmFjby5zZXRVc2VyKG51bGwpO1xuICAgICAgICB0aGlzLm5hY28uc2V0U2lnbmF0dXJlKHNpZ25hdHVyZSk7XG5cbiAgICAgICAgdGhpcy5uYWNvLmdldFVzZXIoKS5zdWJzY3JpYmUoKHVzZXI6IFVzZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICBpZiAobnVsbCAhPT0gdXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5nZXQoJ25hY29faW50ZW5kZWRfdXJsJykudGhlbigodXJsOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgnbmFjb19pbnRlbmRlZF91cmwnKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsID8gdXJsIDogJy8nO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gJ1VuYXV0aGVudGljYXRlZCEnO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbiIsImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ25ha2VyLWF1dGgtc2lsZW50JyxcbiAgICB0ZW1wbGF0ZTogJ1Byb2Nlc3Npbmcgc2lsZW50IGF1dGguLi4nLFxufSlcbmV4cG9ydCBjbGFzcyBBdXRoU2lsZW50UGFnZSB7XG59XG4iLCJpbXBvcnQgeyBNb2R1bGVXaXRoUHJvdmlkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUsIFJvdXRlcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBBdXRoUGFnZSB9IGZyb20gJy4vcGFnZXMvYXV0aC5wYWdlJztcbmltcG9ydCB7IEF1dGhTaWxlbnRQYWdlIH0gZnJvbSAnLi9wYWdlcy9hdXRoLXNpbGVudC5wYWdlJztcblxuY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gICAge1xuICAgICAgICBwYXRoOiAnYXV0aCcsXG4gICAgICAgIGNvbXBvbmVudDogQXV0aFBhZ2VcbiAgICB9LFxuICAgIHtcbiAgICAgICAgcGF0aDogJ2F1dGgvc2lsZW50JyxcbiAgICAgICAgY29tcG9uZW50OiBBdXRoU2lsZW50UGFnZVxuICAgIH0sXG5dO1xuXG5leHBvcnQgY29uc3QgQVVUSF9ST1VUSU5HOiBNb2R1bGVXaXRoUHJvdmlkZXJzID0gUm91dGVyTW9kdWxlLmZvckNoaWxkKHJvdXRlcyk7XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQVVUSF9ST1VUSU5HIH0gZnJvbSAnLi9yb3V0ZXMnO1xuaW1wb3J0IHsgQXV0aFBhZ2UgfSBmcm9tICcuL3BhZ2VzL2F1dGgucGFnZSc7XG5pbXBvcnQgeyBBdXRoU2lsZW50UGFnZSB9IGZyb20gJy4vcGFnZXMvYXV0aC1zaWxlbnQucGFnZSc7XG5cbkBOZ01vZHVsZSh7XG4gICAgaW1wb3J0czogW1xuICAgICAgICBBVVRIX1JPVVRJTkcsXG4gICAgXSxcbiAgICBkZWNsYXJhdGlvbnM6IFtcbiAgICAgICAgQXV0aFBhZ2UsXG4gICAgICAgIEF1dGhTaWxlbnRQYWdlLFxuICAgIF0sXG59KVxuZXhwb3J0IGNsYXNzIE5hY29WaWV3TW9kdWxlIHtcbn1cbiIsImltcG9ydCB7IE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOYWNvU2VydmljZSB9IGZyb20gJy4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXV0aGVudGljYXRlZEd1YXJkIH0gZnJvbSAnLi9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZCc7XG5pbXBvcnQgeyBOQUNPX0NPTkZJRywgbmFjb0ZhY3RvcnkgfSBmcm9tICcuL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnknO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UsIFVidWRTdG9yYWdlTW9kdWxlIH0gZnJvbSAnQHVidWQvc3RvcmFnZSc7XG5pbXBvcnQgeyBOYWNvVmlld01vZHVsZSB9IGZyb20gJy4vdmlld3MvbW9kdWxlJztcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbkBOZ01vZHVsZSh7XG4gICAgaW1wb3J0czogW1xuICAgICAgICBVYnVkU3RvcmFnZU1vZHVsZSxcbiAgICAgICAgTmFjb1ZpZXdNb2R1bGUsXG4gICAgXSxcbn0pXG5leHBvcnQgY2xhc3MgTmFjb01vZHVsZSB7XG4gICAgcHVibGljIHN0YXRpYyBmb3JSb290KGNvbmZpZzogeyBjbGllbnRJZDogc3RyaW5nLCBlbmRwb2ludD86IHN0cmluZyB9KTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuZ01vZHVsZTogTmFjb01vZHVsZSxcbiAgICAgICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZTogTkFDT19DT05GSUcsXG4gICAgICAgICAgICAgICAgICAgIHVzZVZhbHVlOiBjb25maWcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGU6IE5hY29TZXJ2aWNlLFxuICAgICAgICAgICAgICAgICAgICB1c2VGYWN0b3J5OiBuYWNvRmFjdG9yeSxcbiAgICAgICAgICAgICAgICAgICAgZGVwczogW05BQ09fQ09ORklHLCBSb3V0ZXIsIFN0b3JhZ2UsIEh0dHBDbGllbnQsIExvY2F0aW9uXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIEF1dGhlbnRpY2F0ZWRHdWFyZCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgfVxufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7OztnQkFJdUIsSUFBc0I7d0JBSGYsZ0NBQWdDO1FBSXRELE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxD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
\No newline at end of file