## Scripts de Base de Datos (12 archivos) - init-database.sh: Inicializacion completa con usuario y BD - init-database-v3.sh: Version con dotenv-vault - reset-database.sh: Reset BD manteniendo usuario - recreate-database.sh: Recreacion completa - cleanup-duplicados.sh, fix-duplicate-triggers.sh - verify-users.sh, verify-missions-status.sh - load-users-and-profiles.sh, DB-127-validar-gaps.sh ## Scripts de Produccion (5 archivos) - build-production.sh: Compilar backend y frontend - deploy-production.sh: Desplegar con PM2 - pre-deploy-check.sh: Validaciones pre-deploy - repair-missing-data.sh: Reparar datos faltantes - migrate-missing-objects.sh: Migrar objetos SQL ## Documentacion (7 archivos) - GUIA-DESPLIEGUE-PRODUCCION-COMPLETA.md - GUIA-ACTUALIZACION-PRODUCCION.md - GUIA-VALIDACION-PRODUCCION.md - GUIA-DEPLOYMENT-AGENTE-PRODUCCION.md - GUIA-SSL-NGINX-PRODUCCION.md - GUIA-SSL-AUTOFIRMADO.md - DIRECTIVA-DEPLOYMENT.md ## Actualizaciones DDL/Seeds - 99-post-ddl-permissions.sql: Permisos actualizados - LOAD-SEEDS-gamification_system.sh: Seeds completos ## Nuevos archivos - PROMPT-AGENTE-PRODUCCION.md: Prompt para agente productivo - FLUJO-CARGA-LIMPIA.md: Documentacion de carga limpia Resuelve: Problema de carga de BD entre dev y produccion Cumple: DIRECTIVA-POLITICA-CARGA-LIMPIA.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
504 lines
15 KiB
Bash
Executable File
504 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
##############################################################################
|
|
# GAMILIT Platform - Database Reset Script
|
|
#
|
|
# Propósito: Reiniciar SOLO la base de datos (mantiene usuario existente)
|
|
# ⚠️ Elimina datos pero NO el usuario PostgreSQL
|
|
#
|
|
# Uso:
|
|
# ./reset-database.sh # Modo interactivo
|
|
# ./reset-database.sh --env dev # Desarrollo
|
|
# ./reset-database.sh --env prod # Producción
|
|
# ./reset-database.sh --env dev --force # Sin confirmación
|
|
# ./reset-database.sh --password "mi_pass" # Con password conocido
|
|
#
|
|
# Funcionalidades:
|
|
# 1. ⚠️ Elimina la BD gamilit_platform
|
|
# 2. ✅ Mantiene el usuario gamilit_user
|
|
# 3. Recrea BD, ejecuta DDL y carga seeds
|
|
#
|
|
# Ideal para:
|
|
# - Usuario ya existe con password conocido
|
|
# - Resetear datos sin tocar configuración de usuario
|
|
# - Ambientes donde el usuario tiene permisos específicos
|
|
#
|
|
##############################################################################
|
|
|
|
set -e
|
|
|
|
# Colores
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# Configuración de rutas
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DATABASE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
DDL_DIR="$DATABASE_ROOT/ddl"
|
|
SEEDS_DIR="$DATABASE_ROOT/seeds"
|
|
|
|
# Configuración de base de datos
|
|
DB_NAME="gamilit_platform"
|
|
DB_USER="gamilit_user"
|
|
DB_HOST="localhost"
|
|
DB_PORT="5432"
|
|
POSTGRES_USER="postgres"
|
|
|
|
# Variables
|
|
ENVIRONMENT=""
|
|
FORCE_MODE=false
|
|
DB_PASSWORD=""
|
|
|
|
# ============================================================================
|
|
# FUNCIONES AUXILIARES
|
|
# ============================================================================
|
|
|
|
print_header() {
|
|
echo ""
|
|
echo -e "${YELLOW}========================================${NC}"
|
|
echo -e "${YELLOW}$1${NC}"
|
|
echo -e "${YELLOW}========================================${NC}"
|
|
echo ""
|
|
}
|
|
|
|
print_step() {
|
|
echo -e "${CYAN}▶ $1${NC}"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}✓ $1${NC}"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}✗ $1${NC}"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}⚠ $1${NC}"
|
|
}
|
|
|
|
print_info() {
|
|
echo " $1"
|
|
}
|
|
|
|
show_help() {
|
|
cat << EOF
|
|
GAMILIT Platform - Reset de Base de Datos (Mantiene Usuario)
|
|
|
|
Uso: $0 [OPCIONES]
|
|
|
|
Opciones:
|
|
--env dev|prod Ambiente
|
|
--password PASS Password del usuario existente (requerido)
|
|
--force No pedir confirmación
|
|
--help Mostrar ayuda
|
|
|
|
Ejemplos:
|
|
$0 --env dev --password "mi_password"
|
|
$0 --env prod --password "prod_pass" --force
|
|
|
|
Este script:
|
|
1. Elimina la base de datos gamilit_platform
|
|
2. Mantiene el usuario gamilit_user
|
|
3. Recrea la BD con DDL y seeds
|
|
|
|
⚠️ Requiere conocer el password del usuario existente
|
|
|
|
EOF
|
|
}
|
|
|
|
# ============================================================================
|
|
# FUNCIONES SQL
|
|
# ============================================================================
|
|
|
|
execute_as_postgres() {
|
|
local sql="$1"
|
|
if [ "$USE_SUDO" = true ]; then
|
|
echo "$sql" | sudo -u postgres psql 2>&1
|
|
else
|
|
PGPASSWORD="$PGPASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$POSTGRES_USER" -c "$sql" 2>&1
|
|
fi
|
|
}
|
|
|
|
query_as_postgres() {
|
|
local sql="$1"
|
|
if [ "$USE_SUDO" = true ]; then
|
|
echo "$sql" | sudo -u postgres psql -t | xargs
|
|
else
|
|
PGPASSWORD="$PGPASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$POSTGRES_USER" -t -c "$sql" | xargs
|
|
fi
|
|
}
|
|
|
|
execute_sql_file() {
|
|
local file="$1"
|
|
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$file" 2>&1
|
|
}
|
|
|
|
# ============================================================================
|
|
# VERIFICACIÓN
|
|
# ============================================================================
|
|
|
|
check_prerequisites() {
|
|
print_step "Verificando prerequisitos..."
|
|
|
|
if ! command -v psql &> /dev/null; then
|
|
print_error "psql no encontrado"
|
|
exit 1
|
|
fi
|
|
print_success "psql encontrado"
|
|
|
|
if [ ! -d "$DDL_DIR" ]; then
|
|
print_error "Directorio DDL no encontrado: $DDL_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -d "$SEEDS_DIR" ]; then
|
|
print_error "Directorio seeds no encontrado: $SEEDS_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar conexión PostgreSQL
|
|
if sudo -n -u postgres psql -c "SELECT 1" &> /dev/null 2>&1; then
|
|
USE_SUDO=true
|
|
print_success "Conectado a PostgreSQL (sudo)"
|
|
elif [ -n "$PGPASSWORD" ] && psql -h "$DB_HOST" -p "$DB_PORT" -U "$POSTGRES_USER" -c "SELECT 1" &> /dev/null 2>&1; then
|
|
USE_SUDO=false
|
|
print_success "Conectado a PostgreSQL (TCP)"
|
|
else
|
|
print_error "No se puede conectar a PostgreSQL"
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar que el usuario existe
|
|
user_exists=$(query_as_postgres "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'")
|
|
if [ -z "$user_exists" ]; then
|
|
print_error "Usuario '$DB_USER' no existe"
|
|
print_info "Usa init-database.sh para crear el usuario primero"
|
|
exit 1
|
|
fi
|
|
print_success "Usuario $DB_USER existe"
|
|
|
|
# Verificar password del usuario
|
|
if [ -z "$DB_PASSWORD" ]; then
|
|
print_error "Password requerido (usar --password)"
|
|
exit 1
|
|
fi
|
|
|
|
# Probar conexión con el password
|
|
if ! PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "SELECT 1" > /dev/null 2>&1; then
|
|
print_error "Password incorrecto para usuario $DB_USER"
|
|
exit 1
|
|
fi
|
|
print_success "Password verificado"
|
|
}
|
|
|
|
# ============================================================================
|
|
# PASO 1: ELIMINAR BASE DE DATOS
|
|
# ============================================================================
|
|
|
|
drop_database() {
|
|
print_step "PASO 1/4: Eliminando base de datos..."
|
|
|
|
db_exists=$(query_as_postgres "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'")
|
|
|
|
if [ -z "$db_exists" ]; then
|
|
print_info "Base de datos '$DB_NAME' no existe, se creará nueva"
|
|
return
|
|
fi
|
|
|
|
print_info "Terminando conexiones activas..."
|
|
execute_as_postgres "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DB_NAME' AND pid <> pg_backend_pid();" > /dev/null 2>&1 || true
|
|
sleep 1
|
|
|
|
print_info "Eliminando base de datos '$DB_NAME'..."
|
|
if execute_as_postgres "DROP DATABASE IF EXISTS $DB_NAME;" > /dev/null 2>&1; then
|
|
print_success "Base de datos eliminada"
|
|
else
|
|
print_error "Error al eliminar base de datos"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# PASO 2: CREAR BASE DE DATOS
|
|
# ============================================================================
|
|
|
|
create_database() {
|
|
print_step "PASO 2/4: Creando base de datos..."
|
|
|
|
print_info "Creando base de datos $DB_NAME..."
|
|
execute_as_postgres "CREATE DATABASE $DB_NAME OWNER $DB_USER ENCODING 'UTF8';" > /dev/null
|
|
print_success "Base de datos creada"
|
|
|
|
execute_as_postgres "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" > /dev/null
|
|
print_success "Privilegios otorgados"
|
|
}
|
|
|
|
# ============================================================================
|
|
# PASO 3: EJECUTAR DDL Y SEEDS
|
|
# ============================================================================
|
|
|
|
execute_ddl() {
|
|
print_step "PASO 3/4: Ejecutando DDL..."
|
|
|
|
export PGPASSWORD="$DB_PASSWORD"
|
|
|
|
local schemas=(
|
|
"auth"
|
|
"auth_management"
|
|
"system_configuration"
|
|
"gamification_system"
|
|
"educational_content"
|
|
"content_management"
|
|
"social_features"
|
|
"progress_tracking"
|
|
"audit_logging"
|
|
)
|
|
|
|
# Crear schemas
|
|
print_info "Creando schemas..."
|
|
for schema in "${schemas[@]}"; do
|
|
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "CREATE SCHEMA IF NOT EXISTS $schema;" > /dev/null 2>&1
|
|
done
|
|
print_success "9 schemas creados"
|
|
|
|
# Crear ENUMs
|
|
print_info "Creando ENUMs..."
|
|
if [ -d "$DDL_DIR/schemas/gamification_system/enums" ]; then
|
|
for enum_file in "$DDL_DIR/schemas/gamification_system/enums"/*.sql; do
|
|
if [ -f "$enum_file" ]; then
|
|
execute_sql_file "$enum_file" > /dev/null 2>&1 || true
|
|
fi
|
|
done
|
|
fi
|
|
print_success "ENUMs creados"
|
|
|
|
# Crear tablas
|
|
print_info "Creando tablas..."
|
|
local table_count=0
|
|
for schema in "${schemas[@]}"; do
|
|
local tables_dir="$DDL_DIR/schemas/$schema/tables"
|
|
if [ -d "$tables_dir" ]; then
|
|
for table_file in "$tables_dir"/*.sql; do
|
|
if [ -f "$table_file" ]; then
|
|
if execute_sql_file "$table_file" > /dev/null 2>&1; then
|
|
((table_count++))
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
print_success "$table_count tablas creadas"
|
|
|
|
# Otorgar permisos a gamilit_user
|
|
print_info "Otorgando permisos a gamilit_user..."
|
|
local perms_file="$DDL_DIR/99-post-ddl-permissions.sql"
|
|
if [ -f "$perms_file" ]; then
|
|
execute_sql_file "$perms_file" > /dev/null 2>&1
|
|
print_success "Permisos otorgados"
|
|
else
|
|
print_warning "Archivo de permisos no encontrado: $perms_file"
|
|
fi
|
|
|
|
unset PGPASSWORD
|
|
}
|
|
|
|
load_seeds() {
|
|
print_step "PASO 4/4: Cargando seeds..."
|
|
|
|
export PGPASSWORD="$DB_PASSWORD"
|
|
|
|
local seeds_base="$SEEDS_DIR/dev"
|
|
local loaded=0
|
|
local failed=0
|
|
|
|
# Array con orden específico respetando dependencias
|
|
# IMPORTANTE: Este orden es crítico para evitar errores de FK
|
|
local seed_files=(
|
|
# 1. Tenants y auth providers (sin dependencias)
|
|
"$seeds_base/auth_management/01-tenants.sql"
|
|
"$seeds_base/auth_management/02-auth_providers.sql"
|
|
|
|
# 2. Users (depende de tenants - opcional)
|
|
"$seeds_base/auth/01-demo-users.sql"
|
|
|
|
# 3. Profiles (CRÍTICO: depende de users y tenants)
|
|
"$seeds_base/auth_management/03-profiles.sql"
|
|
|
|
# 4. Resto de auth_management
|
|
"$seeds_base/auth_management/04-user_roles.sql"
|
|
"$seeds_base/auth_management/05-user_preferences.sql"
|
|
"$seeds_base/auth_management/06-auth_attempts.sql"
|
|
"$seeds_base/auth_management/07-security_events.sql"
|
|
|
|
# 5. System configuration
|
|
"$seeds_base/system_configuration/01-system_settings.sql"
|
|
"$seeds_base/system_configuration/02-feature_flags.sql"
|
|
|
|
# 6. Gamificación (depende de users/profiles)
|
|
"$seeds_base/gamification_system/01-achievement_categories.sql"
|
|
"$seeds_base/gamification_system/02-achievements.sql"
|
|
"$seeds_base/gamification_system/03-leaderboard_metadata.sql"
|
|
"$seeds_base/gamification_system/04-initialize_user_gamification.sql"
|
|
|
|
# 7. Educational content
|
|
"$seeds_base/educational_content/01-modules.sql"
|
|
"$seeds_base/educational_content/02-exercises-module1.sql"
|
|
"$seeds_base/educational_content/03-exercises-module2.sql"
|
|
"$seeds_base/educational_content/04-exercises-module3.sql"
|
|
"$seeds_base/educational_content/05-exercises-module4.sql"
|
|
"$seeds_base/educational_content/06-exercises-module5.sql"
|
|
"$seeds_base/educational_content/07-assessment-rubrics.sql"
|
|
|
|
# 8. Content management
|
|
"$seeds_base/content_management/01-marie-curie-bio.sql"
|
|
"$seeds_base/content_management/02-media-files.sql"
|
|
"$seeds_base/content_management/03-tags.sql"
|
|
|
|
# 9. Social features
|
|
"$seeds_base/social_features/01-schools.sql"
|
|
"$seeds_base/social_features/02-classrooms.sql"
|
|
"$seeds_base/social_features/03-classroom-members.sql"
|
|
"$seeds_base/social_features/04-teams.sql"
|
|
|
|
# 10. Progress tracking
|
|
"$seeds_base/progress_tracking/01-demo-progress.sql"
|
|
"$seeds_base/progress_tracking/02-exercise-attempts.sql"
|
|
|
|
# 11. Audit logging
|
|
"$seeds_base/audit_logging/01-audit-logs.sql"
|
|
"$seeds_base/audit_logging/02-system-metrics.sql"
|
|
)
|
|
|
|
for seed_file in "${seed_files[@]}"; do
|
|
if [ -f "$seed_file" ]; then
|
|
local basename_file=$(basename "$seed_file")
|
|
print_info " $basename_file"
|
|
|
|
# CRÍTICO: NO ocultar errores - ejecutar y mostrar salida
|
|
if execute_sql_file "$seed_file" 2>&1 | grep -i "error" > /dev/null; then
|
|
((failed++))
|
|
print_warning " ⚠️ Errores en $basename_file (continuando...)"
|
|
else
|
|
((loaded++))
|
|
fi
|
|
else
|
|
print_warning "Seed no encontrado: $(basename $seed_file)"
|
|
fi
|
|
done
|
|
|
|
if [ $failed -gt 0 ]; then
|
|
print_warning "$loaded seeds cargados, $failed con errores"
|
|
else
|
|
print_success "$loaded seeds cargados exitosamente"
|
|
fi
|
|
|
|
unset PGPASSWORD
|
|
}
|
|
|
|
# ============================================================================
|
|
# CONFIRMACIÓN
|
|
# ============================================================================
|
|
|
|
confirm_reset() {
|
|
print_header "⚠️ ADVERTENCIA: RESET DE BASE DE DATOS"
|
|
|
|
echo -e "${YELLOW}Este script:${NC}"
|
|
echo -e " • Eliminará la base de datos: ${RED}$DB_NAME${NC}"
|
|
echo -e " • Mantendrá el usuario: ${GREEN}$DB_USER${NC}"
|
|
echo -e " • Recreará schemas, tablas y datos"
|
|
echo ""
|
|
|
|
if [ "$FORCE_MODE" = false ]; then
|
|
read -p "¿Continuar con el reset? (yes/no): " confirm
|
|
if [ "$confirm" != "yes" ]; then
|
|
print_info "Operación cancelada"
|
|
exit 0
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# MAIN
|
|
# ============================================================================
|
|
|
|
main() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--env)
|
|
ENVIRONMENT="$2"
|
|
shift 2
|
|
;;
|
|
--password)
|
|
DB_PASSWORD="$2"
|
|
shift 2
|
|
;;
|
|
--force)
|
|
FORCE_MODE=true
|
|
shift
|
|
;;
|
|
--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
*)
|
|
print_error "Opción desconocida: $1"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$ENVIRONMENT" ]; then
|
|
print_header "GAMILIT Platform - Reset de BD"
|
|
echo "Selecciona ambiente:"
|
|
echo " 1) dev"
|
|
echo " 2) prod"
|
|
read -p "Opción: " env_option
|
|
|
|
case $env_option in
|
|
1) ENVIRONMENT="dev" ;;
|
|
2) ENVIRONMENT="prod" ;;
|
|
*)
|
|
print_error "Opción inválida"
|
|
exit 1
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
if [ "$ENVIRONMENT" != "dev" ] && [ "$ENVIRONMENT" != "prod" ]; then
|
|
print_error "Ambiente inválido: $ENVIRONMENT"
|
|
exit 1
|
|
fi
|
|
|
|
# Si no se proveyó password, preguntar
|
|
if [ -z "$DB_PASSWORD" ]; then
|
|
read -sp "Password para usuario $DB_USER: " DB_PASSWORD
|
|
echo ""
|
|
fi
|
|
|
|
confirm_reset
|
|
check_prerequisites
|
|
drop_database
|
|
create_database
|
|
execute_ddl
|
|
load_seeds
|
|
|
|
print_header "✅ BASE DE DATOS RESETEADA"
|
|
|
|
echo -e "${GREEN}Base de datos recreada exitosamente${NC}"
|
|
echo ""
|
|
echo -e "${CYAN}Conexión:${NC}"
|
|
echo -e " Database: $DB_NAME"
|
|
echo -e " User: $DB_USER"
|
|
echo -e " Host: $DB_HOST:$DB_PORT"
|
|
echo ""
|
|
print_success "¡Listo para usar!"
|
|
echo ""
|
|
}
|
|
|
|
main "$@"
|