fix: Resolve UI errors and improve user creation flow
- Fix validateDOMNesting warnings in Reports and QuickStartWizard components - Fix user creation API field mapping (accessKey/secretKey to username/password) - Increase timeout for bucket-with-user creation to prevent socket hang up errors - Improve credential display with clear Access Key/Secret Key labels - Add MinIO CLI connection examples to credential displays - Make timeout 60 seconds for complex operations that create bucket, user, and policy This fixes: - React DOM nesting warnings with Chip components - 400 Bad Request errors when creating users - Socket hang up errors during bucket+user creation - Clear display of MinIO access credentials 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -119,10 +119,13 @@ const CreateBucketDialog: React.FC<CreateBucketDialogProps> = ({
|
||||
|
||||
if (data.createUser) {
|
||||
// Create bucket with user (like the script)
|
||||
// This operation can take longer as it creates bucket, user, and policy
|
||||
await api.post('/buckets/with-user', {
|
||||
bucketName: data.bucketName,
|
||||
username: data.username!,
|
||||
password: data.password!,
|
||||
}, {
|
||||
timeout: 60000, // 60 seconds timeout for this complex operation
|
||||
});
|
||||
setCredentials({
|
||||
username: data.username!,
|
||||
@@ -300,7 +303,7 @@ const CreateBucketDialog: React.FC<CreateBucketDialogProps> = ({
|
||||
{credentials && (
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
User Credentials
|
||||
MinIO User Credentials
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
||||
Save these credentials securely. They won't be shown again.
|
||||
@@ -309,27 +312,36 @@ const CreateBucketDialog: React.FC<CreateBucketDialogProps> = ({
|
||||
<Box sx={{ bgcolor: 'grey.100', p: 2, borderRadius: 1, mb: 2 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 1 }}>
|
||||
<Typography variant="body2">
|
||||
<strong>Username:</strong> {credentials.username}
|
||||
<strong>Access Key (Username):</strong> {credentials.username}
|
||||
</Typography>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => copyToClipboard(credentials.username)}
|
||||
title="Copy access key"
|
||||
>
|
||||
<ContentCopy fontSize="small" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Typography variant="body2">
|
||||
<strong>Password:</strong> {credentials.password}
|
||||
<strong>Secret Key (Password):</strong> {credentials.password}
|
||||
</Typography>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => copyToClipboard(credentials.password)}
|
||||
title="Copy secret key"
|
||||
>
|
||||
<ContentCopy fontSize="small" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Use these credentials to connect via MinIO Client:
|
||||
</Typography>
|
||||
<Box sx={{ bgcolor: 'grey.900', color: 'grey.100', p: 1, borderRadius: 1, fontFamily: 'monospace', fontSize: '0.875rem', mt: 1 }}>
|
||||
mc alias set myminio http://your-minio-server:9000 {credentials.username} {credentials.password}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
@@ -123,7 +123,9 @@ const QuickStartWizard: React.FC<QuickStartWizardProps> = ({
|
||||
|
||||
try {
|
||||
// Step 1: Create bucket
|
||||
await api.post('/buckets', { name: setupData.bucketName });
|
||||
await api.post('/buckets', { name: setupData.bucketName }, {
|
||||
timeout: 30000, // 30 seconds timeout
|
||||
});
|
||||
|
||||
// Step 2: Create user
|
||||
await userService.createUser({
|
||||
@@ -165,7 +167,7 @@ const QuickStartWizard: React.FC<QuickStartWizardProps> = ({
|
||||
};
|
||||
|
||||
const handleCopyCredentials = () => {
|
||||
const credentials = `MinIO Credentials\n\nBucket: ${completedSetup.bucket}\nUsername: ${completedSetup.user}\nPassword: ${completedSetup.password}\nPolicy: ${completedSetup.policy}`;
|
||||
const credentials = `MinIO Credentials\n\nBucket: ${completedSetup.bucket}\nAccess Key: ${completedSetup.user}\nSecret Key: ${completedSetup.password}\nPolicy: ${completedSetup.policy}\n\nConnection Example:\nmc alias set myminio http://your-minio-server:9000 ${completedSetup.user} ${completedSetup.password}`;
|
||||
navigator.clipboard.writeText(credentials);
|
||||
};
|
||||
|
||||
@@ -335,14 +337,16 @@ const QuickStartWizard: React.FC<QuickStartWizardProps> = ({
|
||||
<ListItemText
|
||||
primary="Access Level"
|
||||
secondary={
|
||||
<Chip
|
||||
label={setupData.policyType}
|
||||
size="small"
|
||||
color={
|
||||
setupData.policyType === 'readwrite' ? 'success' :
|
||||
setupData.policyType === 'readonly' ? 'info' : 'warning'
|
||||
}
|
||||
/>
|
||||
<Box component="span">
|
||||
<Chip
|
||||
label={setupData.policyType}
|
||||
size="small"
|
||||
color={
|
||||
setupData.policyType === 'readwrite' ? 'success' :
|
||||
setupData.policyType === 'readonly' ? 'info' : 'warning'
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
@@ -371,17 +375,17 @@ const QuickStartWizard: React.FC<QuickStartWizardProps> = ({
|
||||
<Paper variant="outlined" sx={{ p: 3, mt: 2, bgcolor: 'grey.50' }}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
<Assignment sx={{ verticalAlign: 'middle', mr: 1 }} />
|
||||
Your Credentials
|
||||
Your MinIO Credentials
|
||||
</Typography>
|
||||
<Box sx={{ fontFamily: 'monospace', mt: 2 }}>
|
||||
<Typography variant="body2">
|
||||
<strong>Bucket:</strong> {completedSetup.bucket}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
<strong>Username:</strong> {completedSetup.user}
|
||||
<strong>Access Key:</strong> {completedSetup.user}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
<strong>Password:</strong> {completedSetup.password}
|
||||
<strong>Secret Key:</strong> {completedSetup.password}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
<strong>Policy:</strong> {completedSetup.policy}
|
||||
|
||||
@@ -311,14 +311,16 @@ const Reports: React.FC = () => {
|
||||
</Box>
|
||||
{scheduleInfo && (
|
||||
<>
|
||||
<Typography variant="body2" paragraph>
|
||||
<strong>Status:</strong>{' '}
|
||||
<Box sx={{ mb: 2 }}>
|
||||
<Typography variant="body2" component="span">
|
||||
<strong>Status:</strong>{' '}
|
||||
</Typography>
|
||||
<Chip
|
||||
label={scheduleInfo.enabled ? 'Enabled' : 'Disabled'}
|
||||
size="small"
|
||||
color={scheduleInfo.enabled ? 'success' : 'default'}
|
||||
/>
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="body2" paragraph>
|
||||
<strong>Schedule:</strong> {scheduleInfo.schedule}
|
||||
</Typography>
|
||||
|
||||
@@ -39,7 +39,10 @@ class UserService {
|
||||
|
||||
async createUser(userData: CreateUserRequest): Promise<void> {
|
||||
try {
|
||||
await axios.post(`${this.baseURL}/users`, userData, {
|
||||
await axios.post(`${this.baseURL}/users`, {
|
||||
username: userData.accessKey,
|
||||
password: userData.secretKey,
|
||||
}, {
|
||||
headers: getAuthHeaders(),
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user