@financialforcedev/orizuru-auth
Version:
Salesforce authentication for Heroku Node applications.
131 lines • 17.1 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 __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("../..");
const identity_1 = require("../client/salesforce/identity");
const jwtBearerToken_1 = require("../flow/jwtBearerToken");
const accessToken_1 = require("./common/accessToken");
const fail_1 = require("./common/fail");
/**
* Returns an express middleware that checks that an access token can be retrieved
* for the user specified on the request.
*
* Should be used in tandem with the tokenValidator middleware, and must be
* executed after that. This requires that a ConnectedApp is configured to pre-
* authorise users and the user is authorised.
*
* @fires EVENT_GRANT_CHECKED, EVENT_DENIED
* @param app The Orizuru server instance.
* @param [provider] The name of the auth provider. Defaults to 'salesforce'.
* @param [params] The grant checker middleware parameters.
* @param [opts] The optional parameters used when requesting grants.
* @returns A express middleware that checks an access token can be retrieved for
* the user on the request.
*/
function createMiddleware(app, provider, params, opts) {
const internalProvider = provider || 'salesforce';
const internalParams = params || app.options.openid[internalProvider];
const _a = opts || accessToken_1.DEFAULT_MIDDLEWARE_OPTIONS, { setTokenOnContext } = _a, grantOptions = __rest(_a, ["setTokenOnContext"]);
const requestAccessToken = jwtBearerToken_1.createTokenGrantor(app.options.authProvider[internalProvider]);
// The GrantCheckerMiddlewareParameters type excludes the grant_type
// so that it doesn't have to be set by the caller. Make sure it is set here.
const grantParams = Object.assign({}, internalParams);
grantParams.grantType = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
return async function checkUserGrant(req, res, next) {
try {
const user = checkUserIsOnTheRequest(req);
const tokenResponse = await requestAccessToken(Object.assign({}, grantParams, { user }), grantOptions);
setGrant(app, req);
accessToken_1.setAccessTokenOnRequest(req, tokenResponse.access_token, setTokenOnContext);
setInstanceUrlOnRequest(req, tokenResponse);
next();
}
catch (error) {
fail_1.fail(app, error, req, res, next);
}
};
}
exports.createMiddleware = createMiddleware;
/**
* Checks that the user is present on the request and is valid.
*
* @param req The HTTP request.
*/
function checkUserIsOnTheRequest(req) {
if (!req.orizuru) {
throw new Error('Missing required object parameter: orizuru');
}
if (!req.orizuru.user) {
throw new Error('Missing required object parameter: orizuru[user]');
}
if (req.orizuru.user.username == null) {
throw new Error('Missing required string parameter: orizuru[user][username]');
}
if (!req.orizuru.user.username.length) {
throw new Error('Invalid parameter: orizuru[user][username] cannot be empty');
}
return req.orizuru.user;
}
/**
* Sets the grant checked boolean on the Orizuru context.
*
* @fires EVENT_GRANT_CHECKED
* @param app The Orizuru server instance.
* @param req The HTTP request.
*/
function setGrant(app, req) {
const orizuru = req.orizuru;
orizuru.grantChecked = true;
app.emit(__1.EVENT_GRANT_CHECKED, `Grant checked for user (${orizuru.user.username}) [${req.ip}].`);
}
/**
* Sets the instance URL on the Orizuru context.
*
* @param req The HTTP request.
* @param accessTokenResponse The access token response
*/
function setInstanceUrlOnRequest(req, accessTokenResponse) {
if (!identity_1.isSalesforceAccessTokenResponse(accessTokenResponse)) {
return;
}
const orizuru = req.orizuru;
orizuru.salesforce = orizuru.salesforce || {};
orizuru.salesforce.instanceUrl = accessTokenResponse.instance_url;
}
exports.setInstanceUrlOnRequest = setInstanceUrlOnRequest;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JhbnRDaGVja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2luZGV4L21pZGRsZXdhcmUvZ3JhbnRDaGVja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHOzs7Ozs7Ozs7Ozs7O0FBUUgsNkJBQWlHO0FBRWpHLDREQUFnRjtBQUNoRiwyREFBNEQ7QUFDNUQsc0RBQThHO0FBQzlHLHdDQUFxQztBQUVyQzs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxHQUFvQixFQUFFLFFBQWlCLEVBQUUsTUFBOEIsRUFBRSxJQUF1QztJQUVoSixNQUFNLGdCQUFnQixHQUFHLFFBQVEsSUFBSSxZQUFZLENBQUM7SUFDbEQsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDdEUsTUFBTSxxREFBMkUsRUFBM0UsRUFBRSxpQkFBaUIsT0FBd0QsRUFBdEQsZ0RBQXNELENBQUM7SUFFbEYsTUFBTSxrQkFBa0IsR0FBRyxtQ0FBa0IsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFFMUYsb0VBQW9FO0lBQ3BFLDZFQUE2RTtJQUM3RSxNQUFNLFdBQVcsR0FBNEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDL0UsV0FBVyxDQUFDLFNBQVMsR0FBRyw2Q0FBNkMsQ0FBQztJQUV0RSxPQUFPLEtBQUssVUFBVSxjQUFjLENBQUMsR0FBWSxFQUFFLEdBQWEsRUFBRSxJQUFrQjtRQUVuRixJQUFJO1lBRUgsTUFBTSxJQUFJLEdBQUcsdUJBQXVCLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFMUMsTUFBTSxhQUFhLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBbUIsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUV6SCxRQUFRLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ25CLHFDQUF1QixDQUFDLEdBQUcsRUFBRSxhQUFhLENBQUMsWUFBWSxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFDNUUsdUJBQXVCLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBRTVDLElBQUksRUFBRSxDQUFDO1NBRVA7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNmLFdBQUksQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDakM7SUFFRixDQUFDLENBQUM7QUFFSCxDQUFDO0FBakNELDRDQWlDQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLHVCQUF1QixDQUFDLEdBQVk7SUFFNUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUU7UUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO0tBQzlEO0lBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFO1FBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELENBQUMsQ0FBQztLQUNwRTtJQUVELElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksRUFBRTtRQUN0QyxNQUFNLElBQUksS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUM7S0FDOUU7SUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRTtRQUN0QyxNQUFNLElBQUksS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUM7S0FDOUU7SUFFRCxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0FBRXpCLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLFFBQVEsQ0FBQyxHQUFvQixFQUFFLEdBQVk7SUFFbkQsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLE9BQVEsQ0FBQztJQUM3QixPQUFPLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztJQUU1QixHQUFHLENBQUMsSUFBSSxDQUFDLHVCQUFtQixFQUFFLDJCQUEyQixPQUFPLENBQUMsSUFBSyxDQUFDLFFBQVEsTUFBTSxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUVsRyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQix1QkFBdUIsQ0FBQyxHQUFZLEVBQUUsbUJBQXdDO0lBRTdGLElBQUksQ0FBQywwQ0FBK0IsQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFO1FBQzFELE9BQU87S0FDUDtJQUVELE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxPQUFRLENBQUM7SUFDN0IsT0FBTyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztJQUM5QyxPQUFPLENBQUMsVUFBVSxDQUFDLFdBQVcsR0FBRyxtQkFBbUIsQ0FBQyxZQUFZLENBQUM7QUFFbkUsQ0FBQztBQVZELDBEQVVDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOSwgRmluYW5jaWFsRm9yY2UuY29tLCBpbmNcbiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbiAqICAgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuICpcbiAqIC0gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICogICAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICogLSBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gKiAgICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiAqICAgICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKiAtIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIEZpbmFuY2lhbEZvcmNlLmNvbSwgaW5jIG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9yc1xuICogICAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dFxuICogICAgICBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG4gKiAgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFU1xuICogIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMXG4gKiAgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsXG4gKiAgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTXG4gKiAgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZXG4gKiAgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpXG4gKiAgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKi9cblxuLyoqXG4gKiBAbW9kdWxlIG1pZGRsZXdhcmUvZ3JhbnRDaGVja2VyXG4gKi9cblxuaW1wb3J0IHsgTmV4dEZ1bmN0aW9uLCBSZXF1ZXN0LCBSZXF1ZXN0SGFuZGxlciwgUmVzcG9uc2UgfSBmcm9tICdAZmluYW5jaWFsZm9yY2VkZXYvb3JpenVydSc7XG5cbmltcG9ydCB7IEVWRU5UX0dSQU5UX0NIRUNLRUQsIEdyYW50T3B0aW9ucywgSnd0R3JhbnRQYXJhbXMsIEp3dFRva2VuR3JhbnRvclBhcmFtcyB9IGZyb20gJy4uLy4uJztcbmltcG9ydCB7IEFjY2Vzc1Rva2VuUmVzcG9uc2UgfSBmcm9tICcuLi9jbGllbnQvb2F1dGgyJztcbmltcG9ydCB7IGlzU2FsZXNmb3JjZUFjY2Vzc1Rva2VuUmVzcG9uc2UgfSBmcm9tICcuLi9jbGllbnQvc2FsZXNmb3JjZS9pZGVudGl0eSc7XG5pbXBvcnQgeyBjcmVhdGVUb2tlbkdyYW50b3IgfSBmcm9tICcuLi9mbG93L2p3dEJlYXJlclRva2VuJztcbmltcG9ydCB7IERFRkFVTFRfTUlERExFV0FSRV9PUFRJT05TLCBNaWRkbGV3YXJlT3B0aW9ucywgc2V0QWNjZXNzVG9rZW5PblJlcXVlc3QgfSBmcm9tICcuL2NvbW1vbi9hY2Nlc3NUb2tlbic7XG5pbXBvcnQgeyBmYWlsIH0gZnJvbSAnLi9jb21tb24vZmFpbCc7XG5cbi8qKlxuICogUmV0dXJucyBhbiBleHByZXNzIG1pZGRsZXdhcmUgdGhhdCBjaGVja3MgdGhhdCBhbiBhY2Nlc3MgdG9rZW4gY2FuIGJlIHJldHJpZXZlZFxuICogZm9yIHRoZSB1c2VyIHNwZWNpZmllZCBvbiB0aGUgcmVxdWVzdC5cbiAqXG4gKiBTaG91bGQgYmUgdXNlZCBpbiB0YW5kZW0gd2l0aCB0aGUgdG9rZW5WYWxpZGF0b3IgbWlkZGxld2FyZSwgYW5kIG11c3QgYmVcbiAqIGV4ZWN1dGVkIGFmdGVyIHRoYXQuIFRoaXMgcmVxdWlyZXMgdGhhdCBhIENvbm5lY3RlZEFwcCBpcyBjb25maWd1cmVkIHRvIHByZS1cbiAqIGF1dGhvcmlzZSB1c2VycyBhbmQgdGhlIHVzZXIgaXMgYXV0aG9yaXNlZC5cbiAqXG4gKiBAZmlyZXMgRVZFTlRfR1JBTlRfQ0hFQ0tFRCwgRVZFTlRfREVOSUVEXG4gKiBAcGFyYW0gYXBwIFRoZSBPcml6dXJ1IHNlcnZlciBpbnN0YW5jZS5cbiAqIEBwYXJhbSBbcHJvdmlkZXJdIFRoZSBuYW1lIG9mIHRoZSBhdXRoIHByb3ZpZGVyLiBEZWZhdWx0cyB0byAnc2FsZXNmb3JjZScuXG4gKiBAcGFyYW0gW3BhcmFtc10gVGhlIGdyYW50IGNoZWNrZXIgbWlkZGxld2FyZSBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIFtvcHRzXSBUaGUgb3B0aW9uYWwgcGFyYW1ldGVycyB1c2VkIHdoZW4gcmVxdWVzdGluZyBncmFudHMuXG4gKiBAcmV0dXJucyBBIGV4cHJlc3MgbWlkZGxld2FyZSB0aGF0IGNoZWNrcyBhbiBhY2Nlc3MgdG9rZW4gY2FuIGJlIHJldHJpZXZlZCBmb3JcbiAqIHRoZSB1c2VyIG9uIHRoZSByZXF1ZXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWlkZGxld2FyZShhcHA6IE9yaXp1cnUuSVNlcnZlciwgcHJvdmlkZXI/OiBzdHJpbmcsIHBhcmFtcz86IEp3dFRva2VuR3JhbnRvclBhcmFtcywgb3B0cz86IE1pZGRsZXdhcmVPcHRpb25zICYgR3JhbnRPcHRpb25zKTogUmVxdWVzdEhhbmRsZXIge1xuXG5cdGNvbnN0IGludGVybmFsUHJvdmlkZXIgPSBwcm92aWRlciB8fCAnc2FsZXNmb3JjZSc7XG5cdGNvbnN0IGludGVybmFsUGFyYW1zID0gcGFyYW1zIHx8IGFwcC5vcHRpb25zLm9wZW5pZFtpbnRlcm5hbFByb3ZpZGVyXTtcblx0Y29uc3QgeyBzZXRUb2tlbk9uQ29udGV4dCwgLi4uZ3JhbnRPcHRpb25zIH0gPSBvcHRzIHx8IERFRkFVTFRfTUlERExFV0FSRV9PUFRJT05TO1xuXG5cdGNvbnN0IHJlcXVlc3RBY2Nlc3NUb2tlbiA9IGNyZWF0ZVRva2VuR3JhbnRvcihhcHAub3B0aW9ucy5hdXRoUHJvdmlkZXJbaW50ZXJuYWxQcm92aWRlcl0pO1xuXG5cdC8vIFRoZSBHcmFudENoZWNrZXJNaWRkbGV3YXJlUGFyYW1ldGVycyB0eXBlIGV4Y2x1ZGVzIHRoZSBncmFudF90eXBlXG5cdC8vIHNvIHRoYXQgaXQgZG9lc24ndCBoYXZlIHRvIGJlIHNldCBieSB0aGUgY2FsbGVyLiBNYWtlIHN1cmUgaXQgaXMgc2V0IGhlcmUuXG5cdGNvbnN0IGdyYW50UGFyYW1zOiBQYXJ0aWFsPEp3dEdyYW50UGFyYW1zPiA9IE9iamVjdC5hc3NpZ24oe30sIGludGVybmFsUGFyYW1zKTtcblx0Z3JhbnRQYXJhbXMuZ3JhbnRUeXBlID0gJ3VybjppZXRmOnBhcmFtczpvYXV0aDpncmFudC10eXBlOmp3dC1iZWFyZXInO1xuXG5cdHJldHVybiBhc3luYyBmdW5jdGlvbiBjaGVja1VzZXJHcmFudChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikge1xuXG5cdFx0dHJ5IHtcblxuXHRcdFx0Y29uc3QgdXNlciA9IGNoZWNrVXNlcklzT25UaGVSZXF1ZXN0KHJlcSk7XG5cblx0XHRcdGNvbnN0IHRva2VuUmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0QWNjZXNzVG9rZW4oT2JqZWN0LmFzc2lnbih7fSwgZ3JhbnRQYXJhbXMsIHsgdXNlciB9KSBhcyBKd3RHcmFudFBhcmFtcywgZ3JhbnRPcHRpb25zKTtcblxuXHRcdFx0c2V0R3JhbnQoYXBwLCByZXEpO1xuXHRcdFx0c2V0QWNjZXNzVG9rZW5PblJlcXVlc3QocmVxLCB0b2tlblJlc3BvbnNlLmFjY2Vzc190b2tlbiwgc2V0VG9rZW5PbkNvbnRleHQpO1xuXHRcdFx0c2V0SW5zdGFuY2VVcmxPblJlcXVlc3QocmVxLCB0b2tlblJlc3BvbnNlKTtcblxuXHRcdFx0bmV4dCgpO1xuXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGZhaWwoYXBwLCBlcnJvciwgcmVxLCByZXMsIG5leHQpO1xuXHRcdH1cblxuXHR9O1xuXG59XG5cbi8qKlxuICogQ2hlY2tzIHRoYXQgdGhlIHVzZXIgaXMgcHJlc2VudCBvbiB0aGUgcmVxdWVzdCBhbmQgaXMgdmFsaWQuXG4gKlxuICogQHBhcmFtIHJlcSBUaGUgSFRUUCByZXF1ZXN0LlxuICovXG5mdW5jdGlvbiBjaGVja1VzZXJJc09uVGhlUmVxdWVzdChyZXE6IFJlcXVlc3QpIHtcblxuXHRpZiAoIXJlcS5vcml6dXJ1KSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIG9iamVjdCBwYXJhbWV0ZXI6IG9yaXp1cnUnKTtcblx0fVxuXG5cdGlmICghcmVxLm9yaXp1cnUudXNlcikge1xuXHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBvYmplY3QgcGFyYW1ldGVyOiBvcml6dXJ1W3VzZXJdJyk7XG5cdH1cblxuXHRpZiAocmVxLm9yaXp1cnUudXNlci51c2VybmFtZSA9PSBudWxsKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIHN0cmluZyBwYXJhbWV0ZXI6IG9yaXp1cnVbdXNlcl1bdXNlcm5hbWVdJyk7XG5cdH1cblxuXHRpZiAoIXJlcS5vcml6dXJ1LnVzZXIudXNlcm5hbWUubGVuZ3RoKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhcmFtZXRlcjogb3JpenVydVt1c2VyXVt1c2VybmFtZV0gY2Fubm90IGJlIGVtcHR5Jyk7XG5cdH1cblxuXHRyZXR1cm4gcmVxLm9yaXp1cnUudXNlcjtcblxufVxuXG4vKipcbiAqIFNldHMgdGhlIGdyYW50IGNoZWNrZWQgYm9vbGVhbiBvbiB0aGUgT3JpenVydSBjb250ZXh0LlxuICpcbiAqIEBmaXJlcyBFVkVOVF9HUkFOVF9DSEVDS0VEXG4gKiBAcGFyYW0gYXBwIFRoZSBPcml6dXJ1IHNlcnZlciBpbnN0YW5jZS5cbiAqIEBwYXJhbSByZXEgVGhlIEhUVFAgcmVxdWVzdC5cbiAqL1xuZnVuY3Rpb24gc2V0R3JhbnQoYXBwOiBPcml6dXJ1LklTZXJ2ZXIsIHJlcTogUmVxdWVzdCkge1xuXG5cdGNvbnN0IG9yaXp1cnUgPSByZXEub3JpenVydSE7XG5cdG9yaXp1cnUuZ3JhbnRDaGVja2VkID0gdHJ1ZTtcblxuXHRhcHAuZW1pdChFVkVOVF9HUkFOVF9DSEVDS0VELCBgR3JhbnQgY2hlY2tlZCBmb3IgdXNlciAoJHtvcml6dXJ1LnVzZXIhLnVzZXJuYW1lfSkgWyR7cmVxLmlwfV0uYCk7XG5cbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBpbnN0YW5jZSBVUkwgb24gdGhlIE9yaXp1cnUgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0gcmVxIFRoZSBIVFRQIHJlcXVlc3QuXG4gKiBAcGFyYW0gYWNjZXNzVG9rZW5SZXNwb25zZSBUaGUgYWNjZXNzIHRva2VuIHJlc3BvbnNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRJbnN0YW5jZVVybE9uUmVxdWVzdChyZXE6IFJlcXVlc3QsIGFjY2Vzc1Rva2VuUmVzcG9uc2U6IEFjY2Vzc1Rva2VuUmVzcG9uc2UpIHtcblxuXHRpZiAoIWlzU2FsZXNmb3JjZUFjY2Vzc1Rva2VuUmVzcG9uc2UoYWNjZXNzVG9rZW5SZXNwb25zZSkpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRjb25zdCBvcml6dXJ1ID0gcmVxLm9yaXp1cnUhO1xuXHRvcml6dXJ1LnNhbGVzZm9yY2UgPSBvcml6dXJ1LnNhbGVzZm9yY2UgfHwge307XG5cdG9yaXp1cnUuc2FsZXNmb3JjZS5pbnN0YW5jZVVybCA9IGFjY2Vzc1Rva2VuUmVzcG9uc2UuaW5zdGFuY2VfdXJsO1xuXG59XG4iXX0=