feat: Update default admin credentials and organization branding, refactor admin creation in install script to direct database insertion, disable rate limiting, and update documentation.

This commit is contained in:
2026-03-13 13:24:06 -03:00
parent c49a49dc19
commit 3167723a89
4 changed files with 96 additions and 35 deletions
+3 -3
View File
@@ -7,7 +7,7 @@ LMS_DATABASE_URL=postgresql://user:password@localhost:5433/openccb_lms
# General fallback # General fallback
DATABASE_URL=postgresql://user:password@localhost:5433/openccb_cms DATABASE_URL=postgresql://user:password@localhost:5433/openccb_cms
# JWT Secret # JWT Secret (generate with ./generate_jwt_secret.sh)
JWT_SECRET=supersecret JWT_SECRET=supersecret
# Logging # Logging
@@ -37,8 +37,8 @@ EXTERNAL_TABLE_GRADES=notas
EXTERNAL_ID_TIPO_NOTA=1 EXTERNAL_ID_TIPO_NOTA=1
# Branding Defaults # Branding Defaults
DEFAULT_ORG_NAME="OpenCCB" DEFAULT_ORG_NAME="Norteamericano"
DEFAULT_PLATFORM_NAME="OpenCCB Learning" DEFAULT_PLATFORM_NAME="Norteamericano Learning"
DEFAULT_LOGO_URL="" DEFAULT_LOGO_URL=""
DEFAULT_FAVICON_URL="" DEFAULT_FAVICON_URL=""
DEFAULT_PRIMARY_COLOR="#3B82F6" DEFAULT_PRIMARY_COLOR="#3B82F6"
+39
View File
@@ -278,6 +278,14 @@ NEXT_PUBLIC_CMS_API_URL=http://localhost:3001
NEXT_PUBLIC_LMS_API_URL=http://localhost:3002 NEXT_PUBLIC_LMS_API_URL=http://localhost:3002
``` ```
### Default Credentials
After running `./install.sh`, the default admin user is:
- **Email**: `admin@norteamericano.cl`
- **Password**: `Admin123!`
You can customize these during installation.
## Testing ## Testing
### E2E Tests (Playwright) ### E2E Tests (Playwright)
@@ -340,6 +348,37 @@ cargo test -p common
## Common Issues ## Common Issues
### CORS Errors (Login/Registro)
Si ves errores de CORS al intentar loguearte:
```
Access to fetch at 'http://localhost:3001/auth/login' from origin 'http://localhost:3000'
has been blocked by CORS policy
```
**Solución**: Asegúrate de que el rate limiter NO esté aplicado a las rutas de autenticación.
En `services/cms-service/src/main.rs`, el `GovernorLayer` debe estar solo en `protected_routes`,
no en `public_routes`.
### Rate Limiter Bloqueando Peticiones
**Estado actual**: El rate limiter (`tower_governor`) está **deshabilitado** debido a problemas de compatibilidad con el middleware de autenticación.
Si quieres habilitarlo en producción:
1. Agrega `GovernorLayer` solo a rutas protegidas usando `.route_layer()`
2. Configúralo después del middleware de autenticación
3. Ajusta los límites (por defecto: 10 req/s, burst 50)
```rust
.protected_routes
.route_layer(middleware::from_fn(org_extractor_middleware))
.route_layer(GovernorLayer { config: governor_conf })
```
**Advertencia**: Si el rate limiter está mal configurado, las peticiones a `/courses`, `/auth/login`, etc. pueden fallar con error 500 sin logs.
### Port Conflicts ### Port Conflicts
If port 5432 is occupied, the setup uses 5433: If port 5432 is occupied, the setup uses 5433:
+52 -21
View File
@@ -241,13 +241,13 @@ if [ "$ADMIN_EXISTS" != "t" ]; then
echo "👤 Configurar Administrador Inicial" echo "👤 Configurar Administrador Inicial"
read -p "Nombre Completo [Administrador del Sistema]: " ADMIN_NAME read -p "Nombre Completo [Administrador del Sistema]: " ADMIN_NAME
ADMIN_NAME=${ADMIN_NAME:-Administrador del Sistema} ADMIN_NAME=${ADMIN_NAME:-Administrador del Sistema}
read -p "Email del Administrador [admin@example.com]: " ADMIN_EMAIL read -p "Email del Administrador [admin@norteamericano.cl]: " ADMIN_EMAIL
ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com} ADMIN_EMAIL=${ADMIN_EMAIL:-admin@norteamericano.cl}
read -s -p "Contraseña del Administrador [password123]: " ADMIN_PASS read -s -p "Contraseña del Administrador [Admin123!]: " ADMIN_PASS
ADMIN_PASS=${ADMIN_PASS:-password123} ADMIN_PASS=${ADMIN_PASS:-Admin123!}
echo "" echo ""
read -p "Nombre de la Organización [OpenCCB]: " ORG_NAME read -p "Nombre de la Organización [Norteamericano]: " ORG_NAME
ORG_NAME=${ORG_NAME:-OpenCCB} ORG_NAME=${ORG_NAME:-Norteamericano}
fi fi
# Selective Build/Rebuild # Selective Build/Rebuild
@@ -269,22 +269,12 @@ fi
if [ "$ADMIN_EXISTS" != "t" ]; then if [ "$ADMIN_EXISTS" != "t" ]; then
echo "⏳ Esperando a que el API CMS esté listo..." echo "⏳ Esperando a que el API CMS esté listo..."
API_URL="http://localhost:3001" API_URL="http://localhost:3001"
PAYLOAD=$(cat <<EOF
{
"email": "$ADMIN_EMAIL",
"password": "$ADMIN_PASS",
"full_name": "$ADMIN_NAME",
"organization_name": "$ORG_NAME",
"role": "admin"
}
EOF
)
# Wait until the API actually responds (not just the port being open) # Wait until the API actually responds (not just the port being open)
MAX_RETRIES=30 MAX_RETRIES=30
count=0 count=0
echo -n "Esperando API" echo -n "Esperando API"
until curl -s -o /dev/null "$API_URL/auth/login" -H "Content-Type: application/json" -d '{}' 2>/dev/null; do until curl -s -o /dev/null "$API_URL/health" 2>/dev/null; do
echo -n "." echo -n "."
sleep 2 sleep 2
count=$((count+1)) count=$((count+1))
@@ -296,14 +286,50 @@ EOF
done done
echo "" echo ""
RESPONSE=$(curl -s -X POST "$API_URL/auth/register" -H "Content-Type: application/json" -d "$PAYLOAD") # Create admin user directly in database using pgcrypto
echo "🔐 Creando administrador en la base de datos..."
docker exec openccb-db-1 psql -U user -d openccb_cms -c "
CREATE EXTENSION IF NOT EXISTS pgcrypto;
SELECT * FROM fn_register_user(
'$ADMIN_EMAIL',
crypt('$ADMIN_PASS', gen_salt('bf', 12)),
'$ADMIN_NAME',
'admin',
'$ORG_NAME'
);
" 2>/dev/null
if echo "$RESPONSE" | grep -q "token"; then if [ $? -eq 0 ]; then
echo "✅ ¡Éxito! Administrador creado." echo "✅ ¡Éxito! Administrador creado."
API_KEY=$(docker exec openccb-db-1 psql -U user -d openccb_cms -t -c "SELECT api_key FROM organizations LIMIT 1;" | xargs) API_KEY=$(docker exec openccb-db-1 psql -U user -d openccb_cms -t -c "SELECT api_key FROM organizations LIMIT 1;" | xargs 2>/dev/null)
echo "🔑 API Key Inicial: $API_KEY" echo "🔑 API Key Inicial: $API_KEY"
echo ""
echo "📋 Credenciales de acceso:"
echo " Email: $ADMIN_EMAIL"
echo " Contraseña: $ADMIN_PASS"
else else
echo "⚠️ Fallo al crear el administrador. Respuesta: $RESPONSE" echo "⚠️ Fallo al crear el administrador. Intentando con método alternativo..."
# Fallback: Try API endpoint
PAYLOAD=$(cat <<EOF
{
"email": "$ADMIN_EMAIL",
"password": "$ADMIN_PASS",
"full_name": "$ADMIN_NAME",
"organization_name": "$ORG_NAME",
"role": "admin"
}
EOF
)
RESPONSE=$(curl -s -X POST "$API_URL/auth/register" -H "Content-Type: application/json" -d "$PAYLOAD")
if echo "$RESPONSE" | grep -q "token"; then
echo "✅ ¡Éxito! Administrador creado vía API."
API_KEY=$(docker exec openccb-db-1 psql -U user -d openccb_cms -t -c "SELECT api_key FROM organizations LIMIT 1;" | xargs 2>/dev/null)
echo "🔑 API Key Inicial: $API_KEY"
else
echo "⚠️ Fallo al crear el administrador. Respuesta: $RESPONSE"
fi
fi fi
else else
echo "✅ El administrador ya existe. Saltando registro." echo "✅ El administrador ya existe. Saltando registro."
@@ -316,3 +342,8 @@ echo "===================================================="
echo "Studio (Admin/CMS): http://localhost:3000" echo "Studio (Admin/CMS): http://localhost:3000"
echo "Experience (LMS): http://localhost:3003" echo "Experience (LMS): http://localhost:3003"
echo "====================================================" echo "===================================================="
echo ""
echo "📋 Notas:"
echo " - Rate limiter: DESHABILITADO (problemas de compatibilidad)"
echo " - Para producción, configura tower_governor en services/cms-service/src/main.rs"
echo "===================================================="
+2 -11
View File
@@ -20,10 +20,7 @@ use dotenvy::dotenv;
use sqlx::postgres::PgPoolOptions; use sqlx::postgres::PgPoolOptions;
use std::env; use std::env;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tower_governor::governor::GovernorConfigBuilder;
use tower_governor::GovernorLayer;
use tower_http::cors::{Any, CorsLayer}; use tower_http::cors::{Any, CorsLayer};
use tower_http::set_header::SetResponseHeaderLayer; use tower_http::set_header::SetResponseHeaderLayer;
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
@@ -99,14 +96,8 @@ async fn main() {
.allow_methods(Any) .allow_methods(Any)
.allow_headers(Any); .allow_headers(Any);
// Rate limiting configuration // Rate limiting: Deshabilitado temporalmente por problemas de compatibilidad con tower-governor
let governor_conf = Arc::new( // Para habilitar en producción, configurar con GovernorLayer y ajustar los límites apropiadamente
GovernorConfigBuilder::default()
.per_second(10)
.burst_size(50)
.finish()
.unwrap(),
);
// Rutas protegidas que requieren autenticación y contexto de organización // Rutas protegidas que requieren autenticación y contexto de organización
let protected_routes = Router::new() let protected_routes = Router::new()