110 lines
3.1 KiB
Python
110 lines
3.1 KiB
Python
from datetime import timedelta
|
|
|
|
from fastapi import (
|
|
APIRouter,
|
|
Cookie,
|
|
Depends,
|
|
Form,
|
|
HTTPException,
|
|
Response,
|
|
Security,
|
|
status,
|
|
)
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
|
from sqlalchemy.orm import Session
|
|
|
|
from .. import __version__
|
|
from ..core.config import settings
|
|
from ..core.security import (
|
|
Token,
|
|
authenticate_user,
|
|
client_allowed,
|
|
create_access_token,
|
|
get_current_active_user,
|
|
)
|
|
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,
|
|
"ver": __version__.__version__,
|
|
},
|
|
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,
|
|
"ver": __version__.__version__,
|
|
},
|
|
expires_delta=access_token_expires,
|
|
)
|
|
return {"access_token": access_token, "token_type": "bearer"}
|