Further cleanup
This commit is contained in:
@@ -10,22 +10,18 @@ from datetime import datetime
|
||||
import ormar
|
||||
import pydantic
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
from fastapi import APIRouter, Response, HTTPException, Request, Depends, status
|
||||
from fastapi import APIRouter, Response, HTTPException, Request, Depends
|
||||
from fastapi.background import BackgroundTasks
|
||||
from fastapi.responses import JSONResponse, RedirectResponse, PlainTextResponse
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
from jose import jwt, JWTError
|
||||
|
||||
from classquiz import oauth
|
||||
from classquiz.helpers.avatar import gzipped_user_avatar
|
||||
import base64
|
||||
from classquiz.oauth.authenticate_user import rememberme_check, log_user_in
|
||||
|
||||
from classquiz.auth import (
|
||||
get_password_hash,
|
||||
verify_password,
|
||||
authenticate_user,
|
||||
get_current_user,
|
||||
)
|
||||
from classquiz.cache import clear_cache_for_account
|
||||
@@ -33,7 +29,7 @@ from classquiz.config import redis, settings, meilisearch
|
||||
import uuid
|
||||
import bleach
|
||||
from pydantic import BaseModel
|
||||
from classquiz.db.models import User, UserSession, UpdatePassword, Token, Quiz, ApiKey
|
||||
from classquiz.db.models import User, UserSession, UpdatePassword, Quiz, ApiKey
|
||||
from classquiz.emails import send_register_email, send_forgotten_password_email
|
||||
from classquiz.routers.users import webauthn, twofa
|
||||
|
||||
@@ -66,7 +62,12 @@ router.include_router(oauth.router, tags=["users", "oauth"], prefix="/oauth")
|
||||
async def create_user(user: RouteUser, background_task: BackgroundTasks) -> User | JSONResponse:
|
||||
if settings.registration_disabled:
|
||||
raise HTTPException(status_code=423)
|
||||
user = User(**user.model_dump(), id=uuid.uuid4(), avatar=gzipped_user_avatar(), created_at=datetime.now())
|
||||
user: User = User(
|
||||
**user.model_dump(),
|
||||
id=uuid.uuid4(),
|
||||
avatar=gzipped_user_avatar(),
|
||||
created_at=datetime.now(),
|
||||
)
|
||||
try:
|
||||
validate_email(user.email)
|
||||
except EmailNotValidError as e:
|
||||
@@ -91,31 +92,6 @@ async def create_user(user: RouteUser, background_task: BackgroundTasks) -> User
|
||||
return user
|
||||
|
||||
|
||||
@router.post("/token/cookie", response_model=Token, deprecated=True)
|
||||
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)
|
||||
user = await User.objects.select_related("fidocredentialss").get(id=user.id)
|
||||
if not user or user.totp_secret is not None or user or len(user.fidocredentialss) != 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect username or password",
|
||||
)
|
||||
|
||||
return await log_user_in(response=response, request=request, user=user)
|
||||
|
||||
|
||||
@router.get("/token/rememberme")
|
||||
async def rememberme_token(request: Request, response: Response):
|
||||
rememberme_token_lol = request.cookies.get("rememberme_token")
|
||||
if rememberme_token_lol is None:
|
||||
raise HTTPException(status_code=400, detail="No rememberme cookie")
|
||||
return await rememberme_check(rememberme_token=rememberme_token_lol, response=response)
|
||||
|
||||
|
||||
@router.get("/logout")
|
||||
async def logout(request: Request, response: Response):
|
||||
remember_token = request.cookies.get("rememberme_token")
|
||||
@@ -229,24 +205,26 @@ async def reset_password_with_token(reset_password: ResetPassword, response: Res
|
||||
return {"message": "Password updated successfully"}
|
||||
|
||||
|
||||
@router.get("/sessions/list", response_model=list[UserSession], response_model_exclude={"user", "session_key", "quizs"})
|
||||
@router.get(
|
||||
"/sessions/list",
|
||||
response_model=list[UserSession],
|
||||
response_model_exclude={"user", "session_key", "quizs"},
|
||||
)
|
||||
async def list_sessions(user: User = Depends(get_current_user)):
|
||||
sessions = await UserSession.objects.filter(user=user).all()
|
||||
return [session.model_dump() for session in sessions]
|
||||
|
||||
|
||||
@router.delete("/sessions/{session_id}")
|
||||
async def delete_session(session_id: str, user: User = Depends(get_current_user)):
|
||||
try:
|
||||
session_id = uuid.UUID(session_id)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid session id")
|
||||
async def delete_session(session_id: uuid.UUID, user: User = Depends(get_current_user)):
|
||||
await UserSession.objects.filter(user=user, id=session_id).delete()
|
||||
return {"message": "Session deleted"}
|
||||
|
||||
|
||||
@router.get(
|
||||
"/session", response_model=UserSession, response_model_exclude={"user": ..., "session_key": ..., "quizs": ...}
|
||||
"/session",
|
||||
response_model=UserSession,
|
||||
response_model_exclude={"user": ..., "session_key": ..., "quizs": ...},
|
||||
)
|
||||
async def get_session(request: Request, user: User = Depends(get_current_user)):
|
||||
try:
|
||||
@@ -300,43 +278,10 @@ class InternalAuthData(BaseModel):
|
||||
jwt: str | None = None
|
||||
|
||||
|
||||
@router.post("/auth/internal")
|
||||
async def internal_auth(data: InternalAuthData, resp: Response):
|
||||
try:
|
||||
data.jwt = data.jwt.replace("Bearer ", "")
|
||||
except AttributeError:
|
||||
pass
|
||||
if data.jwt is not None:
|
||||
try:
|
||||
payload = jwt.decode(data.jwt, settings.secret_key, algorithms=["HS256"])
|
||||
email: str = payload.get("sub")
|
||||
if email is None:
|
||||
resp.status_code = 401
|
||||
return resp
|
||||
except JWTError:
|
||||
resp.status_code = 401
|
||||
return resp
|
||||
else:
|
||||
return await rememberme_check(data.rememberme, resp)
|
||||
|
||||
|
||||
class GetEmailFromJWT(BaseModel):
|
||||
jwt: str
|
||||
|
||||
|
||||
@router.post("/auth/internal/email")
|
||||
async def get_email_from_jwt(data: GetEmailFromJWT):
|
||||
try:
|
||||
data.jwt = data.jwt.replace("Bearer ", "")
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
payload = jwt.decode(data.jwt, settings.secret_key, algorithms=["HS256"])
|
||||
return payload.get("sub")
|
||||
except JWTError:
|
||||
raise HTTPException(status_code=401)
|
||||
|
||||
|
||||
@router.post("/api_keys", response_model=ApiKey, response_model_include={"key"})
|
||||
async def generate_api_key(user: User = Depends(get_current_user)):
|
||||
key = ApiKey(key=os.urandom(24).hex(), user=user)
|
||||
@@ -351,7 +296,7 @@ async def list_api_keys(user: User = Depends(get_current_user)):
|
||||
|
||||
|
||||
@router.delete("/api_keys")
|
||||
async def delete_api_key(api_key: str, user: User = Depends(get_current_user)):
|
||||
async def delete_api_key(api_key: str, _: User = Depends(get_current_user)):
|
||||
key = await ApiKey.objects.get_or_none(key=api_key)
|
||||
if key is None:
|
||||
raise HTTPException(status_code=404, detail="Key not found")
|
||||
|
||||
Reference in New Issue
Block a user