@financialforcedev/orizuru-auth
Version:
Salesforce authentication for Heroku Node applications.
128 lines • 26.8 kB
JavaScript
;
/*
* Copyright (c) 2019, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @module client/openid
*/
const axios_1 = __importDefault(require("axios"));
const oauth2_1 = require("./oauth2");
const oauth2Jwt_1 = require("./oauth2Jwt");
const identity_1 = require("./openid/identity");
const jwk_1 = require("./openid/jwk");
const DEFAULT_USERINFO_OPTIONS = Object.freeze({
responseFormat: 'application/json'
});
/**
* An OpenID client that implements the [OpenID Connect Specification](https://openid.net/specs/openid-connect-core-1_0.html).
*/
class OpenIdClient extends oauth2Jwt_1.OAuth2JWTClient {
/**
* Creates a new OpenID client with the given environment.
*
* @param env The OAuth2 environment parameters.
*/
constructor(env) {
super(env);
this.clientType = 'OpenID';
}
/**
* Initalize the OpenIdClient by requesting the [OpenID provider configuration information](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig)
* for the issuer provided in the environment.
*/
async init() {
const config = Object.assign({}, oauth2_1.OAuth2Client.DEFAULT_REQUEST_CONFIG, {
timeout: this.env.httpTimeout
});
const uri = `${this.env.issuerURI.replace(/\/$/, '')}/.well-known/openid-configuration`;
const response = await axios_1.default.get(uri, config);
if (response.status !== 200) {
throw new Error(`Failed to initialise ${this.clientType} client. OpenID configuration request failed.`);
}
const data = response.data;
this.authorizationEndpoint = data.authorization_endpoint;
this.introspectionEndpoint = data.introspection_endpoint || null;
this.jwksEndpoint = data.jwks_uri;
this.revocationEndpoint = data.revocation_endpoint;
this.tokenEndpoint = data.token_endpoint;
this.userinfoEndpoint = data.userinfo_endpoint;
if (this.jwksEndpoint) {
this.jwkPemFormatMap = await jwk_1.retrieveJsonWebKeysInPemFormat(this.jwksEndpoint, config);
}
}
/**
* @inheritdoc
* @returns The OpenID Access Token Response.
*/
async grant(params, opts) {
return super.grant(params, opts);
}
/**
* Retrieve the user information using the provided token.
*
* @param token The token to be used.
* @param [opts] The user info options to be used.
*/
async userinfo(token, opts) {
if (!this.userinfoEndpoint) {
throw new Error(`${this.clientType} client has not been initialized`);
}
const internalOpts = Object.assign({}, DEFAULT_USERINFO_OPTIONS, opts);
const config = Object.assign({}, oauth2_1.OAuth2Client.DEFAULT_REQUEST_CONFIG, {
headers: {
Accept: internalOpts.responseFormat,
Authorization: `Bearer ${token}`
}
});
const response = await axios_1.default.get(this.userinfoEndpoint, config);
if (response.status !== 200) {
throw new Error(`Failed to obtain user information: ${response.data}.`);
}
return response.data;
}
/**
* @inheritdoc
*/
handleAccessTokenResponse(accessTokenResponse, internalOpts) {
try {
if (internalOpts.verifyIdToken) {
identity_1.verifyIdToken(accessTokenResponse, this.jwkPemFormatMap);
}
if (internalOpts.decodeIdToken) {
identity_1.decodeIdToken(accessTokenResponse);
}
}
catch (error) {
throw new Error(`Failed to obtain grant: ${error.message}.`);
}
return accessTokenResponse;
}
}
exports.OpenIdClient = OpenIdClient;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmlkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2luZGV4L2NsaWVudC9vcGVuaWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3Qkc7Ozs7O0FBRUg7O0dBRUc7QUFFSCxrREFBMEI7QUFHMUIscUNBQTBGO0FBQzFGLDJDQUFvRTtBQUNwRSxnREFBaUU7QUFDakUsc0NBQXNGO0FBRXRGLE1BQU0sd0JBQXdCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM5QyxjQUFjLEVBQUUsa0JBQWtCO0NBQ2xDLENBQUMsQ0FBQztBQXdRSDs7R0FFRztBQUNILE1BQWEsWUFBYSxTQUFRLDJCQUFlO0lBaUJoRDs7OztPQUlHO0lBQ0gsWUFBWSxHQUFnQjtRQUMzQixLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDWCxJQUFJLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQztJQUM1QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLElBQUk7UUFFaEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUscUJBQVksQ0FBQyxzQkFBc0IsRUFBRTtZQUNyRSxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXO1NBQzdCLENBQUMsQ0FBQztRQUVILE1BQU0sR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsbUNBQW1DLENBQUM7UUFDeEYsTUFBTSxRQUFRLEdBQUcsTUFBTSxlQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUU5QyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLElBQUksQ0FBQyxVQUFVLCtDQUErQyxDQUFDLENBQUM7U0FDeEc7UUFFRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO1FBRTNCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUM7UUFDekQsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQyxzQkFBc0IsSUFBSSxJQUFJLENBQUM7UUFDakUsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUM7UUFDbkQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFFL0MsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RCLElBQUksQ0FBQyxlQUFlLEdBQUcsTUFBTSxvQ0FBOEIsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ3ZGO0lBRUYsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBbUIsRUFBRSxJQUF5QjtRQUNoRSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBcUIsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQWEsRUFBRSxJQUFzQjtRQUUxRCxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFO1lBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxrQ0FBa0MsQ0FBQyxDQUFDO1NBQ3RFO1FBRUQsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFdkUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUscUJBQVksQ0FBQyxzQkFBc0IsRUFBRTtZQUNyRSxPQUFPLEVBQUU7Z0JBQ1IsTUFBTSxFQUFFLFlBQVksQ0FBQyxjQUFjO2dCQUNuQyxhQUFhLEVBQUUsVUFBVSxLQUFLLEVBQUU7YUFDaEM7U0FDRCxDQUFDLENBQUM7UUFFSCxNQUFNLFFBQVEsR0FBRyxNQUFNLGVBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRWhFLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxHQUFHLEVBQUU7WUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsUUFBUSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7U0FDeEU7UUFFRCxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFFdEIsQ0FBQztJQUVEOztPQUVHO0lBQ08seUJBQXlCLENBQUMsbUJBQXdDLEVBQUUsWUFBZ0M7UUFFN0csSUFBSTtZQUVILElBQUksWUFBWSxDQUFDLGFBQWEsRUFBRTtnQkFDL0Isd0JBQWEsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7YUFDekQ7WUFFRCxJQUFJLFlBQVksQ0FBQyxhQUFhLEVBQUU7Z0JBQy9CLHdCQUFhLENBQUMsbUJBQW1CLENBQUMsQ0FBQzthQUNuQztTQUVEO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztTQUM3RDtRQUVELE9BQU8sbUJBQWdELENBQUM7SUFFekQsQ0FBQztDQUVEO0FBekhELG9DQXlIQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTksIEZpbmFuY2lhbEZvcmNlLmNvbSwgaW5jXG4gKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sXG4gKiAgIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcbiAqXG4gKiAtIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAqICAgICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAqIC0gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICogICAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXG4gKiAgICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuICogLSBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBGaW5hbmNpYWxGb3JjZS5jb20sIGluYyBub3IgdGhlIG5hbWVzIG9mIGl0cyBjb250cmlidXRvcnNcbiAqICAgICAgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXRcbiAqICAgICAgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxuICpcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxuICogIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVNcbiAqICBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTFxuICogIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLFxuICogIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EU1xuICogIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWVxuICogIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKVxuICogIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICovXG5cbi8qKlxuICogQG1vZHVsZSBjbGllbnQvb3BlbmlkXG4gKi9cblxuaW1wb3J0IGF4aW9zIGZyb20gJ2F4aW9zJztcblxuaW1wb3J0IHsgRW52aXJvbm1lbnQgfSBmcm9tICcuL2NhY2hlJztcbmltcG9ydCB7IEFjY2Vzc1Rva2VuUmVzcG9uc2UsIEdyYW50UGFyYW1zLCBPQXV0aDJDbGllbnQsIFJlc3BvbnNlRm9ybWF0IH0gZnJvbSAnLi9vYXV0aDInO1xuaW1wb3J0IHsgSldULCBKd3RHcmFudE9wdGlvbnMsIE9BdXRoMkpXVENsaWVudCB9IGZyb20gJy4vb2F1dGgySnd0JztcbmltcG9ydCB7IGRlY29kZUlkVG9rZW4sIHZlcmlmeUlkVG9rZW4gfSBmcm9tICcuL29wZW5pZC9pZGVudGl0eSc7XG5pbXBvcnQgeyBKc29uV2ViS2V5UGVtRm9ybWF0TWFwLCByZXRyaWV2ZUpzb25XZWJLZXlzSW5QZW1Gb3JtYXQgfSBmcm9tICcuL29wZW5pZC9qd2snO1xuXG5jb25zdCBERUZBVUxUX1VTRVJJTkZPX09QVElPTlMgPSBPYmplY3QuZnJlZXplKHtcblx0cmVzcG9uc2VGb3JtYXQ6ICdhcHBsaWNhdGlvbi9qc29uJ1xufSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbklEQWNjZXNzVG9rZW5SZXNwb25zZSBleHRlbmRzIEFjY2Vzc1Rva2VuUmVzcG9uc2Uge1xuXG5cdC8qKlxuXHQgKiBBbiBbT3BlbklEIFRva2VuXShodHRwczovL29wZW5pZC5uZXQvc3BlY3Mvb3BlbmlkLWNvbm5lY3QtY29yZS0xXzAuaHRtbCNJRFRva2VuKSB0aGF0IGNvbnRhaW5zIGNsYWltcyBhYm91dCB0aGUgYXV0aGVudGljYXRpb24gb2YgYW4gZW5kLXVzZXIgYnkgYW5cblx0ICogYXV0aG9yaXphdGlvbiBzZXJ2ZXIuXG5cdCAqL1xuXHRpZF90b2tlbj86IG51bGwgfCBzdHJpbmcgfCBPcGVuSURUb2tlbiB8IE9wZW5JRFRva2VuV2l0aFN0YW5kYXJkQ2xhaW1zO1xuXG59XG5cbi8qKlxuICogT3B0aW9uYWwgcGFyYW1ldGVycyB1c2VkIHdoZW4gcmVxdWVzdGluZyBncmFudHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbklkR3JhbnRPcHRpb25zIGV4dGVuZHMgSnd0R3JhbnRPcHRpb25zIHtcblxuXHQvKipcblx0ICogSWYgdHJ1ZSwgdGhlIEpXVCBwcmVzZW50IGluIHRoZSBpZF90b2tlbiBmaWVsZCBvZiB0aGUgYWNjZXNzIHRva2VuIHJlc3BvbnNlIGlzIHBhcnNlZC5cblx0ICovXG5cdGRlY29kZUlkVG9rZW4/OiBib29sZWFuO1xuXG5cdC8qKlxuXHQgKiBJZiB0cnVlLCB2ZXJpZnkgdGhlIElEIHRva2VuIHdpdGggdGhlIHJldHJpZXZlZCBKV0tzLlxuXHQgKi9cblx0dmVyaWZ5SWRUb2tlbj86IGJvb2xlYW47XG5cbn1cblxuLyoqXG4gKiBBIHRva2VuIHRoYXQgY29uZm9ybXMgdG8gdGhlIFtPcGVuSUQgc3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9vcGVuaWQubmV0L3NwZWNzL29wZW5pZC1jb25uZWN0LWNvcmUtMV8wLmh0bWwjSURUb2tlbikuXG4gKlxuICogSXQgaXMgcmV0dXJuZWQgaW4gdGhlIGBpZF90b2tlbmAgZmllbGQgb2YgdGhlIGBBY2Nlc3NUb2tlblJlc3BvbnNlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVuSURUb2tlbiBleHRlbmRzIEpXVCB7XG5cblx0LyoqXG5cdCAqIEF1dGhlbnRpY2F0aW9uIENvbnRleHQgQ2xhc3MgUmVmZXJlbmNlIENsYWltLlxuXHQgKi9cblx0YWNyPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBBdXRoZW50aWNhdGlvbiBNZXRob2RzIFJlZmVyZW5jZXMgQ2xhaW0uXG5cdCAqL1xuXHRhbXI/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIEFjY2VzcyBUb2tlbiBIYXNoIFZhbHVlIENsYWltLlxuXHQgKi9cblx0YXRfaGFzaD86IHN0cmluZztcblxuXHQvKipcblx0ICogVXNlciBBdXRoZW50aWNhdGlvbiBUaW1lIENsYWltO1xuXHQgKi9cblx0YXV0aF90aW1lPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBBdXRob3JpemVkIFBhcnR5IENsYWltLlxuXHQgKi9cblx0YXpwPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdGRvY1xuXHQgKi9cblx0aWF0OiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIFN0cmluZyB2YWx1ZSB1c2VkIHRvIGFzc29jaWF0ZSBhIENsaWVudCBzZXNzaW9uIHdpdGggYW4gSUQgVG9rZW4sIGFuZCB0byBtaXRpZ2F0ZSByZXBsYXkgYXR0YWNrcyBjbGFpbS5cblx0ICovXG5cdG5vbmNlPzogc3RyaW5nO1xuXG59XG5cbi8qKlxuICogW0FkZHJlc3MgY2xhaW1dKGh0dHBzOi8vb3BlbmlkLm5ldC9zcGVjcy9vcGVuaWQtY29ubmVjdC1jb3JlLTFfMC5odG1sI0FkZHJlc3NDbGFpbSlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVuSWRUb2tlbkFkZHJlc3Mge1xuXG5cdC8qKlxuXHQgKiBGdWxsIG1haWxpbmcgYWRkcmVzcyxcblx0ICovXG5cdGZvcm1hdHRlZD86IHN0cmluZztcblxuXHQvKipcblx0ICogRnVsbCBzdHJlZXQgYWRkcmVzcy5cblx0ICovXG5cdHN0cmVldF9hZGRyZXNzPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBDaXR5IG9yIGxvY2FsaXR5IGNvbXBvbmVudC5cblx0ICovXG5cdGxvY2FsaXR5Pzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBTdGF0ZSwgcHJvdmluY2UsIHByZWZlY3R1cmUsIG9yIHJlZ2lvbiBjb21wb25lbnQuXG5cdCAqL1xuXHRyZWdpb24/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFppcCBjb2RlIG9yIHBvc3RhbCBjb2RlIGNvbXBvbmVudC5cblx0ICovXG5cdHBvc3RhbF9jb2RlPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBDb3VudHJ5IG5hbWUgY29tcG9uZW50LlxuXHQgKi9cblx0Y291bnRyeT86IHN0cmluZztcblxufVxuXG4vKipcbiAqIFN0YW5kYXJkIHNldCBvZiBjbGFpbXMgcmV0dXJuZWQgaW4gYSB1c2VyaW5mbyByZXF1ZXN0LlxuICpcbiAqIFRoZSBzdGFuZGFyZCBjbGFpbXMgY29uZm9ybSB0byB0aGUgW09wZW5JRCBzcGVjaWZpY2F0aW9uXShodHRwczovL29wZW5pZC5uZXQvc3BlY3Mvb3BlbmlkLWNvbm5lY3QtY29yZS0xXzAuaHRtbCNTdGFuZGFyZENsYWltcykuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbklEVG9rZW5XaXRoU3RhbmRhcmRDbGFpbXMgZXh0ZW5kcyBPcGVuSURUb2tlbiB7XG5cblx0LyoqXG5cdCAqIEVuZC1Vc2VyJ3MgcHJlZmVycmVkIGFkZHJlc3MuXG5cdCAqXG5cdCAqIFRoZSB2YWx1ZSBvZiB0aGUgYWRkcmVzcyBtZW1iZXIgaXMgYSBKU09OIFtSRkM0NjI3XSBzdHJ1Y3R1cmUgY29udGFpbmluZyBzb21lIG9yXG5cdCAqIGFsbCBvZiB0aGUgbWVtYmVycyBkZWZpbmVkIFtoZXJlXShodHRwczovL29wZW5pZC5uZXQvc3BlY3Mvb3BlbmlkLWNvbm5lY3QtY29yZS0xXzAuaHRtbCNBZGRyZXNzQ2xhaW0pLlxuXHQgKi9cblx0YWRkcmVzcz86IE9wZW5JZFRva2VuQWRkcmVzcztcblxuXHQvKipcblx0ICogRW5kLVVzZXIncyBiaXJ0aGRheSwgcmVwcmVzZW50ZWQgYXMgYW4gSVNPIDg2MDE6MjAwNCBbSVNPODYwMeKAkTIwMDRdIFlZWVktTU0tREQgZm9ybWF0LlxuXHQgKiBUaGUgeWVhciBNQVkgYmUgMDAwMCwgaW5kaWNhdGluZyB0aGF0IGl0IGlzIG9taXR0ZWQuXG5cdCAqIFRvIHJlcHJlc2VudCBvbmx5IHRoZSB5ZWFyLCBZWVlZIGZvcm1hdCBpcyBhbGxvd2VkLlxuXHQgKi9cblx0YmlydGhkYXRlPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBFbmQtVXNlcidzIHByZWZlcnJlZCBlLW1haWwgYWRkcmVzcy5cblx0ICpcblx0ICogSXRzIHZhbHVlIE1VU1QgY29uZm9ybSB0byB0aGUgUkZDIDUzMjIgW1JGQzUzMjJdIGFkZHItc3BlYyBzeW50YXguXG5cdCAqIFRoaXMgdmFsdWUgTVVTVCBOT1QgYmUgcmVsaWVkIHVwb24gdG8gYmUgdW5pcXVlIGJ5IHRoZSBSUCwgYXMgZGlzY3Vzc2VkIGluIFNlY3Rpb24gMi41LjMuXG5cdCAqL1xuXHRlbWFpbDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUcnVlIGlmIHRoZSBFbmQtVXNlcidzIGUtbWFpbCBhZGRyZXNzIGhhcyBiZWVuIHZlcmlmaWVkOyBvdGhlcndpc2UgZmFsc2UuXG5cdCAqIFdoZW4gdGhpcyBDbGFpbSBWYWx1ZSBpcyB0cnVlLCB0aGlzIG1lYW5zIHRoYXQgdGhlIE9QIHRvb2sgYWZmaXJtYXRpdmUgc3RlcHMgdG8gZW5zdXJlIHRoYXRcblx0ICogdGhpcyBlLW1haWwgYWRkcmVzcyB3YXMgY29udHJvbGxlZCBieSB0aGUgRW5kLVVzZXIgYXQgdGhlIHRpbWUgdGhlIHZlcmlmaWNhdGlvbiB3YXMgcGVyZm9ybWVkLlxuXHQgKiBUaGUgbWVhbnMgYnkgd2hpY2ggYW4gZS1tYWlsIGFkZHJlc3MgaXMgdmVyaWZpZWQgaXMgY29udGV4dC1zcGVjaWZpYywgYW5kIGRlcGVuZGVudCB1cG9uIHRoZVxuXHQgKiB0cnVzdCBmcmFtZXdvcmsgb3IgY29udHJhY3R1YWwgYWdyZWVtZW50cyB3aXRoaW4gd2hpY2ggdGhlIHBhcnRpZXMgYXJlIG9wZXJhdGluZy5cblx0ICovXG5cdGVtYWlsX3ZlcmlmaWVkOiBib29sZWFuO1xuXG5cdC8qKlxuXHQgKiBTdXJuYW1lKHMpIG9yIGxhc3QgbmFtZShzKSBvZiB0aGUgRW5kLVVzZXIuXG5cdCAqL1xuXHRmYW1pbHlfbmFtZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBFbmQtVXNlcidzIGdlbmRlci5cblx0ICovXG5cdGdlbmRlcj86IHN0cmluZztcblxuXHQvKipcblx0ICogR2l2ZW4gbmFtZShzKSBvciBmaXJzdCBuYW1lKHMpIG9mIHRoZSBFbmQtVXNlci5cblx0ICovXG5cdGdpdmVuX25hbWU6IHN0cmluZztcblxuXHQvKipcblx0ICogRW5kLVVzZXIncyBsb2NhbGUsIHJlcHJlc2VudGVkIGFzIGEgQkNQNDcgW1JGQzU2NDZdIGxhbmd1YWdlIHRhZy5cblx0ICovXG5cdGxvY2FsZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBNaWRkbGUgbmFtZShzKSBvZiB0aGUgRW5kLVVzZXIuXG5cdCAqL1xuXHRtaWRkbGVfbmFtZT86IHN0cmluZztcblxuXHQvKipcblx0ICogRW5kLVVzZXIncyBmdWxsIG5hbWUgaW4gZGlzcGxheWFibGUgZm9ybSBpbmNsdWRpbmcgYWxsIG5hbWUgcGFydHMsIHBvc3NpYmx5IGluY2x1ZGluZ1xuXHQgKiB0aXRsZXMgYW5kIHN1ZmZpeGVzLCBvcmRlcmVkIGFjY29yZGluZyB0byB0aGUgRW5kLVVzZXIncyBsb2NhbGUgYW5kIHByZWZlcmVuY2VzLlxuXHQgKi9cblx0bmFtZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBDYXN1YWwgbmFtZSBvZiB0aGUgRW5kLVVzZXIgdGhhdCBtYXkgb3IgbWF5IG5vdCBiZSB0aGUgc2FtZSBhcyB0aGUgZ2l2ZW5fbmFtZS5cblx0ICogRm9yIGluc3RhbmNlLCBhIG5pY2tuYW1lIHZhbHVlIG9mIE1pa2UgbWlnaHQgYmUgcmV0dXJuZWQgYWxvbmdzaWRlIGEgZ2l2ZW5fbmFtZSB2YWx1ZSBvZiBNaWNoYWVsLlxuXHQgKi9cblx0bmlja25hbWU6IHN0cmluZztcblxuXHQvKipcblx0ICogRW5kLVVzZXIncyBwcmVmZXJyZWQgdGVsZXBob25lIG51bWJlci5cblx0ICpcblx0ICogRS4xNjQgW0UuMTY0XSBpcyByZWNvbW1lbmRlZCBhcyB0aGUgZm9ybWF0IG9mIHRoaXMgQ2xhaW0sIGZvciBleGFtcGxlLCArMSAoNDI1KSA1NTUtMTIxMiBvciArNTYgKDIpIDY4NyAyNDAwLlxuXHQgKiBJZiB0aGUgcGhvbmUgbnVtYmVyIGNvbnRhaW5zIGFuIGV4dGVuc2lvbiwgaXQgaXMgcmVjb21tZW5kZWQgdGhhdCB0aGUgZXh0ZW5zaW9uIGJlIHJlcHJlc2VudGVkIHVzaW5nXG5cdCAqIHRoZSBSRkMgMzk2NiBbUkZDMzk2Nl0gZXh0ZW5zaW9uIHN5bnRheCwgZm9yIGV4YW1wbGUsICsxICg2MDQpIDU1NS0xMjM0O2V4dD01Njc4LlxuXHQgKi9cblx0cGhvbmVfbnVtYmVyOiBzdHJpbmcgfCBudWxsO1xuXG5cdC8qKlxuXHQgKiBUcnVlIGlmIHRoZSBFbmQtVXNlcidzIHBob25lIG51bWJlciBoYXMgYmVlbiB2ZXJpZmllZDsgb3RoZXJ3aXNlIGZhbHNlLlxuXHQgKlxuXHQgKiBXaGVuIHRoaXMgQ2xhaW0gVmFsdWUgaXMgdHJ1ZSwgdGhpcyBtZWFucyB0aGF0IHRoZSBPUCB0b29rIGFmZmlybWF0aXZlIHN0ZXBzIHRvIGVuc3VyZSB0aGF0IHRoaXMgcGhvbmUgbnVtYmVyXG5cdCAqIHdhcyBjb250cm9sbGVkIGJ5IHRoZSBFbmQtVXNlciBhdCB0aGUgdGltZSB0aGUgdmVyaWZpY2F0aW9uIHdhcyBwZXJmb3JtZWQuXG5cdCAqIFRoZSBtZWFucyBieSB3aGljaCBhIHBob25lIG51bWJlciBpcyB2ZXJpZmllZCBpcyBjb250ZXh0LXNwZWNpZmljLCBhbmQgZGVwZW5kZW50IHVwb24gdGhlIHRydXN0IGZyYW1ld29yayBvclxuXHQgKiBjb250cmFjdHVhbCBhZ3JlZW1lbnRzIHdpdGhpbiB3aGljaCB0aGUgcGFydGllcyBhcmUgb3BlcmF0aW5nLiBXaGVuIHRydWUsIHRoZSBwaG9uZV9udW1iZXJcblx0ICogQ2xhaW0gTVVTVCBiZSBpbiBFLjE2NCBmb3JtYXQgYW5kIGFueSBleHRlbnNpb25zIE1VU1QgYmUgcmVwcmVzZW50ZWQgaW4gUkZDIDM5NjYgZm9ybWF0LlxuXHQgKi9cblx0cGhvbmVfbnVtYmVyX3ZlcmlmaWVkPzogYm9vbGVhbjtcblxuXHQvKipcblx0ICogVVJMIG9mIHRoZSBFbmQtVXNlcidzIHByb2ZpbGUgcGljdHVyZS5cblx0ICpcblx0ICogVGhpcyBVUkwgTVVTVCByZWZlciB0byBhbiBpbWFnZSBmaWxlIChmb3IgZXhhbXBsZSwgYSBQTkcsIEpQRUcsIG9yIEdJRiBpbWFnZSBmaWxlKSxcblx0ICogcmF0aGVyIHRoYW4gdG8gYSBXZWIgcGFnZSBjb250YWluaW5nIGFuIGltYWdlLiBOb3RlIHRoYXQgdGhpcyBVUkwgc2hvdWxkIHNwZWNpZmljYWxseVxuXHQgKiByZWZlcmVuY2UgYSBwcm9maWxlIHBob3RvIG9mIHRoZSBFbmQtVXNlciBzdWl0YWJsZSBmb3IgZGlzcGxheWluZyB3aGVuIGRlc2NyaWJpbmdcblx0ICogdGhlIEVuZC1Vc2VyLCByYXRoZXIgdGhhbiBhbiBhcmJpdHJhcnkgcGhvdG8gdGFrZW4gYnkgdGhlIEVuZC1Vc2VyLlxuXHQgKi9cblx0cGljdHVyZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBTaG9ydGhhbmQgbmFtZSB0aGF0IHRoZSBFbmQtVXNlciB3aXNoZXMgdG8gYmUgcmVmZXJyZWQgdG8gYXQgdGhlIFJQLCBzdWNoIGFzIGphbmVkb2Ugb3Igai5kb2UuXG5cdCAqIFRoaXMgdmFsdWUgTUFZIGJlIGFueSB2YWxpZCBKU09OIHN0cmluZyBpbmNsdWRpbmcgc3BlY2lhbCBjaGFyYWN0ZXJzIHN1Y2ggYXMgQCwgLywgb3Igd2hpdGVzcGFjZS5cblx0ICogVGhpcyB2YWx1ZSBNVVNUIE5PVCBiZSByZWxpZWQgdXBvbiB0byBiZSB1bmlxdWUgYnkgdGhlIFJQLlxuXHQgKi9cblx0cHJlZmVycmVkX3VzZXJuYW1lOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFVSTCBvZiB0aGUgRW5kLVVzZXIncyBwcm9maWxlIHBhZ2UuXG5cdCAqXG5cdCAqIFRoZSBjb250ZW50cyBvZiB0aGlzIFdlYiBwYWdlIHNob3VsZCBiZSBhYm91dCB0aGUgRW5kLVVzZXIuXG5cdCAqL1xuXHRwcm9maWxlOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFRpbWUgdGhlIEVuZC1Vc2VyJ3MgaW5mb3JtYXRpb24gd2FzIGxhc3QgdXBkYXRlZC5cblx0ICpcblx0ICogVGhlIHRpbWUgaXMgcmVwcmVzZW50ZWQgYXMgdGhlIG51bWJlciBvZiBzZWNvbmRzIGZyb20gMTk3MC0wMS0wMVQwOjA6MFogYXMgbWVhc3VyZWQgaW4gVVRDIHVudGlsIHRoZSBkYXRlL3RpbWUuXG5cdCAqL1xuXHR1cGRhdGVkX2F0OiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIFVSTCBvZiB0aGUgRW5kLVVzZXIncyBXZWIgcGFnZSBvciBibG9nLlxuXHQgKlxuXHQgKiBUaGlzIFdlYiBwYWdlIHNob3VsZCBjb250YWluIGluZm9ybWF0aW9uIHB1Ymxpc2hlZCBieSB0aGUgRW5kLVVzZXIgb3IgYW4gb3JnYW5pemF0aW9uIHRoYXQgdGhlIEVuZC1Vc2VyIGlzIGFmZmlsaWF0ZWQgd2l0aC5cblx0ICovXG5cdHdlYnNpdGU/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFN0cmluZyBmcm9tIHpvbmVpbmZvIFt6b25laW5mb10gdGltZSB6b25lIGRhdGFiYXNlIHJlcHJlc2VudGluZyB0aGUgRW5kLVVzZXIncyB0aW1lIHpvbmUuXG5cdCAqIEZvciBleGFtcGxlLCBFdXJvcGUvUGFyaXMgb3IgQW1lcmljYS9Mb3NfQW5nZWxlcy5cblx0ICovXG5cdHpvbmVpbmZvOiBzdHJpbmc7XG5cbn1cblxuLyoqXG4gKiBPcHRpb25hbCBwYXJhbWV0ZXJzIHVzZWQgd2hlbiByZXF1ZXN0aW5nIHVzZXIgaW5mb3JtYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVXNlckluZm9PcHRpb25zIHtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgcmVzcG9uc2UgZm9ybWF0LCBlaXRoZXIgSlNPTiwgWE1MIG9yIFVSTF9FTkNPREVELlxuXHQgKi9cblx0cmVzcG9uc2VGb3JtYXQ/OiBSZXNwb25zZUZvcm1hdDtcblxufVxuXG4vKipcbiAqIEFuIE9wZW5JRCBjbGllbnQgdGhhdCBpbXBsZW1lbnRzIHRoZSBbT3BlbklEIENvbm5lY3QgU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9vcGVuaWQubmV0L3NwZWNzL29wZW5pZC1jb25uZWN0LWNvcmUtMV8wLmh0bWwpLlxuICovXG5leHBvcnQgY2xhc3MgT3BlbklkQ2xpZW50IGV4dGVuZHMgT0F1dGgySldUQ2xpZW50IHtcblxuXHQvKipcblx0ICogW0pTT04gV2ViIEtleSBTZXQgRG9jdW1lbnRdKGh0dHBzOi8vb3BlbmlkLm5ldC9zcGVjcy9vcGVuaWQtY29ubmVjdC1kaXNjb3ZlcnktMV8wLmh0bWwjUHJvdmlkZXJNZXRhZGF0YSlcblx0ICovXG5cdHByaXZhdGUgandrc0VuZHBvaW50Pzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBbVXNlckluZm8gZW5kcG9pbnRdKGh0dHBzOi8vb3BlbmlkLm5ldC9zcGVjcy9vcGVuaWQtY29ubmVjdC1jb3JlLTFfMC5odG1sI1VzZXJJbmZvKVxuXHQgKi9cblx0cHJpdmF0ZSB1c2VyaW5mb0VuZHBvaW50Pzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBNYXAgb2YgdGhlIHJldHJpZXZlZCBKU09OIFdlYiBLZXlzLCBrZXllZCBieSB0aGUgS2V5IElEIFBhcmFtZXRlciwgaW4gUEVNIGZvcm1hdC5cblx0ICovXG5cdHByaXZhdGUgandrUGVtRm9ybWF0TWFwPzogSnNvbldlYktleVBlbUZvcm1hdE1hcDtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBPcGVuSUQgY2xpZW50IHdpdGggdGhlIGdpdmVuIGVudmlyb25tZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0gZW52IFRoZSBPQXV0aDIgZW52aXJvbm1lbnQgcGFyYW1ldGVycy5cblx0ICovXG5cdGNvbnN0cnVjdG9yKGVudjogRW52aXJvbm1lbnQpIHtcblx0XHRzdXBlcihlbnYpO1xuXHRcdHRoaXMuY2xpZW50VHlwZSA9ICdPcGVuSUQnO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRhbGl6ZSB0aGUgT3BlbklkQ2xpZW50IGJ5IHJlcXVlc3RpbmcgdGhlIFtPcGVuSUQgcHJvdmlkZXIgY29uZmlndXJhdGlvbiBpbmZvcm1hdGlvbl0oaHR0cHM6Ly9vcGVuaWQubmV0L3NwZWNzL29wZW5pZC1jb25uZWN0LWRpc2NvdmVyeS0xXzAuaHRtbCNQcm92aWRlckNvbmZpZylcblx0ICogZm9yIHRoZSBpc3N1ZXIgcHJvdmlkZWQgaW4gdGhlIGVudmlyb25tZW50LlxuXHQgKi9cblx0cHVibGljIGFzeW5jIGluaXQoKSB7XG5cblx0XHRjb25zdCBjb25maWcgPSBPYmplY3QuYXNzaWduKHt9LCBPQXV0aDJDbGllbnQuREVGQVVMVF9SRVFVRVNUX0NPTkZJRywge1xuXHRcdFx0dGltZW91dDogdGhpcy5lbnYuaHR0cFRpbWVvdXRcblx0XHR9KTtcblxuXHRcdGNvbnN0IHVyaSA9IGAke3RoaXMuZW52Lmlzc3VlclVSSS5yZXBsYWNlKC9cXC8kLywgJycpfS8ud2VsbC1rbm93bi9vcGVuaWQtY29uZmlndXJhdGlvbmA7XG5cdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5nZXQodXJpLCBjb25maWcpO1xuXG5cdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBpbml0aWFsaXNlICR7dGhpcy5jbGllbnRUeXBlfSBjbGllbnQuIE9wZW5JRCBjb25maWd1cmF0aW9uIHJlcXVlc3QgZmFpbGVkLmApO1xuXHRcdH1cblxuXHRcdGNvbnN0IGRhdGEgPSByZXNwb25zZS5kYXRhO1xuXG5cdFx0dGhpcy5hdXRob3JpemF0aW9uRW5kcG9pbnQgPSBkYXRhLmF1dGhvcml6YXRpb25fZW5kcG9pbnQ7XG5cdFx0dGhpcy5pbnRyb3NwZWN0aW9uRW5kcG9pbnQgPSBkYXRhLmludHJvc3BlY3Rpb25fZW5kcG9pbnQgfHwgbnVsbDtcblx0XHR0aGlzLmp3a3NFbmRwb2ludCA9IGRhdGEuandrc191cmk7XG5cdFx0dGhpcy5yZXZvY2F0aW9uRW5kcG9pbnQgPSBkYXRhLnJldm9jYXRpb25fZW5kcG9pbnQ7XG5cdFx0dGhpcy50b2tlbkVuZHBvaW50ID0gZGF0YS50b2tlbl9lbmRwb2ludDtcblx0XHR0aGlzLnVzZXJpbmZvRW5kcG9pbnQgPSBkYXRhLnVzZXJpbmZvX2VuZHBvaW50O1xuXG5cdFx0aWYgKHRoaXMuandrc0VuZHBvaW50KSB7XG5cdFx0XHR0aGlzLmp3a1BlbUZvcm1hdE1hcCA9IGF3YWl0IHJldHJpZXZlSnNvbldlYktleXNJblBlbUZvcm1hdCh0aGlzLmp3a3NFbmRwb2ludCwgY29uZmlnKTtcblx0XHR9XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdGRvY1xuXHQgKiBAcmV0dXJucyBUaGUgT3BlbklEIEFjY2VzcyBUb2tlbiBSZXNwb25zZS5cblx0ICovXG5cdHB1YmxpYyBhc3luYyBncmFudChwYXJhbXM6IEdyYW50UGFyYW1zLCBvcHRzPzogT3BlbklkR3JhbnRPcHRpb25zKTogUHJvbWlzZTxPcGVuSURBY2Nlc3NUb2tlblJlc3BvbnNlPiB7XG5cdFx0cmV0dXJuIHN1cGVyLmdyYW50KHBhcmFtcyBhcyBHcmFudFBhcmFtcywgb3B0cyk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0cmlldmUgdGhlIHVzZXIgaW5mb3JtYXRpb24gdXNpbmcgdGhlIHByb3ZpZGVkIHRva2VuLlxuXHQgKlxuXHQgKiBAcGFyYW0gdG9rZW4gVGhlIHRva2VuIHRvIGJlIHVzZWQuXG5cdCAqIEBwYXJhbSBbb3B0c10gVGhlIHVzZXIgaW5mbyBvcHRpb25zIHRvIGJlIHVzZWQuXG5cdCAqL1xuXHRwdWJsaWMgYXN5bmMgdXNlcmluZm8odG9rZW46IHN0cmluZywgb3B0cz86IFVzZXJJbmZvT3B0aW9ucyk6IFByb21pc2U8T3BlbklEVG9rZW5XaXRoU3RhbmRhcmRDbGFpbXM+IHtcblxuXHRcdGlmICghdGhpcy51c2VyaW5mb0VuZHBvaW50KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5jbGllbnRUeXBlfSBjbGllbnQgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkYCk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgaW50ZXJuYWxPcHRzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9VU0VSSU5GT19PUFRJT05TLCBvcHRzKTtcblxuXHRcdGNvbnN0IGNvbmZpZyA9IE9iamVjdC5hc3NpZ24oe30sIE9BdXRoMkNsaWVudC5ERUZBVUxUX1JFUVVFU1RfQ09ORklHLCB7XG5cdFx0XHRoZWFkZXJzOiB7XG5cdFx0XHRcdEFjY2VwdDogaW50ZXJuYWxPcHRzLnJlc3BvbnNlRm9ybWF0LFxuXHRcdFx0XHRBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dG9rZW59YFxuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5nZXQodGhpcy51c2VyaW5mb0VuZHBvaW50LCBjb25maWcpO1xuXG5cdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBvYnRhaW4gdXNlciBpbmZvcm1hdGlvbjogJHtyZXNwb25zZS5kYXRhfS5gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gcmVzcG9uc2UuZGF0YTtcblxuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0ZG9jXG5cdCAqL1xuXHRwcm90ZWN0ZWQgaGFuZGxlQWNjZXNzVG9rZW5SZXNwb25zZShhY2Nlc3NUb2tlblJlc3BvbnNlOiBBY2Nlc3NUb2tlblJlc3BvbnNlLCBpbnRlcm5hbE9wdHM6IE9wZW5JZEdyYW50T3B0aW9ucykge1xuXG5cdFx0dHJ5IHtcblxuXHRcdFx0aWYgKGludGVybmFsT3B0cy52ZXJpZnlJZFRva2VuKSB7XG5cdFx0XHRcdHZlcmlmeUlkVG9rZW4oYWNjZXNzVG9rZW5SZXNwb25zZSwgdGhpcy5qd2tQZW1Gb3JtYXRNYXApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoaW50ZXJuYWxPcHRzLmRlY29kZUlkVG9rZW4pIHtcblx0XHRcdFx0ZGVjb2RlSWRUb2tlbihhY2Nlc3NUb2tlblJlc3BvbnNlKTtcblx0XHRcdH1cblxuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBvYnRhaW4gZ3JhbnQ6ICR7ZXJyb3IubWVzc2FnZX0uYCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFjY2Vzc1Rva2VuUmVzcG9uc2UgYXMgT3BlbklEQWNjZXNzVG9rZW5SZXNwb25zZTtcblxuXHR9XG5cbn1cbiJdfQ==