diff options
author | Corey Hulen <corey@hulen.com> | 2016-04-21 22:37:01 -0700 |
---|---|---|
committer | Corey Hulen <corey@hulen.com> | 2016-04-21 22:37:01 -0700 |
commit | 2e5617c29be69637acd384e85f795a0b343bec8d (patch) | |
tree | 6b8bdae1e664013b97c2dda94985375abda91aa5 /webapp/components/admin_console | |
parent | 5c755463ed3a4c74a383fb4460b5be02d8868481 (diff) | |
download | chat-2e5617c29be69637acd384e85f795a0b343bec8d.tar.gz chat-2e5617c29be69637acd384e85f795a0b343bec8d.tar.bz2 chat-2e5617c29be69637acd384e85f795a0b343bec8d.zip |
PLT-2057 User as a first class object (#2648)
* Adding TeamMember to system
* Fixing all unit tests on the backend
* Fixing merge conflicts
* Fixing merge conflict
* Adding javascript unit tests
* Adding TeamMember to system
* Fixing all unit tests on the backend
* Fixing merge conflicts
* Fixing merge conflict
* Adding javascript unit tests
* Adding client side unit test
* Cleaning up the clint side tests
* Fixing msg
* Adding more client side unit tests
* Adding more using tests
* Adding last bit of client side unit tests and adding make cmd
* Fixing bad merge
* Fixing libraries
* Updating to new client side API
* Fixing borken unit test
* Fixing unit tests
* ugg...trying to beat gofmt
* ugg...trying to beat gofmt
* Cleaning up remainder of the server side routes
* Adding inital load api
* Increased coverage of webhook unit tests (#2660)
* Adding loading ... to root html
* Fixing bad merge
* Removing explicit content type so superagent will guess corectly (#2685)
* Fixing merge and unit tests
* Adding create team UI
* Fixing signup flows
* Adding LDAP unit tests and enterprise unit test helper (#2702)
* Add the ability to reset MFA from the commandline (#2706)
* Fixing compliance unit tests
* Fixing client side tests
* Adding open server to system console
* Moving websocket connection
* Fixing unit test
* Fixing unit tests
* Fixing unit tests
* Adding nickname and more LDAP unit tests (#2717)
* Adding join open teams
* Cleaning up all TODOs in the code
* Fixing web sockets
* Removing unused webockets file
* PLT-2533 Add the ability to reset a user's MFA from the system console (#2715)
* Add the ability to reset a user's MFA from the system console
* Add client side unit test for adminResetMfa
* Reorganizing authentication to fix LDAP error message (#2723)
* Fixing failing unit test
* Initial upgrade db code
* Adding upgrade script
* Fixing upgrade script after running on core
* Update OAuth and Claim routes to work with user model changes (#2739)
* Fixing perminant deletion. Adding ability to delete all user and the entire database (#2740)
* Fixing team invite ldap login call (#2741)
* Fixing bluebar and some img stuff
* Fix all the different file upload web utils (#2743)
* Fixing invalid session redirect (#2744)
* Redirect on bad channel name (#2746)
* Fixing a bunch of issue and removing dead code
* Patch to fix error message on leave channel (#2747)
* Setting EnableOpenServer to false by default
* Fixing config
* Fixing upgrade
* Fixing reported bugs
* Bug fixes for PLT-2057
* PLT-2563 Redo password recovery to use a database table (#2745)
* Redo password recovery to use a database table
* Update reset password audits
* Split out admin and user reset password APIs to be separate
* Delete password recovery when user is permanently deleted
* Consolidate password resetting into a single function
* Removed private channels as an option for outgoing webhooks (#2752)
* PLT-2577/PLT-2552 Fixes for backstage (#2753)
* Added URL to incoming webhook list
* Fixed client functions for adding/removing integrations
* Disallowed slash commands without trigger words
* Fixed clientside handling of errors on AddCommand page
* Minor auth cleanup (#2758)
* Changed EditPostModal to just close if you save without making any changes (#2759)
* Renamed client -> Client in async_client.jsx and fixed eslint warnings (#2756)
* Fixed url in channel info modal (#2755)
* Fixing reported issues
* Moving to version 3 of the apis
* Fixing command unit tests (#2760)
* Adding team admins
* Fixing DM issue
* Fixing eslint error
* Properly set EditPostModal's originalText state in all cases (#2762)
* Update client config check to assume features is defined if server is licensed (#2772)
* Fixing url link
* Fixing issue with websocket crashing when sending messages to different teams
Diffstat (limited to 'webapp/components/admin_console')
19 files changed, 220 insertions, 119 deletions
diff --git a/webapp/components/admin_console/admin_navbar_dropdown.jsx b/webapp/components/admin_console/admin_navbar_dropdown.jsx index 729d4b14d..dd56411f4 100644 --- a/webapp/components/admin_console/admin_navbar_dropdown.jsx +++ b/webapp/components/admin_console/admin_navbar_dropdown.jsx @@ -3,27 +3,20 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Utils from 'utils/utils.jsx'; -import TeamStore from 'stores/team_store.jsx'; import Constants from 'utils/constants.jsx'; +import * as GlobalActions from 'action_creators/global_actions.jsx'; import {FormattedMessage} from 'react-intl'; import {Link} from 'react-router'; -function getStateFromStores() { - return {currentTeam: TeamStore.getCurrent()}; -} - import React from 'react'; export default class AdminNavbarDropdown extends React.Component { constructor(props) { super(props); this.blockToggle = false; - - this.state = getStateFromStores(); } componentDidMount() { @@ -64,24 +57,27 @@ export default class AdminNavbarDropdown extends React.Component { > <li> <Link - to={'/' + this.state.currentTeam.name + '/channels/town-square'} + to={'/select_team'} > <FormattedMessage id='admin.nav.switch' defaultMessage='Switch to {display_name}' values={{ - display_name: this.state.currentTeam.display_name + display_name: global.window.mm_config.SiteName }} /> </Link> </li> <li> - <Link to={Utils.getTeamURLFromAddressBar() + '/logout'}> + <a + href='#' + onClick={GlobalActions.emitUserLoggedOutEvent} + > <FormattedMessage id='admin.nav.logout' defaultMessage='Logout' /> - </Link> + </a> </li> </ul> </li> diff --git a/webapp/components/admin_console/admin_sidebar_header.jsx b/webapp/components/admin_console/admin_sidebar_header.jsx index 2e6252075..400730030 100644 --- a/webapp/components/admin_console/admin_sidebar_header.jsx +++ b/webapp/components/admin_console/admin_sidebar_header.jsx @@ -4,6 +4,7 @@ import $ from 'jquery'; import AdminNavbarDropdown from './admin_navbar_dropdown.jsx'; import UserStore from 'stores/user_store.jsx'; +import Client from 'utils/web_client.jsx'; import {FormattedMessage} from 'react-intl'; @@ -41,7 +42,7 @@ export default class SidebarHeader extends React.Component { profilePicture = ( <img className='user__picture' - src={'/api/v1/users/' + me.id + '/image?time=' + me.update_at} + src={Client.getUsersRoute() + '/' + me.id + '/image?time=' + me.update_at} /> ); } diff --git a/webapp/components/admin_console/compliance_reports.jsx b/webapp/components/admin_console/compliance_reports.jsx index 84def2bce..702c1a969 100644 --- a/webapp/components/admin_console/compliance_reports.jsx +++ b/webapp/components/admin_console/compliance_reports.jsx @@ -7,7 +7,7 @@ import * as Utils from '../../utils/utils.jsx'; import AdminStore from '../../stores/admin_store.jsx'; import UserStore from '../../stores/user_store.jsx'; -import * as Client from '../../utils/client.jsx'; +import * as Client from '../../utils/web_client.jsx'; import * as AsyncClient from '../../utils/async_client.jsx'; import {FormattedMessage, FormattedDate, FormattedTime} from 'react-intl'; @@ -153,7 +153,7 @@ export default class ComplianceReports extends React.Component { var download = ''; if (report.status === 'finished') { download = ( - <a href={'/api/v1/admin/download_compliance_report/' + report.id}> + <a href={Client.getAdminRoute() + '/download_compliance_report/' + report.id}> <FormattedMessage id='admin.compliance_table.download' defaultMessage='Download' diff --git a/webapp/components/admin_console/compliance_settings.jsx b/webapp/components/admin_console/compliance_settings.jsx index 206bb0faa..b127634e8 100644 --- a/webapp/components/admin_console/compliance_settings.jsx +++ b/webapp/components/admin_console/compliance_settings.jsx @@ -2,7 +2,7 @@ // See License.txt for license information. import $ from 'jquery'; -import * as Client from '../../utils/client.jsx'; +import * as Client from '../../utils/web_client.jsx'; import * as AsyncClient from '../../utils/async_client.jsx'; import * as Utils from '../../utils/utils.jsx'; diff --git a/webapp/components/admin_console/email_settings.jsx b/webapp/components/admin_console/email_settings.jsx index 8df48b206..1fa75ead9 100644 --- a/webapp/components/admin_console/email_settings.jsx +++ b/webapp/components/admin_console/email_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import crypto from 'crypto'; import ConnectionSecurityDropdownSetting from './connection_security_dropdown_setting.jsx'; diff --git a/webapp/components/admin_console/gitlab_settings.jsx b/webapp/components/admin_console/gitlab_settings.jsx index 7fdedde13..747905ac6 100644 --- a/webapp/components/admin_console/gitlab_settings.jsx +++ b/webapp/components/admin_console/gitlab_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl'; diff --git a/webapp/components/admin_console/image_settings.jsx b/webapp/components/admin_console/image_settings.jsx index 576ff18fd..023e9af3b 100644 --- a/webapp/components/admin_console/image_settings.jsx +++ b/webapp/components/admin_console/image_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import crypto from 'crypto'; diff --git a/webapp/components/admin_console/ldap_settings.jsx b/webapp/components/admin_console/ldap_settings.jsx index dd6e4338f..01402a588 100644 --- a/webapp/components/admin_console/ldap_settings.jsx +++ b/webapp/components/admin_console/ldap_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as Utils from 'utils/utils.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; @@ -61,6 +61,7 @@ class LdapSettings extends React.Component { config.LdapSettings.BindPassword = this.refs.BindPassword.value.trim(); config.LdapSettings.FirstNameAttribute = this.refs.FirstNameAttribute.value.trim(); config.LdapSettings.LastNameAttribute = this.refs.LastNameAttribute.value.trim(); + config.LdapSettings.NicknameAttribute = this.refs.NicknameAttribute.value.trim(); config.LdapSettings.EmailAttribute = this.refs.EmailAttribute.value.trim(); config.LdapSettings.UsernameAttribute = this.refs.UsernameAttribute.value.trim(); config.LdapSettings.IdAttribute = this.refs.IdAttribute.value.trim(); @@ -441,6 +442,35 @@ class LdapSettings extends React.Component { <div className='form-group'> <label className='control-label col-sm-4' + htmlFor='NicknameAttribute' + > + <FormattedMessage + id='admin.ldap.nicknameAttrTitle' + defaultMessage='Nickname Attribute:' + /> + </label> + <div className='col-sm-8'> + <input + type='text' + className='form-control' + id='NicknameAttribute' + ref='NicknameAttribute' + placeholder={Utils.localizeMessage('admin.ldap.nicknameAttrEx', 'Ex "nickname"')} + defaultValue={this.props.config.LdapSettings.NicknameAttribute} + onChange={this.handleChange} + disabled={!this.state.enable} + /> + <p className='help-text'> + <FormattedMessage + id='admin.ldap.nicknameAttrDesc' + defaultMessage='(Optional) The attribute in the LDAP server that will be used to populate the nickname of users in Mattermost.' + /> + </p> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' htmlFor='EmailAttribute' > <FormattedMessage diff --git a/webapp/components/admin_console/legal_and_support_settings.jsx b/webapp/components/admin_console/legal_and_support_settings.jsx index bbbb3713c..9f72f5fdf 100644 --- a/webapp/components/admin_console/legal_and_support_settings.jsx +++ b/webapp/components/admin_console/legal_and_support_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'react-intl'; diff --git a/webapp/components/admin_console/license_settings.jsx b/webapp/components/admin_console/license_settings.jsx index 20e2fc83a..f2c511e44 100644 --- a/webapp/components/admin_console/license_settings.jsx +++ b/webapp/components/admin_console/license_settings.jsx @@ -4,7 +4,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; import * as Utils from 'utils/utils.jsx'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl'; @@ -54,10 +54,7 @@ class LicenseSettings extends React.Component { $('#upload-button').button('loading'); - const formData = new FormData(); - formData.append('license', file, file.name); - - Client.uploadLicenseFile(formData, + Client.uploadLicenseFile(file, () => { Utils.clearFileInput(element[0]); $('#upload-button').button('reset'); diff --git a/webapp/components/admin_console/log_settings.jsx b/webapp/components/admin_console/log_settings.jsx index 5aa3ca1e0..061c2b6e3 100644 --- a/webapp/components/admin_console/log_settings.jsx +++ b/webapp/components/admin_console/log_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'react-intl'; diff --git a/webapp/components/admin_console/privacy_settings.jsx b/webapp/components/admin_console/privacy_settings.jsx index a312dddca..5045a6d31 100644 --- a/webapp/components/admin_console/privacy_settings.jsx +++ b/webapp/components/admin_console/privacy_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'react-intl'; diff --git a/webapp/components/admin_console/rate_settings.jsx b/webapp/components/admin_console/rate_settings.jsx index f3fb1742c..de7a40e6b 100644 --- a/webapp/components/admin_console/rate_settings.jsx +++ b/webapp/components/admin_console/rate_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'react-intl'; diff --git a/webapp/components/admin_console/reset_password_modal.jsx b/webapp/components/admin_console/reset_password_modal.jsx index f80c740e3..5133f3f28 100644 --- a/webapp/components/admin_console/reset_password_modal.jsx +++ b/webapp/components/admin_console/reset_password_modal.jsx @@ -2,7 +2,7 @@ // See License.txt for license information. import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import Constants from 'utils/constants.jsx'; import {Modal} from 'react-bootstrap'; @@ -40,12 +40,9 @@ class ResetPasswordModal extends React.Component { this.setState({serverError: null}); - var data = {}; - data.new_password = password; - data.name = this.props.team.name; - data.user_id = this.props.user.id; - - Client.resetPassword(data, + Client.adminResetPassword( + this.props.user.id, + password, () => { this.props.onModalSubmit(ReactDOM.findDOMNode(this.refs.password).value); }, @@ -159,4 +156,4 @@ ResetPasswordModal.propTypes = { onModalDismissed: React.PropTypes.func }; -export default injectIntl(ResetPasswordModal);
\ No newline at end of file +export default injectIntl(ResetPasswordModal); diff --git a/webapp/components/admin_console/service_settings.jsx b/webapp/components/admin_console/service_settings.jsx index 2c3f4081c..90b6a39b4 100644 --- a/webapp/components/admin_console/service_settings.jsx +++ b/webapp/components/admin_console/service_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl'; diff --git a/webapp/components/admin_console/sql_settings.jsx b/webapp/components/admin_console/sql_settings.jsx index 33bb2cece..f2e005b83 100644 --- a/webapp/components/admin_console/sql_settings.jsx +++ b/webapp/components/admin_console/sql_settings.jsx @@ -3,7 +3,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import crypto from 'crypto'; diff --git a/webapp/components/admin_console/team_settings.jsx b/webapp/components/admin_console/team_settings.jsx index 6c9828351..bbb7ec3c4 100644 --- a/webapp/components/admin_console/team_settings.jsx +++ b/webapp/components/admin_console/team_settings.jsx @@ -2,7 +2,7 @@ // See License.txt for license information. import $ from 'jquery'; -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; @@ -42,6 +42,7 @@ class TeamSettings extends React.Component { this.handleImageSubmit = this.handleImageSubmit.bind(this); this.uploading = false; + this.timestamp = 0; this.state = { saveNeeded: false, @@ -53,7 +54,7 @@ class TeamSettings extends React.Component { componentWillMount() { if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true') { - $.get('/api/v1/admin/get_brand_image').done(() => this.setState({brandImageExists: true})); + $.get(Client.getAdminRoute() + '/get_brand_image').done(() => this.setState({brandImageExists: true})); } } @@ -89,6 +90,7 @@ class TeamSettings extends React.Component { if (element.prop('files').length > 0) { this.setState({fileSelected: true, brandImage: element.prop('files')[0]}); } + $('#upload-button').button('reset'); } handleSubmit(e) { @@ -100,8 +102,8 @@ class TeamSettings extends React.Component { config.TeamSettings.RestrictCreationToDomains = this.refs.RestrictCreationToDomains.value.trim(); config.TeamSettings.EnableTeamCreation = this.refs.EnableTeamCreation.checked; config.TeamSettings.EnableUserCreation = this.refs.EnableUserCreation.checked; + config.TeamSettings.EnableOpenServer = this.refs.EnableOpenServer.checked; config.TeamSettings.RestrictTeamNames = this.refs.RestrictTeamNames.checked; - config.TeamSettings.EnableTeamListing = this.refs.EnableTeamListing.checked; if (this.refs.EnableCustomBrand) { config.TeamSettings.EnableCustomBrand = this.refs.EnableCustomBrand.checked; @@ -155,6 +157,7 @@ class TeamSettings extends React.Component { Client.uploadBrandImage(this.state.brandImage, () => { $('#upload-button').button('complete'); + this.timestamp = Utils.getTimestamp(); this.setState({brandImageExists: true, brandImage: null}); this.uploading = false; }, @@ -193,7 +196,7 @@ class TeamSettings extends React.Component { img = ( <img className='brand-img' - src='/api/v1/admin/get_brand_image' + src={Client.getAdminRoute() + '/get_brand_image?t=' + this.timestamp} /> ); } else { @@ -537,6 +540,53 @@ class TeamSettings extends React.Component { <div className='form-group'> <label className='control-label col-sm-4' + htmlFor='EnableOpenServer' + > + <FormattedMessage + id='admin.team.openServerTitle' + defaultMessage='Enable Open Server: ' + /> + </label> + <div className='col-sm-8'> + <label className='radio-inline'> + <input + type='radio' + name='EnableOpenServer' + value='true' + ref='EnableOpenServer' + defaultChecked={this.props.config.TeamSettings.EnableOpenServer} + onChange={this.handleChange} + /> + <FormattedMessage + id='admin.team.true' + defaultMessage='true' + /> + </label> + <label className='radio-inline'> + <input + type='radio' + name='EnableOpenServer' + value='false' + defaultChecked={!this.props.config.TeamSettings.EnableOpenServer} + onChange={this.handleChange} + /> + <FormattedMessage + id='admin.team.false' + defaultMessage='false' + /> + </label> + <p className='help-text'> + <FormattedMessage + id='admin.team.openServerDescription' + defaultMessage='When true, anyone can signup for a user account on this server without the need to be invited.' + /> + </p> + </div> + </div> + + <div className='form-group'> + <label + className='control-label col-sm-4' htmlFor='RestrictCreationToDomains' > <FormattedMessage @@ -610,53 +660,6 @@ class TeamSettings extends React.Component { </div> </div> - <div className='form-group'> - <label - className='control-label col-sm-4' - htmlFor='EnableTeamListing' - > - <FormattedMessage - id='admin.team.dirTitle' - defaultMessage='Enable Team Directory: ' - /> - </label> - <div className='col-sm-8'> - <label className='radio-inline'> - <input - type='radio' - name='EnableTeamListing' - value='true' - ref='EnableTeamListing' - defaultChecked={this.props.config.TeamSettings.EnableTeamListing} - onChange={this.handleChange} - /> - <FormattedMessage - id='admin.team.true' - defaultMessage='true' - /> - </label> - <label className='radio-inline'> - <input - type='radio' - name='EnableTeamListing' - value='false' - defaultChecked={!this.props.config.TeamSettings.EnableTeamListing} - onChange={this.handleChange} - /> - <FormattedMessage - id='admin.team.false' - defaultMessage='false' - /> - </label> - <p className='help-text'> - <FormattedMessage - id='admin.team.dirDesc' - defaultMessage='When true, teams that are configured to show in team directory will show on main page inplace of creating a new team.' - /> - </p> - </div> - </div> - {brand} <div className='form-group'> diff --git a/webapp/components/admin_console/team_users.jsx b/webapp/components/admin_console/team_users.jsx index 8b37bd237..2b0e6af0a 100644 --- a/webapp/components/admin_console/team_users.jsx +++ b/webapp/components/admin_console/team_users.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import LoadingScreen from '../loading_screen.jsx'; import UserItem from './user_item.jsx'; import ResetPasswordModal from './reset_password_modal.jsx'; diff --git a/webapp/components/admin_console/user_item.jsx b/webapp/components/admin_console/user_item.jsx index 5bd05d063..b8f21d77e 100644 --- a/webapp/components/admin_console/user_item.jsx +++ b/webapp/components/admin_console/user_item.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import * as Client from 'utils/client.jsx'; +import Client from 'utils/web_client.jsx'; import * as Utils from 'utils/utils.jsx'; import UserStore from 'stores/user_store.jsx'; import ConfirmModal from '../confirm_modal.jsx'; import TeamStore from 'stores/team_store.jsx'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; import React from 'react'; import {browserHistory} from 'react-router'; @@ -22,6 +22,7 @@ export default class UserItem extends React.Component { this.handleMakeAdmin = this.handleMakeAdmin.bind(this); this.handleMakeSystemAdmin = this.handleMakeSystemAdmin.bind(this); this.handleResetPassword = this.handleResetPassword.bind(this); + this.handleResetMfa = this.handleResetMfa.bind(this); this.handleDemote = this.handleDemote.bind(this); this.handleDemoteSubmit = this.handleDemoteSubmit.bind(this); this.handleDemoteCancel = this.handleDemoteCancel.bind(this); @@ -40,12 +41,9 @@ export default class UserItem extends React.Component { if (this.props.user.id === me.id) { this.handleDemote(this.props.user, ''); } else { - const data = { - user_id: this.props.user.id, - new_roles: '' - }; - - Client.updateRoles(data, + Client.updateRoles( + this.props.user.id, + '', () => { this.props.refreshProfiles(); }, @@ -86,12 +84,9 @@ export default class UserItem extends React.Component { if (this.props.user.id === me.id) { this.handleDemote(this.props.user, 'admin'); } else { - const data = { - user_id: this.props.user.id, - new_roles: 'admin' - }; - - Client.updateRoles(data, + Client.updateRoles( + this.props.user.id, + 'admin', () => { this.props.refreshProfiles(); }, @@ -104,12 +99,10 @@ export default class UserItem extends React.Component { handleMakeSystemAdmin(e) { e.preventDefault(); - const data = { - user_id: this.props.user.id, - new_roles: 'system_admin' - }; - Client.updateRoles(data, + Client.updateRoles( + this.props.user.id, + 'system_admin', () => { this.props.refreshProfiles(); }, @@ -124,6 +117,19 @@ export default class UserItem extends React.Component { this.props.doPasswordReset(this.props.user); } + handleResetMfa(e) { + e.preventDefault(); + + Client.adminResetMfa(this.props.user.id, + () => { + this.props.refreshProfiles(); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + handleDemote(user, role) { this.setState({ serverError: this.state.serverError, @@ -143,12 +149,9 @@ export default class UserItem extends React.Component { } handleDemoteSubmit() { - const data = { - user_id: this.props.user.id, - new_roles: this.state.role - }; - - Client.updateRoles(data, + Client.updateRoles( + this.props.user.id, + this.state.role, () => { this.setState({ serverError: null, @@ -211,10 +214,15 @@ export default class UserItem extends React.Component { const email = user.email; let showMakeMember = user.roles === 'admin' || user.roles === 'system_admin'; - let showMakeAdmin = user.roles === '' || user.roles === 'system_admin'; + + //let showMakeAdmin = user.roles === '' || user.roles === 'system_admin'; + let showMakeAdmin = false; + let showMakeSystemAdmin = user.roles === '' || user.roles === 'admin'; let showMakeActive = false; let showMakeNotActive = user.roles !== 'system_admin'; + let mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true'; + let showMfaReset = mfaEnabled && user.mfa_active; if (user.delete_at > 0) { currentRoles = ( @@ -319,6 +327,64 @@ export default class UserItem extends React.Component { </li> ); } + + let mfaReset = null; + if (showMfaReset) { + mfaReset = ( + <li role='presentation'> + <a + role='menuitem' + href='#' + onClick={this.handleResetMfa} + > + <FormattedMessage + id='admin.user_item.resetMfa' + defaultMessage='Remove MFA' + /> + </a> + </li> + ); + } + + let mfaActiveText; + if (mfaEnabled) { + if (user.mfa_active) { + mfaActiveText = ( + <FormattedHTMLMessage + id='admin.user_item.mfaYes' + defaultMessage=', <strong>MFA</strong>: Yes' + /> + ); + } else { + mfaActiveText = ( + <FormattedHTMLMessage + id='admin.user_item.mfaNo' + defaultMessage=', <strong>MFA</strong>: No' + /> + ); + } + } + + let authServiceText; + if (user.auth_service) { + authServiceText = ( + <FormattedHTMLMessage + id='admin.user_item.authServiceNotEmail' + defaultMessage=', <strong>Sign-in Method:</strong> {service}' + values={{ + service: Utils.toTitleCase(user.auth_service) + }} + /> + ); + } else { + authServiceText = ( + <FormattedHTMLMessage + id='admin.user_item.authServiceEmail' + defaultMessage=', <strong>Sign-in Method:</strong> Email' + /> + ); + } + const me = UserStore.getCurrentUser(); let makeDemoteModal = null; if (this.props.user.id === me.id) { @@ -368,13 +434,23 @@ export default class UserItem extends React.Component { <div className='more-modal__row'> <img className='more-modal__image pull-left' - src={`/api/v1/users/${user.id}/image?time=${user.update_at}`} + src={`${Client.getUsersRoute()}/${user.id}/image?time=${user.update_at}`} height='36' width='36' /> <div className='more-modal__details'> <div className='more-modal__name'>{Utils.getDisplayName(user)}</div> - <div className='more-modal__description'>{email}</div> + <div className='more-modal__description'> + <FormattedHTMLMessage + id='admin.user_item.emailTitle' + defaultMessage='<strong>Email:</strong> {email}' + values={{ + email + }} + /> + {authServiceText} + {mfaActiveText} + </div> </div> <div className='more-modal__actions'> <div className='dropdown member-drop'> @@ -397,6 +473,7 @@ export default class UserItem extends React.Component { {makeActive} {makeNotActive} {makeSystemAdmin} + {mfaReset} <li role='presentation'> <a role='menuitem' |