68 lines
1.8 KiB
Python
68 lines
1.8 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status, Response
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core import settings
|
|
from app.core.security import (
|
|
verify_password,
|
|
create_access_token,
|
|
set_auth_cookie,
|
|
)
|
|
|
|
from app.db import get_async_db
|
|
from app.db.models import User
|
|
|
|
from app.api.v1.schemas import TokenRequest, TokenResponse
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
# ------------------------
|
|
# Authentication
|
|
# ------------------------
|
|
|
|
@router.post(
|
|
"/login",
|
|
response_model=TokenResponse,
|
|
status_code=status.HTTP_200_OK,
|
|
tags=["Authentication"]
|
|
)
|
|
async def get_token(payload: TokenRequest, response: Response, db: Session = Depends(get_async_db)):
|
|
result = await db.execute(select(User).where(User.username == payload.username))
|
|
user = result.scalar_one_or_none()
|
|
if not user or not verify_password(payload.password, user.hashed_password):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Invalid crendentials",
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
)
|
|
|
|
access_token = create_access_token(
|
|
data = {"sub": str(user.id)}
|
|
)
|
|
|
|
set_auth_cookie(
|
|
response,
|
|
token=access_token,
|
|
max_age=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
|
|
)
|
|
|
|
return {"access_token": access_token}
|
|
|
|
|
|
@router.post(
|
|
"/logout",
|
|
status_code=status.HTTP_200_OK,
|
|
tags=["Authentication"],
|
|
)
|
|
def logout(response: Response) -> dict:
|
|
response.delete_cookie(
|
|
key="access_token",
|
|
path="/", # même chemin que lors du set_cookie
|
|
httponly=True,
|
|
samesite="lax" if settings.ENV == "dev" else "strict",
|
|
secure=settings.USE_SSL, # mettre True en prod sur HTTPS
|
|
)
|
|
return {"detail": "Logged out successfully"} |