Skip to content

Commit

Permalink
Support User: Add in-progress version of support user.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdodd committed Dec 2, 2015
1 parent 8f20724 commit dd9d8ac
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 3 deletions.
3 changes: 3 additions & 0 deletions client/components/support-user/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Support User
=============
This component is used to provide user support.
126 changes: 126 additions & 0 deletions client/components/support-user/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* External dependencies
*/
import React from 'react';
import classNames from 'classnames';

/**
* Internal dependencies
*/
import observe from 'lib/mixins/data-observe';
import User from 'lib/user';
import userSettings from 'lib/user-settings';
import Dialog from 'components/dialog';
import KeyboardShortcuts from 'lib/keyboard-shortcuts';

module.exports = React.createClass( {
displayName: 'SupportUser',

mixins: [ observe( 'userSettings' ), React.addons.LinkedStateMixin ],

componentDidMount: function() {
KeyboardShortcuts.on( 'open-support-user', this.toggleShowDialog );
},

componentWillUnmount: function() {
KeyboardShortcuts.off( 'open-support-user', this.toggleShowDialog );
},

getInitialState: function() {
return {
supportUser: null,
isSupportUser: false,
showDialog: false
};
},

isEnabled: function() {
if ( ! userSettings.hasSettings() ) {
userSettings.fetchSettings();
return false;
}
return ! userSettings.getSetting( 'user_login_can_be_changed' );
},

toggleShowDialog: function() {
if ( this.isEnabled() ) {
this.setState( { showDialog: ! this.state.showDialog } );
}
},

closeDialog: function() {
},

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 );
this.setState( { isSupportUser: true } );
this.setState( { supportPassword: null } );
}

this.setState( { showDialog: false } );
},

onRestoreUser: function( e ) {
if ( this.state.isSupportUser && this.state.restoreUser ) {
let user = new User();
user.clear().fetch();
this.setState( {
supportUser: null,
supportPassword: null,
isSupportUser: false,
showDialog: false
} );
window.location.reload.bind( window.location );
}
},

render: function() {
if ( this.state.isSupportUser ) {
return (
<Dialog additionalClassNames="support-user" isVisible={ this.state.showDialog } onClose={ this.closeDialog }>
<div className="restore-user">
<form onSubmit={ this.onRestoreUser }>
<button type="submit" className="button">
Restore User
</button>
</form>
</div>
</Dialog>
);
} else {
return (
<Dialog additionalClassNames="support-user" isVisible={ this.state.showDialog } onClose={ this.closeDialog }>
<div className="support-user">
<form onSubmit={ this.onChangeUser }>
<label>
Username
<input
type="text"
name="supportUser"
id="supportUser"
valueLink={ this.linkState( 'supportUser' ) }
/>
</label>
<label>
Support Password
<input
type="password"
name="supportPassword"
id="supportPassword"
valueLink={ this.linkState( 'supportPassword' ) }
/>
</label>
<button type="submit" className="button">
Change to Support User
</button>
</form>
</div>
</Dialog>
); }
}
} );
Empty file.
2 changes: 2 additions & 0 deletions client/layout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var Masterbar = require( './masterbar' ),
PulsingDot = require( 'components/pulsing-dot' ),
SitesListNotices = require( 'lib/sites-list/notices' ),
PollerPool = require( 'lib/data-poller' ),
SupportUser = require( 'components/support-user' ),
KeyboardShortcutsMenu;

if ( config.isEnabled( 'keyboard-shortcuts' ) ) {
Expand Down Expand Up @@ -102,6 +103,7 @@ module.exports = React.createClass( {
return (
<div className={ sectionClass }>
{ config.isEnabled( 'keyboard-shortcuts' ) ? <KeyboardShortcutsMenu /> : null }
<SupportUser />
<Masterbar user={ this.props.user } section={ this.state.section } sites={ this.props.sites }/>
<div className={ loadingClass } ><PulsingDot active={ this.state.isLoading } /></div>
<div id="content" className="wp-content">
Expand Down
8 changes: 8 additions & 0 deletions client/lib/keyboard-shortcuts/key-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ KeyBindings.prototype.get = function() {
keys: [ 'n' ],
text: i18n.translate( 'Open Notifications' )
}
},
{
eventName: 'open-support-user',
keys: [ 's', 'u' ],
description: {
keys: [],
text: '',
}
}
],

Expand Down
8 changes: 8 additions & 0 deletions client/lib/user/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,14 @@ User.prototype.set = function( attributes ) {
return changed;
};

User.prototype.changeUser = function( username, password ) {
wpcom.changeUser( username, password, function( error ) {
if ( ! error ) {
this.fetch();
}
}.bind( this ) );
};

/**
* Expose `User`
*/
Expand Down
7 changes: 4 additions & 3 deletions shared/lib/wp/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ var debug = require( 'debug' )( 'calypso:wp' );
* Internal dependencies
*/
var WPCOM = require( 'lib/wpcom-undocumented' ),
config = require( 'config' );
config = require( 'config' ),
wrapWithSupport = require( './wrap-with-support' );

var wpcom;

Expand All @@ -19,7 +20,7 @@ if ( config.isEnabled( 'oauth' ) ) {
// Set proxy request handler
wpcom = WPCOM( require( 'wpcom-proxy-request' ) );

//Upgrade to "access all users blogs" mode
// Upgrade to "access all users blogs" mode
wpcom.request( {
metaAPI: { accessAllUsersBlogs: true }
}, function( error ) {
Expand All @@ -33,4 +34,4 @@ if ( config.isEnabled( 'oauth' ) ) {
/**
* Expose `wpcom`
*/
module.exports = wpcom;
module.exports = wrapWithSupport( wpcom );
102 changes: 102 additions & 0 deletions shared/lib/wp/wrap-with-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
export default function wrapWithSupport( wpcom ) {
let supportUser = '';
let supportToken = '';

/**
* Request parameters are as follows:
* - param (required) A string or object that contains the path
* - query (optional) An object that expands the response object
* - body (required*) Required by POST and PUT, but not by GET and DEL
* - fn (required) A callback function to handle the returned result
* - ...rest (optional) Some queries have additional parameters after
* callback function
*
* Return the index of the query parameter, or if one does not exist,
* return false.
*/
const getQueryIndex = function( req, args ) {
let fnIndex, queryIndex;

// Find the index of the callback in the arguments
fnIndex = args.findIndex( function( e ) {
return 'function' === typeof e;
} );

// Set queryIndex based on the request type and fnIndex
if ( req === 'post' || req === 'put' ) {
queryIndex = ( 3 === fnIndex ) ? 1 : false;
} else {
queryIndex = ( 2 === fnIndex ) ? 1 : false;
}
return queryIndex;
}

/**
* Add the supportUser and supportToken to the query.
*/
const addSupportData = function( query ) {
return Object.assign( {}, query, {
support_user: supportUser,
_support_token: supportToken
} );
}

/**
* Mutate the query parameter of the request by adding values for
* support_user and _support_token to the query parameter.
*/
const extendRequest = function( req, args ) {
if ( ! supportUser || ! supportToken ) {
return args;
}

let queryIndex = getQueryIndex( req, args );
if ( queryIndex ) {
args[ queryIndex ] = addSupportData( args[ queryIndex ] );
} else {
args.splice( 1, 0, addSupportData( {} ) );
}
return args;
}

const del = wpcom.req.del.bind( wpcom.req );
const get = wpcom.req.get.bind( wpcom.req );
const post = wpcom.req.post.bind( wpcom.req );
const put = wpcom.req.put.bind( wpcom.req );

return Object.assign( wpcom, {
changeUser: function( username, password, fn ) {
var args = {
apiVersion: '1.1',
path: '/internal/support/' + username + '/grant'
};

return wpcom.req.post( args, { password: password }, function( error, response ) {
if ( ! error ) {
supportUser = response.username;
supportToken = response.token;
}

fn( error, response );
} );
},
restoreUser: function() {
supportUser = '';
supportToken = '';
},
req: {
del: function( ...args ) {
return del.apply( wpcom, extendRequest( 'del', args ) );
},
get: function( ...args ) {
return get.apply( wpcom, extendRequest( 'get', args ) );
},
post: function( ...args ) {
return post.apply( wpcom, extendRequest( 'post', args ) );
},
put: function( ...args ) {
return put.apply( wpcom, extendRequest( 'put', args ) );
}
}
} );
};

0 comments on commit dd9d8ac

Please sign in to comment.