feat: add password support for local user creation and per-user login

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-17 19:08:19 +01:00
parent 653ef958ed
commit 6f5b5b8655
7 changed files with 71 additions and 30 deletions

View File

@@ -267,7 +267,7 @@ export function useDeleteRole() {
export function useCreateUser() {
const qc = useQueryClient();
return useMutation({
mutationFn: (data: { username: string; displayName?: string; email?: string }) =>
mutationFn: (data: { username: string; displayName?: string; email?: string; password?: string }) =>
adminFetch<UserDetail>('/users', {
method: 'POST',
body: JSON.stringify(data),

View File

@@ -37,6 +37,7 @@ export function UsersTab() {
const [newUsername, setNewUsername] = useState('');
const [newDisplayName, setNewDisplayName] = useState('');
const [newEmail, setNewEmail] = useState('');
const [newPassword, setNewPassword] = useState('');
const [createError, setCreateError] = useState('');
const createUser = useCreateUser();
@@ -110,10 +111,16 @@ export function UsersTab() {
onChange={e => setNewEmail(e.target.value)}
placeholder="Email (optional)" />
</div>
<div className={styles.createFormRow}>
<label className={styles.createFormLabel}>Password</label>
<input className={styles.createFormInput} type="password" value={newPassword}
onChange={e => setNewPassword(e.target.value)}
placeholder="Password (required for local login)" />
</div>
{createError && <div className={styles.createFormError}>{createError}</div>}
<div className={styles.createFormActions}>
<button type="button" className={styles.createFormBtn}
onClick={() => { setShowCreateForm(false); setNewUsername(''); setNewDisplayName(''); setNewEmail(''); setCreateError(''); }}>Cancel</button>
onClick={() => { setShowCreateForm(false); setNewUsername(''); setNewDisplayName(''); setNewEmail(''); setNewPassword(''); setCreateError(''); }}>Cancel</button>
<button type="button" className={styles.createFormBtnPrimary}
disabled={!newUsername.trim() || createUser.isPending}
onClick={() => {
@@ -121,8 +128,9 @@ export function UsersTab() {
username: newUsername.trim(),
displayName: newDisplayName.trim() || undefined,
email: newEmail.trim() || undefined,
password: newPassword || undefined,
}, {
onSuccess: () => { setShowCreateForm(false); setNewUsername(''); setNewDisplayName(''); setNewEmail(''); setCreateError(''); },
onSuccess: () => { setShowCreateForm(false); setNewUsername(''); setNewDisplayName(''); setNewEmail(''); setNewPassword(''); setCreateError(''); },
onError: (err) => setCreateError(err instanceof Error ? err.message : 'Failed to create user'),
});
}}>Create</button>