From f7bfc4b956ef39c0a9225bf81f563902af7548ad Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 14 Apr 2026 10:29:25 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20arreglar=20conexi=C3=B3n=20con=20google?= =?UTF-8?q?=20auth=20y=20proceso=20de=20arreglar=20conexi=C3=B3n=20entre?= =?UTF-8?q?=20paso2=20y=20paso3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/api/models/docit2mf_models.py | 2 +- backend/api/routers/docit2mf_build.py | 8 ++-- backend/api/routers/google_auth.py | 23 +++++++--- frontend/src/context/AuthProvider.jsx | 30 ++++++++----- frontend/src/pages/Login.jsx | 61 ++++++++++++++++++--------- 5 files changed, 83 insertions(+), 41 deletions(-) diff --git a/backend/api/models/docit2mf_models.py b/backend/api/models/docit2mf_models.py index d8069cb..a9a20d6 100644 --- a/backend/api/models/docit2mf_models.py +++ b/backend/api/models/docit2mf_models.py @@ -35,7 +35,7 @@ class DoCIT2MFRequest(BaseModel): def support_valid(cls, v, info): c, d = v if c >= d: - raise ValueError("El soporte debe cumplir c < d.") + raise ValueError("El soporte debe cumplir c <= d.") core = info.data.get("core") if core: diff --git a/backend/api/routers/docit2mf_build.py b/backend/api/routers/docit2mf_build.py index ba4c06a..f0761aa 100644 --- a/backend/api/routers/docit2mf_build.py +++ b/backend/api/routers/docit2mf_build.py @@ -1,7 +1,7 @@ # api/routers/docit2mf_build.py import logging -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, Request from slowapi import Limiter from slowapi.util import get_remote_address from api.models.docit2mf_models import DoCIT2MFMultiRequest @@ -14,11 +14,11 @@ logger = logging.getLogger(__name__) @router.post("/doc-it2mf/build") @limiter.limit("10/minute") -async def build_doc_it2mf(request: DoCIT2MFMultiRequest): +async def build_doc_it2mf(request: Request, body: DoCIT2MFMultiRequest): results = [] try: - for level in request.levels: + for level in body.levels: results.append(build_it2mf_from_level(level)) except ValueError as e: logger.warning(f"Validation error in doc-it2mf/build: {str(e)}") @@ -27,4 +27,4 @@ async def build_doc_it2mf(request: DoCIT2MFMultiRequest): logger.error(f"Unexpected error in doc-it2mf/build: {str(e)}", exc_info=True) raise HTTPException(status_code=500, detail="Internal server error") - return {"levels": results} + return {"levels": results} \ No newline at end of file diff --git a/backend/api/routers/google_auth.py b/backend/api/routers/google_auth.py index c7e5f77..96734a2 100644 --- a/backend/api/routers/google_auth.py +++ b/backend/api/routers/google_auth.py @@ -1,19 +1,18 @@ -# api/routers/google_auth.py - from fastapi import APIRouter, HTTPException, Request from fastapi.responses import RedirectResponse +from datetime import datetime, timedelta import httpx import os import jwt from api.database.mongodb import users_collection -from api.utils.security import create_access_token router = APIRouter(prefix="/auth/google", tags=["auth"]) GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID") GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET") REDIRECT_URI = os.getenv("GOOGLE_REDIRECT_URI") +SECRET_KEY = os.getenv("SECRET_KEY") # ----------------------------- @@ -90,6 +89,20 @@ async def google_callback(request: Request): else: user_id = user["_id"] - token = create_access_token({"user_id": str(user_id)}) + token = jwt.encode( + { + "sub": str(user_id), + "email": email, + "name": name, + "exp": datetime.utcnow() + timedelta(hours=24) + }, + SECRET_KEY, + algorithm="HS256" + ) - return RedirectResponse(f"http://localhost:5173/login?token={token}") + await users_collection.update_one( + {"_id": user_id}, + {"$set": {"token": token}} + ) + + return RedirectResponse(f"http://localhost:5173/login?token={token}") \ No newline at end of file diff --git a/frontend/src/context/AuthProvider.jsx b/frontend/src/context/AuthProvider.jsx index 5180fb6..4f76f7e 100644 --- a/frontend/src/context/AuthProvider.jsx +++ b/frontend/src/context/AuthProvider.jsx @@ -1,23 +1,33 @@ -import { useState } from 'react'; +import { useState, useCallback } from 'react'; import { AuthContext } from './AuthContext'; export const AuthProvider = ({ children }) => { const [user, setUser] = useState(() => { - const storedUser = localStorage.getItem('user'); - return storedUser ? JSON.parse(storedUser) : null; + try { + const storedUser = localStorage.getItem('user'); + return storedUser ? JSON.parse(storedUser) : null; + } catch { + return null; + } }); - const login = (userData, token) => { - setUser(userData); - localStorage.setItem('user', JSON.stringify(userData)); - localStorage.setItem('token', token); - }; + const login = useCallback((data) => { + const currentUser = data.user || data; + const token = data.access_token || data.token; - const logout = () => { + setUser(currentUser); + localStorage.setItem('user', JSON.stringify(currentUser)); + + if (token) { + localStorage.setItem('token', token); + } + }, []); + + const logout = useCallback(() => { setUser(null); localStorage.removeItem('user'); localStorage.removeItem('token'); - }; + }, []); return ( { @@ -22,23 +24,28 @@ export default function Login() { url.searchParams.delete('token'); window.history.replaceState({}, '', url); - const fetchUserAndLogin = async () => { - try { - localStorage.setItem('token', token); - - const realUserData = await authService.getCurrentUser(); - - login({ user: realUserData, token }); + try { + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); + const jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); + + const decodedToken = JSON.parse(jsonPayload); - navigate('/', { replace: true }); - } catch (err) { - console.error("Error al sincronizar perfil de Google:", err); - setError("Error de sincronización con Google. Inténtalo de nuevo."); - localStorage.removeItem('token'); - } - }; + const googleUser = { + _id: decodedToken.sub || decodedToken.user_id || "google_id", + username: decodedToken.email ? decodedToken.email.split('@')[0] : "Usuario Google", + email: decodedToken.email || "" + }; - fetchUserAndLogin(); + login({ user: googleUser, access_token: token }); + navigate('/', { replace: true }); + + } catch (err) { + console.error("Error al decodificar el token de Google:", err); + setError("Error al procesar el login con Google. El token está corrupto."); + } } }, [searchParams, login, navigate]); @@ -46,8 +53,8 @@ export default function Login() { e.preventDefault(); setError(''); try { - const userData = await authService.login(email, password); - login(userData); + const data = await authService.login(email, password); + login(data); navigate('/'); } catch (err) { setError('Credenciales incorrectas.'); @@ -68,19 +75,31 @@ export default function Login() { {error && ( -
{error}
+
+ {error} +
)}
- setEmail(e.target.value)} className="w-full px-5 py-3 rounded-2xl border border-slate-200 focus:ring-2 focus:ring-blue-500 outline-none transition-all bg-slate-50 focus:bg-white" placeholder="correo@ejemplo.com" /> + setEmail(e.target.value)} + className="w-full px-5 py-3 rounded-2xl border border-slate-200 focus:ring-2 focus:ring-blue-500 outline-none transition-all bg-slate-50 focus:bg-white" + placeholder="correo@ejemplo.com" + />
- setPassword(e.target.value)} className="w-full px-5 py-3 rounded-2xl border border-slate-200 focus:ring-2 focus:ring-blue-500 outline-none transition-all bg-slate-50 focus:bg-white" placeholder="••••••••" /> + setPassword(e.target.value)} + className="w-full px-5 py-3 rounded-2xl border border-slate-200 focus:ring-2 focus:ring-blue-500 outline-none transition-all bg-slate-50 focus:bg-white" + placeholder="••••••••" + />
- +