@financialforcedev/orizuru-auth
Version:
Salesforce authentication for Heroku Node applications.
128 lines • 21.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/salesforce/identity
*/
const crypto_1 = __importDefault(require("crypto"));
/**
* Parse the user information from the `id` property of an access token response.
*
* It is assumed that the `id` conforms to the Salesforce [Identity URL](https://help.salesforce.com/articleView?id=remoteaccess_using_openid.htm) format.
*
* @param response The Salesforce user info response.
*/
function parseUserInfo(response) {
let identityUrl;
let validated;
if (response.id) {
identityUrl = response.id;
validated = false;
}
else if (response.sub) {
identityUrl = response.sub;
// This response is obtained when the token has been introspected.
// Set validated to true as the token is valid.
validated = true;
}
else {
throw new Error('Missing required string parameter: identityUrl');
}
const idUrls = identityUrl.split('/');
const id = idUrls.pop();
const organizationId = idUrls.pop();
if (!id || (id.length !== 15 && id.length !== 18)) {
throw new Error('Missing required string parameter: id');
}
if (!organizationId || (organizationId.length !== 15 && organizationId.length !== 18)) {
throw new Error('Missing required string parameter: organizationId');
}
response.userInfo = Object.assign({
id,
organizationId,
url: identityUrl,
validated
}, response.userInfo);
}
exports.parseUserInfo = parseUserInfo;
/**
* [Verifies the signature](https://help.salesforce.com/articleView?id=remoteaccess_oauth_web_server_flow.htm#grant_access_token) of the access token response.
*
* Used to verify that the identity URL hasn’t changed since the server sent it.
*
* @param clientSecret The client secret for your application.
* @param accessTokenResponse The Salesforce access token response.
*/
function verifySignature(clientSecret, accessTokenResponse) {
if (accessTokenResponse.signature) {
const hmac = crypto_1.default.createHmac('sha256', clientSecret);
hmac.update(`${accessTokenResponse.id}${accessTokenResponse.issued_at}`);
const expectedSignature = Buffer.from(hmac.digest('base64'));
const actualSignature = Buffer.from(accessTokenResponse.signature);
if (expectedSignature.length !== actualSignature.length) {
throw new Error('Invalid signature');
}
if (!crypto_1.default.timingSafeEqual(expectedSignature, actualSignature)) {
throw new Error('Invalid signature');
}
accessTokenResponse.userInfo = {
url: accessTokenResponse.id,
validated: true
};
}
else {
throw new Error('No signature present');
}
}
exports.verifySignature = verifySignature;
/**
* Determines whether the response is a Salesforce access token response.
*
* @param token The access token response.
* @returns A boolean indicating if this token is a Salesforce access token response.
*/
function isSalesforceAccessTokenResponse(token) {
return token.id !== undefined
|| token.instance_url !== undefined
|| token.issued_at !== undefined
|| token.signature !== undefined;
}
exports.isSalesforceAccessTokenResponse = isSalesforceAccessTokenResponse;
/**
* Determines whether the response is a Salesforce introspection response.
*
* @param token The introspection response.
* @returns A boolean indicating if this token is a Salesforce introspection response.
*/
function isSalesforceIntrospectionResponse(token) {
return token.userInfo !== undefined;
}
exports.isSalesforceIntrospectionResponse = isSalesforceIntrospectionResponse;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvaW5kZXgvY2xpZW50L3NhbGVzZm9yY2UvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3Qkc7Ozs7O0FBRUg7O0dBRUc7QUFFSCxvREFBNEI7QUErTTVCOzs7Ozs7R0FNRztBQUNILFNBQWdCLGFBQWEsQ0FBQyxRQUEwQjtJQUV2RCxJQUFJLFdBQW1CLENBQUM7SUFDeEIsSUFBSSxTQUFrQixDQUFDO0lBRXZCLElBQUksUUFBUSxDQUFDLEVBQUUsRUFBRTtRQUNoQixXQUFXLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUMxQixTQUFTLEdBQUcsS0FBSyxDQUFDO0tBQ2xCO1NBQU0sSUFBSSxRQUFRLENBQUMsR0FBRyxFQUFFO1FBRXhCLFdBQVcsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDO1FBRTNCLGtFQUFrRTtRQUNsRSwrQ0FBK0M7UUFDL0MsU0FBUyxHQUFHLElBQUksQ0FBQztLQUVqQjtTQUFNO1FBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO0tBQ2xFO0lBRUQsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN0QyxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDeEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRXBDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsTUFBTSxLQUFLLEVBQUUsQ0FBQyxFQUFFO1FBQ2xELE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztLQUN6RDtJQUVELElBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxLQUFLLEVBQUUsSUFBSSxjQUFjLENBQUMsTUFBTSxLQUFLLEVBQUUsQ0FBQyxFQUFFO1FBQ3RGLE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztLQUNyRTtJQUVELFFBQVEsQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUNqQyxFQUFFO1FBQ0YsY0FBYztRQUNkLEdBQUcsRUFBRSxXQUFXO1FBQ2hCLFNBQVM7S0FDVCxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUV2QixDQUFDO0FBdkNELHNDQXVDQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixlQUFlLENBQUMsWUFBb0IsRUFBRSxtQkFBa0Q7SUFFdkcsSUFBSSxtQkFBbUIsQ0FBQyxTQUFTLEVBQUU7UUFFbEMsTUFBTSxJQUFJLEdBQUcsZ0JBQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxFQUFFLEdBQUcsbUJBQW1CLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUV6RSxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQzdELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFbkUsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssZUFBZSxDQUFDLE1BQU0sRUFBRTtZQUN4RCxNQUFNLElBQUksS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUM7U0FDckM7UUFFRCxJQUFJLENBQUMsZ0JBQU0sQ0FBQyxlQUFlLENBQUMsaUJBQWlCLEVBQUUsZUFBZSxDQUFDLEVBQUU7WUFDaEUsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1NBQ3JDO1FBRUQsbUJBQW1CLENBQUMsUUFBUSxHQUFHO1lBQzlCLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxFQUFZO1lBQ3JDLFNBQVMsRUFBRSxJQUFJO1NBQ2YsQ0FBQztLQUVGO1NBQU07UUFDTixNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUM7S0FDeEM7QUFFRixDQUFDO0FBM0JELDBDQTJCQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsK0JBQStCLENBQUMsS0FBc0Y7SUFDckksT0FBUSxLQUF1QyxDQUFDLEVBQUUsS0FBSyxTQUFTO1dBQzNELEtBQXVDLENBQUMsWUFBWSxLQUFLLFNBQVM7V0FDbEUsS0FBdUMsQ0FBQyxTQUFTLEtBQUssU0FBUztXQUMvRCxLQUF1QyxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUM7QUFDdEUsQ0FBQztBQUxELDBFQUtDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixpQ0FBaUMsQ0FBQyxLQUE4RDtJQUMvRyxPQUFRLEtBQXlDLENBQUMsUUFBUSxLQUFLLFNBQVMsQ0FBQztBQUMxRSxDQUFDO0FBRkQsOEVBRUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE5LCBGaW5hbmNpYWxGb3JjZS5jb20sIGluY1xuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuICogICBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG4gKlxuICogLSBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gKiAgICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gKiAtIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAqICAgICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuICogICAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cbiAqIC0gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgRmluYW5jaWFsRm9yY2UuY29tLCBpbmMgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzXG4gKiAgICAgIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0XG4gKiAgICAgIHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi5cbiAqXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbiAqICBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTXG4gKiAgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTExcbiAqICBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCxcbiAqICBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFNcbiAqICBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqICBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSlcbiAqICBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqL1xuXG4vKipcbiAqIEBtb2R1bGUgY2xpZW50L3NhbGVzZm9yY2UvaWRlbnRpdHlcbiAqL1xuXG5pbXBvcnQgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5cbmltcG9ydCB7IEFjY2Vzc1Rva2VuUmVzcG9uc2UsIEludHJvc3BlY3Rpb25SZXNwb25zZSB9IGZyb20gJy4uL29hdXRoMic7XG5pbXBvcnQgeyBPcGVuSURBY2Nlc3NUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vb3BlbmlkJztcbmltcG9ydCB7IFNhbGVzZm9yY2VBY2Nlc3NUb2tlblJlc3BvbnNlLCBTYWxlc2ZvcmNlSW50cm9zcGVjdGlvblJlc3BvbnNlIH0gZnJvbSAnLi4vc2FsZXNmb3JjZSc7XG5cbi8qKlxuICogVGhlIFNhbGVzZm9yY2UgVXNlciBJZGVudGl0eSBJbmZvcm1hdGlvbi5cbiAqXG4gKiBUaGlzIGluZm9ybWF0aW9uIGlzIGZvdW5kIGluIHRoZSBbSWRlbnRpdHkgVVJMXShodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vYXJ0aWNsZVZpZXc/aWQ9cmVtb3RlYWNjZXNzX3VzaW5nX29wZW5pZC5odG0jcmVzcG9uc2UpIHJlc3BvbnNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNhbGVzZm9yY2VJZGVudGl0eSB7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgdXNlciBpcyBhY3RpdmUuXG5cdCAqL1xuXHRhY3RpdmU6IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGNpdHkgc3BlY2lmaWVkIGluIHRoZSBhZGRyZXNzIG9mIHRoZSB1c2Vy4oCZcyBzZXR0aW5ncy5cblx0ICovXG5cdGFkZHJfY2l0eTogc3RyaW5nIHwgbnVsbDtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY291bnRyeSBzcGVjaWZpZWQgaW4gdGhlIGFkZHJlc3Mgb2YgdGhlIHVzZXLigJlzIHNldHRpbmdzLlxuXHQgKi9cblx0YWRkcl9jb3VudHJ5OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHN0YXRlIHNwZWNpZmllZCBpbiB0aGUgYWRkcmVzcyBvZiB0aGUgdXNlcuKAmXMgc2V0dGluZy5cblx0ICovXG5cdGFkZHJfc3RhdGU6IHN0cmluZyB8IG51bGw7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHN0cmVldCBzcGVjaWZpZWQgaW4gdGhlIGFkZHJlc3Mgb2YgdGhlIHVzZXLigJlzIHNldHRpbmdzLlxuXHQgKi9cblx0YWRkcl9zdHJlZXQ6IHN0cmluZyB8IG51bGw7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHppcCBvciBwb3N0YWwgY29kZSBzcGVjaWZpZWQgaW4gdGhlIGFkZHJlc3Mgb2YgdGhlIHVzZXLigJlzIHNldHRpbmdzLlxuXHQgKi9cblx0YWRkcl96aXA6IHN0cmluZyB8IG51bGw7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIGFjY2VzcyB0b2tlbiB3YXMgaXNzdWVkIGZvciB0aGlzIGlkZW50aXR5LlxuXHQgKi9cblx0YXNzZXJ0ZWRfdXNlcjogYm9vbGVhbjtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZGlzcGxheSBuYW1lIChmdWxsIG5hbWUpIG9mIHRoZSBxdWVyaWVkIHVzZXIuXG5cdCAqL1xuXHRkaXNwbGF5X25hbWU6IHN0cmluZztcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgdXNlcidzIHByZWZlcnJlZCBlLW1haWwgYWRkcmVzcy5cblx0ICovXG5cdGVtYWlsOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgRW5kLVVzZXIncyBlLW1haWwgYWRkcmVzcyBoYXMgYmVlbiB2ZXJpZmllZDsgb3RoZXJ3aXNlIGZhbHNlLlxuXHQgKi9cblx0ZW1haWxfdmVyaWZpZWQ6IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIFJldHVybiB0aGUgdXNlcidzIGZpcnN0IG5hbWUuXG5cdCAqL1xuXHRmaXJzdF9uYW1lOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIElkZW50aXR5IFVSTCAodGhlIHNhbWUgVVJMIHRoYXQgd2FzIHF1ZXJpZWQpLlxuXHQgKi9cblx0aWQ6IHN0cmluZztcblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoZSB1c2VyIGlzIGEgbGlnaHRuaW5nIGxvZ2luIHVzZXI7XG5cdCAqL1xuXHRpc19saWdodG5pbmdfbG9naW5fdXNlcj86IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHVzZXIncyBsYW5ndWFnZS5cblx0ICovXG5cdGxhbmd1YWdlOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGxhc3QgbW9kaWZpY2F0aW9uIG9mIHRoZSB1c2VyIHJlY29yZC5cblx0ICovXG5cdGxhc3RfbW9kaWZpZWRfZGF0ZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB1c2VyJ3MgbGFzdCBuYW1lLlxuXHQgKi9cblx0bGFzdF9uYW1lOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG1vYmlsZSBwaG9uZSBudW1iZXIgc3BlY2lmaWVkIGluIHRoZSB1c2Vy4oCZcyBzZXR0aW5ncy5cblx0ICovXG5cdG1vYmlsZV9waG9uZTogc3RyaW5nIHwgbnVsbDtcblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoZSB1c2VyIGhhcyB2ZXJpZmllZCB0aGUgbW9iaWxlIHBob25lIG51bWJlci5cblx0ICovXG5cdG1vYmlsZV9waG9uZV92ZXJpZmllZDogYm9vbGVhbjtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgdXNlcidzIENvbW11bml0eSBuaWNrbmFtZS5cblx0ICovXG5cdG5pY2tfbmFtZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB1c2VyJ3Mgb3JnYW5pemF0aW9uIElELlxuXHQgKi9cblx0b3JnYW5pemF0aW9uX2lkOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHVzZXIncyBwcm9maWxlIHBpY3R1cmVzLlxuXHQgKi9cblx0cGhvdG9zOiB7XG5cdFx0W2luZGV4OiBzdHJpbmddOiBzdHJpbmcgfCBudWxsO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB1c2Vy4oCZcyBjdXJyZW50IENoYXR0ZXIgc3RhdHVzLlxuXHQgKi9cblx0c3RhdHVzOiB7XG5cdFx0W2luZGV4OiBzdHJpbmddOiBzdHJpbmcgfCBudWxsO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB0aW1lIHpvbmUgc3BlY2lmaWVkIGluIHRoZSB1c2Vy4oCZcyBzZXR0aW5ncy5cblx0ICovXG5cdHRpbWV6b25lOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIE1hcCBjb250YWluaW5nIHZhcmlvdXMgQVBJIGVuZHBvaW50cyB0aGF0IGNhbiBiZSB1c2VkIHdpdGggdGhlIHNwZWNpZmllZCB1c2VyLlxuXHQgKi9cblx0dXJsczoge1xuXHRcdFtpbmRleDogc3RyaW5nXTogc3RyaW5nIHwgbnVsbDtcblx0fTtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgdXNlcidzIGlkLlxuXHQgKi9cblx0dXNlcl9pZDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB1c2VyJ3MgdXNlciB0eXBlLlxuXHQgKi9cblx0dXNlcl90eXBlOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIFNhbGVzZm9yY2UgdXNlciBuYW1lLlxuXHQgKi9cblx0dXNlcm5hbWU6IHN0cmluZztcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgb2Zmc2V0IGZyb20gVVRDIG9mIHRoZSB0aW1lIHpvbmUgZm9yIHRoZSB1c2VyLCBpbiBtaWxsaXNlY29uZHMuXG5cdCAqL1xuXHR1dGNPZmZzZXQ6IG51bWJlcjtcblxufVxuXG4vKipcbiAqIFRoZSB1c2VyIGluZm9ybWF0aW9uIGdlbmVyYXRlZCB3aGVuIHBhcnNpbmcgdGhlIFtJZGVudGl0eSBVUkxdKGh0dHBzOi8vaGVscC5zYWxlc2ZvcmNlLmNvbS9hcnRpY2xlVmlldz9pZD1yZW1vdGVhY2Nlc3NfdXNpbmdfb3BlbmlkLmh0bSkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVXNlckluZm8ge1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSB1c2VyIElELlxuXHQgKi9cblx0aWQ/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG9yZ2FuaXphdGlvbiBJRC5cblx0ICovXG5cdG9yZ2FuaXphdGlvbklkPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBmdWxsIElkZW50aXR5IFVSTC5cblx0ICovXG5cdHVybDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBJZiB0cnVlLCB0aGUgSWRlbnRpdHkgVVJMIGhhcyBiZWVuIHZhbGlkYXRlZCBhbmQgaXMgdmFsaWQuXG5cdCAqL1xuXHR2YWxpZGF0ZWQ6IGJvb2xlYW47XG5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBVc2VySW5mb1Jlc3BvbnNlIHtcblxuXHQvKipcblx0ICogSWRlbnRpdHkgVVJMIHRoYXQgY2FuIGJlIHVzZWQgdG8gYm90aCBpZGVudGlmeSB0aGUgdXNlciBhbmQgcXVlcnkgZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHVzZXIuXG5cdCAqL1xuXHRpZD86IHN0cmluZztcblxuXHQvKipcblx0ICogU3ViamVjdCAgdGhhdCBjYW4gYmUgdXNlZCB0byBib3RoIGlkZW50aWZ5IHRoZSB1c2VyIGFuZCBxdWVyeSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdXNlci5cblx0ICovXG5cdHN1Yj86IHN0cmluZztcblxuXHQvKipcblx0ICogVGhlIHVzZXIgaW5mb3JtYXRpb24gZ2VuZXJhdGVkIHdoZW4gcGFyc2luZyB0aGUgW0lkZW50aXR5IFVSTF0oaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL2FydGljbGVWaWV3P2lkPXJlbW90ZWFjY2Vzc191c2luZ19vcGVuaWQuaHRtKS5cblx0ICovXG5cdHVzZXJJbmZvPzogVXNlckluZm87XG5cbn1cblxuLyoqXG4gKiBQYXJzZSB0aGUgdXNlciBpbmZvcm1hdGlvbiBmcm9tIHRoZSBgaWRgIHByb3BlcnR5IG9mIGFuIGFjY2VzcyB0b2tlbiByZXNwb25zZS5cbiAqXG4gKiBJdCBpcyBhc3N1bWVkIHRoYXQgdGhlIGBpZGAgY29uZm9ybXMgdG8gdGhlIFNhbGVzZm9yY2UgW0lkZW50aXR5IFVSTF0oaHR0cHM6Ly9oZWxwLnNhbGVzZm9yY2UuY29tL2FydGljbGVWaWV3P2lkPXJlbW90ZWFjY2Vzc191c2luZ19vcGVuaWQuaHRtKSBmb3JtYXQuXG4gKlxuICogQHBhcmFtIHJlc3BvbnNlIFRoZSBTYWxlc2ZvcmNlIHVzZXIgaW5mbyByZXNwb25zZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVXNlckluZm8ocmVzcG9uc2U6IFVzZXJJbmZvUmVzcG9uc2UpIHtcblxuXHRsZXQgaWRlbnRpdHlVcmw6IHN0cmluZztcblx0bGV0IHZhbGlkYXRlZDogYm9vbGVhbjtcblxuXHRpZiAocmVzcG9uc2UuaWQpIHtcblx0XHRpZGVudGl0eVVybCA9IHJlc3BvbnNlLmlkO1xuXHRcdHZhbGlkYXRlZCA9IGZhbHNlO1xuXHR9IGVsc2UgaWYgKHJlc3BvbnNlLnN1Yikge1xuXG5cdFx0aWRlbnRpdHlVcmwgPSByZXNwb25zZS5zdWI7XG5cblx0XHQvLyBUaGlzIHJlc3BvbnNlIGlzIG9idGFpbmVkIHdoZW4gdGhlIHRva2VuIGhhcyBiZWVuIGludHJvc3BlY3RlZC5cblx0XHQvLyBTZXQgdmFsaWRhdGVkIHRvIHRydWUgYXMgdGhlIHRva2VuIGlzIHZhbGlkLlxuXHRcdHZhbGlkYXRlZCA9IHRydWU7XG5cblx0fSBlbHNlIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgc3RyaW5nIHBhcmFtZXRlcjogaWRlbnRpdHlVcmwnKTtcblx0fVxuXG5cdGNvbnN0IGlkVXJscyA9IGlkZW50aXR5VXJsLnNwbGl0KCcvJyk7XG5cdGNvbnN0IGlkID0gaWRVcmxzLnBvcCgpO1xuXHRjb25zdCBvcmdhbml6YXRpb25JZCA9IGlkVXJscy5wb3AoKTtcblxuXHRpZiAoIWlkIHx8IChpZC5sZW5ndGggIT09IDE1ICYmIGlkLmxlbmd0aCAhPT0gMTgpKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIHN0cmluZyBwYXJhbWV0ZXI6IGlkJyk7XG5cdH1cblxuXHRpZiAoIW9yZ2FuaXphdGlvbklkIHx8IChvcmdhbml6YXRpb25JZC5sZW5ndGggIT09IDE1ICYmIG9yZ2FuaXphdGlvbklkLmxlbmd0aCAhPT0gMTgpKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIHN0cmluZyBwYXJhbWV0ZXI6IG9yZ2FuaXphdGlvbklkJyk7XG5cdH1cblxuXHRyZXNwb25zZS51c2VySW5mbyA9IE9iamVjdC5hc3NpZ24oe1xuXHRcdGlkLFxuXHRcdG9yZ2FuaXphdGlvbklkLFxuXHRcdHVybDogaWRlbnRpdHlVcmwsXG5cdFx0dmFsaWRhdGVkXG5cdH0sIHJlc3BvbnNlLnVzZXJJbmZvKTtcblxufVxuXG4vKipcbiAqIFtWZXJpZmllcyB0aGUgc2lnbmF0dXJlXShodHRwczovL2hlbHAuc2FsZXNmb3JjZS5jb20vYXJ0aWNsZVZpZXc/aWQ9cmVtb3RlYWNjZXNzX29hdXRoX3dlYl9zZXJ2ZXJfZmxvdy5odG0jZ3JhbnRfYWNjZXNzX3Rva2VuKSBvZiB0aGUgYWNjZXNzIHRva2VuIHJlc3BvbnNlLlxuICpcbiAqIFVzZWQgdG8gdmVyaWZ5IHRoYXQgdGhlIGlkZW50aXR5IFVSTCBoYXNu4oCZdCBjaGFuZ2VkIHNpbmNlIHRoZSBzZXJ2ZXIgc2VudCBpdC5cbiAqXG4gKiBAcGFyYW0gY2xpZW50U2VjcmV0IFRoZSBjbGllbnQgc2VjcmV0IGZvciB5b3VyIGFwcGxpY2F0aW9uLlxuICogQHBhcmFtIGFjY2Vzc1Rva2VuUmVzcG9uc2UgVGhlIFNhbGVzZm9yY2UgYWNjZXNzIHRva2VuIHJlc3BvbnNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyaWZ5U2lnbmF0dXJlKGNsaWVudFNlY3JldDogc3RyaW5nLCBhY2Nlc3NUb2tlblJlc3BvbnNlOiBTYWxlc2ZvcmNlQWNjZXNzVG9rZW5SZXNwb25zZSkge1xuXG5cdGlmIChhY2Nlc3NUb2tlblJlc3BvbnNlLnNpZ25hdHVyZSkge1xuXG5cdFx0Y29uc3QgaG1hYyA9IGNyeXB0by5jcmVhdGVIbWFjKCdzaGEyNTYnLCBjbGllbnRTZWNyZXQpO1xuXHRcdGhtYWMudXBkYXRlKGAke2FjY2Vzc1Rva2VuUmVzcG9uc2UuaWR9JHthY2Nlc3NUb2tlblJlc3BvbnNlLmlzc3VlZF9hdH1gKTtcblxuXHRcdGNvbnN0IGV4cGVjdGVkU2lnbmF0dXJlID0gQnVmZmVyLmZyb20oaG1hYy5kaWdlc3QoJ2Jhc2U2NCcpKTtcblx0XHRjb25zdCBhY3R1YWxTaWduYXR1cmUgPSBCdWZmZXIuZnJvbShhY2Nlc3NUb2tlblJlc3BvbnNlLnNpZ25hdHVyZSk7XG5cblx0XHRpZiAoZXhwZWN0ZWRTaWduYXR1cmUubGVuZ3RoICE9PSBhY3R1YWxTaWduYXR1cmUubGVuZ3RoKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG5cdFx0fVxuXG5cdFx0aWYgKCFjcnlwdG8udGltaW5nU2FmZUVxdWFsKGV4cGVjdGVkU2lnbmF0dXJlLCBhY3R1YWxTaWduYXR1cmUpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG5cdFx0fVxuXG5cdFx0YWNjZXNzVG9rZW5SZXNwb25zZS51c2VySW5mbyA9IHtcblx0XHRcdHVybDogYWNjZXNzVG9rZW5SZXNwb25zZS5pZCBhcyBzdHJpbmcsXG5cdFx0XHR2YWxpZGF0ZWQ6IHRydWVcblx0XHR9O1xuXG5cdH0gZWxzZSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdObyBzaWduYXR1cmUgcHJlc2VudCcpO1xuXHR9XG5cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIHJlc3BvbnNlIGlzIGEgU2FsZXNmb3JjZSBhY2Nlc3MgdG9rZW4gcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHRva2VuIFRoZSBhY2Nlc3MgdG9rZW4gcmVzcG9uc2UuXG4gKiBAcmV0dXJucyBBIGJvb2xlYW4gaW5kaWNhdGluZyBpZiB0aGlzIHRva2VuIGlzIGEgU2FsZXNmb3JjZSBhY2Nlc3MgdG9rZW4gcmVzcG9uc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1NhbGVzZm9yY2VBY2Nlc3NUb2tlblJlc3BvbnNlKHRva2VuOiBBY2Nlc3NUb2tlblJlc3BvbnNlIHwgT3BlbklEQWNjZXNzVG9rZW5SZXNwb25zZSB8IFNhbGVzZm9yY2VBY2Nlc3NUb2tlblJlc3BvbnNlKTogdG9rZW4gaXMgU2FsZXNmb3JjZUFjY2Vzc1Rva2VuUmVzcG9uc2Uge1xuXHRyZXR1cm4gKHRva2VuIGFzIFNhbGVzZm9yY2VBY2Nlc3NUb2tlblJlc3BvbnNlKS5pZCAhPT0gdW5kZWZpbmVkXG5cdFx0fHwgKHRva2VuIGFzIFNhbGVzZm9yY2VBY2Nlc3NUb2tlblJlc3BvbnNlKS5pbnN0YW5jZV91cmwgIT09IHVuZGVmaW5lZFxuXHRcdHx8ICh0b2tlbiBhcyBTYWxlc2ZvcmNlQWNjZXNzVG9rZW5SZXNwb25zZSkuaXNzdWVkX2F0ICE9PSB1bmRlZmluZWRcblx0XHR8fCAodG9rZW4gYXMgU2FsZXNmb3JjZUFjY2Vzc1Rva2VuUmVzcG9uc2UpLnNpZ25hdHVyZSAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciB0aGUgcmVzcG9uc2UgaXMgYSBTYWxlc2ZvcmNlIGludHJvc3BlY3Rpb24gcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHRva2VuIFRoZSBpbnRyb3NwZWN0aW9uIHJlc3BvbnNlLlxuICogQHJldHVybnMgQSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhpcyB0b2tlbiBpcyBhIFNhbGVzZm9yY2UgaW50cm9zcGVjdGlvbiByZXNwb25zZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2FsZXNmb3JjZUludHJvc3BlY3Rpb25SZXNwb25zZSh0b2tlbjogSW50cm9zcGVjdGlvblJlc3BvbnNlIHwgU2FsZXNmb3JjZUludHJvc3BlY3Rpb25SZXNwb25zZSk6IHRva2VuIGlzIFNhbGVzZm9yY2VJbnRyb3NwZWN0aW9uUmVzcG9uc2Uge1xuXHRyZXR1cm4gKHRva2VuIGFzIFNhbGVzZm9yY2VJbnRyb3NwZWN0aW9uUmVzcG9uc2UpLnVzZXJJbmZvICE9PSB1bmRlZmluZWQ7XG59XG4iXX0=