feat(ui): create DB user with enhanced validations

pull/5925/head
Pavel Zavora 2022-06-06 08:37:41 +02:00
parent dc16f3387b
commit 4becfd9404
2 changed files with 65 additions and 16 deletions

View File

@ -1,7 +1,7 @@
import React, {useCallback, useMemo, useState} from 'react'
import {connect, ResolveThunks} from 'react-redux'
import {withSource} from 'src/CheckSources'
import {Source} from 'src/types'
import {Source, NotificationAction} from 'src/types'
import {UserRole, User, Database} from 'src/types/influxAdmin'
import {notify as notifyAction} from 'src/shared/actions/notifications'
import {
@ -11,7 +11,11 @@ import {
createUserAsync,
filterUsers as filterUsersAction,
} from 'src/admin/actions/influxdb'
import {notifyDBUserNamePasswordInvalid} from 'src/shared/copy/notifications'
import {
notifyDBUserNameInvalid,
notifyDBPasswordInvalid,
notifyDBUserNameExists,
} from 'src/shared/copy/notifications'
import AdminInfluxDBTabbedPage, {
hasRoleManagement,
isConnectedToLDAP,
@ -25,10 +29,23 @@ import MultiSelectDropdown from 'src/reusable_ui/components/dropdowns/MultiSelec
import {ComponentSize, SlideToggle} from 'src/reusable_ui'
import computeEffectiveDBPermissions from './util/computeEffectiveDBPermissions'
import allOrParticularSelection from './util/allOrParticularSelection'
import CreateUserDialog from '../../components/influxdb/CreateUserDialog'
import {withRouter, WithRouterProps} from 'react-router'
const isValidUser = (user: User) => {
const minLen = 3
return user.name.length >= minLen && user.password.length >= minLen
const minLen = 3
const validateUser = (
user: Pick<User, 'name' | 'password'>,
notify: NotificationAction
) => {
if (user.name.length < minLen) {
notify(notifyDBUserNameInvalid())
return false
}
if (user.password.length < minLen) {
notify(notifyDBPasswordInvalid())
return false
}
return true
}
const mapStateToProps = ({adminInfluxDB: {databases, users, roles}}) => ({
@ -56,9 +73,10 @@ interface ConnectedProps {
}
type ReduxDispatchProps = ResolveThunks<typeof mapDispatchToProps>
type Props = OwnProps & ConnectedProps & ReduxDispatchProps
type Props = WithRouterProps & OwnProps & ConnectedProps & ReduxDispatchProps
const UsersPage = ({
router,
source,
databases,
users,
@ -66,14 +84,12 @@ const UsersPage = ({
notify,
createUser,
filterUsers,
addUser,
removeUser,
editUser,
}: Props) => {
const handleSaveUser = useCallback(
async (user: User) => {
if (!isValidUser(user)) {
notify(notifyDBUserNamePasswordInvalid())
if (!validateUser(user, notify)) {
return
}
if (user.isNew) {
@ -82,8 +98,6 @@ const UsersPage = ({
},
[notify, source]
)
const isEditing = useMemo(() => users.some(u => u.isEditing), [users])
const [isEnterprise, usersPage] = useMemo(
() => [
hasRoleManagement(source),
@ -130,8 +144,34 @@ const UsersPage = ({
showRoles,
setShowRoles,
])
const [createVisible, setCreateVisible] = useState(false)
const createNew = useCallback(
async (user: {name: string; password: string}) => {
if (users.some(x => x.name === user.name)) {
notify(notifyDBUserNameExists())
return
}
if (!validateUser(user, notify)) {
return
}
await createUser(source.links.users, user)
router.push(
`/sources/${source.id}/admin-influxdb/users/${encodeURIComponent(
user.name
)}`
)
},
[users, router, source, notify]
)
return (
<AdminInfluxDBTabbedPage activeTab="users" source={source}>
<CreateUserDialog
visible={createVisible}
setVisible={setCreateVisible}
create={createNew}
/>
<div className="panel panel-solid influxdb-admin">
<div className="panel-heading">
<div className="search-widget">
@ -186,8 +226,7 @@ const UsersPage = ({
<div className="panel-heading--right">
<button
className="btn btn-sm btn-primary"
disabled={isEditing}
onClick={addUser}
onClick={() => setCreateVisible(true)}
data-test="create-user--button"
>
<span className="icon plus" /> Create User
@ -265,5 +304,5 @@ const UsersPageAvailable = (props: Props) => {
}
export default withSource(
connect(mapStateToProps, mapDispatchToProps)(UsersPageAvailable)
withRouter(connect(mapStateToProps, mapDispatchToProps)(UsersPageAvailable))
)

View File

@ -419,9 +419,19 @@ export const notifyDatabaseDeleteConfirmationRequired = (
message: `Type "DELETE ${databaseName}" to confirm. This action cannot be undone.`,
})
export const notifyDBUserNamePasswordInvalid = (): Notification => ({
export const notifyDBUserNameInvalid = (): Notification => ({
...defaultErrorNotification,
message: 'Username and/or Password too short.',
message: 'User name is too short.',
})
export const notifyDBPasswordInvalid = (): Notification => ({
...defaultErrorNotification,
message: 'Password is too short.',
})
export const notifyDBUserNameExists = (): Notification => ({
...defaultErrorNotification,
message: 'User name already exists.',
})
export const notifyRoleNameInvalid = (): Notification => ({