Menu

Tree [c94db6] master /
 History

HTTPS access


File Date Author Commit
 .claude 7 hours ago Cristian Gaitán Cristian Gaitán [c94db6] Mensajes de error al ejecutar consultas
 docs 7 hours ago Cristian Gaitán Cristian Gaitán [c94db6] Mensajes de error al ejecutar consultas
 frontend 7 hours ago Cristian Gaitán Cristian Gaitán [c94db6] Mensajes de error al ejecutar consultas
 python_api 7 hours ago Cristian Gaitán Cristian Gaitán [c94db6] Mensajes de error al ejecutar consultas
 tests 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 .gitignore 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 .gitlab-ci.yml 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 README.md 7 hours ago Cristian Gaitán Cristian Gaitán [c94db6] Mensajes de error al ejecutar consultas
 acl_users.json.example 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 acl_users.json.migrated 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 hash_password.py 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 requirements.txt 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 run-dev-mysql.sh 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 run-dev-sqlite.sh 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 run-python-api.sh 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión
 sonar-project.properties 8 hours ago Cristian Gaitán Cristian Gaitán [ed93fc] Nueva Versión

Read Me

AECSA DB Studio

Plataforma de administración de bases de datos con interfaz visual estilo DBeaver/Workbench,
motor de pipelines de datos (jobs), gráficas, reportes PDF y gestor de bloques de transformación reutilizables.


Tabla de contenidos

  1. Arquitectura general
  2. Componentes principales
  3. Instalación y arranque
  4. Variables de entorno
  5. Sistema de permisos (ACL)
  6. Motor de jobs y pipelines
  7. API REST
  8. Logs y monitoreo
  9. Estructura de archivos

Arquitectura general

┌─────────────────────────────────────────────────────────┐
  Frontend  (React 18 + Vite)                            
   Editor SQL con autocompletado (CodeMirror)           
   Canvas visual de pipelines (@xyflow/react)           
   Dashboard, Gráficas (Recharts), Reportes PDF        
└────────────────────┬────────────────────────────────────┘
                      HTTP / REST (Bearer JWT)
┌────────────────────▼────────────────────────────────────┐
  Backend  (FastAPI + Python)                            
   /db/v1/*           Administración de bases de datos  
   /jobs/v1/*         Motor de pipelines y jobs         
   /charts/v1/*       Gráficas guardadas                
   /reports/v1/*      Reportes PDF                      
   /transform-blocks/v1/* Bloques reutilizables         
   /admin/users/*     Gestión de usuarios ACL           
   /oauth/token       Autenticación JWT                 
└──────┬──────────────────────────┬───────────────────────┘
                                 
┌──────▼──────┐          ┌────────▼──────────────────────┐
 app_state               Bases de datos administradas  
 (SQLite /               MySQL / PostgreSQL / SQLite   
  MySQL /                (una o varias, configuradas   
  PostgreSQL)             en .env como SERVERS)        
                       └────────────────────────────────┘
 users_acl   
 charts      
 jobs        
 job_runs    
 job_run_steps
 reports     
 transform_  
 blocks      
└─────────────┘

Componentes principales

Backend (python_api/)

Módulo Descripción
app/api/ Routers FastAPI — uno por recurso
app/services/jobs_engine.py Motor de ejecución de pipelines. 20+ tipos de paso: SQL, transformación, calidad de datos, flujo, Python en sandbox
app/services/jobs_service.py CRUD de jobs, disparo de corridas (manual/scheduler)
app/services/transform_blocks_service.py CRUD de bloques de transformación reutilizables
app/services/charts_service.py CRUD de gráficas + ejecución de consultas
app/services/reports_service.py Generación de PDFs con ReportLab
app/services/python_sandbox.py Sandbox real con bwrap (bubblewrap): aislamiento de red/filesystem/CPU/RAM
app/core/acl.py Motor de autorización por scopes
app/core/acl_users.py CRUD de usuarios ACL en la BD
app/core/security.py Emisión y validación de JWT
app/db/connection.py Pool de conexiones SQLAlchemy a las BDs administradas
app/db/app_state.py BD de estado propio de la app (SQLite por defecto)
app/support/audit_logger.py Logging estructurado por categoría (ops, security, jobs, errors)

Frontend (frontend/)

Componente Descripción
SqlEditorTab.jsx Editor SQL con autocompletado de esquema via CodeMirror
JobCanvas.jsx Canvas visual de pipelines con drag & drop (@xyflow/react)
JobEditorTab.jsx Editor completo de un job (canvas + metadatos)
ChartsTab.jsx Vista de gráficas con Recharts
TransformBlockFormModal.jsx Editor de bloques de transformación (sub-canvas)
ScopeBuilder.jsx Constructor visual de permisos ACL

Instalación y arranque

Requisitos

  • Python 3.11+
  • Node.js 18+
  • MySQL 8+ o PostgreSQL 14+ (para las bases administradas)
  • bwrap (bubblewrap) para el paso Python en sandbox:
    bash sudo apt install bubblewrap # Debian/Ubuntu

Backend

cd python_api
pip install -r requirements.txt

# Configurar variables (ver sección Variables de entorno)
cp ../.env.example ../.env
# Editar .env con los datos de los servidores de BD

# Arrancar (desarrollo)
cd ..
./run-dev-mysql.sh
# o: ENABLE_ACL=true ./run-dev-mysql.sh

# El backend queda en http://localhost:3560
# Swagger completo:        /docs  o  /swagger
# Swagger SQL + consultas: /swagger-consultas
# Swagger solo API datos:  /swagger-api

Frontend

cd frontend
npm install
npm run dev        # desarrollo (http://localhost:5173)
npm run build      # producción → dist/

Primer usuario

Con ENABLE_ACL=true, la app requiere un usuario para hacer login. Si no hay ninguno en la BD (arranque fresco), el script hash_password.py genera el hash:

cd python_api
python hash_password.py MiPassword123!
# Copia el hash y ejecuta el endpoint POST /admin/users con admin auth
# o importa acl_users.json.example como acl_users.json antes del primer arranque

Variables de entorno

Todas van en el .env en la raíz del repo. Las marcadas con * son obligatorias en producción.

Variable Default Descripción
JWT_SECRET * Clave para firmar JWTs. Mínimo 32 caracteres aleatorios
ENABLE_ACL false true = requiere login y aplica scopes
APP_DB_URL sqlite:///./app_state.db BD de estado de la app. Cambiar a MySQL/PostgreSQL en producción
SERVERS {} JSON con los servidores de BD administrados (ver ejemplo abajo)
DATABASE_TYPE mysql mysql | postgresql | sqlite
PORT 3560 Puerto del backend
ALLOW_RAW_SQL false true = permite exec-query sin CTE (requiere scope db:xxx:sql)
ENABLE_DOCS true false = deshabilita Swagger en producción
LOG_DIR logs/ Directorio de logs
JOB_OUTPUTS_DIR job_outputs/ Archivos generados por jobs
JOB_UPLOADS_DIR job_uploads/ CSVs/XLSXs subidos para pasos file_input
JOB_UPLOAD_MAX_MB 50 Tamaño máximo de archivo subido

Configuración de servidores (SERVERS)

SERVERS='{
  "produccion": {
    "type": "mysql",
    "host": "db.empresa.com",
    "port": 3306,
    "user": "dbstudio",
    "password": "secreto",
    "databases": ["crm", "ventas", "logistica"]
  },
  "analytics": {
    "type": "postgresql",
    "host": "analytics.empresa.com",
    "port": 5432,
    "user": "readonly",
    "password": "otro_secreto",
    "databases": ["warehouse"]
  }
}'

BD de estado en MySQL/PostgreSQL

APP_DB_URL=mysql+pymysql://usuario:clave@servidor:3306/dbstudio_meta
# o
APP_DB_URL=postgresql+psycopg://usuario:clave@servidor:5432/dbstudio_meta

Las tablas se crean automáticamente al arrancar (sin migraciones manuales).


Sistema de permisos (ACL)

Con ENABLE_ACL=false (default): cualquier JWT válido tiene acceso total.
Con ENABLE_ACL=true: cada usuario tiene un conjunto de scopes.

Grammar de scopes

admin                               Acceso total  bypasea todo lo demás

# Bases de datos
db:<bd>:read                        Leer cualquier tabla de <bd>
db:<bd>:write                       Escribir/actualizar/borrar en <bd>
db:<bd>:schema                      Crear/editar vistas, procedimientos, triggers
db:<bd>:sql                         Ejecutar SQL crudo y CTEs
db:<bd>:table:<tabla>:read          Lectura granular a una tabla
db:<bd>:table:<tabla>:write         Escritura granular a una tabla
db:*:read / db:*:write / etc.       Wildcard  aplica a todas las BDs

# Herramientas globales
download                            Exportar resultados como CSV/XLSX
copy                                Copiar datos de la grilla (solo UX)

# Módulos de la aplicación
charts:read / charts:write          Gráficas guardadas
reports:read / reports:write        Reportes PDF
jobs:read / jobs:write              Definiciones de jobs
jobs:execute                        Disparar corridas manuales
jobs:python                         Guardar pasos con código Python (sandbox)
transform_blocks:read / :write      Bloques de transformación reutilizables

Perfiles típicos

Perfil Scopes
Admin admin
Desarrollador db:xxx:read write sql schema + todos los módulos
Analista db:xxx:read sql download charts:read reports:read jobs:read
Operador de jobs db:xxx:read sql jobs:read jobs:execute
Solo lectura db:xxx:read download

Motor de jobs y pipelines

Tipos de paso disponibles

Categoría Tipos
Entrada sql_source, generate_rows (plantilla o tabla), file_input
Salida save_table, export_file (CSV/XLSX/JSON/JSON_objeto/XML), render_chart (PNG), generate_report (PDF)
Transformación filter_rows, sort_rows, select_values, calculator, group_by, pivot_table
Uniones join_rows (SQL join via pandas), union_rows
Flujo dummy, switch_case
Calidad data_cleanse, data_validate
Script python_transform (sandbox bwrap)
Bloques transform_block (referencia a un bloque reutilizable guardado)

Encadenamiento multi-servidor

Un paso sql_source que recibe datos de un paso anterior los materializa como tabla temporal en el servidor destino, permitiendo JOINs entre datos de distintos servidores sin conexión directa entre ellos. Los datos viajan en memoria vía Python.

Seguridad del sandbox Python

El paso python_transform corre en un sandbox real con bwrap (mismo aislamiento de Flatpak):

  • Sin acceso a red (namespace de red separado)
  • Filesystem de solo lectura salvo un directorio temporal propio
  • Límites de CPU y memoria via resource.setrlimit
  • Timeout de pared configurable
  • Allowlist de imports: pandas, numpy, math, datetime, json, re, statistics, itertools, collections

API REST

Autenticación

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

username=ana&password=secreto

Respuesta: {"access_token": "<JWT>", "token_type": "bearer"}

Todos los demás endpoints requieren Authorization: Bearer <token>.

Documentación interactiva

URL Contenido
/docs Swagger completo — todos los endpoints
/swagger-consultas Solo exec-query, CTE, export + endpoints de consumo de datos
/swagger-api Solo API de consumo de datos (para integrar con Grafana, Power BI, etc.)

Endpoints clave para integración externa

# Datos de la última salida exitosa de un step (para polling periódico)
GET /jobs/v1/{job_id}/data/{step_id}
 {"data": [...filas...], "count": N, "meta": {...}}

# Archivo de la última salida (CSV, JSON, XML, PNG, XLSX)
GET /jobs/v1/{job_id}/latest-output/{step_id}
 archivo con Content-Type apropiado (sin forced download)

# Datos de una gráfica guardada
POST /charts/v1/{chart_id}/data
 {"data": [...filas...], "meta": {...}}

# Generar PDF de un reporte
POST /reports/v1/{report_id}/generate
 archivo PDF

Logs y monitoreo

Los logs se generan en logs/ con rotación diaria (30 días de retención).

Archivos de log

Archivo Contenido Retención
logs/ops.log Requests normales (< 400): consultas, exports, reads 30 días
logs/security.log Login, logout, creación/modificación de usuarios 90 días
logs/jobs.log Ciclo de vida de jobs: creación, corridas, fallos por paso 30 días
logs/errors.log Requests con status ≥ 400, excepciones inesperadas 7 días

Formato de línea

[2026-07-01 14:32:01] INFO     dbstudio.ops  REQUEST_OK  method=POST  path=/db/v1/cte  user=ana  ip=10.0.0.5  status=200  duration_ms=142  db=crm
[2026-07-01 14:32:05] INFO     dbstudio.security  LOGIN_OK  username=ana  ip=10.0.0.5  status=200  duration_ms=38
[2026-07-01 14:33:00] INFO     dbstudio.jobs  RUN_START  job_id=3  job_name="Export diario"  run_id=17  trigger=schedule  user=sistema  steps=4
[2026-07-01 14:33:02] INFO     dbstudio.jobs  RUN_COMPLETE  job_id=3  job_name="Export diario"  run_id=17  trigger=schedule  user=sistema
[2026-07-01 14:40:01] WARNING  dbstudio.security  LOGIN_FAIL  username=hacker  ip=192.168.1.100  status=401  duration_ms=250

Monitoreo de eventos clave

Evento Log Nivel
Login exitoso security.log INFO
Login fallido security.log WARNING
Usuario creado/modificado/borrado security.log INFO
Job creado/borrado jobs.log INFO
Corrida iniciada/completada jobs.log INFO
Paso de job fallido jobs.log WARNING
Request con error 4xx errors.log WARNING
Request con error 5xx errors.log ERROR

Estructura de archivos

api-mysql/
├── .env                          # Variables de entorno (no commitear)
├── .env.example                  # Plantilla de configuración
├── run-dev-mysql.sh              # Script de arranque del backend
├── hash_password.py              # CLI para generar hashes bcrypt
├── acl_users.json.example        # Ejemplo de usuarios ACL

├── python_api/                   # Backend FastAPI
   ├── app/
      ├── main.py               # App factory, routers, Swagger x3
      ├── api/                  # Routers HTTP
         ├── jobs.py           # /jobs/v1/*
         ├── charts.py         # /charts/v1/*
         ├── reports.py        # /reports/v1/*
         ├── transform_blocks.py # /transform-blocks/v1/*
         ├── admin_users.py    # /admin/users/*
         └── oauth.py          # /oauth/token
      ├── core/
         ├── acl.py            # Motor de scopes
         ├── acl_users.py      # CRUD de usuarios en BD
         ├── config.py         # Settings via pydantic-settings
         └── security.py       # JWT (emisión y validación)
      ├── db/
         ├── app_state.py      # Motor SQLAlchemy para estado propio
         ├── models_app.py     # ORM: UserModel, ChartModel, JobModel...
         └── connection.py     # Pool de conexiones a BDs administradas
      ├── services/
         ├── jobs_engine.py    # Motor de ejecución de pipelines
         ├── jobs_service.py   # CRUD + scheduler de jobs
         ├── python_sandbox.py # Sandbox bwrap para python_transform
         ├── charts_service.py
         ├── reports_service.py
         └── transform_blocks_service.py
      ├── http/
         └── middlewares/
             └── audit_log.py  # Middleware de logging por request
      └── support/
          └── audit_logger.py   # Loggers por categoría con rotación
   └── requirements.txt

├── frontend/                     # React + Vite
   ├── src/
      ├── App.jsx               # Shell principal + routing por tabs
      ├── components/           # UI components
         ├── SqlEditorTab.jsx
         ├── JobCanvas.jsx     # Canvas visual de pipelines
         ├── JobEditorTab.jsx
         ├── ChartsTab.jsx
         └── ...
      ├── api/client.js         # Cliente HTTP (axios + manejo de errores)
      ├── hooks/
         └── useSqlCompletion.js # Autocompletado SQL por schema
      ├── store/AppContext.jsx  # Estado global (tabs, auth, theme)
      └── utils/sqlUtils.js     # Detección de bindings y modo de query
   └── package.json

├── logs/                         # Logs de la app (generados en runtime)
   ├── ops.log
   ├── security.log
   ├── jobs.log
   └── errors.log

├── job_outputs/                  # Archivos generados por jobs
└── job_uploads/                  # Archivos subidos para pasos file_input
Auth0 Logo