1 | /**
|
2 | * @fileoverview added by tsickle
|
3 | * @suppress {checkTypes} checked by tsc
|
4 | */
|
5 | import * as tslib_1 from "tslib";
|
6 | import { Injectable } from '@angular/core';
|
7 | import { Router } from '@angular/router';
|
8 | import { Storage } from '@ubud/storage';
|
9 | import { Config } from '../values/config';
|
10 | import { User } from '../models/user';
|
11 | import { forkJoin, from, Observable, of } from 'rxjs';
|
12 | import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
13 | import { plainToClass } from 'class-transformer';
|
14 | import { HttpClient } from '@angular/common/http';
|
15 | import { Location } from '@angular/common';
|
16 | import { fromPromise } from 'rxjs-compat/observable/fromPromise';
|
17 | var NacoService = /** @class */ (function () {
|
18 | function NacoService(config, router, storage, http, location) {
|
19 | this.config = config;
|
20 | this.router = router;
|
21 | this.storage = storage;
|
22 | this.http = http;
|
23 | this.location = location;
|
24 | this.VERSION = 'v1';
|
25 | this.signature = null;
|
26 | this.user = null;
|
27 | this.refreshToken = null;
|
28 | this.clientSecret = null;
|
29 | if (this.config.clientSecret) {
|
30 | this.setClientSecret(this.config.clientSecret);
|
31 | }
|
32 | }
|
33 | /**
|
34 | * @param {?} user
|
35 | * @return {?}
|
36 | */
|
37 | NacoService.prototype.setUser = /**
|
38 | * @param {?} user
|
39 | * @return {?}
|
40 | */
|
41 | function (user) {
|
42 | this.user = user;
|
43 | };
|
44 | /**
|
45 | * @return {?}
|
46 | */
|
47 | NacoService.prototype.getUser = /**
|
48 | * @return {?}
|
49 | */
|
50 | function () {
|
51 | var _this = this;
|
52 | if (null !== this.user) {
|
53 | return of(this.user);
|
54 | }
|
55 | var /** @type {?} */ uri = this.getUri('/users/me');
|
56 | return from(this.getSignature()).pipe(switchMap(function (signature) {
|
57 | if (!signature) {
|
58 | return _this.refreshUser(_this.config.scopes);
|
59 | }
|
60 | var /** @type {?} */ options = {
|
61 | headers: {
|
62 | Authorization: signature.type + " " + signature.token,
|
63 | },
|
64 | };
|
65 | return _this.http.get(uri, options).pipe(map(function (res) {
|
66 | if (res.data) {
|
67 | return res.data;
|
68 | }
|
69 | throw new Error('There are no body to be transformed');
|
70 | }), map(function (data) {
|
71 | var /** @type {?} */ authUser = plainToClass(User, data);
|
72 | _this.setUser(authUser);
|
73 | return authUser;
|
74 | }), catchError(function (e) {
|
75 | if (401 === e.status) {
|
76 | return _this.refreshUser(signature.scopes);
|
77 | }
|
78 | return of(null);
|
79 | }));
|
80 | }));
|
81 | };
|
82 | /**
|
83 | * @param {?} user
|
84 | * @return {?}
|
85 | */
|
86 | NacoService.prototype.getProfilePicture = /**
|
87 | * @param {?} user
|
88 | * @return {?}
|
89 | */
|
90 | function (user) {
|
91 | return this.config.endpoint + '/users/' + user + '/picture';
|
92 | };
|
93 | /**
|
94 | * @return {?}
|
95 | */
|
96 | NacoService.prototype.getSignature = /**
|
97 | * @return {?}
|
98 | */
|
99 | function () {
|
100 | if (this.signature) {
|
101 | return Promise.resolve(this.signature);
|
102 | }
|
103 | return this.storage.get('signature');
|
104 | };
|
105 | /**
|
106 | * @param {?} signature
|
107 | * @return {?}
|
108 | */
|
109 | NacoService.prototype.setSignature = /**
|
110 | * @param {?} signature
|
111 | * @return {?}
|
112 | */
|
113 | function (signature) {
|
114 | this.signature = signature;
|
115 | this.storage.set('signature', signature);
|
116 | };
|
117 | /**
|
118 | * @param {?} secret
|
119 | * @return {?}
|
120 | */
|
121 | NacoService.prototype.setClientSecret = /**
|
122 | * @param {?} secret
|
123 | * @return {?}
|
124 | */
|
125 | function (secret) {
|
126 | this.clientSecret = secret;
|
127 | };
|
128 | /**
|
129 | * @param {?} refreshToken
|
130 | * @return {?}
|
131 | */
|
132 | NacoService.prototype.setRefreshToken = /**
|
133 | * @param {?} refreshToken
|
134 | * @return {?}
|
135 | */
|
136 | function (refreshToken) {
|
137 | this.refreshToken = refreshToken;
|
138 | this.storage.set('refresh_token', refreshToken);
|
139 | };
|
140 | /**
|
141 | * @param {?=} scopes
|
142 | * @return {?}
|
143 | */
|
144 | NacoService.prototype.refreshUser = /**
|
145 | * @param {?=} scopes
|
146 | * @return {?}
|
147 | */
|
148 | function (scopes) {
|
149 | var _this = this;
|
150 | this.setUser(null);
|
151 | this.setSignature(null);
|
152 | return forkJoin(this.getRefreshToken(), this.getClientSecret()).pipe(switchMap(function (results) {
|
153 | var /** @type {?} */ refreshToken = results[0];
|
154 | var /** @type {?} */ clientSecret = results[1];
|
155 | if (refreshToken && clientSecret) {
|
156 | return _this.refreshWithRefreshToken(clientSecret, refreshToken.token, scopes);
|
157 | }
|
158 | return _this.refreshWithSilentAuth(scopes);
|
159 | }));
|
160 | };
|
161 | /**
|
162 | * @param {?} clientSecret
|
163 | * @param {?} refreshToken
|
164 | * @param {?=} scopes
|
165 | * @return {?}
|
166 | */
|
167 | NacoService.prototype.refreshWithRefreshToken = /**
|
168 | * @param {?} clientSecret
|
169 | * @param {?} refreshToken
|
170 | * @param {?=} scopes
|
171 | * @return {?}
|
172 | */
|
173 | function (clientSecret, refreshToken, scopes) {
|
174 | var _this = this;
|
175 | var /** @type {?} */ request = this.http.post(this.getUri('/tokens'), {
|
176 | grant_type: 'refresh_token',
|
177 | scopes: scopes || this.config.scopes,
|
178 | client_id: this.config.clientId,
|
179 | client_secret: clientSecret,
|
180 | refresh_token: refreshToken,
|
181 | });
|
182 | return request.pipe(tap(function (tokens) {
|
183 | if (tokens && tokens.data) {
|
184 | _this.setSignature({
|
185 | expiresIn: tokens.data.expires_in,
|
186 | type: tokens.data.token_type,
|
187 | token: tokens.data.access_token,
|
188 | scopes: decodeURIComponent(tokens.data.scopes || _this.config.scopes),
|
189 | });
|
190 | _this.setRefreshToken({
|
191 | type: tokens.data.token_type,
|
192 | token: tokens.data.refresh_token,
|
193 | });
|
194 | }
|
195 | }), map(function (tokens) { return tokens && tokens.data; }), switchMap(function (hasToken) {
|
196 | if (hasToken) {
|
197 | return _this.getUser();
|
198 | }
|
199 | return of(null);
|
200 | }));
|
201 | };
|
202 | /**
|
203 | * @param {?=} scopes
|
204 | * @return {?}
|
205 | */
|
206 | NacoService.prototype.refreshWithSilentAuth = /**
|
207 | * @param {?=} scopes
|
208 | * @return {?}
|
209 | */
|
210 | function (scopes) {
|
211 | var _this = this;
|
212 | return new Observable(function (observer) {
|
213 | var /** @type {?} */ redirectUri = _this.getCurrentOrigin('auth/silent');
|
214 | var /** @type {?} */ uri = _this.login(scopes || _this.config.scopes, redirectUri, true, 'token', false);
|
215 | var /** @type {?} */ iframe = document.createElement('iframe');
|
216 | iframe.setAttribute('src', uri);
|
217 | iframe.style.display = 'none';
|
218 | iframe.addEventListener('load', function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
219 | var e_1, _a, queryString, queryParts, params, queryParts_1, queryParts_1_1, item, itemParts, user, e_2;
|
220 | return tslib_1.__generator(this, function (_b) {
|
221 | switch (_b.label) {
|
222 | case 0:
|
223 | _b.trys.push([0, 5, , 6]);
|
224 | queryString = iframe.contentWindow.location.search.substring(1);
|
225 | iframe.parentNode.removeChild(iframe);
|
226 | if (!queryString) return [3 /*break*/, 4];
|
227 | queryParts = queryString.split('&');
|
228 | params = {};
|
229 | try {
|
230 | for (queryParts_1 = tslib_1.__values(queryParts), queryParts_1_1 = queryParts_1.next(); !queryParts_1_1.done; queryParts_1_1 = queryParts_1.next()) {
|
231 | item = queryParts_1_1.value;
|
232 | itemParts = item.split('=');
|
233 | params[itemParts[0]] = itemParts[1];
|
234 | }
|
235 | }
|
236 | catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
237 | finally {
|
238 | try {
|
239 | if (queryParts_1_1 && !queryParts_1_1.done && (_a = queryParts_1.return)) _a.call(queryParts_1);
|
240 | }
|
241 | finally { if (e_1) throw e_1.error; }
|
242 | }
|
243 | if (!params.hasOwnProperty('access_token')) return [3 /*break*/, 2];
|
244 | this.setSignature({
|
245 | token: params['access_token'],
|
246 | type: params['token_type'],
|
247 | expiresIn: params['expires_in'],
|
248 | scopes: decodeURIComponent(params['scopes'] || this.config.scopes),
|
249 | });
|
250 | return [4 /*yield*/, this.getUser().toPromise()];
|
251 | case 1:
|
252 | user = _b.sent();
|
253 | if (user) {
|
254 | this.setUser(user);
|
255 | }
|
256 | observer.next(user);
|
257 | return [3 /*break*/, 3];
|
258 | case 2:
|
259 | observer.next(null);
|
260 | _b.label = 3;
|
261 | case 3: return [2 /*return*/];
|
262 | case 4:
|
263 | observer.next(null);
|
264 | return [3 /*break*/, 6];
|
265 | case 5:
|
266 | e_2 = _b.sent();
|
267 | observer.next(null);
|
268 | return [3 /*break*/, 6];
|
269 | case 6: return [2 /*return*/];
|
270 | }
|
271 | });
|
272 | }); }, false);
|
273 | document.body.appendChild(iframe);
|
274 | });
|
275 | };
|
276 | /**
|
277 | * @param {?} code
|
278 | * @param {?} redirectUri
|
279 | * @param {?=} scopes
|
280 | * @return {?}
|
281 | */
|
282 | NacoService.prototype.getAccessTokenFromAuthCode = /**
|
283 | * @param {?} code
|
284 | * @param {?} redirectUri
|
285 | * @param {?=} scopes
|
286 | * @return {?}
|
287 | */
|
288 | function (code, redirectUri, scopes) {
|
289 | var _this = this;
|
290 | return fromPromise(this.getState()).pipe(switchMap(function (state) {
|
291 | var /** @type {?} */ params = {
|
292 | code: code,
|
293 | grant_type: 'authorization_code',
|
294 | scopes: scopes || _this.config.scopes,
|
295 | client_id: _this.config.clientId,
|
296 | client_secret: _this.config.clientSecret,
|
297 | redirect_uri: redirectUri,
|
298 | };
|
299 | if (state) {
|
300 | params["state"] = state;
|
301 | }
|
302 | return _this.http.post(_this.getUri('/tokens'), params);
|
303 | }), map(function (res) {
|
304 | if (res.data) {
|
305 | return res.data;
|
306 | }
|
307 | throw new Error('There are no body to be transformed');
|
308 | }));
|
309 | };
|
310 | /**
|
311 | * @param {?} scopes
|
312 | * @param {?=} redirectUri
|
313 | * @param {?=} silent
|
314 | * @param {?=} responseType
|
315 | * @param {?=} needState
|
316 | * @return {?}
|
317 | */
|
318 | NacoService.prototype.login = /**
|
319 | * @param {?} scopes
|
320 | * @param {?=} redirectUri
|
321 | * @param {?=} silent
|
322 | * @param {?=} responseType
|
323 | * @param {?=} needState
|
324 | * @return {?}
|
325 | */
|
326 | function (scopes, redirectUri, silent, responseType, needState) {
|
327 | if (silent === void 0) { silent = false; }
|
328 | if (responseType === void 0) { responseType = 'token'; }
|
329 | if (needState === void 0) { needState = true; }
|
330 | if (!redirectUri) {
|
331 | redirectUri = this.router.url;
|
332 | }
|
333 | var /** @type {?} */ params = {
|
334 | response_type: responseType,
|
335 | scopes: scopes,
|
336 | client: this.config.clientId,
|
337 | silent: silent,
|
338 | continue: encodeURIComponent(redirectUri),
|
339 | };
|
340 | if (needState) {
|
341 | var /** @type {?} */ state = this.generateState();
|
342 | this.storage.set('state', state);
|
343 | params.state = state;
|
344 | }
|
345 | var /** @type {?} */ query = this.buildQueryString(params);
|
346 | return this.config.endpoint + '/auth?' + query;
|
347 | };
|
348 | /**
|
349 | * @param {?=} redirectUri
|
350 | * @return {?}
|
351 | */
|
352 | NacoService.prototype.logout = /**
|
353 | * @param {?=} redirectUri
|
354 | * @return {?}
|
355 | */
|
356 | function (redirectUri) {
|
357 | var _this = this;
|
358 | this.signature = null;
|
359 | this.user = null;
|
360 | this.refreshToken = null;
|
361 | return new Promise(function (resolve) {
|
362 | var /** @type {?} */ clear = [_this.storage.remove('signature'), _this.storage.remove('user'), _this.storage.remove('refresh_token')];
|
363 | Promise.all(clear).then(function () {
|
364 | var /** @type {?} */ endpoint = _this.config.endpoint + '/auth/logout';
|
365 | if (redirectUri) {
|
366 | endpoint += '?continue=' + encodeURIComponent(redirectUri);
|
367 | }
|
368 | resolve(endpoint);
|
369 | });
|
370 | });
|
371 | };
|
372 | /**
|
373 | * @return {?}
|
374 | */
|
375 | NacoService.prototype.getState = /**
|
376 | * @return {?}
|
377 | */
|
378 | function () {
|
379 | return this.storage.get('state');
|
380 | };
|
381 | /**
|
382 | * @param {?} route
|
383 | * @return {?}
|
384 | */
|
385 | NacoService.prototype.buildNestedUri = /**
|
386 | * @param {?} route
|
387 | * @return {?}
|
388 | */
|
389 | function (route) {
|
390 | var _this = this;
|
391 | var /** @type {?} */ uri = '';
|
392 | if (route.routeConfig && route.routeConfig.path) {
|
393 | var /** @type {?} */ routePath = route.routeConfig.path;
|
394 | for (var /** @type {?} */ key in route.params) {
|
395 | if (key) {
|
396 | var /** @type {?} */ re = new RegExp(':' + key);
|
397 | routePath = routePath.replace(re, route.params[key]);
|
398 | }
|
399 | }
|
400 | uri += '/' + routePath;
|
401 | }
|
402 | if (route.children) {
|
403 | route.children.forEach(function (item) {
|
404 | uri += _this.buildNestedUri(item);
|
405 | });
|
406 | }
|
407 | return uri;
|
408 | };
|
409 | /**
|
410 | * @return {?}
|
411 | */
|
412 | NacoService.prototype.getRefreshToken = /**
|
413 | * @return {?}
|
414 | */
|
415 | function () {
|
416 | if (null !== this.refreshToken) {
|
417 | return Promise.resolve(this.refreshToken);
|
418 | }
|
419 | return this.storage.get('refresh_token');
|
420 | };
|
421 | /**
|
422 | * @return {?}
|
423 | */
|
424 | NacoService.prototype.getClientSecret = /**
|
425 | * @return {?}
|
426 | */
|
427 | function () {
|
428 | if (null !== this.clientSecret) {
|
429 | return Promise.resolve(this.clientSecret);
|
430 | }
|
431 | return this.storage.get('client_secret');
|
432 | };
|
433 | /**
|
434 | * @param {?} path
|
435 | * @return {?}
|
436 | */
|
437 | NacoService.prototype.getUri = /**
|
438 | * @param {?} path
|
439 | * @return {?}
|
440 | */
|
441 | function (path) {
|
442 | return this.config.endpoint + '/api/' + this.VERSION + path;
|
443 | };
|
444 | /**
|
445 | * @param {?=} path
|
446 | * @return {?}
|
447 | */
|
448 | NacoService.prototype.getCurrentOrigin = /**
|
449 | * @param {?=} path
|
450 | * @return {?}
|
451 | */
|
452 | function (path) {
|
453 | return window.location.origin + this.location.prepareExternalUrl(path || '');
|
454 | };
|
455 | /**
|
456 | * @return {?}
|
457 | */
|
458 | NacoService.prototype.generateState = /**
|
459 | * @return {?}
|
460 | */
|
461 | function () {
|
462 | var /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
463 | var /** @type {?} */ text = '';
|
464 | for (var /** @type {?} */ i = 0; i < 5; i++) {
|
465 | text += possible.charAt(Math.floor(Math.random() * possible.length));
|
466 | }
|
467 | return text;
|
468 | };
|
469 | /**
|
470 | * @param {?} params
|
471 | * @return {?}
|
472 | */
|
473 | NacoService.prototype.buildQueryString = /**
|
474 | * @param {?} params
|
475 | * @return {?}
|
476 | */
|
477 | function (params) {
|
478 | var /** @type {?} */ queryParams = Object.keys(params).map(function (key) {
|
479 | return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
|
480 | });
|
481 | return queryParams.join('&');
|
482 | };
|
483 | /**
|
484 | * @param {?} route
|
485 | * @param {?=} responseType
|
486 | * @return {?}
|
487 | */
|
488 | NacoService.prototype.goToAccountEndpoint = /**
|
489 | * @param {?} route
|
490 | * @param {?=} responseType
|
491 | * @return {?}
|
492 | */
|
493 | function (route, responseType) {
|
494 | var _this = this;
|
495 | var /** @type {?} */ ltrim = function (text) { return text.replace(/^\/+/, ''); };
|
496 | var /** @type {?} */ next = this.getCurrentOrigin('/' + ltrim(this.buildNestedUri(route.root)));
|
497 | this.storage.set('naco_intended_url', next).then(function () {
|
498 | _this.redirect(_this.login(_this.config.scopes, _this.getCurrentOrigin('/auth'), false, responseType || _this.config.responseType, true));
|
499 | });
|
500 | };
|
501 | /**
|
502 | * @return {?}
|
503 | */
|
504 | NacoService.prototype.goToIntendedUrl = /**
|
505 | * @return {?}
|
506 | */
|
507 | function () {
|
508 | var _this = this;
|
509 | this.storage.get('naco_intended_url').then(function (url) {
|
510 | _this.storage.remove('naco_intended_url');
|
511 | _this.redirect(url || '/');
|
512 | });
|
513 | };
|
514 | /**
|
515 | * @param {?} url
|
516 | * @return {?}
|
517 | */
|
518 | NacoService.prototype.redirect = /**
|
519 | * @param {?} url
|
520 | * @return {?}
|
521 | */
|
522 | function (url) {
|
523 | window.location.href = url;
|
524 | };
|
525 | NacoService.decorators = [
|
526 | { type: Injectable },
|
527 | ];
|
528 | /** @nocollapse */
|
529 | NacoService.ctorParameters = function () { return [
|
530 | { type: Config },
|
531 | { type: Router },
|
532 | { type: Storage },
|
533 | { type: HttpClient },
|
534 | { type: Location }
|
535 | ]; };
|
536 | return NacoService;
|
537 | }());
|
538 | export { NacoService };
|
539 | function NacoService_tsickle_Closure_declarations() {
|
540 | /** @type {?} */
|
541 | NacoService.prototype.VERSION;
|
542 | /** @type {?} */
|
543 | NacoService.prototype.signature;
|
544 | /** @type {?} */
|
545 | NacoService.prototype.user;
|
546 | /** @type {?} */
|
547 | NacoService.prototype.refreshToken;
|
548 | /** @type {?} */
|
549 | NacoService.prototype.clientSecret;
|
550 | /** @type {?} */
|
551 | NacoService.prototype.config;
|
552 | /** @type {?} */
|
553 | NacoService.prototype.router;
|
554 | /** @type {?} */
|
555 | NacoService.prototype.storage;
|
556 | /** @type {?} */
|
557 | NacoService.prototype.http;
|
558 | /** @type {?} */
|
559 | NacoService.prototype.location;
|
560 | }
|
561 |
|
562 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFjby5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5ha2VyL25hY28vIiwic291cmNlcyI6WyJkb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFrQyxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFZLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVoRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxVQUFVLEVBQXFCLE1BQU0sc0JBQXNCLENBQUM7QUFDckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQzs7eUJBWS9DLE1BQWMsRUFDZCxNQUFjLEVBQ2QsT0FBZ0IsRUFDaEIsSUFBZ0IsRUFDaEIsUUFBa0I7UUFKbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxZQUFPLEdBQVAsT0FBTyxDQUFTO1FBQ2hCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsYUFBUSxHQUFSLFFBQVEsQ0FBVTt1QkFaTixJQUFJO3lCQUVRLElBQUk7b0JBQ2QsSUFBSTs0QkFDUyxJ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QUM7UUFFakYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzdDLEtBQUksQ0FBQyxRQUFRLENBQ1QsS0FBSSxDQUFDLEtBQUssQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxLQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLFlBQVksSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FDeEgsQ0FBQztTQUNMLENBQUMsQ0FBQzs7Ozs7SUFHQSxxQ0FBZTs7Ozs7UUFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQVMsbUJBQW1CLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQSxHQUFHO1lBQ2xELEtBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDekMsS0FBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7U0FDN0IsQ0FBQyxDQUFDOzs7Ozs7SUFHQSw4QkFBUTs7OztjQUFDLEdBQVc7UUFDdkIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDOzs7Z0JBallsQyxVQUFVOzs7O2dCQVZGLE1BQU07Z0JBRjBCLE1BQU07Z0JBQ3RDLE9BQU87Z0JBT1AsVUFBVTtnQkFDVixRQUFROztzQkFWakI7O1NBY2EsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIFBhcmFtcywgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL21vZGVscy91c2VyJztcbmltcG9ydCB7IGZvcmtKb2luLCBmcm9tLCBPYnNlcnZhYmxlLCBPYnNlcnZlciwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFNpZ25hdHVyZSB9IGZyb20gJy4uL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgbWFwLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IHBsYWluVG9DbGFzcyB9IGZyb20gJ2NsYXNzLXRyYW5zZm9ybWVyJztcbmltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgZnJvbVByb21pc2UgfSBmcm9tICdyeGpzLWNvbXBhdC9vYnNlcnZhYmxlL2Zyb21Qcm9taXNlJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5hY29TZXJ2aWNlIHtcbiAgICBwdWJsaWMgcmVhZG9ubHkgVkVSU0lPTiA9ICd2MSc7XG5cbiAgICBwcml2YXRlIHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSB1c2VyOiBVc2VyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgY2xpZW50U2VjcmV0OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJvdGVjdGVkIGNvbmZpZzogQ29uZmlnLFxuICAgICAgICBwcm90ZWN0ZWQgcm91dGVyOiBSb3V0ZXIsXG4gICAgICAgIHByb3RlY3RlZCBzdG9yYWdlOiBTdG9yYWdlLFxuICAgICAgICBwcm90ZWN0ZWQgaHR0cDogSHR0cENsaWVudCxcbiAgICAgICAgcHJvdGVjdGVkIGxvY2F0aW9uOiBMb2NhdGlvbixcbiAgICApIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmNsaWVudFNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5zZXRDbGllbnRTZWNyZXQodGhpcy5jb25maWcuY2xpZW50U2VjcmV0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzZXRVc2VyKHVzZXI6IFVzZXIgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFVzZXIoKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy51c2VyKSB7XG4gICAgICAgICAgICByZXR1cm4gb2YodGhpcy51c2VyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHVyaSA9IHRoaXMuZ2V0VXJpKCcvdXNlcnMvbWUnKTtcblxuICAgICAgICByZXR1cm4gZnJvbSh0aGlzLmdldFNpZ25hdHVyZSgpKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChzaWduYXR1cmU6IFNpZ25hdHVyZSB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoVXNlcih0aGlzLmNvbmZpZy5zY29wZXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGAke3NpZ25hdHVyZS50eXBlfSAke3NpZ25hdHVyZS50b2tlbn1gLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5odHRwLmdldDxhbnk+KHVyaSwgb3B0aW9ucykucGlwZShcbiAgICAgICAgICAgICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcy5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGFyZSBubyBib2R5IHRvIGJlIHRyYW5zZm9ybWVkJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBtYXAoKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV0aFVzZXI6IGFueSA9IHBsYWluVG9DbGFzcyhVc2VyLCBkYXRhKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRVc2VyKGF1dGhVc2VyKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF1dGhVc2VyO1xuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoZTogSHR0cEVycm9yUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICg0MDEgPT09IGUuc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFVzZXIoc2lnbmF0dXJlLnNjb3Blcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRQcm9maWxlUGljdHVyZSh1c2VyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL3VzZXJzLycgKyB1c2VyICsgJy9waWN0dXJlJztcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2lnbmF0dXJlKCk6IFByb21pc2U8U2lnbmF0dXJlIHwgbnVsbD4ge1xuICAgICAgICBpZiAodGhpcy5zaWduYXR1cmUpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5zaWduYXR1cmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ3NpZ25hdHVyZScpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRTaWduYXR1cmUoc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuXG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3NpZ25hdHVyZScsIHNpZ25hdHVyZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldENsaWVudFNlY3JldChzZWNyZXQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmNsaWVudFNlY3JldCA9IHNlY3JldDtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0UmVmcmVzaFRva2VuKHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVmcmVzaFRva2VuID0gcmVmcmVzaFRva2VuO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdyZWZyZXNoX3Rva2VuJywgcmVmcmVzaFRva2VuKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFVzZXIoc2NvcGVzPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICB0aGlzLnNldFVzZXIobnVsbCk7XG4gICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKG51bGwpO1xuXG4gICAgICAgIHJldHVybiBmb3JrSm9pbih0aGlzLmdldFJlZnJlc2hUb2tlbigpLCB0aGlzLmdldENsaWVudFNlY3JldCgpKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChyZXN1bHRzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSA9IHJlc3VsdHNbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgY2xpZW50U2VjcmV0OiBzdHJpbmcgPSByZXN1bHRzWzFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hUb2tlbiAmJiBjbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFdpdGhSZWZyZXNoVG9rZW4oY2xpZW50U2VjcmV0LCByZWZyZXNoVG9rZW4udG9rZW4sIHNjb3Blcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFdpdGhTaWxlbnRBdXRoKHNjb3Blcyk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFdpdGhSZWZyZXNoVG9rZW4oY2xpZW50U2VjcmV0OiBzdHJpbmcsIHJlZnJlc2hUb2tlbjogc3RyaW5nLCBzY29wZXM/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLmh0dHAucG9zdCh0aGlzLmdldFVyaSgnL3Rva2VucycpLCB7XG4gICAgICAgICAgICBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgICAgICBzY29wZXM6IHNjb3BlcyB8fCB0aGlzLmNvbmZpZy5zY29wZXMsXG4gICAgICAgICAgICBjbGllbnRfaWQ6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgY2xpZW50X3NlY3JldDogY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVxdWVzdC5waXBlKFxuICAgICAgICAgICAgdGFwKCh0b2tlbnM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0b2tlbnMgJiYgdG9rZW5zLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTaWduYXR1cmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0luOiB0b2tlbnMuZGF0YS5leHBpcmVzX2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogdG9rZW5zLmRhdGEudG9rZW5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbnMuZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZXM6IGRlY29kZVVSSUNvbXBvbmVudCh0b2tlbnMuZGF0YS5zY29wZXMgfHwgdGhpcy5jb25maWcuc2NvcGVzKSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRSZWZyZXNoVG9rZW4oe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogdG9rZW5zLmRhdGEudG9rZW5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbnMuZGF0YS5yZWZyZXNoX3Rva2VuLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIG1hcCgodG9rZW5zOiBhbnkpID0+IHRva2VucyAmJiB0b2tlbnMuZGF0YSksXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKGhhc1Rva2VuOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1Rva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFVzZXIoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFdpdGhTaWxlbnRBdXRoKHNjb3Blcz86IHN0cmluZyk6IE9ic2VydmFibGU8VXNlciB8IG51bGw+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPigob2JzZXJ2ZXI6IE9ic2VydmVyPFVzZXIgfCBudWxsPikgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVkaXJlY3RVcmkgPSB0aGlzLmdldEN1cnJlbnRPcmlnaW4oJ2F1dGgvc2lsZW50Jyk7XG4gICAgICAgICAgICBjb25zdCB1cmkgPSB0aGlzLmxvZ2luKHNjb3BlcyB8fCB0aGlzLmNvbmZpZy5zY29wZXMsIHJlZGlyZWN0VXJpLCB0cnVlLCAndG9rZW4nLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgICAgICAgICAgaWZyYW1lLnNldEF0dHJpYnV0ZSgnc3JjJywgdXJpKTtcbiAgICAgICAgICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICAgICAgICBpZnJhbWUuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAnbG9hZCcsXG4gICAgICAgICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcXVlcnlTdHJpbmcgPSBpZnJhbWUuY29udGVudFdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc3Vic3RyaW5nKDEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZnJhbWUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChpZnJhbWUpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWVyeVBhcnRzID0gcXVlcnlTdHJpbmcuc3BsaXQoJyYnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBxdWVyeVBhcnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1QYXJ0cyA9IGl0ZW0uc3BsaXQoJz0nKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXNbaXRlbVBhcnRzWzBdXSA9IGl0ZW1QYXJ0c1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW1zLmhhc093blByb3BlcnR5KCdhY2Nlc3NfdG9rZW4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFNpZ25hdHVyZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogcGFyYW1zWydhY2Nlc3NfdG9rZW4nXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHBhcmFtc1sndG9rZW5fdHlwZSddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0luOiBwYXJhbXNbJ2V4cGlyZXNfaW4nXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlczogZGVjb2RlVVJJQ29tcG9uZW50KHBhcmFtc1snc2NvcGVzJ10gfHwgdGhpcy5jb25maWcuc2NvcGVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuZ2V0VXNlcigpLnRvUHJvbWlzZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIodXNlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHVzZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFjY2Vzc1Rva2VuRnJvbUF1dGhDb2RlKGNvZGU6IHN0cmluZywgcmVkaXJlY3RVcmk6IHN0cmluZywgc2NvcGVzPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuZ2V0U3RhdGUoKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoc3RhdGU/OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXM6IFBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgY29kZSxcbiAgICAgICAgICAgICAgICAgICAgZ3JhbnRfdHlwZTogJ2F1dGhvcml6YXRpb25fY29kZScsXG4gICAgICAgICAgICAgICAgICAgIHNjb3Blczogc2NvcGVzIHx8IHRoaXMuY29uZmlnLnNjb3BlcyxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50X2lkOiB0aGlzLmNvbmZpZy5jbGllbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50X3NlY3JldDogdGhpcy5jb25maWcuY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgICAgICAgICByZWRpcmVjdF91cmk6IHJlZGlyZWN0VXJpLFxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zLnN0YXRlID0gc3RhdGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0KHRoaXMuZ2V0VXJpKCcvdG9rZW5zJyksIHBhcmFtcyk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIG1hcCgocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgYXJlIG5vIGJvZHkgdG8gYmUgdHJhbnNmb3JtZWQnKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dpbihcbiAgICAgICAgc2NvcGVzOiBzdHJpbmcsXG4gICAgICAgIHJlZGlyZWN0VXJpPzogc3RyaW5nLFxuICAgICAgICBzaWxlbnQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndG9rZW4nIHwgJ2NvZGUnID0gJ3Rva2VuJyxcbiAgICAgICAgbmVlZFN0YXRlOiBib29sZWFuID0gdHJ1ZSxcbiAgICApOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICByZWRpcmVjdFVyaSA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhcmFtczogYW55ID0ge1xuICAgICAgICAgICAgcmVzcG9uc2VfdHlwZTogcmVzcG9uc2VUeXBlLFxuICAgICAgICAgICAgc2NvcGVzOiBzY29wZXMsXG4gICAgICAgICAgICBjbGllbnQ6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgc2lsZW50OiBzaWxlbnQsXG4gICAgICAgICAgICBjb250aW51ZTogZW5jb2RlVVJJQ29tcG9uZW50KHJlZGlyZWN0VXJpKSxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobmVlZFN0YXRlKSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2VuZXJhdGVTdGF0ZSgpO1xuXG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdzdGF0ZScsIHN0YXRlKTtcbiAgICAgICAgICAgIHBhcmFtcy5zdGF0ZSA9IHN0YXRlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcXVlcnk6IHN0cmluZyA9IHRoaXMuYnVpbGRRdWVyeVN0cmluZyhwYXJhbXMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aD8nICsgcXVlcnk7XG4gICAgfVxuXG4gICAgcHVibGljIGxvZ291dChyZWRpcmVjdFVyaT86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gbnVsbDtcbiAgICAgICAgdGhpcy51c2VyID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWZyZXNoVG9rZW4gPSBudWxsO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNsZWFyID0gW3RoaXMuc3RvcmFnZS5yZW1vdmUoJ3NpZ25hdHVyZScpLCB0aGlzLnN0b3JhZ2UucmVtb3ZlKCd1c2VyJyksIHRoaXMuc3RvcmFnZS5yZW1vdmUoJ3JlZnJlc2hfdG9rZW4nKV07XG5cbiAgICAgICAgICAgIFByb21pc2UuYWxsKGNsZWFyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgZW5kcG9pbnQgPSB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aC9sb2dvdXQnO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVuZHBvaW50ICs9ICc/Y29udGludWU9JyArIGVuY29kZVVSSUNvbXBvbmVudChyZWRpcmVjdFVyaSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbmRwb2ludCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFN0YXRlKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgnc3RhdGUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYnVpbGROZXN0ZWRVcmkocm91dGU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QpOiBzdHJpbmcge1xuICAgICAgICBsZXQgdXJpID0gJyc7XG5cbiAgICAgICAgaWYgKHJvdXRlLnJvdXRlQ29uZmlnICYmIHJvdXRlLnJvdXRlQ29uZmlnLnBhdGgpIHtcbiAgICAgICAgICAgIGxldCByb3V0ZVBhdGggPSByb3V0ZS5yb3V0ZUNvbmZpZy5wYXRoO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiByb3V0ZS5wYXJhbXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cCgnOicgKyBrZXkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJvdXRlUGF0aCA9IHJvdXRlUGF0aC5yZXBsYWNlKHJlLCByb3V0ZS5wYXJhbXNba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cmkgKz0gJy8nICsgcm91dGVQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJvdXRlLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICByb3V0ZS5jaGlsZHJlbi5mb3JFYWNoKChpdGVtOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gICAgICAgICAgICAgICAgdXJpICs9IHRoaXMuYnVpbGROZXN0ZWRVcmkoaXRlbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1cmk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWZyZXNoVG9rZW4oKTogUHJvbWlzZTxTaWduYXR1cmUgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLnJlZnJlc2hUb2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgncmVmcmVzaF90b2tlbicpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q2xpZW50U2VjcmV0KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy5jbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5jbGllbnRTZWNyZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ2NsaWVudF9zZWNyZXQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFVyaShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2FwaS8nICsgdGhpcy5WRVJTSU9OICsgcGF0aDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Q3VycmVudE9yaWdpbihwYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB0aGlzLmxvY2F0aW9uLnByZXBhcmVFeHRlcm5hbFVybChwYXRoIHx8ICcnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU3RhdGUoKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcG9zc2libGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICAgICAgICBsZXQgdGV4dCA9ICcnO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICB0ZXh0ICs9IHBvc3NpYmxlLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBwb3NzaWJsZS5sZW5ndGgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRRdWVyeVN0cmluZyhwYXJhbXM6IG9iamVjdCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocGFyYW1zKS5tYXAoKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXMuam9pbignJicpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnb1RvQWNjb3VudEVuZHBvaW50KHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCByZXNwb25zZVR5cGU/OiAndG9rZW4nIHwgJ2NvZGUnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGx0cmltID0gdGV4dCA9PiB0ZXh0LnJlcGxhY2UoL15cXC8rLywgJycpO1xuXG4gICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLmdldEN1cnJlbnRPcmlnaW4oJy8nICsgbHRyaW0odGhpcy5idWlsZE5lc3RlZFVyaShyb3V0ZS5yb290KSkpO1xuXG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ25hY29faW50ZW5kZWRfdXJsJywgbmV4dCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlZGlyZWN0KFxuICAgICAgICAgICAgICAgIHRoaXMubG9naW4odGhpcy5jb25maWcuc2NvcGVzLCB0aGlzLmdldEN1cnJlbnRPcmlnaW4oJy9hdXRoJyksIGZhbHNlLCByZXNwb25zZVR5cGUgfHwgdGhpcy5jb25maWcucmVzcG9uc2VUeXBlLCB0cnVlKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnb1RvSW50ZW5kZWRVcmwoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5nZXQ8c3RyaW5nPignbmFjb19pbnRlbmRlZF91cmwnKS50aGVuKHVybCA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCduYWNvX2ludGVuZGVkX3VybCcpO1xuICAgICAgICAgICAgdGhpcy5yZWRpcmVjdCh1cmwgfHwgJy8nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZGlyZWN0KHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgIH1cbn1cbiJdfQ== |
\ | No newline at end of file |