UNPKG

passport-tidal

Version:

PassportJS Login/Signup for TIDAL

188 lines (159 loc) 20.6 kB
'use strict'; 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 + '&amplitudeDeviceId=' + 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