Migración desde workspace-v2/projects/template-saas/apps/database Este repositorio es parte del estándar multi-repo v2 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
252 lines
9.7 KiB
Bash
Executable File
252 lines
9.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================
|
|
# TEMPLATE-SAAS: Create Database Script
|
|
# Version: 1.0.0
|
|
# ============================================
|
|
|
|
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
|
|
DB_HOST="${DB_HOST:-localhost}"
|
|
DB_PORT="${DB_PORT:-5432}"
|
|
DB_NAME="${DB_NAME:-template_saas_dev}"
|
|
DB_USER="${DB_USER:-template_saas_user}"
|
|
DB_PASSWORD="${DB_PASSWORD:-template_saas_dev_2026}"
|
|
DB_ADMIN_USER="${DB_ADMIN_USER:-postgres}"
|
|
DB_ADMIN_PASSWORD="${DB_ADMIN_PASSWORD:-postgres}"
|
|
|
|
# Script directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DDL_DIR="$SCRIPT_DIR/../ddl"
|
|
SEEDS_DIR="$SCRIPT_DIR/../seeds"
|
|
|
|
echo -e "${BLUE}============================================${NC}"
|
|
echo -e "${BLUE} TEMPLATE-SAAS Database Creation${NC}"
|
|
echo -e "${BLUE}============================================${NC}"
|
|
echo ""
|
|
echo -e "Host: ${YELLOW}$DB_HOST:$DB_PORT${NC}"
|
|
echo -e "Database: ${YELLOW}$DB_NAME${NC}"
|
|
echo -e "User: ${YELLOW}$DB_USER${NC}"
|
|
echo ""
|
|
|
|
# Function to run SQL as admin
|
|
run_sql_admin() {
|
|
PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d postgres -c "$1"
|
|
}
|
|
|
|
# Function to run SQL file as admin on target DB
|
|
run_sql_file_admin() {
|
|
PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d "$DB_NAME" -f "$1"
|
|
}
|
|
|
|
# Function to run SQL file as app user
|
|
run_sql_file() {
|
|
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$1"
|
|
}
|
|
|
|
# Check PostgreSQL connection
|
|
echo -e "${BLUE}[1/7] Checking PostgreSQL connection...${NC}"
|
|
if ! PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d postgres -c '\q' 2>/dev/null; then
|
|
echo -e "${RED}ERROR: Cannot connect to PostgreSQL at $DB_HOST:$DB_PORT${NC}"
|
|
exit 1
|
|
fi
|
|
echo -e "${GREEN}✓ PostgreSQL connection successful${NC}"
|
|
|
|
# Create user if not exists (skip if admin doesn't have CREATEROLE)
|
|
echo -e "${BLUE}[2/7] Creating database user...${NC}"
|
|
USER_EXISTS=$(PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'")
|
|
if [ "$USER_EXISTS" != "1" ]; then
|
|
# Check if admin has CREATEROLE privilege
|
|
CAN_CREATE_ROLE=$(PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d postgres -tAc "SELECT rolcreaterole FROM pg_roles WHERE rolname='$DB_ADMIN_USER'")
|
|
if [ "$CAN_CREATE_ROLE" = "t" ]; then
|
|
run_sql_admin "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';"
|
|
echo -e "${GREEN}✓ User $DB_USER created${NC}"
|
|
else
|
|
echo -e "${YELLOW}→ Admin cannot create roles. Using admin user as DB owner.${NC}"
|
|
DB_USER="$DB_ADMIN_USER"
|
|
DB_PASSWORD="$DB_ADMIN_PASSWORD"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}→ User $DB_USER already exists${NC}"
|
|
fi
|
|
|
|
# Create database if not exists
|
|
echo -e "${BLUE}[3/7] Creating database...${NC}"
|
|
DB_EXISTS=$(PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'")
|
|
if [ "$DB_EXISTS" != "1" ]; then
|
|
run_sql_admin "CREATE DATABASE $DB_NAME OWNER $DB_USER;"
|
|
echo -e "${GREEN}✓ Database $DB_NAME created${NC}"
|
|
else
|
|
echo -e "${YELLOW}→ Database $DB_NAME already exists${NC}"
|
|
fi
|
|
|
|
# Grant privileges
|
|
run_sql_admin "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
|
|
|
|
# Load extensions (requires admin)
|
|
echo -e "${BLUE}[4/7] Loading extensions...${NC}"
|
|
if [ -f "$DDL_DIR/00-extensions.sql" ]; then
|
|
run_sql_file_admin "$DDL_DIR/00-extensions.sql"
|
|
echo -e "${GREEN}✓ Extensions loaded${NC}"
|
|
else
|
|
echo -e "${RED}ERROR: 00-extensions.sql not found${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Load base DDL files
|
|
echo -e "${BLUE}[5/7] Loading DDL (schemas, enums, functions)...${NC}"
|
|
|
|
# Schemas
|
|
if [ -f "$DDL_DIR/01-schemas.sql" ]; then
|
|
run_sql_file_admin "$DDL_DIR/01-schemas.sql"
|
|
echo -e "${GREEN} ✓ Schemas created${NC}"
|
|
fi
|
|
|
|
# Enums
|
|
if [ -f "$DDL_DIR/02-enums.sql" ]; then
|
|
run_sql_file_admin "$DDL_DIR/02-enums.sql"
|
|
echo -e "${GREEN} ✓ Enums created${NC}"
|
|
fi
|
|
|
|
# Grant schema privileges to user
|
|
PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d "$DB_NAME" -c "
|
|
GRANT USAGE ON SCHEMA auth TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA tenants TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA users TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA billing TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA plans TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA audit TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA notifications TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA feature_flags TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA storage TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA ai TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA webhooks TO $DB_USER;
|
|
GRANT USAGE ON SCHEMA whatsapp TO $DB_USER;
|
|
"
|
|
|
|
# Load schema tables in order
|
|
echo -e "${BLUE}[6/7] Loading tables...${NC}"
|
|
|
|
# Order matters for foreign keys
|
|
SCHEMA_ORDER=(
|
|
"tenants"
|
|
"plans"
|
|
"users"
|
|
"auth"
|
|
"billing"
|
|
"audit"
|
|
"notifications"
|
|
"feature_flags"
|
|
"ai"
|
|
"storage"
|
|
"webhooks"
|
|
"whatsapp"
|
|
)
|
|
|
|
for schema in "${SCHEMA_ORDER[@]}"; do
|
|
SCHEMA_DIR="$DDL_DIR/schemas/$schema/tables"
|
|
if [ -d "$SCHEMA_DIR" ]; then
|
|
echo -e " Loading schema: ${YELLOW}$schema${NC}"
|
|
for sql_file in $(ls "$SCHEMA_DIR"/*.sql 2>/dev/null | sort); do
|
|
run_sql_file_admin "$sql_file"
|
|
echo -e " ${GREEN}✓${NC} $(basename $sql_file)"
|
|
done
|
|
fi
|
|
done
|
|
|
|
# Load functions (after tables exist)
|
|
if [ -f "$DDL_DIR/03-functions.sql" ]; then
|
|
run_sql_file_admin "$DDL_DIR/03-functions.sql"
|
|
echo -e "${GREEN} ✓ Functions created${NC}"
|
|
fi
|
|
|
|
# Grant table privileges
|
|
PGPASSWORD="$DB_ADMIN_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_ADMIN_USER" -d "$DB_NAME" -c "
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA auth TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA tenants TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA users TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA billing TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA plans TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA audit TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA notifications TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA feature_flags TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA ai TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA storage TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA webhooks TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA whatsapp TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA billing TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA ai TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA storage TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA webhooks TO $DB_USER;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA whatsapp TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA auth TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA tenants TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA users TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA billing TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA plans TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA audit TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA notifications TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA feature_flags TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA ai TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA storage TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA webhooks TO $DB_USER;
|
|
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA whatsapp TO $DB_USER;
|
|
"
|
|
|
|
# Load seeds
|
|
echo -e "${BLUE}[7/7] Loading seeds...${NC}"
|
|
|
|
# Production seeds
|
|
if [ -d "$SEEDS_DIR/prod" ]; then
|
|
for sql_file in $(ls "$SEEDS_DIR/prod"/*.sql 2>/dev/null | sort); do
|
|
run_sql_file_admin "$sql_file"
|
|
echo -e " ${GREEN}✓${NC} $(basename $sql_file)"
|
|
done
|
|
fi
|
|
|
|
# Development seeds (if DEV_SEEDS=1)
|
|
if [ "$DEV_SEEDS" = "1" ] && [ -d "$SEEDS_DIR/dev" ]; then
|
|
echo -e " Loading development seeds..."
|
|
for sql_file in $(ls "$SEEDS_DIR/dev"/*.sql 2>/dev/null | sort); do
|
|
run_sql_file_admin "$sql_file"
|
|
echo -e " ${GREEN}✓${NC} $(basename $sql_file)"
|
|
done
|
|
fi
|
|
|
|
# Summary
|
|
echo ""
|
|
echo -e "${GREEN}============================================${NC}"
|
|
echo -e "${GREEN} Database creation completed!${NC}"
|
|
echo -e "${GREEN}============================================${NC}"
|
|
echo ""
|
|
echo -e "Connection string:"
|
|
echo -e "${YELLOW}postgresql://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME${NC}"
|
|
echo ""
|
|
|
|
# Verify tables
|
|
echo -e "${BLUE}Verification:${NC}"
|
|
TABLE_COUNT=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema');")
|
|
echo -e " Tables created: ${GREEN}$TABLE_COUNT${NC}"
|
|
|
|
PLANS_COUNT=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT COUNT(*) FROM plans.plans;")
|
|
echo -e " Plans seeded: ${GREEN}$PLANS_COUNT${NC}"
|
|
|
|
PERMS_COUNT=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT COUNT(*) FROM users.permissions;")
|
|
echo -e " Permissions seeded: ${GREEN}$PERMS_COUNT${NC}"
|
|
|
|
FLAGS_COUNT=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT COUNT(*) FROM feature_flags.flags;")
|
|
echo -e " Feature flags seeded: ${GREEN}$FLAGS_COUNT${NC}"
|
|
|
|
TEMPLATES_COUNT=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT COUNT(*) FROM notifications.templates;")
|
|
echo -e " Notification templates seeded: ${GREEN}$TEMPLATES_COUNT${NC}"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}Done!${NC}"
|