Remove build_errors.txt and validate_auth.sh scripts; clean up unused imports and fix type inference issues in lms-service.

This commit is contained in:
2026-04-28 12:29:03 -04:00
parent e88fd571f0
commit b670ff3c04
12 changed files with 0 additions and 3389 deletions
-372
View File
@@ -1,372 +0,0 @@
# OpenCCB - Resumen de Configuración y Despliegue
## Fecha: 26 de Marzo de 2026
---
## 📋 Resumen del Proyecto
**OpenCCB** es una plataforma LMS/CMS de código abierto desplegada en **AWS EC2** con nginx-proxy para SSL automático.
**Servidor AWS:**
- **Host**: `ec2-18-224-137-67.us-east-2.compute.amazonaws.com`
- **Usuario**: `ubuntu`
- **SSH Key**: `ubuntu.pem`
- **Región**: us-east-2 (Ohio)
---
## 🔧 Configuración Actual
### Dominios
- `studio.norteamericano.com` - CMS/Admin
- `learning.norteamericano.com` - LMS/Estudiantes
### Arquitectura
```
┌─────────────────────────────────────────────────────┐
│ AWS EC2 │
│ │
│ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ nginx │───▶│ Studio + CMS │ │
│ │ proxy │ │ (Next.js + Rust) │ │
│ │ :80, :443 │ │ :3000, :3001 │ │
│ └──────┬──────┘ └──────────┬───────────────┘ │
│ │ │ │
│ │ ┌─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ acme │ │ Experience + LMS │ │
│ │ companion │ │ (Next.js + Rust) │ │
│ │ (Let's │ │ :3003, :3002 │ │
│ │ Encrypt) │ └──────────┬───────────────┘ │
│ └─────────────┘ │ │
│ │ │
│ ┌──────────▼───────────────┐ │
│ │ PostgreSQL + PGVector │ │
│ │ :5432 │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────┘
```
---
## 🚀 Comandos de Despliegue
### Desde tu máquina local:
```bash
# Ejecutar deploy
./deploy.sh
```
El script preguntará:
1. Nombre del administrador
2. Email del administrador
3. Contraseña (oculta)
4. Nombre de la organización
5. ¿Usar SSL? [y/N]
- **y**: Usará HTTPS (con o sin staging)
- **N**: Usará HTTP (recomendado para staging)
6. ¿Usar STAGING? [y/N] (solo si elegiste SSL)
- **y**: Certificados de prueba (sin rate limits)
- **N**: Certificados reales (con rate limits)
### Conexión al servidor:
```bash
ssh -i "ubuntu.pem" ubuntu@ec2-18-224-137-67.us-east-2.compute.amazonaws.com
cd /var/www/openccb
```
---
## ⚠️ Problemas Conocidos y Soluciones
### 1. Login Pegado / Error de Conexión API
**Problema**: El botón de login se queda procesando infinitamente.
**Causa**: Las URLs de la API incluyen el puerto `:3001` incorrectamente.
**Solución Aplicada**:
- Actualizado `web/studio/src/lib/api.ts` para hardcodear las URLs de producción
- El código ahora detecta el hostname y usa la URL sin puerto
**Comandos para Solucionar**:
```bash
# Conectarse al servidor
ssh -i "ubuntu.pem" ubuntu@ec2-18-224-137-67.us-east-2.compute.amazonaws.com
cd /var/www/openccb
# Detener todo
sudo docker compose down
# Eliminar imágenes cacheadas
sudo docker rmi openccb-studio 2>/dev/null || true
sudo docker images | grep openccb | awk '{print $3}' | xargs sudo docker rmi -f 2>/dev/null || true
# Limpiar caché de Docker
sudo docker builder prune -af
sudo docker system prune -af
# Reconstruir DESDE CERO (CRÍTICO usar --no-cache)
sudo docker compose build --no-cache studio
# Iniciar todo
sudo docker compose up -d
# Esperar 1 minuto
sleep 60
# Verificar
sudo docker compose ps
docker logs openccb-studio --tail 20
```
**Verificación en el Navegador**:
1. Abrir ventana de incógnito (Ctrl+Shift+N)
2. Ir a `http://studio.norteamericano.com`
3. Abrir consola (F12) → Pestaña Network
4. Intentar loguearse
5. Verificar que la URL sea: `http://studio.norteamericano.com/auth/login` (SIN puerto)
### 2. Rate Limit de Let's Encrypt
**Problema**: Se alcanzó el límite de 5 certificados por semana.
**Solución Temporal**:
- Usar HTTP en lugar de HTTPS
- O usar Let's Encrypt Staging (certificados de prueba)
**Fecha de Reinicio**: 2026-03-27 04:21:42 UTC
---
## 📁 Archivos Modificados
### 1. `deploy.sh`
- ✅ Pregunta datos del administrador
- ✅ Pregunta sobre SSL y Staging
- ✅ Actualiza docker-compose.yml según elección (HTTP/HTTPS)
- ✅ Reconstruye contenedores con `--no-cache`
- ✅ Verifica variables de entorno en los contenedores
- ✅ Muestra URLs correctas según protocolo elegido
### 2. `docker-compose.yml`
- ✅ URLs en HTTP por defecto
- ✅ Ambos argumentos de build para studio:
- `NEXT_PUBLIC_CMS_API_URL: http://studio.norteamericano.com`
- `NEXT_PUBLIC_LMS_API_URL: http://learning.norteamericano.com`
- ✅ Variables de entorno correctas
### 3. `web/studio/Dockerfile`
- ✅ Agrega `ARG NEXT_PUBLIC_LMS_API_URL`
- ✅ Agrega `ENV NEXT_PUBLIC_LMS_API_URL`
### 4. `web/studio/src/lib/api.ts`
- ✅ Corrige función `getApiBaseUrl` para producción
- ✅ Hardcodea URLs para `studio.norteamericano.com` y `learning.norteamericano.com`
- ✅ Elimina el puerto de las URLs en producción
---
## 🔐 Credenciales (Ejemplo)
**Usuario Administrador**:
- Email: `admin@norteamericano.com`
- Contraseña: `Admin123!` (o la que se haya configurado)
**Base de Datos** (en `/var/www/openccb/.env`):
```
DB_PASSWORD=<generada_aleatoriamente>
JWT_SECRET=<generada_aleatoriamente>
```
---
## 📊 Comandos Útiles
### Ver estado de servicios
```bash
sudo docker compose ps
```
### Ver logs
```bash
# Todos los servicios
sudo docker compose logs -f
# Servicio específico
docker logs openccb-studio --tail 50
docker logs openccb-experience --tail 50
docker logs acme-companion --tail 50
```
### Verificar variables de entorno
```bash
# Studio
sudo docker exec openccb-studio env | grep NEXT_PUBLIC
# Experience
sudo docker exec openccb-experience env | grep NEXT_PUBLIC
# Debería mostrar:
# NEXT_PUBLIC_CMS_API_URL=http://studio.norteamericano.com
# NEXT_PUBLIC_LMS_API_URL=http://learning.norteamericano.com
```
### Reconstruir contenedores
```bash
# Todo
sudo docker compose build --no-cache
sudo docker compose up -d
# Solo studio
sudo docker compose build --no-cache studio
sudo docker compose up -d studio
```
### Limpiar caché de Docker
```bash
# Limpiar builder
sudo docker builder prune -af
# Limpiar sistema
sudo docker system prune -af
```
### Verificar certificados SSL
```bash
docker logs acme-companion --tail 50
```
---
## 🎯 Próximos Pasos
### 1. Reconstruir Studio con --no-cache
```bash
ssh -i "ubuntu.pem" ubuntu@ec2-18-224-137-67.us-east-2.compute.amazonaws.com
cd /var/www/openccb
sudo docker compose down
sudo docker rmi openccb-studio 2>/dev/null || true
sudo docker builder prune -af
sudo docker compose build --no-cache studio
sudo docker compose up -d
sleep 60
sudo docker compose ps
```
### 2. Probar Login
- Abrir ventana de incógnito
- Ir a `http://studio.norteamericano.com`
- Ver consola (F12) → Network
- Verificar URL: `http://studio.norteamericano.com/auth/login`
- Intentar loguearse
### 3. Verificar Funcionalidades
- [ ] Login de administrador
- [ ] Creación de cursos
- [ ] Subida de archivos
- [ ] Integración con LMS
- [ ] Certificados SSL generados
### 4. Cambiar a HTTPS (Después del Rate Limit)
```bash
# Después del 2026-03-27
./deploy.sh
# Responder "y" a "¿Usar SSL?"
# Responder "n" a "¿Usar STAGING?"
```
---
## 🔧 Solución de Problemas Comunes
### Login se queda procesando
```bash
# Verificar URL en consola del navegador
# Debe ser: http://studio.norteamericano.com/auth/login
# NO debe tener :3001
# Si tiene puerto, reconstruir con --no-cache
sudo docker compose build --no-cache studio
sudo docker compose up -d
```
### Error 502 Bad Gateway
```bash
# Verificar que los servicios están corriendo
sudo docker compose ps
# Ver logs
docker logs openccb-studio --tail 50
docker logs nginx-proxy --tail 50
# Reiniciar
sudo docker compose restart
```
### Variables NEXT_PUBLIC faltantes
```bash
# Ver docker-compose.yml
cat docker-compose.yml | grep -A 10 "studio:"
# Verificar en contenedor
sudo docker exec openccb-studio env | grep NEXT_PUBLIC
# Reconstruir
sudo docker compose build --no-cache studio
```
### Certificados SSL no se generan
```bash
# Ver logs
docker logs acme-companion --tail 100
# Verificar DNS
dig studio.norteamericano.com
dig learning.norteamericano.com
# Verificar puertos
sudo netstat -tlnp | grep :80
```
---
## 📝 Notas Importantes
1. **HTTP vs HTTPS**: Actualmente se usa HTTP porque:
- Los certificados de staging no son válidos para producción
- Las llamadas API entre dominios requieren HTTP o certificados válidos
2. **Rate Limit**: Let's Encrypt permite 5 certificados por semana por dominio. El límite se reinicia el 2026-03-27.
3. **--no-cache es CRÍTICO**: Siempre usar `--no-cache` al reconstruir Studio para que los cambios en el código se apliquen. Docker usa caché por defecto.
4. **Ventana de Incógnito**: Después de reconstruir, siempre probar en ventana de incógnito para evitar caché del navegador.
5. **URLs Hardcodeadas**: El código ahora tiene las URLs de producción hardcodeadas para `studio.norteamericano.com` y `learning.norteamericano.com`. Esto evita problemas con variables de entorno.
---
## 📞 Contacto y Soporte
**Documentación**:
- `DESPLIEGUE.md` - Instrucciones de despliegue
- `README.md` - Documentación general
- `docker-compose.yml` - Configuración de servicios
**Archivos de Configuración**:
- `/var/www/openccb/.env` - Variables de entorno
- `/var/www/openccb/docker-compose.yml` - Servicios Docker
- `web/studio/Dockerfile` - Build de Studio
- `web/studio/src/lib/api.ts` - Configuración de APIs
- `deploy.sh` - Script de despliegue
---
**Última Actualización**: 26 de Marzo de 2026
**Estado**: ✅ Solución aplicada - Pendiente reconstruir con --no-cache y probar login
-468
View File
@@ -1,468 +0,0 @@
# OpenCCB - Project Context
## Project Overview
**OpenCCB (Open Comprehensive Course Backbone)** is an open-source Learning Management System (LMS) and Content Management System (CMS) platform built for performance, security, and scalability. It provides a complete infrastructure for course creation, student management, and AI-powered learning features.
### Architecture
The project uses a **unified container architecture** with the following structure:
| Service | Ports | Description |
|---------|-------|-------------|
| **Studio + CMS** | 3000/3001 | Next.js admin frontend + Rust CMS API |
| **Experience + LMS** | 3003/3002 | Next.js student frontend + Rust LMS API |
| **Database** | 5433 | PostgreSQL 16 (shared, separate DBs: `openccb_cms`, `openccb_lms`) |
### Technology Stack
**Backend:**
- Rust Edition 2024 (workspace with 3 crates)
- Web Framework: Axum 0.8
- Database: SQLx 0.8 with PostgreSQL 16
- Authentication: JWT (jsonwebtoken 9.3), bcrypt
- Security: HMAC, SHA2, OpenID Connect (SSO)
- Rate Limiting: tower-governor 0.7
**Frontend:**
- Next.js 14 (App Router)
- React 18 + TypeScript 5
- Styling: Tailwind CSS 3.4
- UI: Lucide React, Framer Motion, React Markdown
- Mermaid diagrams for dynamic visualization
**Infrastructure:**
- Docker & Docker Compose
- Single-tenant design (premium module)
- Local AI: Ollama (Llama 3.2) + Faster-Whisper
**Key Features:**
- AI-powered course generation and quiz creation
- Discussion forums with nested replies
- LTI 1.3 Tool Provider (Canvas, Moodle integration)
- Monetization via Mercado Pago
- Live learning with Jitsi integration
- Student portfolios with Open Badges
- Predictive analytics (dropout risk detection)
- Multi-language support (EN, ES, PT)
- Gamification (XP, levels, badges, leaderboards)
- **Semantic search with PGVector** (question bank, knowledge base)
- **RAG-enhanced AI tutor** with contextual retrieval
- **MySQL integration** (study plans, courses import)
## Project Structure
```
openccb/
├── services/
│ ├── cms-service/ # Rust CMS API (course management, content creation)
│ │ ├── migrations/ # SQLx database migrations
│ │ └── src/
│ └── lms-service/ # Rust LMS API (student experience, grades)
│ └── src/
├── shared/
│ └── common/ # Shared Rust library (auth, models, utils)
├── web/
│ ├── studio/ # Next.js CMS frontend (admin/instructor)
│ └── experience/ # Next.js LMS frontend (student)
├── e2e/ # Playwright end-to-end tests
├── scripts/ # Utility scripts (auth, database)
└── [config files]
```
### Rust Workspace Members
```toml
[workspace]
members = [
"services/cms-service",
"services/lms-service",
"shared/common",
]
```
## Building and Running
### Docker (Recommended)
```bash
# Start all services
docker-compose up --build
# Start in detached mode
docker-compose up -d
# Rebuild and start
docker-compose up -d --build
# Clean install (removes volumes)
docker-compose down -v && docker-compose up --build
# Run E2E tests
docker-compose --profile test up e2e
```
### Local Development
**Prerequisites:**
- Rust (Edition 2024)
- Node.js 18+
- PostgreSQL 16
- sqlx-cli: `cargo install sqlx-cli --no-default-features --features postgres`
**Backend (Rust):**
```bash
# CMS Service (port 3001)
cd services/cms-service
DATABASE_URL=postgresql://user:password@localhost:5433/openccb_cms cargo run
# LMS Service (port 3002)
cd services/lms-service
DATABASE_URL=postgresql://user:password@localhost:5433/openccb_lms cargo run
# With debug logging
RUST_LOG=debug cargo run -p cms-service
```
**Frontend (Next.js):**
```bash
# Studio (CMS Frontend - port 3000)
cd web/studio
npm install
npm run dev
# Experience (LMS Frontend - port 3003)
cd web/experience
npm install
npm run dev
```
### Installation Script
```bash
# Full installation with database setup
./install.sh
# Fast mode (skip dependency checks)
./install.sh --fast
```
## Development Commands
### Code Quality
```bash
# Frontend linting and formatting
cd web/studio && npm run lint:fix
cd web/studio && npm run format
cd web/studio && npm run type-check
# Same commands available in web/experience
```
### Database Management
```bash
# Reset database (delete and recreate)
./reset_db.sh
# Run migrations manually
DATABASE_URL=postgresql://user:password@localhost:5433/openccb_cms \
sqlx migrate run --source services/cms-service/migrations
DATABASE_URL=postgresql://user:password@localhost:5433/openccb_lms \
sqlx migrate run --source services/lms-service/migrations
```
### Health Checks
```bash
# CMS Service
curl http://localhost:3001/health
curl http://localhost:3001/health/live
curl http://localhost:3001/health/ready
# LMS Service
curl http://localhost:3002/health
curl http://localhost:3002/health/live
curl http://localhost:3002/health/ready
```
### Utilities
```bash
# Generate secure JWT secret
./generate_jwt_secret.sh
# Clear session
./clear_session.sh
# Validate authentication
./validate_auth.sh
# Diagnose auth issues
./diagnose_auth.sh
```
## API Endpoints
### Authentication (CMS - port 3001)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/auth/register` | Create new user |
| POST | `/auth/login` | Login and get JWT token |
| GET | `/auth/profile` | Get current user profile |
### Course Management (CMS)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/courses` | Create course |
| POST | `/courses/generate` | AI-generate course structure |
| GET | `/courses/{id}/export` | Export course to JSON |
| POST | `/courses/import` | Import course from JSON |
| DELETE | `/courses/{id}` | Delete course |
| POST | `/lessons` | Add lesson to module |
| POST | `/assets/upload` | Upload media/document |
### Learning Experience (LMS - port 3002)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/enroll` | Enroll in course |
| POST | `/grades` | Submit lesson score |
| GET | `/notifications` | Get user notifications |
| POST | `/notifications/{id}/read` | Mark notification as read |
### Discussion Forums (LMS)
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/courses/{id}/discussions` | List threads |
| POST | `/courses/{id}/discussions` | Create thread |
| GET | `/discussions/{id}` | Get thread with replies |
| POST | `/discussions/{id}/posts` | Reply to thread |
| POST | `/posts/{id}/vote` | Vote on post |
| POST | `/posts/{id}/endorse` | Mark post as correct (instructor) |
### AI Features
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/lessons/{id}/transcribe` | Start transcription |
| POST | `/lessons/{id}/generate-quiz` | Generate quiz with AI |
| POST | `/lessons/{id}/chat` | Chat with lesson tutor |
| GET | `/lessons/{id}/feedback` | Get AI feedback |
| GET | `/courses/{id}/dropout-risks` | Get dropout risk analysis |
| POST | `/question-bank/embeddings/generate` | Generate embeddings for questions |
| POST | `/question-bank/{id}/embedding/regenerate` | Regenerate question embedding |
| GET | `/question-bank/semantic-search` | Search questions semantically |
| GET | `/question-bank/similar/{id}` | Find similar questions (duplicates) |
| POST | `/question-bank/generate-with-rag` | Generate question with RAG + 4 skills |
| POST | `/knowledge-base/embeddings/generate` | Generate knowledge base embeddings |
| GET | `/knowledge-base/semantic-search` | Search knowledge base semantically |
## Environment Configuration
Copy `.env.example` to `.env` and configure:
```bash
# Database
CMS_DATABASE_URL=postgresql://user:password@localhost:5433/openccb_cms
LMS_DATABASE_URL=postgresql://user:password@localhost:5433/openccb_lms
# JWT Secret (generate with ./generate_jwt_secret.sh)
JWT_SECRET=your_secure_secret
# AI Configuration
AI_PROVIDER=local
LOCAL_WHISPER_URL=http://localhost:9000
LOCAL_OLLAMA_URL=http://localhost:11434
LOCAL_LLM_MODEL=llama3.2:3b
EMBEDDING_MODEL=nomic-embed-text
# Frontend URLs
NEXT_PUBLIC_CMS_API_URL=http://localhost:3001
NEXT_PUBLIC_LMS_API_URL=http://localhost:3002
# Backend-to-backend (LMS -> CMS)
CMS_API_URL=http://studio:3001
```
### Default Credentials
After running `./install.sh`, the default admin user is:
- **Email**: `admin@norteamericano.cl`
- **Password**: `Admin123!`
You can customize these during installation.
## Testing
### E2E Tests (Playwright)
```bash
# Run all tests
cd e2e && npx playwright test
# Run with UI
cd e2e && npx playwright test --ui
# Run specific test file
cd e2e && npx playwright test tests/auth.spec.ts
# Generate report
cd e2e && npx playwright show-report
```
### Backend Tests
```bash
# Run Rust tests
cargo test -p cms-service
cargo test -p lms-service
cargo test -p common
```
## Key Conventions
### Rust Code Style
- Use workspace dependencies from root `Cargo.toml`
- Shared code goes in `shared/common`
- Use `sqlx::query!` macros for compile-time SQL verification
- Error handling with `thiserror` and `anyhow`
- Tracing for logging (`tracing::info!`, `tracing::debug!`)
### Frontend Code Style
- TypeScript strict mode enabled
- Tailwind CSS for styling
- Lucide React for icons
- Framer Motion for animations
- Components in `src/components/`
- Pages in `src/app/` (Next.js App Router)
### Database
- Separate databases for CMS and LMS
- Migrations managed by SQLx
- UUIDs for primary keys
- Timestamps with timezone (timestamptz)
### Authentication
- JWT-based authentication
- Bcrypt password hashing
- Role-based access control (admin, instructor, student)
- OpenID Connect support for SSO
## 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
If port 5432 is occupied, the setup uses 5433:
```bash
# Check if port is in use
lsof -i :5432
lsof -i :5433
```
### Database Connection Issues
```bash
# Check if PostgreSQL is running
docker ps | grep postgres
# Check database connectivity
docker exec openccb-db-1 pg_isready -U user
```
### PGVector Issues
```bash
# Check if pgvector extension is enabled
docker exec -it openccb-db-1 psql -U user -d openccb_cms -c "SELECT * FROM pg_extension WHERE extname = 'vector';"
# If not enabled, run migration
DATABASE_URL=postgresql://user:password@localhost:5433/openccb_cms \
sqlx migrate run --source services/cms-service/migrations
```
### Embedding Generation Issues
```bash
# Check if Ollama is running
curl http://localhost:11434/api/tags
# Pull embedding model
docker exec -it ollama ollama pull nomic-embed-text
# Test embedding generation
curl -X POST http://localhost:11434/api/embeddings \
-H "Content-Type: application/json" \
-d '{"model": "nomic-embed-text", "prompt": "Hello world"}'
```
### Frontend Build Issues
```bash
# Clear Next.js cache
rm -rf web/studio/.next
rm -rf web/experience/.next
# Reinstall dependencies
cd web/studio && rm -rf node_modules && npm install
```
### Rust Compilation Issues
```bash
# Clean and rebuild
cargo clean
cargo build
# Update dependencies
cargo update
```
## Related Documentation
- `README.md` - Comprehensive user documentation with API manual
- `OPTIMIZATIONS.md` - Performance optimizations implemented
- `roadmap.md` - Project roadmap and feature status
- `diagnose_auth.sh` - Authentication debugging script
-31
View File
@@ -1,31 +0,0 @@
const { Client } = require('pg');
async function checkEnrollments() {
const client = new Client({
connectionString: "postgresql://user:password@localhost:5432/openccb_lms"
});
try {
await client.connect();
console.log("Connected to LMS DB");
console.log("\n--- Users ---");
const users = await client.query("SELECT id, email, organization_id, full_name FROM users");
console.table(users.rows);
console.log("\n--- Enrollments ---");
const enrollments = await client.query("SELECT id, user_id, course_id, organization_id FROM enrollments");
console.table(enrollments.rows);
console.log("\n--- Courses ---");
const courses = await client.query("SELECT id, title, organization_id FROM courses");
console.table(courses.rows);
} catch (err) {
console.error("Error:", err);
} finally {
await client.end();
}
}
checkEnrollments();
-74
View File
@@ -1,74 +0,0 @@
const mysql = require('mysql2/promise');
async function checkMySQL() {
try {
const conn = await mysql.createConnection('mysql://root:Smith3976!@ec2-18-222-25-254.us-east-2.compute.amazonaws.com:3306/sige_sam_v3');
console.log('Conectado a MySQL\n');
// Mostrar tablas
const [tables] = await conn.query('SHOW TABLES');
console.log('=== TABLAS ===');
console.table(tables);
// Estructura de curso
console.log('\n=== ESTRUCTURA DE curso ===');
const [cursoCols] = await conn.query('DESCRIBE curso');
console.table(cursoCols);
// Estructura de plandeestudios
console.log('\n=== ESTRUCTURA DE plandeestudios ===');
const [planCols] = await conn.query('DESCRIBE plandeestudios');
console.table(planCols);
// Ver algunos cursos de ejemplo
console.log('\n=== CURSOS (ejemplo) ===');
const [cursos] = await conn.query('SELECT * FROM curso LIMIT 5');
console.table(cursos);
// Ver planes de estudio
console.log('\n=== PLANES DE ESTUDIO (ejemplo) ===');
const [planes] = await conn.query('SELECT * FROM plandeestudios LIMIT 5');
console.table(planes);
// Buscar tabla con idDetalleContrato
console.log('\n=== Buscando tablas con idDetalleContrato ===');
const [detalleTables] = await conn.query(`
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'sige_sam_v3'
AND COLUMN_NAME LIKE '%idDetalle%'
`);
console.table(detalleTables);
// Estructura de detallecontrato
console.log('\n=== ESTRUCTURA DE detallecontrato ===');
const [detalleCols] = await conn.query('DESCRIBE detallecontrato');
console.table(detalleCols);
// Estructura de prueba (banco de preguntas)
console.log('\n=== ESTRUCTURA DE prueba ===');
const [pruebaCols] = await conn.query('DESCRIBE prueba');
console.table(pruebaCols);
// Ver algunos detallecontrato
console.log('\n=== DETALLE CONTRATO (ejemplo) ===');
const [detalles] = await conn.query('SELECT * FROM detallecontrato LIMIT 5');
console.table(detalles);
// Ver banco de preguntas
console.log('\n=== BANCO DE PREGUNTAS (ejemplo) ===');
const [preguntas] = await conn.query('SELECT * FROM bancopreguntas LIMIT 5');
console.table(preguntas);
// Ver tipo_nota
console.log('\n=== TIPO NOTA ===');
const [tiposNota] = await conn.query('SELECT * FROM tiponota');
console.table(tiposNota);
await conn.end();
} catch (err) {
console.error('Error:', err.message);
}
}
checkMySQL();
-14
View File
@@ -1,14 +0,0 @@
#!/bin/bash
# Script para limpiar tokens antiguos y forzar re-login
echo "=== Limpiando tokens antiguos de localStorage ==="
echo ""
echo "Por favor, ejecuta esto en la consola del navegador (F12 → Console):"
echo ""
echo "localStorage.removeItem('studio_token');"
echo "localStorage.removeItem('studio_user');"
echo "location.reload();"
echo ""
echo "Luego vuelve a hacer login con:"
echo " Email: juan.allende@gmail.com"
echo " Password: apoca11"
-49
View File
@@ -1,49 +0,0 @@
#!/bin/bash
echo "=== DIAGNÓSTICO DE AUTENTICACIÓN ==="
echo ""
# 1. Verificar que el backend acepta login
echo "1. Probando LOGIN directo al backend..."
RESPONSE=$(curl -s -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"juan.allende@gmail.com","password":"password123"}')
TOKEN=$(echo $RESPONSE | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then
echo "❌ ERROR: No se pudo obtener token del backend"
echo "Respuesta: $RESPONSE"
exit 1
else
echo "✅ Token obtenido exitosamente"
echo "Token: ${TOKEN:0:50}..."
fi
echo ""
echo "2. Probando acceso a /courses CON el token..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
http://localhost:3001/courses)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "✅ Acceso a /courses exitoso (200)"
else
echo "❌ Acceso a /courses falló con código: $HTTP_CODE"
# Mostrar respuesta completa
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:3001/courses
fi
echo ""
echo "3. Verificando JWT_SECRET en el contenedor..."
JWT_SECRET=$(docker exec openccb-studio-1 env | grep JWT_SECRET | cut -d'=' -f2)
echo "JWT_SECRET actual: $JWT_SECRET"
echo ""
echo "=== INSTRUCCIONES ==="
echo "Si el test 2 fue exitoso, el problema está en el navegador."
echo "Ejecuta en la consola del navegador (F12):"
echo ""
echo " localStorage.clear();"
echo " location.reload();"
echo ""
echo "Luego vuelve a hacer login."
-1
View File
@@ -1 +0,0 @@
Invalid credentials
-301
View File
@@ -1,301 +0,0 @@
{
"name": "openccb",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"mysql2": "^3.20.0",
"pg": "^8.17.2"
}
},
"node_modules/@types/node": {
"version": "25.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/aws-ssl-profiles": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
"integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10"
}
},
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"license": "MIT",
"dependencies": {
"is-property": "^1.0.2"
}
},
"node_modules/iconv-lite": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
"integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
"license": "MIT"
},
"node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"license": "Apache-2.0"
},
"node_modules/lru.min": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz",
"integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==",
"license": "MIT",
"engines": {
"bun": ">=1.0.0",
"deno": ">=1.30.0",
"node": ">=8.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wellwelwel"
}
},
"node_modules/mysql2": {
"version": "3.20.0",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.20.0.tgz",
"integrity": "sha512-eCLUs7BNbgA6nf/MZXsaBO1SfGs0LtLVrJD3WeWq+jPLDWkSufTD+aGMwykfUVPdZnblaUK1a8G/P63cl9FkKg==",
"license": "MIT",
"dependencies": {
"aws-ssl-profiles": "^1.1.2",
"denque": "^2.1.0",
"generate-function": "^2.3.1",
"iconv-lite": "^0.7.2",
"long": "^5.3.2",
"lru.min": "^1.1.4",
"named-placeholders": "^1.1.6",
"sql-escaper": "^1.3.3"
},
"engines": {
"node": ">= 8.0"
},
"peerDependencies": {
"@types/node": ">= 8"
}
},
"node_modules/named-placeholders": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz",
"integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==",
"license": "MIT",
"dependencies": {
"lru.min": "^1.1.0"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/pg": {
"version": "8.17.2",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.17.2.tgz",
"integrity": "sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw==",
"license": "MIT",
"peer": true,
"dependencies": {
"pg-connection-string": "^2.10.1",
"pg-pool": "^3.11.0",
"pg-protocol": "^1.11.0",
"pg-types": "2.2.0",
"pgpass": "1.0.5"
},
"engines": {
"node": ">= 16.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.3.0"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
"integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
"license": "MIT",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.1.tgz",
"integrity": "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw==",
"license": "MIT"
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"license": "ISC",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz",
"integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==",
"license": "MIT",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz",
"integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==",
"license": "MIT"
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"license": "MIT",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
"integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/sql-escaper": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.3.tgz",
"integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==",
"license": "MIT",
"engines": {
"bun": ">=1.0.0",
"deno": ">=2.0.0",
"node": ">=12.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/mysqljs/sql-escaper?sponsor=1"
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"license": "MIT"
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
}
}
}
-6
View File
@@ -1,6 +0,0 @@
{
"dependencies": {
"mysql2": "^3.20.0",
"pg": "^8.17.2"
}
}
File diff suppressed because it is too large Load Diff
-620
View File
@@ -1,620 +0,0 @@
Checking lms-service v0.1.0 (/home/juan/dev/openccb/services/lms-service)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers.rs:154:22
|
154 | let categories = sqlx::query!(
| ______________________^
155 | | "SELECT id, name FROM grading_categories WHERE course_id = $1 ORDER BY name",
156 | | course_id
157 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers.rs:163:20
|
163 | let students = sqlx::query!(
| ____________________^
164 | | r#"
165 | | SELECT
166 | | u.id,
... |
180 | | org_ctx.id
181 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers.rs:193:27
|
193 | let detailed_grades = sqlx::query_as!(
| ___________________________^
194 | | UserCategoryGrade,
195 | | r#"
196 | | SELECT
... |
205 | | course_id
206 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers.rs:896:24
|
896 | let dependencies = sqlx::query_as!(
| ________________________^
897 | | LessonDependency,
898 | | r#"
899 | | SELECT ld.*
... |
905 | | id
906 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers.rs:1004:30
|
1004 | let unmet_dependencies = sqlx::query!(
| ______________________________^
1005 | | r#"
1006 | | SELECT ld.prerequisite_lesson_id, p.title as prereq_title, ld.min_score_percentage
1007 | | FROM lesson_dependencies ld
... |
1020 | | claims.sub
1021 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_announcements.rs:55:23
|
55 | let cohorts = sqlx::query!(
| _______________________^
56 | | "SELECT cohort_id FROM announcement_cohorts WHERE announcement_id = $1",
57 | | a.id
58 | | )
| |_________^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:21:46
|
21 | let existing: Option<CourseSubmission> = sqlx::query_as!(
| ______________________________________________^
22 | | CourseSubmission,
23 | | "SELECT * FROM course_submissions WHERE user_id = $1 AND lesson_id = $2",
24 | | claims.sub,
25 | | lesson_id
26 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:33:23
|
33 | let updated = sqlx::query_as!(
| _______________________^
34 | | CourseSubmission,
35 | | r#"
36 | | UPDATE course_submissions
... |
43 | | lesson_id
44 | | )
| |_________^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:53:22
|
53 | let submission = sqlx::query_as!(
| ______________________^
54 | | CourseSubmission,
55 | | r#"
56 | | INSERT INTO course_submissions (user_id, course_id, lesson_id, organization_id, content)
... |
64 | | payload.content
65 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:83:22
|
83 | let submission = sqlx::query_as!(
| ______________________^
84 | | CourseSubmission,
85 | | r#"
86 | | SELECT s.*
... |
105 | | org_ctx.id
106 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:122:22
|
122 | let submission = sqlx::query!(
| ______________________^
123 | | "SELECT user_id FROM course_submissions WHERE id = $1",
124 | | payload.submission_id
125 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:143:20
|
143 | let existing = sqlx::query!(
| ____________________^
144 | | "SELECT id FROM peer_reviews WHERE submission_id = $1 AND reviewer_id = $2",
145 | | payload.submission_id,
146 | | claims.sub
147 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:160:18
|
160 | let review = sqlx::query_as!(
| __________________^
161 | | PeerReview,
162 | | r#"
163 | | INSERT INTO peer_reviews (submission_id, reviewer_id, score, feedback, organization_id)
... |
171 | | org_ctx.id
172 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error: error communicating with database: Connection refused (os error 111)
--> services/lms-service/src/handlers_peer_review.rs:187:19
|
187 | let reviews = sqlx::query_as!(
| ___________________^
188 | | PeerReview,
189 | | r#"
190 | | SELECT pr.*
... |
196 | | lesson_id
197 | | )
| |_____^
|
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0412]: cannot find type `AnalyticsFilter` in module `common::models`
--> services/lms-service/src/handlers.rs:1736:42
|
1736 | Query(filter): Query<common::models::AnalyticsFilter>,
| ^^^^^^^^^^^^^^^ not found in `common::models`
error[E0412]: cannot find type `RecommendationResponse` in this scope
--> services/lms-service/src/handlers.rs:1802:18
|
1802 | ) -> Result<Json<RecommendationResponse>, (StatusCode, String)> {
| ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
help: consider importing this struct
|
1 + use common::models::RecommendationResponse;
|
error[E0412]: cannot find type `RecommendationResponse` in this scope
--> services/lms-service/src/handlers.rs:1945:22
|
1945 | let ai_response: RecommendationResponse = response
| ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
help: consider importing this struct
|
1 + use common::models::RecommendationResponse;
|
error[E0425]: cannot find function `dangerous_insecure_decode` in crate `jsonwebtoken`
--> services/lms-service/src/lti.rs:107:51
|
107 | let claims: serde_json::Value = jsonwebtoken::dangerous_insecure_decode(&payload.id_token)
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in `jsonwebtoken`
warning: unused imports: `SubmitAssignmentPayload` and `SubmitPeerReviewPayload`
--> services/lms-service/src/handlers.rs:12:44
|
12 | Module, Notification, Organization, SubmitAssignmentPayload, SubmitPeerReviewPayload, User, UserResponse,
| ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
warning: unused import: `crate::lti`
--> services/lms-service/src/handlers.rs:14:5
|
14 | use crate::lti;
| ^^^^^^^^^^
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:154:22
|
154 | let categories = sqlx::query!(
| ______________________^
155 | | "SELECT id, name FROM grading_categories WHERE course_id = $1 ORDER BY name",
156 | | course_id
... |
159 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:160:15
|
160 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
160 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:163:20
|
163 | let students = sqlx::query!(
| ____________________^
164 | | r#"
165 | | SELECT
166 | | u.id,
... |
182 | | .fetch_all(&pool)
183 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:184:15
|
184 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
184 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:193:27
|
193 | let detailed_grades = sqlx::query_as!(
| ___________________________^
194 | | UserCategoryGrade,
195 | | r#"
196 | | SELECT
... |
207 | | .fetch_all(&pool)
208 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:209:15
|
209 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
209 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:896:24
|
896 | let dependencies = sqlx::query_as!(
| ________________________^
897 | | LessonDependency,
898 | | r#"
899 | | SELECT ld.*
... |
907 | | .fetch_all(&pool)
908 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:1004:30
|
1004 | let unmet_dependencies = sqlx::query!(
| ______________________________^
1005 | | r#"
1006 | | SELECT ld.prerequisite_lesson_id, p.title as prereq_title, ld.min_score_percentage
1007 | | FROM lesson_dependencies ld
... |
1022 | | .fetch_all(&pool)
1023 | | .await
| |__________^ cannot infer type
error[E0277]: the trait bound `for<'r> DailyProgress: FromRow<'r, _>` is not satisfied
--> services/lms-service/src/handlers.rs:1461:49
|
1461 | let daily_completions = sqlx::query_as::<_, common::models::DailyProgress>(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> FromRow<'r, _>` is not implemented for `DailyProgress`
|
= help: the following other types implement trait `FromRow<'r, R>`:
`()` implements `FromRow<'r, R>`
`(T1, T2)` implements `FromRow<'r, R>`
`(T1, T2, T3)` implements `FromRow<'r, R>`
`(T1, T2, T3, T4)` implements `FromRow<'r, R>`
`(T1, T2, T3, T4, T5)` implements `FromRow<'r, R>`
`(T1, T2, T3, T4, T5, T6)` implements `FromRow<'r, R>`
`(T1, T2, T3, T4, T5, T6, T7)` implements `FromRow<'r, R>`
`(T1, T2, T3, T4, T5, T6, T7, T8)` implements `FromRow<'r, R>`
and 58 others
note: required by a bound in `sqlx::query_as`
--> /home/juan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sqlx-core-0.8.6/src/query_as.rs:345:8
|
342 | pub fn query_as<'q, DB, O>(sql: &'q str) -> QueryAs<'q, DB, O, <DB as Database>::Arguments<'q>>
| -------- required by a bound in this function
...
345 | O: for<'r> FromRow<'r, DB::Row>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `query_as`
error[E0599]: the method `fetch_all` exists for struct `QueryAs<'_, Postgres, DailyProgress, PgArguments>`, but its trait bounds were not satisfied
--> services/lms-service/src/handlers.rs:1476:6
|
1461 | let daily_completions = sqlx::query_as::<_, common::models::DailyProgress>(
| _____________________________-
1462 | | r#"
1463 | | SELECT
1464 | | TO_CHAR(created_at, 'YYYY-MM-DD') as date,
... |
1475 | | .bind(org_ctx.id)
1476 | | .fetch_all(&pool)
| | -^^^^^^^^^ method cannot be called on `QueryAs<'_, Postgres, DailyProgress, PgArguments>` due to unsatisfied trait bounds
| |_____|
|
|
::: /home/juan/dev/openccb/shared/common/src/models.rs:349:1
|
349 | pub struct DailyProgress {
| ------------------------ doesn't satisfy `DailyProgress: FromRow<'r, PgRow>`
|
= note: the following trait bounds were not satisfied:
`DailyProgress: FromRow<'r, PgRow>`
error[E0282]: type annotations needed
--> services/lms-service/src/handlers.rs:1461:29
|
1461 | let daily_completions = sqlx::query_as::<_, common::models::DailyProgress>(
| _____________________________^
1462 | | r#"
1463 | | SELECT
1464 | | TO_CHAR(created_at, 'YYYY-MM-DD') as date,
... |
1476 | | .fetch_all(&pool)
1477 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_announcements.rs:55:23
|
55 | let cohorts = sqlx::query!(
| _______________________^
56 | | "SELECT cohort_id FROM announcement_cohorts WHERE announcement_id = $1",
57 | | a.id
... |
60 | | .await
| |______________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_announcements.rs:61:19
|
61 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
61 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:21:46
|
21 | let existing: Option<CourseSubmission> = sqlx::query_as!(
| ______________________________________________^
22 | | CourseSubmission,
23 | | "SELECT * FROM course_submissions WHERE user_id = $1 AND lesson_id = $2",
24 | | claims.sub,
... |
27 | | .fetch_optional(&pool)
28 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:29:15
|
29 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
29 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:33:23
|
33 | let updated = sqlx::query_as!(
| _______________________^
34 | | CourseSubmission,
35 | | r#"
36 | | UPDATE course_submissions
... |
45 | | .fetch_one(&pool)
46 | | .await
| |______________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:47:19
|
47 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
47 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:53:22
|
53 | let submission = sqlx::query_as!(
| ______________________^
54 | | CourseSubmission,
55 | | r#"
56 | | INSERT INTO course_submissions (user_id, course_id, lesson_id, organization_id, content)
... |
66 | | .fetch_one(&pool)
67 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:68:15
|
68 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
68 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:83:22
|
83 | let submission = sqlx::query_as!(
| ______________________^
84 | | CourseSubmission,
85 | | r#"
86 | | SELECT s.*
... |
107 | | .fetch_optional(&pool)
108 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:109:15
|
109 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
109 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:122:22
|
122 | let submission = sqlx::query!(
| ______________________^
123 | | "SELECT user_id FROM course_submissions WHERE id = $1",
124 | | payload.submission_id
... |
127 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:128:15
|
128 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
128 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:143:20
|
143 | let existing = sqlx::query!(
| ____________________^
144 | | "SELECT id FROM peer_reviews WHERE submission_id = $1 AND reviewer_id = $2",
145 | | payload.submission_id,
146 | | claims.sub
147 | | )
148 | | .fetch_optional(&pool)
149 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:150:15
|
150 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
150 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:160:18
|
160 | let review = sqlx::query_as!(
| __________________^
161 | | PeerReview,
162 | | r#"
163 | | INSERT INTO peer_reviews (submission_id, reviewer_id, score, feedback, organization_id)
... |
173 | | .fetch_one(&pool)
174 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:175:15
|
175 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
175 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:187:19
|
187 | let reviews = sqlx::query_as!(
| ___________________^
188 | | PeerReview,
189 | | r#"
190 | | SELECT pr.*
... |
198 | | .fetch_all(&pool)
199 | | .await
| |__________^ cannot infer type
error[E0282]: type annotations needed
--> services/lms-service/src/handlers_peer_review.rs:200:15
|
200 | .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
200 | .map_err(|e: /* Type */| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
| ++++++++++++
Some errors have detailed explanations: E0277, E0282, E0412, E0425, E0599.
For more information about an error, try `rustc --explain E0277`.
warning: `lms-service` (bin "lms-service") generated 2 warnings
error: could not compile `lms-service` (bin "lms-service") due to 47 previous errors; 2 warnings emitted
-65
View File
@@ -1,65 +0,0 @@
#!/bin/bash
# 1. Verificar Login de Juan
echo "Probando Login para juan.allende@gmail.com..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"juan.allende@gmail.com","password":"password123"}')
if [ "$HTTP_CODE" -eq 200 ]; then
echo "ÉXITO: El login funcionó para juan.allende@gmail.com con password123"
else
echo "FALLO: El login falló con estado $HTTP_CODE"
# Imprimir cuerpo para depuración
curl -s -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"juan.allende@gmail.com","password":"password123"}'
echo ""
fi
# 3. Verificar Contexto de Organización (Scoping de Cursos)
echo "Probando Scoping de Cursos por Organización..."
# Login para obtener token
USER_DATA=$(curl -s -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"juan.allende@gmail.com","password":"password123"}')
TOKEN=$(echo "$USER_DATA" | jq -r '.token')
ORG_ID=$(echo "$USER_DATA" | jq -r '.user.organization_id')
if [ "$TOKEN" != "null" ]; then
echo "ÉXITO: Se obtuvo el token para juan.allende@gmail.com"
# Intentar listar cursos
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X GET http://localhost:3001/courses \
-H "Authorization: Bearer $TOKEN")
if [ "$HTTP_CODE" -eq 200 ]; then
echo "ÉXITO: Cursos recuperados correctamente con scope de organización"
else
echo "FALLO: Error al recuperar cursos (Estado: $HTTP_CODE)"
fi
# 4. Verificar Cambio de Contexto de Admin (X-Organization-Id)
# Crear una organización ficticia para probar el cambio
echo "Probando Cambio de Contexto de Admin (X-Organization-Id)..."
NEW_ORG_ID=$(curl -s -X POST http://localhost:3001/organizations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Prueba de Cambio de Contexto"}' | jq -r '.id')
if [ "$NEW_ORG_ID" != "null" ]; then
echo "ÉXITO: Nueva organización creada ($NEW_ORG_ID)"
# Intentar listar cursos usando el nuevo contexto de org
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X GET http://localhost:3001/courses \
-H "Authorization: Bearer $TOKEN" \
-H "X-Organization-Id: $NEW_ORG_ID")
if [ "$HTTP_CODE" -eq 200 ]; then
echo "ÉXITO: El cambio de contexto funcionó vía X-Organization-Id"
else
echo "FALLO: El cambio de contexto falló (Estado: $HTTP_CODE)"
fi
else
echo "FALLO: No se pudo crear la organización de prueba"
fi
else
echo "FALLO: No se pudo obtener el token para probar el contexto de organización"
fi