From cdd4dcc2dbcdf30e454668798c2f90d5055b374a Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 23 Jul 2025 17:06:24 +0200 Subject: [PATCH] fix: Resolve API connection issues and add Quick Start features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix API URL configuration to use relative paths (fixes localhost:8080 error) - Add Quick Start Wizard to dashboard for guided bucket/user setup - Create bash scripts for automated bucket and user creation - Add quickstart.sh for interactive setup experience - Update documentation with correct ports and new features - Improve user onboarding with step-by-step wizard This addresses: - Connection refused errors when creating users/policies - WebSocket connection issues - Need for easy one-step setup process - Port configuration clarity in documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 74 ++- .../src/components/Dashboard/Dashboard.tsx | 38 +- .../components/Dashboard/QuickStartWizard.tsx | 490 ++++++++++++++++++ frontend/src/services/policyService.ts | 2 +- frontend/src/services/userService.ts | 2 +- scripts/create-bucket-with-user.sh | 386 ++++++++++++++ scripts/quickstart.sh | 232 +++++++++ 7 files changed, 1212 insertions(+), 12 deletions(-) create mode 100644 frontend/src/components/Dashboard/QuickStartWizard.tsx create mode 100755 scripts/create-bucket-with-user.sh create mode 100755 scripts/quickstart.sh diff --git a/README.md b/README.md index 4c6a8ef..d4a640e 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ A secure, user-friendly web interface for managing MinIO storage infrastructure. ## Features +- **🚀 Quick Start Wizard** + - One-click setup for bucket, user, and policy + - Step-by-step guided configuration + - Automatic credential generation + - Built-in best practices + - **🪣 Bucket Management** - Create buckets with automatic user creation - List and monitor bucket sizes @@ -44,7 +50,21 @@ A secure, user-friendly web interface for managing MinIO storage infrastructure. ## Quick Start -### 1. Clone the Repository +### Option 1: Interactive Quick Start Script + +```bash +./scripts/quickstart.sh +``` + +This will: +- Check and start all services +- Guide you through initial setup +- Create your first bucket and user +- Provide connection details + +### Option 2: Manual Setup + +#### 1. Clone the Repository ```bash git clone @@ -105,8 +125,16 @@ All configuration is managed through the `.env` file: ### Port Configuration Default ports: -- Backend API: 7510 -- Frontend UI: 7511 +- Backend API: 7510 (not 8080) +- Frontend UI: 7511 (development) or 3000 (React default) +- MinIO: 9000 + +**Important**: The frontend is configured to use relative API URLs. If you're running the backend on a different port or host, set the `REACT_APP_API_URL` environment variable: + +```bash +# For development with custom backend URL +REACT_APP_API_URL=http://localhost:7510 npm start +``` To use different ports, see [Port Configuration Guide](docs/PORT_CONFIGURATION.md). @@ -342,7 +370,45 @@ REPORT_RECIPIENT=info@example.com ## Usage Guide -### Creating a Bucket with User +### Command-Line Tools + +#### Create Bucket with User Script + +```bash +./scripts/create-bucket-with-user.sh -b my-bucket -u my-user -p readwrite +``` + +Options: +- `-b, --bucket `: Bucket name (auto-generated if not specified) +- `-u, --user `: User name (auto-generated if not specified) +- `-p, --policy `: Policy type: `readonly`, `writeonly`, `readwrite` (default) +- `-a, --api-url `: API URL (default: http://localhost:7510) +- `--admin-user `: Admin username for authentication +- `--admin-pass `: Admin password for authentication + +#### Quick Start Script + +```bash +./scripts/quickstart.sh +``` + +This interactive script will: +1. Check if services are running +2. Optionally start services using docker-compose +3. Guide you through creating an initial bucket and user +4. Provide MinIO CLI commands for testing + +### Web Interface + +#### Quick Start Wizard + +Click the "Quick Start" button on the dashboard for a guided setup that will: +- Create a bucket +- Set up a user with secure password +- Configure appropriate access policies +- Provide ready-to-use credentials + +#### Creating a Bucket with User 1. Navigate to **Buckets** page 2. Click **Create Bucket** diff --git a/frontend/src/components/Dashboard/Dashboard.tsx b/frontend/src/components/Dashboard/Dashboard.tsx index 0b3b61e..1bf100a 100644 --- a/frontend/src/components/Dashboard/Dashboard.tsx +++ b/frontend/src/components/Dashboard/Dashboard.tsx @@ -8,14 +8,17 @@ import { LinearProgress, Alert, Paper, + Button, } from '@mui/material'; import { Storage as StorageIcon, People as PeopleIcon, Folder as FolderIcon, Speed as SpeedIcon, + Rocket as RocketIcon, } from '@mui/icons-material'; import api, { handleApiError } from '../../services/api'; +import QuickStartWizard from './QuickStartWizard'; interface DashboardStats { totalBuckets: number; @@ -65,6 +68,7 @@ const Dashboard: React.FC = () => { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); + const [wizardOpen, setWizardOpen] = useState(false); useEffect(() => { loadDashboardData(); @@ -112,12 +116,25 @@ const Dashboard: React.FC = () => { return ( - - Dashboard - - - Welcome to MinIO WebUI. Monitor your storage infrastructure at a glance. - + + + + Dashboard + + + Welcome to MinIO WebUI. Monitor your storage infrastructure at a glance. + + + + @@ -189,6 +206,15 @@ const Dashboard: React.FC = () => { + + setWizardOpen(false)} + onComplete={() => { + setWizardOpen(false); + loadDashboardData(); + }} + /> ); }; diff --git a/frontend/src/components/Dashboard/QuickStartWizard.tsx b/frontend/src/components/Dashboard/QuickStartWizard.tsx new file mode 100644 index 0000000..c400481 --- /dev/null +++ b/frontend/src/components/Dashboard/QuickStartWizard.tsx @@ -0,0 +1,490 @@ +import React, { useState } from 'react'; +import { + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, + Stepper, + Step, + StepLabel, + TextField, + Box, + Typography, + Alert, + FormControl, + InputLabel, + Select, + MenuItem, + Paper, + List, + ListItem, + ListItemIcon, + ListItemText, + IconButton, + InputAdornment, + Chip, + LinearProgress, +} from '@mui/material'; +import { + Storage, + Person, + Security, + Check, + ContentCopy, + Visibility, + VisibilityOff, + Folder, + VpnKey, + Assignment, +} from '@mui/icons-material'; +import userService from '../../services/userService'; +import policyService from '../../services/policyService'; +import api from '../../services/api'; + +interface QuickStartWizardProps { + open: boolean; + onClose: () => void; + onComplete: () => void; +} + +interface SetupData { + bucketName: string; + userName: string; + userPassword: string; + policyType: 'readonly' | 'readwrite' | 'writeonly'; +} + +const QuickStartWizard: React.FC = ({ + open, + onClose, + onComplete, +}) => { + const [activeStep, setActiveStep] = useState(0); + const [setupData, setSetupData] = useState({ + bucketName: '', + userName: '', + userPassword: '', + policyType: 'readwrite', + }); + const [showPassword, setShowPassword] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + const [completedSetup, setCompletedSetup] = useState(null); + + const steps = ['Create Bucket', 'Create User', 'Set Permissions', 'Review & Complete']; + + const generatePassword = () => { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*'; + let password = ''; + for (let i = 0; i < 16; i++) { + password += chars.charAt(Math.floor(Math.random() * chars.length)); + } + setSetupData({ ...setupData, userPassword: password }); + }; + + const handleNext = () => { + setError(''); + if (activeStep === 0 && !setupData.bucketName) { + setError('Please enter a bucket name'); + return; + } + if (activeStep === 1) { + if (!setupData.userName) { + setError('Please enter a username'); + return; + } + if (!setupData.userPassword) { + setError('Please enter or generate a password'); + return; + } + const validation = userService.validatePassword(setupData.userPassword); + if (!validation.valid) { + setError(validation.errors[0]); + return; + } + } + + if (activeStep === steps.length - 1) { + handleComplete(); + } else { + setActiveStep((prevStep) => prevStep + 1); + } + }; + + const handleBack = () => { + setActiveStep((prevStep) => prevStep - 1); + setError(''); + }; + + const handleComplete = async () => { + setLoading(true); + setError(''); + + try { + // Step 1: Create bucket + await api.post('/buckets', { name: setupData.bucketName }); + + // Step 2: Create user + await userService.createUser({ + accessKey: setupData.userName, + secretKey: setupData.userPassword, + }); + + // Step 3: Create policy + const policyName = `${setupData.bucketName}-${setupData.policyType}-policy`; + const policyJson = policyService.generatePolicyFromTemplate( + `bucket${setupData.policyType.charAt(0).toUpperCase() + setupData.policyType.slice(1).replace('only', 'Only')}`, + setupData.bucketName + ); + + await policyService.createPolicy({ + name: policyName, + policy: policyJson, + }); + + // Step 4: Attach policy to user + await policyService.attachPolicy({ + policyName: policyName, + userName: setupData.userName, + }); + + setCompletedSetup({ + bucket: setupData.bucketName, + user: setupData.userName, + password: setupData.userPassword, + policy: policyName, + }); + + setActiveStep(steps.length); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to complete setup'); + } finally { + setLoading(false); + } + }; + + const handleCopyCredentials = () => { + const credentials = `MinIO Credentials\n\nBucket: ${completedSetup.bucket}\nUsername: ${completedSetup.user}\nPassword: ${completedSetup.password}\nPolicy: ${completedSetup.policy}`; + navigator.clipboard.writeText(credentials); + }; + + const handleClose = () => { + if (!loading) { + onClose(); + // Reset wizard state + setActiveStep(0); + setSetupData({ + bucketName: '', + userName: '', + userPassword: '', + policyType: 'readwrite', + }); + setError(''); + setCompletedSetup(null); + } + }; + + const getStepContent = (step: number) => { + switch (step) { + case 0: + return ( + + + Let's start by creating a bucket to store your objects. + + setSetupData({ ...setupData, bucketName: e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '') })} + helperText="Use lowercase letters, numbers, and hyphens only" + error={!!error && activeStep === 0} + /> + + A bucket is a container for storing your files and objects in MinIO. + + + ); + + case 1: + return ( + + + Create a user who will have access to this bucket. + + setSetupData({ ...setupData, userName: e.target.value })} + error={!!error && activeStep === 1} + /> + setSetupData({ ...setupData, userPassword: e.target.value })} + error={!!error && activeStep === 1} + helperText={error || "Min 8 chars, uppercase, lowercase, and number required"} + InputProps={{ + endAdornment: ( + + setShowPassword(!showPassword)} edge="end"> + {showPassword ? : } + + + ), + }} + /> + + + ); + + case 2: + return ( + + + Choose what permissions this user should have for the bucket. + + + Access Level + + + + Policies control what actions users can perform on buckets and objects. + + + ); + + case 3: + return ( + + + Review your configuration before creating: + + + + + + + + + + + + + + + + + + + + + + + + + + + } + /> + + + + + ); + + default: + return null; + } + }; + + const renderCompletionScreen = () => ( + + + + + Setup Complete! + + + Your bucket and user have been created successfully. + + + + + + + Your Credentials + + + + Bucket: {completedSetup.bucket} + + + Username: {completedSetup.user} + + + Password: {completedSetup.password} + + + Policy: {completedSetup.policy} + + + + + + + Save these credentials securely. The password cannot be retrieved later. + + + + Next Steps: + + + + + + + + + + + + + + ); + + return ( + + + + + Quick Start Wizard + + + + {error && activeStep < steps.length && ( + + {error} + + )} + + {activeStep < steps.length ? ( + <> + + {steps.map((label) => ( + + {label} + + ))} + + {getStepContent(activeStep)} + + ) : ( + renderCompletionScreen() + )} + + {loading && } + + + {activeStep < steps.length ? ( + <> + + + + + ) : ( + + )} + + + ); +}; + +export default QuickStartWizard; \ No newline at end of file diff --git a/frontend/src/services/policyService.ts b/frontend/src/services/policyService.ts index ecf461f..4d94427 100644 --- a/frontend/src/services/policyService.ts +++ b/frontend/src/services/policyService.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import { getAuthHeaders } from '../utils/auth'; -const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:8080'; +const API_BASE_URL = process.env.REACT_APP_API_URL || ''; export interface Policy { name: string; diff --git a/frontend/src/services/userService.ts b/frontend/src/services/userService.ts index 3cf7454..213f96f 100644 --- a/frontend/src/services/userService.ts +++ b/frontend/src/services/userService.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import { getAuthHeaders } from '../utils/auth'; -const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:8080'; +const API_BASE_URL = process.env.REACT_APP_API_URL || ''; export interface User { accessKey: string; diff --git a/scripts/create-bucket-with-user.sh b/scripts/create-bucket-with-user.sh new file mode 100755 index 0000000..4728f38 --- /dev/null +++ b/scripts/create-bucket-with-user.sh @@ -0,0 +1,386 @@ +#!/bin/bash + +# MinIO WebUI - Create Bucket with User Script +# This script creates a MinIO bucket and a user with appropriate access policies + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Default values +API_URL="${API_URL:-http://localhost:7510}" +BUCKET_PREFIX="bucket" +USER_PREFIX="user" +POLICY_TYPE="readwrite" + +# Function to print colored output +print_status() { + echo -e "${GREEN}[✓]${NC} $1" +} + +print_error() { + echo -e "${RED}[✗]${NC} $1" +} + +print_info() { + echo -e "${YELLOW}[i]${NC} $1" +} + +# Function to generate secure password +generate_password() { + # Generate a 16-character password with letters, numbers, and special characters + openssl rand -base64 16 | tr -d "=/" | cut -c1-16 +} + +# Function to check if jq is installed +check_dependencies() { + if ! command -v jq &> /dev/null; then + print_error "jq is required but not installed. Please install it first." + exit 1 + fi + + if ! command -v curl &> /dev/null; then + print_error "curl is required but not installed. Please install it first." + exit 1 + fi +} + +# Function to get auth token +get_auth_token() { + local username=$1 + local password=$2 + + response=$(curl -s -X POST "${API_URL}/api/auth/login" \ + -H "Content-Type: application/json" \ + -d "{\"username\":\"${username}\",\"password\":\"${password}\"}" \ + -w "\n%{http_code}") + + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | head -n-1) + + if [ "$http_code" != "200" ]; then + print_error "Failed to authenticate. HTTP Code: $http_code" + echo "$body" | jq -r '.error // .message // .' 2>/dev/null || echo "$body" + return 1 + fi + + token=$(echo "$body" | jq -r '.token // .access_token // .' 2>/dev/null) + if [ -z "$token" ] || [ "$token" == "null" ]; then + print_error "Failed to extract token from response" + return 1 + fi + + echo "$token" +} + +# Function to create bucket +create_bucket() { + local token=$1 + local bucket_name=$2 + + response=$(curl -s -X POST "${API_URL}/api/buckets" \ + -H "Authorization: Bearer ${token}" \ + -H "Content-Type: application/json" \ + -d "{\"name\":\"${bucket_name}\"}" \ + -w "\n%{http_code}") + + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | head -n-1) + + if [ "$http_code" != "200" ] && [ "$http_code" != "201" ]; then + print_error "Failed to create bucket. HTTP Code: $http_code" + echo "$body" | jq -r '.error // .message // .' 2>/dev/null || echo "$body" + return 1 + fi + + print_status "Bucket '${bucket_name}' created successfully" +} + +# Function to create user +create_user() { + local token=$1 + local username=$2 + local password=$3 + + response=$(curl -s -X POST "${API_URL}/api/users" \ + -H "Authorization: Bearer ${token}" \ + -H "Content-Type: application/json" \ + -d "{\"accessKey\":\"${username}\",\"secretKey\":\"${password}\"}" \ + -w "\n%{http_code}") + + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | head -n-1) + + if [ "$http_code" != "200" ] && [ "$http_code" != "201" ]; then + print_error "Failed to create user. HTTP Code: $http_code" + echo "$body" | jq -r '.error // .message // .' 2>/dev/null || echo "$body" + return 1 + fi + + print_status "User '${username}' created successfully" +} + +# Function to create policy +create_policy() { + local token=$1 + local policy_name=$2 + local bucket_name=$3 + local policy_type=$4 + + # Generate policy based on type + case "$policy_type" in + "readonly") + policy_json=$(cat </dev/null || echo "$body" + return 1 + fi + + print_status "Policy '${policy_name}' created successfully" +} + +# Function to attach policy to user +attach_policy() { + local token=$1 + local policy_name=$2 + local username=$3 + + response=$(curl -s -X POST "${API_URL}/api/policies/attach" \ + -H "Authorization: Bearer ${token}" \ + -H "Content-Type: application/json" \ + -d "{\"policyName\":\"${policy_name}\",\"userName\":\"${username}\"}" \ + -w "\n%{http_code}") + + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | head -n-1) + + if [ "$http_code" != "200" ] && [ "$http_code" != "201" ]; then + print_error "Failed to attach policy. HTTP Code: $http_code" + echo "$body" | jq -r '.error // .message // .' 2>/dev/null || echo "$body" + return 1 + fi + + print_status "Policy '${policy_name}' attached to user '${username}'" +} + +# Main function +main() { + echo "MinIO WebUI - Create Bucket with User" + echo "=====================================" + echo + + # Check dependencies + check_dependencies + + # Parse command line arguments + while [[ $# -gt 0 ]]; do + case $1 in + -b|--bucket) + BUCKET_NAME="$2" + shift 2 + ;; + -u|--user) + USER_NAME="$2" + shift 2 + ;; + -p|--policy) + POLICY_TYPE="$2" + shift 2 + ;; + -a|--api-url) + API_URL="$2" + shift 2 + ;; + --admin-user) + ADMIN_USER="$2" + shift 2 + ;; + --admin-pass) + ADMIN_PASS="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [options]" + echo + echo "Options:" + echo " -b, --bucket Bucket name (default: auto-generated)" + echo " -u, --user User name (default: auto-generated)" + echo " -p, --policy Policy type: readonly, writeonly, readwrite (default: readwrite)" + echo " -a, --api-url API URL (default: http://localhost:7510)" + echo " --admin-user Admin username for authentication" + echo " --admin-pass Admin password for authentication" + echo " -h, --help Show this help message" + echo + echo "Example:" + echo " $0 -b my-bucket -u my-user -p readwrite" + echo + exit 0 + ;; + *) + print_error "Unknown option: $1" + exit 1 + ;; + esac + done + + # Generate names if not provided + TIMESTAMP=$(date +%Y%m%d%H%M%S) + BUCKET_NAME=${BUCKET_NAME:-"${BUCKET_PREFIX}-${TIMESTAMP}"} + USER_NAME=${USER_NAME:-"${USER_PREFIX}-${TIMESTAMP}"} + POLICY_NAME="policy-${BUCKET_NAME}" + + # Generate password for new user + USER_PASSWORD=$(generate_password) + + # Get admin credentials + if [ -z "$ADMIN_USER" ] || [ -z "$ADMIN_PASS" ]; then + print_info "Please enter admin credentials" + read -p "Admin username: " ADMIN_USER + read -s -p "Admin password: " ADMIN_PASS + echo + fi + + print_info "Starting setup process..." + echo + + # Authenticate + print_info "Authenticating..." + TOKEN=$(get_auth_token "$ADMIN_USER" "$ADMIN_PASS") + if [ $? -ne 0 ]; then + print_error "Authentication failed" + exit 1 + fi + print_status "Authentication successful" + + # Create bucket + print_info "Creating bucket '${BUCKET_NAME}'..." + create_bucket "$TOKEN" "$BUCKET_NAME" + if [ $? -ne 0 ]; then + print_error "Failed to create bucket" + exit 1 + fi + + # Create user + print_info "Creating user '${USER_NAME}'..." + create_user "$TOKEN" "$USER_NAME" "$USER_PASSWORD" + if [ $? -ne 0 ]; then + print_error "Failed to create user" + exit 1 + fi + + # Create policy + print_info "Creating ${POLICY_TYPE} policy '${POLICY_NAME}'..." + create_policy "$TOKEN" "$POLICY_NAME" "$BUCKET_NAME" "$POLICY_TYPE" + if [ $? -ne 0 ]; then + print_error "Failed to create policy" + exit 1 + fi + + # Attach policy to user + print_info "Attaching policy to user..." + attach_policy "$TOKEN" "$POLICY_NAME" "$USER_NAME" + if [ $? -ne 0 ]; then + print_error "Failed to attach policy" + exit 1 + fi + + echo + echo "=====================================" + echo -e "${GREEN}Setup completed successfully!${NC}" + echo "=====================================" + echo + echo "Bucket Name: ${BUCKET_NAME}" + echo "User Name: ${USER_NAME}" + echo "Password: ${USER_PASSWORD}" + echo "Policy: ${POLICY_NAME} (${POLICY_TYPE})" + echo + echo "You can now use these credentials to access the bucket." + echo + echo "Example MinIO CLI commands:" + echo " mc alias set myminio http://localhost:9000 ${USER_NAME} ${USER_PASSWORD}" + echo " mc ls myminio/${BUCKET_NAME}" + echo +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/scripts/quickstart.sh b/scripts/quickstart.sh new file mode 100755 index 0000000..2660b01 --- /dev/null +++ b/scripts/quickstart.sh @@ -0,0 +1,232 @@ +#!/bin/bash + +# MinIO WebUI Quickstart Script +# This script helps you quickly set up MinIO WebUI with an initial bucket and user + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Default values +MINIO_URL="${MINIO_URL:-http://localhost:9000}" +WEBUI_URL="${WEBUI_URL:-http://localhost:7510}" +FRONTEND_URL="${FRONTEND_URL:-http://localhost:3000}" + +# Function to print colored output +print_header() { + echo -e "\n${BLUE}===================================================${NC}" + echo -e "${BLUE}$1${NC}" + echo -e "${BLUE}===================================================${NC}" +} + +print_status() { + echo -e "${GREEN}[✓]${NC} $1" +} + +print_error() { + echo -e "${RED}[✗]${NC} $1" +} + +print_info() { + echo -e "${YELLOW}[i]${NC} $1" +} + +# Function to check if a service is running +check_service() { + local name=$1 + local url=$2 + + if curl -s -o /dev/null -w "%{http_code}" "$url" | grep -q "200\|401\|403"; then + print_status "$name is running at $url" + return 0 + else + print_error "$name is not accessible at $url" + return 1 + fi +} + +# Function to wait for service +wait_for_service() { + local name=$1 + local url=$2 + local max_attempts=30 + local attempt=0 + + print_info "Waiting for $name to start..." + + while [ $attempt -lt $max_attempts ]; do + if curl -s -o /dev/null -w "%{http_code}" "$url" | grep -q "200\|401\|403"; then + print_status "$name is ready!" + return 0 + fi + + sleep 2 + attempt=$((attempt + 1)) + echo -n "." + done + + echo + print_error "$name failed to start within 60 seconds" + return 1 +} + +# Main quickstart function +quickstart() { + print_header "MinIO WebUI Quickstart" + echo "This script will help you set up MinIO WebUI with initial data" + echo + + # Check if docker-compose is available + if command -v docker-compose &> /dev/null; then + print_info "Docker Compose detected" + + # Ask if user wants to start services + read -p "Do you want to start MinIO WebUI services? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_info "Starting services with docker-compose..." + docker-compose up -d + + # Wait for services to start + wait_for_service "MinIO" "$MINIO_URL" + wait_for_service "Backend API" "$WEBUI_URL" + wait_for_service "Frontend" "$FRONTEND_URL" + fi + else + # Check if services are already running + print_info "Checking if services are running..." + + if ! check_service "Backend API" "$WEBUI_URL/api/health"; then + print_error "Backend API is not running. Please start it first:" + echo " cd backend && npm run dev" + exit 1 + fi + fi + + echo + print_header "Initial Setup" + + # Ask for admin credentials + print_info "Please enter MinIO admin credentials" + read -p "Admin username: " ADMIN_USER + read -s -p "Admin password: " ADMIN_PASS + echo + echo + + # Ask if user wants to create initial bucket and user + read -p "Would you like to create an initial bucket and user? (y/n): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + # Get setup preferences + echo + read -p "Enter bucket name (or press Enter for auto-generated): " BUCKET_NAME + read -p "Enter username (or press Enter for auto-generated): " USER_NAME + + echo + print_info "Select access level:" + echo " 1) Read Only" + echo " 2) Write Only" + echo " 3) Read & Write (default)" + read -p "Choice [1-3]: " POLICY_CHOICE + + case $POLICY_CHOICE in + 1) POLICY_TYPE="readonly" ;; + 2) POLICY_TYPE="writeonly" ;; + *) POLICY_TYPE="readwrite" ;; + esac + + # Run the create-bucket-with-user script + echo + print_info "Creating bucket and user..." + + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + + if [ -f "$SCRIPT_DIR/create-bucket-with-user.sh" ]; then + "$SCRIPT_DIR/create-bucket-with-user.sh" \ + ${BUCKET_NAME:+-b "$BUCKET_NAME"} \ + ${USER_NAME:+-u "$USER_NAME"} \ + -p "$POLICY_TYPE" \ + -a "$WEBUI_URL" \ + --admin-user "$ADMIN_USER" \ + --admin-pass "$ADMIN_PASS" + else + print_error "create-bucket-with-user.sh script not found" + exit 1 + fi + fi + + echo + print_header "Setup Complete!" + echo + print_info "MinIO WebUI is ready to use!" + echo + echo "Access the web interface at: ${FRONTEND_URL}" + echo "API endpoint: ${WEBUI_URL}" + echo "MinIO endpoint: ${MINIO_URL}" + echo + echo "Next steps:" + echo " 1. Open ${FRONTEND_URL} in your browser" + echo " 2. Log in with your MinIO admin credentials" + echo " 3. Use the Quick Start button on the dashboard for guided setup" + echo " 4. Explore buckets, users, and policies pages" + echo + print_status "Happy storage management! 🚀" +} + +# Function to show help +show_help() { + echo "MinIO WebUI Quickstart Script" + echo + echo "Usage: $0 [options]" + echo + echo "Options:" + echo " -h, --help Show this help message" + echo " --minio-url MinIO endpoint (default: http://localhost:9000)" + echo " --webui-url WebUI API endpoint (default: http://localhost:7510)" + echo " --frontend-url Frontend URL (default: http://localhost:3000)" + echo + echo "Environment variables:" + echo " MINIO_URL MinIO endpoint URL" + echo " WEBUI_URL WebUI backend API URL" + echo " FRONTEND_URL Frontend application URL" + echo + echo "Example:" + echo " $0" + echo " $0 --minio-url http://minio.local:9000" + echo +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + --minio-url) + MINIO_URL="$2" + shift 2 + ;; + --webui-url) + WEBUI_URL="$2" + shift 2 + ;; + --frontend-url) + FRONTEND_URL="$2" + shift 2 + ;; + *) + print_error "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Run quickstart +quickstart \ No newline at end of file