UNPKG

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