#!/bin/bash # Database Management Script # Handles backup and restore operations for both SQLite (frontend) and PostgreSQL (backend) set -e # Exit on any error # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BACKEND_DIR="$SCRIPT_DIR/legalconsenthub-backend" FRONTEND_DIR="$SCRIPT_DIR/legalconsenthub" # Database files SQLITE_DB="$FRONTEND_DIR/sqlite.db" SQLITE_BACKUP="$FRONTEND_DIR/sqlite-backup.db" POSTGRES_BACKUP="$BACKEND_DIR/src/main/resources/legalconsenthub-db-backup.sql" # PostgreSQL connection details POSTGRES_HOST="localhost" POSTGRES_PORT="5432" POSTGRES_DB="legalconsenthub" POSTGRES_USER="legalconsenthub" POSTGRES_PASSWORD="legalconsenthub" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Helper functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check if PostgreSQL container is running check_postgres() { # Check if the legalconsenthub-backend container is running if docker ps --format "table {{.Names}}\t{{.Status}}" | grep -q "legalconsenthub-backend.*Up"; then # Additional check to see if the database is ready if docker exec legalconsenthub-backend pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" &>/dev/null; then return 0 fi fi return 1 } # Check if PostgreSQL container exists and is running ensure_postgres_running() { if ! check_postgres; then log_error "PostgreSQL container 'legalconsenthub-backend' is not running." log_error "Please start the container before running backup/restore operations." exit 1 fi } # Create backup of current SQLite database backup_sqlite() { log_info "Creating SQLite backup..." if [ -f "$SQLITE_DB" ]; then cp "$SQLITE_DB" "$SQLITE_BACKUP" log_success "SQLite backup created: $SQLITE_BACKUP" else log_warning "SQLite database not found: $SQLITE_DB" fi } # Create backup of current PostgreSQL database backup_postgres() { log_info "Creating PostgreSQL backup..." ensure_postgres_running # Create temporary backup file local temp_backup="${POSTGRES_BACKUP}.tmp" # Generate backup with pg_dump docker exec legalconsenthub-backend pg_dump \ -U "$POSTGRES_USER" \ -d "$POSTGRES_DB" \ --no-owner \ --no-privileges \ --clean \ --if-exists \ > "$temp_backup" # Add force DROP statements at the beginning { echo "--" echo "-- PostgreSQL database dump" echo "--" echo "" echo "--" echo "-- Force drop all tables and constraints to ensure clean restoration" echo "--" echo "" echo "DROP TABLE IF EXISTS public.user_organization_roles CASCADE;" echo "DROP TABLE IF EXISTS public.notification CASCADE;" echo "DROP TABLE IF EXISTS public.form_element_section CASCADE;" echo "DROP TABLE IF EXISTS public.form_element_options CASCADE;" echo "DROP TABLE IF EXISTS public.form_element CASCADE;" echo "DROP TABLE IF EXISTS public.comment CASCADE;" echo "DROP TABLE IF EXISTS public.application_form CASCADE;" echo "DROP TABLE IF EXISTS public.app_user CASCADE;" echo "DROP TABLE IF EXISTS public.databasechangeloglock CASCADE;" echo "DROP TABLE IF EXISTS public.databasechangelog CASCADE;" echo "" echo "-- Drop any remaining sequences, views, or other objects" echo "DROP SEQUENCE IF EXISTS public.hibernate_sequence CASCADE;" echo "" echo "-- Reset database configuration" # Skip the first few lines of the original dump (headers) and append the rest tail -n +4 "$temp_backup" } > "$POSTGRES_BACKUP" # Remove temporary file rm "$temp_backup" log_success "PostgreSQL backup created with force DROP statements: $POSTGRES_BACKUP" } # Restore SQLite database from backup restore_sqlite() { log_info "Restoring SQLite database from backup..." if [ -f "$SQLITE_BACKUP" ]; then # Remove current database if it exists if [ -f "$SQLITE_DB" ]; then rm "$SQLITE_DB" log_info "Removed current SQLite database" fi # Copy backup to current database cp "$SQLITE_BACKUP" "$SQLITE_DB" log_success "SQLite database restored from: $SQLITE_BACKUP" else log_error "SQLite backup not found: $SQLITE_BACKUP" exit 1 fi } # Restore PostgreSQL database from backup restore_postgres() { log_info "Restoring PostgreSQL database from backup..." if [ ! -f "$POSTGRES_BACKUP" ]; then log_error "PostgreSQL backup not found: $POSTGRES_BACKUP" exit 1 fi ensure_postgres_running # Terminate all connections and drop/recreate database log_info "Terminating all connections to PostgreSQL database..." docker exec legalconsenthub-backend psql \ -U "$POSTGRES_USER" \ -d "postgres" \ -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$POSTGRES_DB' AND pid <> pg_backend_pid();" log_info "Dropping and recreating PostgreSQL database..." docker exec legalconsenthub-backend psql \ -U "$POSTGRES_USER" \ -d "postgres" \ -c "DROP DATABASE IF EXISTS $POSTGRES_DB;" docker exec legalconsenthub-backend psql \ -U "$POSTGRES_USER" \ -d "postgres" \ -c "CREATE DATABASE $POSTGRES_DB OWNER $POSTGRES_USER;" # Restore from backup log_info "Restoring database from backup file..." docker exec -i legalconsenthub-backend psql \ -U "$POSTGRES_USER" \ -d "$POSTGRES_DB" \ < "$POSTGRES_BACKUP" log_success "PostgreSQL database restored from: $POSTGRES_BACKUP" } # Show usage information show_usage() { echo "Database Management Script" echo "" echo "Usage: $0 [COMMAND]" echo "" echo "Commands:" echo " backup Create backups of current databases" echo " restore Restore databases from backups" echo " backup-sqlite Create backup of SQLite database only" echo " backup-postgres Create backup of PostgreSQL database only" echo " restore-sqlite Restore SQLite database from backup only" echo " restore-postgres Restore PostgreSQL database from backup only" echo " status Show current status" echo " help Show this help message" echo "" echo "Note: PostgreSQL operations require the 'legalconsenthub-backend' container to be running." echo "" echo "Examples:" echo " $0 backup # Create backups of both databases" echo " $0 restore # Restore both databases from backups" echo " $0 backup-sqlite # Backup only SQLite database" echo " $0 status # Check database status" } # Show current status show_status() { log_info "Database Status:" echo "" # SQLite status echo "SQLite Database:" if [ -f "$SQLITE_DB" ]; then local size=$(du -h "$SQLITE_DB" | cut -f1) local modified=$(stat -c "%y" "$SQLITE_DB" 2>/dev/null || stat -f "%Sm" "$SQLITE_DB" 2>/dev/null || echo "Unknown") echo " Current DB: ✅ $SQLITE_DB ($size, modified: $modified)" else echo " Current DB: ❌ Not found" fi if [ -f "$SQLITE_BACKUP" ]; then local backup_size=$(du -h "$SQLITE_BACKUP" | cut -f1) local backup_modified=$(stat -c "%y" "$SQLITE_BACKUP" 2>/dev/null || stat -f "%Sm" "$SQLITE_BACKUP" 2>/dev/null || echo "Unknown") echo " Backup: ✅ $SQLITE_BACKUP ($backup_size, modified: $backup_modified)" else echo " Backup: ❌ Not found" fi echo "" # PostgreSQL status echo "PostgreSQL Database:" if check_postgres; then echo " Container: ✅ legalconsenthub-backend (Running)" local db_size=$(docker exec legalconsenthub-backend psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -t -c "SELECT pg_size_pretty(pg_database_size('$POSTGRES_DB'));" 2>/dev/null | xargs || echo "Unknown") echo " Database: ✅ $POSTGRES_DB ($db_size)" else echo " Container: ❌ legalconsenthub-backend (Not running or not found)" echo " Database: ❓ Cannot check (container not available)" fi if [ -f "$POSTGRES_BACKUP" ]; then local backup_size=$(du -h "$POSTGRES_BACKUP" | cut -f1) local backup_modified=$(stat -c "%y" "$POSTGRES_BACKUP" 2>/dev/null || stat -f "%Sm" "$POSTGRES_BACKUP" 2>/dev/null || echo "Unknown") echo " Backup: ✅ $POSTGRES_BACKUP ($backup_size, modified: $backup_modified)" else echo " Backup: ❌ Not found" fi } # Main script logic main() { case "${1:-help}" in "backup") log_info "Creating backups of both databases..." backup_sqlite backup_postgres log_success "All backups completed successfully!" ;; "restore") log_info "Restoring both databases from backups..." restore_sqlite restore_postgres log_success "All databases restored successfully!" ;; "backup-sqlite") backup_sqlite ;; "backup-postgres") backup_postgres ;; "restore-sqlite") restore_sqlite ;; "restore-postgres") restore_postgres ;; "status") show_status ;; "help"|"-h"|"--help") show_usage ;; *) log_error "Unknown command: $1" echo "" show_usage exit 1 ;; esac } # Check for required tools check_dependencies() { local missing_tools=() # Check for Docker if ! command -v docker &> /dev/null; then missing_tools+=("docker") fi if [ ${#missing_tools[@]} -gt 0 ]; then log_error "Missing required tools:" for tool in "${missing_tools[@]}"; do echo " - $tool" done echo "" echo "Please install the missing tools and try again." exit 1 fi } # Run dependency check and main function check_dependencies main "$@"