@dbx-tools/auth 0.9.32 → 0.9.37
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/README.md +49 -97
- package/index.ts +8 -26
- package/lib/index.d.ts +8 -26
- package/lib/index.js +6 -22
- package/lib/src/{databricks-cli.d.ts → _databricks-cli.d.ts} +3 -7
- package/lib/src/_databricks-cli.js +172 -0
- package/lib/src/_errors.d.ts +5 -0
- package/lib/src/_errors.js +10 -0
- package/lib/src/{lifecycle.d.ts → _lifecycle.d.ts} +5 -5
- package/lib/src/_lifecycle.js +214 -0
- package/lib/src/_logging.d.ts +1 -1
- package/lib/src/_logging.js +2 -2
- package/lib/src/{personal-access-token.d.ts → _personal-access-token.d.ts} +1 -1
- package/lib/src/_personal-access-token.js +30 -0
- package/lib/src/_profile-config.d.ts +43 -0
- package/lib/src/_profile-config.js +443 -0
- package/lib/src/{service-principal.d.ts → _service-principal.d.ts} +1 -1
- package/lib/src/_service-principal.js +69 -0
- package/lib/src/{storage.d.ts → _storage.d.ts} +2 -13
- package/lib/src/_storage.js +94 -0
- package/lib/src/_types.d.ts +40 -0
- package/lib/src/_types.js +2 -0
- package/lib/src/client.d.ts +30 -0
- package/lib/src/client.js +223 -0
- package/lib/src/config.d.ts +36 -0
- package/lib/src/config.js +15 -0
- package/lib/src/profile.d.ts +11 -0
- package/lib/src/profile.js +21 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +34 -10
- package/src/{databricks-cli.ts → _databricks-cli.ts} +20 -109
- package/src/_errors.ts +11 -0
- package/src/{lifecycle.ts → _lifecycle.ts} +12 -40
- package/src/_logging.ts +2 -2
- package/src/{personal-access-token.ts → _personal-access-token.ts} +1 -1
- package/src/_profile-config.ts +545 -0
- package/src/{service-principal.ts → _service-principal.ts} +2 -2
- package/src/{storage.ts → _storage.ts} +2 -31
- package/src/_types.ts +45 -0
- package/src/client.ts +291 -0
- package/src/config.ts +44 -0
- package/src/profile.ts +33 -0
- package/lib/exports.d.ts +0 -2
- package/lib/exports.js +0 -3
- package/lib/src/_profile-core.d.ts +0 -28
- package/lib/src/_profile-core.js +0 -216
- package/lib/src/_profile.d.ts +0 -15
- package/lib/src/_profile.js +0 -236
- package/lib/src/databricks-auth.d.ts +0 -11
- package/lib/src/databricks-auth.js +0 -314
- package/lib/src/databricks-cli.js +0 -239
- package/lib/src/errors.d.ts +0 -7
- package/lib/src/errors.js +0 -14
- package/lib/src/file-storage.d.ts +0 -20
- package/lib/src/file-storage.js +0 -207
- package/lib/src/generated/databricks-cli-assets.json +0 -33
- package/lib/src/http-client.d.ts +0 -23
- package/lib/src/http-client.js +0 -116
- package/lib/src/lifecycle.js +0 -233
- package/lib/src/personal-access-token.js +0 -30
- package/lib/src/service-principal.js +0 -69
- package/lib/src/storage.js +0 -112
- package/lib/src/types.d.ts +0 -165
- package/lib/src/types.js +0 -67
- package/src/_profile-core.ts +0 -258
- package/src/_profile.ts +0 -319
- package/src/databricks-auth.ts +0 -416
- package/src/errors.ts +0 -16
- package/src/file-storage.ts +0 -230
- package/src/generated/databricks-cli-assets.json +0 -33
- package/src/http-client.ts +0 -147
- package/src/types.ts +0 -196
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import * as environmentUtils from "@dbx-tools/shared-core/environment-utils";
|
|
4
|
-
import { authLogger, tokenMetadata } from "./_logging.js";
|
|
5
|
-
import { AuthError } from "./errors.js";
|
|
6
|
-
import { DatabricksCliProvider, resolveDatabricksCli } from "./databricks-cli.js";
|
|
7
|
-
import { publicToken, TokenLifecycle } from "./lifecycle.js";
|
|
8
|
-
import { FileCredentialStore } from "./file-storage.js";
|
|
9
|
-
import { DatabricksPersonalAccessTokenProvider } from "./personal-access-token.js";
|
|
10
|
-
import { listDatabricksProfiles, machineScopes, resolveConfigFile, resolveDatabricksProfile, } from "./_profile.js";
|
|
11
|
-
import { DatabricksServicePrincipalProvider } from "./service-principal.js";
|
|
12
|
-
import { MemoryCredentialStore } from "./storage.js";
|
|
13
|
-
import { AuthKind, AuthOptions, DEFAULT_ACCESS_TOKEN_HEADER, Storage, TargetKind, WORKSPACE_ID_HEADER, } from "./types.js";
|
|
14
|
-
const logger = authLogger("databricks");
|
|
15
|
-
/** Persistent Databricks auth facade over the provider-neutral lifecycle. */
|
|
16
|
-
class PersistentAuth {
|
|
17
|
-
profileValue;
|
|
18
|
-
storageValue;
|
|
19
|
-
options;
|
|
20
|
-
environment;
|
|
21
|
-
client;
|
|
22
|
-
requestToken;
|
|
23
|
-
constructor(profileValue, storageValue, options, environment, client, requestToken) {
|
|
24
|
-
this.profileValue = profileValue;
|
|
25
|
-
this.storageValue = storageValue;
|
|
26
|
-
this.options = options;
|
|
27
|
-
this.environment = environment;
|
|
28
|
-
this.client = client;
|
|
29
|
-
this.requestToken = requestToken;
|
|
30
|
-
}
|
|
31
|
-
async challenge() {
|
|
32
|
-
if (!this.client)
|
|
33
|
-
throw new AuthError("oauth", "app_obo uses the current request token and cannot start login");
|
|
34
|
-
logger.debug("authentication challenge requested", this.context());
|
|
35
|
-
await this.client.login();
|
|
36
|
-
logger.debug("authentication challenge completed", this.context());
|
|
37
|
-
}
|
|
38
|
-
token(login) {
|
|
39
|
-
logger.debug("Databricks token requested", {
|
|
40
|
-
...this.context(),
|
|
41
|
-
login: login ?? "auto",
|
|
42
|
-
source: this.requestToken ? "request" : "lifecycle",
|
|
43
|
-
});
|
|
44
|
-
return this.requestToken
|
|
45
|
-
? Promise.resolve(publicToken(this.requestToken))
|
|
46
|
-
: this.requiredClient().tokenWithLogin(login);
|
|
47
|
-
}
|
|
48
|
-
async authenticate(login) {
|
|
49
|
-
const token = await this.token(login);
|
|
50
|
-
const headers = {
|
|
51
|
-
[DEFAULT_ACCESS_TOKEN_HEADER]: `${token.tokenType} ${token.accessToken}`,
|
|
52
|
-
...(this.profileValue.workspaceId
|
|
53
|
-
? { [WORKSPACE_ID_HEADER]: this.profileValue.workspaceId }
|
|
54
|
-
: {}),
|
|
55
|
-
};
|
|
56
|
-
logger.debug("generated Databricks authentication headers", {
|
|
57
|
-
...this.context(),
|
|
58
|
-
headerNames: Object.keys(headers),
|
|
59
|
-
token: tokenMetadata(token),
|
|
60
|
-
});
|
|
61
|
-
return headers;
|
|
62
|
-
}
|
|
63
|
-
async authorizationHeaderForUrl(requestUrl, login) {
|
|
64
|
-
return (await this.requestHeadersForUrl(requestUrl, login))[DEFAULT_ACCESS_TOKEN_HEADER];
|
|
65
|
-
}
|
|
66
|
-
async requestHeadersForUrl(requestUrl, login) {
|
|
67
|
-
const request = new URL(requestUrl);
|
|
68
|
-
const credentialOrigin = new URL(this.profileValue.host).origin;
|
|
69
|
-
if (request.origin !== credentialOrigin) {
|
|
70
|
-
logger.debug("skipped authentication for different origin", {
|
|
71
|
-
...this.context(),
|
|
72
|
-
requestOrigin: request.origin,
|
|
73
|
-
credentialOrigin,
|
|
74
|
-
});
|
|
75
|
-
return {};
|
|
76
|
-
}
|
|
77
|
-
logger.debug("applying authentication to matching origin", {
|
|
78
|
-
...this.context(),
|
|
79
|
-
requestOrigin: request.origin,
|
|
80
|
-
});
|
|
81
|
-
return this.authenticate(login);
|
|
82
|
-
}
|
|
83
|
-
forceRefreshToken(login = true) {
|
|
84
|
-
logger.debug("Databricks token force refresh requested", { ...this.context(), login });
|
|
85
|
-
return this.requestToken
|
|
86
|
-
? Promise.resolve(publicToken(this.requestToken))
|
|
87
|
-
: this.requiredClient().forceRefresh(login);
|
|
88
|
-
}
|
|
89
|
-
refreshRejectedToken(staleAccessToken, login = true) {
|
|
90
|
-
logger.debug("Databricks rejected token refresh requested", {
|
|
91
|
-
...this.context(),
|
|
92
|
-
login,
|
|
93
|
-
requestToken: Boolean(this.requestToken),
|
|
94
|
-
});
|
|
95
|
-
return this.requestToken
|
|
96
|
-
? Promise.resolve(publicToken(this.requestToken))
|
|
97
|
-
: this.requiredClient().refreshRejectedToken(staleAccessToken, login);
|
|
98
|
-
}
|
|
99
|
-
logout() {
|
|
100
|
-
logger.debug("Databricks logout requested", this.context());
|
|
101
|
-
return this.client?.logout() ?? Promise.resolve();
|
|
102
|
-
}
|
|
103
|
-
status() {
|
|
104
|
-
return {
|
|
105
|
-
profile: this.profileValue.name,
|
|
106
|
-
host: this.profileValue.host,
|
|
107
|
-
storage: this.storageValue,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
principal() {
|
|
111
|
-
return this.profileValue.principal;
|
|
112
|
-
}
|
|
113
|
-
workspaceId() {
|
|
114
|
-
return this.profileValue.workspaceId;
|
|
115
|
-
}
|
|
116
|
-
authKind() {
|
|
117
|
-
return this.profileValue.authKind;
|
|
118
|
-
}
|
|
119
|
-
profile(name) {
|
|
120
|
-
const profile = !name || name === this.profileValue.name
|
|
121
|
-
? this.profileValue
|
|
122
|
-
: resolveDatabricksProfile({ ...this.options, profile: name }, this.environment);
|
|
123
|
-
return profileSummary(profile);
|
|
124
|
-
}
|
|
125
|
-
listProfiles(refresh = false) {
|
|
126
|
-
return listDatabricksProfiles(this.options.configFile, refresh, this.environment);
|
|
127
|
-
}
|
|
128
|
-
requiredClient() {
|
|
129
|
-
if (!this.client)
|
|
130
|
-
throw new AuthError("oauth", "Authentication lifecycle is not available");
|
|
131
|
-
return this.client;
|
|
132
|
-
}
|
|
133
|
-
context() {
|
|
134
|
-
return {
|
|
135
|
-
profile: this.profileValue.name,
|
|
136
|
-
host: this.profileValue.host,
|
|
137
|
-
authKind: this.profileValue.authKind,
|
|
138
|
-
storage: this.storageValue,
|
|
139
|
-
hasWorkspaceId: Boolean(this.profileValue.workspaceId),
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/** Create a Databricks authentication client. */
|
|
144
|
-
export function createAuthClient(options = { preferUserToMachine: true }, storage = Storage.Auto, dependencies = {}) {
|
|
145
|
-
return createPersistentAuth(options, storage, dependencies);
|
|
146
|
-
}
|
|
147
|
-
/** Resolve a Databricks profile and open built-in credential storage. */
|
|
148
|
-
async function createPersistentAuth(options, storage, dependencies) {
|
|
149
|
-
const environment = dependencies.environment ?? process.env;
|
|
150
|
-
const profile = resolveDatabricksProfile(options, environment);
|
|
151
|
-
const inApp = profile.authKind === AuthKind.AppOnBehalfOf ||
|
|
152
|
-
profile.authKind === AuthKind.AppServicePrincipal;
|
|
153
|
-
const backend = storage === Storage.Auto ? Storage.Memory : storage;
|
|
154
|
-
logger.debug("creating persistent Databricks auth", {
|
|
155
|
-
profile: profile.name,
|
|
156
|
-
host: profile.host,
|
|
157
|
-
authKind: profile.authKind,
|
|
158
|
-
requestedStorage: storage,
|
|
159
|
-
resolvedStorage: backend,
|
|
160
|
-
inApp,
|
|
161
|
-
});
|
|
162
|
-
const store = backend === Storage.Memory
|
|
163
|
-
? new MemoryCredentialStore()
|
|
164
|
-
: new FileCredentialStore(options.cacheDir ?? join(homedir(), ".databricks"));
|
|
165
|
-
return createPersistentAuthWithStorage(options, store, storage, dependencies, profile);
|
|
166
|
-
}
|
|
167
|
-
/** Resolve a Databricks profile using caller-owned generic storage. */
|
|
168
|
-
async function createPersistentAuthWithStorage(options, store, storage = store.name() === "memory" ? Storage.Memory : Storage.File, dependencies = {}, resolvedProfile) {
|
|
169
|
-
const profile = resolvedProfile ?? resolveDatabricksProfile(options, dependencies.environment ?? process.env);
|
|
170
|
-
if (profile.authKind === AuthKind.AppOnBehalfOf) {
|
|
171
|
-
logger.debug("created request-scoped App OBO authentication", {
|
|
172
|
-
profile: profile.name,
|
|
173
|
-
host: profile.host,
|
|
174
|
-
hasWorkspaceId: Boolean(profile.workspaceId),
|
|
175
|
-
});
|
|
176
|
-
return new PersistentAuth(profile, Storage.Memory, options, dependencies.environment ?? process.env, undefined, {
|
|
177
|
-
accessToken: profile.accessToken,
|
|
178
|
-
tokenType: "Bearer",
|
|
179
|
-
scopes: [...profile.scopes],
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
const provider = await providerFor(profile, options, dependencies);
|
|
183
|
-
const client = new TokenLifecycle(profile.cacheKey, provider, store, AuthOptions.create(options.auth));
|
|
184
|
-
const persistent = new PersistentAuth(profile, storage === Storage.Auto ? storageFromName(store.name()) : storage, options, dependencies.environment ?? process.env, client);
|
|
185
|
-
logger.debug("created persistent authentication lifecycle", {
|
|
186
|
-
profile: profile.name,
|
|
187
|
-
host: profile.host,
|
|
188
|
-
authKind: profile.authKind,
|
|
189
|
-
storage: persistent.status().storage,
|
|
190
|
-
});
|
|
191
|
-
return persistent;
|
|
192
|
-
}
|
|
193
|
-
async function providerFor(profile, options, dependencies) {
|
|
194
|
-
const environment = dependencies.environment ?? process.env;
|
|
195
|
-
const inApp = environmentUtils.isDatabricksAppEnv({ ...environment });
|
|
196
|
-
switch (profile.authKind) {
|
|
197
|
-
case AuthKind.UserToMachine: {
|
|
198
|
-
const install = !inApp || options.installCliInApp === true;
|
|
199
|
-
logger.debug("selected Databricks CLI provider", {
|
|
200
|
-
profile: profile.name,
|
|
201
|
-
inApp,
|
|
202
|
-
install,
|
|
203
|
-
});
|
|
204
|
-
return new DatabricksCliProvider(profile.name, () => dependencies.resolveCli
|
|
205
|
-
? dependencies.resolveCli({ install })
|
|
206
|
-
: resolveDatabricksCli(environment, { install }), cliEnvironment(profile, resolveConfigFile(options.configFile, environment)));
|
|
207
|
-
}
|
|
208
|
-
case AuthKind.PersonalAccessToken:
|
|
209
|
-
logger.debug("selected personal access token provider", { profile: profile.name });
|
|
210
|
-
return new DatabricksPersonalAccessTokenProvider(profile.accessToken);
|
|
211
|
-
case AuthKind.MachineToMachine:
|
|
212
|
-
case AuthKind.AppServicePrincipal: {
|
|
213
|
-
logger.debug("selected service-principal provider", {
|
|
214
|
-
profile: profile.name,
|
|
215
|
-
authKind: profile.authKind,
|
|
216
|
-
target: profile.target,
|
|
217
|
-
});
|
|
218
|
-
const endpoints = await resolveOAuthEndpoints(profile, dependencies.fetch);
|
|
219
|
-
return new DatabricksServicePrincipalProvider({
|
|
220
|
-
tokenEndpoint: endpoints.tokenEndpoint,
|
|
221
|
-
clientId: profile.clientId,
|
|
222
|
-
clientSecret: profile.clientSecret,
|
|
223
|
-
scopes: machineScopes(profile.scopes),
|
|
224
|
-
...(profile.groupId ? { groupId: profile.groupId } : {}),
|
|
225
|
-
allowInsecureRequests: isLoopbackHttp(profile.host),
|
|
226
|
-
fetch: dependencies.fetch,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
case AuthKind.AppOnBehalfOf:
|
|
230
|
-
throw new AuthError("config", "App OBO tokens do not use a persistent provider");
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
async function resolveOAuthEndpoints(profile, fetcher = globalThis.fetch) {
|
|
234
|
-
const host = profile.host.replace(/\/$/, "");
|
|
235
|
-
if (profile.target === TargetKind.Account) {
|
|
236
|
-
if (!profile.accountId)
|
|
237
|
-
throw new AuthError("config", "Account target requires account_id");
|
|
238
|
-
const endpoints = {
|
|
239
|
-
tokenEndpoint: `${host}/oidc/accounts/${profile.accountId}/v1/token`,
|
|
240
|
-
};
|
|
241
|
-
logger.debug("resolved account OAuth endpoint", {
|
|
242
|
-
profile: profile.name,
|
|
243
|
-
tokenOrigin: new URL(endpoints.tokenEndpoint).origin,
|
|
244
|
-
});
|
|
245
|
-
return endpoints;
|
|
246
|
-
}
|
|
247
|
-
const discovery = profile.target === TargetKind.Unified
|
|
248
|
-
? `${host}/oidc/accounts/${requiredAccountId(profile)}/.well-known/oauth-authorization-server`
|
|
249
|
-
: `${host}/oidc/.well-known/oauth-authorization-server`;
|
|
250
|
-
logger.debug("requesting OAuth discovery", {
|
|
251
|
-
profile: profile.name,
|
|
252
|
-
target: profile.target,
|
|
253
|
-
discovery,
|
|
254
|
-
});
|
|
255
|
-
const response = await fetcher(discovery, { redirect: "manual" });
|
|
256
|
-
logger.debug("received OAuth discovery response", {
|
|
257
|
-
profile: profile.name,
|
|
258
|
-
status: response.status,
|
|
259
|
-
});
|
|
260
|
-
if (response.status === 404)
|
|
261
|
-
throw new AuthError("oauth", `OAuth is not supported at ${discovery}`);
|
|
262
|
-
if (!response.ok)
|
|
263
|
-
throw new AuthError("oauth", `OAuth discovery returned HTTP ${response.status}`);
|
|
264
|
-
const value = (await response.json());
|
|
265
|
-
const tokenEndpoint = stringValue(value.token_endpoint);
|
|
266
|
-
if (!tokenEndpoint)
|
|
267
|
-
throw new AuthError("oauth", "OAuth discovery response is incomplete");
|
|
268
|
-
logger.debug("resolved OAuth token endpoint", {
|
|
269
|
-
profile: profile.name,
|
|
270
|
-
tokenOrigin: new URL(tokenEndpoint).origin,
|
|
271
|
-
});
|
|
272
|
-
return { tokenEndpoint };
|
|
273
|
-
}
|
|
274
|
-
function requiredAccountId(profile) {
|
|
275
|
-
if (!profile.accountId)
|
|
276
|
-
throw new AuthError("config", "Unified target requires account_id");
|
|
277
|
-
return profile.accountId;
|
|
278
|
-
}
|
|
279
|
-
function storageFromName(name) {
|
|
280
|
-
return name === "memory" ? Storage.Memory : Storage.File;
|
|
281
|
-
}
|
|
282
|
-
function profileSummary(profile) {
|
|
283
|
-
return {
|
|
284
|
-
name: profile.name,
|
|
285
|
-
host: profile.host,
|
|
286
|
-
...(profile.accountId ? { accountId: profile.accountId } : {}),
|
|
287
|
-
...(profile.workspaceId ? { workspaceId: profile.workspaceId } : {}),
|
|
288
|
-
target: profile.target,
|
|
289
|
-
authKind: profile.authKind,
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
function isLoopbackHttp(host) {
|
|
293
|
-
const url = new URL(host);
|
|
294
|
-
return url.protocol === "http:" && ["127.0.0.1", "localhost"].includes(url.hostname);
|
|
295
|
-
}
|
|
296
|
-
function cliEnvironment(profile, configFile) {
|
|
297
|
-
return {
|
|
298
|
-
DATABRICKS_CONFIG_FILE: configFile,
|
|
299
|
-
DATABRICKS_CONFIG_PROFILE: profile.name,
|
|
300
|
-
DATABRICKS_HOST: profile.host,
|
|
301
|
-
...(profile.accountId ? { DATABRICKS_ACCOUNT_ID: profile.accountId } : {}),
|
|
302
|
-
...(profile.workspaceId ? { DATABRICKS_WORKSPACE_ID: profile.workspaceId } : {}),
|
|
303
|
-
...(profile.authKind === AuthKind.PersonalAccessToken
|
|
304
|
-
? {
|
|
305
|
-
DATABRICKS_AUTH_TYPE: "pat",
|
|
306
|
-
DATABRICKS_TOKEN: profile.accessToken,
|
|
307
|
-
}
|
|
308
|
-
: {}),
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
function stringValue(value) {
|
|
312
|
-
return typeof value === "string" && value.trim() ? value : undefined;
|
|
313
|
-
}
|
|
314
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJyaWNrcy1hdXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RhdGFicmlja3MtYXV0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFakMsT0FBTyxLQUFLLGdCQUFnQixNQUFNLDBDQUEwQyxDQUFDO0FBRTdFLE9BQU8sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLG9CQUFvQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUscUNBQXFDLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNuRixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLGFBQWEsRUFDYixpQkFBaUIsRUFDakIsd0JBQXdCLEdBQ3pCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQ0FBa0MsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNyRCxPQUFPLEVBQ0wsUUFBUSxFQUVSLFdBQVcsRUFLWCwyQkFBMkIsRUFDM0IsT0FBTyxFQUNQLFVBQVUsRUFHVixtQkFBbUIsR0FDcEIsTUFBTSxZQUFZLENBQUM7QUFFcEIsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBU3hDLDZFQUE2RTtBQUM3RSxNQUFNLGNBQWM7SUFFQztJQUNBO0lBQ0E7SUFDQTtJQUNB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dkMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1FBQzdCLEdBQUcsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLHVCQUF1QixFQUFFLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2hGLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxtQkFBbUI7WUFDbkQsQ0FBQyxDQUFDO2dCQUNFLG9CQUFvQixFQUFFLEtBQUs7Z0JBQzNCLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxXQUFZO2FBQ3ZDO1lBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUNSLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsS0FBYztJQUNqQyxPQUFPLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3ZFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBob21lZGlyIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5cbmltcG9ydCAqIGFzIGVudmlyb25tZW50VXRpbHMgZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmUvZW52aXJvbm1lbnQtdXRpbHNcIjtcblxuaW1wb3J0IHsgYXV0aExvZ2dlciwgdG9rZW5NZXRhZGF0YSB9IGZyb20gXCIuL19sb2dnaW5nLnRzXCI7XG5pbXBvcnQgeyBBdXRoRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnMudHNcIjtcbmltcG9ydCB7IERhdGFicmlja3NDbGlQcm92aWRlciwgcmVzb2x2ZURhdGFicmlja3NDbGkgfSBmcm9tIFwiLi9kYXRhYnJpY2tzLWNsaS50c1wiO1xuaW1wb3J0IHsgcHVibGljVG9rZW4sIFRva2VuTGlmZWN5Y2xlIH0gZnJvbSBcIi4vbGlmZWN5Y2xlLnRzXCI7XG5pbXBvcnQgeyBGaWxlQ3JlZGVudGlhbFN0b3JlIH0gZnJvbSBcIi4vZmlsZS1zdG9yYWdlLnRzXCI7XG5pbXBvcnQgeyBEYXRhYnJpY2tzUGVyc29uYWxBY2Nlc3NUb2tlblByb3ZpZGVyIH0gZnJvbSBcIi4vcGVyc29uYWwtYWNjZXNzLXRva2VuLnRzXCI7XG5pbXBvcnQge1xuICBsaXN0RGF0YWJyaWNrc1Byb2ZpbGVzLFxuICBtYWNoaW5lU2NvcGVzLFxuICByZXNvbHZlQ29uZmlnRmlsZSxcbiAgcmVzb2x2ZURhdGFicmlja3NQcm9maWxlLFxufSBmcm9tIFwiLi9fcHJvZmlsZS50c1wiO1xuaW1wb3J0IHsgRGF0YWJyaWNrc1NlcnZpY2VQcmluY2lwYWxQcm92aWRlciB9IGZyb20gXCIuL3NlcnZpY2UtcHJpbmNpcGFsLnRzXCI7XG5pbXBvcnQgeyBNZW1vcnlDcmVkZW50aWFsU3RvcmUgfSBmcm9tIFwiLi9zdG9yYWdlLnRzXCI7XG5pbXBvcnQge1xuICBBdXRoS2luZCxcbiAgdHlwZSBBdXRoQ2xpZW50LFxuICBBdXRoT3B0aW9ucyxcbiAgdHlwZSBDcmVkZW50aWFsU3RvcmUsXG4gIHR5cGUgRGF0YWJyaWNrc0F1dGhPcHRpb25zLFxuICB0eXBlIERhdGFicmlja3NBdXRoU3RhdHVzLFxuICB0eXBlIERhdGFicmlja3NQcm9maWxlLFxuICBERUZBVUxUX0FDQ0VTU19UT0tFTl9IRUFERVIsXG4gIFN0b3JhZ2UsXG4gIFRhcmdldEtpbmQsXG4gIHR5cGUgVG9rZW4sXG4gIHR5cGUgVG9rZW5Qcm92aWRlcixcbiAgV09SS1NQQUNFX0lEX0hFQURFUixcbn0gZnJvbSBcIi4vdHlwZXMudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gYXV0aExvZ2dlcihcImRhdGFicmlja3NcIik7XG5cbi8qKiBJbmplY3RhYmxlIGhvc3QgY2FwYWJpbGl0aWVzIGZvciBEYXRhYnJpY2tzIGF1dGhlbnRpY2F0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhYnJpY2tzQXV0aERlcGVuZGVuY2llcyB7XG4gIGVudmlyb25tZW50PzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPj47XG4gIGZldGNoPzogdHlwZW9mIGdsb2JhbFRoaXMuZmV0Y2g7XG4gIHJlc29sdmVDbGk/OiAob3B0aW9uczogeyBpbnN0YWxsOiBib29sZWFuIH0pID0+IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPjtcbn1cblxuLyoqIFBlcnNpc3RlbnQgRGF0YWJyaWNrcyBhdXRoIGZhY2FkZSBvdmVyIHRoZSBwcm92aWRlci1uZXV0cmFsIGxpZmVjeWNsZS4gKi9cbmNsYXNzIFBlcnNpc3RlbnRBdXRoIGltcGxlbWVudHMgQXV0aENsaWVudCB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvZmlsZVZhbHVlOiBEYXRhYnJpY2tzUHJvZmlsZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHN0b3JhZ2VWYWx1ZTogU3RvcmFnZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IERhdGFicmlja3NBdXRoT3B0aW9ucyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGVudmlyb25tZW50OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNsaWVudD86IFRva2VuTGlmZWN5Y2xlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVxdWVzdFRva2VuPzogVG9rZW4sXG4gICkge31cblxuICBhc3luYyBjaGFsbGVuZ2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmNsaWVudClcbiAgICAgIHRocm93IG5ldyBBdXRoRXJyb3IoXCJvYXV0aFwiLCBcImFwcF9vYm8gdXNlcyB0aGUgY3VycmVudCByZXF1ZXN0IHRva2VuIGFuZCBjYW5ub3Qgc3RhcnQgbG9naW5cIik7XG4gICAgbG9nZ2VyLmRlYnVnKFwiYXV0aGVudGljYXRpb24gY2hhbGxlbmdlIHJlcXVlc3RlZFwiLCB0aGlzLmNvbnRleHQoKSk7XG4gICAgYXdhaXQgdGhpcy5jbGllbnQubG9naW4oKTtcbiAgICBsb2dnZXIuZGVidWcoXCJhdXRoZW50aWNhdGlvbiBjaGFsbGVuZ2UgY29tcGxldGVkXCIsIHRoaXMuY29udGV4dCgpKTtcbiAgfVxuXG4gIHRva2VuKGxvZ2luPzogYm9vbGVhbikge1xuICAgIGxvZ2dlci5kZWJ1ZyhcIkRhdGFicmlja3MgdG9rZW4gcmVxdWVzdGVkXCIsIHtcbiAgICAgIC4uLnRoaXMuY29udGV4dCgpLFxuICAgICAgbG9naW46IGxvZ2luID8/IFwiYXV0b1wiLFxuICAgICAgc291cmNlOiB0aGlzLnJlcXVlc3RUb2tlbiA/IFwicmVxdWVzdFwiIDogXCJsaWZlY3ljbGVcIixcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0VG9rZW5cbiAgICAgID8gUHJvbWlzZS5yZXNvbHZlKHB1YmxpY1Rva2VuKHRoaXMucmVxdWVzdFRva2VuKSlcbiAgICAgIDogdGhpcy5yZXF1aXJlZENsaWVudCgpLnRva2VuV2l0aExvZ2luKGxvZ2luKTtcbiAgfVxuXG4gIGFzeW5jIGF1dGhlbnRpY2F0ZShsb2dpbj86IGJvb2xlYW4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgICBjb25zdCB0b2tlbiA9IGF3YWl0IHRoaXMudG9rZW4obG9naW4pO1xuICAgIGNvbnN0IGhlYWRlcnMgPSB7XG4gICAgICBbREVGQVVMVF9BQ0NFU1NfVE9LRU5fSEVBREVSXTogYCR7dG9rZW4udG9rZW5UeXBlfSAke3Rva2VuLmFjY2Vzc1Rva2VufWAsXG4gICAgICAuLi4odGhpcy5wcm9maWxlVmFsdWUud29ya3NwYWNlSWRcbiAgICAgICAgPyB7IFtXT1JLU1BBQ0VfSURfSEVBREVSXTogdGhpcy5wcm9maWxlVmFsdWUud29ya3NwYWNlSWQgfVxuICAgICAgICA6IHt9KSxcbiAgICB9O1xuICAgIGxvZ2dlci5kZWJ1ZyhcImdlbmVyYXRlZCBEYXRhYnJpY2tzIGF1dGhlbnRpY2F0aW9uIGhlYWRlcnNcIiwge1xuICAgICAgLi4udGhpcy5jb250ZXh0KCksXG4gICAgICBoZWFkZXJOYW1lczogT2JqZWN0LmtleXMoaGVhZGVycyksXG4gICAgICB0b2tlbjogdG9rZW5NZXRhZGF0YSh0b2tlbiksXG4gICAgfSk7XG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cblxuICBhc3luYyBhdXRob3JpemF0aW9uSGVhZGVyRm9yVXJsKFxuICAgIHJlcXVlc3RVcmw6IHN0cmluZyxcbiAgICBsb2dpbj86IGJvb2xlYW4sXG4gICk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLnJlcXVlc3RIZWFkZXJzRm9yVXJsKHJlcXVlc3RVcmwsIGxvZ2luKSlbREVGQVVMVF9BQ0NFU1NfVE9LRU5fSEVBREVSXTtcbiAgfVxuXG4gIGFzeW5jIHJlcXVlc3RIZWFkZXJzRm9yVXJsKHJlcXVlc3RVcmw6IHN0cmluZywgbG9naW4/OiBib29sZWFuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IG5ldyBVUkwocmVxdWVzdFVybCk7XG4gICAgY29uc3QgY3JlZGVudGlhbE9yaWdpbiA9IG5ldyBVUkwodGhpcy5wcm9maWxlVmFsdWUuaG9zdCkub3JpZ2luO1xuICAgIGlmIChyZXF1ZXN0Lm9yaWdpbiAhPT0gY3JlZGVudGlhbE9yaWdpbikge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwic2tpcHBlZCBhdXRoZW50aWNhdGlvbiBmb3IgZGlmZmVyZW50IG9yaWdpblwiLCB7XG4gICAgICAgIC4uLnRoaXMuY29udGV4dCgpLFxuICAgICAgICByZXF1ZXN0T3JpZ2luOiByZXF1ZXN0Lm9yaWdpbixcbiAgICAgICAgY3JlZGVudGlhbE9yaWdpbixcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBsb2dnZXIuZGVidWcoXCJhcHBseWluZyBhdXRoZW50aWNhdGlvbiB0byBtYXRjaGluZyBvcmlnaW5cIiwge1xuICAgICAgLi4udGhpcy5jb250ZXh0KCksXG4gICAgICByZXF1ZXN0T3JpZ2luOiByZXF1ZXN0Lm9yaWdpbixcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5hdXRoZW50aWNhdGUobG9naW4pO1xuICB9XG5cbiAgZm9yY2VSZWZyZXNoVG9rZW4obG9naW4gPSB0cnVlKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiRGF0YWJyaWNrcyB0b2tlbiBmb3JjZSByZWZyZXNoIHJlcXVlc3RlZFwiLCB7IC4uLnRoaXMuY29udGV4dCgpLCBsb2dpbiB9KTtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0VG9rZW5cbiAgICAgID8gUHJvbWlzZS5yZXNvbHZlKHB1YmxpY1Rva2VuKHRoaXMucmVxdWVzdFRva2VuKSlcbiAgICAgIDogdGhpcy5yZXF1aXJlZENsaWVudCgpLmZvcmNlUmVmcmVzaChsb2dpbik7XG4gIH1cblxuICByZWZyZXNoUmVqZWN0ZWRUb2tlbihzdGFsZUFjY2Vzc1Rva2VuOiBzdHJpbmcsIGxvZ2luID0gdHJ1ZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcIkRhdGFicmlja3MgcmVqZWN0ZWQgdG9rZW4gcmVmcmVzaCByZXF1ZXN0ZWRcIiwge1xuICAgICAgLi4udGhpcy5jb250ZXh0KCksXG4gICAgICBsb2dpbixcbiAgICAgIHJlcXVlc3RUb2tlbjogQm9vbGVhbih0aGlzLnJlcXVlc3RUb2tlbiksXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdFRva2VuXG4gICAgICA/IFByb21pc2UucmVzb2x2ZShwdWJsaWNUb2tlbih0aGlzLnJlcXVlc3RUb2tlbikpXG4gICAgICA6IHRoaXMucmVxdWlyZWRDbGllbnQoKS5yZWZyZXNoUmVqZWN0ZWRUb2tlbihzdGFsZUFjY2Vzc1Rva2VuLCBsb2dpbik7XG4gIH1cblxuICBsb2dvdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiRGF0YWJyaWNrcyBsb2dvdXQgcmVxdWVzdGVkXCIsIHRoaXMuY29udGV4dCgpKTtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQ/LmxvZ291dCgpID8/IFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgc3RhdHVzKCk6IERhdGFicmlja3NBdXRoU3RhdHVzIHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvZmlsZTogdGhpcy5wcm9maWxlVmFsdWUubmFtZSxcbiAgICAgIGhvc3Q6IHRoaXMucHJvZmlsZVZhbHVlLmhvc3QsXG4gICAgICBzdG9yYWdlOiB0aGlzLnN0b3JhZ2VWYWx1ZSxcbiAgICB9O1xuICB9XG5cbiAgcHJpbmNpcGFsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucHJvZmlsZVZhbHVlLnByaW5jaXBhbDtcbiAgfVxuXG4gIHdvcmtzcGFjZUlkKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucHJvZmlsZVZhbHVlLndvcmtzcGFjZUlkO1xuICB9XG5cbiAgYXV0aEtpbmQoKTogQXV0aEtpbmQge1xuICAgIHJldHVybiB0aGlzLnByb2ZpbGVWYWx1ZS5hdXRoS2luZDtcbiAgfVxuXG4gIHByb2ZpbGUobmFtZT86IHN0cmluZykge1xuICAgIGNvbnN0IHByb2ZpbGUgPVxuICAgICAgIW5hbWUgfHwgbmFtZSA9PT0gdGhpcy5wcm9maWxlVmFsdWUubmFtZVxuICAgICAgICA/IHRoaXMucHJvZmlsZVZhbHVlXG4gICAgICAgIDogcmVzb2x2ZURhdGFicmlja3NQcm9maWxlKHsgLi4udGhpcy5vcHRpb25zLCBwcm9maWxlOiBuYW1lIH0sIHRoaXMuZW52aXJvbm1lbnQpO1xuICAgIHJldHVybiBwcm9maWxlU3VtbWFyeShwcm9maWxlKTtcbiAgfVxuXG4gIGxpc3RQcm9maWxlcyhyZWZyZXNoID0gZmFsc2UpIHtcbiAgICByZXR1cm4gbGlzdERhdGFicmlja3NQcm9maWxlcyh0aGlzLm9wdGlvbnMuY29uZmlnRmlsZSwgcmVmcmVzaCwgdGhpcy5lbnZpcm9ubWVudCk7XG4gIH1cblxuICBwcml2YXRlIHJlcXVpcmVkQ2xpZW50KCk6IFRva2VuTGlmZWN5Y2xlIHtcbiAgICBpZiAoIXRoaXMuY2xpZW50KSB0aHJvdyBuZXcgQXV0aEVycm9yKFwib2F1dGhcIiwgXCJBdXRoZW50aWNhdGlvbiBsaWZlY3ljbGUgaXMgbm90IGF2YWlsYWJsZVwiKTtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQ7XG4gIH1cblxuICBwcml2YXRlIGNvbnRleHQoKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIHJldHVybiB7XG4gICAgICBwcm9maWxlOiB0aGlzLnByb2ZpbGVWYWx1ZS5uYW1lLFxuICAgICAgaG9zdDogdGhpcy5wcm9maWxlVmFsdWUuaG9zdCxcbiAgICAgIGF1dGhLaW5kOiB0aGlzLnByb2ZpbGVWYWx1ZS5hdXRoS2luZCxcbiAgICAgIHN0b3JhZ2U6IHRoaXMuc3RvcmFnZVZhbHVlLFxuICAgICAgaGFzV29ya3NwYWNlSWQ6IEJvb2xlYW4odGhpcy5wcm9maWxlVmFsdWUud29ya3NwYWNlSWQpLFxuICAgIH07XG4gIH1cbn1cblxuLyoqIENyZWF0ZSBhIERhdGFicmlja3MgYXV0aGVudGljYXRpb24gY2xpZW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUF1dGhDbGllbnQoXG4gIG9wdGlvbnM6IERhdGFicmlja3NBdXRoT3B0aW9ucyA9IHsgcHJlZmVyVXNlclRvTWFjaGluZTogdHJ1ZSB9LFxuICBzdG9yYWdlID0gU3RvcmFnZS5BdXRvLFxuICBkZXBlbmRlbmNpZXM6IERhdGFicmlja3NBdXRoRGVwZW5kZW5jaWVzID0ge30sXG4pOiBQcm9taXNlPEF1dGhDbGllbnQ+IHtcbiAgcmV0dXJuIGNyZWF0ZVBlcnNpc3RlbnRBdXRoKG9wdGlvbnMsIHN0b3JhZ2UsIGRlcGVuZGVuY2llcyk7XG59XG5cbi8qKiBSZXNvbHZlIGEgRGF0YWJyaWNrcyBwcm9maWxlIGFuZCBvcGVuIGJ1aWx0LWluIGNyZWRlbnRpYWwgc3RvcmFnZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVBlcnNpc3RlbnRBdXRoKFxuICBvcHRpb25zOiBEYXRhYnJpY2tzQXV0aE9wdGlvbnMsXG4gIHN0b3JhZ2U6IFN0b3JhZ2UsXG4gIGRlcGVuZGVuY2llczogRGF0YWJyaWNrc0F1dGhEZXBlbmRlbmNpZXMsXG4pOiBQcm9taXNlPFBlcnNpc3RlbnRBdXRoPiB7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gZGVwZW5kZW5jaWVzLmVudmlyb25tZW50ID8/IHByb2Nlc3MuZW52O1xuICBjb25zdCBwcm9maWxlID0gcmVzb2x2ZURhdGFicmlja3NQcm9maWxlKG9wdGlvbnMsIGVudmlyb25tZW50KTtcbiAgY29uc3QgaW5BcHAgPVxuICAgIHByb2ZpbGUuYXV0aEtpbmQgPT09IEF1dGhLaW5kLkFwcE9uQmVoYWxmT2YgfHxcbiAgICBwcm9maWxlLmF1dGhLaW5kID09PSBBdXRoS2luZC5BcHBTZXJ2aWNlUHJpbmNpcGFsO1xuICBjb25zdCBiYWNrZW5kID0gc3RvcmFnZSA9PT0gU3RvcmFnZS5BdXRvID8gU3RvcmFnZS5NZW1vcnkgOiBzdG9yYWdlO1xuICBsb2dnZXIuZGVidWcoXCJjcmVhdGluZyBwZXJzaXN0ZW50IERhdGFicmlja3MgYXV0aFwiLCB7XG4gICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgIGhvc3Q6IHByb2ZpbGUuaG9zdCxcbiAgICBhdXRoS2luZDogcHJvZmlsZS5hdXRoS2luZCxcbiAgICByZXF1ZXN0ZWRTdG9yYWdlOiBzdG9yYWdlLFxuICAgIHJlc29sdmVkU3RvcmFnZTogYmFja2VuZCxcbiAgICBpbkFwcCxcbiAgfSk7XG4gIGNvbnN0IHN0b3JlID1cbiAgICBiYWNrZW5kID09PSBTdG9yYWdlLk1lbW9yeVxuICAgICAgPyBuZXcgTWVtb3J5Q3JlZGVudGlhbFN0b3JlKClcbiAgICAgIDogbmV3IEZpbGVDcmVkZW50aWFsU3RvcmUob3B0aW9ucy5jYWNoZURpciA/PyBqb2luKGhvbWVkaXIoKSwgXCIuZGF0YWJyaWNrc1wiKSk7XG4gIHJldHVybiBjcmVhdGVQZXJzaXN0ZW50QXV0aFdpdGhTdG9yYWdlKG9wdGlvbnMsIHN0b3JlLCBzdG9yYWdlLCBkZXBlbmRlbmNpZXMsIHByb2ZpbGUpO1xufVxuXG4vKiogUmVzb2x2ZSBhIERhdGFicmlja3MgcHJvZmlsZSB1c2luZyBjYWxsZXItb3duZWQgZ2VuZXJpYyBzdG9yYWdlLiAqL1xuYXN5bmMgZnVuY3Rpb24gY3JlYXRlUGVyc2lzdGVudEF1dGhXaXRoU3RvcmFnZShcbiAgb3B0aW9uczogRGF0YWJyaWNrc0F1dGhPcHRpb25zLFxuICBzdG9yZTogQ3JlZGVudGlhbFN0b3JlLFxuICBzdG9yYWdlID0gc3RvcmUubmFtZSgpID09PSBcIm1lbW9yeVwiID8gU3RvcmFnZS5NZW1vcnkgOiBTdG9yYWdlLkZpbGUsXG4gIGRlcGVuZGVuY2llczogRGF0YWJyaWNrc0F1dGhEZXBlbmRlbmNpZXMgPSB7fSxcbiAgcmVzb2x2ZWRQcm9maWxlPzogRGF0YWJyaWNrc1Byb2ZpbGUsXG4pOiBQcm9taXNlPFBlcnNpc3RlbnRBdXRoPiB7XG4gIGNvbnN0IHByb2ZpbGUgPVxuICAgIHJlc29sdmVkUHJvZmlsZSA/PyByZXNvbHZlRGF0YWJyaWNrc1Byb2ZpbGUob3B0aW9ucywgZGVwZW5kZW5jaWVzLmVudmlyb25tZW50ID8/IHByb2Nlc3MuZW52KTtcbiAgaWYgKHByb2ZpbGUuYXV0aEtpbmQgPT09IEF1dGhLaW5kLkFwcE9uQmVoYWxmT2YpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJjcmVhdGVkIHJlcXVlc3Qtc2NvcGVkIEFwcCBPQk8gYXV0aGVudGljYXRpb25cIiwge1xuICAgICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgICAgaG9zdDogcHJvZmlsZS5ob3N0LFxuICAgICAgaGFzV29ya3NwYWNlSWQ6IEJvb2xlYW4ocHJvZmlsZS53b3Jrc3BhY2VJZCksXG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBQZXJzaXN0ZW50QXV0aChcbiAgICAgIHByb2ZpbGUsXG4gICAgICBTdG9yYWdlLk1lbW9yeSxcbiAgICAgIG9wdGlvbnMsXG4gICAgICBkZXBlbmRlbmNpZXMuZW52aXJvbm1lbnQgPz8gcHJvY2Vzcy5lbnYsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB7XG4gICAgICAgIGFjY2Vzc1Rva2VuOiBwcm9maWxlLmFjY2Vzc1Rva2VuISxcbiAgICAgICAgdG9rZW5UeXBlOiBcIkJlYXJlclwiLFxuICAgICAgICBzY29wZXM6IFsuLi5wcm9maWxlLnNjb3Blc10sXG4gICAgICB9LFxuICAgICk7XG4gIH1cbiAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBwcm92aWRlckZvcihwcm9maWxlLCBvcHRpb25zLCBkZXBlbmRlbmNpZXMpO1xuICBjb25zdCBjbGllbnQgPSBuZXcgVG9rZW5MaWZlY3ljbGUoXG4gICAgcHJvZmlsZS5jYWNoZUtleSxcbiAgICBwcm92aWRlcixcbiAgICBzdG9yZSxcbiAgICBBdXRoT3B0aW9ucy5jcmVhdGUob3B0aW9ucy5hdXRoKSxcbiAgKTtcbiAgY29uc3QgcGVyc2lzdGVudCA9IG5ldyBQZXJzaXN0ZW50QXV0aChcbiAgICBwcm9maWxlLFxuICAgIHN0b3JhZ2UgPT09IFN0b3JhZ2UuQXV0byA/IHN0b3JhZ2VGcm9tTmFtZShzdG9yZS5uYW1lKCkpIDogc3RvcmFnZSxcbiAgICBvcHRpb25zLFxuICAgIGRlcGVuZGVuY2llcy5lbnZpcm9ubWVudCA/PyBwcm9jZXNzLmVudixcbiAgICBjbGllbnQsXG4gICk7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZWQgcGVyc2lzdGVudCBhdXRoZW50aWNhdGlvbiBsaWZlY3ljbGVcIiwge1xuICAgIHByb2ZpbGU6IHByb2ZpbGUubmFtZSxcbiAgICBob3N0OiBwcm9maWxlLmhvc3QsXG4gICAgYXV0aEtpbmQ6IHByb2ZpbGUuYXV0aEtpbmQsXG4gICAgc3RvcmFnZTogcGVyc2lzdGVudC5zdGF0dXMoKS5zdG9yYWdlLFxuICB9KTtcbiAgcmV0dXJuIHBlcnNpc3RlbnQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHByb3ZpZGVyRm9yKFxuICBwcm9maWxlOiBEYXRhYnJpY2tzUHJvZmlsZSxcbiAgb3B0aW9uczogRGF0YWJyaWNrc0F1dGhPcHRpb25zLFxuICBkZXBlbmRlbmNpZXM6IERhdGFicmlja3NBdXRoRGVwZW5kZW5jaWVzLFxuKTogUHJvbWlzZTxUb2tlblByb3ZpZGVyPiB7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gZGVwZW5kZW5jaWVzLmVudmlyb25tZW50ID8/IHByb2Nlc3MuZW52O1xuICBjb25zdCBpbkFwcCA9IGVudmlyb25tZW50VXRpbHMuaXNEYXRhYnJpY2tzQXBwRW52KHsgLi4uZW52aXJvbm1lbnQgfSk7XG4gIHN3aXRjaCAocHJvZmlsZS5hdXRoS2luZCkge1xuICAgIGNhc2UgQXV0aEtpbmQuVXNlclRvTWFjaGluZToge1xuICAgICAgY29uc3QgaW5zdGFsbCA9ICFpbkFwcCB8fCBvcHRpb25zLmluc3RhbGxDbGlJbkFwcCA9PT0gdHJ1ZTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcInNlbGVjdGVkIERhdGFicmlja3MgQ0xJIHByb3ZpZGVyXCIsIHtcbiAgICAgICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgICAgICBpbkFwcCxcbiAgICAgICAgaW5zdGFsbCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzQ2xpUHJvdmlkZXIoXG4gICAgICAgIHByb2ZpbGUubmFtZSxcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBkZXBlbmRlbmNpZXMucmVzb2x2ZUNsaVxuICAgICAgICAgICAgPyBkZXBlbmRlbmNpZXMucmVzb2x2ZUNsaSh7IGluc3RhbGwgfSlcbiAgICAgICAgICAgIDogcmVzb2x2ZURhdGFicmlja3NDbGkoZW52aXJvbm1lbnQsIHsgaW5zdGFsbCB9KSxcbiAgICAgICAgY2xpRW52aXJvbm1lbnQocHJvZmlsZSwgcmVzb2x2ZUNvbmZpZ0ZpbGUob3B0aW9ucy5jb25maWdGaWxlLCBlbnZpcm9ubWVudCkpLFxuICAgICAgKTtcbiAgICB9XG4gICAgY2FzZSBBdXRoS2luZC5QZXJzb25hbEFjY2Vzc1Rva2VuOlxuICAgICAgbG9nZ2VyLmRlYnVnKFwic2VsZWN0ZWQgcGVyc29uYWwgYWNjZXNzIHRva2VuIHByb3ZpZGVyXCIsIHsgcHJvZmlsZTogcHJvZmlsZS5uYW1lIH0pO1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzUGVyc29uYWxBY2Nlc3NUb2tlblByb3ZpZGVyKHByb2ZpbGUuYWNjZXNzVG9rZW4hKTtcbiAgICBjYXNlIEF1dGhLaW5kLk1hY2hpbmVUb01hY2hpbmU6XG4gICAgY2FzZSBBdXRoS2luZC5BcHBTZXJ2aWNlUHJpbmNpcGFsOiB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJzZWxlY3RlZCBzZXJ2aWNlLXByaW5jaXBhbCBwcm92aWRlclwiLCB7XG4gICAgICAgIHByb2ZpbGU6IHByb2ZpbGUubmFtZSxcbiAgICAgICAgYXV0aEtpbmQ6IHByb2ZpbGUuYXV0aEtpbmQsXG4gICAgICAgIHRhcmdldDogcHJvZmlsZS50YXJnZXQsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGVuZHBvaW50cyA9IGF3YWl0IHJlc29sdmVPQXV0aEVuZHBvaW50cyhwcm9maWxlLCBkZXBlbmRlbmNpZXMuZmV0Y2gpO1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzU2VydmljZVByaW5jaXBhbFByb3ZpZGVyKHtcbiAgICAgICAgdG9rZW5FbmRwb2ludDogZW5kcG9pbnRzLnRva2VuRW5kcG9pbnQsXG4gICAgICAgIGNsaWVudElkOiBwcm9maWxlLmNsaWVudElkLFxuICAgICAgICBjbGllbnRTZWNyZXQ6IHByb2ZpbGUuY2xpZW50U2VjcmV0ISxcbiAgICAgICAgc2NvcGVzOiBtYWNoaW5lU2NvcGVzKHByb2ZpbGUuc2NvcGVzKSxcbiAgICAgICAgLi4uKHByb2ZpbGUuZ3JvdXBJZCA/IHsgZ3JvdXBJZDogcHJvZmlsZS5ncm91cElkIH0gOiB7fSksXG4gICAgICAgIGFsbG93SW5zZWN1cmVSZXF1ZXN0czogaXNMb29wYmFja0h0dHAocHJvZmlsZS5ob3N0KSxcbiAgICAgICAgZmV0Y2g6IGRlcGVuZGVuY2llcy5mZXRjaCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBjYXNlIEF1dGhLaW5kLkFwcE9uQmVoYWxmT2Y6XG4gICAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY29uZmlnXCIsIFwiQXBwIE9CTyB0b2tlbnMgZG8gbm90IHVzZSBhIHBlcnNpc3RlbnQgcHJvdmlkZXJcIik7XG4gIH1cbn1cblxuaW50ZXJmYWNlIEF1dGhvcml6YXRpb25TZXJ2ZXIge1xuICB0b2tlbkVuZHBvaW50OiBzdHJpbmc7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVPQXV0aEVuZHBvaW50cyhcbiAgcHJvZmlsZTogRGF0YWJyaWNrc1Byb2ZpbGUsXG4gIGZldGNoZXI6IHR5cGVvZiBnbG9iYWxUaGlzLmZldGNoID0gZ2xvYmFsVGhpcy5mZXRjaCxcbik6IFByb21pc2U8QXV0aG9yaXphdGlvblNlcnZlcj4ge1xuICBjb25zdCBob3N0ID0gcHJvZmlsZS5ob3N0LnJlcGxhY2UoL1xcLyQvLCBcIlwiKTtcbiAgaWYgKHByb2ZpbGUudGFyZ2V0ID09PSBUYXJnZXRLaW5kLkFjY291bnQpIHtcbiAgICBpZiAoIXByb2ZpbGUuYWNjb3VudElkKSB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY29uZmlnXCIsIFwiQWNjb3VudCB0YXJnZXQgcmVxdWlyZXMgYWNjb3VudF9pZFwiKTtcbiAgICBjb25zdCBlbmRwb2ludHMgPSB7XG4gICAgICB0b2tlbkVuZHBvaW50OiBgJHtob3N0fS9vaWRjL2FjY291bnRzLyR7cHJvZmlsZS5hY2NvdW50SWR9L3YxL3Rva2VuYCxcbiAgICB9O1xuICAgIGxvZ2dlci5kZWJ1ZyhcInJlc29sdmVkIGFjY291bnQgT0F1dGggZW5kcG9pbnRcIiwge1xuICAgICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgICAgdG9rZW5PcmlnaW46IG5ldyBVUkwoZW5kcG9pbnRzLnRva2VuRW5kcG9pbnQpLm9yaWdpbixcbiAgICB9KTtcbiAgICByZXR1cm4gZW5kcG9pbnRzO1xuICB9XG4gIGNvbnN0IGRpc2NvdmVyeSA9XG4gICAgcHJvZmlsZS50YXJnZXQgPT09IFRhcmdldEtpbmQuVW5pZmllZFxuICAgICAgPyBgJHtob3N0fS9vaWRjL2FjY291bnRzLyR7cmVxdWlyZWRBY2NvdW50SWQocHJvZmlsZSl9Ly53ZWxsLWtub3duL29hdXRoLWF1dGhvcml6YXRpb24tc2VydmVyYFxuICAgICAgOiBgJHtob3N0fS9vaWRjLy53ZWxsLWtub3duL29hdXRoLWF1dGhvcml6YXRpb24tc2VydmVyYDtcbiAgbG9nZ2VyLmRlYnVnKFwicmVxdWVzdGluZyBPQXV0aCBkaXNjb3ZlcnlcIiwge1xuICAgIHByb2ZpbGU6IHByb2ZpbGUubmFtZSxcbiAgICB0YXJnZXQ6IHByb2ZpbGUudGFyZ2V0LFxuICAgIGRpc2NvdmVyeSxcbiAgfSk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2hlcihkaXNjb3ZlcnksIHsgcmVkaXJlY3Q6IFwibWFudWFsXCIgfSk7XG4gIGxvZ2dlci5kZWJ1ZyhcInJlY2VpdmVkIE9BdXRoIGRpc2NvdmVyeSByZXNwb25zZVwiLCB7XG4gICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzLFxuICB9KTtcbiAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDA0KVxuICAgIHRocm93IG5ldyBBdXRoRXJyb3IoXCJvYXV0aFwiLCBgT0F1dGggaXMgbm90IHN1cHBvcnRlZCBhdCAke2Rpc2NvdmVyeX1gKTtcbiAgaWYgKCFyZXNwb25zZS5vaylcbiAgICB0aHJvdyBuZXcgQXV0aEVycm9yKFwib2F1dGhcIiwgYE9BdXRoIGRpc2NvdmVyeSByZXR1cm5lZCBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xuICBjb25zdCB2YWx1ZSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB0b2tlbkVuZHBvaW50ID0gc3RyaW5nVmFsdWUodmFsdWUudG9rZW5fZW5kcG9pbnQpO1xuICBpZiAoIXRva2VuRW5kcG9pbnQpIHRocm93IG5ldyBBdXRoRXJyb3IoXCJvYXV0aFwiLCBcIk9BdXRoIGRpc2NvdmVyeSByZXNwb25zZSBpcyBpbmNvbXBsZXRlXCIpO1xuICBsb2dnZXIuZGVidWcoXCJyZXNvbHZlZCBPQXV0aCB0b2tlbiBlbmRwb2ludFwiLCB7XG4gICAgcHJvZmlsZTogcHJvZmlsZS5uYW1lLFxuICAgIHRva2VuT3JpZ2luOiBuZXcgVVJMKHRva2VuRW5kcG9pbnQpLm9yaWdpbixcbiAgfSk7XG4gIHJldHVybiB7IHRva2VuRW5kcG9pbnQgfTtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZWRBY2NvdW50SWQocHJvZmlsZTogRGF0YWJyaWNrc1Byb2ZpbGUpOiBzdHJpbmcge1xuICBpZiAoIXByb2ZpbGUuYWNjb3VudElkKSB0aHJvdyBuZXcgQXV0aEVycm9yKFwiY29uZmlnXCIsIFwiVW5pZmllZCB0YXJnZXQgcmVxdWlyZXMgYWNjb3VudF9pZFwiKTtcbiAgcmV0dXJuIHByb2ZpbGUuYWNjb3VudElkO1xufVxuXG5mdW5jdGlvbiBzdG9yYWdlRnJvbU5hbWUobmFtZTogc3RyaW5nKTogU3RvcmFnZSB7XG4gIHJldHVybiBuYW1lID09PSBcIm1lbW9yeVwiID8gU3RvcmFnZS5NZW1vcnkgOiBTdG9yYWdlLkZpbGU7XG59XG5cbmZ1bmN0aW9uIHByb2ZpbGVTdW1tYXJ5KHByb2ZpbGU6IERhdGFicmlja3NQcm9maWxlKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogcHJvZmlsZS5uYW1lLFxuICAgIGhvc3Q6IHByb2ZpbGUuaG9zdCxcbiAgICAuLi4ocHJvZmlsZS5hY2NvdW50SWQgPyB7IGFjY291bnRJZDogcHJvZmlsZS5hY2NvdW50SWQgfSA6IHt9KSxcbiAgICAuLi4ocHJvZmlsZS53b3Jrc3BhY2VJZCA/IHsgd29ya3NwYWNlSWQ6IHByb2ZpbGUud29ya3NwYWNlSWQgfSA6IHt9KSxcbiAgICB0YXJnZXQ6IHByb2ZpbGUudGFyZ2V0LFxuICAgIGF1dGhLaW5kOiBwcm9maWxlLmF1dGhLaW5kLFxuICB9O1xufVxuXG5mdW5jdGlvbiBpc0xvb3BiYWNrSHR0cChob3N0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgdXJsID0gbmV3IFVSTChob3N0KTtcbiAgcmV0dXJuIHVybC5wcm90b2NvbCA9PT0gXCJodHRwOlwiICYmIFtcIjEyNy4wLjAuMVwiLCBcImxvY2FsaG9zdFwiXS5pbmNsdWRlcyh1cmwuaG9zdG5hbWUpO1xufVxuXG5mdW5jdGlvbiBjbGlFbnZpcm9ubWVudChwcm9maWxlOiBEYXRhYnJpY2tzUHJvZmlsZSwgY29uZmlnRmlsZTogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIHJldHVybiB7XG4gICAgREFUQUJSSUNLU19DT05GSUdfRklMRTogY29uZmlnRmlsZSxcbiAgICBEQVRBQlJJQ0tTX0NPTkZJR19QUk9GSUxFOiBwcm9maWxlLm5hbWUsXG4gICAgREFUQUJSSUNLU19IT1NUOiBwcm9maWxlLmhvc3QsXG4gICAgLi4uKHByb2ZpbGUuYWNjb3VudElkID8geyBEQVRBQlJJQ0tTX0FDQ09VTlRfSUQ6IHByb2ZpbGUuYWNjb3VudElkIH0gOiB7fSksXG4gICAgLi4uKHByb2ZpbGUud29ya3NwYWNlSWQgPyB7IERBVEFCUklDS1NfV09SS1NQQUNFX0lEOiBwcm9maWxlLndvcmtzcGFjZUlkIH0gOiB7fSksXG4gICAgLi4uKHByb2ZpbGUuYXV0aEtpbmQgPT09IEF1dGhLaW5kLlBlcnNvbmFsQWNjZXNzVG9rZW5cbiAgICAgID8ge1xuICAgICAgICAgIERBVEFCUklDS1NfQVVUSF9UWVBFOiBcInBhdFwiLFxuICAgICAgICAgIERBVEFCUklDS1NfVE9LRU46IHByb2ZpbGUuYWNjZXNzVG9rZW4hLFxuICAgICAgICB9XG4gICAgICA6IHt9KSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc3RyaW5nVmFsdWUodmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlLnRyaW0oKSA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuIl19
|