feat: initial version
Some checks failed
Test Stalwart Installation Action / Basic Installation (No Config) (pull_request) Failing after 35s
Test Stalwart Installation Action / Installation with Admin Password (pull_request) Failing after 2m16s
Test Stalwart Installation Action / Error Handling Tests (pull_request) Successful in 2m17s
Test Stalwart Installation Action / Full Configuration (Domains + Users) (pull_request) Failing after 2m21s
Test Stalwart Installation Action / Test on Ubuntu ubuntu-20.04 (pull_request) Has been cancelled
Test Stalwart Installation Action / Test on Ubuntu ubuntu-22.04 (pull_request) Has been cancelled
Test Stalwart Installation Action / Test on Ubuntu ubuntu-24.04 (pull_request) Has been cancelled
Test Stalwart Installation Action / Test Summary (pull_request) Has been cancelled
Some checks failed
Test Stalwart Installation Action / Basic Installation (No Config) (pull_request) Failing after 35s
Test Stalwart Installation Action / Installation with Admin Password (pull_request) Failing after 2m16s
Test Stalwart Installation Action / Error Handling Tests (pull_request) Successful in 2m17s
Test Stalwart Installation Action / Full Configuration (Domains + Users) (pull_request) Failing after 2m21s
Test Stalwart Installation Action / Test on Ubuntu ubuntu-20.04 (pull_request) Has been cancelled
Test Stalwart Installation Action / Test on Ubuntu ubuntu-22.04 (pull_request) Has been cancelled
Test Stalwart Installation Action / Test on Ubuntu ubuntu-24.04 (pull_request) Has been cancelled
Test Stalwart Installation Action / Test Summary (pull_request) Has been cancelled
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
297
scripts/configure.sh
Executable file
297
scripts/configure.sh
Executable file
@@ -0,0 +1,297 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Stalwart Post-Installation Configuration Script
|
||||
# Configures admin password, domains, and users via REST API
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Source utility functions
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/utils.sh"
|
||||
|
||||
# Configuration
|
||||
readonly STALWART_PATH="${STALWART_INSTALL_PATH:-/opt/stalwart}"
|
||||
readonly API_URL="http://localhost:8080/api"
|
||||
readonly DEFAULT_ADMIN_PASSWORD="changeme"
|
||||
readonly MAX_RETRIES=60
|
||||
readonly RETRY_DELAY=2
|
||||
|
||||
# Environment variables (passed from action.yml)
|
||||
ADMIN_PASSWORD="${STALWART_ADMIN_PASSWORD:-}"
|
||||
DOMAINS_JSON="${STALWART_DOMAINS:-}"
|
||||
USERS_JSON="${STALWART_USERS:-}"
|
||||
|
||||
# Main configuration function
|
||||
main() {
|
||||
log_info "Starting Stalwart post-installation configuration"
|
||||
|
||||
# Wait for Stalwart API to be ready
|
||||
if ! wait_for_stalwart_api; then
|
||||
log_error "Stalwart API failed to become ready within timeout"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Authenticate with default password first
|
||||
log_info "Authenticating with Stalwart API..."
|
||||
local auth_token
|
||||
if ! auth_token=$(authenticate "$DEFAULT_ADMIN_PASSWORD"); then
|
||||
log_error "Failed to authenticate with default admin password"
|
||||
log_info "This might mean Stalwart has already been configured"
|
||||
|
||||
# Try with provided password if different
|
||||
if [ -n "$ADMIN_PASSWORD" ] && [ "$ADMIN_PASSWORD" != "$DEFAULT_ADMIN_PASSWORD" ]; then
|
||||
log_info "Trying with provided admin password..."
|
||||
if ! auth_token=$(authenticate "$ADMIN_PASSWORD"); then
|
||||
log_error "Failed to authenticate with provided password"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log_success "Authentication successful"
|
||||
|
||||
# Update admin password if provided and different from default
|
||||
if [ -n "$ADMIN_PASSWORD" ] && [ "$ADMIN_PASSWORD" != "$DEFAULT_ADMIN_PASSWORD" ]; then
|
||||
log_info "Updating admin password..."
|
||||
if update_admin_password "$auth_token" "$ADMIN_PASSWORD"; then
|
||||
log_success "Admin password updated successfully"
|
||||
# Re-authenticate with new password
|
||||
if ! auth_token=$(authenticate "$ADMIN_PASSWORD"); then
|
||||
log_error "Failed to re-authenticate with new password"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_warning "Failed to update admin password, continuing with default"
|
||||
fi
|
||||
else
|
||||
log_info "No admin password provided, keeping default (changeme)"
|
||||
log_warning "⚠️ Remember to change the default password!"
|
||||
fi
|
||||
|
||||
# Create domains if provided
|
||||
if [ -n "$DOMAINS_JSON" ]; then
|
||||
log_info "Creating domains..."
|
||||
if validate_json "$DOMAINS_JSON"; then
|
||||
create_domains "$auth_token" "$DOMAINS_JSON"
|
||||
else
|
||||
log_error "Invalid domains JSON format"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_info "No domains specified, skipping domain creation"
|
||||
fi
|
||||
|
||||
# Create users if provided
|
||||
if [ -n "$USERS_JSON" ]; then
|
||||
log_info "Creating users..."
|
||||
if validate_json "$USERS_JSON"; then
|
||||
create_users "$auth_token" "$USERS_JSON"
|
||||
else
|
||||
log_error "Invalid users JSON format"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_info "No users specified, skipping user creation"
|
||||
fi
|
||||
|
||||
log_success "Stalwart configuration completed successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Wait for Stalwart API to be ready
|
||||
wait_for_stalwart_api() {
|
||||
log_info "Waiting for Stalwart API to be ready (timeout: ${MAX_RETRIES}s)..."
|
||||
|
||||
local attempt=0
|
||||
while [ $attempt -lt $MAX_RETRIES ]; do
|
||||
# Try to access the API login endpoint
|
||||
if curl -sf -m 5 "${API_URL%/api}/login" >/dev/null 2>&1; then
|
||||
log_success "Stalwart API is ready"
|
||||
return 0
|
||||
fi
|
||||
|
||||
attempt=$((attempt + 1))
|
||||
if [ $attempt -lt $MAX_RETRIES ]; then
|
||||
sleep $RETRY_DELAY
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Authenticate with Stalwart API
|
||||
# Args: $1 = password
|
||||
# Returns: JWT token on stdout
|
||||
authenticate() {
|
||||
local password="$1"
|
||||
|
||||
local response
|
||||
local token
|
||||
|
||||
response=$(curl -sf -X POST "${API_URL}/authenticate" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"login\":\"admin\",\"password\":\"${password}\"}" 2>&1) || {
|
||||
return 1
|
||||
}
|
||||
|
||||
token=$(echo "$response" | jq -r '.token // empty' 2>/dev/null)
|
||||
|
||||
if [ -z "$token" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$token"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Update admin password
|
||||
# Args: $1 = auth token, $2 = new password
|
||||
update_admin_password() {
|
||||
local token="$1"
|
||||
local new_password="$2"
|
||||
|
||||
local response
|
||||
response=$(curl -sf -X PUT "${API_URL}/account/admin" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"password\":\"${new_password}\"}" 2>&1) || {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Create domains from JSON array
|
||||
# Args: $1 = auth token, $2 = domains JSON array
|
||||
create_domains() {
|
||||
local token="$1"
|
||||
local domains_json="$2"
|
||||
|
||||
local domain_count
|
||||
domain_count=$(echo "$domains_json" | jq 'length' 2>/dev/null)
|
||||
|
||||
if [ -z "$domain_count" ] || [ "$domain_count" = "0" ]; then
|
||||
log_warning "No domains found in JSON array"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Creating $domain_count domain(s)..."
|
||||
|
||||
local index=0
|
||||
local created=0
|
||||
local failed=0
|
||||
|
||||
while [ $index -lt "$domain_count" ]; do
|
||||
local domain
|
||||
domain=$(echo "$domains_json" | jq -c ".[$index]" 2>/dev/null)
|
||||
|
||||
if [ -z "$domain" ] || [ "$domain" = "null" ]; then
|
||||
log_warning "Skipping invalid domain at index $index"
|
||||
failed=$((failed + 1))
|
||||
index=$((index + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
local domain_name
|
||||
domain_name=$(echo "$domain" | jq -r '.name // empty' 2>/dev/null)
|
||||
|
||||
if [ -z "$domain_name" ]; then
|
||||
log_warning "Skipping domain without 'name' field at index $index"
|
||||
failed=$((failed + 1))
|
||||
index=$((index + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Create domain via API
|
||||
if curl -sf -X POST "${API_URL}/domain" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$domain" >/dev/null 2>&1; then
|
||||
log_success "✓ Created domain: $domain_name"
|
||||
created=$((created + 1))
|
||||
else
|
||||
log_warning "✗ Failed to create domain: $domain_name"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
index=$((index + 1))
|
||||
done
|
||||
|
||||
log_info "Domain creation summary: $created created, $failed failed"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Create users from JSON array
|
||||
# Args: $1 = auth token, $2 = users JSON array
|
||||
create_users() {
|
||||
local token="$1"
|
||||
local users_json="$2"
|
||||
|
||||
local user_count
|
||||
user_count=$(echo "$users_json" | jq 'length' 2>/dev/null)
|
||||
|
||||
if [ -z "$user_count" ] || [ "$user_count" = "0" ]; then
|
||||
log_warning "No users found in JSON array"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Creating $user_count user(s)..."
|
||||
|
||||
local index=0
|
||||
local created=0
|
||||
local failed=0
|
||||
|
||||
while [ $index -lt "$user_count" ]; do
|
||||
local user
|
||||
user=$(echo "$users_json" | jq -c ".[$index]" 2>/dev/null)
|
||||
|
||||
if [ -z "$user" ] || [ "$user" = "null" ]; then
|
||||
log_warning "Skipping invalid user at index $index"
|
||||
failed=$((failed + 1))
|
||||
index=$((index + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
local email
|
||||
email=$(echo "$user" | jq -r '.email // empty' 2>/dev/null)
|
||||
|
||||
if [ -z "$email" ]; then
|
||||
log_warning "Skipping user without 'email' field at index $index"
|
||||
failed=$((failed + 1))
|
||||
index=$((index + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Build API payload (name, password, description, quota)
|
||||
local payload
|
||||
payload=$(echo "$user" | jq '{
|
||||
name: .email,
|
||||
password: .password,
|
||||
description: (.name // .email),
|
||||
quota: (.quota // 1073741824)
|
||||
}' 2>/dev/null)
|
||||
|
||||
# Create user via API
|
||||
if curl -sf -X POST "${API_URL}/account" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$payload" >/dev/null 2>&1; then
|
||||
log_success "✓ Created user: $email"
|
||||
created=$((created + 1))
|
||||
else
|
||||
log_warning "✗ Failed to create user: $email"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
index=$((index + 1))
|
||||
done
|
||||
|
||||
log_info "User creation summary: $created created, $failed failed"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Execute main function
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user