604 lines
27 KiB
Bash
Executable File
604 lines
27 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
###############################################################################
|
|
# Script de inicialización completa para Anexo76
|
|
#
|
|
# Este script configura automáticamente:
|
|
# 1. User Profile Attributes en Keycloak (tenant_id)
|
|
# 2. Clientes de Keycloak (Backend y Frontend)
|
|
# 3. Mappers de atributos (tenant_id)
|
|
# 4. Usuario demo en Keycloak (usuario=demo, password=demo123)
|
|
# 5. Tenant y Company en PostgreSQL
|
|
# 6. Relación usuario-tenant en tabla user_tenants
|
|
# 7. Actualización del tenant_id del usuario con el valor real
|
|
#
|
|
# Requisitos:
|
|
# - Keycloak corriendo en http://localhost:8080
|
|
# - PostgreSQL corriendo en localhost:5432
|
|
# - Base de datos anexo76_core creada
|
|
# - jq instalado (para procesamiento JSON)
|
|
#
|
|
# Nota: El atributo tenant_id se crea con valor inicial "1" y luego
|
|
# se actualiza con el ID real del tenant creado en PostgreSQL.
|
|
###############################################################################
|
|
|
|
# set -e # Comentado para permitir que el script continúe aunque algunos comandos fallen (ej: mapper ya existe)
|
|
|
|
# Colores para output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Variables de configuración
|
|
KEYCLOAK_URL="${KEYCLOAK_URL:-http://localhost:8080}"
|
|
KEYCLOAK_ADMIN="${KEYCLOAK_ADMIN:-admin}"
|
|
KEYCLOAK_ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD:-admin}"
|
|
KEYCLOAK_REALM="${KEYCLOAK_REALM:-master}"
|
|
KEYCLOACK_ADMIN_URL="${KEYCLOACK_ADMIN_URL:-http://localhost:9000}"
|
|
|
|
POSTGRES_HOST="${POSTGRES_HOST:-localhost}"
|
|
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
|
POSTGRES_DB="${POSTGRES_DB:-anexo76_core}"
|
|
POSTGRES_USER="${POSTGRES_USER:-postgres}"
|
|
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-postgres}"
|
|
|
|
DEMO_USERNAME="demo"
|
|
DEMO_PASSWORD="demo123"
|
|
DEMO_EMAIL="demo@aduanasoft.com"
|
|
DEMO_FIRSTNAME="Demo"
|
|
DEMO_LASTNAME="User"
|
|
|
|
TENANT_NAME="Aduanasoft"
|
|
TENANT_SLUG="aduanasoft"
|
|
COMPANY_NAME="Aduanasoft S.A. de C.V."
|
|
COMPANY_RFC="ADS010101AAA"
|
|
|
|
echo -e "${GREEN}════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} Inicialización del Sistema Anexo76${NC}"
|
|
echo -e "${GREEN}════════════════════════════════════════════════════════${NC}"
|
|
|
|
###############################################################################
|
|
# 1. Esperar a que Keycloak esté listo
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[1/8] Esperando a que Keycloak esté disponible...${NC}"
|
|
MAX_RETRIES=30
|
|
RETRY_COUNT=0
|
|
|
|
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
|
if curl -s -f "${KEYCLOACK_ADMIN_URL}/health/ready" > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ Keycloak está listo${NC}"
|
|
break
|
|
fi
|
|
RETRY_COUNT=$((RETRY_COUNT + 1))
|
|
echo "Intento $RETRY_COUNT/$MAX_RETRIES..."
|
|
sleep 2
|
|
done
|
|
|
|
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
|
|
echo -e "${RED}✗ Error: Keycloak no está disponible después de $MAX_RETRIES intentos${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
###############################################################################
|
|
# 2. Obtener token de administrador de Keycloak
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[2/8] Obteniendo token de administrador de Keycloak...${NC}"
|
|
|
|
TOKEN_RESPONSE=$(curl -s -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "username=${KEYCLOAK_ADMIN}" \
|
|
-d "password=${KEYCLOAK_ADMIN_PASSWORD}" \
|
|
-d "grant_type=password" \
|
|
-d "client_id=admin-cli")
|
|
|
|
ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | sed 's/"access_token":"//')
|
|
|
|
if [ -z "$ACCESS_TOKEN" ]; then
|
|
echo -e "${RED}✗ Error: No se pudo obtener el token de acceso${NC}"
|
|
echo "Respuesta: $TOKEN_RESPONSE"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✓ Token obtenido exitosamente${NC}"
|
|
|
|
###############################################################################
|
|
# 3. Configurar User Profile Attributes con valores por defecto
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[3/8] Configurando User Profile Attributes...${NC}"
|
|
|
|
# Obtener configuración actual del User Profile
|
|
USER_PROFILE=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/profile" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
|
|
# Verificar si tenant_id existe
|
|
TENANT_ID_EXISTS=$(echo "$USER_PROFILE" | grep -q "\"name\":\"tenant_id\"" && echo "true" || echo "false")
|
|
|
|
if [ "$TENANT_ID_EXISTS" = "false" ]; then
|
|
echo "Agregando atributo tenant_id al User Profile..."
|
|
|
|
# Crear el atributo tenant_id con valor por defecto
|
|
UPDATED_PROFILE=$(echo "$USER_PROFILE" | jq '.attributes += [{
|
|
"name": "tenant_id",
|
|
"displayName": "Tenant ID",
|
|
"validations": {},
|
|
"annotations": {
|
|
"inputType": "text"
|
|
},
|
|
"required": {
|
|
"roles": [],
|
|
"scopes": []
|
|
},
|
|
"permissions": {
|
|
"view": ["admin", "user"],
|
|
"edit": ["admin"]
|
|
},
|
|
"multivalued": false,
|
|
"group": null
|
|
}]')
|
|
|
|
# Actualizar el User Profile
|
|
curl -s -X PUT "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/profile" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$UPDATED_PROFILE"
|
|
|
|
echo -e "${GREEN}✓ Atributo tenant_id agregado al User Profile${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Atributo tenant_id ya existe en User Profile${NC}"
|
|
fi
|
|
|
|
###############################################################################
|
|
# 4. Configurar clientes de Keycloak (Backend y Frontend)
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[4/8] Configurando clientes de Keycloak...${NC}"
|
|
|
|
# 3.1 Crear cliente Backend
|
|
echo "Configurando cliente Backend..."
|
|
BACKEND_CLIENT_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients?clientId=anexo76-backend" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
|
|
if echo "$BACKEND_CLIENT_EXISTS" | grep -q "\"clientId\":\"anexo76-backend\""; then
|
|
echo -e "${YELLOW}⚠ Cliente Backend ya existe${NC}"
|
|
BACKEND_CLIENT_ID=$(echo "$BACKEND_CLIENT_EXISTS" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
|
|
else
|
|
CREATE_BACKEND=$(curl -s -w "\n%{http_code}" -X POST "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"clientId": "anexo76-backend",
|
|
"name": "Anexo76 Backend API",
|
|
"description": "Backend API para el sistema Anexo76",
|
|
"enabled": true,
|
|
"protocol": "openid-connect",
|
|
"publicClient": false,
|
|
"serviceAccountsEnabled": true,
|
|
"directAccessGrantsEnabled": true,
|
|
"standardFlowEnabled": true,
|
|
"implicitFlowEnabled": false,
|
|
"rootUrl": "http://localhost:8000/api",
|
|
"baseUrl": "http://localhost:8000/api",
|
|
"redirectUris": [
|
|
"http://localhost:8000/*",
|
|
"http://localhost:5173/*"
|
|
],
|
|
"webOrigins": ["http://localhost:8000/api"],
|
|
"attributes": {
|
|
"access.token.lifespan": "3600",
|
|
"client.secret.creation.time": "0"
|
|
}
|
|
}')
|
|
|
|
HTTP_CODE=$(echo "$CREATE_BACKEND" | tail -n1)
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo -e "${GREEN}✓ Cliente Backend creado${NC}"
|
|
# Obtener ID del cliente recién creado
|
|
BACKEND_CLIENT_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients?clientId=anexo76-backend" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
BACKEND_CLIENT_ID=$(echo "$BACKEND_CLIENT_EXISTS" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
|
|
else
|
|
echo -e "${RED}✗ Error al crear cliente Backend (HTTP ${HTTP_CODE})${NC}"
|
|
fi
|
|
fi
|
|
|
|
# Obtener y mostrar el secret del cliente Backend
|
|
if [ -n "$BACKEND_CLIENT_ID" ]; then
|
|
BACKEND_SECRET=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients/${BACKEND_CLIENT_ID}/client-secret" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" | grep -o '"value":"[^"]*' | sed 's/"value":"//')
|
|
|
|
echo -e "${GREEN}✓ Backend Client ID: anexo76-backend${NC}"
|
|
echo -e "${GREEN}✓ Backend Client Secret: ${BACKEND_SECRET}${NC}"
|
|
|
|
# Actualizar archivo .env con el client secret
|
|
if [ -n "$BACKEND_SECRET" ]; then
|
|
ENV_FILE=""
|
|
# Buscar archivo .env en el directorio actual o en el directorio padre
|
|
if [ -f ".env" ]; then
|
|
ENV_FILE=".env"
|
|
elif [ -f "../.env" ]; then
|
|
ENV_FILE="../.env"
|
|
fi
|
|
|
|
if [ -n "$ENV_FILE" ]; then
|
|
# Verificar si la variable ya existe en el archivo
|
|
if grep -q "^KEYCLOAK_CLIENT_SECRET=" "$ENV_FILE"; then
|
|
# Actualizar el valor existente
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
# macOS
|
|
sed -i '' "s|^KEYCLOAK_CLIENT_SECRET=.*|KEYCLOAK_CLIENT_SECRET=${BACKEND_SECRET}|" "$ENV_FILE"
|
|
else
|
|
# Linux
|
|
sed -i "s|^KEYCLOAK_CLIENT_SECRET=.*|KEYCLOAK_CLIENT_SECRET=${BACKEND_SECRET}|" "$ENV_FILE"
|
|
fi
|
|
echo -e "${GREEN}✓ KEYCLOAK_CLIENT_SECRET actualizado en ${ENV_FILE}${NC}"
|
|
else
|
|
# Agregar la variable si no existe
|
|
echo "KEYCLOAK_CLIENT_SECRET=${BACKEND_SECRET}" >> "$ENV_FILE"
|
|
echo -e "${GREEN}✓ KEYCLOAK_CLIENT_SECRET agregado a ${ENV_FILE}${NC}"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ No se encontró archivo .env, el secret debe agregarse manualmente${NC}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# 3.2 Crear cliente Frontend
|
|
echo "Configurando cliente Frontend..."
|
|
FRONTEND_CLIENT_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients?clientId=anexo76-frontend" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
|
|
if echo "$FRONTEND_CLIENT_EXISTS" | grep -q "\"clientId\":\"anexo76-frontend\""; then
|
|
echo -e "${YELLOW}⚠ Cliente Frontend ya existe${NC}"
|
|
FRONTEND_CLIENT_ID=$(echo "$FRONTEND_CLIENT_EXISTS" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
|
|
else
|
|
CREATE_FRONTEND=$(curl -s -w "\n%{http_code}" -X POST "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"clientId": "anexo76-frontend",
|
|
"name": "Anexo76 Frontend",
|
|
"description": "Aplicación web frontend para el sistema Anexo76",
|
|
"enabled": true,
|
|
"protocol": "openid-connect",
|
|
"publicClient": true,
|
|
"directAccessGrantsEnabled": false,
|
|
"standardFlowEnabled": true,
|
|
"implicitFlowEnabled": false,
|
|
"rootUrl": "http://localhost:5173",
|
|
"baseUrl": "http://localhost:5173",
|
|
"redirectUris": [
|
|
"http://localhost:5173/*",
|
|
"http://localhost:3000/*"
|
|
],
|
|
"webOrigins": [
|
|
"http://localhost:5173",
|
|
"http://localhost:3000"
|
|
],
|
|
"attributes": {
|
|
"pkce.code.challenge.method": "S256"
|
|
}
|
|
}')
|
|
|
|
HTTP_CODE=$(echo "$CREATE_FRONTEND" | tail -n1)
|
|
RESPONSE_BODY=$(echo "$CREATE_FRONTEND" | head -n -1)
|
|
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo -e "${GREEN}✓ Cliente Frontend creado${NC}"
|
|
# Obtener ID del cliente recién creado
|
|
FRONTEND_CLIENT_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients?clientId=anexo76-frontend" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
FRONTEND_CLIENT_ID=$(echo "$FRONTEND_CLIENT_EXISTS" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
|
|
else
|
|
echo -e "${RED}✗ Error al crear cliente Frontend (HTTP ${HTTP_CODE})${NC}"
|
|
echo "Respuesta del servidor: $RESPONSE_BODY"
|
|
fi
|
|
fi
|
|
|
|
###############################################################################
|
|
# 5. Configurar Mappers para tenant_id
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[5/8] Configurando mappers para tenant_id...${NC}"
|
|
|
|
# 4.1 Configurar mapper para Backend
|
|
if [ -n "$BACKEND_CLIENT_ID" ]; then
|
|
echo "Configurando mapper para Backend..."
|
|
|
|
# Verificar si el mapper tenant_id ya existe en el cliente
|
|
MAPPER_TENANT_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients/${BACKEND_CLIENT_ID}/protocol-mappers/models" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" | grep -o "\"name\":\"tenant-id-mapper\"")
|
|
|
|
if [ -z "$MAPPER_TENANT_EXISTS" ]; then
|
|
# Crear mapper para tenant_id directamente en el cliente
|
|
CREATE_MAPPER_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients/${BACKEND_CLIENT_ID}/protocol-mappers/models" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "tenant-id-mapper",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-attribute-mapper",
|
|
"config": {
|
|
"user.attribute": "tenant_id",
|
|
"claim.name": "tenant_id",
|
|
"jsonType.label": "String",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"userinfo.token.claim": "true"
|
|
}
|
|
}')
|
|
|
|
HTTP_CODE=$(echo "$CREATE_MAPPER_RESPONSE" | tail -n1)
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo -e "${GREEN}✓ Mapper tenant_id creado para Backend${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Error al crear mapper para Backend (HTTP ${HTTP_CODE})${NC}"
|
|
echo "Respuesta: $(echo "$CREATE_MAPPER_RESPONSE" | head -n -1)"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Mapper tenant_id ya existe para Backend${NC}"
|
|
fi
|
|
fi
|
|
|
|
|
|
# 4.2 Configurar mapper para Frontend
|
|
if [ -n "$FRONTEND_CLIENT_ID" ]; then
|
|
echo "Configurando mapper para Frontend..."
|
|
|
|
# Verificar si el mapper tenant_id ya existe en el cliente
|
|
MAPPER_TENANT_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients/${FRONTEND_CLIENT_ID}/protocol-mappers/models" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" | grep -o "\"name\":\"tenant-id-mapper\"")
|
|
|
|
if [ -z "$MAPPER_TENANT_EXISTS" ]; then
|
|
# Crear mapper para tenant_id directamente en el cliente
|
|
CREATE_MAPPER_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/clients/${FRONTEND_CLIENT_ID}/protocol-mappers/models" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "tenant-id-mapper",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-attribute-mapper",
|
|
"config": {
|
|
"user.attribute": "tenant_id",
|
|
"claim.name": "tenant_id",
|
|
"jsonType.label": "String",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"userinfo.token.claim": "true"
|
|
}
|
|
}')
|
|
|
|
HTTP_CODE=$(echo "$CREATE_MAPPER_RESPONSE" | tail -n1)
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo -e "${GREEN}✓ Mapper tenant_id creado para Frontend${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Error al crear mapper para Frontend (HTTP ${HTTP_CODE})${NC}"
|
|
echo "Respuesta: $(echo "$CREATE_MAPPER_RESPONSE" | head -n -1)"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Mapper tenant_id ya existe para Frontend${NC}"
|
|
fi
|
|
fi
|
|
|
|
|
|
###############################################################################
|
|
# 6. Crear usuario demo en Keycloak
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[6/8] Creando usuario demo en Keycloak...${NC}"
|
|
|
|
# Verificar si el usuario ya existe
|
|
USER_EXISTS=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users?username=${DEMO_USERNAME}" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
|
|
if echo "$USER_EXISTS" | grep -q "\"username\":\"${DEMO_USERNAME}\""; then
|
|
echo -e "${YELLOW}⚠ Usuario demo ya existe, actualizando...${NC}"
|
|
USER_ID=$(echo "$USER_EXISTS" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
|
|
|
|
# Actualizar usuario existente
|
|
curl -s -X PUT "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/${USER_ID}" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"enabled\": true,
|
|
\"firstName\": \"${DEMO_FIRSTNAME}\",
|
|
\"lastName\": \"${DEMO_LASTNAME}\",
|
|
\"email\": \"${DEMO_EMAIL}\",
|
|
\"emailVerified\": true
|
|
}"
|
|
|
|
# Resetear contraseña
|
|
curl -s -X PUT "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/${USER_ID}/reset-password" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"type\": \"password\",
|
|
\"value\": \"${DEMO_PASSWORD}\",
|
|
\"temporary\": false
|
|
}"
|
|
|
|
echo -e "${GREEN}✓ Usuario demo actualizado${NC}"
|
|
else
|
|
# Crear nuevo usuario con tenant_id por defecto
|
|
CREATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"username\": \"${DEMO_USERNAME}\",
|
|
\"enabled\": true,
|
|
\"firstName\": \"${DEMO_FIRSTNAME}\",
|
|
\"lastName\": \"${DEMO_LASTNAME}\",
|
|
\"email\": \"${DEMO_EMAIL}\",
|
|
\"emailVerified\": true,
|
|
\"attributes\": {
|
|
\"tenant_id\": [\"1\"]
|
|
},
|
|
\"credentials\": [{
|
|
\"type\": \"password\",
|
|
\"value\": \"${DEMO_PASSWORD}\",
|
|
\"temporary\": false
|
|
}]
|
|
}")
|
|
|
|
HTTP_CODE=$(echo "$CREATE_RESPONSE" | tail -n1)
|
|
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo -e "${GREEN}✓ Usuario demo creado exitosamente${NC}"
|
|
|
|
# Obtener el ID del usuario recién creado
|
|
USER_RESPONSE=$(curl -s -X GET "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users?username=${DEMO_USERNAME}" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json")
|
|
USER_ID=$(echo "$USER_RESPONSE" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
|
|
else
|
|
echo -e "${RED}✗ Error al crear usuario (HTTP ${HTTP_CODE})${NC}"
|
|
echo "Respuesta: $CREATE_RESPONSE"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo -e "${GREEN}✓ Usuario: ${DEMO_USERNAME}${NC}"
|
|
echo -e "${GREEN}✓ Password: ${DEMO_PASSWORD}${NC}"
|
|
echo -e "${GREEN}✓ Keycloak User ID: ${USER_ID}${NC}"
|
|
|
|
###############################################################################
|
|
# 7. Agregar atributo tenant_id al usuario
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[7/8] Configurando atributo tenant_id para usuario demo...${NC}"
|
|
|
|
# Nota: El tenant_id se agregará después de crear el tenant en PostgreSQL
|
|
|
|
###############################################################################
|
|
# 8. Crear tenant y company en PostgreSQL
|
|
###############################################################################
|
|
echo -e "\n${YELLOW}[8/8] Creando tenant y company en PostgreSQL...${NC}"
|
|
|
|
# Esperar a que PostgreSQL esté listo
|
|
echo "Esperando a que PostgreSQL esté disponible..."
|
|
MAX_PG_RETRIES=60
|
|
PG_RETRY_COUNT=0
|
|
|
|
while [ $PG_RETRY_COUNT -lt $MAX_PG_RETRIES ]; do
|
|
# Usar docker exec para verificar pg_isready directamente
|
|
if docker exec anexo76-postgres-a76 pg_isready -h localhost -U "${POSTGRES_USER}" > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ PostgreSQL está listo${NC}"
|
|
break
|
|
fi
|
|
PG_RETRY_COUNT=$((PG_RETRY_COUNT + 1))
|
|
echo "Intento $PG_RETRY_COUNT/$MAX_PG_RETRIES..."
|
|
sleep 1
|
|
done
|
|
|
|
if [ $PG_RETRY_COUNT -eq $MAX_PG_RETRIES ]; then
|
|
echo -e "${RED}✗ Error: PostgreSQL no está disponible después de $MAX_PG_RETRIES intentos${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Insertar o actualizar tenant
|
|
echo "Insertando tenant en PostgreSQL..."
|
|
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "INSERT INTO a76.tenants (name, slug, type, keycloak_realm, contact_email, is_active, created_at, updated_at) VALUES ('${TENANT_NAME}', '${TENANT_SLUG}', 'SHARED'::tenanttype, '${KEYCLOAK_REALM}', '${DEMO_EMAIL}', true, now(), now()) ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name, contact_email = EXCLUDED.contact_email, updated_at = CURRENT_TIMESTAMP;" 2>&1
|
|
|
|
# Obtener el ID del tenant con mejor manejo de errores
|
|
echo "Obteniendo ID del tenant..."
|
|
TENANT_ID_RESULT=$(docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -t -c "SELECT id FROM a76.tenants WHERE slug = '${TENANT_SLUG}';" 2>&1)
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo -e "${RED}✗ Error al consultar el tenant:${NC}"
|
|
echo "$TENANT_ID_RESULT"
|
|
echo -e "${YELLOW}Verificando si la tabla existe...${NC}"
|
|
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "\dt a76.tenants;"
|
|
exit 1
|
|
fi
|
|
|
|
TENANT_ID=$(echo "$TENANT_ID_RESULT" | xargs) # Trim whitespace
|
|
|
|
if [ -z "$TENANT_ID" ]; then
|
|
echo -e "${RED}✗ Error: No se pudo obtener el ID del tenant${NC}"
|
|
echo "Resultado de la consulta: '$TENANT_ID_RESULT'"
|
|
echo -e "${YELLOW}Intentando ver todos los tenants...${NC}"
|
|
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "SELECT id, slug FROM a76.tenants LIMIT 10;"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✓ Tenant ID: ${TENANT_ID}${NC}"
|
|
|
|
# Insertar company si no existe
|
|
COMPANY_EXISTS=$(docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -t -c "SELECT COUNT(*) FROM a76.company WHERE tenant_id = ${TENANT_ID};")
|
|
COMPANY_EXISTS=$(echo "$COMPANY_EXISTS" | xargs)
|
|
|
|
if [ "$COMPANY_EXISTS" = "0" ]; then
|
|
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "INSERT INTO a76.company (tenant_id, name, rfc, is_service_company, created_at, updated_at) VALUES (${TENANT_ID}, '${COMPANY_NAME}', '${COMPANY_RFC}', false, now(), now());" 2>&1
|
|
echo -e "${GREEN}✓ Company creada${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Company ya existe para este tenant${NC}"
|
|
fi
|
|
|
|
# Obtener información de la company
|
|
COMPANY_INFO=$(docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -t -c "SELECT id, name FROM a76.company WHERE tenant_id = ${TENANT_ID} LIMIT 1;")
|
|
|
|
echo -e "${GREEN}✓ Company: ${COMPANY_INFO}${NC}"
|
|
|
|
# Agregar tenant_id al usuario demo en Keycloak
|
|
echo -e "\n${YELLOW}Asignando tenant_id al usuario demo...${NC}"
|
|
|
|
curl -s -X PUT "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/${USER_ID}" \
|
|
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"attributes\": {
|
|
\"tenant_id\": [\"${TENANT_ID}\"]
|
|
}
|
|
}"
|
|
|
|
echo -e "${GREEN}✓ Atributo tenant_id asignado al usuario${NC}"
|
|
|
|
# Agregar relación usuario-tenant en la base de datos
|
|
echo -e "\n${YELLOW}Creando relación usuario-tenant en la base de datos...${NC}"
|
|
|
|
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "INSERT INTO a76.user_tenants (keycloak_user_id, tenant_id, company_id, role, is_active, created_at, updated_at) VALUES ('${USER_ID}', ${TENANT_ID}, 1, 'admin', true, now(), now()) ON CONFLICT (keycloak_user_id, tenant_id, company_id) DO UPDATE SET is_active = true, updated_at = CURRENT_TIMESTAMP;" 2>&1
|
|
|
|
echo -e "${GREEN}✓ Relación usuario-tenant creada en la base de datos${NC}"
|
|
|
|
###############################################################################
|
|
# Resumen final
|
|
###############################################################################
|
|
echo -e "\n${GREEN}════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} ✓ Inicialización completada exitosamente${NC}"
|
|
echo -e "${GREEN}════════════════════════════════════════════════════════${NC}"
|
|
echo -e "\n${YELLOW}Credenciales de acceso:${NC}"
|
|
echo -e " Usuario: ${GREEN}${DEMO_USERNAME}${NC}"
|
|
echo -e " Password: ${GREEN}${DEMO_PASSWORD}${NC}"
|
|
echo -e " Email: ${GREEN}${DEMO_EMAIL}${NC}"
|
|
echo -e "\n${YELLOW}Información del sistema:${NC}"
|
|
echo -e " Tenant: ${GREEN}${TENANT_NAME} (ID: ${TENANT_ID})${NC}"
|
|
echo -e " Realm: ${GREEN}${KEYCLOAK_REALM}${NC}"
|
|
echo -e " Keycloak URL: ${GREEN}${KEYCLOAK_URL}${NC}"
|
|
echo -e "\n${YELLOW}Clientes Keycloak configurados:${NC}"
|
|
echo -e " Backend Client ID: ${GREEN}anexo76-backend${NC}"
|
|
if [ -n "$BACKEND_SECRET" ]; then
|
|
echo -e " Backend Secret: ${GREEN}${BACKEND_SECRET}${NC}"
|
|
if [ -n "$ENV_FILE" ]; then
|
|
echo -e " ${GREEN}✓${NC} KEYCLOAK_CLIENT_SECRET actualizado en ${ENV_FILE}"
|
|
else
|
|
echo -e " ${YELLOW}⚠${NC} Agregar manualmente al archivo .env como KEYCLOAK_CLIENT_SECRET"
|
|
fi
|
|
fi
|
|
echo -e " Frontend Client ID: ${GREEN}anexo76-frontend${NC}"
|
|
echo -e "\n${YELLOW}User Profile Attributes configurados:${NC}"
|
|
echo -e " ${GREEN}✓${NC} tenant_id (opcional, valor inicial: 1)"
|
|
echo -e "\n${YELLOW}Mappers configurados:${NC}"
|
|
echo -e " ${GREEN}✓${NC} tenant_id mapper para Backend"
|
|
echo -e " ${GREEN}✓${NC} tenant_id mapper para Frontend"
|
|
echo -e "\n${YELLOW}Configuración del usuario demo:${NC}"
|
|
echo -e " ${GREEN}✓${NC} tenant_id actualizado al ID real: ${TENANT_ID}"
|
|
echo -e " ${GREEN}✓${NC} Relación usuario-tenant creada (rol: admin)"
|
|
echo -e "\n${YELLOW}Puedes acceder al sistema en:${NC}"
|
|
echo -e " ${GREEN}http://localhost:5173${NC}"
|
|
echo -e "\n${GREEN}════════════════════════════════════════════════════════${NC}\n"
|