@azure/msal-angular 3.0.0-alpha.1 → 3.0.0-beta.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.
- package/IMsalService.d.ts +15 -15
- package/LICENSE +20 -20
- package/README.md +157 -155
- package/constants.d.ts +5 -5
- package/esm2020/IMsalService.mjs +6 -6
- package/esm2020/azure-msal-angular.mjs +4 -4
- package/esm2020/constants.mjs +10 -10
- package/esm2020/msal.broadcast.config.mjs +6 -6
- package/esm2020/msal.broadcast.service.mjs +57 -57
- package/esm2020/msal.guard.config.mjs +6 -6
- package/esm2020/msal.guard.mjs +218 -218
- package/esm2020/msal.interceptor.config.mjs +6 -6
- package/esm2020/msal.interceptor.mjs +270 -270
- package/esm2020/msal.module.mjs +46 -46
- package/esm2020/msal.navigation.client.mjs +51 -51
- package/esm2020/msal.redirect.component.mjs +31 -31
- package/esm2020/msal.service.mjs +81 -81
- package/esm2020/packageMetadata.mjs +4 -4
- package/esm2020/public-api.mjs +18 -18
- package/fesm2015/azure-msal-angular.mjs +703 -703
- package/fesm2015/azure-msal-angular.mjs.map +1 -1
- package/fesm2020/azure-msal-angular.mjs +700 -700
- package/fesm2020/azure-msal-angular.mjs.map +1 -1
- package/index.d.ts +5 -5
- package/msal.broadcast.config.d.ts +3 -3
- package/msal.broadcast.service.d.ts +17 -17
- package/msal.guard.config.d.ts +9 -9
- package/msal.guard.d.ts +43 -43
- package/msal.interceptor.config.d.ts +17 -17
- package/msal.interceptor.d.ts +63 -63
- package/msal.module.d.ts +13 -13
- package/msal.navigation.client.d.ts +19 -19
- package/msal.redirect.component.d.ts +15 -15
- package/msal.service.d.ts +31 -31
- package/package.json +7 -3
- package/packageMetadata.d.ts +2 -2
- package/public-api.d.ts +17 -17
|
@@ -1,270 +1,270 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { Injectable, Inject } from '@angular/core';
|
|
6
|
-
import { DOCUMENT } from '@angular/common';
|
|
7
|
-
import { BrowserConfigurationAuthError, InteractionStatus, InteractionType, StringUtils, UrlString, } from '@azure/msal-browser';
|
|
8
|
-
import { EMPTY, of } from 'rxjs';
|
|
9
|
-
import { switchMap, catchError, take, filter } from 'rxjs/operators';
|
|
10
|
-
import { MSAL_INTERCEPTOR_CONFIG } from './constants';
|
|
11
|
-
import * as i0 from "@angular/core";
|
|
12
|
-
import * as i1 from "./msal.service";
|
|
13
|
-
import * as i2 from "@angular/common";
|
|
14
|
-
import * as i3 from "./msal.broadcast.service";
|
|
15
|
-
export class MsalInterceptor {
|
|
16
|
-
constructor(msalInterceptorConfig, authService, location, msalBroadcastService,
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
18
|
-
document) {
|
|
19
|
-
this.msalInterceptorConfig = msalInterceptorConfig;
|
|
20
|
-
this.authService = authService;
|
|
21
|
-
this.location = location;
|
|
22
|
-
this.msalBroadcastService = msalBroadcastService;
|
|
23
|
-
this._document = document;
|
|
24
|
-
}
|
|
25
|
-
intercept(req, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
26
|
-
next
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
-
) {
|
|
29
|
-
if (this.msalInterceptorConfig.interactionType !== InteractionType.Popup &&
|
|
30
|
-
this.msalInterceptorConfig.interactionType !== InteractionType.Redirect) {
|
|
31
|
-
throw new BrowserConfigurationAuthError('invalid_interaction_type', 'Invalid interaction type provided to MSAL Interceptor. InteractionType.Popup, InteractionType.Redirect must be provided in the msalInterceptorConfiguration');
|
|
32
|
-
}
|
|
33
|
-
this.authService.getLogger().verbose('MSAL Interceptor activated');
|
|
34
|
-
const scopes = this.getScopesForEndpoint(req.url, req.method);
|
|
35
|
-
// If no scopes for endpoint, does not acquire token
|
|
36
|
-
if (!scopes || scopes.length === 0) {
|
|
37
|
-
this.authService
|
|
38
|
-
.getLogger()
|
|
39
|
-
.verbose('Interceptor - no scopes for endpoint');
|
|
40
|
-
return next.handle(req);
|
|
41
|
-
}
|
|
42
|
-
// Sets account as active account or first account
|
|
43
|
-
let account;
|
|
44
|
-
if (!!this.authService.instance.getActiveAccount()) {
|
|
45
|
-
this.authService
|
|
46
|
-
.getLogger()
|
|
47
|
-
.verbose('Interceptor - active account selected');
|
|
48
|
-
account = this.authService.instance.getActiveAccount();
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
this.authService
|
|
52
|
-
.getLogger()
|
|
53
|
-
.verbose('Interceptor - no active account, fallback to first account');
|
|
54
|
-
account = this.authService.instance.getAllAccounts()[0];
|
|
55
|
-
}
|
|
56
|
-
const authRequest = typeof this.msalInterceptorConfig.authRequest === 'function'
|
|
57
|
-
? this.msalInterceptorConfig.authRequest(this.authService, req, {
|
|
58
|
-
account: account,
|
|
59
|
-
})
|
|
60
|
-
: { ...this.msalInterceptorConfig.authRequest, account };
|
|
61
|
-
this.authService
|
|
62
|
-
.getLogger()
|
|
63
|
-
.info(`Interceptor - ${scopes.length} scopes found for endpoint`);
|
|
64
|
-
this.authService
|
|
65
|
-
.getLogger()
|
|
66
|
-
.infoPii(`Interceptor - [${scopes}] scopes found for ${req.url}`);
|
|
67
|
-
return this.acquireToken(authRequest, scopes, account).pipe(switchMap((result) => {
|
|
68
|
-
this.authService
|
|
69
|
-
.getLogger()
|
|
70
|
-
.verbose('Interceptor - setting authorization headers');
|
|
71
|
-
const headers = req.headers.set('Authorization', `Bearer ${result.accessToken}`);
|
|
72
|
-
const requestClone = req.clone({ headers });
|
|
73
|
-
return next.handle(requestClone);
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Try to acquire token silently. Invoke interaction if acquireTokenSilent rejected with error or resolved with null access token
|
|
78
|
-
* @param authRequest Request
|
|
79
|
-
* @param scopes Array of scopes for the request
|
|
80
|
-
* @param account Account
|
|
81
|
-
* @returns Authentication result
|
|
82
|
-
*/
|
|
83
|
-
acquireToken(authRequest, scopes, account) {
|
|
84
|
-
// Note: For MSA accounts, include openid scope when calling acquireTokenSilent to return idToken
|
|
85
|
-
return this.authService
|
|
86
|
-
.acquireTokenSilent({ ...authRequest, scopes, account })
|
|
87
|
-
.pipe(catchError(() => {
|
|
88
|
-
this.authService
|
|
89
|
-
.getLogger()
|
|
90
|
-
.error('Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.');
|
|
91
|
-
return this.msalBroadcastService.inProgress$.pipe(take(1), switchMap((status) => {
|
|
92
|
-
if (status === InteractionStatus.None) {
|
|
93
|
-
return this.acquireTokenInteractively(authRequest, scopes);
|
|
94
|
-
}
|
|
95
|
-
return this.msalBroadcastService.inProgress$.pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireToken(authRequest, scopes, account)));
|
|
96
|
-
}));
|
|
97
|
-
}), switchMap((result) => {
|
|
98
|
-
if (!result.accessToken) {
|
|
99
|
-
this.authService
|
|
100
|
-
.getLogger()
|
|
101
|
-
.error('Interceptor - acquireTokenSilent resolved with null access token. Known issue with B2C tenants, invoking interaction to resolve.');
|
|
102
|
-
return this.msalBroadcastService.inProgress$.pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireTokenInteractively(authRequest, scopes)));
|
|
103
|
-
}
|
|
104
|
-
return of(result);
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Invoke interaction for the given set of scopes
|
|
109
|
-
* @param authRequest Request
|
|
110
|
-
* @param scopes Array of scopes for the request
|
|
111
|
-
* @returns Result from the interactive request
|
|
112
|
-
*/
|
|
113
|
-
acquireTokenInteractively(authRequest, scopes) {
|
|
114
|
-
if (this.msalInterceptorConfig.interactionType === InteractionType.Popup) {
|
|
115
|
-
this.authService
|
|
116
|
-
.getLogger()
|
|
117
|
-
.verbose('Interceptor - error acquiring token silently, acquiring by popup');
|
|
118
|
-
return this.authService.acquireTokenPopup({ ...authRequest, scopes });
|
|
119
|
-
}
|
|
120
|
-
this.authService
|
|
121
|
-
.getLogger()
|
|
122
|
-
.verbose('Interceptor - error acquiring token silently, acquiring by redirect');
|
|
123
|
-
const redirectStartPage = window.location.href;
|
|
124
|
-
this.authService.acquireTokenRedirect({
|
|
125
|
-
...authRequest,
|
|
126
|
-
scopes,
|
|
127
|
-
redirectStartPage,
|
|
128
|
-
});
|
|
129
|
-
return EMPTY;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Looks up the scopes for the given endpoint from the protectedResourceMap
|
|
133
|
-
* @param endpoint Url of the request
|
|
134
|
-
* @param httpMethod Http method of the request
|
|
135
|
-
* @returns Array of scopes, or null if not found
|
|
136
|
-
*
|
|
137
|
-
*/
|
|
138
|
-
getScopesForEndpoint(endpoint, httpMethod) {
|
|
139
|
-
this.authService
|
|
140
|
-
.getLogger()
|
|
141
|
-
.verbose('Interceptor - getting scopes for endpoint');
|
|
142
|
-
// Ensures endpoints and protected resources compared are normalized
|
|
143
|
-
const normalizedEndpoint = this.location.normalize(endpoint);
|
|
144
|
-
const protectedResourcesArray = Array.from(this.msalInterceptorConfig.protectedResourceMap.keys());
|
|
145
|
-
const matchingProtectedResources = this.matchResourcesToEndpoint(protectedResourcesArray, normalizedEndpoint);
|
|
146
|
-
// Check absolute urls of resources first before checking relative to prevent incorrect matching where multiple resources have similar relative urls
|
|
147
|
-
if (matchingProtectedResources.absoluteResources.length > 0) {
|
|
148
|
-
return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.absoluteResources, httpMethod);
|
|
149
|
-
}
|
|
150
|
-
else if (matchingProtectedResources.relativeResources.length > 0) {
|
|
151
|
-
return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.relativeResources, httpMethod);
|
|
152
|
-
}
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Finds resource endpoints that match request endpoint
|
|
157
|
-
* @param protectedResourcesEndpoints
|
|
158
|
-
* @param endpoint
|
|
159
|
-
* @returns
|
|
160
|
-
*/
|
|
161
|
-
matchResourcesToEndpoint(protectedResourcesEndpoints, endpoint) {
|
|
162
|
-
const matchingResources = {
|
|
163
|
-
absoluteResources: [],
|
|
164
|
-
relativeResources: [],
|
|
165
|
-
};
|
|
166
|
-
protectedResourcesEndpoints.forEach((key) => {
|
|
167
|
-
// Normalizes and adds resource to matchingResources.absoluteResources if key matches endpoint. StringUtils.matchPattern accounts for wildcards
|
|
168
|
-
const normalizedKey = this.location.normalize(key);
|
|
169
|
-
if (StringUtils.matchPattern(normalizedKey, endpoint)) {
|
|
170
|
-
matchingResources.absoluteResources.push(key);
|
|
171
|
-
}
|
|
172
|
-
// Get url components for relative urls
|
|
173
|
-
const absoluteKey = this.getAbsoluteUrl(key);
|
|
174
|
-
const keyComponents = new UrlString(absoluteKey).getUrlComponents();
|
|
175
|
-
const absoluteEndpoint = this.getAbsoluteUrl(endpoint);
|
|
176
|
-
const endpointComponents = new UrlString(absoluteEndpoint).getUrlComponents();
|
|
177
|
-
// Normalized key should include query strings if applicable
|
|
178
|
-
const relativeNormalizedKey = keyComponents.QueryString
|
|
179
|
-
? `${keyComponents.AbsolutePath}?${keyComponents.QueryString}`
|
|
180
|
-
: this.location.normalize(keyComponents.AbsolutePath);
|
|
181
|
-
// Add resource to matchingResources.relativeResources if same origin, relativeKey matches endpoint, and is not empty
|
|
182
|
-
if (keyComponents.HostNameAndPort === endpointComponents.HostNameAndPort &&
|
|
183
|
-
StringUtils.matchPattern(relativeNormalizedKey, absoluteEndpoint) &&
|
|
184
|
-
relativeNormalizedKey !== '' &&
|
|
185
|
-
relativeNormalizedKey !== '/*') {
|
|
186
|
-
matchingResources.relativeResources.push(key);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
return matchingResources;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Transforms relative urls to absolute urls
|
|
193
|
-
* @param url
|
|
194
|
-
* @returns
|
|
195
|
-
*/
|
|
196
|
-
getAbsoluteUrl(url) {
|
|
197
|
-
const link = this._document.createElement('a');
|
|
198
|
-
link.href = url;
|
|
199
|
-
return link.href;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Finds scopes from first matching endpoint with HTTP method that matches request
|
|
203
|
-
* @param protectedResourceMap Protected resource map
|
|
204
|
-
* @param endpointArray Array of resources that match request endpoint
|
|
205
|
-
* @param httpMethod Http method of the request
|
|
206
|
-
* @returns
|
|
207
|
-
*/
|
|
208
|
-
matchScopesToEndpoint(protectedResourceMap, endpointArray, httpMethod) {
|
|
209
|
-
const allMatchedScopes = [];
|
|
210
|
-
// Check each matched endpoint for matching HttpMethod and scopes
|
|
211
|
-
endpointArray.forEach((matchedEndpoint) => {
|
|
212
|
-
const scopesForEndpoint = [];
|
|
213
|
-
const methodAndScopesArray = protectedResourceMap.get(matchedEndpoint);
|
|
214
|
-
// Return if resource is unprotected
|
|
215
|
-
if (methodAndScopesArray === null) {
|
|
216
|
-
allMatchedScopes.push(null);
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
methodAndScopesArray.forEach((entry) => {
|
|
220
|
-
// Entry is either array of scopes or ProtectedResourceScopes object
|
|
221
|
-
if (typeof entry === 'string') {
|
|
222
|
-
scopesForEndpoint.push(entry);
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
// Ensure methods being compared are normalized
|
|
226
|
-
const normalizedRequestMethod = httpMethod.toLowerCase();
|
|
227
|
-
const normalizedResourceMethod = entry.httpMethod.toLowerCase();
|
|
228
|
-
// Method in protectedResourceMap matches request http method
|
|
229
|
-
if (normalizedResourceMethod === normalizedRequestMethod) {
|
|
230
|
-
// Validate if scopes comes null to unprotect the resource in a certain http method
|
|
231
|
-
if (entry.scopes === null) {
|
|
232
|
-
allMatchedScopes.push(null);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
entry.scopes.forEach((scope) => {
|
|
236
|
-
scopesForEndpoint.push(scope);
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
// Only add to all scopes if scopes for endpoint and method is found
|
|
243
|
-
if (scopesForEndpoint.length > 0) {
|
|
244
|
-
allMatchedScopes.push(scopesForEndpoint);
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
if (allMatchedScopes.length > 0) {
|
|
248
|
-
if (allMatchedScopes.length > 1) {
|
|
249
|
-
this.authService
|
|
250
|
-
.getLogger()
|
|
251
|
-
.warning('Interceptor - More than 1 matching scopes for endpoint found.');
|
|
252
|
-
}
|
|
253
|
-
// Returns scopes for first matching endpoint
|
|
254
|
-
return allMatchedScopes[0];
|
|
255
|
-
}
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
MsalInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: MsalInterceptor, deps: [{ token: MSAL_INTERCEPTOR_CONFIG }, { token: i1.MsalService }, { token: i2.Location }, { token: i3.MsalBroadcastService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
260
|
-
MsalInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: MsalInterceptor });
|
|
261
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: MsalInterceptor, decorators: [{
|
|
262
|
-
type: Injectable
|
|
263
|
-
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
264
|
-
type: Inject,
|
|
265
|
-
args: [MSAL_INTERCEPTOR_CONFIG]
|
|
266
|
-
}] }, { type: i1.MsalService }, { type: i2.Location }, { type: i3.MsalBroadcastService }, { type: undefined, decorators: [{
|
|
267
|
-
type: Inject,
|
|
268
|
-
args: [DOCUMENT]
|
|
269
|
-
}] }]; } });
|
|
270
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXNhbC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tc2FsLmludGVyY2VwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBWSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQU9yRCxPQUFPLEVBR0wsNkJBQTZCLEVBQzdCLGlCQUFpQixFQUNqQixlQUFlLEVBQ2YsV0FBVyxFQUNYLFNBQVMsR0FDVixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBYyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVNyRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxhQUFhLENBQUM7Ozs7O0FBR3RELE1BQU0sT0FBTyxlQUFlO0lBRzFCLFlBRVUscUJBQW1ELEVBQ25ELFdBQXdCLEVBQ3hCLFFBQWtCLEVBQ2xCLG9CQUEwQztJQUNsRCxpSEFBaUg7SUFDL0YsUUFBYztRQUx4QiwwQkFBcUIsR0FBckIscUJBQXFCLENBQThCO1FBQ25ELGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLGFBQVEsR0FBUixRQUFRLENBQVU7UUFDbEIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUlsRCxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQW9CLENBQUM7SUFDeEMsQ0FBQztJQUVELFNBQVMsQ0FDUCxHQUFxQixFQUFFLHlEQUF5RDtJQUNoRixJQUFpQjtJQUNqQiw4REFBOEQ7O1FBRTlELElBQ0UsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGVBQWUsS0FBSyxlQUFlLENBQUMsS0FBSztZQUNwRSxJQUFJLENBQUMscUJBQXFCLENBQUMs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QU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO2dDQUM3QixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7NEJBQ2hDLENBQUMsQ0FBQyxDQUFDO3lCQUNKO3FCQUNGO2lCQUNGO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFFSCxvRUFBb0U7WUFDcEUsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNoQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQzthQUMxQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQy9CLElBQUksZ0JBQWdCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDL0IsSUFBSSxDQUFDLFdBQVc7cUJBQ2IsU0FBUyxFQUFFO3FCQUNYLE9BQU8sQ0FDTiwrREFBK0QsQ0FDaEUsQ0FBQzthQUNMO1lBQ0QsNkNBQTZDO1lBQzdDLE9BQU8sZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDNUI7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7OzRHQWpXVSxlQUFlLGtCQUloQix1QkFBdUIsb0dBTXZCLFFBQVE7Z0hBVlAsZUFBZTsyRkFBZixlQUFlO2tCQUQzQixVQUFVOzswQkFLTixNQUFNOzJCQUFDLHVCQUF1Qjs7MEJBTTlCLE1BQU07MkJBQUMsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgSW5qZWN0YWJsZSwgSW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IExvY2F0aW9uLCBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7XHJcbiAgSHR0cFJlcXVlc3QsXHJcbiAgSHR0cEhhbmRsZXIsXHJcbiAgSHR0cEV2ZW50LFxyXG4gIEh0dHBJbnRlcmNlcHRvcixcclxufSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgaW1wb3J0L25vLXVucmVzb2x2ZWRcclxuaW1wb3J0IHtcclxuICBBY2NvdW50SW5mbyxcclxuICBBdXRoZW50aWNhdGlvblJlc3VsdCxcclxuICBCcm93c2VyQ29uZmlndXJhdGlvbkF1dGhFcnJvcixcclxuICBJbnRlcmFjdGlvblN0YXR1cyxcclxuICBJbnRlcmFjdGlvblR5cGUsXHJcbiAgU3RyaW5nVXRpbHMsXHJcbiAgVXJsU3RyaW5nLFxyXG59IGZyb20gJ0BhenVyZS9tc2FsLWJyb3dzZXInO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBFTVBUWSwgb2YgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgc3dpdGNoTWFwLCBjYXRjaEVycm9yLCB0YWtlLCBmaWx0ZXIgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IE1zYWxTZXJ2aWNlIH0gZnJvbSAnLi9tc2FsLnNlcnZpY2UnO1xyXG5pbXBvcnQge1xyXG4gIE1zYWxJbnRlcmNlcHRvckF1dGhSZXF1ZXN0LFxyXG4gIE1zYWxJbnRlcmNlcHRvckNvbmZpZ3VyYXRpb24sXHJcbiAgUHJvdGVjdGVkUmVzb3VyY2VTY29wZXMsXHJcbiAgTWF0Y2hpbmdSZXNvdXJjZXMsXHJcbn0gZnJvbSAnLi9tc2FsLmludGVyY2VwdG9yLmNvbmZpZyc7XHJcbmltcG9ydCB7IE1zYWxCcm9hZGNhc3RTZXJ2aWNlIH0gZnJvbSAnLi9tc2FsLmJyb2FkY2FzdC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTVNBTF9JTlRFUkNFUFRPUl9DT05GSUcgfSBmcm9tICcuL2NvbnN0YW50cyc7XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBNc2FsSW50ZXJjZXB0b3IgaW1wbGVtZW50cyBIdHRwSW50ZXJjZXB0b3Ige1xyXG4gIHByaXZhdGUgX2RvY3VtZW50PzogRG9jdW1lbnQ7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdChNU0FMX0lOVEVSQ0VQVE9SX0NPTkZJRylcclxuICAgIHByaXZhdGUgbXNhbEludGVyY2VwdG9yQ29uZmlnOiBNc2FsSW50ZXJjZXB0b3JDb25maWd1cmF0aW9uLFxyXG4gICAgcHJpdmF0ZSBhdXRoU2VydmljZTogTXNhbFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGxvY2F0aW9uOiBMb2NhdGlvbixcclxuICAgIHByaXZhdGUgbXNhbEJyb2FkY2FzdFNlcnZpY2U6IE1zYWxCcm9hZGNhc3RTZXJ2aWNlLFxyXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnksIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1tb2R1bGUtYm91bmRhcnktdHlwZXNcclxuICAgIEBJbmplY3QoRE9DVU1FTlQpIGRvY3VtZW50PzogYW55XHJcbiAgKSB7XHJcbiAgICB0aGlzLl9kb2N1bWVudCA9IGRvY3VtZW50IGFzIERvY3VtZW50O1xyXG4gIH1cclxuXHJcbiAgaW50ZXJjZXB0KFxyXG4gICAgcmVxOiBIdHRwUmVxdWVzdDxhbnk+LCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcclxuICAgIG5leHQ6IEh0dHBIYW5kbGVyXHJcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxyXG4gICk6IE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+IHtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcuaW50ZXJhY3Rpb25UeXBlICE9PSBJbnRlcmFjdGlvblR5cGUuUG9wdXAgJiZcclxuICAgICAgdGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcuaW50ZXJhY3Rpb25UeXBlICE9PSBJbnRlcmFjdGlvblR5cGUuUmVkaXJlY3RcclxuICAgICkge1xyXG4gICAgICB0aHJvdyBuZXcgQnJvd3NlckNvbmZpZ3VyYXRpb25BdXRoRXJyb3IoXHJcbiAgICAgICAgJ2ludmFsaWRfaW50ZXJhY3Rpb25fdHlwZScsXHJcbiAgICAgICAgJ0ludmFsaWQgaW50ZXJhY3Rpb24gdHlwZSBwcm92aWRlZCB0byBNU0FMIEludGVyY2VwdG9yLiBJbnRlcmFjdGlvblR5cGUuUG9wdXAsIEludGVyYWN0aW9uVHlwZS5SZWRpcmVjdCBtdXN0IGJlIHByb3ZpZGVkIGluIHRoZSBtc2FsSW50ZXJjZXB0b3JDb25maWd1cmF0aW9uJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuYXV0aFNlcnZpY2UuZ2V0TG9nZ2VyKCkudmVyYm9zZSgnTVNBTCBJbnRlcmNlcHRvciBhY3RpdmF0ZWQnKTtcclxuICAgIGNvbnN0IHNjb3BlcyA9IHRoaXMuZ2V0U2NvcGVzRm9yRW5kcG9pbnQocmVxLnVybCwgcmVxLm1ldGhvZCk7XHJcblxyXG4gICAgLy8gSWYgbm8gc2NvcGVzIGZvciBlbmRwb2ludCwgZG9lcyBub3QgYWNxdWlyZSB0b2tlblxyXG4gICAgaWYgKCFzY29wZXMgfHwgc2NvcGVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLmF1dGhTZXJ2aWNlXHJcbiAgICAgICAgLmdldExvZ2dlcigpXHJcbiAgICAgICAgLnZlcmJvc2UoJ0ludGVyY2VwdG9yIC0gbm8gc2NvcGVzIGZvciBlbmRwb2ludCcpO1xyXG4gICAgICByZXR1cm4gbmV4dC5oYW5kbGUocmVxKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBTZXRzIGFjY291bnQgYXMgYWN0aXZlIGFjY291bnQgb3IgZmlyc3QgYWNjb3VudFxyXG4gICAgbGV0IGFjY291bnQ6IEFjY291bnRJbmZvO1xyXG4gICAgaWYgKCEhdGhpcy5hdXRoU2VydmljZS5pbnN0YW5jZS5nZXRBY3RpdmVBY2NvdW50KCkpIHtcclxuICAgICAgdGhpcy5hdXRoU2VydmljZVxyXG4gICAgICAgIC5nZXRMb2dnZXIoKVxyXG4gICAgICAgIC52ZXJib3NlKCdJbnRlcmNlcHRvciAtIGFjdGl2ZSBhY2NvdW50IHNlbGVjdGVkJyk7XHJcbiAgICAgIGFjY291bnQgPSB0aGlzLmF1dGhTZXJ2aWNlLmluc3RhbmNlLmdldEFjdGl2ZUFjY291bnQoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuYXV0aFNlcnZpY2VcclxuICAgICAgICAuZ2V0TG9nZ2VyKClcclxuICAgICAgICAudmVyYm9zZSgnSW50ZXJjZXB0b3IgLSBubyBhY3RpdmUgYWNjb3VudCwgZmFsbGJhY2sgdG8gZmlyc3QgYWNjb3VudCcpO1xyXG4gICAgICBhY2NvdW50ID0gdGhpcy5hdXRoU2VydmljZS5pbnN0YW5jZS5nZXRBbGxBY2NvdW50cygpWzBdO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGF1dGhSZXF1ZXN0ID1cclxuICAgICAgdHlwZW9mIHRoaXMubXNhbEludGVyY2VwdG9yQ29uZmlnLmF1dGhSZXF1ZXN0ID09PSAnZnVuY3Rpb24nXHJcbiAgICAgICAgPyB0aGlzLm1zYWxJbnRlcmNlcHRvckNvbmZpZy5hdXRoUmVxdWVzdCh0aGlzLmF1dGhTZXJ2aWNlLCByZXEsIHtcclxuICAgICAgICAgICAgYWNjb3VudDogYWNjb3VudCxcclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgOiB7IC4uLnRoaXMubXNhbEludGVyY2VwdG9yQ29uZmlnLmF1dGhSZXF1ZXN0LCBhY2NvdW50IH07XHJcblxyXG4gICAgdGhpcy5hdXRoU2VydmljZVxyXG4gICAgICAuZ2V0TG9nZ2VyKClcclxuICAgICAgLmluZm8oYEludGVyY2VwdG9yIC0gJHtzY29wZXMubGVuZ3RofSBzY29wZXMgZm91bmQgZm9yIGVuZHBvaW50YCk7XHJcbiAgICB0aGlzLmF1dGhTZXJ2aWNlXHJcbiAgICAgIC5nZXRMb2dnZXIoKVxyXG4gICAgICAuaW5mb1BpaShgSW50ZXJjZXB0b3IgLSBbJHtzY29wZXN9XSBzY29wZXMgZm91bmQgZm9yICR7cmVxLnVybH1gKTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy5hY3F1aXJlVG9rZW4oYXV0aFJlcXVlc3QsIHNjb3BlcywgYWNjb3VudCkucGlwZShcclxuICAgICAgc3dpdGNoTWFwKChyZXN1bHQ6IEF1dGhlbnRpY2F0aW9uUmVzdWx0KSA9PiB7XHJcbiAgICAgICAgdGhpcy5hdXRoU2VydmljZVxyXG4gICAgICAgICAgLmdldExvZ2dlcigpXHJcbiAgICAgICAgICAudmVyYm9zZSgnSW50ZXJjZXB0b3IgLSBzZXR0aW5nIGF1dGhvcml6YXRpb24gaGVhZGVycycpO1xyXG4gICAgICAgIGNvbnN0IGhlYWRlcnMgPSByZXEuaGVhZGVycy5zZXQoXHJcbiAgICAgICAgICAnQXV0aG9yaXphdGlvbicsXHJcbiAgICAgICAgICBgQmVhcmVyICR7cmVzdWx0LmFjY2Vzc1Rva2VufWBcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICBjb25zdCByZXF1ZXN0Q2xvbmUgPSByZXEuY2xvbmUoeyBoZWFkZXJzIH0pO1xyXG4gICAgICAgIHJldHVybiBuZXh0LmhhbmRsZShyZXF1ZXN0Q2xvbmUpO1xyXG4gICAgICB9KVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRyeSB0byBhY3F1aXJlIHRva2VuIHNpbGVudGx5LiBJbnZva2UgaW50ZXJhY3Rpb24gaWYgYWNxdWlyZVRva2VuU2lsZW50IHJlamVjdGVkIHdpdGggZXJyb3Igb3IgcmVzb2x2ZWQgd2l0aCBudWxsIGFjY2VzcyB0b2tlblxyXG4gICAqIEBwYXJhbSBhdXRoUmVxdWVzdCBSZXF1ZXN0XHJcbiAgICogQHBhcmFtIHNjb3BlcyBBcnJheSBvZiBzY29wZXMgZm9yIHRoZSByZXF1ZXN0XHJcbiAgICogQHBhcmFtIGFjY291bnQgQWNjb3VudFxyXG4gICAqIEByZXR1cm5zIEF1dGhlbnRpY2F0aW9uIHJlc3VsdFxyXG4gICAqL1xyXG4gIHByaXZhdGUgYWNxdWlyZVRva2VuKFxyXG4gICAgYXV0aFJlcXVlc3Q6IE1zYWxJbnRlcmNlcHRvckF1dGhSZXF1ZXN0LFxyXG4gICAgc2NvcGVzOiBzdHJpbmdbXSxcclxuICAgIGFjY291bnQ6IEFjY291bnRJbmZvXHJcbiAgKTogT2JzZXJ2YWJsZTxBdXRoZW50aWNhdGlvblJlc3VsdD4ge1xyXG4gICAgLy8gTm90ZTogRm9yIE1TQSBhY2NvdW50cywgaW5jbHVkZSBvcGVuaWQgc2NvcGUgd2hlbiBjYWxsaW5nIGFjcXVpcmVUb2tlblNpbGVudCB0byByZXR1cm4gaWRUb2tlblxyXG4gICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2VcclxuICAgICAgLmFjcXVpcmVUb2tlblNpbGVudCh7IC4uLmF1dGhSZXF1ZXN0LCBzY29wZXMsIGFjY291bnQgfSlcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmF1dGhTZXJ2aWNlXHJcbiAgICAgICAgICAgIC5nZXRMb2dnZXIoKVxyXG4gICAgICAgICAgICAuZXJyb3IoXHJcbiAgICAgICAgICAgICAgJ0ludGVyY2VwdG9yIC0gYWNxdWlyZVRva2VuU2lsZW50IHJlamVjdGVkIHdpdGggZXJyb3IuIEludm9raW5nIGludGVyYWN0aW9uIHRvIHJlc29sdmUuJ1xyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgcmV0dXJuIHRoaXMubXNhbEJyb2FkY2FzdFNlcnZpY2UuaW5Qcm9ncmVzcyQucGlwZShcclxuICAgICAgICAgICAgdGFrZSgxKSxcclxuICAgICAgICAgICAgc3dpdGNoTWFwKChzdGF0dXM6IEludGVyYWN0aW9uU3RhdHVzKSA9PiB7XHJcbiAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gSW50ZXJhY3Rpb25TdGF0dXMuTm9uZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWNxdWlyZVRva2VuSW50ZXJhY3RpdmVseShhdXRoUmVxdWVzdCwgc2NvcGVzKTtcclxuICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLm1zYWxCcm9hZGNhc3RTZXJ2aWNlLmluUHJvZ3Jlc3MkLnBpcGUoXHJcbiAgICAgICAgICAgICAgICBmaWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAgIChzdGF0dXM6IEludGVyYWN0aW9uU3RhdHVzKSA9PlxyXG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9PT0gSW50ZXJhY3Rpb25TdGF0dXMuTm9uZVxyXG4gICAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICAgIHRha2UoMSksXHJcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5hY3F1aXJlVG9rZW4oYXV0aFJlcXVlc3QsIHNjb3BlcywgYWNjb3VudCkpXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgc3dpdGNoTWFwKChyZXN1bHQ6IEF1dGhlbnRpY2F0aW9uUmVzdWx0KSA9PiB7XHJcbiAgICAgICAgICBpZiAoIXJlc3VsdC5hY2Nlc3NUb2tlbikge1xyXG4gICAgICAgICAgICB0aGlzLmF1dGhTZXJ2aWNlXHJcbiAgICAgICAgICAgICAgLmdldExvZ2dlcigpXHJcbiAgICAgICAgICAgICAgLmVycm9yKFxyXG4gICAgICAgICAgICAgICAgJ0ludGVyY2VwdG9yIC0gYWNxdWlyZVRva2VuU2lsZW50IHJlc29sdmVkIHdpdGggbnVsbCBhY2Nlc3MgdG9rZW4uIEtub3duIGlzc3VlIHdpdGggQjJDIHRlbmFudHMsIGludm9raW5nIGludGVyYWN0aW9uIHRvIHJlc29sdmUuJ1xyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1zYWxCcm9hZGNhc3RTZXJ2aWNlLmluUHJvZ3Jlc3MkLnBpcGUoXHJcbiAgICAgICAgICAgICAgZmlsdGVyKFxyXG4gICAgICAgICAgICAgICAgKHN0YXR1czogSW50ZXJhY3Rpb25TdGF0dXMpID0+IHN0YXR1cyA9PT0gSW50ZXJhY3Rpb25TdGF0dXMuTm9uZVxyXG4gICAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgICAgdGFrZSgxKSxcclxuICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT5cclxuICAgICAgICAgICAgICAgIHRoaXMuYWNxdWlyZVRva2VuSW50ZXJhY3RpdmVseShhdXRoUmVxdWVzdCwgc2NvcGVzKVxyXG4gICAgICAgICAgICAgIClcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiBvZihyZXN1bHQpO1xyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbnZva2UgaW50ZXJhY3Rpb24gZm9yIHRoZSBnaXZlbiBzZXQgb2Ygc2NvcGVzXHJcbiAgICogQHBhcmFtIGF1dGhSZXF1ZXN0IFJlcXVlc3RcclxuICAgKiBAcGFyYW0gc2NvcGVzIEFycmF5IG9mIHNjb3BlcyBmb3IgdGhlIHJlcXVlc3RcclxuICAgKiBAcmV0dXJucyBSZXN1bHQgZnJvbSB0aGUgaW50ZXJhY3RpdmUgcmVxdWVzdFxyXG4gICAqL1xyXG4gIHByaXZhdGUgYWNxdWlyZVRva2VuSW50ZXJhY3RpdmVseShcclxuICAgIGF1dGhSZXF1ZXN0OiBNc2FsSW50ZXJjZXB0b3JBdXRoUmVxdWVzdCxcclxuICAgIHNjb3Blczogc3RyaW5nW11cclxuICApOiBPYnNlcnZhYmxlPEF1dGhlbnRpY2F0aW9uUmVzdWx0PiB7XHJcbiAgICBpZiAodGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcuaW50ZXJhY3Rpb25UeXBlID09PSBJbnRlcmFjdGlvblR5cGUuUG9wdXApIHtcclxuICAgICAgdGhpcy5hdXRoU2VydmljZVxyXG4gICAgICAgIC5nZXRMb2dnZXIoKVxyXG4gICAgICAgIC52ZXJib3NlKFxyXG4gICAgICAgICAgJ0ludGVyY2VwdG9yIC0gZXJyb3IgYWNxdWlyaW5nIHRva2VuIHNpbGVudGx5LCBhY3F1aXJpbmcgYnkgcG9wdXAnXHJcbiAgICAgICAgKTtcclxuICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2UuYWNxdWlyZVRva2VuUG9wdXAoeyAuLi5hdXRoUmVxdWVzdCwgc2NvcGVzIH0pO1xyXG4gICAgfVxyXG4gICAgdGhpcy5hdXRoU2VydmljZVxyXG4gICAgICAuZ2V0TG9nZ2VyKClcclxuICAgICAgLnZlcmJvc2UoXHJcbiAgICAgICAgJ0ludGVyY2VwdG9yIC0gZXJyb3IgYWNxdWlyaW5nIHRva2VuIHNpbGVudGx5LCBhY3F1aXJpbmcgYnkgcmVkaXJlY3QnXHJcbiAgICAgICk7XHJcbiAgICBjb25zdCByZWRpcmVjdFN0YXJ0UGFnZSA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xyXG4gICAgdGhpcy5hdXRoU2VydmljZS5hY3F1aXJlVG9rZW5SZWRpcmVjdCh7XHJcbiAgICAgIC4uLmF1dGhSZXF1ZXN0LFxyXG4gICAgICBzY29wZXMsXHJcbiAgICAgIHJlZGlyZWN0U3RhcnRQYWdlLFxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gRU1QVFk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb29rcyB1cCB0aGUgc2NvcGVzIGZvciB0aGUgZ2l2ZW4gZW5kcG9pbnQgZnJvbSB0aGUgcHJvdGVjdGVkUmVzb3VyY2VNYXBcclxuICAgKiBAcGFyYW0gZW5kcG9pbnQgVXJsIG9mIHRoZSByZXF1ZXN0XHJcbiAgICogQHBhcmFtIGh0dHBNZXRob2QgSHR0cCBtZXRob2Qgb2YgdGhlIHJlcXVlc3RcclxuICAgKiBAcmV0dXJucyBBcnJheSBvZiBzY29wZXMsIG9yIG51bGwgaWYgbm90IGZvdW5kXHJcbiAgICpcclxuICAgKi9cclxuICBwcml2YXRlIGdldFNjb3Blc0ZvckVuZHBvaW50KFxyXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcclxuICAgIGh0dHBNZXRob2Q6IHN0cmluZ1xyXG4gICk6IEFycmF5PHN0cmluZz4gfCBudWxsIHtcclxuICAgIHRoaXMuYXV0aFNlcnZpY2VcclxuICAgICAgLmdldExvZ2dlcigpXHJcbiAgICAgIC52ZXJib3NlKCdJbnRlcmNlcHRvciAtIGdldHRpbmcgc2NvcGVzIGZvciBlbmRwb2ludCcpO1xyXG5cclxuICAgIC8vIEVuc3VyZXMgZW5kcG9pbnRzIGFuZCBwcm90ZWN0ZWQgcmVzb3VyY2VzIGNvbXBhcmVkIGFyZSBub3JtYWxpemVkXHJcbiAgICBjb25zdCBub3JtYWxpemVkRW5kcG9pbnQgPSB0aGlzLmxvY2F0aW9uLm5vcm1hbGl6ZShlbmRwb2ludCk7XHJcblxyXG4gICAgY29uc3QgcHJvdGVjdGVkUmVzb3VyY2VzQXJyYXkgPSBBcnJheS5mcm9tKFxyXG4gICAgICB0aGlzLm1zYWxJbnRlcmNlcHRvckNvbmZpZy5wcm90ZWN0ZWRSZXNvdXJjZU1hcC5rZXlzKClcclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgbWF0Y2hpbmdQcm90ZWN0ZWRSZXNvdXJjZXMgPSB0aGlzLm1hdGNoUmVzb3VyY2VzVG9FbmRwb2ludChcclxuICAgICAgcHJvdGVjdGVkUmVzb3VyY2VzQXJyYXksXHJcbiAgICAgIG5vcm1hbGl6ZWRFbmRwb2ludFxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBDaGVjayBhYnNvbHV0ZSB1cmxzIG9mIHJlc291cmNlcyBmaXJzdCBiZWZvcmUgY2hlY2tpbmcgcmVsYXRpdmUgdG8gcHJldmVudCBpbmNvcnJlY3QgbWF0Y2hpbmcgd2hlcmUgbXVsdGlwbGUgcmVzb3VyY2VzIGhhdmUgc2ltaWxhciByZWxhdGl2ZSB1cmxzXHJcbiAgICBpZiAobWF0Y2hpbmdQcm90ZWN0ZWRSZXNvdXJjZXMuYWJzb2x1dGVSZXNvdXJjZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5tYXRjaFNjb3Blc1RvRW5kcG9pbnQoXHJcbiAgICAgICAgdGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcucHJvdGVjdGVkUmVzb3VyY2VNYXAsXHJcbiAgICAgICAgbWF0Y2hpbmdQcm90ZWN0ZWRSZXNvdXJjZXMuYWJzb2x1dGVSZXNvdXJjZXMsXHJcbiAgICAgICAgaHR0cE1ldGhvZFxyXG4gICAgICApO1xyXG4gICAgfSBlbHNlIGlmIChtYXRjaGluZ1Byb3RlY3RlZFJlc291cmNlcy5yZWxhdGl2ZVJlc291cmNlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLm1hdGNoU2NvcGVzVG9FbmRwb2ludChcclxuICAgICAgICB0aGlzLm1zYWxJbnRlcmNlcHRvckNvbmZpZy5wcm90ZWN0ZWRSZXNvdXJjZU1hcCxcclxuICAgICAgICBtYXRjaGluZ1Byb3RlY3RlZFJlc291cmNlcy5yZWxhdGl2ZVJlc291cmNlcyxcclxuICAgICAgICBodHRwTWV0aG9kXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGaW5kcyByZXNvdXJjZSBlbmRwb2ludHMgdGhhdCBtYXRjaCByZXF1ZXN0IGVuZHBvaW50XHJcbiAgICogQHBhcmFtIHByb3RlY3RlZFJlc291cmNlc0VuZHBvaW50c1xyXG4gICAqIEBwYXJhbSBlbmRwb2ludFxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBtYXRjaFJlc291cmNlc1RvRW5kcG9pbnQoXHJcbiAgICBwcm90ZWN0ZWRSZXNvdXJjZXNFbmRwb2ludHM6IHN0cmluZ1tdLFxyXG4gICAgZW5kcG9pbnQ6IHN0cmluZ1xyXG4gICk6IE1hdGNoaW5nUmVzb3VyY2VzIHtcclxuICAgIGNvbnN0IG1hdGNoaW5nUmVzb3VyY2VzOiBNYXRjaGluZ1Jlc291cmNlcyA9IHtcclxuICAgICAgYWJzb2x1dGVSZXNvdXJjZXM6IFtdLFxyXG4gICAgICByZWxhdGl2ZVJlc291cmNlczogW10sXHJcbiAgICB9O1xyXG5cclxuICAgIHByb3RlY3RlZFJlc291cmNlc0VuZHBvaW50cy5mb3JFYWNoKChrZXkpID0+IHtcclxuICAgICAgLy8gTm9ybWFsaXplcyBhbmQgYWRkcyByZXNvdXJjZSB0byBtYXRjaGluZ1Jlc291cmNlcy5hYnNvbHV0ZVJlc291cmNlcyBpZiBrZXkgbWF0Y2hlcyBlbmRwb2ludC4gU3RyaW5nVXRpbHMubWF0Y2hQYXR0ZXJuIGFjY291bnRzIGZvciB3aWxkY2FyZHNcclxuICAgICAgY29uc3Qgbm9ybWFsaXplZEtleSA9IHRoaXMubG9jYXRpb24ubm9ybWFsaXplKGtleSk7XHJcbiAgICAgIGlmIChTdHJpbmdVdGlscy5tYXRjaFBhdHRlcm4obm9ybWFsaXplZEtleSwgZW5kcG9pbnQpKSB7XHJcbiAgICAgICAgbWF0Y2hpbmdSZXNvdXJjZXMuYWJzb2x1dGVSZXNvdXJjZXMucHVzaChrZXkpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBHZXQgdXJsIGNvbXBvbmVudHMgZm9yIHJlbGF0aXZlIHVybHNcclxuICAgICAgY29uc3QgYWJzb2x1dGVLZXkgPSB0aGlzLmdldEFic29sdXRlVXJsKGtleSk7XHJcbiAgICAgIGNvbnN0IGtleUNvbXBvbmVudHMgPSBuZXcgVXJsU3RyaW5nKGFic29sdXRlS2V5KS5nZXRVcmxDb21wb25lbnRzKCk7XHJcbiAgICAgIGNvbnN0IGFic29sdXRlRW5kcG9pbnQgPSB0aGlzLmdldEFic29sdXRlVXJsKGVuZHBvaW50KTtcclxuICAgICAgY29uc3QgZW5kcG9pbnRDb21wb25lbnRzID0gbmV3IFVybFN0cmluZyhcclxuICAgICAgICBhYnNvbHV0ZUVuZHBvaW50XHJcbiAgICAgICkuZ2V0VXJsQ29tcG9uZW50cygpO1xyXG5cclxuICAgICAgLy8gTm9ybWFsaXplZCBrZXkgc2hvdWxkIGluY2x1ZGUgcXVlcnkgc3RyaW5ncyBpZiBhcHBsaWNhYmxlXHJcbiAgICAgIGNvbnN0IHJlbGF0aXZlTm9ybWFsaXplZEtleSA9IGtleUNvbXBvbmVudHMuUXVlcnlTdHJpbmdcclxuICAgICAgICA/IGAke2tleUNvbXBvbmVudHMuQWJzb2x1dGVQYXRofT8ke2tleUNvbXBvbmVudHMuUXVlcnlTdHJpbmd9YFxyXG4gICAgICAgIDogdGhpcy5sb2NhdGlvbi5ub3JtYWxpemUoa2V5Q29tcG9uZW50cy5BYnNvbHV0ZVBhdGgpO1xyXG5cclxuICAgICAgLy8gQWRkIHJlc291cmNlIHRvIG1hdGNoaW5nUmVzb3VyY2VzLnJlbGF0aXZlUmVzb3VyY2VzIGlmIHNhbWUgb3JpZ2luLCByZWxhdGl2ZUtleSBtYXRjaGVzIGVuZHBvaW50LCBhbmQgaXMgbm90IGVtcHR5XHJcbiAgICAgIGlmIChcclxuICAgICAgICBrZXlDb21wb25lbnRzLkhvc3ROYW1lQW5kUG9ydCA9PT0gZW5kcG9pbnRDb21wb25lbnRzLkhvc3ROYW1lQW5kUG9ydCAmJlxyXG4gICAgICAgIFN0cmluZ1V0aWxzLm1hdGNoUGF0dGVybihyZWxhdGl2ZU5vcm1hbGl6ZWRLZXksIGFic29sdXRlRW5kcG9pbnQpICYmXHJcbiAgICAgICAgcmVsYXRpdmVOb3JtYWxpemVkS2V5ICE9PSAnJyAmJlxyXG4gICAgICAgIHJlbGF0aXZlTm9ybWFsaXplZEtleSAhPT0gJy8qJ1xyXG4gICAgICApIHtcclxuICAgICAgICBtYXRjaGluZ1Jlc291cmNlcy5yZWxhdGl2ZVJlc291cmNlcy5wdXNoKGtleSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiBtYXRjaGluZ1Jlc291cmNlcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRyYW5zZm9ybXMgcmVsYXRpdmUgdXJscyB0byBhYnNvbHV0ZSB1cmxzXHJcbiAgICogQHBhcmFtIHVybFxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXRBYnNvbHV0ZVVybCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBsaW5rID0gdGhpcy5fZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xyXG4gICAgbGluay5ocmVmID0gdXJsO1xyXG4gICAgcmV0dXJuIGxpbmsuaHJlZjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZpbmRzIHNjb3BlcyBmcm9tIGZpcnN0IG1hdGNoaW5nIGVuZHBvaW50IHdpdGggSFRUUCBtZXRob2QgdGhhdCBtYXRjaGVzIHJlcXVlc3RcclxuICAgKiBAcGFyYW0gcHJvdGVjdGVkUmVzb3VyY2VNYXAgUHJvdGVjdGVkIHJlc291cmNlIG1hcFxyXG4gICAqIEBwYXJhbSBlbmRwb2ludEFycmF5IEFycmF5IG9mIHJlc291cmNlcyB0aGF0IG1hdGNoIHJlcXVlc3QgZW5kcG9pbnRcclxuICAgKiBAcGFyYW0gaHR0cE1ldGhvZCBIdHRwIG1ldGhvZCBvZiB0aGUgcmVxdWVzdFxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBtYXRjaFNjb3Blc1RvRW5kcG9pbnQoXHJcbiAgICBwcm90ZWN0ZWRSZXNvdXJjZU1hcDogTWFwPFxyXG4gICAgICBzdHJpbmcsXHJcbiAgICAgIEFycmF5PHN0cmluZyB8IFByb3RlY3RlZFJlc291cmNlU2NvcGVzPiB8IG51bGxcclxuICAgID4sXHJcbiAgICBlbmRwb2ludEFycmF5OiBzdHJpbmdbXSxcclxuICAgIGh0dHBNZXRob2Q6IHN0cmluZ1xyXG4gICk6IEFycmF5PHN0cmluZz4gfCBudWxsIHtcclxuICAgIGNvbnN0IGFsbE1hdGNoZWRTY29wZXMgPSBbXTtcclxuXHJcbiAgICAvLyBDaGVjayBlYWNoIG1hdGNoZWQgZW5kcG9pbnQgZm9yIG1hdGNoaW5nIEh0dHBNZXRob2QgYW5kIHNjb3Blc1xyXG4gICAgZW5kcG9pbnRBcnJheS5mb3JFYWNoKChtYXRjaGVkRW5kcG9pbnQpID0+IHtcclxuICAgICAgY29uc3Qgc2NvcGVzRm9yRW5kcG9pbnQgPSBbXTtcclxuICAgICAgY29uc3QgbWV0aG9kQW5kU2NvcGVzQXJyYXkgPSBwcm90ZWN0ZWRSZXNvdXJjZU1hcC5nZXQobWF0Y2hlZEVuZHBvaW50KTtcclxuXHJcbiAgICAgIC8vIFJldHVybiBpZiByZXNvdXJjZSBpcyB1bnByb3RlY3RlZFxyXG4gICAgICBpZiAobWV0aG9kQW5kU2NvcGVzQXJyYXkgPT09IG51bGwpIHtcclxuICAgICAgICBhbGxNYXRjaGVkU2NvcGVzLnB1c2gobnVsbCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBtZXRob2RBbmRTY29wZXNBcnJheS5mb3JFYWNoKChlbnRyeSkgPT4ge1xyXG4gICAgICAgIC8vIEVudHJ5IGlzIGVpdGhlciBhcnJheSBvZiBzY29wZXMgb3IgUHJvdGVjdGVkUmVzb3VyY2VTY29wZXMgb2JqZWN0XHJcbiAgICAgICAgaWYgKHR5cGVvZiBlbnRyeSA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgIHNjb3Blc0ZvckVuZHBvaW50LnB1c2goZW50cnkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyBFbnN1cmUgbWV0aG9kcyBiZWluZyBjb21wYXJlZCBhcmUgbm9ybWFsaXplZFxyXG4gICAgICAgICAgY29uc3Qgbm9ybWFsaXplZFJlcXVlc3RNZXRob2QgPSBodHRwTWV0aG9kLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkUmVzb3VyY2VNZXRob2QgPSBlbnRyeS5odHRwTWV0aG9kLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgICAvLyBNZXRob2QgaW4gcHJvdGVjdGVkUmVzb3VyY2VNYXAgbWF0Y2hlcyByZXF1ZXN0IGh0dHAgbWV0aG9kXHJcbiAgICAgICAgICBpZiAobm9ybWFsaXplZFJlc291cmNlTWV0aG9kID09PSBub3JtYWxpemVkUmVxdWVzdE1ldGhvZCkge1xyXG4gICAgICAgICAgICAvLyBWYWxpZGF0ZSBpZiBzY29wZXMgY29tZXMgbnVsbCB0byB1bnByb3RlY3QgdGhlIHJlc291cmNlIGluIGEgY2VydGFpbiBodHRwIG1ldGhvZFxyXG4gICAgICAgICAgICBpZiAoZW50cnkuc2NvcGVzID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgYWxsTWF0Y2hlZFNjb3Blcy5wdXNoKG51bGwpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIGVudHJ5LnNjb3Blcy5mb3JFYWNoKChzY29wZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgc2NvcGVzRm9yRW5kcG9pbnQucHVzaChzY29wZSk7XHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gT25seSBhZGQgdG8gYWxsIHNjb3BlcyBpZiBzY29wZXMgZm9yIGVuZHBvaW50IGFuZCBtZXRob2QgaXMgZm91bmRcclxuICAgICAgaWYgKHNjb3Blc0ZvckVuZHBvaW50Lmxlbmd0aCA+IDApIHtcclxuICAgICAgICBhbGxNYXRjaGVkU2NvcGVzLnB1c2goc2NvcGVzRm9yRW5kcG9pbnQpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoYWxsTWF0Y2hlZFNjb3Blcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGlmIChhbGxNYXRjaGVkU2NvcGVzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgICB0aGlzLmF1dGhTZXJ2aWNlXHJcbiAgICAgICAgICAuZ2V0TG9nZ2VyKClcclxuICAgICAgICAgIC53YXJuaW5nKFxyXG4gICAgICAgICAgICAnSW50ZXJjZXB0b3IgLSBNb3JlIHRoYW4gMSBtYXRjaGluZyBzY29wZXMgZm9yIGVuZHBvaW50IGZvdW5kLidcclxuICAgICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gUmV0dXJucyBzY29wZXMgZm9yIGZpcnN0IG1hdGNoaW5nIGVuZHBvaW50XHJcbiAgICAgIHJldHVybiBhbGxNYXRjaGVkU2NvcGVzWzBdO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxufVxyXG4iXX0=
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { Injectable, Inject } from '@angular/core';
|
|
6
|
+
import { DOCUMENT } from '@angular/common';
|
|
7
|
+
import { BrowserConfigurationAuthError, InteractionStatus, InteractionType, StringUtils, UrlString, } from '@azure/msal-browser';
|
|
8
|
+
import { EMPTY, of } from 'rxjs';
|
|
9
|
+
import { switchMap, catchError, take, filter } from 'rxjs/operators';
|
|
10
|
+
import { MSAL_INTERCEPTOR_CONFIG } from './constants';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
import * as i1 from "./msal.service";
|
|
13
|
+
import * as i2 from "@angular/common";
|
|
14
|
+
import * as i3 from "./msal.broadcast.service";
|
|
15
|
+
export class MsalInterceptor {
|
|
16
|
+
constructor(msalInterceptorConfig, authService, location, msalBroadcastService,
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
18
|
+
document) {
|
|
19
|
+
this.msalInterceptorConfig = msalInterceptorConfig;
|
|
20
|
+
this.authService = authService;
|
|
21
|
+
this.location = location;
|
|
22
|
+
this.msalBroadcastService = msalBroadcastService;
|
|
23
|
+
this._document = document;
|
|
24
|
+
}
|
|
25
|
+
intercept(req, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
26
|
+
next
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
) {
|
|
29
|
+
if (this.msalInterceptorConfig.interactionType !== InteractionType.Popup &&
|
|
30
|
+
this.msalInterceptorConfig.interactionType !== InteractionType.Redirect) {
|
|
31
|
+
throw new BrowserConfigurationAuthError('invalid_interaction_type', 'Invalid interaction type provided to MSAL Interceptor. InteractionType.Popup, InteractionType.Redirect must be provided in the msalInterceptorConfiguration');
|
|
32
|
+
}
|
|
33
|
+
this.authService.getLogger().verbose('MSAL Interceptor activated');
|
|
34
|
+
const scopes = this.getScopesForEndpoint(req.url, req.method);
|
|
35
|
+
// If no scopes for endpoint, does not acquire token
|
|
36
|
+
if (!scopes || scopes.length === 0) {
|
|
37
|
+
this.authService
|
|
38
|
+
.getLogger()
|
|
39
|
+
.verbose('Interceptor - no scopes for endpoint');
|
|
40
|
+
return next.handle(req);
|
|
41
|
+
}
|
|
42
|
+
// Sets account as active account or first account
|
|
43
|
+
let account;
|
|
44
|
+
if (!!this.authService.instance.getActiveAccount()) {
|
|
45
|
+
this.authService
|
|
46
|
+
.getLogger()
|
|
47
|
+
.verbose('Interceptor - active account selected');
|
|
48
|
+
account = this.authService.instance.getActiveAccount();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.authService
|
|
52
|
+
.getLogger()
|
|
53
|
+
.verbose('Interceptor - no active account, fallback to first account');
|
|
54
|
+
account = this.authService.instance.getAllAccounts()[0];
|
|
55
|
+
}
|
|
56
|
+
const authRequest = typeof this.msalInterceptorConfig.authRequest === 'function'
|
|
57
|
+
? this.msalInterceptorConfig.authRequest(this.authService, req, {
|
|
58
|
+
account: account,
|
|
59
|
+
})
|
|
60
|
+
: { ...this.msalInterceptorConfig.authRequest, account };
|
|
61
|
+
this.authService
|
|
62
|
+
.getLogger()
|
|
63
|
+
.info(`Interceptor - ${scopes.length} scopes found for endpoint`);
|
|
64
|
+
this.authService
|
|
65
|
+
.getLogger()
|
|
66
|
+
.infoPii(`Interceptor - [${scopes}] scopes found for ${req.url}`);
|
|
67
|
+
return this.acquireToken(authRequest, scopes, account).pipe(switchMap((result) => {
|
|
68
|
+
this.authService
|
|
69
|
+
.getLogger()
|
|
70
|
+
.verbose('Interceptor - setting authorization headers');
|
|
71
|
+
const headers = req.headers.set('Authorization', `Bearer ${result.accessToken}`);
|
|
72
|
+
const requestClone = req.clone({ headers });
|
|
73
|
+
return next.handle(requestClone);
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Try to acquire token silently. Invoke interaction if acquireTokenSilent rejected with error or resolved with null access token
|
|
78
|
+
* @param authRequest Request
|
|
79
|
+
* @param scopes Array of scopes for the request
|
|
80
|
+
* @param account Account
|
|
81
|
+
* @returns Authentication result
|
|
82
|
+
*/
|
|
83
|
+
acquireToken(authRequest, scopes, account) {
|
|
84
|
+
// Note: For MSA accounts, include openid scope when calling acquireTokenSilent to return idToken
|
|
85
|
+
return this.authService
|
|
86
|
+
.acquireTokenSilent({ ...authRequest, scopes, account })
|
|
87
|
+
.pipe(catchError(() => {
|
|
88
|
+
this.authService
|
|
89
|
+
.getLogger()
|
|
90
|
+
.error('Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.');
|
|
91
|
+
return this.msalBroadcastService.inProgress$.pipe(take(1), switchMap((status) => {
|
|
92
|
+
if (status === InteractionStatus.None) {
|
|
93
|
+
return this.acquireTokenInteractively(authRequest, scopes);
|
|
94
|
+
}
|
|
95
|
+
return this.msalBroadcastService.inProgress$.pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireToken(authRequest, scopes, account)));
|
|
96
|
+
}));
|
|
97
|
+
}), switchMap((result) => {
|
|
98
|
+
if (!result.accessToken) {
|
|
99
|
+
this.authService
|
|
100
|
+
.getLogger()
|
|
101
|
+
.error('Interceptor - acquireTokenSilent resolved with null access token. Known issue with B2C tenants, invoking interaction to resolve.');
|
|
102
|
+
return this.msalBroadcastService.inProgress$.pipe(filter((status) => status === InteractionStatus.None), take(1), switchMap(() => this.acquireTokenInteractively(authRequest, scopes)));
|
|
103
|
+
}
|
|
104
|
+
return of(result);
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Invoke interaction for the given set of scopes
|
|
109
|
+
* @param authRequest Request
|
|
110
|
+
* @param scopes Array of scopes for the request
|
|
111
|
+
* @returns Result from the interactive request
|
|
112
|
+
*/
|
|
113
|
+
acquireTokenInteractively(authRequest, scopes) {
|
|
114
|
+
if (this.msalInterceptorConfig.interactionType === InteractionType.Popup) {
|
|
115
|
+
this.authService
|
|
116
|
+
.getLogger()
|
|
117
|
+
.verbose('Interceptor - error acquiring token silently, acquiring by popup');
|
|
118
|
+
return this.authService.acquireTokenPopup({ ...authRequest, scopes });
|
|
119
|
+
}
|
|
120
|
+
this.authService
|
|
121
|
+
.getLogger()
|
|
122
|
+
.verbose('Interceptor - error acquiring token silently, acquiring by redirect');
|
|
123
|
+
const redirectStartPage = window.location.href;
|
|
124
|
+
this.authService.acquireTokenRedirect({
|
|
125
|
+
...authRequest,
|
|
126
|
+
scopes,
|
|
127
|
+
redirectStartPage,
|
|
128
|
+
});
|
|
129
|
+
return EMPTY;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Looks up the scopes for the given endpoint from the protectedResourceMap
|
|
133
|
+
* @param endpoint Url of the request
|
|
134
|
+
* @param httpMethod Http method of the request
|
|
135
|
+
* @returns Array of scopes, or null if not found
|
|
136
|
+
*
|
|
137
|
+
*/
|
|
138
|
+
getScopesForEndpoint(endpoint, httpMethod) {
|
|
139
|
+
this.authService
|
|
140
|
+
.getLogger()
|
|
141
|
+
.verbose('Interceptor - getting scopes for endpoint');
|
|
142
|
+
// Ensures endpoints and protected resources compared are normalized
|
|
143
|
+
const normalizedEndpoint = this.location.normalize(endpoint);
|
|
144
|
+
const protectedResourcesArray = Array.from(this.msalInterceptorConfig.protectedResourceMap.keys());
|
|
145
|
+
const matchingProtectedResources = this.matchResourcesToEndpoint(protectedResourcesArray, normalizedEndpoint);
|
|
146
|
+
// Check absolute urls of resources first before checking relative to prevent incorrect matching where multiple resources have similar relative urls
|
|
147
|
+
if (matchingProtectedResources.absoluteResources.length > 0) {
|
|
148
|
+
return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.absoluteResources, httpMethod);
|
|
149
|
+
}
|
|
150
|
+
else if (matchingProtectedResources.relativeResources.length > 0) {
|
|
151
|
+
return this.matchScopesToEndpoint(this.msalInterceptorConfig.protectedResourceMap, matchingProtectedResources.relativeResources, httpMethod);
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Finds resource endpoints that match request endpoint
|
|
157
|
+
* @param protectedResourcesEndpoints
|
|
158
|
+
* @param endpoint
|
|
159
|
+
* @returns
|
|
160
|
+
*/
|
|
161
|
+
matchResourcesToEndpoint(protectedResourcesEndpoints, endpoint) {
|
|
162
|
+
const matchingResources = {
|
|
163
|
+
absoluteResources: [],
|
|
164
|
+
relativeResources: [],
|
|
165
|
+
};
|
|
166
|
+
protectedResourcesEndpoints.forEach((key) => {
|
|
167
|
+
// Normalizes and adds resource to matchingResources.absoluteResources if key matches endpoint. StringUtils.matchPattern accounts for wildcards
|
|
168
|
+
const normalizedKey = this.location.normalize(key);
|
|
169
|
+
if (StringUtils.matchPattern(normalizedKey, endpoint)) {
|
|
170
|
+
matchingResources.absoluteResources.push(key);
|
|
171
|
+
}
|
|
172
|
+
// Get url components for relative urls
|
|
173
|
+
const absoluteKey = this.getAbsoluteUrl(key);
|
|
174
|
+
const keyComponents = new UrlString(absoluteKey).getUrlComponents();
|
|
175
|
+
const absoluteEndpoint = this.getAbsoluteUrl(endpoint);
|
|
176
|
+
const endpointComponents = new UrlString(absoluteEndpoint).getUrlComponents();
|
|
177
|
+
// Normalized key should include query strings if applicable
|
|
178
|
+
const relativeNormalizedKey = keyComponents.QueryString
|
|
179
|
+
? `${keyComponents.AbsolutePath}?${keyComponents.QueryString}`
|
|
180
|
+
: this.location.normalize(keyComponents.AbsolutePath);
|
|
181
|
+
// Add resource to matchingResources.relativeResources if same origin, relativeKey matches endpoint, and is not empty
|
|
182
|
+
if (keyComponents.HostNameAndPort === endpointComponents.HostNameAndPort &&
|
|
183
|
+
StringUtils.matchPattern(relativeNormalizedKey, absoluteEndpoint) &&
|
|
184
|
+
relativeNormalizedKey !== '' &&
|
|
185
|
+
relativeNormalizedKey !== '/*') {
|
|
186
|
+
matchingResources.relativeResources.push(key);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return matchingResources;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Transforms relative urls to absolute urls
|
|
193
|
+
* @param url
|
|
194
|
+
* @returns
|
|
195
|
+
*/
|
|
196
|
+
getAbsoluteUrl(url) {
|
|
197
|
+
const link = this._document.createElement('a');
|
|
198
|
+
link.href = url;
|
|
199
|
+
return link.href;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Finds scopes from first matching endpoint with HTTP method that matches request
|
|
203
|
+
* @param protectedResourceMap Protected resource map
|
|
204
|
+
* @param endpointArray Array of resources that match request endpoint
|
|
205
|
+
* @param httpMethod Http method of the request
|
|
206
|
+
* @returns
|
|
207
|
+
*/
|
|
208
|
+
matchScopesToEndpoint(protectedResourceMap, endpointArray, httpMethod) {
|
|
209
|
+
const allMatchedScopes = [];
|
|
210
|
+
// Check each matched endpoint for matching HttpMethod and scopes
|
|
211
|
+
endpointArray.forEach((matchedEndpoint) => {
|
|
212
|
+
const scopesForEndpoint = [];
|
|
213
|
+
const methodAndScopesArray = protectedResourceMap.get(matchedEndpoint);
|
|
214
|
+
// Return if resource is unprotected
|
|
215
|
+
if (methodAndScopesArray === null) {
|
|
216
|
+
allMatchedScopes.push(null);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
methodAndScopesArray.forEach((entry) => {
|
|
220
|
+
// Entry is either array of scopes or ProtectedResourceScopes object
|
|
221
|
+
if (typeof entry === 'string') {
|
|
222
|
+
scopesForEndpoint.push(entry);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// Ensure methods being compared are normalized
|
|
226
|
+
const normalizedRequestMethod = httpMethod.toLowerCase();
|
|
227
|
+
const normalizedResourceMethod = entry.httpMethod.toLowerCase();
|
|
228
|
+
// Method in protectedResourceMap matches request http method
|
|
229
|
+
if (normalizedResourceMethod === normalizedRequestMethod) {
|
|
230
|
+
// Validate if scopes comes null to unprotect the resource in a certain http method
|
|
231
|
+
if (entry.scopes === null) {
|
|
232
|
+
allMatchedScopes.push(null);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
entry.scopes.forEach((scope) => {
|
|
236
|
+
scopesForEndpoint.push(scope);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
// Only add to all scopes if scopes for endpoint and method is found
|
|
243
|
+
if (scopesForEndpoint.length > 0) {
|
|
244
|
+
allMatchedScopes.push(scopesForEndpoint);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
if (allMatchedScopes.length > 0) {
|
|
248
|
+
if (allMatchedScopes.length > 1) {
|
|
249
|
+
this.authService
|
|
250
|
+
.getLogger()
|
|
251
|
+
.warning('Interceptor - More than 1 matching scopes for endpoint found.');
|
|
252
|
+
}
|
|
253
|
+
// Returns scopes for first matching endpoint
|
|
254
|
+
return allMatchedScopes[0];
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
MsalInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: MsalInterceptor, deps: [{ token: MSAL_INTERCEPTOR_CONFIG }, { token: i1.MsalService }, { token: i2.Location }, { token: i3.MsalBroadcastService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
260
|
+
MsalInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: MsalInterceptor });
|
|
261
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: MsalInterceptor, decorators: [{
|
|
262
|
+
type: Injectable
|
|
263
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
264
|
+
type: Inject,
|
|
265
|
+
args: [MSAL_INTERCEPTOR_CONFIG]
|
|
266
|
+
}] }, { type: i1.MsalService }, { type: i2.Location }, { type: i3.MsalBroadcastService }, { type: undefined, decorators: [{
|
|
267
|
+
type: Inject,
|
|
268
|
+
args: [DOCUMENT]
|
|
269
|
+
}] }]; } });
|
|
270
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXNhbC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tc2FsLmludGVyY2VwdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBWSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQU9yRCxPQUFPLEVBR0wsNkJBQTZCLEVBQzdCLGlCQUFpQixFQUNqQixlQUFlLEVBQ2YsV0FBVyxFQUNYLFNBQVMsR0FDVixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBYyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVNyRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxhQUFhLENBQUM7Ozs7O0FBR3RELE1BQU0sT0FBTyxlQUFlO0lBRzFCLFlBRVUscUJBQW1ELEVBQ25ELFdBQXdCLEVBQ3hCLFFBQWtCLEVBQ2xCLG9CQUEwQztJQUNsRCxpSEFBaUg7SUFDL0YsUUFBYztRQUx4QiwwQkFBcUIsR0FBckIscUJBQXFCLENBQThCO1FBQ25ELGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLGFBQVEsR0FBUixRQUFRLENBQVU7UUFDbEIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUlsRCxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQW9CLENBQUM7SUFDeEMsQ0FBQztJQUVELFNBQVMsQ0FDUCxHQUFxQixFQUFFLHlEQUF5RDtJQUNoRixJQUFpQjtJQUNqQiw4REFBOEQ7O1FBRTlELElBQ0UsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGVBQWUsS0FBSyxlQUFlLENBQUMsS0FBSztZQUNwRSxJQUFJLENBQUMscUJBQXFCLENBQUMs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QU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO2dDQUM3QixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7NEJBQ2hDLENBQUMsQ0FBQyxDQUFDO3lCQUNKO3FCQUNGO2lCQUNGO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFFSCxvRUFBb0U7WUFDcEUsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNoQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQzthQUMxQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQy9CLElBQUksZ0JBQWdCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDL0IsSUFBSSxDQUFDLFdBQVc7cUJBQ2IsU0FBUyxFQUFFO3FCQUNYLE9BQU8sQ0FDTiwrREFBK0QsQ0FDaEUsQ0FBQzthQUNMO1lBQ0QsNkNBQTZDO1lBQzdDLE9BQU8sZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDNUI7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7OzRHQWpXVSxlQUFlLGtCQUloQix1QkFBdUIsb0dBTXZCLFFBQVE7Z0hBVlAsZUFBZTsyRkFBZixlQUFlO2tCQUQzQixVQUFVOzswQkFLTixNQUFNOzJCQUFDLHVCQUF1Qjs7MEJBTTlCLE1BQU07MkJBQUMsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IExvY2F0aW9uLCBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBIdHRwUmVxdWVzdCxcbiAgSHR0cEhhbmRsZXIsXG4gIEh0dHBFdmVudCxcbiAgSHR0cEludGVyY2VwdG9yLFxufSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgaW1wb3J0L25vLXVucmVzb2x2ZWRcbmltcG9ydCB7XG4gIEFjY291bnRJbmZvLFxuICBBdXRoZW50aWNhdGlvblJlc3VsdCxcbiAgQnJvd3NlckNvbmZpZ3VyYXRpb25BdXRoRXJyb3IsXG4gIEludGVyYWN0aW9uU3RhdHVzLFxuICBJbnRlcmFjdGlvblR5cGUsXG4gIFN0cmluZ1V0aWxzLFxuICBVcmxTdHJpbmcsXG59IGZyb20gJ0BhenVyZS9tc2FsLWJyb3dzZXInO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgRU1QVFksIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIGNhdGNoRXJyb3IsIHRha2UsIGZpbHRlciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE1zYWxTZXJ2aWNlIH0gZnJvbSAnLi9tc2FsLnNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgTXNhbEludGVyY2VwdG9yQXV0aFJlcXVlc3QsXG4gIE1zYWxJbnRlcmNlcHRvckNvbmZpZ3VyYXRpb24sXG4gIFByb3RlY3RlZFJlc291cmNlU2NvcGVzLFxuICBNYXRjaGluZ1Jlc291cmNlcyxcbn0gZnJvbSAnLi9tc2FsLmludGVyY2VwdG9yLmNvbmZpZyc7XG5pbXBvcnQgeyBNc2FsQnJvYWRjYXN0U2VydmljZSB9IGZyb20gJy4vbXNhbC5icm9hZGNhc3Quc2VydmljZSc7XG5pbXBvcnQgeyBNU0FMX0lOVEVSQ0VQVE9SX0NPTkZJRyB9IGZyb20gJy4vY29uc3RhbnRzJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE1zYWxJbnRlcmNlcHRvciBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XG4gIHByaXZhdGUgX2RvY3VtZW50PzogRG9jdW1lbnQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChNU0FMX0lOVEVSQ0VQVE9SX0NPTkZJRylcbiAgICBwcml2YXRlIG1zYWxJbnRlcmNlcHRvckNvbmZpZzogTXNhbEludGVyY2VwdG9yQ29uZmlndXJhdGlvbixcbiAgICBwcml2YXRlIGF1dGhTZXJ2aWNlOiBNc2FsU2VydmljZSxcbiAgICBwcml2YXRlIGxvY2F0aW9uOiBMb2NhdGlvbixcbiAgICBwcml2YXRlIG1zYWxCcm9hZGNhc3RTZXJ2aWNlOiBNc2FsQnJvYWRjYXN0U2VydmljZSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSwgQHR5cGVzY3JpcHQtZXNsaW50L2V4cGxpY2l0LW1vZHVsZS1ib3VuZGFyeS10eXBlc1xuICAgIEBJbmplY3QoRE9DVU1FTlQpIGRvY3VtZW50PzogYW55XG4gICkge1xuICAgIHRoaXMuX2RvY3VtZW50ID0gZG9jdW1lbnQgYXMgRG9jdW1lbnQ7XG4gIH1cblxuICBpbnRlcmNlcHQoXG4gICAgcmVxOiBIdHRwUmVxdWVzdDxhbnk+LCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBuZXh0OiBIdHRwSGFuZGxlclxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICk6IE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+IHtcbiAgICBpZiAoXG4gICAgICB0aGlzLm1zYWxJbnRlcmNlcHRvckNvbmZpZy5pbnRlcmFjdGlvblR5cGUgIT09IEludGVyYWN0aW9uVHlwZS5Qb3B1cCAmJlxuICAgICAgdGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcuaW50ZXJhY3Rpb25UeXBlICE9PSBJbnRlcmFjdGlvblR5cGUuUmVkaXJlY3RcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBCcm93c2VyQ29uZmlndXJhdGlvbkF1dGhFcnJvcihcbiAgICAgICAgJ2ludmFsaWRfaW50ZXJhY3Rpb25fdHlwZScsXG4gICAgICAgICdJbnZhbGlkIGludGVyYWN0aW9uIHR5cGUgcHJvdmlkZWQgdG8gTVNBTCBJbnRlcmNlcHRvci4gSW50ZXJhY3Rpb25UeXBlLlBvcHVwLCBJbnRlcmFjdGlvblR5cGUuUmVkaXJlY3QgbXVzdCBiZSBwcm92aWRlZCBpbiB0aGUgbXNhbEludGVyY2VwdG9yQ29uZmlndXJhdGlvbidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5hdXRoU2VydmljZS5nZXRMb2dnZXIoKS52ZXJib3NlKCdNU0FMIEludGVyY2VwdG9yIGFjdGl2YXRlZCcpO1xuICAgIGNvbnN0IHNjb3BlcyA9IHRoaXMuZ2V0U2NvcGVzRm9yRW5kcG9pbnQocmVxLnVybCwgcmVxLm1ldGhvZCk7XG5cbiAgICAvLyBJZiBubyBzY29wZXMgZm9yIGVuZHBvaW50LCBkb2VzIG5vdCBhY3F1aXJlIHRva2VuXG4gICAgaWYgKCFzY29wZXMgfHwgc2NvcGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5hdXRoU2VydmljZVxuICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgLnZlcmJvc2UoJ0ludGVyY2VwdG9yIC0gbm8gc2NvcGVzIGZvciBlbmRwb2ludCcpO1xuICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSk7XG4gICAgfVxuXG4gICAgLy8gU2V0cyBhY2NvdW50IGFzIGFjdGl2ZSBhY2NvdW50IG9yIGZpcnN0IGFjY291bnRcbiAgICBsZXQgYWNjb3VudDogQWNjb3VudEluZm87XG4gICAgaWYgKCEhdGhpcy5hdXRoU2VydmljZS5pbnN0YW5jZS5nZXRBY3RpdmVBY2NvdW50KCkpIHtcbiAgICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgIC52ZXJib3NlKCdJbnRlcmNlcHRvciAtIGFjdGl2ZSBhY2NvdW50IHNlbGVjdGVkJyk7XG4gICAgICBhY2NvdW50ID0gdGhpcy5hdXRoU2VydmljZS5pbnN0YW5jZS5nZXRBY3RpdmVBY2NvdW50KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgIC52ZXJib3NlKCdJbnRlcmNlcHRvciAtIG5vIGFjdGl2ZSBhY2NvdW50LCBmYWxsYmFjayB0byBmaXJzdCBhY2NvdW50Jyk7XG4gICAgICBhY2NvdW50ID0gdGhpcy5hdXRoU2VydmljZS5pbnN0YW5jZS5nZXRBbGxBY2NvdW50cygpWzBdO1xuICAgIH1cblxuICAgIGNvbnN0IGF1dGhSZXF1ZXN0ID1cbiAgICAgIHR5cGVvZiB0aGlzLm1zYWxJbnRlcmNlcHRvckNvbmZpZy5hdXRoUmVxdWVzdCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICA/IHRoaXMubXNhbEludGVyY2VwdG9yQ29uZmlnLmF1dGhSZXF1ZXN0KHRoaXMuYXV0aFNlcnZpY2UsIHJlcSwge1xuICAgICAgICAgICAgYWNjb3VudDogYWNjb3VudCxcbiAgICAgICAgICB9KVxuICAgICAgICA6IHsgLi4udGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcuYXV0aFJlcXVlc3QsIGFjY291bnQgfTtcblxuICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgIC5nZXRMb2dnZXIoKVxuICAgICAgLmluZm8oYEludGVyY2VwdG9yIC0gJHtzY29wZXMubGVuZ3RofSBzY29wZXMgZm91bmQgZm9yIGVuZHBvaW50YCk7XG4gICAgdGhpcy5hdXRoU2VydmljZVxuICAgICAgLmdldExvZ2dlcigpXG4gICAgICAuaW5mb1BpaShgSW50ZXJjZXB0b3IgLSBbJHtzY29wZXN9XSBzY29wZXMgZm91bmQgZm9yICR7cmVxLnVybH1gKTtcblxuICAgIHJldHVybiB0aGlzLmFjcXVpcmVUb2tlbihhdXRoUmVxdWVzdCwgc2NvcGVzLCBhY2NvdW50KS5waXBlKFxuICAgICAgc3dpdGNoTWFwKChyZXN1bHQ6IEF1dGhlbnRpY2F0aW9uUmVzdWx0KSA9PiB7XG4gICAgICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgICAudmVyYm9zZSgnSW50ZXJjZXB0b3IgLSBzZXR0aW5nIGF1dGhvcml6YXRpb24gaGVhZGVycycpO1xuICAgICAgICBjb25zdCBoZWFkZXJzID0gcmVxLmhlYWRlcnMuc2V0KFxuICAgICAgICAgICdBdXRob3JpemF0aW9uJyxcbiAgICAgICAgICBgQmVhcmVyICR7cmVzdWx0LmFjY2Vzc1Rva2VufWBcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCByZXF1ZXN0Q2xvbmUgPSByZXEuY2xvbmUoeyBoZWFkZXJzIH0pO1xuICAgICAgICByZXR1cm4gbmV4dC5oYW5kbGUocmVxdWVzdENsb25lKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcnkgdG8gYWNxdWlyZSB0b2tlbiBzaWxlbnRseS4gSW52b2tlIGludGVyYWN0aW9uIGlmIGFjcXVpcmVUb2tlblNpbGVudCByZWplY3RlZCB3aXRoIGVycm9yIG9yIHJlc29sdmVkIHdpdGggbnVsbCBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIGF1dGhSZXF1ZXN0IFJlcXVlc3RcbiAgICogQHBhcmFtIHNjb3BlcyBBcnJheSBvZiBzY29wZXMgZm9yIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBhY2NvdW50IEFjY291bnRcbiAgICogQHJldHVybnMgQXV0aGVudGljYXRpb24gcmVzdWx0XG4gICAqL1xuICBwcml2YXRlIGFjcXVpcmVUb2tlbihcbiAgICBhdXRoUmVxdWVzdDogTXNhbEludGVyY2VwdG9yQXV0aFJlcXVlc3QsXG4gICAgc2NvcGVzOiBzdHJpbmdbXSxcbiAgICBhY2NvdW50OiBBY2NvdW50SW5mb1xuICApOiBPYnNlcnZhYmxlPEF1dGhlbnRpY2F0aW9uUmVzdWx0PiB7XG4gICAgLy8gTm90ZTogRm9yIE1TQSBhY2NvdW50cywgaW5jbHVkZSBvcGVuaWQgc2NvcGUgd2hlbiBjYWxsaW5nIGFjcXVpcmVUb2tlblNpbGVudCB0byByZXR1cm4gaWRUb2tlblxuICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlXG4gICAgICAuYWNxdWlyZVRva2VuU2lsZW50KHsgLi4uYXV0aFJlcXVlc3QsIHNjb3BlcywgYWNjb3VudCB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgICAgICAgIC5nZXRMb2dnZXIoKVxuICAgICAgICAgICAgLmVycm9yKFxuICAgICAgICAgICAgICAnSW50ZXJjZXB0b3IgLSBhY3F1aXJlVG9rZW5TaWxlbnQgcmVqZWN0ZWQgd2l0aCBlcnJvci4gSW52b2tpbmcgaW50ZXJhY3Rpb24gdG8gcmVzb2x2ZS4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB0aGlzLm1zYWxCcm9hZGNhc3RTZXJ2aWNlLmluUHJvZ3Jlc3MkLnBpcGUoXG4gICAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgICAgc3dpdGNoTWFwKChzdGF0dXM6IEludGVyYWN0aW9uU3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChzdGF0dXMgPT09IEludGVyYWN0aW9uU3RhdHVzLk5vbmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3F1aXJlVG9rZW5JbnRlcmFjdGl2ZWx5KGF1dGhSZXF1ZXN0LCBzY29wZXMpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubXNhbEJyb2FkY2FzdFNlcnZpY2UuaW5Qcm9ncmVzcyQucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoXG4gICAgICAgICAgICAgICAgICAoc3RhdHVzOiBJbnRlcmFjdGlvblN0YXR1cykgPT5cbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID09PSBJbnRlcmFjdGlvblN0YXR1cy5Ob25lXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLmFjcXVpcmVUb2tlbihhdXRoUmVxdWVzdCwgc2NvcGVzLCBhY2NvdW50KSlcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKTtcbiAgICAgICAgfSksXG4gICAgICAgIHN3aXRjaE1hcCgocmVzdWx0OiBBdXRoZW50aWNhdGlvblJlc3VsdCkgPT4ge1xuICAgICAgICAgIGlmICghcmVzdWx0LmFjY2Vzc1Rva2VuKSB7XG4gICAgICAgICAgICB0aGlzLmF1dGhTZXJ2aWNlXG4gICAgICAgICAgICAgIC5nZXRMb2dnZXIoKVxuICAgICAgICAgICAgICAuZXJyb3IoXG4gICAgICAgICAgICAgICAgJ0ludGVyY2VwdG9yIC0gYWNxdWlyZVRva2VuU2lsZW50IHJlc29sdmVkIHdpdGggbnVsbCBhY2Nlc3MgdG9rZW4uIEtub3duIGlzc3VlIHdpdGggQjJDIHRlbmFudHMsIGludm9raW5nIGludGVyYWN0aW9uIHRvIHJlc29sdmUuJ1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXNhbEJyb2FkY2FzdFNlcnZpY2UuaW5Qcm9ncmVzcyQucGlwZShcbiAgICAgICAgICAgICAgZmlsdGVyKFxuICAgICAgICAgICAgICAgIChzdGF0dXM6IEludGVyYWN0aW9uU3RhdHVzKSA9PiBzdGF0dXMgPT09IEludGVyYWN0aW9uU3RhdHVzLk5vbmVcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICAgICAgc3dpdGNoTWFwKCgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5hY3F1aXJlVG9rZW5JbnRlcmFjdGl2ZWx5KGF1dGhSZXF1ZXN0LCBzY29wZXMpXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBvZihyZXN1bHQpO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2UgaW50ZXJhY3Rpb24gZm9yIHRoZSBnaXZlbiBzZXQgb2Ygc2NvcGVzXG4gICAqIEBwYXJhbSBhdXRoUmVxdWVzdCBSZXF1ZXN0XG4gICAqIEBwYXJhbSBzY29wZXMgQXJyYXkgb2Ygc2NvcGVzIGZvciB0aGUgcmVxdWVzdFxuICAgKiBAcmV0dXJucyBSZXN1bHQgZnJvbSB0aGUgaW50ZXJhY3RpdmUgcmVxdWVzdFxuICAgKi9cbiAgcHJpdmF0ZSBhY3F1aXJlVG9rZW5JbnRlcmFjdGl2ZWx5KFxuICAgIGF1dGhSZXF1ZXN0OiBNc2FsSW50ZXJjZXB0b3JBdXRoUmVxdWVzdCxcbiAgICBzY29wZXM6IHN0cmluZ1tdXG4gICk6IE9ic2VydmFibGU8QXV0aGVudGljYXRpb25SZXN1bHQ+IHtcbiAgICBpZiAodGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcuaW50ZXJhY3Rpb25UeXBlID09PSBJbnRlcmFjdGlvblR5cGUuUG9wdXApIHtcbiAgICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgIC52ZXJib3NlKFxuICAgICAgICAgICdJbnRlcmNlcHRvciAtIGVycm9yIGFjcXVpcmluZyB0b2tlbiBzaWxlbnRseSwgYWNxdWlyaW5nIGJ5IHBvcHVwJ1xuICAgICAgICApO1xuICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2UuYWNxdWlyZVRva2VuUG9wdXAoeyAuLi5hdXRoUmVxdWVzdCwgc2NvcGVzIH0pO1xuICAgIH1cbiAgICB0aGlzLmF1dGhTZXJ2aWNlXG4gICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgIC52ZXJib3NlKFxuICAgICAgICAnSW50ZXJjZXB0b3IgLSBlcnJvciBhY3F1aXJpbmcgdG9rZW4gc2lsZW50bHksIGFjcXVpcmluZyBieSByZWRpcmVjdCdcbiAgICAgICk7XG4gICAgY29uc3QgcmVkaXJlY3RTdGFydFBhZ2UgPSB3aW5kb3cubG9jYXRpb24uaHJlZjtcbiAgICB0aGlzLmF1dGhTZXJ2aWNlLmFjcXVpcmVUb2tlblJlZGlyZWN0KHtcbiAgICAgIC4uLmF1dGhSZXF1ZXN0LFxuICAgICAgc2NvcGVzLFxuICAgICAgcmVkaXJlY3RTdGFydFBhZ2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIEVNUFRZO1xuICB9XG5cbiAgLyoqXG4gICAqIExvb2tzIHVwIHRoZSBzY29wZXMgZm9yIHRoZSBnaXZlbiBlbmRwb2ludCBmcm9tIHRoZSBwcm90ZWN0ZWRSZXNvdXJjZU1hcFxuICAgKiBAcGFyYW0gZW5kcG9pbnQgVXJsIG9mIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBodHRwTWV0aG9kIEh0dHAgbWV0aG9kIG9mIHRoZSByZXF1ZXN0XG4gICAqIEByZXR1cm5zIEFycmF5IG9mIHNjb3Blcywgb3IgbnVsbCBpZiBub3QgZm91bmRcbiAgICpcbiAgICovXG4gIHByaXZhdGUgZ2V0U2NvcGVzRm9yRW5kcG9pbnQoXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICBodHRwTWV0aG9kOiBzdHJpbmdcbiAgKTogQXJyYXk8c3RyaW5nPiB8IG51bGwge1xuICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgIC5nZXRMb2dnZXIoKVxuICAgICAgLnZlcmJvc2UoJ0ludGVyY2VwdG9yIC0gZ2V0dGluZyBzY29wZXMgZm9yIGVuZHBvaW50Jyk7XG5cbiAgICAvLyBFbnN1cmVzIGVuZHBvaW50cyBhbmQgcHJvdGVjdGVkIHJlc291cmNlcyBjb21wYXJlZCBhcmUgbm9ybWFsaXplZFxuICAgIGNvbnN0IG5vcm1hbGl6ZWRFbmRwb2ludCA9IHRoaXMubG9jYXRpb24ubm9ybWFsaXplKGVuZHBvaW50KTtcblxuICAgIGNvbnN0IHByb3RlY3RlZFJlc291cmNlc0FycmF5ID0gQXJyYXkuZnJvbShcbiAgICAgIHRoaXMubXNhbEludGVyY2VwdG9yQ29uZmlnLnByb3RlY3RlZFJlc291cmNlTWFwLmtleXMoKVxuICAgICk7XG5cbiAgICBjb25zdCBtYXRjaGluZ1Byb3RlY3RlZFJlc291cmNlcyA9IHRoaXMubWF0Y2hSZXNvdXJjZXNUb0VuZHBvaW50KFxuICAgICAgcHJvdGVjdGVkUmVzb3VyY2VzQXJyYXksXG4gICAgICBub3JtYWxpemVkRW5kcG9pbnRcbiAgICApO1xuXG4gICAgLy8gQ2hlY2sgYWJzb2x1dGUgdXJscyBvZiByZXNvdXJjZXMgZmlyc3QgYmVmb3JlIGNoZWNraW5nIHJlbGF0aXZlIHRvIHByZXZlbnQgaW5jb3JyZWN0IG1hdGNoaW5nIHdoZXJlIG11bHRpcGxlIHJlc291cmNlcyBoYXZlIHNpbWlsYXIgcmVsYXRpdmUgdXJsc1xuICAgIGlmIChtYXRjaGluZ1Byb3RlY3RlZFJlc291cmNlcy5hYnNvbHV0ZVJlc291cmNlcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5tYXRjaFNjb3Blc1RvRW5kcG9pbnQoXG4gICAgICAgIHRoaXMubXNhbEludGVyY2VwdG9yQ29uZmlnLnByb3RlY3RlZFJlc291cmNlTWFwLFxuICAgICAgICBtYXRjaGluZ1Byb3RlY3RlZFJlc291cmNlcy5hYnNvbHV0ZVJlc291cmNlcyxcbiAgICAgICAgaHR0cE1ldGhvZFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKG1hdGNoaW5nUHJvdGVjdGVkUmVzb3VyY2VzLnJlbGF0aXZlUmVzb3VyY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLm1hdGNoU2NvcGVzVG9FbmRwb2ludChcbiAgICAgICAgdGhpcy5tc2FsSW50ZXJjZXB0b3JDb25maWcucHJvdGVjdGVkUmVzb3VyY2VNYXAsXG4gICAgICAgIG1hdGNoaW5nUHJvdGVjdGVkUmVzb3VyY2VzLnJlbGF0aXZlUmVzb3VyY2VzLFxuICAgICAgICBodHRwTWV0aG9kXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHJlc291cmNlIGVuZHBvaW50cyB0aGF0IG1hdGNoIHJlcXVlc3QgZW5kcG9pbnRcbiAgICogQHBhcmFtIHByb3RlY3RlZFJlc291cmNlc0VuZHBvaW50c1xuICAgKiBAcGFyYW0gZW5kcG9pbnRcbiAgICogQHJldHVybnNcbiAgICovXG4gIHByaXZhdGUgbWF0Y2hSZXNvdXJjZXNUb0VuZHBvaW50KFxuICAgIHByb3RlY3RlZFJlc291cmNlc0VuZHBvaW50czogc3RyaW5nW10sXG4gICAgZW5kcG9pbnQ6IHN0cmluZ1xuICApOiBNYXRjaGluZ1Jlc291cmNlcyB7XG4gICAgY29uc3QgbWF0Y2hpbmdSZXNvdXJjZXM6IE1hdGNoaW5nUmVzb3VyY2VzID0ge1xuICAgICAgYWJzb2x1dGVSZXNvdXJjZXM6IFtdLFxuICAgICAgcmVsYXRpdmVSZXNvdXJjZXM6IFtdLFxuICAgIH07XG5cbiAgICBwcm90ZWN0ZWRSZXNvdXJjZXNFbmRwb2ludHMuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAvLyBOb3JtYWxpemVzIGFuZCBhZGRzIHJlc291cmNlIHRvIG1hdGNoaW5nUmVzb3VyY2VzLmFic29sdXRlUmVzb3VyY2VzIGlmIGtleSBtYXRjaGVzIGVuZHBvaW50LiBTdHJpbmdVdGlscy5tYXRjaFBhdHRlcm4gYWNjb3VudHMgZm9yIHdpbGRjYXJkc1xuICAgICAgY29uc3Qgbm9ybWFsaXplZEtleSA9IHRoaXMubG9jYXRpb24ubm9ybWFsaXplKGtleSk7XG4gICAgICBpZiAoU3RyaW5nVXRpbHMubWF0Y2hQYXR0ZXJuKG5vcm1hbGl6ZWRLZXksIGVuZHBvaW50KSkge1xuICAgICAgICBtYXRjaGluZ1Jlc291cmNlcy5hYnNvbHV0ZVJlc291cmNlcy5wdXNoKGtleSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEdldCB1cmwgY29tcG9uZW50cyBmb3IgcmVsYXRpdmUgdXJsc1xuICAgICAgY29uc3QgYWJzb2x1dGVLZXkgPSB0aGlzLmdldEFic29sdXRlVXJsKGtleSk7XG4gICAgICBjb25zdCBrZXlDb21wb25lbnRzID0gbmV3IFVybFN0cmluZyhhYnNvbHV0ZUtleSkuZ2V0VXJsQ29tcG9uZW50cygpO1xuICAgICAgY29uc3QgYWJzb2x1dGVFbmRwb2ludCA9IHRoaXMuZ2V0QWJzb2x1dGVVcmwoZW5kcG9pbnQpO1xuICAgICAgY29uc3QgZW5kcG9pbnRDb21wb25lbnRzID0gbmV3IFVybFN0cmluZyhcbiAgICAgICAgYWJzb2x1dGVFbmRwb2ludFxuICAgICAgKS5nZXRVcmxDb21wb25lbnRzKCk7XG5cbiAgICAgIC8vIE5vcm1hbGl6ZWQga2V5IHNob3VsZCBpbmNsdWRlIHF1ZXJ5IHN0cmluZ3MgaWYgYXBwbGljYWJsZVxuICAgICAgY29uc3QgcmVsYXRpdmVOb3JtYWxpemVkS2V5ID0ga2V5Q29tcG9uZW50cy5RdWVyeVN0cmluZ1xuICAgICAgICA/IGAke2tleUNvbXBvbmVudHMuQWJzb2x1dGVQYXRofT8ke2tleUNvbXBvbmVudHMuUXVlcnlTdHJpbmd9YFxuICAgICAgICA6IHRoaXMubG9jYXRpb24ubm9ybWFsaXplKGtleUNvbXBvbmVudHMuQWJzb2x1dGVQYXRoKTtcblxuICAgICAgLy8gQWRkIHJlc291cmNlIHRvIG1hdGNoaW5nUmVzb3VyY2VzLnJlbGF0aXZlUmVzb3VyY2VzIGlmIHNhbWUgb3JpZ2luLCByZWxhdGl2ZUtleSBtYXRjaGVzIGVuZHBvaW50LCBhbmQgaXMgbm90IGVtcHR5XG4gICAgICBpZiAoXG4gICAgICAgIGtleUNvbXBvbmVudHMuSG9zdE5hbWVBbmRQb3J0ID09PSBlbmRwb2ludENvbXBvbmVudHMuSG9zdE5hbWVBbmRQb3J0ICYmXG4gICAgICAgIFN0cmluZ1V0aWxzLm1hdGNoUGF0dGVybihyZWxhdGl2ZU5vcm1hbGl6ZWRLZXksIGFic29sdXRlRW5kcG9pbnQpICYmXG4gICAgICAgIHJlbGF0aXZlTm9ybWFsaXplZEtleSAhPT0gJycgJiZcbiAgICAgICAgcmVsYXRpdmVOb3JtYWxpemVkS2V5ICE9PSAnLyonXG4gICAgICApIHtcbiAgICAgICAgbWF0Y2hpbmdSZXNvdXJjZXMucmVsYXRpdmVSZXNvdXJjZXMucHVzaChrZXkpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIG1hdGNoaW5nUmVzb3VyY2VzO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZm9ybXMgcmVsYXRpdmUgdXJscyB0byBhYnNvbHV0ZSB1cmxzXG4gICAqIEBwYXJhbSB1cmxcbiAgICogQHJldHVybnNcbiAgICovXG4gIHByaXZhdGUgZ2V0QWJzb2x1dGVVcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGxpbmsgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgbGluay5ocmVmID0gdXJsO1xuICAgIHJldHVybiBsaW5rLmhyZWY7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgc2NvcGVzIGZyb20gZmlyc3QgbWF0Y2hpbmcgZW5kcG9pbnQgd2l0aCBIVFRQIG1ldGhvZCB0aGF0IG1hdGNoZXMgcmVxdWVzdFxuICAgKiBAcGFyYW0gcHJvdGVjdGVkUmVzb3VyY2VNYXAgUHJvdGVjdGVkIHJlc291cmNlIG1hcFxuICAgKiBAcGFyYW0gZW5kcG9pbnRBcnJheSBBcnJheSBvZiByZXNvdXJjZXMgdGhhdCBtYXRjaCByZXF1ZXN0IGVuZHBvaW50XG4gICAqIEBwYXJhbSBodHRwTWV0aG9kIEh0dHAgbWV0aG9kIG9mIHRoZSByZXF1ZXN0XG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBwcml2YXRlIG1hdGNoU2NvcGVzVG9FbmRwb2ludChcbiAgICBwcm90ZWN0ZWRSZXNvdXJjZU1hcDogTWFwPFxuICAgICAgc3RyaW5nLFxuICAgICAgQXJyYXk8c3RyaW5nIHwgUHJvdGVjdGVkUmVzb3VyY2VTY29wZXM+IHwgbnVsbFxuICAgID4sXG4gICAgZW5kcG9pbnRBcnJheTogc3RyaW5nW10sXG4gICAgaHR0cE1ldGhvZDogc3RyaW5nXG4gICk6IEFycmF5PHN0cmluZz4gfCBudWxsIHtcbiAgICBjb25zdCBhbGxNYXRjaGVkU2NvcGVzID0gW107XG5cbiAgICAvLyBDaGVjayBlYWNoIG1hdGNoZWQgZW5kcG9pbnQgZm9yIG1hdGNoaW5nIEh0dHBNZXRob2QgYW5kIHNjb3Blc1xuICAgIGVuZHBvaW50QXJyYXkuZm9yRWFjaCgobWF0Y2hlZEVuZHBvaW50KSA9PiB7XG4gICAgICBjb25zdCBzY29wZXNGb3JFbmRwb2ludCA9IFtdO1xuICAgICAgY29uc3QgbWV0aG9kQW5kU2NvcGVzQXJyYXkgPSBwcm90ZWN0ZWRSZXNvdXJjZU1hcC5nZXQobWF0Y2hlZEVuZHBvaW50KTtcblxuICAgICAgLy8gUmV0dXJuIGlmIHJlc291cmNlIGlzIHVucHJvdGVjdGVkXG4gICAgICBpZiAobWV0aG9kQW5kU2NvcGVzQXJyYXkgPT09IG51bGwpIHtcbiAgICAgICAgYWxsTWF0Y2hlZFNjb3Blcy5wdXNoKG51bGwpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIG1ldGhvZEFuZFNjb3Blc0FycmF5LmZvckVhY2goKGVudHJ5KSA9PiB7XG4gICAgICAgIC8vIEVudHJ5IGlzIGVpdGhlciBhcnJheSBvZiBzY29wZXMgb3IgUHJvdGVjdGVkUmVzb3VyY2VTY29wZXMgb2JqZWN0XG4gICAgICAgIGlmICh0eXBlb2YgZW50cnkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgc2NvcGVzRm9yRW5kcG9pbnQucHVzaChlbnRyeSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRW5zdXJlIG1ldGhvZHMgYmVpbmcgY29tcGFyZWQgYXJlIG5vcm1hbGl6ZWRcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkUmVxdWVzdE1ldGhvZCA9IGh0dHBNZXRob2QudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkUmVzb3VyY2VNZXRob2QgPSBlbnRyeS5odHRwTWV0aG9kLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgLy8gTWV0aG9kIGluIHByb3RlY3RlZFJlc291cmNlTWFwIG1hdGNoZXMgcmVxdWVzdCBodHRwIG1ldGhvZFxuICAgICAgICAgIGlmIChub3JtYWxpemVkUmVzb3VyY2VNZXRob2QgPT09IG5vcm1hbGl6ZWRSZXF1ZXN0TWV0aG9kKSB7XG4gICAgICAgICAgICAvLyBWYWxpZGF0ZSBpZiBzY29wZXMgY29tZXMgbnVsbCB0byB1bnByb3RlY3QgdGhlIHJlc291cmNlIGluIGEgY2VydGFpbiBodHRwIG1ldGhvZFxuICAgICAgICAgICAgaWYgKGVudHJ5LnNjb3BlcyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICBhbGxNYXRjaGVkU2NvcGVzLnB1c2gobnVsbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBlbnRyeS5zY29wZXMuZm9yRWFjaCgoc2NvcGUpID0+IHtcbiAgICAgICAgICAgICAgICBzY29wZXNGb3JFbmRwb2ludC5wdXNoKHNjb3BlKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gT25seSBhZGQgdG8gYWxsIHNjb3BlcyBpZiBzY29wZXMgZm9yIGVuZHBvaW50IGFuZCBtZXRob2QgaXMgZm91bmRcbiAgICAgIGlmIChzY29wZXNGb3JFbmRwb2ludC5sZW5ndGggPiAwKSB7XG4gICAgICAgIGFsbE1hdGNoZWRTY29wZXMucHVzaChzY29wZXNGb3JFbmRwb2ludCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoYWxsTWF0Y2hlZFNjb3Blcy5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAoYWxsTWF0Y2hlZFNjb3Blcy5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRoaXMuYXV0aFNlcnZpY2VcbiAgICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgICAud2FybmluZyhcbiAgICAgICAgICAgICdJbnRlcmNlcHRvciAtIE1vcmUgdGhhbiAxIG1hdGNoaW5nIHNjb3BlcyBmb3IgZW5kcG9pbnQgZm91bmQuJ1xuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgICAvLyBSZXR1cm5zIHNjb3BlcyBmb3IgZmlyc3QgbWF0Y2hpbmcgZW5kcG9pbnRcbiAgICAgIHJldHVybiBhbGxNYXRjaGVkU2NvcGVzWzBdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG4iXX0=
|