from fastapi import (APIRouter, Request, status, Depends, Form ) from fastapi.responses import (HTMLResponse, RedirectResponse ) from fastapi.templating import Jinja2Templates from sqlalchemy.orm import Session from ..db.db_connect import get_db from ..models.users import User router = APIRouter() # Get html templates templates = Jinja2Templates(directory="app/frontend/templates") # retrieve the current user session info def _get_session_user(request: Request): return request.session.get("user") # check if the current user is an admin def _is_admin(session_user) -> bool: try: return (session_user.get("role") or "").lower() == "admin" except Exception: return False def _authorize_or_redirect(request: Request, target_user_id: int) -> RedirectResponse | None: # Retrieve current session user info session_user = _get_session_user(request) # if no session redirect to login if not session_user: return RedirectResponse(url="/login", status_code=status.HTTP_303_SEE_OTHER) # if the user is not an admin and trying to access another profile redirect to own profile if session_user.get("id") != target_user_id and not _is_admin(session_user): return RedirectResponse(url=f"/users/{session_user.get('id')}/profile", status_code=status.HTTP_303_SEE_OTHER) return None # Routing to the user profile page @router.get("/users/{user_id}/profile", response_class=HTMLResponse) def profile_page(request: Request, user_id: int, db: Session = Depends(get_db)): # redirection logic application for authorization test redirect = _authorize_or_redirect(request, user_id) if redirect: return redirect # define user variable to query the database for user info user = db.query(User).filter(User.id == user_id).first() # Error handling for non existent users if not user: # return profile not found if user does not exist return templates.TemplateResponse( "account/profile.html", {"request": request, "not_found": True, "active": "profile", "user": _get_session_user(request)}, status_code=status.HTTP_404_NOT_FOUND, ) # passing all validation direct to profile page with user info return templates.TemplateResponse( "account/profile.html", {"request": request, "active": "profile", "user": _get_session_user(request), "profile_user": user}, ) # Updating profile info to the database using post method @router.post("/users/{user_id}/profile", response_class=HTMLResponse) # Defining profile update variables i.e full name and email and db session def profile_update( request: Request, user_id: int, first_name: str = Form(...), surname: str = Form(None), email: str = Form(...), db: Session = Depends(get_db), ): redirect = _authorize_or_redirect(request, user_id) if redirect: return redirect user = db.query(User).filter(User.id == user_id).first() # Error handling for non existent users if not user: return templates.TemplateResponse( "account/profile.html", {"request": request, "not_found": True, "active": "profile", "user": _get_session_user(request)}, status_code=status.HTTP_404_NOT_FOUND, ) first_name = (first_name or "").strip() surname = (surname or "").strip() or None email = (email or "").strip() if not first_name or len(first_name) > 255: return templates.TemplateResponse( "account/profile.html", { "request": request, "active": "profile", "user": _get_session_user(request), "profile_user": user, "error": "Please provide a first name up to 255 characters.", }, status_code=status.HTTP_400_BAD_REQUEST, ) if not email or len(email) > 255: return templates.TemplateResponse( "account/profile.html", { "request": request, "active": "profile", "user": _get_session_user(request), "profile_user": user, "error": "Please provide an email up to 255 characters.", }, status_code=status.HTTP_400_BAD_REQUEST, ) # Update user info in the database user.first_name = first_name user.surname = surname user.email = email db.add(user) db.commit() # update session info when profile is updated try: session_user = request.session.get("user") or {} if session_user.get("id") == user.id: session_user["name"] = (user.full_name or user.email) request.session["user"] = session_user except Exception: pass # reload profile with success message return templates.TemplateResponse( "account/profile.html", { "request": request, "active": "profile", "user": _get_session_user(request), "profile_user": user, "message": "Profile updated.", }, ) # routing to the user settings page(iteration 2) currently a placeholder @router.get("/users/{user_id}/settings", response_class=HTMLResponse) def settings_page(request: Request, user_id: int, db: Session = Depends(get_db)): redirect = _authorize_or_redirect(request, user_id) if redirect: return redirect user = db.query(User).filter(User.id == user_id).first() # Error handling for non existent users if not user: return templates.TemplateResponse( "account/settings.html", {"request": request, "not_found": True, "active": "settings", "user": _get_session_user(request)}, status_code=status.HTTP_404_NOT_FOUND, ) # if validate load settings page for the user return templates.TemplateResponse( "account/settings.html", {"request": request, "active": "settings", "user": _get_session_user(request), "profile_user": user}, )