passport-tidal
Version:
PassportJS Login/Signup for TIDAL
188 lines (159 loc) • 20.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; // Load modules.
var _passportOauth = require('passport-oauth2');
var _passportOauth2 = _interopRequireDefault(_passportOauth);
var _tidalTokenError = require('./errors/tidalTokenError');
var _tidalTokenError2 = _interopRequireDefault(_tidalTokenError);
var _util = require('util');
var _util2 = _interopRequireDefault(_util);
var _url = require('url');
var _url2 = _interopRequireDefault(_url);
var _user = require('./models/user');
var _user2 = _interopRequireDefault(_user);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* `Strategy` constructor.
*
* The Tidal authentication strategy authenticates requests by delegating to
* Tidal using the OAuth2 protocol.
*
* Applications must supply a `verify` callback which accepts a `token`,
* and service-specific `profile`, and then calls the `cb` callback supplying
* a `user`, which should be set to `false` if the credentials are not valid.
* If an exception occured, `err` should be set.
*
* Options:
* - `clientID` identifies client to Tidal
* - `clientSecret` secret used to establish ownership of the consumer key
* - `callbackURL` URL to which Tidal will redirect the user after obtaining authorization
*
* Examples:
* passport.use(new TidalStrategy({
* clientID: '123-456-789',
* clientSecret: 'shhh-its-a-secret'
* callbackURL: 'https://www.example.net/auth/tidal/callback'
* },
* function(token, profile, cb) {
* User.findOrCreate(..., function (err, user) {
* cb(err, user);
* });
* }
* ));
*
* @constructor
* @param {object} options
* @param {function} verify
* @access public
*/
function Strategy(options, verify) {
options = options || {};
options.authorizationURL = options.authorizationURL || 'https://login.tidal.com/authorize';
options.tokenURL = options.tokenURL || 'https://login.tidal.com/oauth2/token';
_passportOauth2.default.call(this, options, verify);
this.name = 'tidal';
this._userProfileURL = options.userProfileURL || 'https://login.tidal.com/oauth2/user';
}
// Inherit from `OAuth2Strategy`.
_util2.default.inherits(Strategy, _passportOauth2.default);
/**
* Authenticate request by delegating to Tidal using OAuth.
*
* @param {http.IncomingMessage} req
* @param {object} [options]
* @access protected
*/
Strategy.prototype.authenticate = function (req, options) {
if (req.query && req.query.denied) {
return this.fail();
}
if (req.session && req.session.lang) {
// if the lang is there as a query param, replace
if (this._oauth2._authorizeUrl.includes('lang=')) {
// getting the starting index of the language in order to override
var indexOfLang = this._oauth2._authorizeUrl.indexOf('lang=');
var baseUrl = this._oauth2._authorizeUrl;
this._oauth2._authorizeUrl = baseUrl.substr(0, indexOfLang + 5) + req.session.lang + baseUrl.substr(indexOfLang + 5 + req.session.lang.length);
} else {
this._oauth2._authorizeUrl = this._oauth2._authorizeUrl + '?lang=' + req.session.lang;
}
}
if (req.session && req.session.amplitudeDeviceId) {
// if the lang is there as a query param, replace
if (this._oauth2._authorizeUrl.includes('amplitudeDeviceId=')) {
// getting the starting index of the language in order to override
var indexOfamplitudeDeviceId = this._oauth2._authorizeUrl.indexOf('amplitudeDeviceId=');
var _baseUrl = this._oauth2._authorizeUrl;
this._oauth2._authorizeUrl = _baseUrl.substr(0, indexOfamplitudeDeviceId + 18) + req.session.amplitudeDeviceId + _baseUrl.substr(indexOfamplitudeDeviceId + 18 + req.session.amplitudeDeviceId.length);
} else {
if (req.session.lang) {
this._oauth2._authorizeUrl = this._oauth2._authorizeUrl + '&litudeDeviceId=' + req.session.amplitudeDeviceId;
} else {
this._oauth2._authorizeUrl = this._oauth2._authorizeUrl + '?amplitudeDeviceId=' + req.session.amplitudeDeviceId;
}
}
}
// Call the base class for standard OAuth2 authentication.
_passportOauth2.default.prototype.authenticate.call(this, req, options);
};
/**
* Retrieve user profile from Tidal.
*
* This function constructs a normalized profile, with the following properties:
*
* - `id` (equivalent to `user_id`)
* - `username` (equivalent to `screen_name`)
*
* @param {string} token
* @param {function} done
* @access protected
*/
Strategy.prototype.userProfile = function (token, done) {
var json = void 0;
var url = _url2.default.parse(this._userProfileURL);
this._oauth2.get(_url2.default.format(url), token, function (err, body) {
if (err) {
if (err.data) {
try {
json = JSON.parse(err.data);
} catch (_) {
return done(new _passportOauth2.default.InternalOAuthError('Failed to fetch user profile', err));
}
}
if (json && json.errors && json.errors.length) {
var e = json.errors[0];
// return done(new APIError(e.message, e.code));
return done(new _passportOauth2.default.InternalOAuthError('Failed to fetch user profile', e));
}
return done(new _passportOauth2.default.InternalOAuthError('Failed to fetch user profile', err));
}
try {
json = JSON.parse(body);
} catch (ex) {
return done(new Error('Failed to parse user profile'));
}
var user = new _user2.default(json);
user._raw = body;
done(null, user);
});
};
/**
* Parse error response from Tidal OAuth2 endpoint.
*
* @param {string} body
* @param {number} status
* @return {Error}
* @access protected
*/
Strategy.prototype.parseErrorResponse = function (body) {
var json = JSON.parse(body);
if (json.error && _typeof(json.error) == 'object') {
return new _tidalTokenError2.default(json.error.message, json.error.type, json.error.code);
}
return _passportOauth2.default.prototype.parseErrorResponse.call(this, body, status);
};
// Expose constructor.
exports.default = Strategy;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0cmF0ZWd5LmpzIl0sIm5hbWVzIjpbIlN0cmF0ZWd5Iiwib3B0aW9ucyIsInZlcmlmeSIsImF1dGhvcml6YXRpb25VUkwiLCJ0b2tlblVSTCIsImNhbGwiLCJuYW1lIiwiX3VzZXJQcm9maWxlVVJMIiwidXNlclByb2ZpbGVVUkwiLCJpbmhlcml0cyIsInByb3RvdHlwZSIsImF1dGhlbnRpY2F0ZSIsInJlcSIsInF1ZXJ5IiwiZGVuaWVkIiwiZmFpbCIsInNlc3Npb24iLCJsYW5nIiwiX29hdXRoMiIsIl9hdXRob3JpemVVcmwiLCJpbmNsdWRlcyIsImluZGV4T2ZMYW5nIiwiaW5kZXhPZiIsImJhc2VVcmwiLCJzdWJzdHIiLCJsZW5ndGgiLCJhbXBsaXR1ZGVEZXZpY2VJZCIsImluZGV4T2ZhbXBsaXR1ZGVEZXZpY2VJZCIsInVzZXJQcm9maWxlIiwidG9rZW4iLCJkb25lIiwianNvbiIsInVybCIsInBhcnNlIiwiZ2V0IiwiZm9ybWF0IiwiZXJyIiwiYm9keSIsImRhdGEiLCJKU09OIiwiXyIsIkludGVybmFsT0F1dGhFcnJvciIsImVycm9ycyIsImUiLCJleCIsIkVycm9yIiwidXNlciIsIl9yYXciLCJwYXJzZUVycm9yUmVzcG9uc2UiLCJlcnJvciIsIm1lc3NhZ2UiLCJ0eXBlIiwiY29kZSIsInN0YXR1cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OzhRQUFBOzs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWtDQSxTQUFTQSxRQUFULENBQWtCQyxPQUFsQixFQUEyQkMsTUFBM0IsRUFBbUM7QUFDL0JELGNBQVVBLFdBQVcsRUFBckI7QUFDQUEsWUFBUUUsZ0JBQVIsR0FBMkJGLFFBQVFFLGdCQUFSLElBQTRCLG1DQUF2RDtBQUNBRixZQUFRRyxRQUFSLEdBQW1CSCxRQUFRRyxRQUFSLElBQW9CLHNDQUF2QztBQUNBLDRCQUFlQyxJQUFmLENBQW9CLElB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Q0Q7O0FBbUNBOzs7Ozs7OztBQVFBOUMsU0FBU1UsU0FBVCxDQUFtQnNDLGtCQUFuQixHQUF3QyxVQUFTWCxJQUFULEVBQXVCO0FBQzNELFFBQUlOLE9BQU9RLEtBQUtOLEtBQUwsQ0FBV0ksSUFBWCxDQUFYO0FBQ0EsUUFBSU4sS0FBS2tCLEtBQUwsSUFBYyxRQUFPbEIsS0FBS2tCLEtBQVosS0FBcUIsUUFBdkMsRUFBaUQ7QUFDN0MsZUFBTyw4QkFBb0JsQixLQUFLa0IsS0FBTCxDQUFXQyxPQUEvQixFQUF3Q25CLEtBQUtrQixLQUFMLENBQVdFLElBQW5ELEVBQXlEcEIsS0FBS2tCLEtBQUwsQ0FBV0csSUFBcEUsQ0FBUDtBQUNIO0FBQ0QsV0FBTyx3QkFBZTFDLFNBQWYsQ0FBeUJzQyxrQkFBekIsQ0FBNEMzQyxJQUE1QyxDQUFpRCxJQUFqRCxFQUF1RGdDLElBQXZELEVBQTZEZ0IsTUFBN0QsQ0FBUDtBQUNILENBTkQ7O0FBUUE7a0JBQ2VyRCxRIiwiZmlsZSI6InN0cmF0ZWd5LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTG9hZCBtb2R1bGVzLlxyXG5pbXBvcnQgT0F1dGgyU3RyYXRlZ3kgZnJvbSAncGFzc3BvcnQtb2F1dGgyJztcclxuaW1wb3J0IFRpZGFsVG9rZW5FcnJvciBmcm9tICcuL2Vycm9ycy90aWRhbFRva2VuRXJyb3InO1xyXG5pbXBvcnQgdXRpbCBmcm9tICd1dGlsJztcclxuaW1wb3J0IHVyaSBmcm9tICd1cmwnO1xyXG5pbXBvcnQgVXNlciBmcm9tICcuL21vZGVscy91c2VyJztcclxuXHJcbi8qKlxyXG4qIGBTdHJhdGVneWAgY29uc3RydWN0b3IuXHJcbipcclxuKiBUaGUgVGlkYWwgYXV0aGVudGljYXRpb24gc3RyYXRlZ3kgYXV0aGVudGljYXRlcyByZXF1ZXN0cyBieSBkZWxlZ2F0aW5nIHRvXHJcbiogVGlkYWwgdXNpbmcgdGhlIE9BdXRoMiBwcm90b2NvbC5cclxuKlxyXG4qIEFwcGxpY2F0aW9ucyBtdXN0IHN1cHBseSBhIGB2ZXJpZnlgIGNhbGxiYWNrIHdoaWNoIGFjY2VwdHMgYSBgdG9rZW5gLFxyXG4qIGFuZCBzZXJ2aWNlLXNwZWNpZmljIGBwcm9maWxlYCwgYW5kIHRoZW4gY2FsbHMgdGhlIGBjYmAgY2FsbGJhY2sgc3VwcGx5aW5nXHJcbiogYSBgdXNlcmAsIHdoaWNoIHNob3VsZCBiZSBzZXQgdG8gYGZhbHNlYCBpZiB0aGUgY3JlZGVudGlhbHMgYXJlIG5vdCB2YWxpZC5cclxuKiBJZiBhbiBleGNlcHRpb24gb2NjdXJlZCwgYGVycmAgc2hvdWxkIGJlIHNldC5cclxuKlxyXG4qIE9wdGlvbnM6XHJcbiogICAtIGBjbGllbnRJRGAgICAgIGlkZW50aWZpZXMgY2xpZW50IHRvIFRpZGFsXHJcbiogICAtIGBjbGllbnRTZWNyZXRgICBzZWNyZXQgdXNlZCB0byBlc3RhYmxpc2ggb3duZXJzaGlwIG9mIHRoZSBjb25zdW1lciBrZXlcclxuKiAgIC0gYGNhbGxiYWNrVVJMYCAgICAgVVJMIHRvIHdoaWNoIFRpZGFsIHdpbGwgcmVkaXJlY3QgdGhlIHVzZXIgYWZ0ZXIgb2J0YWluaW5nIGF1dGhvcml6YXRpb25cclxuKlxyXG4qIEV4YW1wbGVzOlxyXG4qICAgICBwYXNzcG9ydC51c2UobmV3IFRpZGFsU3RyYXRlZ3koe1xyXG4qICAgICAgICAgY2xpZW50SUQ6ICcxMjMtNDU2LTc4OScsXHJcbiogICAgICAgICBjbGllbnRTZWNyZXQ6ICdzaGhoLWl0cy1hLXNlY3JldCdcclxuKiAgICAgICAgIGNhbGxiYWNrVVJMOiAnaHR0cHM6Ly93d3cuZXhhbXBsZS5uZXQvYXV0aC90aWRhbC9jYWxsYmFjaydcclxuKiAgICAgICB9LFxyXG4qICAgICAgIGZ1bmN0aW9uKHRva2VuLCBwcm9maWxlLCBjYikge1xyXG4qICAgICAgICAgVXNlci5maW5kT3JDcmVhdGUoLi4uLCBmdW5jdGlvbiAoZXJyLCB1c2VyKSB7XHJcbiogICAgICAgICAgIGNiKGVyciwgdXNlcik7XHJcbiogICAgICAgICB9KTtcclxuKiAgICAgICB9XHJcbiogICAgICkpO1xyXG4qXHJcbiogQGNvbnN0cnVjdG9yXHJcbiogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcclxuKiBAcGFyYW0ge2Z1bmN0aW9ufSB2ZXJpZnlcclxuKiBAYWNjZXNzIHB1YmxpY1xyXG4qL1xyXG5mdW5jdGlvbiBTdHJhdGVneShvcHRpb25zLCB2ZXJpZnkpIHtcclxuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG4gICAgb3B0aW9ucy5hdXRob3JpemF0aW9uVVJMID0gb3B0aW9ucy5hdXRob3JpemF0aW9uVVJMIHx8ICdodHRwczovL2xvZ2luLnRpZGFsLmNvbS9hdXRob3JpemUnO1xyXG4gICAgb3B0aW9ucy50b2tlblVSTCA9IG9wdGlvbnMudG9rZW5VUkwgfHwgJ2h0dHBzOi8vbG9naW4udGlkYWwuY29tL29hdXRoMi90b2tlbic7XHJcbiAgICBPQXV0aDJTdHJhdGVneS5jYWxsKHRoaXMsIG9wdGlvbnMsIHZlcmlmeSk7XHJcbiAgICB0aGlzLm5hbWUgPSAndGlkYWwnO1xyXG4gICAgdGhpcy5fdXNlclByb2ZpbGVVUkwgPSBvcHRpb25zLnVzZXJQcm9maWxlVVJMIHx8ICdodHRwczovL2xvZ2luLnRpZGFsLmNvbS9vYXV0aDIvdXNlcic7XHJcbn1cclxuXHJcbi8vIEluaGVyaXQgZnJvbSBgT0F1dGgyU3RyYXRlZ3lgLlxyXG51dGlsLmluaGVyaXRzKFN0cmF0ZWd5LCBPQXV0aDJTdHJhdGVneSk7XHJcblxyXG4vKipcclxuKiBBdXRoZW50aWNhdGUgcmVxdWVzdCBieSBkZWxlZ2F0aW5nIHRvIFRpZGFsIHVzaW5nIE9BdXRoLlxyXG4qXHJcbiogQHBhcmFtIHtodHRwLkluY29taW5nTWVzc2FnZX0gcmVxXHJcbiogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxyXG4qIEBhY2Nlc3MgcHJvdGVjdGVkXHJcbiovXHJcblN0cmF0ZWd5LnByb3RvdHlwZS5hdXRoZW50aWNhdGUgPSBmdW5jdGlvbihyZXEsIG9wdGlvbnMpOiBhbnkge1xyXG4gICAgaWYgKHJlcS5xdWVyeSAmJiByZXEucXVlcnkuZGVuaWVkKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZmFpbCgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChyZXEuc2Vzc2lvbiAmJiByZXEuc2Vzc2lvbi5sYW5nKSB7XHJcbiAgICAgICAgLy8gaWYgdGhlIGxhbmcgaXMgdGhlcmUgYXMgYSBxdWVyeSBwYXJhbSwgcmVwbGFjZVxyXG4gICAgICAgIGlmICh0aGlzLl9vYXV0aDIuX2F1dGhvcml6ZVVybC5pbmNsdWRlcygnbGFuZz0nKSkge1xyXG4gICAgICAgICAgICAvLyBnZXR0aW5nIHRoZSBzdGFydGluZyBpbmRleCBvZiB0aGUgbGFuZ3VhZ2UgaW4gb3JkZXIgdG8gb3ZlcnJpZGVcclxuICAgICAgICAgICAgY29uc3QgaW5kZXhPZkxhbmcgPSB0aGlzLl9vYXV0aDIuX2F1dGhvcml6ZVVybC5pbmRleE9mKCdsYW5nPScpO1xyXG4gICAgICAgICAgICBjb25zdCBiYXNlVXJsID0gdGhpcy5fb2F1dGgyLl9hdXRob3JpemVVcmw7XHJcbiAgICAgICAgICAgIHRoaXMuX29hdXRoMi5fYXV0aG9yaXplVXJsID0gYmFzZVVybC5zdWJzdHIoMCwgaW5kZXhPZkxhbmcgKyA1KSArIHJlcS5zZXNzaW9uLmxhbmcgKyBiYXNlVXJsLnN1YnN0cihpbmRleE9mTGFuZyArIDUgKyByZXEuc2Vzc2lvbi5sYW5nLmxlbmd0aCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5fb2F1dGgyLl9hdXRob3JpemVVcmwgPSB0aGlzLl9vYXV0aDIuX2F1dGhvcml6ZVVybCArICc/bGFuZz0nICsgcmVxLnNlc3Npb24ubGFuZztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHJlcS5zZXNzaW9uICYmIHJlcS5zZXNzaW9uLmFtcGxpdHVkZURldmljZUlkKSB7XHJcbiAgICAgICAgLy8gaWYgdGhlIGxhbmcgaXMgdGhlcmUgYXMgYSBxdWVyeSBwYXJhbSwgcmVwbGFjZVxyXG4gICAgICAgIGlmICh0aGlzLl9vYXV0aDIuX2F1dGhvcml6ZVVybC5pbmNsdWRlcygnYW1wbGl0dWRlRGV2aWNlSWQ9JykpIHtcclxuICAgICAgICAgICAgLy8gZ2V0dGluZyB0aGUgc3RhcnRpbmcgaW5kZXggb2YgdGhlIGxhbmd1YWdlIGluIG9yZGVyIHRvIG92ZXJyaWRlXHJcbiAgICAgICAgICAgIGNvbnN0IGluZGV4T2ZhbXBsaXR1ZGVEZXZpY2VJZCA9IHRoaXMuX29hdXRoMi5fYXV0aG9yaXplVXJsLmluZGV4T2YoJ2FtcGxpdHVkZURldmljZUlkPScpO1xyXG4gICAgICAgICAgICBjb25zdCBiYXNlVXJsID0gdGhpcy5fb2F1dGgyLl9hdXRob3JpemVVcmw7XHJcbiAgICAgICAgICAgIHRoaXMuX29hdXRoMi5fYXV0aG9yaXplVXJsID0gYmFzZVVybC5zdWJzdHIoMCwgaW5kZXhPZmFtcGxpdHVkZURldmljZUlkICsgMTgpICsgcmVxLnNlc3Npb24uYW1wbGl0dWRlRGV2aWNlSWQgKyBiYXNlVXJsLnN1YnN0cihpbmRleE9mYW1wbGl0dWRlRGV2aWNlSWQgKyAxOCArIHJlcS5zZXNzaW9uLmFtcGxpdHVkZURldmljZUlkLmxlbmd0aCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKHJlcS5zZXNzaW9uLmxhbmcpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29hdXRoMi5fYXV0aG9yaXplVXJsID0gdGhpcy5fb2F1dGgyLl9hdXRob3JpemVVcmwgKyAnJmFtcGxpdHVkZURldmljZUlkPScgKyByZXEuc2Vzc2lvbi5hbXBsaXR1ZGVEZXZpY2VJZDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29hdXRoMi5fYXV0aG9yaXplVXJsID0gdGhpcy5fb2F1dGgyLl9hdXRob3JpemVVcmwgKyAnP2FtcGxpdHVkZURldmljZUlkPScgKyByZXEuc2Vzc2lvbi5hbXBsaXR1ZGVEZXZpY2VJZDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBDYWxsIHRoZSBiYXNlIGNsYXNzIGZvciBzdGFuZGFyZCBPQXV0aDIgYXV0aGVudGljYXRpb24uXHJcbiAgICBPQXV0aDJTdHJhdGVneS5wcm90b3R5cGUuYXV0aGVudGljYXRlLmNhbGwodGhpcywgcmVxLCBvcHRpb25zKTtcclxufTtcclxuXHJcbi8qKlxyXG4qIFJldHJpZXZlIHVzZXIgcHJvZmlsZSBmcm9tIFRpZGFsLlxyXG4qXHJcbiogVGhpcyBmdW5jdGlvbiBjb25zdHJ1Y3RzIGEgbm9ybWFsaXplZCBwcm9maWxlLCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczpcclxuKlxyXG4qICAgLSBgaWRgICAgICAgICAoZXF1aXZhbGVudCB0byBgdXNlcl9pZGApXHJcbiogICAtIGB1c2VybmFtZWAgIChlcXVpdmFsZW50IHRvIGBzY3JlZW5fbmFtZWApXHJcbipcclxuKiBAcGFyYW0ge3N0cmluZ30gdG9rZW5cclxuKiBAcGFyYW0ge2Z1bmN0aW9ufSBkb25lXHJcbiogQGFjY2VzcyBwcm90ZWN0ZWRcclxuKi9cclxuU3RyYXRlZ3kucHJvdG90eXBlLnVzZXJQcm9maWxlID0gZnVuY3Rpb24odG9rZW4sIGRvbmUpIHtcclxuICAgIGxldCBqc29uO1xyXG5cclxuICAgIGxldCB1cmwgPSB1cmkucGFyc2UodGhpcy5fdXNlclByb2ZpbGVVUkwpO1xyXG5cclxuICAgIHRoaXMuX29hdXRoMi5nZXQodXJpLmZvcm1hdCh1cmwpLCB0b2tlbiwgZnVuY3Rpb24gKGVyciwgYm9keSk6IEZ1bmN0aW9uIHtcclxuICAgICAgICBpZiAoZXJyKSB7XHJcbiAgICAgICAgICAgIGlmIChlcnIuZGF0YSkge1xyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBqc29uID0gSlNPTi5wYXJzZShlcnIuZGF0YSk7XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7IHJldHVybiBkb25lKG5ldyBPQXV0aDJTdHJhdGVneS5JbnRlcm5hbE9BdXRoRXJyb3IoJ0ZhaWxlZCB0byBmZXRjaCB1c2VyIHByb2ZpbGUnLCBlcnIpKTsgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoanNvbiAmJiBqc29uLmVycm9ycyAmJiBqc29uLmVycm9ycy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIGxldCBlID0ganNvbi5lcnJvcnNbMF07XHJcbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gZG9uZShuZXcgQVBJRXJyb3IoZS5tZXNzYWdlLCBlLmNvZGUpKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBkb25lKG5ldyBPQXV0aDJTdHJhdGVneS5JbnRlcm5hbE9BdXRoRXJyb3IoJ0ZhaWxlZCB0byBmZXRjaCB1c2VyIHByb2ZpbGUnLCBlKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGRvbmUobmV3IE9BdXRoMlN0cmF0ZWd5LkludGVybmFsT0F1dGhFcnJvcignRmFpbGVkIHRvIGZldGNoIHVzZXIgcHJvZmlsZScsIGVycikpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAganNvbiA9IEpTT04ucGFyc2UoYm9keSk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGRvbmUobmV3IEVycm9yKCdGYWlsZWQgdG8gcGFyc2UgdXNlciBwcm9maWxlJykpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHVzZXIgPSBuZXcgVXNlcihqc29uKTtcclxuICAgICAgICB1c2VyLl9yYXcgPSBib2R5O1xyXG5cclxuICAgICAgICBkb25lKG51bGwsIHVzZXIpO1xyXG4gICAgfSk7XHJcblxyXG59O1xyXG5cclxuLyoqXHJcbiogUGFyc2UgZXJyb3IgcmVzcG9uc2UgZnJvbSBUaWRhbCBPQXV0aDIgZW5kcG9pbnQuXHJcbipcclxuKiBAcGFyYW0ge3N0cmluZ30gYm9keVxyXG4qIEBwYXJhbSB7bnVtYmVyfSBzdGF0dXNcclxuKiBAcmV0dXJuIHtFcnJvcn1cclxuKiBAYWNjZXNzIHByb3RlY3RlZFxyXG4qL1xyXG5TdHJhdGVneS5wcm90b3R5cGUucGFyc2VFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24oYm9keSk6IE9iamVjdCB7XHJcbiAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoYm9keSk7XHJcbiAgICBpZiAoanNvbi5lcnJvciAmJiB0eXBlb2YganNvbi5lcnJvciA9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIHJldHVybiBuZXcgVGlkYWxUb2tlbkVycm9yKGpzb24uZXJyb3IubWVzc2FnZSwganNvbi5lcnJvci50eXBlLCBqc29uLmVycm9yLmNvZGUpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIE9BdXRoMlN0cmF0ZWd5LnByb3RvdHlwZS5wYXJzZUVycm9yUmVzcG9uc2UuY2FsbCh0aGlzLCBib2R5LCBzdGF0dXMpO1xyXG59O1xyXG5cclxuLy8gRXhwb3NlIGNvbnN0cnVjdG9yLlxyXG5leHBvcnQgZGVmYXVsdCBTdHJhdGVneTtcclxuIl19