ngx-oauth 4.2.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,300 @@
1
+ import { Inject, Injectable } from '@angular/core';
2
+ import { HttpParams } from '@angular/common/http';
3
+ import { catchError, concatMap, delay, filter, map, shareReplay, switchMap, tap } from 'rxjs/operators';
4
+ import { firstValueFrom, from, noop, of, ReplaySubject, throwError } from 'rxjs';
5
+ import { HEADER_APPLICATION, LOCATION, OAuthStatus, OAuthType } from '../models';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "../models";
8
+ import * as i2 from "./token.service";
9
+ import * as i3 from "@angular/common/http";
10
+ import * as i4 from "@angular/common";
11
+ const arrToString = (buf) => buf.reduce((s, b) => s + String.fromCharCode(b), '');
12
+ const base64url = (str) => btoa(str)
13
+ .replace(/\+/g, '-')
14
+ .replace(/\//g, '_')
15
+ .replace(/=/g, '');
16
+ const randomString = (length = 48) => {
17
+ const buff = arrToString(crypto.getRandomValues(new Uint8Array(length * 2)));
18
+ return base64url(buff).substring(0, length);
19
+ };
20
+ const pkce = async (value) => {
21
+ const buff = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));
22
+ return base64url(arrToString(new Uint8Array(buff)));
23
+ };
24
+ const parseOauthUri = (hash) => {
25
+ const regex = /([^&=]+)=([^&]*)/g;
26
+ const params = {};
27
+ let m;
28
+ // tslint:disable-next-line:no-conditional-assignment
29
+ while ((m = regex.exec(hash)) !== null) {
30
+ params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
31
+ }
32
+ return Object.keys(params).length && params || {};
33
+ };
34
+ const jwt = (token) => JSON.parse(atob(token.split('.')[1]));
35
+ export class OAuthService {
36
+ constructor(authConfig, tokenService, http, location, locationService) {
37
+ this.authConfig = authConfig;
38
+ this.tokenService = tokenService;
39
+ this.http = http;
40
+ this.location = location;
41
+ this.locationService = locationService;
42
+ this.state$ = new ReplaySubject(1);
43
+ this.config$ = of(this.config).pipe(filter(Boolean), filter(config => !!config?.clientId), map(config => config), switchMap(config => !config.issuerPath && of(config) || this.http.get(`${config.issuerPath}/.well-known/openid-configuration`).pipe(tap(v => this.config = {
44
+ ...v.authorization_endpoint && { authorizePath: v.authorization_endpoint } || {},
45
+ ...v.token_endpoint && { tokenPath: v.token_endpoint } || {},
46
+ ...v.revocation_endpoint && { revokePath: v.revocation_endpoint } || {},
47
+ ...v.code_challenge_methods_supported && { pkce: v.code_challenge_methods_supported.indexOf('S256') > -1 } || {},
48
+ ...v.userinfo_endpoint && { userPath: v.userinfo_endpoint } || {},
49
+ ...v.introspection_endpoint && { introspectionPath: v.introspection_endpoint } || {},
50
+ ...v.end_session_endpoint && { logoutPath: v.end_session_endpoint } || {},
51
+ ...{ scope: config.scope || 'openid' }
52
+ }), map(() => this.config))), shareReplay(1));
53
+ this.token$ = this.config$.pipe(tap(config => {
54
+ const { hash, search, origin, pathname } = this.location;
55
+ const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
56
+ const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search) || hash && /(code=)|(error=)/.test(hash);
57
+ if (isImplicitRedirect) {
58
+ const parameters = parseOauthUri(hash.substring(1));
59
+ this.token = {
60
+ ...parameters,
61
+ type: OAuthType.IMPLICIT,
62
+ };
63
+ this.checkResponse(this.token, parameters);
64
+ }
65
+ else if (isAuthCodeRedirect) {
66
+ const parameters = parseOauthUri(search && search.substring(1) || hash && hash.substring(1));
67
+ if (!this.checkResponse(this.token, parameters)) {
68
+ this.token = parameters;
69
+ }
70
+ else {
71
+ const newParametersString = this.getCleanedUnSearchParameters();
72
+ const { clientId, clientSecret, tokenPath, scope } = config;
73
+ const { codeVerifier } = this.token || {}; //should be set by authorizationUrl construction
74
+ this.http.post(tokenPath, new HttpParams({
75
+ fromObject: {
76
+ code: parameters?.['code'],
77
+ client_id: clientId,
78
+ ...clientSecret && { client_secret: clientSecret } || {},
79
+ redirect_uri: `${origin}${pathname}`,
80
+ grant_type: 'authorization_code',
81
+ ...scope && { scope } || {},
82
+ ...codeVerifier && { code_verifier: codeVerifier } || {}
83
+ }
84
+ }), { headers: HEADER_APPLICATION }).pipe().subscribe(token => {
85
+ this.token = {
86
+ ...token,
87
+ type: OAuthType.AUTHORIZATION_CODE
88
+ };
89
+ this.locationService.replaceState(`${pathname}${newParametersString}`);
90
+ });
91
+ }
92
+ }
93
+ }), switchMap(() => this.tokenService.token$), shareReplay(1));
94
+ this.status$ = this.token$.pipe(map(token => token.access_token && OAuthStatus.AUTHORIZED || token.error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED), shareReplay(1));
95
+ this.userInfo$ = this.status$.pipe(filter(s => s === OAuthStatus.AUTHORIZED), map(() => this.config.userPath), filter(Boolean), switchMap(path => this.getUserInfo(path)), shareReplay(1));
96
+ this.type$ = this.tokenService.type$;
97
+ this.ignorePaths = this.authConfig.ignorePaths || [];
98
+ }
99
+ get storageKey() {
100
+ return this.authConfig.storageKey;
101
+ }
102
+ set storageKey(storageKey) {
103
+ if (storageKey) {
104
+ this.authConfig.storageKey = storageKey;
105
+ this.tokenService.token = this.tokenService.saved;
106
+ }
107
+ }
108
+ get token() {
109
+ return this.tokenService.token;
110
+ }
111
+ set token(token) {
112
+ this.tokenService.token = token;
113
+ }
114
+ get config() {
115
+ return this.authConfig.config;
116
+ }
117
+ set config(config) {
118
+ if (config) {
119
+ this.authConfig.config = {
120
+ ...this.authConfig.config,
121
+ ...config
122
+ };
123
+ }
124
+ }
125
+ async login(parameters) {
126
+ if (!!parameters && parameters.password) {
127
+ await this.resourceLogin(parameters);
128
+ }
129
+ else if (!!parameters && parameters.redirectUri && parameters.responseType) {
130
+ await this.toAuthorizationUrl(parameters);
131
+ }
132
+ else {
133
+ await this.clientCredentialLogin();
134
+ }
135
+ }
136
+ logout(useLogoutUrl) {
137
+ this.revoke();
138
+ this.token = {};
139
+ const { logoutPath, logoutRedirectUri } = this.authConfig.config;
140
+ if (useLogoutUrl && logoutPath) {
141
+ const { origin, pathname } = this.location;
142
+ const currentPath = `${origin}${pathname}`;
143
+ this.location.replace(`${logoutPath}?post_logout_redirect_uri=${logoutRedirectUri || currentPath}`);
144
+ }
145
+ }
146
+ getUserInfo(path) {
147
+ const { userPath } = this.config;
148
+ return this.http.get(path || userPath);
149
+ }
150
+ revoke() {
151
+ const { revokePath, clientId, clientSecret } = this.authConfig.config;
152
+ if (revokePath) {
153
+ const { access_token, refresh_token } = this.token || {};
154
+ const toRevoke = [];
155
+ if (access_token) {
156
+ toRevoke.push({
157
+ ...clientId && { client_id: clientId } || {},
158
+ ...clientSecret && { client_secret: clientSecret } || {},
159
+ token: access_token,
160
+ token_type_hint: 'access_token'
161
+ });
162
+ }
163
+ if (refresh_token) {
164
+ toRevoke.push({
165
+ ...clientId && { client_id: clientId } || {},
166
+ ...clientSecret && { client_secret: clientSecret } || {},
167
+ token: refresh_token,
168
+ token_type_hint: 'refresh_token'
169
+ });
170
+ }
171
+ from(toRevoke).pipe(concatMap(o => of(o).pipe(delay(300))), // space request to avoid cancellation
172
+ switchMap(o => this.http.post(revokePath, new HttpParams({ fromObject: o })))).subscribe(noop);
173
+ }
174
+ }
175
+ clientCredentialLogin() {
176
+ const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
177
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
178
+ fromObject: {
179
+ client_id: clientId,
180
+ client_secret: clientSecret,
181
+ grant_type: OAuthType.CLIENT_CREDENTIAL,
182
+ ...scope ? { scope } : {},
183
+ }
184
+ }), { headers: HEADER_APPLICATION }).pipe(catchError((err) => {
185
+ this.token = err;
186
+ return throwError(() => err);
187
+ }), tap(params => {
188
+ this.token = {
189
+ ...params,
190
+ type: OAuthType.CLIENT_CREDENTIAL,
191
+ };
192
+ })));
193
+ }
194
+ resourceLogin(parameters) {
195
+ const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
196
+ const { username, password } = parameters;
197
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
198
+ fromObject: {
199
+ client_id: clientId,
200
+ ...clientSecret && { client_secret: clientSecret } || {},
201
+ grant_type: OAuthType.RESOURCE,
202
+ ...scope && { scope } || {},
203
+ username,
204
+ password
205
+ }
206
+ }), { headers: HEADER_APPLICATION }).pipe(catchError(err => {
207
+ this.token = err;
208
+ return throwError(() => err);
209
+ }), tap(params => {
210
+ this.token = {
211
+ ...params,
212
+ type: OAuthType.RESOURCE,
213
+ };
214
+ })));
215
+ }
216
+ async toAuthorizationUrl(parameters) {
217
+ const { config } = this.authConfig;
218
+ let authorizationUrl = `${config.authorizePath}`;
219
+ authorizationUrl += config.authorizePath.includes('?') && '&' || '?';
220
+ authorizationUrl += `client_id=${config.clientId}`;
221
+ authorizationUrl += `&redirect_uri=${encodeURIComponent(parameters.redirectUri)}`;
222
+ authorizationUrl += `&response_type=${parameters.responseType}`;
223
+ authorizationUrl += `&scope=${encodeURIComponent(config.scope || '')}`;
224
+ authorizationUrl += `&state=${encodeURIComponent(parameters.state || '')}`;
225
+ return this.location.replace(`${authorizationUrl}${this.generateNonce(config)}${await this.generateCodeChallenge(config)}`);
226
+ }
227
+ async generateCodeChallenge(config) {
228
+ if (config.pkce) {
229
+ const codeVerifier = randomString();
230
+ this.token = { ...this.token, codeVerifier };
231
+ return `&code_challenge=${await pkce(codeVerifier)}&code_challenge_method=S256`;
232
+ }
233
+ return '';
234
+ }
235
+ generateNonce(config) {
236
+ if (config && config.scope && config.scope.indexOf('openid') > -1) {
237
+ const nonce = randomString(10);
238
+ this.token = { ...this.token, nonce };
239
+ return `&nonce=${nonce}`;
240
+ }
241
+ return '';
242
+ }
243
+ checkResponse(token, parameters) {
244
+ this.emitState(parameters);
245
+ this.cleanLocationHash();
246
+ if (!parameters || parameters['error']) {
247
+ return false;
248
+ }
249
+ if (token && token.nonce && parameters['access_token']) {
250
+ const jwtToken = jwt(parameters['access_token']);
251
+ return token.nonce === jwtToken.nonce;
252
+ }
253
+ return parameters['access_token'] || parameters['code'];
254
+ }
255
+ getCleanedUnSearchParameters() {
256
+ const { search } = this.location;
257
+ let searchString = search && search.substring(1) || '';
258
+ const hashKeys = ['code', 'state', 'error', 'error_description', 'session_state', 'scope', 'authuser', 'prompt'];
259
+ hashKeys.forEach(hashKey => {
260
+ const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
261
+ searchString = searchString.replace(re, '');
262
+ });
263
+ return searchString.length && `?${searchString}` || '';
264
+ }
265
+ cleanLocationHash() {
266
+ const { hash } = this.location;
267
+ let curHash = hash && hash.substring(1) || '';
268
+ const hashKeys = [
269
+ 'access_token',
270
+ 'token_type',
271
+ 'expires_in',
272
+ 'scope',
273
+ 'state',
274
+ 'error',
275
+ 'error_description',
276
+ 'session_state',
277
+ 'nonce',
278
+ 'id_token',
279
+ 'code'
280
+ ];
281
+ hashKeys.forEach(hashKey => {
282
+ const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
283
+ curHash = curHash.replace(re, '');
284
+ });
285
+ this.location.hash = curHash;
286
+ }
287
+ emitState(parameters) {
288
+ const { state } = parameters || {};
289
+ state && this.state$.next(state);
290
+ }
291
+ }
292
+ OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: OAuthService, deps: [{ token: i1.OAuthConfig }, { token: i2.OAuthTokenService }, { token: i3.HttpClient }, { token: LOCATION }, { token: i4.Location }], target: i0.ɵɵFactoryTarget.Injectable });
293
+ OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: OAuthService });
294
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: OAuthService, decorators: [{
295
+ type: Injectable
296
+ }], ctorParameters: function () { return [{ type: i1.OAuthConfig }, { type: i2.OAuthTokenService }, { type: i3.HttpClient }, { type: Location, decorators: [{
297
+ type: Inject,
298
+ args: [LOCATION]
299
+ }] }, { type: i4.Location }]; } });
300
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2F1dGguc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1vYXV0aC9zcmMvc2VydmljZXMvb2F1dGguc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsTUFBTSxFQUFFLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNqRCxPQUFPLEVBQWEsVUFBVSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RyxPQUFPLEVBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDL0UsT0FBTyxFQUdMLGtCQUFrQixFQUNsQixRQUFRLEVBR1IsV0FBVyxFQUVYLFNBQVMsRUFNVixNQUFNLFdBQVcsQ0FBQzs7Ozs7O0FBSW5CLE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBZSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFFOUYsTUFBTSxTQUFTLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7S0FDekMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7S0FDbkIsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7S0FDbkIsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztBQUVyQixNQUFNLFlBQVksR0FBRyxDQUFDLFNBQWlC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SSxFQUFFLENBQUM7UUFDakMsS0FBSyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25DLENBQUM7O3lHQWhUVSxZQUFZLHdHQW1ISCxRQUFROzZHQW5IakIsWUFBWTsyRkFBWixZQUFZO2tCQUR4QixVQUFVOzswQkFvSEksTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtIdHRwQ2xpZW50LCBIdHRwUGFyYW1zfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQge2NhdGNoRXJyb3IsIGNvbmNhdE1hcCwgZGVsYXksIGZpbHRlciwgbWFwLCBzaGFyZVJlcGxheSwgc3dpdGNoTWFwLCB0YXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7Zmlyc3RWYWx1ZUZyb20sIGZyb20sIG5vb3AsIG9mLCBSZXBsYXlTdWJqZWN0LCB0aHJvd0Vycm9yfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIEF1dGhvcml6YXRpb25Db2RlQ29uZmlnLFxuICBBdXRob3JpemF0aW9uUGFyYW1ldGVycyxcbiAgSEVBREVSX0FQUExJQ0FUSU9OLFxuICBMT0NBVElPTixcbiAgT0F1dGhDb25maWcsXG4gIE9BdXRoUGFyYW1ldGVycyxcbiAgT0F1dGhTdGF0dXMsXG4gIE9BdXRoVG9rZW4sXG4gIE9BdXRoVHlwZSxcbiAgT0F1dGhUeXBlQ29uZmlnLFxuICBPcGVuSWRDb25maWcsXG4gIE9wZW5JZENvbmZpZ3VyYXRpb24sXG4gIFJlc291cmNlUGFyYW1ldGVycyxcbiAgVXNlckluZm9cbn0gZnJvbSAnLi4vbW9kZWxzJztcbmltcG9ydCB7TG9jYXRpb24gYXMgTG9jYXRpb24yfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtPQXV0aFRva2VuU2VydmljZX0gZnJvbSAnLi90b2tlbi5zZXJ2aWNlJztcblxuY29uc3QgYXJyVG9TdHJpbmcgPSAoYnVmOiBVaW50OEFycmF5KSA9PiBidWYucmVkdWNlKChzLCBiKSA9PiBzICsgU3RyaW5nLmZyb21DaGFyQ29kZShiKSwgJycpO1xuXG5jb25zdCBiYXNlNjR1cmwgPSAoc3RyOiBzdHJpbmcpID0+IGJ0b2Eoc3RyKVxuICAucmVwbGFjZSgvXFwrL2csICctJylcbiAgLnJlcGxhY2UoL1xcLy9nLCAnXycpXG4gIC5yZXBsYWNlKC89L2csICcnKTtcblxuY29uc3QgcmFuZG9tU3RyaW5nID0gKGxlbmd0aDogbnVtYmVyID0gNDgpID0+IHtcbiAgY29uc3QgYnVmZiA9IGFyclRvU3RyaW5nKGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkobGVuZ3RoICogMikpKTtcbiAgcmV0dXJuIGJhc2U2NHVybChidWZmKS5zdWJzdHJpbmcoMCwgbGVuZ3RoKTtcbn07XG5cbmNvbnN0IHBrY2UgPSBhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuICBjb25zdCBidWZmID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5kaWdlc3QoJ1NIQS0yNTYnLCBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUodmFsdWUpKTtcbiAgcmV0dXJuIGJhc2U2NHVybChhcnJUb1N0cmluZyhuZXcgVWludDhBcnJheShidWZmKSkpO1xufTtcblxuY29uc3QgcGFyc2VPYXV0aFVyaSA9IChoYXNoOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgcmVnZXggPSAvKFteJj1dKyk9KFteJl0qKS9nO1xuICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgbGV0IG07XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1jb25kaXRpb25hbC1hc3NpZ25tZW50XG4gIHdoaWxlICgobSA9IHJlZ2V4LmV4ZWMoaGFzaCkpICE9PSBudWxsKSB7XG4gICAgcGFyYW1zW2RlY29kZVVSSUNvbXBvbmVudChtWzFdKV0gPSBkZWNvZGVVUklDb21wb25lbnQobVsyXSk7XG4gIH1cbiAgcmV0dXJuIE9iamVjdC5rZXlzKHBhcmFtcykubGVuZ3RoICYmIHBhcmFtcyB8fCB7fTtcbn07XG5cbmNvbnN0IGp3dCA9ICh0b2tlbjogc3RyaW5nKSA9PiBKU09OLnBhcnNlKGF0b2IodG9rZW4uc3BsaXQoJy4nKVsxXSkpO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgT0F1dGhTZXJ2aWNlIHtcblxuICBzdGF0ZSQgPSBuZXcgUmVwbGF5U3ViamVjdDxzdHJpbmc+KDEpO1xuICBjb25maWckID0gb2YodGhpcy5jb25maWcpLnBpcGUoXG4gICAgZmlsdGVyKEJvb2xlYW4pLFxuICAgIGZpbHRlcihjb25maWcgPT4gISFjb25maWc/LmNsaWVudElkKSxcbiAgICBtYXAoY29uZmlnID0+IGNvbmZpZyBhcyBPcGVuSWRDb25maWcpLFxuICAgIHN3aXRjaE1hcChjb25maWcgPT4gIWNvbmZpZy5pc3N1ZXJQYXRoICYmIG9mKGNvbmZpZykgfHwgdGhpcy5odHRwLmdldDxPcGVuSWRDb25maWd1cmF0aW9uPihgJHtjb25maWcuaXNzdWVyUGF0aH0vLndlbGwta25vd24vb3BlbmlkLWNvbmZpZ3VyYXRpb25gKS5waXBlKFxuICAgICAgdGFwKHYgPT4gdGhpcy5jb25maWcgPSB7XG4gICAgICAgIC4uLnYuYXV0aG9yaXphdGlvbl9lbmRwb2ludCAmJiB7YXV0aG9yaXplUGF0aDogdi5hdXRob3JpemF0aW9uX2VuZHBvaW50fSB8fCB7fSxcbiAgICAgICAgLi4udi50b2tlbl9lbmRwb2ludCAmJiB7dG9rZW5QYXRoOiB2LnRva2VuX2VuZHBvaW50fSB8fCB7fSxcbiAgICAgICAgLi4udi5yZXZvY2F0aW9uX2VuZHBvaW50ICYmIHtyZXZva2VQYXRoOiB2LnJldm9jYXRpb25fZW5kcG9pbnR9IHx8IHt9LFxuICAgICAgICAuLi52LmNvZGVfY2hhbGxlbmdlX21ldGhvZHNfc3VwcG9ydGVkICYmIHtwa2NlOiB2LmNvZGVfY2hhbGxlbmdlX21ldGhvZHNfc3VwcG9ydGVkLmluZGV4T2YoJ1MyNTYnKSA+IC0xfSB8fCB7fSxcbiAgICAgICAgLi4udi51c2VyaW5mb19lbmRwb2ludCAmJiB7dXNlclBhdGg6IHYudXNlcmluZm9fZW5kcG9pbnR9IHx8IHt9LFxuICAgICAgICAuLi52LmludHJvc3BlY3Rpb25fZW5kcG9pbnQgJiYge2ludHJvc3BlY3Rpb25QYXRoOiB2LmludHJvc3BlY3Rpb25fZW5kcG9pbnR9IHx8IHt9LFxuICAgICAgICAuLi52LmVuZF9zZXNzaW9uX2VuZHBvaW50ICYmIHtsb2dvdXRQYXRoOiB2LmVuZF9zZXNzaW9uX2VuZHBvaW50fSB8fCB7fSxcbiAgICAgICAgLi4ue3Njb3BlOiBjb25maWcuc2NvcGUgfHwgJ29wZW5pZCd9XG4gICAgICB9IGFzIGFueSksXG4gICAgICBtYXAoKCkgPT4gdGhpcy5jb25maWcpXG4gICAgKSksXG4gICAgc2hhcmVSZXBsYXkoMSlcbiAgKTtcbiAgdG9rZW4kID0gdGhpcy5jb25maWckLnBpcGUoXG4gICAgdGFwKGNvbmZpZyA9PiB7XG4gICAgICBjb25zdCB7aGFzaCwgc2VhcmNoLCBvcmlnaW4sIHBhdGhuYW1lfSA9IHRoaXMubG9jYXRpb247XG4gICAgICBjb25zdCBpc0ltcGxpY2l0UmVkaXJlY3QgPSBoYXNoICYmIC8oYWNjZXNzX3Rva2VuPSl8KGVycm9yPSkvLnRlc3QoaGFzaCk7XG4gICAgICBjb25zdCBpc0F1dGhDb2RlUmVkaXJlY3QgPSBzZWFyY2ggJiYgLyhjb2RlPSl8KGVycm9yPSkvLnRlc3Qoc2VhcmNoKSB8fCBoYXNoICYmIC8oY29kZT0pfChlcnJvcj0pLy50ZXN0KGhhc2gpO1xuICAgICAgaWYgKGlzSW1wbGljaXRSZWRpcmVjdCkge1xuICAgICAgICBjb25zdCBwYXJhbWV0ZXJzID0gcGFyc2VPYXV0aFVyaShoYXNoLnN1YnN0cmluZygxKSk7XG4gICAgICAgIHRoaXMudG9rZW4gPSB7XG4gICAgICAgICAgLi4ucGFyYW1ldGVycyxcbiAgICAgICAgICB0eXBlOiBPQXV0aFR5cGUuSU1QTElDSVQsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2hlY2tSZXNwb25zZSh0aGlzLnRva2VuLCBwYXJhbWV0ZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNBdXRoQ29kZVJlZGlyZWN0KSB7XG4gICAgICAgIGNvbnN0IHBhcmFtZXRlcnMgPSBwYXJzZU9hdXRoVXJpKHNlYXJjaCAmJiBzZWFyY2guc3Vic3RyaW5nKDEpIHx8IGhhc2ggJiYgaGFzaC5zdWJzdHJpbmcoMSkpO1xuICAgICAgICBpZiAoIXRoaXMuY2hlY2tSZXNwb25zZSh0aGlzLnRva2VuLCBwYXJhbWV0ZXJzKSkge1xuICAgICAgICAgIHRoaXMudG9rZW4gPSBwYXJhbWV0ZXJzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IG5ld1BhcmFtZXRlcnNTdHJpbmcgPSB0aGlzLmdldENsZWFuZWRVblNlYXJjaFBhcmFtZXRlcnMoKTtcbiAgICAgICAgICBjb25zdCB7Y2xpZW50SWQsIGNsaWVudFNlY3JldCwgdG9rZW5QYXRoLCBzY29wZX0gPSBjb25maWcgYXMgQXV0aG9yaXphdGlvbkNvZGVDb25maWc7XG4gICAgICAgICAgY29uc3Qge2NvZGVWZXJpZmllcn0gPSB0aGlzLnRva2VuIHx8IHt9OyAvL3Nob3VsZCBiZSBzZXQgYnkgYXV0aG9yaXphdGlvblVybCBjb25zdHJ1Y3Rpb25cbiAgICAgICAgICB0aGlzLmh0dHAucG9zdCh0b2tlblBhdGgsIG5ldyBIdHRwUGFyYW1zKHtcbiAgICAgICAgICAgIGZyb21PYmplY3Q6IHtcbiAgICAgICAgICAgICAgY29kZTogcGFyYW1ldGVycz8uWydjb2RlJ10sXG4gICAgICAgICAgICAgIGNsaWVudF9pZDogY2xpZW50SWQsXG4gICAgICAgICAgICAgIC4uLmNsaWVudFNlY3JldCAmJiB7Y2xpZW50X3NlY3JldDogY2xpZW50U2VjcmV0fSB8fCB7fSxcbiAgICAgICAgICAgICAgcmVkaXJlY3RfdXJpOiBgJHtvcmlnaW59JHtwYXRobmFtZX1gLFxuICAgICAgICAgICAgICBncmFudF90eXBlOiAnYXV0aG9yaXphdGlvbl9jb2RlJyxcbiAgICAgICAgICAgICAgLi4uc2NvcGUgJiYge3Njb3BlfSB8fCB7fSxcbiAgICAgICAgICAgICAgLi4uY29kZVZlcmlmaWVyICYmIHtjb2RlX3ZlcmlmaWVyOiBjb2RlVmVyaWZpZXJ9IHx8IHt9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSksIHtoZWFkZXJzOiBIRUFERVJfQVBQTElDQVRJT059KS5waXBlKFxuICAgICAgICAgICkuc3Vic2NyaWJlKHRva2VuID0+IHtcbiAgICAgICAgICAgIHRoaXMudG9rZW4gPSB7XG4gICAgICAgICAgICAgIC4uLnRva2VuLFxuICAgICAgICAgICAgICB0eXBlOiBPQXV0aFR5cGUuQVVUSE9SSVpBVElPTl9DT0RFXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5sb2NhdGlvblNlcnZpY2UucmVwbGFjZVN0YXRlKGAke3BhdGhuYW1lfSR7bmV3UGFyYW1ldGVyc1N0cmluZ31gKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pLFxuICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLnRva2VuU2VydmljZS50b2tlbiQpLFxuICAgIHNoYXJlUmVwbGF5KDEpXG4gICk7XG4gIHN0YXR1cyQgPSB0aGlzLnRva2VuJC5waXBlKFxuICAgIG1hcCh0b2tlbiA9PiB0b2tlbi5hY2Nlc3NfdG9rZW4gJiYgT0F1dGhTdGF0dXMuQVVUSE9SSVpFRCB8fCB0b2tlbi5lcnJvciAmJiBPQXV0aFN0YXR1cy5ERU5JRUQgfHwgT0F1dGhTdGF0dXMuTk9UX0FVVEhPUklaRUQpLFxuICAgIHNoYXJlUmVwbGF5KDEpXG4gICk7XG4gIHVzZXJJbmZvJCA9IHRoaXMuc3RhdHVzJC5waXBlKFxuICAgIGZpbHRlcihzID0+IHMgPT09IE9BdXRoU3RhdHVzLkFVVEhPUklaRUQpLFxuICAgIG1hcCgoKSA9PiAodGhpcy5jb25maWcgYXMgYW55KS51c2VyUGF0aCksXG4gICAgZmlsdGVyKEJvb2xlYW4pLFxuICAgIHN3aXRjaE1hcChwYXRoID0+IHRoaXMuZ2V0VXNlckluZm8ocGF0aCkpLFxuICAgIHNoYXJlUmVwbGF5KDEpXG4gICk7XG4gIHR5cGUkID0gdGhpcy50b2tlblNlcnZpY2UudHlwZSQ7XG4gIGlnbm9yZVBhdGhzID0gdGhpcy5hdXRoQ29uZmlnLmlnbm9yZVBhdGhzIHx8IFtdO1xuXG4gIGdldCBzdG9yYWdlS2V5KCkge1xuICAgIHJldHVybiB0aGlzLmF1dGhDb25maWcuc3RvcmFnZUtleTtcbiAgfVxuXG4gIHNldCBzdG9yYWdlS2V5KHN0b3JhZ2VLZXkpIHtcbiAgICBpZiAoc3RvcmFnZUtleSkge1xuICAgICAgdGhpcy5hdXRoQ29uZmlnLnN0b3JhZ2VLZXkgPSBzdG9yYWdlS2V5O1xuICAgICAgdGhpcy50b2tlblNlcnZpY2UudG9rZW4gPSB0aGlzLnRva2VuU2VydmljZS5zYXZlZDtcbiAgICB9XG4gIH1cblxuICBnZXQgdG9rZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMudG9rZW5TZXJ2aWNlLnRva2VuO1xuICB9XG5cbiAgc2V0IHRva2VuKHRva2VuKSB7XG4gICAgdGhpcy50b2tlblNlcnZpY2UudG9rZW4gPSB0b2tlbjtcbiAgfVxuXG4gIGdldCBjb25maWcoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aENvbmZpZy5jb25maWc7XG4gIH1cblxuICBzZXQgY29uZmlnKGNvbmZpZzogT0F1dGhUeXBlQ29uZmlnIHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKGNvbmZpZykge1xuICAgICAgdGhpcy5hdXRoQ29uZmlnLmNvbmZpZyA9IHtcbiAgICAgICAgLi4udGhpcy5hdXRoQ29uZmlnLmNvbmZpZyxcbiAgICAgICAgLi4uY29uZmlnXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBhdXRoQ29uZmlnOiBPQXV0aENvbmZpZyxcbiAgICAgICAgICAgICAgcHJvdGVjdGVkIHRva2VuU2VydmljZTogT0F1dGhUb2tlblNlcnZpY2UsXG4gICAgICAgICAgICAgIHByb3RlY3RlZCBodHRwOiBIdHRwQ2xpZW50LFxuICAgICAgICAgICAgICBASW5qZWN0KExPQ0FUSU9OKSBwcm90ZWN0ZWQgbG9jYXRpb246IExvY2F0aW9uLFxuICAgICAgICAgICAgICBwcm90ZWN0ZWQgbG9jYXRpb25TZXJ2aWNlOiBMb2NhdGlvbjIpIHtcbiAgfVxuXG4gIGFzeW5jIGxvZ2luKHBhcmFtZXRlcnM/OiBPQXV0aFBhcmFtZXRlcnMpIHtcbiAgICBpZiAoISFwYXJhbWV0ZXJzICYmIChwYXJhbWV0ZXJzIGFzIFJlc291cmNlUGFyYW1ldGVycykucGFzc3dvcmQpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVzb3VyY2VMb2dpbihwYXJhbWV0ZXJzIGFzIFJlc291cmNlUGFyYW1ldGVycyk7XG4gICAgfSBlbHNlIGlmICghIXBhcmFtZXRlcnMgJiYgKHBhcmFtZXRlcnMgYXMgQXV0aG9yaXphdGlvblBhcmFtZXRlcnMpLnJlZGlyZWN0VXJpICYmIChwYXJhbWV0ZXJzIGFzIEF1dGhvcml6YXRpb25QYXJhbWV0ZXJzKS5yZXNwb25zZVR5cGVcbiAgICApIHtcbiAgICAgIGF3YWl0IHRoaXMudG9BdXRob3JpemF0aW9uVXJsKHBhcmFtZXRlcnMgYXMgQXV0aG9yaXphdGlvblBhcmFtZXRlcnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmNsaWVudENyZWRlbnRpYWxMb2dpbigpO1xuICAgIH1cbiAgfVxuXG4gIGxvZ291dCh1c2VMb2dvdXRVcmw/OiBib29sZWFuKSB7XG4gICAgdGhpcy5yZXZva2UoKTtcbiAgICB0aGlzLnRva2VuID0ge307XG4gICAgY29uc3Qge2xvZ291dFBhdGgsIGxvZ291dFJlZGlyZWN0VXJpfSA9IHRoaXMuYXV0aENvbmZpZy5jb25maWcgYXMgYW55O1xuICAgIGlmICh1c2VMb2dvdXRVcmwgJiYgbG9nb3V0UGF0aCkge1xuICAgICAgY29uc3Qge29yaWdpbiwgcGF0aG5hbWV9ID0gdGhpcy5sb2NhdGlvbjtcbiAgICAgIGNvbnN0IGN1cnJlbnRQYXRoID0gYCR7b3JpZ2lufSR7cGF0aG5hbWV9YDtcbiAgICAgIHRoaXMubG9jYXRpb24ucmVwbGFjZShgJHtsb2dvdXRQYXRofT9wb3N0X2xvZ291dF9yZWRpcmVjdF91cmk9JHtsb2dvdXRSZWRpcmVjdFVyaSB8fCBjdXJyZW50UGF0aH1gKTtcbiAgICB9XG4gIH1cblxuICBnZXRVc2VySW5mbyhwYXRoPzogc3RyaW5nKSB7XG4gICAgY29uc3Qge3VzZXJQYXRofSA9IHRoaXMuY29uZmlnIGFzIGFueTtcbiAgICByZXR1cm4gdGhpcy5odHRwLmdldDxVc2VySW5mbz4ocGF0aCB8fCB1c2VyUGF0aCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmV2b2tlKCkge1xuICAgIGNvbnN0IHtyZXZva2VQYXRoLCBjbGllbnRJZCwgY2xpZW50U2VjcmV0fSA9IHRoaXMuYXV0aENvbmZpZy5jb25maWcgYXMgYW55O1xuICAgIGlmIChyZXZva2VQYXRoKSB7XG4gICAgICBjb25zdCB7YWNjZXNzX3Rva2VuLCByZWZyZXNoX3Rva2VufSA9IHRoaXMudG9rZW4gfHwge307XG4gICAgICBjb25zdCB0b1Jldm9rZSA9IFtdO1xuICAgICAgaWYgKGFjY2Vzc190b2tlbikge1xuICAgICAgICB0b1Jldm9rZS5wdXNoKHtcbiAgICAgICAgICAuLi5jbGllbnRJZCAmJiB7Y2xpZW50X2lkOiBjbGllbnRJZH0gfHwge30sXG4gICAgICAgICAgLi4uY2xpZW50U2VjcmV0ICYmIHtjbGllbnRfc2VjcmV0OiBjbGllbnRTZWNyZXR9IHx8IHt9LFxuICAgICAgICAgIHRva2VuOiBhY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgdG9rZW5fdHlwZV9oaW50OiAnYWNjZXNzX3Rva2VuJ1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChyZWZyZXNoX3Rva2VuKSB7XG4gICAgICAgIHRvUmV2b2tlLnB1c2goe1xuICAgICAgICAgIC4uLmNsaWVudElkICYmIHtjbGllbnRfaWQ6IGNsaWVudElkfSB8fCB7fSxcbiAgICAgICAgICAuLi5jbGllbnRTZWNyZXQgJiYge2NsaWVudF9zZWNyZXQ6IGNsaWVudFNlY3JldH0gfHwge30sXG4gICAgICAgICAgdG9rZW46IHJlZnJlc2hfdG9rZW4sXG4gICAgICAgICAgdG9rZW5fdHlwZV9oaW50OiAncmVmcmVzaF90b2tlbidcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBmcm9tKHRvUmV2b2tlKS5waXBlKFxuICAgICAgICBjb25jYXRNYXAobyA9PiBvZihvKS5waXBlKGRlbGF5KDMwMCkpKSwgLy8gc3BhY2UgcmVxdWVzdCB0byBhdm9pZCBjYW5jZWxsYXRpb25cbiAgICAgICAgc3dpdGNoTWFwKG8gPT4gdGhpcy5odHRwLnBvc3QocmV2b2tlUGF0aCwgbmV3IEh0dHBQYXJhbXMoe2Zyb21PYmplY3Q6IG99KSkpLFxuICAgICAgKS5zdWJzY3JpYmUobm9vcCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGNsaWVudENyZWRlbnRpYWxMb2dpbigpIHtcbiAgICBjb25zdCB7Y2xpZW50SWQsIGNsaWVudFNlY3JldCwgdG9rZW5QYXRoLCBzY29wZX0gPSB0aGlzLmF1dGhDb25maWcuY29uZmlnIGFzIGFueTtcbiAgICByZXR1cm4gZmlyc3RWYWx1ZUZyb20odGhpcy5odHRwLnBvc3QodG9rZW5QYXRoLCBuZXcgSHR0cFBhcmFtcyh7XG4gICAgICBmcm9tT2JqZWN0OiB7XG4gICAgICAgIGNsaWVudF9pZDogY2xpZW50SWQsXG4gICAgICAgIGNsaWVudF9zZWNyZXQ6IGNsaWVudFNlY3JldCxcbiAgICAgICAgZ3JhbnRfdHlwZTogT0F1dGhUeXBlLkNMSUVOVF9DUkVERU5USUFMLFxuICAgICAgICAuLi5zY29wZSA/IHtzY29wZX0gOiB7fSxcbiAgICAgIH1cbiAgICB9KSwge2hlYWRlcnM6IEhFQURFUl9BUFBMSUNBVElPTn0pLnBpcGUoXG4gICAgICBjYXRjaEVycm9yKChlcnIpID0+IHtcbiAgICAgICAgdGhpcy50b2tlbiA9IGVycjtcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyKTtcbiAgICAgIH0pLFxuICAgICAgdGFwKHBhcmFtcyA9PiB7XG4gICAgICAgIHRoaXMudG9rZW4gPSB7XG4gICAgICAgICAgLi4ucGFyYW1zLFxuICAgICAgICAgIHR5cGU6IE9BdXRoVHlwZS5DTElFTlRfQ1JFREVOVElBTCxcbiAgICAgICAgfTtcbiAgICAgIH0pLFxuICAgICkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlc291cmNlTG9naW4ocGFyYW1ldGVyczogUmVzb3VyY2VQYXJhbWV0ZXJzKSB7XG4gICAgY29uc3Qge2NsaWVudElkLCBjbGllbnRTZWNyZXQsIHRva2VuUGF0aCwgc2NvcGV9ID0gdGhpcy5hdXRoQ29uZmlnLmNvbmZpZyBhcyBhbnk7XG4gICAgY29uc3Qge3VzZXJuYW1lLCBwYXNzd29yZH0gPSBwYXJhbWV0ZXJzO1xuICAgIHJldHVybiBmaXJzdFZhbHVlRnJvbSh0aGlzLmh0dHAucG9zdCh0b2tlblBhdGgsIG5ldyBIdHRwUGFyYW1zKHtcbiAgICAgIGZyb21PYmplY3Q6IHtcbiAgICAgICAgY2xpZW50X2lkOiBjbGllbnRJZCxcbiAgICAgICAgLi4uY2xpZW50U2VjcmV0ICYmIHtjbGllbnRfc2VjcmV0OiBjbGllbnRTZWNyZXR9IHx8IHt9LFxuICAgICAgICBncmFudF90eXBlOiBPQXV0aFR5cGUuUkVTT1VSQ0UsXG4gICAgICAgIC4uLnNjb3BlICYmIHtzY29wZX0gfHwge30sXG4gICAgICAgIHVzZXJuYW1lLFxuICAgICAgICBwYXNzd29yZFxuICAgICAgfVxuICAgIH0pLCB7aGVhZGVyczogSEVBREVSX0FQUExJQ0FUSU9OfSkucGlwZShcbiAgICAgIGNhdGNoRXJyb3IoZXJyID0+IHtcbiAgICAgICAgdGhpcy50b2tlbiA9IGVycjtcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyKTtcbiAgICAgIH0pLFxuICAgICAgdGFwKHBhcmFtcyA9PiB7XG4gICAgICAgIHRoaXMudG9rZW4gPSB7XG4gICAgICAgICAgLi4ucGFyYW1zLFxuICAgICAgICAgIHR5cGU6IE9BdXRoVHlwZS5SRVNPVVJDRSxcbiAgICAgICAgfTtcbiAgICAgIH0pXG4gICAgKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgdG9BdXRob3JpemF0aW9uVXJsKHBhcmFtZXRlcnM6IEF1dGhvcml6YXRpb25QYXJhbWV0ZXJzKSB7XG4gICAgY29uc3Qge2NvbmZpZ30gPSB0aGlzLmF1dGhDb25maWcgYXMgYW55O1xuICAgIGxldCBhdXRob3JpemF0aW9uVXJsID0gYCR7Y29uZmlnLmF1dGhvcml6ZVBhdGh9YDtcbiAgICBhdXRob3JpemF0aW9uVXJsICs9IGNvbmZpZy5hdXRob3JpemVQYXRoLmluY2x1ZGVzKCc/JykgJiYgJyYnIHx8ICc/JztcbiAgICBhdXRob3JpemF0aW9uVXJsICs9IGBjbGllbnRfaWQ9JHtjb25maWcuY2xpZW50SWR9YDtcbiAgICBhdXRob3JpemF0aW9uVXJsICs9IGAmcmVkaXJlY3RfdXJpPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHBhcmFtZXRlcnMucmVkaXJlY3RVcmkpfWA7XG4gICAgYXV0aG9yaXphdGlvblVybCArPSBgJnJlc3BvbnNlX3R5cGU9JHtwYXJhbWV0ZXJzLnJlc3BvbnNlVHlwZX1gO1xuICAgIGF1dGhvcml6YXRpb25VcmwgKz0gYCZzY29wZT0ke2VuY29kZVVSSUNvbXBvbmVudChjb25maWcuc2NvcGUgfHwgJycpfWA7XG4gICAgYXV0aG9yaXphdGlvblVybCArPSBgJnN0YXRlPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHBhcmFtZXRlcnMuc3RhdGUgfHwgJycpfWA7XG4gICAgcmV0dXJuIHRoaXMubG9jYXRpb24ucmVwbGFjZShgJHthdXRob3JpemF0aW9uVXJsfSR7dGhpcy5nZW5lcmF0ZU5vbmNlKGNvbmZpZyl9JHthd2FpdCB0aGlzLmdlbmVyYXRlQ29kZUNoYWxsZW5nZShjb25maWcpfWApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdlbmVyYXRlQ29kZUNoYWxsZW5nZShjb25maWc6IGFueSkge1xuICAgIGlmIChjb25maWcucGtjZSkge1xuICAgICAgY29uc3QgY29kZVZlcmlmaWVyID0gcmFuZG9tU3RyaW5nKCk7XG4gICAgICB0aGlzLnRva2VuID0gey4uLnRoaXMudG9rZW4sIGNvZGVWZXJpZmllcn07XG4gICAgICByZXR1cm4gYCZjb2RlX2NoYWxsZW5nZT0ke2F3YWl0IHBrY2UoY29kZVZlcmlmaWVyKX0mY29kZV9jaGFsbGVuZ2VfbWV0aG9kPVMyNTZgO1xuICAgIH1cbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZXJhdGVOb25jZShjb25maWc6IGFueSkge1xuICAgIGlmIChjb25maWcgJiYgY29uZmlnLnNjb3BlICYmIGNvbmZpZy5zY29wZS5pbmRleE9mKCdvcGVuaWQnKSA+IC0xKSB7XG4gICAgICBjb25zdCBub25jZSA9IHJhbmRvbVN0cmluZygxMCk7XG4gICAgICB0aGlzLnRva2VuID0gey4uLnRoaXMudG9rZW4sIG5vbmNlfTtcbiAgICAgIHJldHVybiBgJm5vbmNlPSR7bm9uY2V9YDtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja1Jlc3BvbnNlKHRva2VuPzogT0F1dGhUb2tlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSB7XG4gICAgdGhpcy5lbWl0U3RhdGUocGFyYW1ldGVycyk7XG4gICAgdGhpcy5jbGVhbkxvY2F0aW9uSGFzaCgpO1xuICAgIGlmICghcGFyYW1ldGVycyB8fCBwYXJhbWV0ZXJzWydlcnJvciddKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICh0b2tlbiAmJiB0b2tlbi5ub25jZSAmJiBwYXJhbWV0ZXJzWydhY2Nlc3NfdG9rZW4nXSkge1xuICAgICAgY29uc3Qgand0VG9rZW4gPSBqd3QocGFyYW1ldGVyc1snYWNjZXNzX3Rva2VuJ10pO1xuICAgICAgcmV0dXJuIHRva2VuLm5vbmNlID09PSBqd3RUb2tlbi5ub25jZTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcmFtZXRlcnNbJ2FjY2Vzc190b2tlbiddIHx8IHBhcmFtZXRlcnNbJ2NvZGUnXTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q2xlYW5lZFVuU2VhcmNoUGFyYW1ldGVycygpIHtcbiAgICBjb25zdCB7c2VhcmNofSA9IHRoaXMubG9jYXRpb247XG4gICAgbGV0IHNlYXJjaFN0cmluZyA9IHNlYXJjaCAmJiBzZWFyY2guc3Vic3RyaW5nKDEpIHx8ICcnO1xuICAgIGNvbnN0IGhhc2hLZXlzID0gWydjb2RlJywgJ3N0YXRlJywgJ2Vycm9yJywgJ2Vycm9yX2Rlc2NyaXB0aW9uJywgJ3Nlc3Npb25fc3RhdGUnLCAnc2NvcGUnLCAnYXV0aHVzZXInLCAncHJvbXB0J107XG4gICAgaGFzaEtleXMuZm9yRWFjaChoYXNoS2V5ID0+IHtcbiAgICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cCgnJicgKyBoYXNoS2V5ICsgJyg9W14mXSopP3xeJyArIGhhc2hLZXkgKyAnKD1bXiZdKik/Jj8nKTtcbiAgICAgIHNlYXJjaFN0cmluZyA9IHNlYXJjaFN0cmluZy5yZXBsYWNlKHJlLCAnJyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHNlYXJjaFN0cmluZy5sZW5ndGggJiYgYD8ke3NlYXJjaFN0cmluZ31gIHx8ICcnO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhbkxvY2F0aW9uSGFzaCgpIHtcbiAgICBjb25zdCB7aGFzaH0gPSB0aGlzLmxvY2F0aW9uO1xuICAgIGxldCBjdXJIYXNoID0gaGFzaCAmJiBoYXNoLnN1YnN0cmluZygxKSB8fCAnJztcbiAgICBjb25zdCBoYXNoS2V5cyA9IFtcbiAgICAgICdhY2Nlc3NfdG9rZW4nLFxuICAgICAgJ3Rva2VuX3R5cGUnLFxuICAgICAgJ2V4cGlyZXNfaW4nLFxuICAgICAgJ3Njb3BlJyxcbiAgICAgICdzdGF0ZScsXG4gICAgICAnZXJyb3InLFxuICAgICAgJ2Vycm9yX2Rlc2NyaXB0aW9uJyxcbiAgICAgICdzZXNzaW9uX3N0YXRlJyxcbiAgICAgICdub25jZScsXG4gICAgICAnaWRfdG9rZW4nLFxuICAgICAgJ2NvZGUnXG4gICAgXTtcbiAgICBoYXNoS2V5cy5mb3JFYWNoKGhhc2hLZXkgPT4ge1xuICAgICAgY29uc3QgcmUgPSBuZXcgUmVnRXhwKCcmJyArIGhhc2hLZXkgKyAnKD1bXiZdKik/fF4nICsgaGFzaEtleSArICcoPVteJl0qKT8mPycpO1xuICAgICAgY3VySGFzaCA9IGN1ckhhc2gucmVwbGFjZShyZSwgJycpO1xuICAgIH0pO1xuICAgIHRoaXMubG9jYXRpb24uaGFzaCA9IGN1ckhhc2g7XG4gIH1cblxuICBwcml2YXRlIGVtaXRTdGF0ZShwYXJhbWV0ZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPikge1xuICAgIGNvbnN0IHtzdGF0ZX0gPSBwYXJhbWV0ZXJzIHx8IHt9O1xuICAgIHN0YXRlICYmIHRoaXMuc3RhdGUkLm5leHQoc3RhdGUpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,83 @@
1
+ var _OAuthTokenService_token$;
2
+ import { __classPrivateFieldGet } from "tslib";
3
+ import { Inject, Injectable } from '@angular/core';
4
+ import { BehaviorSubject, distinctUntilChanged, of, switchMap } from 'rxjs';
5
+ import { HEADER_APPLICATION, OAUTH_HTTP_CLIENT } from '../models';
6
+ import { catchError, map, shareReplay } from 'rxjs/operators';
7
+ import { HttpParams } from '@angular/common/http';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "../models";
10
+ import * as i2 from "@angular/common/http";
11
+ const isExpiredToken = (token) => token && token.expires && Date.now() > token.expires || false;
12
+ export class OAuthTokenService {
13
+ constructor(authConfig, http, zone) {
14
+ this.authConfig = authConfig;
15
+ this.http = http;
16
+ this.zone = zone;
17
+ _OAuthTokenService_token$.set(this, new BehaviorSubject(this.saved));
18
+ this.token$ = __classPrivateFieldGet(this, _OAuthTokenService_token$, "f").pipe(distinctUntilChanged((p, c) => JSON.stringify(p || null) === JSON.stringify(c || null)), shareReplay(1), switchMap(token => !isExpiredToken(token) && of(token) || this.refreshToken(token)));
19
+ this.type$ = this.token$.pipe(map(token => token?.type), shareReplay(1));
20
+ this.accessToken$ = this.token$.pipe(map(token => token?.access_token), shareReplay(1));
21
+ }
22
+ get token() {
23
+ return __classPrivateFieldGet(this, _OAuthTokenService_token$, "f").value;
24
+ }
25
+ set token(token) {
26
+ const expiresIn = Number(token.expires_in) || 0;
27
+ const result = {
28
+ ...token,
29
+ ...expiresIn && { expires: Date.now() + expiresIn * 1000 } || {}
30
+ };
31
+ this.saved = result;
32
+ __classPrivateFieldGet(this, _OAuthTokenService_token$, "f").next(result);
33
+ }
34
+ get saved() {
35
+ const { storageKey, storage } = this.authConfig;
36
+ return storageKey && storage && storage[storageKey] && JSON.parse(storage[storageKey]) || {};
37
+ }
38
+ set saved(token) {
39
+ const { storageKey, storage } = this.authConfig;
40
+ if (storage && storageKey) {
41
+ if (token) {
42
+ storage[storageKey] = JSON.stringify(token);
43
+ }
44
+ else {
45
+ delete storage[storageKey];
46
+ }
47
+ }
48
+ }
49
+ refreshToken(token) {
50
+ const { tokenPath, clientId, clientSecret, scope } = this.authConfig.config;
51
+ const { refresh_token } = token || {};
52
+ return tokenPath && refresh_token && this.http.post(tokenPath, new HttpParams({
53
+ fromObject: {
54
+ client_id: clientId,
55
+ ...clientSecret && { client_secret: clientSecret } || {},
56
+ grant_type: 'refresh_token',
57
+ refresh_token,
58
+ ...scope && { scope } || {},
59
+ }
60
+ }), {
61
+ headers: HEADER_APPLICATION
62
+ }).pipe(catchError(() => {
63
+ this.token = {};
64
+ return of(this.token);
65
+ }), map(token => {
66
+ this.token = {
67
+ ...this.token,
68
+ ...token
69
+ };
70
+ return this.token;
71
+ })) || of(token);
72
+ }
73
+ }
74
+ _OAuthTokenService_token$ = new WeakMap();
75
+ OAuthTokenService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: OAuthTokenService, deps: [{ token: i1.OAuthConfig }, { token: OAUTH_HTTP_CLIENT }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
76
+ OAuthTokenService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: OAuthTokenService });
77
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: OAuthTokenService, decorators: [{
78
+ type: Injectable
79
+ }], ctorParameters: function () { return [{ type: i1.OAuthConfig }, { type: i2.HttpClient, decorators: [{
80
+ type: Inject,
81
+ args: [OAUTH_HTTP_CLIENT]
82
+ }] }, { type: i0.NgZone }]; } });
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1vYXV0aC9zcmMvc2VydmljZXMvdG9rZW4uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFTLE1BQU0sZUFBZSxDQUFDO0FBQ3pELE9BQU8sRUFBQyxlQUFlLEVBQUUsb0JBQW9CLEVBQWMsRUFBRSxFQUFFLFNBQVMsRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUN0RixPQUFPLEVBQUMsa0JBQWtCLEVBQUUsaUJBQWlCLEVBQTBCLE1BQU0sV0FBVyxDQUFDO0FBQ3pGLE9BQU8sRUFBQyxVQUFVLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzVELE9BQU8sRUFBYSxVQUFVLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQzs7OztBQUU1RCxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQWtCLEVBQUUsRUFBRSxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQztBQUc3RyxNQUFNLE9BQU8saUJBQWlCO0lBaUI1QixZQUFzQixVQUF1QixFQUNJLElBQWdCLEVBQzNDLElBQVk7UUFGWixlQUFVLEdBQVYsVUFBVSxDQUFhO1FBQ0ksU0FBSSxHQUFKLElBQUksQ0FBWTtRQUMzQyxTQUFJLEdBQUosSUFBSSxDQUFRO1FBakJsQyxvQ0FBVSxJQUFJLGVBQWUsQ0FBYSxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUM7UUFDdEQsV0FBTSxHQUFHLHVCQUFBLElBQUksaUNBQVEsQ0FBQyxJQUFJLENBQ3hCLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksSUFBSSxD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RUFBRTtZQUNGLE9BQU8sRUFBRSxrQkFBa0I7U0FDNUIsQ0FBQyxDQUFDLElBQUksQ0FDTCxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDaEIsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLENBQUMsQ0FBQyxFQUNGLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxLQUFLLEdBQUc7Z0JBQ1gsR0FBRyxJQUFJLENBQUMsS0FBSztnQkFDYixHQUFHLEtBQUs7YUFDVCxDQUFDO1lBQ0YsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxDQUNILElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pCLENBQUM7Ozs4R0E5RVUsaUJBQWlCLDZDQWtCUixpQkFBaUI7a0hBbEIxQixpQkFBaUI7MkZBQWpCLGlCQUFpQjtrQkFEN0IsVUFBVTs7MEJBbUJJLE1BQU07MkJBQUMsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGUsIE5nWm9uZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgZGlzdGluY3RVbnRpbENoYW5nZWQsIE9ic2VydmFibGUsIG9mLCBzd2l0Y2hNYXB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtIRUFERVJfQVBQTElDQVRJT04sIE9BVVRIX0hUVFBfQ0xJRU5ULCBPQXV0aENvbmZpZywgT0F1dGhUb2tlbn0gZnJvbSAnLi4vbW9kZWxzJztcbmltcG9ydCB7Y2F0Y2hFcnJvciwgbWFwLCBzaGFyZVJlcGxheX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtIdHRwQ2xpZW50LCBIdHRwUGFyYW1zfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbmNvbnN0IGlzRXhwaXJlZFRva2VuID0gKHRva2VuPzogT0F1dGhUb2tlbikgPT4gdG9rZW4gJiYgdG9rZW4uZXhwaXJlcyAmJiBEYXRlLm5vdygpID4gdG9rZW4uZXhwaXJlcyB8fCBmYWxzZTtcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE9BdXRoVG9rZW5TZXJ2aWNlIHtcblxuICAjdG9rZW4kID0gbmV3IEJlaGF2aW9yU3ViamVjdDxPQXV0aFRva2VuPih0aGlzLnNhdmVkKTtcbiAgdG9rZW4kID0gdGhpcy4jdG9rZW4kLnBpcGUoXG4gICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKHAsIGMpID0+IEpTT04uc3RyaW5naWZ5KHAgfHwgbnVsbCkgPT09IEpTT04uc3RyaW5naWZ5KGMgfHwgbnVsbCkpLFxuICAgIHNoYXJlUmVwbGF5KDEpLFxuICAgIHN3aXRjaE1hcCh0b2tlbiA9PiAhaXNFeHBpcmVkVG9rZW4odG9rZW4pICYmIG9mKHRva2VuKSB8fCB0aGlzLnJlZnJlc2hUb2tlbih0b2tlbikpLFxuICApO1xuICB0eXBlJCA9IHRoaXMudG9rZW4kLnBpcGUoXG4gICAgbWFwKHRva2VuID0+IHRva2VuPy50eXBlKSxcbiAgICBzaGFyZVJlcGxheSgxKVxuICApO1xuICBhY2Nlc3NUb2tlbiQgPSB0aGlzLnRva2VuJC5waXBlKFxuICAgIG1hcCh0b2tlbiA9PiB0b2tlbj8uYWNjZXNzX3Rva2VuKSxcbiAgICBzaGFyZVJlcGxheSgxKSxcbiAgKTtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgYXV0aENvbmZpZzogT0F1dGhDb25maWcsXG4gICAgICAgICAgICAgIEBJbmplY3QoT0FVVEhfSFRUUF9DTElFTlQpIHByb3RlY3RlZCBodHRwOiBIdHRwQ2xpZW50LFxuICAgICAgICAgICAgICBwcm90ZWN0ZWQgem9uZTogTmdab25lKSB7XG4gIH1cblxuICBnZXQgdG9rZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuI3Rva2VuJC52YWx1ZTtcbiAgfVxuXG4gIHNldCB0b2tlbih0b2tlbikge1xuICAgIGNvbnN0IGV4cGlyZXNJbiA9IE51bWJlcih0b2tlbi5leHBpcmVzX2luKSB8fCAwO1xuICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgIC4uLnRva2VuLFxuICAgICAgLi4uZXhwaXJlc0luICYmIHtleHBpcmVzOiBEYXRlLm5vdygpICsgZXhwaXJlc0luICogMTAwMH0gfHwge31cbiAgICB9O1xuICAgIHRoaXMuc2F2ZWQgPSByZXN1bHQ7XG4gICAgdGhpcy4jdG9rZW4kLm5leHQocmVzdWx0KTtcbiAgfVxuXG4gIGdldCBzYXZlZCgpIHtcbiAgICBjb25zdCB7c3RvcmFnZUtleSwgc3RvcmFnZX0gPSB0aGlzLmF1dGhDb25maWc7XG4gICAgcmV0dXJuIHN0b3JhZ2VLZXkgJiYgc3RvcmFnZSAmJiBzdG9yYWdlW3N0b3JhZ2VLZXldICYmIEpTT04ucGFyc2Uoc3RvcmFnZVtzdG9yYWdlS2V5XSkgfHwge307XG4gIH1cblxuICBzZXQgc2F2ZWQodG9rZW46IE9BdXRoVG9rZW4pIHtcbiAgICBjb25zdCB7c3RvcmFnZUtleSwgc3RvcmFnZX0gPSB0aGlzLmF1dGhDb25maWc7XG4gICAgaWYgKHN0b3JhZ2UgJiYgc3RvcmFnZUtleSkge1xuICAgICAgaWYgKHRva2VuKSB7XG4gICAgICAgIHN0b3JhZ2Vbc3RvcmFnZUtleV0gPSBKU09OLnN0cmluZ2lmeSh0b2tlbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgc3RvcmFnZVtzdG9yYWdlS2V5XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVmcmVzaFRva2VuKHRva2VuPzogT0F1dGhUb2tlbik6IE9ic2VydmFibGU8T0F1dGhUb2tlbj4ge1xuICAgIGNvbnN0IHt0b2tlblBhdGgsIGNsaWVudElkLCBjbGllbnRTZWNyZXQsIHNjb3BlfSA9IHRoaXMuYXV0aENvbmZpZy5jb25maWcgYXMgYW55O1xuICAgIGNvbnN0IHtyZWZyZXNoX3Rva2VufSA9IHRva2VuIHx8IHt9O1xuICAgIHJldHVybiB0b2tlblBhdGggJiYgcmVmcmVzaF90b2tlbiAmJiB0aGlzLmh0dHAucG9zdDxPQXV0aFRva2VuPih0b2tlblBhdGgsIG5ldyBIdHRwUGFyYW1zKHtcbiAgICAgIGZyb21PYmplY3Q6IHtcbiAgICAgICAgY2xpZW50X2lkOiBjbGllbnRJZCxcbiAgICAgICAgLi4uY2xpZW50U2VjcmV0ICYmIHtjbGllbnRfc2VjcmV0OiBjbGllbnRTZWNyZXR9IHx8IHt9LFxuICAgICAgICBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgIHJlZnJlc2hfdG9rZW4sXG4gICAgICAgIC4uLnNjb3BlICYmIHtzY29wZX0gfHwge30sXG4gICAgICB9XG4gICAgfSksIHtcbiAgICAgIGhlYWRlcnM6IEhFQURFUl9BUFBMSUNBVElPTlxuICAgIH0pLnBpcGUoXG4gICAgICBjYXRjaEVycm9yKCgpID0+IHtcbiAgICAgICAgdGhpcy50b2tlbiA9IHt9O1xuICAgICAgICByZXR1cm4gb2YodGhpcy50b2tlbik7XG4gICAgICB9KSxcbiAgICAgIG1hcCh0b2tlbiA9PiB7XG4gICAgICAgIHRoaXMudG9rZW4gPSB7XG4gICAgICAgICAgLi4udGhpcy50b2tlbixcbiAgICAgICAgICAuLi50b2tlblxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcy50b2tlbjtcbiAgICAgIH0pXG4gICAgKSB8fCBvZih0b2tlbik7XG4gIH1cbn1cbiJdfQ==