diff --git a/client/components/support-user/index.jsx b/client/components/support-user/index.jsx index b088fa70517ce..b7e9915f612eb 100644 --- a/client/components/support-user/index.jsx +++ b/client/components/support-user/index.jsx @@ -36,7 +36,8 @@ module.exports = React.createClass( { return { supportUser: null, isSupportUser: false, - showDialog: false + showDialog: false, + errorMessage: null }; }, @@ -58,18 +59,33 @@ module.exports = React.createClass( { this.setState( { showDialog: false } ); }, + onTokenError: function( error ) { + this.setState( { + supportUser: null, + supportPassword: null, + isSupportUser: false, + showDialog: true, + errorMessage: error.message + } ); + }, + onChangeUser: function( e ) { e.preventDefault(); if ( this.state.supportUser && this.state.supportPassword ) { let user = new User(); user.clear(); - user.changeUser( this.state.supportUser, this.state.supportPassword ); + user.changeUser( + this.state.supportUser, + this.state.supportPassword, + ( error ) => this.onTokenError( error ) + ); this.setState( { isSupportUser: true } ); this.setState( { supportPassword: null } ); } this.setState( { showDialog: false } ); + this.setState( { errorMessage: null } ); }, onRestoreUser: function( e ) { @@ -80,7 +96,8 @@ module.exports = React.createClass( { supportUser: null, supportPassword: null, isSupportUser: false, - showDialog: false + showDialog: false, + errorMessage: null } ); window.location.reload.bind( window.location ); } @@ -129,11 +146,11 @@ module.exports = React.createClass( { render: function() { if ( this.state.isSupportUser ) { return ( -
@@ -152,13 +169,16 @@ module.exports = React.createClass( { ); } else { return ( -

Support user

+ { this.state.errorMessage && +

{ this.state.errorMessage }

+ } Username diff --git a/client/lib/user/user.js b/client/lib/user/user.js index f2d6b9a042651..c33286444aec1 100644 --- a/client/lib/user/user.js +++ b/client/lib/user/user.js @@ -238,12 +238,12 @@ User.prototype.set = function( attributes ) { return changed; }; -User.prototype.changeUser = function( username, password ) { +User.prototype.changeUser = function( username, password, tokenErrorCallback ) { wpcom.changeUser( username, password, function( error ) { if ( ! error ) { this.fetch(); } - }.bind( this ) ); + }.bind( this ), tokenErrorCallback ); }; /** diff --git a/shared/lib/wp/support.js b/shared/lib/wp/support.js index 6ad97b80db19a..98e7880ca15f6 100644 --- a/shared/lib/wp/support.js +++ b/shared/lib/wp/support.js @@ -1,6 +1,20 @@ export default function wpcomSupport( wpcom ) { let supportUser = ''; let supportToken = ''; + let tokenErrorCallback; + + // Error names returned by the server + const ERROR_INVALID_SUPPORT_TOKEN = 'invalid_support_token'; + const ERROR_INCORRECT_SUPPORT_PASSWORD = 'incorrect_password' + + /** + * Return the index of the callback in the request arguments + */ + const getCallbackIndex = function( args ) { + return args.findIndex( ( arg ) => { + return 'function' === typeof arg; + } ); + } /** * Request parameters are as follows: @@ -18,9 +32,7 @@ export default function wpcomSupport( wpcom ) { let fnIndex, queryIndex; // Find the index of the callback in the arguments - fnIndex = args.findIndex( function( e ) { - return 'function' === typeof e; - } ); + fnIndex = getCallbackIndex( args ); // Set queryIndex based on the request type and fnIndex if ( req === 'post' || req === 'put' ) { @@ -41,6 +53,26 @@ export default function wpcomSupport( wpcom ) { } ); } + /** + * Intercept any token errors in the response callback. + */ + const interceptResponse = function ( responseCallback ) { + return ( ...args ) => { + const error = args[ 0 ], + response = args[ 1 ]; + + if ( error && error.error === ERROR_INVALID_SUPPORT_TOKEN ) { + if ( tokenErrorCallback ) { + tokenErrorCallback( error ); + } + } + + if ( responseCallback ) { + responseCallback( ...args ); + } + } + } + /** * Mutate the query parameter of the request by adding values for * support_user and _support_token to the query parameter. @@ -56,6 +88,17 @@ export default function wpcomSupport( wpcom ) { } else { args.splice( 1, 0, addSupportData( {} ) ); } + + let callbackIndex = getCallbackIndex( args ); + if ( callbackIndex ) { + // Wrap the callback to intercept any token errors + args[ callbackIndex ] = interceptResponse( args[ callbackIndex ] ); + } else { + // No response callback was provided, so we add one to the end of the + // arguments, purely to handle the token errors + args.push( interceptResponse( null ) ); + } + return args; } @@ -65,18 +108,28 @@ export default function wpcomSupport( wpcom ) { const put = wpcom.req.put.bind( wpcom.req ); return Object.assign( wpcom, { - changeUser: function( username, password, fn ) { + changeUser: function( username, password, fn, fnTokenError ) { var args = { apiVersion: '1.1', path: '/internal/support/' + username + '/grant' }; + tokenErrorCallback = ( ...args ) => { + wpcom.restoreUser(); + + fnTokenError( ...args ); + } + return wpcom.req.post( args, { password: password }, function( error, response ) { if ( ! error ) { supportUser = response.username; supportToken = response.token; } + if ( error && error.error === ERROR_INCORRECT_SUPPORT_PASSWORD ) { + fnTokenError( error ); + } + fn( error, response ); } ); },