UNPKG

54 kBJavaScriptView Raw
1import { __decorate, __metadata } 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, of } from 'rxjs';
7import { fromPromise } from 'rxjs/internal/observable/fromPromise';
8import { map, switchMap, tap, first, catchError } from 'rxjs/internal/operators';
9import { HttpClient } from '@angular/common/http';
10import { PlatformLocation } 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 */
49 constructor(config, router, storage, http) {
50 this.config = config;
51 this.router = router;
52 this.storage = storage;
53 this.http = http;
54 this.VERSION = 'v1';
55 this.signature = null;
56 this.user = null;
57 this.refreshToken = null;
58 this.clientSecret = null;
59 }
60 /**
61 * @param {?} user
62 * @return {?}
63 */
64 setUser(user) {
65 this.user = user;
66 this.storage.set('user', user);
67 }
68 /**
69 * @return {?}
70 */
71 getUser() {
72 if (null !== this.user) {
73 return of(this.user);
74 }
75 return fromPromise(this.storage.get('user')).pipe(switchMap((user) => {
76 if (null !== user) {
77 return of(user);
78 }
79 const /** @type {?} */ uri = this.getUri('/users/me');
80 return fromPromise(this.getSignature()).pipe(switchMap((signature) => {
81 if (null === signature) {
82 return of(null);
83 }
84 const /** @type {?} */ options = {
85 headers: {
86 Authorization: `${signature.type} ${signature.token}`,
87 },
88 };
89 return this.http.get(uri, options).pipe(map((res) => {
90 if (res.data) {
91 return res.data;
92 }
93 throw new Error('There are no body to be transformed');
94 }), map((data) => {
95 const /** @type {?} */ authUser = plainToClass(User, data);
96 this.setUser(authUser);
97 return authUser;
98 }));
99 }));
100 }));
101 }
102 /**
103 * @return {?}
104 */
105 getSignature() {
106 if (null !== this.signature) {
107 return Promise.resolve(this.signature);
108 }
109 return this.storage.get('signature');
110 }
111 /**
112 * @param {?} signature
113 * @return {?}
114 */
115 setSignature(signature) {
116 this.signature = signature;
117 this.storage.set('signature', signature);
118 }
119 /**
120 * @param {?} secret
121 * @return {?}
122 */
123 setClientSecret(secret) {
124 this.clientSecret = secret;
125 this.storage.set('client_secret', secret);
126 }
127 /**
128 * @param {?} refreshToken
129 * @return {?}
130 */
131 setRefreshToken(refreshToken) {
132 this.refreshToken = refreshToken;
133 this.storage.set('refresh_token', refreshToken);
134 }
135 /**
136 * @param {?=} scopes
137 * @return {?}
138 */
139 refreshUser(scopes) {
140 this.setUser(null);
141 this.setSignature(null);
142 return forkJoin(this.getRefreshToken(), this.getClientSecret()).pipe(switchMap((results) => {
143 const /** @type {?} */ refreshToken = results[0];
144 const /** @type {?} */ clientSecret = results[1];
145 if (refreshToken && clientSecret) {
146 const /** @type {?} */ request = this.http.post(this.getUri('/tokens'), {
147 grant_type: 'refresh_token',
148 scopes: scopes || 'basic email',
149 client_id: this.config.clientId,
150 client_secret: clientSecret,
151 refresh_token: refreshToken.token,
152 });
153 return request.pipe(tap((tokens) => {
154 if (tokens && tokens.data) {
155 this.setSignature({
156 expiresIn: tokens.data.expires_in,
157 type: tokens.data.token_type,
158 token: tokens.data.access_token,
159 });
160 this.setRefreshToken({
161 type: tokens.data.token_type,
162 token: tokens.data.refresh_token,
163 });
164 }
165 }), map((tokens) => tokens && tokens.data), switchMap((hasToken) => {
166 if (hasToken) {
167 return this.getUser();
168 }
169 return of(null);
170 }));
171 }
172 return of(null);
173 }));
174 }
175 /**
176 * @param {?} scopes
177 * @param {?=} redirectUri
178 * @return {?}
179 */
180 login(scopes, redirectUri) {
181 if (!redirectUri) {
182 redirectUri = this.router.url;
183 }
184 const /** @type {?} */ state = this.generateState();
185 this.storage.set('state', state);
186 const /** @type {?} */ query = this.buildQueryString({
187 'response_type': 'token',
188 'scopes': scopes,
189 'client': this.config.clientId,
190 'state': state,
191 'continue': redirectUri,
192 });
193 return this.config.endpoint + '/auth?' + query;
194 }
195 /**
196 * @param {?=} redirectUri
197 * @return {?}
198 */
199 logout(redirectUri) {
200 this.signature = null;
201 this.user = null;
202 return new Promise(resolve => {
203 Promise.all([
204 this.storage.remove('signature'),
205 this.storage.remove('user'),
206 ]).then(() => {
207 let /** @type {?} */ endpoint = this.config.endpoint + '/auth/logout';
208 if (redirectUri) {
209 endpoint += '?continue=' + redirectUri;
210 }
211 resolve(endpoint);
212 });
213 });
214 }
215 /**
216 * @return {?}
217 */
218 getState() {
219 return this.storage.get('state');
220 }
221 /**
222 * @param {?} route
223 * @return {?}
224 */
225 buildNestedUri(route) {
226 let /** @type {?} */ uri = '';
227 if (route.routeConfig && route.routeConfig.path) {
228 uri += '/' + route.routeConfig.path;
229 }
230 if (route.children) {
231 route.children.forEach((item) => {
232 uri += this.buildNestedUri(item);
233 });
234 }
235 return uri;
236 }
237 /**
238 * @return {?}
239 */
240 getRefreshToken() {
241 if (null !== this.refreshToken) {
242 return Promise.resolve(this.refreshToken);
243 }
244 return this.storage.get('refresh_token');
245 }
246 /**
247 * @return {?}
248 */
249 getClientSecret() {
250 if (null !== this.clientSecret) {
251 return Promise.resolve(this.clientSecret);
252 }
253 return this.storage.get('client_secret');
254 }
255 /**
256 * @param {?} path
257 * @return {?}
258 */
259 getUri(path) {
260 return this.config.endpoint + '/api/' + this.VERSION + path;
261 }
262 /**
263 * @return {?}
264 */
265 generateState() {
266 const /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
267 let /** @type {?} */ text = '';
268 for (let /** @type {?} */ i = 0; i < 5; i++) {
269 text += possible.charAt(Math.floor(Math.random() * possible.length));
270 }
271 return text;
272 }
273 /**
274 * @param {?} params
275 * @return {?}
276 */
277 buildQueryString(params) {
278 const /** @type {?} */ queryParams = Object.keys(params).map((key) => {
279 return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
280 });
281 return queryParams.join('&');
282 }
283}
284NacoService.decorators = [
285 { type: Injectable },
286];
287/** @nocollapse */
288NacoService.ctorParameters = () => [
289 { type: Config },
290 { type: Router },
291 { type: Storage },
292 { type: HttpClient }
293];
294
295/**
296 * @fileoverview added by tsickle
297 * @suppress {checkTypes} checked by tsc
298 */
299class Signature {
300}
301
302/**
303 * @fileoverview added by tsickle
304 * @suppress {checkTypes} checked by tsc
305 */
306class AuthenticatedGuard {
307 /**
308 * @param {?} naco
309 * @param {?} storage
310 * @param {?} platformLocation
311 */
312 constructor(naco, storage, platformLocation) {
313 this.naco = naco;
314 this.storage = storage;
315 this.platformLocation = platformLocation;
316 }
317 /**
318 * @param {?} route
319 * @return {?}
320 */
321 canActivate(route) {
322 return this.naco.getUser().pipe(first(), map((user) => {
323 if (null === user) {
324 const /** @type {?} */ base = this.rtrim((/** @type {?} */ (this.platformLocation)).location.href);
325 const /** @type {?} */ uri = this.naco.buildNestedUri(route.root);
326 const /** @type {?} */ next = base.replace(uri, '') + '/' + this.ltrim(uri);
327 const /** @type {?} */ origin = base.replace(uri, '');
328 this.storage.set('naco_intended_url', next).then(() => {
329 window.location.href = this.naco.login('basic email', origin + '/auth');
330 });
331 }
332 return !!user;
333 }));
334 }
335 /**
336 * @param {?} route
337 * @return {?}
338 */
339 canActivateChild(route) {
340 return this.canActivate(route);
341 }
342 /**
343 * @param {?} text
344 * @return {?}
345 */
346 ltrim(text) {
347 return text.replace(/^\/+/, '');
348 }
349 /**
350 * @param {?} text
351 * @return {?}
352 */
353 rtrim(text) {
354 return text.replace(/\/+$/, '');
355 }
356}
357AuthenticatedGuard.decorators = [
358 { type: Injectable },
359];
360/** @nocollapse */
361AuthenticatedGuard.ctorParameters = () => [
362 { type: NacoService },
363 { type: Storage },
364 { type: PlatformLocation }
365];
366
367/**
368 * @fileoverview added by tsickle
369 * @suppress {checkTypes} checked by tsc
370 */
371class AuthInterceptor {
372 /**
373 * @param {?} naco
374 */
375 constructor(naco) {
376 this.naco = naco;
377 }
378 /**
379 * @param {?} req
380 * @param {?} next
381 * @return {?}
382 */
383 intercept(req, next) {
384 return fromPromise(this.naco.getSignature()).pipe(switchMap((signature) => {
385 if (!signature) {
386 return next.handle(req);
387 }
388 return next
389 .handle(req.clone({
390 setHeaders: {
391 Authorization: `${signature.type} ${signature.token}`,
392 },
393 }))
394 .pipe(catchError((error) => {
395 if (error.status === 401) {
396 return this.naco.refreshUser().pipe(switchMap(() => fromPromise(this.naco.getSignature())), switchMap((newSignature) => {
397 return next.handle(req.clone({
398 setHeaders: {
399 Authorization: `${newSignature.type} ${newSignature.token}`,
400 },
401 }));
402 }));
403 }
404 return ErrorObservable.create(error);
405 }));
406 }));
407 }
408}
409AuthInterceptor.decorators = [
410 { type: Injectable },
411];
412/** @nocollapse */
413AuthInterceptor.ctorParameters = () => [
414 { type: NacoService }
415];
416
417/**
418 * @fileoverview added by tsickle
419 * @suppress {checkTypes} checked by tsc
420 */
421/**
422 * @param {?} config
423 * @param {?} router
424 * @param {?} storage
425 * @param {?} http
426 * @return {?}
427 */
428function nacoFactory(config, router, storage, http) {
429 return new NacoService(new Config(Object.assign({}, config)), router, storage, http);
430}
431const /** @type {?} */ NACO_CONFIG = new InjectionToken('NACO_CONFIG');
432
433/**
434 * @fileoverview added by tsickle
435 * @suppress {checkTypes} checked by tsc
436 */
437class AuthPage {
438 /**
439 * @param {?} route
440 * @param {?} naco
441 * @param {?} storage
442 */
443 constructor(route, naco, storage) {
444 this.route = route;
445 this.naco = naco;
446 this.storage = storage;
447 this.message = 'Authenticating...';
448 this.route.queryParams.subscribe((params) => this.handle(params));
449 }
450 /**
451 * @param {?} params
452 * @return {?}
453 */
454 handle(params) {
455 if (params["state"]) {
456 this.naco.getState().then((state) => {
457 if (state !== params["state"]) {
458 this.message = 'Invalid CSRF';
459 return;
460 }
461 this.authenticate(params);
462 });
463 }
464 else {
465 this.authenticate(params);
466 }
467 }
468 /**
469 * @param {?} params
470 * @return {?}
471 */
472 authenticate(params) {
473 const /** @type {?} */ signature = {
474 expiresIn: params["expires_in"],
475 type: params["token_type"],
476 token: params["access_token"],
477 };
478 this.naco.setSignature(signature);
479 this.naco.getUser().subscribe((user) => {
480 if (null !== user) {
481 this.storage.get('naco_intended_url').then((url) => {
482 this.storage.remove('naco_intended_url').then(() => {
483 window.location.href = url ? url : '/';
484 });
485 });
486 return;
487 }
488 this.message = 'Unauthenticated!';
489 });
490 }
491}
492AuthPage.decorators = [
493 { type: Component, args: [{
494 selector: 'naker-auth-page',
495 template: '{{ message }}',
496 },] },
497];
498/** @nocollapse */
499AuthPage.ctorParameters = () => [
500 { type: ActivatedRoute },
501 { type: NacoService },
502 { type: Storage }
503];
504
505/**
506 * @fileoverview added by tsickle
507 * @suppress {checkTypes} checked by tsc
508 */
509const /** @type {?} */ routes = [
510 {
511 path: 'auth',
512 component: AuthPage
513 },
514];
515const /** @type {?} */ AUTH_ROUTING = RouterModule.forChild(routes);
516
517/**
518 * @fileoverview added by tsickle
519 * @suppress {checkTypes} checked by tsc
520 */
521class NacoViewModule {
522}
523NacoViewModule.decorators = [
524 { type: NgModule, args: [{
525 imports: [
526 AUTH_ROUTING,
527 ],
528 declarations: [
529 AuthPage,
530 ],
531 },] },
532];
533
534/**
535 * @fileoverview added by tsickle
536 * @suppress {checkTypes} checked by tsc
537 */
538class NacoModule {
539 /**
540 * @param {?} config
541 * @return {?}
542 */
543 static forRoot(config) {
544 return {
545 ngModule: NacoModule,
546 providers: [
547 {
548 provide: NACO_CONFIG,
549 useValue: config,
550 },
551 {
552 provide: NacoService,
553 useFactory: nacoFactory,
554 deps: [NACO_CONFIG, Router, Storage, HttpClient],
555 },
556 AuthenticatedGuard,
557 ],
558 };
559 }
560}
561NacoModule.decorators = [
562 { type: NgModule, args: [{
563 imports: [
564 UbudStorageModule,
565 NacoViewModule,
566 ],
567 },] },
568];
569
570/**
571 * @fileoverview added by tsickle
572 * @suppress {checkTypes} checked by tsc
573 */
574
575/**
576 * @fileoverview added by tsickle
577 * @suppress {checkTypes} checked by tsc
578 */
579
580export { NacoService, User, Signature, Config, AuthenticatedGuard, AuthInterceptor, NacoModule, NACO_CONFIG as ɵe, nacoFactory as ɵd, NacoViewModule as ɵa, AuthPage as ɵc, AUTH_ROUTING as ɵb };
581
582//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFrZXItbmFjby5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvY29uZmlnLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL21vZGVscy91c2VyLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyIsIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvc2lnbmF0dXJlLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZC50cyIsIm5nOi8vQG5ha2VyL25hY28vaW50ZXJjZXB0b3JzL2F1dGguaW50ZXJjZXB0b3IudHMiLCJuZzovL0BuYWtlci9uYWNvL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnkudHMiLCJuZzovL0BuYWtlci9uYWNvL3ZpZXdzL3BhZ2VzL2F1dGgucGFnZS50cyIsIm5nOi8vQG5ha2VyL25hY28vdmlld3Mvcm91dGVzLnRzIiwibmc6Ly9AbmFrZXIvbmFjby92aWV3cy9tb2R1bGUudHMiLCJuZzovL0BuYWtlci9uYWNvL25hY28ubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBDb25maWcge1xuICAgIHB1YmxpYyBlbmRwb2ludDogc3RyaW5nID0gJ2h0dHBzOi8vYWNjb3VudC5rZW1uYWtlci5nby5pZCc7XG4gICAgcHVibGljIGNsaWVudElkOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoZGF0YT86IFBhcnRpYWw8Q29uZmlnPikge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGRhdGEpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IGZvcndhcmRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFR5cGUgfSBmcm9tICdjbGFzcy10cmFuc2Zvcm1lcic7XG5cbmV4cG9ydCBjbGFzcyBVc2VyIHtcbiAgICBwdWJsaWMgaWQ6IHN0cmluZztcbiAgICBwdWJsaWMgdXNlcm5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgZW1haWw/OiBzdHJpbmc7XG4gICAgcHVibGljIG5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgc3RhdHVzOiBudW1iZXI7XG5cbiAgICBAVHlwZShmb3J3YXJkUmVmKCgpID0+IERhdGUpIGFzIGFueSlcbiAgICBwdWJsaWMgdXBkYXRlZEF0OiBEYXRlO1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL21vZGVscy91c2VyJztcbmltcG9ydCB7IGZvcmtKb2luLCBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgU2lnbmF0dXJlIH0gZnJvbSAnLi4vdmFsdWVzL3NpZ25hdHVyZSc7XG5pbXBvcnQgeyBmcm9tUHJvbWlzZSB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb2JzZXJ2YWJsZS9mcm9tUHJvbWlzZSc7XG5pbXBvcnQgeyBtYXAsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgcGxhaW5Ub0NsYXNzIH0gZnJvbSAnY2xhc3MtdHJhbnNmb3JtZXInO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5hY29TZXJ2aWNlIHtcbiAgICBwdWJsaWMgcmVhZG9ubHkgVkVSU0lPTiA9ICd2MSc7XG5cbiAgICBwcml2YXRlIHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSB1c2VyOiBVc2VyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgY2xpZW50U2VjcmV0OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZzogQ29uZmlnLCBwcml2YXRlIHJvdXRlcjogUm91dGVyLCBwcml2YXRlIHN0b3JhZ2U6IFN0b3JhZ2UsIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCkge1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRVc2VyKHVzZXI6IFVzZXIgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3VzZXInLCB1c2VyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0VXNlcigpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnVzZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBvZih0aGlzLnVzZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuc3RvcmFnZS5nZXQoJ3VzZXInKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgodXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobnVsbCAhPT0gdXNlcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YodXNlcik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgdXJpID0gdGhpcy5nZXRVcmkoJy91c2Vycy9tZScpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuZ2V0U2lnbmF0dXJlKCkpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobnVsbCA9PT0gc2lnbmF0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogYCR7c2lnbmF0dXJlLnR5cGV9ICR7c2lnbmF0dXJlLnRva2VufWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PGFueT4odXJpLCBvcHRpb25zKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcy5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzLmRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGFyZSBubyBib2R5IHRvIGJlIHRyYW5zZm9ybWVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChkYXRhOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV0aFVzZXI6IGFueSA9IHBsYWluVG9DbGFzcyhVc2VyLCBkYXRhKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIoYXV0aFVzZXIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhdXRoVXNlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2lnbmF0dXJlKCk6IFByb21pc2U8U2lnbmF0dXJlIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy5zaWduYXR1cmUpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5zaWduYXR1cmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ3NpZ25hdHVyZScpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRTaWduYXR1cmUoc2lnbmF0dXJlOiBTaWduYXR1cmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zaWduYXR1cmUgPSBzaWduYXR1cmU7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3NpZ25hdHVyZScsIHNpZ25hdHVyZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldENsaWVudFNlY3JldChzZWNyZXQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmNsaWVudFNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgdGhpcy5zdG9yYWdlLnNldCgnY2xpZW50X3NlY3JldCcsIHNlY3JldCk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFJlZnJlc2hUb2tlbihyZWZyZXNoVG9rZW46IFNpZ25hdHVyZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlZnJlc2hUb2tlbiA9IHJlZnJlc2hUb2tlbjtcbiAgICAgICAgdGhpcy5zdG9yYWdlLnNldCgncmVmcmVzaF90b2tlbicsIHJlZnJlc2hUb2tlbik7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZnJlc2hVc2VyKHNjb3Blcz86IHN0cmluZyk6IE9ic2VydmFibGU8VXNlciB8IG51bGw+IHtcbiAgICAgICAgdGhpcy5zZXRVc2VyKG51bGwpO1xuICAgICAgICB0aGlzLnNldFNpZ25hdHVyZShudWxsKTtcblxuICAgICAgICByZXR1cm4gZm9ya0pvaW4odGhpcy5nZXRSZWZyZXNoVG9rZW4oKSwgdGhpcy5nZXRDbGllbnRTZWNyZXQoKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgocmVzdWx0czogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVmcmVzaFRva2VuOiBTaWduYXR1cmUgPSByZXN1bHRzWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNsaWVudFNlY3JldDogc3RyaW5nID0gcmVzdWx0c1sxXTtcblxuICAgICAgICAgICAgICAgIGlmIChyZWZyZXNoVG9rZW4gJiYgY2xpZW50U2VjcmV0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLmh0dHAucG9zdCh0aGlzLmdldFVyaSgnL3Rva2VucycpLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZXM6IHNjb3BlcyB8fCAnYmFzaWMgZW1haWwnLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2xpZW50X2lkOiB0aGlzLmNvbmZpZy5jbGllbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWVudF9zZWNyZXQ6IGNsaWVudFNlY3JldCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZnJlc2hfdG9rZW46IHJlZnJlc2hUb2tlbi50b2tlbixcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcXVlc3QucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhcCgodG9rZW5zOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodG9rZW5zICYmIHRva2Vucy5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGlyZXNJbjogdG9rZW5zLmRhdGEuZXhwaXJlc19pbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHRva2Vucy5kYXRhLnRva2VuX3R5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogdG9rZW5zLmRhdGEuYWNjZXNzX3Rva2VuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFJlZnJlc2hUb2tlbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiB0b2tlbnMuZGF0YS50b2tlbl90eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46IHRva2Vucy5kYXRhLnJlZnJlc2hfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFwKCh0b2tlbnM6IGFueSkgPT4gdG9rZW5zICYmIHRva2Vucy5kYXRhKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoaGFzVG9rZW46IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGFzVG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VXNlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dpbihzY29wZXM6IHN0cmluZywgcmVkaXJlY3RVcmk/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICByZWRpcmVjdFVyaSA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5nZW5lcmF0ZVN0YXRlKCk7XG5cbiAgICAgICAgdGhpcy5zdG9yYWdlLnNldCgnc3RhdGUnLCBzdGF0ZSk7XG5cbiAgICAgICAgY29uc3QgcXVlcnk6IHN0cmluZyA9IHRoaXMuYnVpbGRRdWVyeVN0cmluZyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAncmVzcG9uc2VfdHlwZSc6ICd0b2tlbicsXG4gICAgICAgICAgICAgICAgJ3Njb3Blcyc6IHNjb3BlcyxcbiAgICAgICAgICAgICAgICAnY2xpZW50JzogdGhpcy5jb25maWcuY2xpZW50SWQsXG4gICAgICAgICAgICAgICAgJ3N0YXRlJzogc3RhdGUsXG4gICAgICAgICAgICAgICAgJ2NvbnRpbnVlJzogcmVkaXJlY3RVcmksXG4gICAgICAgICAgICB9LFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aD8nICsgcXVlcnk7XG4gICAgfVxuXG4gICAgcHVibGljIGxvZ291dChyZWRpcmVjdFVyaT86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gbnVsbDtcbiAgICAgICAgdGhpcy51c2VyID0gbnVsbDtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgnc2lnbmF0dXJlJyksXG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgndXNlcicpLFxuICAgICAgICAgICAgXSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGVuZHBvaW50ID0gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2F1dGgvbG9nb3V0JztcblxuICAgICAgICAgICAgICAgIGlmIChyZWRpcmVjdFVyaSkge1xuICAgICAgICAgICAgICAgICAgICBlbmRwb2ludCArPSAnP2NvbnRpbnVlPScgKyByZWRpcmVjdFVyaTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKGVuZHBvaW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U3RhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0KCdzdGF0ZScpO1xuICAgIH1cblxuICAgIHB1YmxpYyBidWlsZE5lc3RlZFVyaShyb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCk6IHN0cmluZyB7XG4gICAgICAgIGxldCB1cmkgPSAnJztcblxuICAgICAgICBpZiAocm91dGUucm91dGVDb25maWcgJiYgcm91dGUucm91dGVDb25maWcucGF0aCkge1xuICAgICAgICAgICAgdXJpICs9ICcvJyArIHJvdXRlLnJvdXRlQ29uZmlnLnBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocm91dGUuY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHJvdXRlLmNoaWxkcmVuLmZvckVhY2goKGl0ZW06IEFjdGl2YXRlZFJvdXRlU25hcHNob3QpID0+IHtcbiAgICAgICAgICAgICAgICB1cmkgKz0gdGhpcy5idWlsZE5lc3RlZFVyaShpdGVtKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVyaTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFJlZnJlc2hUb2tlbigpOiBQcm9taXNlPFNpZ25hdHVyZSB8IG51bGw+IHtcbiAgICAgICAgaWYgKG51bGwgIT09IHRoaXMucmVmcmVzaFRva2VuKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMucmVmcmVzaFRva2VuKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0KCdyZWZyZXNoX3Rva2VuJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDbGllbnRTZWNyZXQoKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLmNsaWVudFNlY3JldCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLmNsaWVudFNlY3JldCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgnY2xpZW50X3NlY3JldCcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VXJpKHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXBpLycgKyB0aGlzLlZFUlNJT04gKyBwYXRoO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2VuZXJhdGVTdGF0ZSgpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBwb3NzaWJsZSA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSc7XG4gICAgICAgIGxldCB0ZXh0ID0gJyc7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgICAgICAgIHRleHQgKz0gcG9zc2libGUuY2hhckF0KE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHBvc3NpYmxlLmxlbmd0aCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBidWlsZFF1ZXJ5U3RyaW5nKHBhcmFtczogb2JqZWN0KTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcXVlcnlQYXJhbXMgPSBPYmplY3Qua2V5cyhwYXJhbXMpLm1hcCgoa2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChwYXJhbXNba2V5XSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBxdWVyeVBhcmFtcy5qb2luKCcmJyk7XG4gICAgfVxufVxuIiwiZXhwb3J0IGNsYXNzIFNpZ25hdHVyZSB7XG4gICAgcHVibGljIGV4cGlyZXNJbj86IG51bWJlcjtcbiAgICBwdWJsaWMgdG9rZW46IHN0cmluZztcbiAgICBwdWJsaWMgdHlwZTogc3RyaW5nO1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ2FuQWN0aXZhdGUsIENhbkFjdGl2YXRlQ2hpbGQgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBmaXJzdCwgbWFwIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL2RvbWFpbnMvbW9kZWxzL3VzZXInO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgU3RvcmFnZSB9IGZyb20gJ0B1YnVkL3N0b3JhZ2UnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlci9zcmMvcm91dGVyX3N0YXRlJztcbmltcG9ydCB7IFBsYXRmb3JtTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aGVudGljYXRlZEd1YXJkIGltcGxlbWVudHMgQ2FuQWN0aXZhdGUsIENhbkFjdGl2YXRlQ2hpbGQge1xuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIG5hY286IE5hY29TZXJ2aWNlLCBwcml2YXRlIHN0b3JhZ2U6IFN0b3JhZ2UsIHByaXZhdGUgcGxhdGZvcm1Mb2NhdGlvbjogUGxhdGZvcm1Mb2NhdGlvbikge1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5BY3RpdmF0ZShyb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5uYWNvLmdldFVzZXIoKS5waXBlKFxuICAgICAgICAgICAgZmlyc3QoKSxcbiAgICAgICAgICAgIG1hcCgodXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobnVsbCA9PT0gdXNlcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBiYXNlID0gdGhpcy5ydHJpbSgodGhpcy5wbGF0Zm9ybUxvY2F0aW9uIGFzIGFueSkubG9jYXRpb24uaHJlZik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVyaSA9IHRoaXMubmFjby5idWlsZE5lc3RlZFVyaShyb3V0ZS5yb290KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV4dCA9IGJhc2UucmVwbGFjZSh1cmksICcnKSArICcvJyArIHRoaXMubHRyaW0odXJpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3JpZ2luID0gYmFzZS5yZXBsYWNlKHVyaSwgJycpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ25hY29faW50ZW5kZWRfdXJsJywgbmV4dCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHRoaXMubmFjby5sb2dpbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYmFzaWMgZW1haWwnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpbiArICcvYXV0aCcsXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gISF1c2VyO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGNhbkFjdGl2YXRlQ2hpbGQocm91dGU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FuQWN0aXZhdGUocm91dGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgbHRyaW0odGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRleHQucmVwbGFjZSgvXlxcLysvLCcnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJ0cmltKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoL1xcLyskLywnJyk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgSHR0cEVycm9yUmVzcG9uc2UsIEh0dHBFdmVudCwgSHR0cEhhbmRsZXIsIEh0dHBJbnRlcmNlcHRvciwgSHR0cFJlcXVlc3QgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOYWNvU2VydmljZSB9IGZyb20gJy4uL2RvbWFpbnMvc2VydmljZXMvbmFjby5zZXJ2aWNlJztcbmltcG9ydCB7IGZyb21Qcm9taXNlIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vYnNlcnZhYmxlL2Zyb21Qcm9taXNlJztcbmltcG9ydCB7IFNpZ25hdHVyZSB9IGZyb20gJy4uL2RvbWFpbnMvdmFsdWVzL3NpZ25hdHVyZSc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL2ludGVybmFsL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBFcnJvck9ic2VydmFibGUgfSBmcm9tICdyeGpzLWNvbXBhdC9vYnNlcnZhYmxlL0Vycm9yT2JzZXJ2YWJsZSc7XG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdXRoSW50ZXJjZXB0b3IgaW1wbGVtZW50cyBIdHRwSW50ZXJjZXB0b3Ige1xuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIG5hY286IE5hY29TZXJ2aWNlKSB7XG4gICAgfVxuXG4gICAgcHVibGljIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PGFueT4sIG5leHQ6IEh0dHBIYW5kbGVyKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj4ge1xuICAgICAgICByZXR1cm4gZnJvbVByb21pc2UodGhpcy5uYWNvLmdldFNpZ25hdHVyZSgpKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChzaWduYXR1cmU6IFNpZ25hdHVyZSB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV4dC5oYW5kbGUocmVxKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV4dFxuICAgICAgICAgICAgICAgICAgICAuaGFuZGxlKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxLmNsb25lKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRIZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGAke3NpZ25hdHVyZS50eXBlfSAke3NpZ25hdHVyZS50b2tlbn1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKGVycm9yOiBIdHRwRXJyb3JSZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5uYWNvLnJlZnJlc2hVc2VyKCkucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PiBmcm9tUHJvbWlzZSh0aGlzLm5hY28uZ2V0U2lnbmF0dXJlKCkpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgobmV3U2lnbmF0dXJlOiBTaWduYXR1cmUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV4dC5oYW5kbGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcS5jbG9uZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRIZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogYCR7bmV3U2lnbmF0dXJlLnR5cGV9ICR7bmV3U2lnbmF0dXJlLnRva2VufWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEVycm9yT2JzZXJ2YWJsZS5jcmVhdGUoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBOYWNvU2VydmljZSB9IGZyb20gJy4uL2RvbWFpbnMvc2VydmljZXMvbmFjby5zZXJ2aWNlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL2RvbWFpbnMvdmFsdWVzL2NvbmZpZyc7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgU3RvcmFnZSB9IGZyb20gJ0B1YnVkL3N0b3JhZ2UnO1xuaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBuYWNvRmFjdG9yeShjb25maWc6IG9iamVjdCwgcm91dGVyOiBSb3V0ZXIsIHN0b3JhZ2U6IFN0b3JhZ2UsIGh0dHA6IEh0dHBDbGllbnQpIHtcbiAgICByZXR1cm4gbmV3IE5hY29TZXJ2aWNlKFxuICAgICAgICBuZXcgQ29uZmlnKHsgLi4uY29uZmlnIH0pLFxuICAgICAgICByb3V0ZXIsXG4gICAgICAgIHN0b3JhZ2UsXG4gICAgICAgIGh0dHBcbiAgICApO1xufVxuXG5leHBvcnQgY29uc3QgTkFDT19DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48b2JqZWN0PignTkFDT19DT05GSUcnKTtcbiIsImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBOYWNvU2VydmljZSB9IGZyb20gJy4uLy4uL2RvbWFpbnMvc2VydmljZXMvbmFjby5zZXJ2aWNlJztcbmltcG9ydCB7IFNpZ25hdHVyZSB9IGZyb20gJy4uLy4uL2RvbWFpbnMvdmFsdWVzL3NpZ25hdHVyZSc7XG5pbXBvcnQgeyBVc2VyIH0gZnJvbSAnLi4vLi4vZG9tYWlucy9tb2RlbHMvdXNlcic7XG5pbXBvcnQgeyBTdG9yYWdlIH0gZnJvbSAnQHVidWQvc3RvcmFnZSc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnbmFrZXItYXV0aC1wYWdlJyxcbiAgICB0ZW1wbGF0ZTogJ3t7IG1lc3NhZ2UgfX0nLFxufSlcbmV4cG9ydCBjbGFzcyBBdXRoUGFnZSB7XG4gICAgcHVibGljIG1lc3NhZ2U6IHN0cmluZyA9ICdBdXRoZW50aWNhdGluZy4uLic7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByb3V0ZTogQWN0aXZhdGVkUm91dGUsIHByaXZhdGUgbmFjbzogTmFjb1NlcnZpY2UsIHByaXZhdGUgc3RvcmFnZTogU3RvcmFnZSkge1xuICAgICAgICB0aGlzLnJvdXRlLnF1ZXJ5UGFyYW1zLnN1YnNjcmliZSgocGFyYW1zOiBQYXJhbXMpID0+IHRoaXMuaGFuZGxlKHBhcmFtcykpO1xuICAgIH1cblxuICAgIHB1YmxpYyBoYW5kbGUocGFyYW1zOiBQYXJhbXMpOiB2b2lkIHtcbiAgICAgICAgaWYgKHBhcmFtcy5zdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5uYWNvLmdldFN0YXRlKCkudGhlbigoc3RhdGU6IHN0cmluZyB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUgIT09IHBhcmFtcy5zdGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2UgPSAnSW52YWxpZCBDU1JGJztcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5hdXRoZW50aWNhdGUocGFyYW1zKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hdXRoZW50aWNhdGUocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXV0aGVudGljYXRlKHBhcmFtczogUGFyYW1zKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHNpZ25hdHVyZTogU2lnbmF0dXJlID0ge1xuICAgICAgICAgICAgZXhwaXJlc0luOiBwYXJhbXMuZXhwaXJlc19pbixcbiAgICAgICAgICAgIHR5cGU6IHBhcmFtcy50b2tlbl90eXBlLFxuICAgICAgICAgICAgdG9rZW46IHBhcmFtcy5hY2Nlc3NfdG9rZW4sXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5uYWNvLnNldFNpZ25hdHVyZShzaWduYXR1cmUpO1xuXG4gICAgICAgIHRoaXMubmFjby5nZXRVc2VyKCkuc3Vic2NyaWJlKCh1c2VyOiBVc2VyIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgaWYgKG51bGwgIT09IHVzZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UuZ2V0KCduYWNvX2ludGVuZGVkX3VybCcpLnRoZW4oKHVybDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5yZW1vdmUoJ25hY29faW50ZW5kZWRfdXJsJykudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybCA/IHVybCA6ICcvJztcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubWVzc2FnZSA9ICdVbmF1dGhlbnRpY2F0ZWQhJztcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4iLCJpbXBvcnQgeyBNb2R1bGVXaXRoUHJvdmlkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUsIFJvdXRlcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBBdXRoUGFnZSB9IGZyb20gJy4vcGFnZXMvYXV0aC5wYWdlJztcblxuY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gICAge1xuICAgICAgICBwYXRoOiAnYXV0aCcsXG4gICAgICAgIGNvbXBvbmVudDogQXV0aFBhZ2VcbiAgICB9LFxuXTtcblxuZXhwb3J0IGNvbnN0IEFVVEhfUk9VVElORzogTW9kdWxlV2l0aFByb3ZpZGVycyA9IFJvdXRlck1vZHVsZS5mb3JDaGlsZChyb3V0ZXMpO1xuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFVVEhfUk9VVElORyB9IGZyb20gJy4vcm91dGVzJztcbmltcG9ydCB7IEF1dGhQYWdlIH0gZnJvbSAnLi9wYWdlcy9hdXRoLnBhZ2UnO1xuXG5ATmdNb2R1bGUoe1xuICAgIGltcG9ydHM6IFtcbiAgICAgICAgQVVUSF9ST1VUSU5HLFxuICAgIF0sXG4gICAgZGVjbGFyYXRpb25zOiBbXG4gICAgICAgIEF1dGhQYWdlLFxuICAgIF0sXG59KVxuZXhwb3J0IGNsYXNzIE5hY29WaWV3TW9kdWxlIHtcbn1cbiIsImltcG9ydCB7IE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOYWNvU2VydmljZSB9IGZyb20gJy4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXV0aGVudGljYXRlZEd1YXJkIH0gZnJvbSAnLi9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZCc7XG5pbXBvcnQgeyBOQUNPX0NPTkZJRywgbmFjb0ZhY3RvcnkgfSBmcm9tICcuL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnknO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UsIFVidWRTdG9yYWdlTW9kdWxlIH0gZnJvbSAnQHVidWQvc3RvcmFnZSc7XG5pbXBvcnQgeyBOYWNvVmlld01vZHVsZSB9IGZyb20gJy4vdmlld3MvbW9kdWxlJztcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbkBOZ01vZHVsZSh7XG4gICAgaW1wb3J0czogW1xuICAgICAgICBVYnVkU3RvcmFnZU1vZHVsZSxcbiAgICAgICAgTmFjb1ZpZXdNb2R1bGUsXG4gICAgXSxcbn0pXG5leHBvcnQgY2xhc3MgTmFjb01vZHVsZSB7XG4gICAgcHVibGljIHN0YXRpYyBmb3JSb290KGNvbmZpZzogeyBjbGllbnRJZDogc3RyaW5nLCBlbmRwb2ludD86IHN0cmluZyB9KTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuZ01vZHVsZTogTmFjb01vZHVsZSxcbiAgICAgICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZTogTkFDT19DT05GSUcsXG4gICAgICAgICAgICAgICAgICAgIHVzZVZhbHVlOiBjb25maWcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGU6IE5hY29TZXJ2aWNlLFxuICAgICAgICAgICAgICAgICAgICB1c2VGYWN0b3J5OiBuYWNvRmFjdG9yeSxcbiAgICAgICAgICAgICAgICAgICAgZGVwczogW05BQ09fQ09ORklHLCBSb3V0ZXIsIFN0b3JhZ2UsIEh0dHBDbGllbnRdLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgQXV0aGVudGljYXRlZEd1YXJkLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfTtcbiAgICB9XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOzs7O2dCQUl1QixJQUFzQjt3QkFIZixnQ0FBZ0M7UUFJdEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7O0NBRWpDOzs7Ozs7O0NDS0E7O0lBRkksSUFBSSxtQkFBQyxVQUFVLENBQUMsTUFBTSxJQUFJLENBQVEsRUFBQzs4QkFDbEIsSUFBSTs7Ozs7OztBQ1gxQjs7Ozs7OztnQkFxQitCLE1BQWMsRUFBVSxNQUFjLEVBQVUsT0FBZ0IsRUFBVSxJQUFnQjtRQUExRixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQVUsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUFVLFlBQU8sR0FBUCxPQUFPLENBQVM7UUFBVSxTQUFJLEdBQUosSUFBSSxDQUFZO3VCQVAzRixJQUFJO3lCQUVRLElBQUk7b0JBQ2QsSUFBSTs0QkFDUyxJQUFJOzRCQUNQLElBQUk7Ozs7OztJQUtuQyxPQUFPLENBQUMsSUFBaUI7UUFDNUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDOzs7OztJQUc1QixPQUFPO1FBQ1YsSUFBSSxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksRUFBRTtZQUNwQixPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDeEI7UUFFRCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUks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
\No newline at end of file