Merge pull request #2452 from influxdata/multitenancy_ui_prevent_self_deletion

Disable 'Remove' button for self in Chronograf UsersTable
pull/2469/head
Jared Scheib 2017-12-04 13:57:33 -08:00 committed by GitHub
commit 75e1c46577
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 15 deletions

View File

@ -22,6 +22,7 @@ const AdminTabs = ({
onUpdateUserRole,
onUpdateUserSuperAdmin,
onDeleteUser,
meID,
}) => {
const tabs = [
{
@ -40,6 +41,7 @@ const AdminTabs = ({
onUpdateUserRole={onUpdateUserRole}
onUpdateUserSuperAdmin={onUpdateUserSuperAdmin}
onDeleteUser={onDeleteUser}
meID={meID}
/>
),
},
@ -65,16 +67,34 @@ const AdminTabs = ({
)
}
const {arrayOf, func, shape, string} = PropTypes
const {arrayOf, bool, func, shape, string} = PropTypes
AdminTabs.propTypes = {
meRole: string.isRequired,
meID: string.isRequired,
// UsersTable
users: arrayOf(shape()),
users: arrayOf(
shape({
id: string,
links: shape({
self: string.isRequired,
}),
name: string.isRequired,
provider: string.isRequired,
roles: arrayOf(
shape({
name: string.isRequired,
organization: string.isRequired,
})
),
scheme: string.isRequired,
superAdmin: bool,
})
).isRequired,
organization: shape({
name: string.isRequired,
id: string.isRequired,
}),
}).isRequired,
onCreateUser: func.isRequired,
onUpdateUserRole: func.isRequired,
onUpdateUserSuperAdmin: func.isRequired,

View File

@ -40,7 +40,7 @@ class UsersTable extends Component {
}
render() {
const {organization, users, onCreateUser} = this.props
const {organization, users, onCreateUser, meID} = this.props
const {isCreatingUser} = this.state
const {
@ -94,6 +94,7 @@ class UsersTable extends Component {
onChangeUserRole={this.handleChangeUserRole}
onChangeSuperAdmin={this.handleChangeSuperAdmin}
onDelete={this.handleDeleteUser}
meID={meID}
/>
)
: <tr className="table-empty-state">
@ -130,5 +131,6 @@ UsersTable.propTypes = {
onUpdateUserRole: func.isRequired,
onUpdateUserSuperAdmin: func.isRequired,
onDeleteUser: func.isRequired,
meID: string.isRequired,
}
export default UsersTable

View File

@ -15,6 +15,7 @@ const UsersTableRow = ({
onChangeUserRole,
onChangeSuperAdmin,
onDelete,
meID,
}) => {
const {colRole, colSuperAdmin, colProvider, colScheme} = USERS_TABLE
@ -65,6 +66,7 @@ const UsersTableRow = ({
onDelete={onDelete}
item={user}
buttonSize="btn-xs"
disabled={user.id === meID}
/>
</tr>
)
@ -81,6 +83,7 @@ UsersTableRow.propTypes = {
onChangeUserRole: func.isRequired,
onChangeSuperAdmin: func.isRequired,
onDelete: func.isRequired,
meID: string.isRequired,
}
export default UsersTableRow

View File

@ -11,10 +11,10 @@ import FancyScrollbar from 'shared/components/FancyScrollbar'
class AdminChronografPage extends Component {
// TODO: revisit this, possibly don't call setState if both are deep equal
componentWillReceiveProps(nextProps) {
const {currentOrganization} = nextProps
const {meCurrentOrganization} = nextProps
const hasChangedCurrentOrganization =
currentOrganization.id !== this.props.currentOrganization.id
meCurrentOrganization.id !== this.props.meCurrentOrganization.id
if (hasChangedCurrentOrganization) {
this.loadUsers()
@ -64,7 +64,7 @@ class AdminChronografPage extends Component {
}
render() {
const {users, currentOrganization, meRole} = this.props
const {users, meCurrentOrganization, meRole, meID} = this.props
return (
<div className="page">
@ -81,9 +81,10 @@ class AdminChronografPage extends Component {
<div className="row">
<AdminTabs
meRole={meRole}
meID={meID}
// UsersTable
users={users}
organization={currentOrganization}
organization={meCurrentOrganization}
onCreateUser={this.handleCreateUser}
onUpdateUserRole={this.handleUpdateUserRole}
onUpdateUserSuperAdmin={this.handleUpdateUserSuperAdmin}
@ -105,11 +106,12 @@ AdminChronografPage.propTypes = {
users: string.isRequired,
}),
users: arrayOf(shape),
currentOrganization: shape({
meCurrentOrganization: shape({
id: string.isRequired,
name: string.isRequired,
}).isRequired,
meRole: string.isRequired,
meID: string.isRequired,
actions: shape({
loadUsersAsync: func.isRequired,
createUserAsync: func.isRequired,
@ -122,12 +124,15 @@ AdminChronografPage.propTypes = {
const mapStateToProps = ({
links,
adminChronograf: {users},
auth: {me: {currentOrganization, role: meRole}},
auth: {
me: {currentOrganization: meCurrentOrganization, role: meRole, id: meID},
},
}) => ({
links,
users,
currentOrganization,
meCurrentOrganization,
meRole,
meID,
})
const mapDispatchToProps = dispatch => ({

View File

@ -4,10 +4,11 @@ import classnames from 'classnames'
import OnClickOutside from 'shared/components/OnClickOutside'
import ConfirmButtons from 'shared/components/ConfirmButtons'
const DeleteButton = ({onClickDelete, buttonSize, text}) =>
const DeleteButton = ({onClickDelete, buttonSize, text, disabled}) =>
<button
className={classnames('btn btn-danger table--show-on-row-hover', {
[buttonSize]: buttonSize,
disabled,
})}
onClick={onClickDelete}
>
@ -37,7 +38,7 @@ class DeleteConfirmButtons extends Component {
}
render() {
const {onDelete, item, buttonSize, text} = this.props
const {onDelete, item, buttonSize, text, disabled} = this.props
const {isConfirming} = this.state
return isConfirming
@ -49,18 +50,20 @@ class DeleteConfirmButtons extends Component {
/>
: <DeleteButton
text={text}
onClickDelete={this.handleClickDelete}
onClickDelete={disabled ? () => {} : this.handleClickDelete}
buttonSize={buttonSize}
disabled={disabled}
/>
}
}
const {func, oneOfType, shape, string} = PropTypes
const {bool, func, oneOfType, shape, string} = PropTypes
DeleteButton.propTypes = {
text: string.isRequired,
onClickDelete: func.isRequired,
buttonSize: string,
disabled: bool,
}
DeleteButton.defaultProps = {
@ -72,6 +75,7 @@ DeleteConfirmButtons.propTypes = {
item: oneOfType([(string, shape())]),
onDelete: func.isRequired,
buttonSize: string,
disabled: bool,
}
DeleteConfirmButtons.defaultProps = {