Initial commit
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from classquiz.config import redis
|
||||
import pydantic
|
||||
|
||||
from classquiz.auth import get_current_user, get_current_user_optional
|
||||
from classquiz.db.models import Quiz, QuizInput, User, PlayGame
|
||||
from random import randint
|
||||
import uuid
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/create")
|
||||
async def create_quiz_lol(quiz_input: QuizInput, user: User = Depends(get_current_user)):
|
||||
quiz = Quiz(**quiz_input.dict(), user_id=user.id)
|
||||
return await quiz.save()
|
||||
|
||||
|
||||
@router.get("/get/{quiz_id}")
|
||||
async def get_quiz_from_id(quiz_id: str, user: User | None = Depends(get_current_user_optional)):
|
||||
try:
|
||||
quiz_id = uuid.UUID(quiz_id)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="badly formed quiz id")
|
||||
if user is None:
|
||||
quiz = await Quiz.objects.get_or_none(id=quiz_id, public=True)
|
||||
else:
|
||||
quiz = await Quiz.objects.get_or_none(id=quiz_id, public=False, user_id=user.id)
|
||||
if quiz is None:
|
||||
return JSONResponse(status_code=404, content={"detail": "quiz not found"})
|
||||
else:
|
||||
return quiz
|
||||
|
||||
|
||||
@router.post("/start/{quiz_id}")
|
||||
async def start_quiz(quiz_id: str, user: User = Depends(get_current_user)):
|
||||
try:
|
||||
quiz_id = uuid.UUID(quiz_id)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="badly formed quiz id")
|
||||
quiz = await Quiz.objects.get_or_none(id=quiz_id, public=False, user_id=user.id)
|
||||
if quiz is None:
|
||||
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)
|
||||
await redis.set(f"game:{str(game.game_pin)}", (game.json()))
|
||||
return {**quiz.dict(exclude={"id"}), **game.dict(exclude={"questions"})}
|
||||
|
||||
|
||||
@router.get("/join/{game_pin}")
|
||||
async def get_game_id(game_pin: str):
|
||||
redis_res = (await redis.get(f"game:{game_pin}")).decode()
|
||||
if redis_res is None:
|
||||
raise HTTPException(status_code=404, detail="game not found")
|
||||
else:
|
||||
return json.loads(redis_res)["game_id"]
|
||||
|
||||
|
||||
@router.get("/list")
|
||||
async def get_quiz_list(user: User = Depends(get_current_user)):
|
||||
return await Quiz.objects.filter(user_id=user.id).all()
|
||||
@@ -0,0 +1,90 @@
|
||||
import os
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Response
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
from classquiz.auth import *
|
||||
from fastapi.background import BackgroundTasks
|
||||
from classquiz.emails import send_mail
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from classquiz.db.models import *
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
route_user = User.get_pydantic(
|
||||
exclude={"id": ..., "verified": ..., "verify_key": ..., "created_at": ..., "usersessions": ...})
|
||||
|
||||
|
||||
@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())
|
||||
try:
|
||||
validate_email(user.email)
|
||||
except EmailNotValidError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
user.verify_key = str(os.urandom(16).hex())
|
||||
res = await User.objects.filter((User.email == user.email) | (User.username == user.username)).all()
|
||||
|
||||
if len(res) != 0:
|
||||
raise HTTPException(status_code=400, detail="User already exists")
|
||||
|
||||
user.password = get_password_hash(user.password)
|
||||
if len(user.username) == 32:
|
||||
return JSONResponse({"details": "Username mustn't be 32 characters long"}, 400)
|
||||
res = await user.save()
|
||||
background_task.add_task(send_mail, email=user.email)
|
||||
return user
|
||||
|
||||
|
||||
@router.post("/token/cookie", response_model=Token)
|
||||
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(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect username or password",
|
||||
)
|
||||
session_key = os.urandom(32).hex()
|
||||
# user_session = UserSession(user=user, session_key=session_key)
|
||||
# print(user_session, "HALLO!!!!")
|
||||
# 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
|
||||
)
|
||||
rememberme_token = create_access_token(
|
||||
data={"sub": user.email}, expires_delta=timedelta(days=360))
|
||||
response.set_cookie(key="access_token", value=f"Bearer {access_token}",
|
||||
httponly=True, samesite='strict')
|
||||
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=rememberme_token, httponly=True, samesite='strict')
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
|
||||
|
||||
@router.get("/token/rememberme")
|
||||
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")
|
||||
payload = jwt.decode(rememberme_cookie, settings.secret_key, algorithms=[ALGORITHM])
|
||||
access_token_expires = timedelta(minutes=settings.access_token_expire_minutes)
|
||||
access_token = create_access_token(
|
||||
data={"sub": payload}, expires_delta=access_token_expires
|
||||
)
|
||||
response.set_cookie(key="access_token", value=f"Bearer {access_token}",
|
||||
httponly=True, samesite='strict')
|
||||
response.set_cookie(key="expiry", value="", max_age=settings.access_token_expire_minutes * 60)
|
||||
|
||||
|
||||
@router.get("/logout")
|
||||
async def logout(request: Request, response: Response):
|
||||
remember_token = request.cookies.get("rememberme_token")
|
||||
if remember_token is not None:
|
||||
UserSession.objects.filter(session_key=remember_token).delete()
|
||||
response.delete_cookie("access_token")
|
||||
response.delete_cookie("expiry")
|
||||
response.delete_cookie("rememberme")
|
||||
response.delete_cookie("rememberme_token")
|
||||
Reference in New Issue
Block a user