feat(phase5): integracion auth hibrida, email dinamico y moodle 4.1 backend con tolerancia a fallos

This commit is contained in:
2026-09-23 13:34:59 -03:00
parent 7ad4e3f099
commit 1aae432bba
22 changed files with 2993 additions and 49 deletions
+27
View File
@@ -1233,4 +1233,31 @@ const handleAuditLogs = async (req, res) => {
router.get(['/audit_logs', '/audit-logs', '/audit'], handleAuditLogs);
// ─── 11. CONFIGURACIÓN GLOBAL & MOODLE SYNC ────────────────────────────────────
const handleGlobalSettings = async (req, res) => {
let settings = {
smtp: { host: 'smtp.gmail.com', port: 587, security: 'tls' },
auth_providers: { local: true, google: false, moodle: false },
google_oauth: { allowed_domains: 'unicaba.edu.ar', callback_url: '/auth/google/callback' },
moodle: { server_url: 'http://10.0.0.207/moodle', auto_sync_enabled: true, sync_interval_minutes: 15 }
};
try {
const resp = await req.apiClient.get('/admin/settings/all');
if (resp.data && resp.data.data) {
settings = resp.data.data;
}
} catch (e) {
console.warn('Global settings fetch notice:', e.message);
}
res.render('admin/settings/global_config', {
title: 'Configuración Global del Sistema - Admin Edu-Space',
settings
});
};
router.get(['/settings', '/global-config', '/config'], handleGlobalSettings);
module.exports = router;
+71 -4
View File
@@ -2,8 +2,24 @@ const express = require('express');
const router = express.Router();
const apiClient = require('../services/apiClient');
router.get('/login', (req, res) => {
res.render('auth/login', { error: null });
router.get('/login', async (req, res) => {
let providers = { local: true, google: false, moodle: false };
let google_client_id = '';
try {
const resp = await apiClient.get('/auth/providers');
if (resp.data && resp.data.providers) {
providers = resp.data.providers;
google_client_id = resp.data.google_client_id || '';
}
} catch (e) {
// Fallback default
}
res.render('auth/login', {
error: req.query.error || null,
providers,
google_client_id
});
});
router.post('/login', async (req, res) => {
@@ -20,7 +36,6 @@ router.post('/login', async (req, res) => {
const token = response.data.access_token;
if (token) {
// Guardamos el JWT en una cookie httpOnly
res.cookie('auth_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
@@ -34,7 +49,59 @@ router.post('/login', async (req, res) => {
} catch (error) {
console.error('Login error:', error.response?.data || error.message);
const errorMsg = error.response?.data?.message || 'Error en el servidor de autenticación';
res.render('auth/login', { error: errorMsg });
res.render('auth/login', {
error: errorMsg,
providers: { local: true, google: false, moodle: false }
});
}
});
// Proxy para Login Delegado Moodle
router.post('/moodle', async (req, res) => {
try {
const { username, password } = req.body;
const response = await apiClient.post('/auth/moodle', { username, password });
const token = response.data.access_token;
if (token) {
res.cookie('auth_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 24 * 60 * 60 * 1000
});
return res.redirect('/dashboard');
}
res.redirect('/auth/login?error=moodle_auth_failed');
} catch (error) {
console.error('Moodle auth error:', error.response?.data || error.message);
const errorMsg = encodeURIComponent(error.response?.data?.message || 'Error de autenticación en Moodle.');
res.redirect(`/auth/login?error=${errorMsg}`);
}
});
// Proxy para Google OAuth
router.post('/google', async (req, res) => {
try {
const response = await apiClient.post('/auth/google', req.body);
const token = response.data.access_token;
if (token) {
res.cookie('auth_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 24 * 60 * 60 * 1000
});
return res.json({ success: true, redirect: '/dashboard' });
}
return res.status(401).json({ success: false, message: 'Fallo al autenticar con Google.' });
} catch (error) {
console.error('Google auth error:', error.response?.data || error.message);
return res.status(error.response?.status || 500).json({
success: false,
message: error.response?.data?.message || 'Error en autenticación Google Workspace.'
});
}
});