Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions webapi/api/endpoints/v1/auths.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Optional
from passlib.hash import sha256_crypt
from db.db_connection import get_session
from auth.auth_service import authenticate_user, crear_jwt, validar_jwt
from auth.auth_service import authenticate_user, crear_jwt, validar_jwt, get_current_user
from infrastructure.email.smtp_service import send_email
import secrets
import base64
Expand Down Expand Up @@ -43,11 +43,8 @@ def login(request: LoginRequest, session: Session = Depends(get_session)):


@router.get("/profile")
def profile(authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
return {"profile darta": data}
def profile(current_user: dict = Depends(get_current_user)):
return {"profile data": current_user}

@router.post("/generate")
async def generate_password(
Expand Down
27 changes: 6 additions & 21 deletions webapi/api/endpoints/v1/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from models.user import User
from models.prompts import Prompts
from db.db_connection import get_session
from auth.auth_service import validar_jwt
from auth.auth_service import get_current_user
from infrastructure.email.smtp_service import send_email

router = APIRouter()
Expand All @@ -13,12 +13,9 @@
async def create_prompt(
prompt: Prompts,
session: Session = Depends(get_session),
authorization: Optional[str] = Header(None),
current_user: dict = Depends(get_current_user),
send_email_header: Optional[str] = Header("false", alias="send_email")
):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
# Ensure the user exists before creating a prompt
user = session.get(User, prompt.user_id)
if not user:
Expand All @@ -40,10 +37,7 @@ async def create_prompt(
@router.get("", response_model=list[Prompts])
def read_prompts(skip: int = 0, limit: int = 10,
session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
statement = select(Prompts).offset(skip).limit(limit)
prompts = session.exec(statement).all()
if not prompts:
Expand All @@ -53,10 +47,7 @@ def read_prompts(skip: int = 0, limit: int = 10,

@router.get("/{prompt_id}", response_model=Prompts)
def get_prompt(prompt_id: int, session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
prompt = session.get(Prompts, prompt_id)
if not prompt:
raise HTTPException(status_code=404, detail="Prompt not found")
Expand All @@ -65,10 +56,7 @@ def get_prompt(prompt_id: int, session: Session = Depends(get_session),
@router.put("/{prompt_id}", response_model=Prompts)
def update_prompt(prompt_id: int, prompt: Prompts,
session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
existing_prompt = session.get(Prompts, prompt_id)
if not existing_prompt:
raise HTTPException(status_code=404, detail="Prompt not found")
Expand All @@ -88,10 +76,7 @@ def update_prompt(prompt_id: int, prompt: Prompts,

@router.delete("/{prompt_id}")
def delete_prompt(prompt_id: int, session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
prompt = session.get(Prompts, prompt_id)
if not prompt:
raise HTTPException(status_code=404, detail="Prompt not found to delete")
Expand Down
29 changes: 7 additions & 22 deletions webapi/api/endpoints/v1/users.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from fastapi import APIRouter, HTTPException, Depends, Header
from fastapi import APIRouter, HTTPException, Depends
from sqlmodel import Session, select
from models.user import User
from typing import Optional
from schemas.user_schema import UserReadWithPrompts
from db.db_connection import get_session
from auth.auth_service import validar_jwt
from auth.auth_service import get_current_user
from passlib.hash import sha256_crypt


Expand All @@ -15,10 +15,7 @@
@router.get("", response_model=list[User])
def read_users(phone: Optional[int] = None, skip: int = 0, limit: int = 10,
session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
statement = select(User).offset(skip).limit(limit)
# If phone is provided, filter by phone number
if phone:
Expand All @@ -31,10 +28,7 @@ def read_users(phone: Optional[int] = None, skip: int = 0, limit: int = 10,

@router.get("/{user_id}", response_model=User)
def get_user(user_id: int, session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
Expand All @@ -43,10 +37,7 @@ def get_user(user_id: int, session: Session = Depends(get_session),

@router.get("/prompts/{user_id}", response_model=UserReadWithPrompts)
def get_user_with_prompts(user_id: int, session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
statement = select(User).where(User.id == user_id)
result = session.exec(statement)
user = result.one_or_none()
Expand All @@ -59,10 +50,7 @@ def get_user_with_prompts(user_id: int, session: Session = Depends(get_session),
@router.put("/{user_id}", response_model=User)
def update_user(user_id: int, user: User,
session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
user.name = user.name.lower()
user.last_name = user.last_name.lower()
existing_user = session.get(User, user_id)
Expand All @@ -85,10 +73,7 @@ def update_user(user_id: int, user: User,

@router.delete("/{user_id}")
def delete_user(user_id: int, session: Session = Depends(get_session),
authorization: Optional[str] = Header(None)):
data = validar_jwt(authorization)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
current_user: dict = Depends(get_current_user)):
try:
user = session.get(User, user_id)
if not user:
Expand Down
32 changes: 31 additions & 1 deletion webapi/auth/auth_service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from typing import Optional
from sqlmodel import Session, select
from models.user import User
Expand Down Expand Up @@ -42,7 +43,7 @@ def crear_jwt(data: dict):
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
return token

# Validar un token
# Validar un token con prefijo "Bearer" (compatibilidad legado)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably I'd remove traces of english translations.. legacy comes from "old fashion way of doing stuff" not literaly "legado" lol
for the rest LGTM!

def validar_jwt(token: str):
try:
if not token:
Expand All @@ -61,4 +62,33 @@ def validar_jwt(token: str):
return None
except Exception:
return None


# Validar token puro (sin prefijo "Bearer")
def validar_jwt_raw(token: str):
try:
if not token:
return None
decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return decoded["data"]
except jwt.ExpiredSignatureError:
return None
except jwt.InvalidTokenError:
return None
except Exception:
return None


# Esquema HTTPBearer — registra el Security Scheme en OpenAPI (/docs)
bearer_scheme = HTTPBearer()


def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(bearer_scheme),
):
"""Dependencia reutilizable para endpoints protegidos con Bearer token."""
data = validar_jwt_raw(credentials.credentials)
if not data:
raise HTTPException(status_code=401, detail="Unauthorized token")
return data