80 lines
3.1 KiB
Python
80 lines
3.1 KiB
Python
from fastapi import APIRouter, Cookie, Depends, HTTPException, Request, Response
|
|
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
|
|
|
from src.cache.rate_limit import rate_limiter
|
|
from src.models.configs_read.env import env_settings
|
|
from src.models.pydantic_models.model import UserOut
|
|
from src.service.auth.auth import CurrentUserService, auth_service
|
|
|
|
router=APIRouter(prefix="/protected")
|
|
oauth2_schema=OAuth2PasswordBearer(tokenUrl="/protected/token", refreshUrl="/protected/refresh")
|
|
|
|
|
|
def require_permissions(*permissions: str): #permissions check dependency
|
|
async def checker(
|
|
token: str = Depends(oauth2_schema),
|
|
auth: CurrentUserService = Depends(auth_service),
|
|
) -> UserOut:
|
|
return UserOut.model_validate(await auth.get_current_user(token, *permissions))
|
|
return checker
|
|
|
|
|
|
@router.post("/token")
|
|
async def get_access_token(request: Request,
|
|
response:Response,
|
|
auth:CurrentUserService=Depends(auth_service),
|
|
form_data:OAuth2PasswordRequestForm=Depends(),
|
|
)->dict:
|
|
|
|
client_ip = request.headers.get('x-forwarded-for', '').split(',')[0].strip() or (request.client.host if request.client else 'unknown')
|
|
|
|
try:
|
|
access_token, refresh_token=await auth.login(form_data_email=form_data.username, form_data_password=form_data.password, request=request)
|
|
except HTTPException:
|
|
await rate_limiter.rate_limit(client_ip)
|
|
raise
|
|
|
|
response.set_cookie(
|
|
key="refresh_token",
|
|
value=refresh_token,
|
|
httponly=True,
|
|
secure=env_settings.PROD_MODE,
|
|
samesite="strict",
|
|
max_age=env_settings.REFRESH_TOKEN_EXPIRE_DAYS * 24 * 60 * 60
|
|
)
|
|
return {"access_token": access_token, "token_type": "bearer"}
|
|
|
|
|
|
@router.post("/refresh")
|
|
async def get_refresh_token(request:Request,
|
|
response:Response,
|
|
refresh_token: str = Cookie(),
|
|
auth:CurrentUserService=Depends(auth_service))->dict:
|
|
|
|
access_token, refresh_token= await auth.refresh_token(refresh_token=refresh_token,request=request)
|
|
|
|
response.set_cookie(
|
|
key="refresh_token",
|
|
value=refresh_token,
|
|
httponly=True,
|
|
secure=env_settings.PROD_MODE,
|
|
samesite="strict",
|
|
max_age=env_settings.REFRESH_TOKEN_EXPIRE_DAYS * 24 * 60 * 60
|
|
)
|
|
|
|
return {"access_token":access_token, "token_type": "bearer"}
|
|
|
|
@router.get("/logout")
|
|
async def logout(response:Response,
|
|
refresh_token: str = Cookie(),
|
|
access_token: str = Depends(oauth2_schema),
|
|
auth:CurrentUserService=Depends(auth_service),
|
|
current_user:UserOut=Depends(require_permissions()))->bool:
|
|
|
|
response.delete_cookie("refresh_token")
|
|
return await auth.logout(refresh_token, access_token)
|
|
|
|
@router.get("")
|
|
async def protected(current_user:UserOut=Depends(require_permissions()))->dict:
|
|
return {"protected router": "Hello, this is a protected router"}
|