🎨 black
This commit is contained in:
@@ -62,8 +62,14 @@ async def start_quiz(quiz_id: str, user: User = Depends(get_current_user)):
|
||||
return JSONResponse(status_code=404, content={"detail": "quiz not found"})
|
||||
else:
|
||||
game_pin = randint(10000000, 99999999)
|
||||
game = PlayGame(quiz_id=quiz_id, game_pin=str(game_pin), questions=quiz.questions, game_id=uuid.uuid4(),
|
||||
title=quiz.title, description=quiz.description)
|
||||
game = PlayGame(
|
||||
quiz_id=quiz_id,
|
||||
game_pin=str(game_pin),
|
||||
questions=quiz.questions,
|
||||
game_id=uuid.uuid4(),
|
||||
title=quiz.title,
|
||||
description=quiz.description,
|
||||
)
|
||||
await redis.set(f"game:{str(game.game_pin)}", (game.json()), ex=18000)
|
||||
return {**quiz.dict(exclude={"id"}), **game.dict(exclude={"questions"})}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ router = APIRouter()
|
||||
file_regex = r"^[a-z0-9]{8}-[a-z0-9-]{27}--[a-z0-9-]{36}$"
|
||||
|
||||
|
||||
@router.get('/download/{file_name}')
|
||||
@router.get("/download/{file_name}")
|
||||
async def download_file(file_name: str):
|
||||
if not re.match(file_regex, file_name):
|
||||
raise HTTPException(status_code=400, detail="Invalid file name")
|
||||
@@ -24,5 +24,8 @@ async def download_file(file_name: str):
|
||||
def iter_file():
|
||||
yield from download
|
||||
|
||||
return StreamingResponse(iter_file(), media_type='image/*',
|
||||
headers={"Cache-Control": "public, immutable, max-age=31536000"})
|
||||
return StreamingResponse(
|
||||
iter_file(),
|
||||
media_type="image/*",
|
||||
headers={"Cache-Control": "public, immutable, max-age=31536000"},
|
||||
)
|
||||
|
||||
+57
-21
@@ -7,18 +7,32 @@ from fastapi.background import BackgroundTasks
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
from classquiz.auth import get_password_hash, verify_password, authenticate_user, create_access_token, get_current_user
|
||||
from classquiz.auth import (
|
||||
get_password_hash,
|
||||
verify_password,
|
||||
authenticate_user,
|
||||
create_access_token,
|
||||
get_current_user,
|
||||
)
|
||||
from classquiz.cache import clear_cache_for_account
|
||||
from classquiz.config import redis, settings
|
||||
import uuid
|
||||
from pydantic import BaseModel
|
||||
from classquiz.db.models import User, UserSession, UpdatePassword, Token
|
||||
from classquiz.emails import send_register_email, send_forgotten_password_email
|
||||
|
||||
settings = settings()
|
||||
router = APIRouter()
|
||||
|
||||
route_user = User.get_pydantic(
|
||||
exclude={"id": ..., "verified": ..., "verify_key": ..., "created_at": ..., "usersessions": ...})
|
||||
exclude={
|
||||
"id": ...,
|
||||
"verified": ...,
|
||||
"verify_key": ...,
|
||||
"created_at": ...,
|
||||
"usersessions": ...,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def _sign_out_everywhere(user: User) -> None:
|
||||
@@ -26,8 +40,11 @@ async def _sign_out_everywhere(user: User) -> None:
|
||||
await clear_cache_for_account(user)
|
||||
|
||||
|
||||
@router.post("/create", response_model=User,
|
||||
response_model_include={"id": ..., "verified": ..., "email": ...})
|
||||
@router.post(
|
||||
"/create",
|
||||
response_model=User,
|
||||
response_model_include={"id": ..., "verified": ..., "email": ...},
|
||||
)
|
||||
async def create_user(user: route_user, background_task: BackgroundTasks) -> User | JSONResponse:
|
||||
user = User(**user.dict(), id=uuid.uuid4())
|
||||
try:
|
||||
@@ -50,8 +67,11 @@ async def create_user(user: route_user, background_task: BackgroundTasks) -> Use
|
||||
|
||||
|
||||
@router.post("/token/cookie", response_model=Token)
|
||||
async def login_for_cookie_access_token(request: Request, response: Response,
|
||||
form_data: OAuth2PasswordRequestForm = Depends()):
|
||||
async def login_for_cookie_access_token(
|
||||
request: Request,
|
||||
response: Response,
|
||||
form_data: OAuth2PasswordRequestForm = Depends(),
|
||||
):
|
||||
user = await authenticate_user(form_data.username, form_data.password)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
@@ -59,21 +79,29 @@ async def login_for_cookie_access_token(request: Request, response: Response,
|
||||
detail="Incorrect username or password",
|
||||
)
|
||||
session_key = os.urandom(32).hex()
|
||||
user_session = UserSession(user=user, session_key=session_key, ip_address=request.client.host,
|
||||
user_agent=request.headers.get("User-Agent"), id=uuid.uuid4())
|
||||
user_session = UserSession(
|
||||
user=user,
|
||||
session_key=session_key,
|
||||
ip_address=request.client.host,
|
||||
user_agent=request.headers.get("User-Agent"),
|
||||
id=uuid.uuid4(),
|
||||
)
|
||||
await user_session.save()
|
||||
# await user_session.save()
|
||||
access_token_expires = timedelta(minutes=settings.access_token_expire_minutes)
|
||||
access_token = create_access_token(
|
||||
data={"sub": user.email}, expires_delta=access_token_expires
|
||||
)
|
||||
access_token = create_access_token(data={"sub": user.email}, expires_delta=access_token_expires)
|
||||
await redis.set(access_token, user.email, ex=settings.access_token_expire_minutes * 60)
|
||||
|
||||
response.set_cookie(key="access_token", value=f"Bearer {access_token}",
|
||||
httponly=True, samesite='strict', max_age=settings.access_token_expire_minutes * 60)
|
||||
response.set_cookie(
|
||||
key="access_token",
|
||||
value=f"Bearer {access_token}",
|
||||
httponly=True,
|
||||
samesite="strict",
|
||||
max_age=settings.access_token_expire_minutes * 60,
|
||||
)
|
||||
response.set_cookie(key="expiry", value="", max_age=settings.access_token_expire_minutes * 60)
|
||||
response.set_cookie(key="rememberme", value="")
|
||||
response.set_cookie(key="rememberme_token", value=session_key, httponly=True, samesite='strict')
|
||||
response.set_cookie(key="rememberme_token", value=session_key, httponly=True, samesite="strict")
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
|
||||
|
||||
@@ -82,16 +110,20 @@ async def rememberme_token(request: Request, response: Response):
|
||||
rememberme_cookie = request.cookies.get("rememberme_token")
|
||||
if rememberme_cookie is None:
|
||||
raise HTTPException(status_code=400, detail="No rememberme cookie")
|
||||
user_session: UserSession | None = await UserSession.objects.filter(session_key=rememberme_cookie).select_related(
|
||||
UserSession.user).get_or_none()
|
||||
user_session: UserSession | None = (
|
||||
await UserSession.objects.filter(session_key=rememberme_cookie).select_related(UserSession.user).get_or_none()
|
||||
)
|
||||
if (user_session is None) or (user_session.user is None):
|
||||
raise HTTPException(status_code=401, detail="No user session")
|
||||
access_token_expires = timedelta(minutes=settings.access_token_expire_minutes * 60)
|
||||
access_token = create_access_token(
|
||||
data={"sub": user_session.user.email}, expires_delta=access_token_expires
|
||||
access_token = create_access_token(data={"sub": user_session.user.email}, expires_delta=access_token_expires)
|
||||
response.set_cookie(
|
||||
key="access_token",
|
||||
value=f"Bearer {access_token}",
|
||||
httponly=True,
|
||||
samesite="strict",
|
||||
max_age=settings.access_token_expire_minutes * 60,
|
||||
)
|
||||
response.set_cookie(key="access_token", value=f"Bearer {access_token}",
|
||||
httponly=True, samesite='strict', max_age=settings.access_token_expire_minutes * 60)
|
||||
response.set_cookie(key="expiry", value="", max_age=settings.access_token_expire_minutes * 60)
|
||||
await user_session.update(last_seen=datetime.now())
|
||||
|
||||
@@ -127,7 +159,11 @@ async def verify_user(verify_key: str):
|
||||
|
||||
|
||||
@router.put("/password/update")
|
||||
async def change_password(password_data: UpdatePassword, response: Response, user: User = Depends(get_current_user)):
|
||||
async def change_password(
|
||||
password_data: UpdatePassword,
|
||||
response: Response,
|
||||
user: User = Depends(get_current_user),
|
||||
):
|
||||
if not verify_password(password_data.old_password, user.password):
|
||||
raise HTTPException(status_code=400, detail="Incorrect password")
|
||||
user.password = get_password_hash(password_data.new_password)
|
||||
|
||||
Reference in New Issue
Block a user