barker/barker/barker/routers/login.py

88 lines
2.8 KiB
Python

from datetime import timedelta
from fastapi import (
APIRouter,
Depends,
HTTPException,
status,
Security,
Cookie,
Form,
Response,
)
from fastapi.security import OAuth2PasswordRequestForm
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session
from ..core.security import (
Token,
authenticate_user,
create_access_token,
get_current_active_user,
client_allowed,
)
from barker.core.config import settings
from ..db.session import SessionLocal
from ..schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db():
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.post("/token", response_model=Token)
async def login_for_access_token(
response: Response,
form_data: OAuth2PasswordRequestForm = Depends(),
client_id: int = Cookie(None),
otp: int = Form(None),
db: Session = Depends(get_db),
):
user = authenticate_user(form_data.username, form_data.password, client_id, otp, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
allowed, c_id = client_allowed(user, client_id, otp, db)
db.commit()
if c_id and c_id != client_id:
response.set_cookie(key="client_id", value=str(c_id), max_age=10 * 365 * 24 * 60 * 60)
if not allowed:
not_allowed_response = JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED,
headers={"WWW-Authenticate": "Bearer"},
content={"detail": "Client is not registered"},
)
not_allowed_response.set_cookie(key="client_id", value=str(c_id), max_age=10 * 365 * 24 * 60 * 60)
return not_allowed_response
access_token_expires = timedelta(minutes=settings.JWT_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={
"sub": user.name,
"scopes": ["authenticated"]
+ list(set([p.name.replace(" ", "-").lower() for r in user.roles for p in r.permissions])),
"userId": str(user.id),
"lockedOut": user.locked_out,
},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}
@router.post("/refresh", response_model=Token)
async def refresh_token(user: UserToken = Security(get_current_active_user)):
access_token_expires = timedelta(minutes=settings.JWT_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.name, "scopes": user.permissions, "userId": str(user.id_), "lockedOut": user.locked_out,},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}