Skip to content

Commit

Permalink
frontend: improve user creation modal
Browse files Browse the repository at this point in the history
partially fixes issue #188
  • Loading branch information
weeco committed Nov 13, 2023
1 parent 0d32871 commit 2d5371e
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 44 deletions.
8 changes: 6 additions & 2 deletions frontend/src/components/pages/acls/Acl.List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,13 @@ class AclList extends PageComponent {
} as CreateUserRequest),

isOkEnabled: state => {
const noWhitespaceRegex = /^\S+$/;
if (!noWhitespaceRegex.test(state.username))
if (state.username.length === 0) return false
if (state.password.length <= 3 || state.password.length > 64) return false

// Check that the username only contains allowed characters (alphanumeric, hypen, underscore, at symbol)
if (/[^a-zA-Z0-9._@-]+/.test(state.username))
return false;

return true;
},
onOk: async state => {
Expand Down
70 changes: 28 additions & 42 deletions frontend/src/components/pages/acls/CreateServiceAccountEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,63 @@
import { ReloadOutlined } from '@ant-design/icons';
import { Button, Input, Flex, Checkbox } from '@redpanda-data/ui';
import { Button, Input, Flex, Checkbox, FormField, CopyButton } from '@redpanda-data/ui';
import { observer } from 'mobx-react';
import { useState } from 'react';
import { CreateUserRequest } from '../../../state/restInterfaces';
import { Label, LabelTooltip } from '../../../utils/tsxUtils';
import { Tooltip } from '@redpanda-data/ui';
import { Tooltip, PasswordInput } from '@redpanda-data/ui';
import { SingleSelect } from '../../misc/Select';

export const CreateServiceAccountEditor = observer((p: { state: CreateUserRequest }) => {
const state = p.state;
const [showPw, setShowPw] = useState(false);
const [allowSpecialChars, setAllowSpecialChars] = useState(false);
const toggleShowPw = () => setShowPw(!showPw);

return (
<div>
<div style={{ display: 'flex', gap: '2em', flexDirection: 'column' }}>
<Label
text="Username"
textSuffix={
<LabelTooltip nowrap left maxW={500}>
The username of the service account to be created.
<br />
Must not be empty, must not contain any whitespace (space, tab, ...)
</LabelTooltip>
}
>
<FormField
description="Must not contain any whitespace. Dots, hyphens and underscores may be used."
label="Username"
isInvalid={ /[^a-zA-Z0-9._@-]+/.test(state.username) }
errorText="The username contains invalid characters. Use only letters, numbers, dots, underscores, at symbols, and hyphens.">

<Input
value={state.username}
onChange={v => {
const newName = v.target.value;
if (newName.includes(':')) return;
state.username = newName;
}}
onChange={v => state.username = v.target.value}
width="100%"
autoFocus
spellCheck={false}
placeholder="Username"
autoComplete="off"
/>
</Label>

<Label
text="Password"
textSuffix={
<LabelTooltip nowrap left maxW={500}>
The password for the service account.
<br />
You can either use the randomly generated password or specify a custom one.
<br />
The password should not exceed 64 characters.
</LabelTooltip>
}
>
</FormField>

<FormField
description="Must be at least 4 characters and should not exceed 64 characters."
label="Password">

<Flex direction="column" gap="2">
<Flex alignItems="center" gap="2">
<Input type={showPw ? 'text' : 'password'} value={state.password} onChange={e => (state.password = e.target.value)} spellCheck={false} {...{ autocomplete: 'off' }} style={{ width: 'calc(100% - 45px)' }} />

<Button h="2rem" w="5rem" onClick={toggleShowPw}>
{showPw ? 'Hide' : 'Show'}
</Button>
<PasswordInput
name="test"
value={state.password}
onChange={e => (state.password = e.target.value)}
isInvalid={state.password.length <= 3 || state.password.length > 64}
/>

<Tooltip label={'Generate new random password'} placement="top" hasArrow>
<Button onClick={() => state.password = generatePassword(30, allowSpecialChars)} variant="ghost" width="35px" display="inline-flex">
<ReloadOutlined />
</Button>
</Tooltip>
<Tooltip label={'Copy password'} placement="top" hasArrow>
<CopyButton content={state.password} variant="ghost"/>
</Tooltip>
</Flex>
<Checkbox isChecked={allowSpecialChars} onChange={(e) => {setAllowSpecialChars(e.target.checked); state.password = generatePassword(30, e.target.checked)}}>Generate with special characters</Checkbox>
</Flex>
</Label>
</FormField>


<Label text="Mechanism">
<FormField label="SASL Mechanism">
<SingleSelect<'SCRAM-SHA-256' | 'SCRAM-SHA-512'> options={[{
value: 'SCRAM-SHA-256',
label: 'SCRAM-SHA-256',
Expand All @@ -81,7 +67,7 @@ export const CreateServiceAccountEditor = observer((p: { state: CreateUserReques
}]} value={state.mechanism} onChange={e => {
state.mechanism = e;
}}/>
</Label>
</FormField>

</div>
</div>
Expand Down

0 comments on commit 2d5371e

Please sign in to comment.