Added storage_limit for user accounts

This commit is contained in:
Mawoka
2023-05-30 11:14:46 +02:00
parent b64ed05235
commit 44432b20c7
4 changed files with 18 additions and 115 deletions
+1
View File
@@ -50,6 +50,7 @@ class Settings(BaseSettings):
github_client_secret: Optional[str]
custom_openid_provider: CustomOpenIDProvider | None = None
telemetry_enabled: bool = True
free_storage_limit: int = 1074000000
# storage_backend
storage_backend: str | None = "deta"
-19
View File
@@ -65,25 +65,6 @@ async def init_editor(edit: bool, quiz_id: Optional[UUID] = None, user: User = D
return InitEditorResponse(token=edit_id)
class GetPowData(BaseModel):
data: str
@router.get("/pow", response_model=GetPowData)
async def get_pow_data(edit_id: str):
session_data = await redis.get(f"edit_session:{edit_id}")
if session_data is None:
raise HTTPException(status_code=401, detail="Edit ID not found!")
random_str = os.urandom(8).hex()
await redis.set(f"edit_session:{edit_id}:pow", random_str, ex=3800)
return GetPowData(data=random_str)
class UploadImageReturn(BaseModel):
id: str
pow_data: str
@router.post("/finish")
async def finish_edit(edit_id: str, quiz_input: QuizInput):
session_data = await redis.get(f"edit_session:{edit_id}")
+4 -77
View File
@@ -11,17 +11,15 @@ from random import randint
import ormar.exceptions
from classquiz.helpers import get_meili_data, generate_spreadsheet
from classquiz.helpers import generate_spreadsheet
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import ValidationError, BaseModel
import bleach
from classquiz.auth import get_current_user
from classquiz.config import redis, settings, storage, meilisearch
from classquiz.db.models import Quiz, QuizInput, User, PlayGame, GameInLobby, QuizQuestion
from classquiz.db.models import Quiz, User, PlayGame, GameInLobby, QuizQuestion
from classquiz.kahoot_importer.import_quiz import import_quiz
import html
import urllib.parse
settings = settings()
@@ -29,33 +27,6 @@ settings = settings()
router = APIRouter()
@router.post("/create", deprecated=True)
async def create_quiz_lol(quiz_input: QuizInput, user: User = Depends(get_current_user)):
imgur_regex = r"^https://i\.imgur\.com\/.{7}.(jpg|png|gif)$"
server_regex = rf"^{re.escape(settings.root_address)}/api/v1/storage/download/.{36}--.{36}$"
quiz_input.title = html.unescape(bleach.clean(quiz_input.title, tags=[], strip=True))
quiz_input.description = html.unescape(bleach.clean(quiz_input.description, tags=[], strip=True))
for question in quiz_input.questions:
if question.image == "":
question.image = None
if (
question.image is not None
and not re.match(imgur_regex, question.image)
and not re.match(server_regex, question.image)
):
raise HTTPException(status_code=400, detail="image url is not valid")
if quiz_input.cover_image == "":
quiz_input.cover_image = None
if quiz_input.cover_image is not None and not bool(re.match(server_regex, quiz_input.cover_image)):
raise HTTPException(status_code=400, detail="image url is not valid")
quiz = Quiz(**quiz_input.dict(), user_id=user.id, id=uuid.uuid4())
await redis.delete("global_quiz_count")
if quiz_input.public:
meilisearch.index(settings.meilisearch_index).add_documents([await get_meili_data(quiz)])
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)):
try:
@@ -213,54 +184,10 @@ async def get_quiz_list(user: User = Depends(get_current_user), page_size: int |
raise HTTPException(status_code=400, detail="Invalid page(size). page(size) have to be greater than 0.")
@router.put("/update/{quiz_id}", deprecated=True)
async def update_quiz(quiz_id: str, quiz_input: QuizInput, user: User = Depends(get_current_user)):
imgur_regex = r"^https://i\.imgur\.com\/.{7}.(jpg|png|gif)$"
server_regex = rf"^{re.escape(settings.root_address)}/api/v1/storage/download/.{{36}}--.{{36}}$"
for question in quiz_input.questions:
if question.image == "":
question.image = None
if (
question.image is not None
and not bool(re.match(server_regex, question.image))
and not bool(re.match(imgur_regex, question.image))
):
raise HTTPException(status_code=400, detail="image url is not valid")
try:
quiz_id = uuid.UUID(quiz_id)
except ValueError:
raise HTTPException(status_code=400, detail="badly formed quiz id")
# Check Cover-Image
if quiz_input.cover_image == "":
quiz_input.cover_image = None
if quiz_input.cover_image is not None and not bool(re.match(server_regex, quiz_input.cover_image)):
raise HTTPException(status_code=400, detail="image url is not valid")
quiz = await Quiz.objects.get_or_none(id=quiz_id, user_id=user.id)
if quiz is None:
return JSONResponse(status_code=404, content={"detail": "quiz not found"})
else:
quiz_input.description = html.unescape(bleach.clean(quiz_input.description, tags=[], strip=True))
quiz_input.title = html.unescape(bleach.clean(quiz_input.title, tags=[], strip=True))
meilisearch.index(settings.meilisearch_index).update_documents([await get_meili_data(quiz)])
if quiz.public and not quiz_input.public:
meilisearch.index(settings.meilisearch_index).delete_document(str(quiz.id))
if not quiz.public and quiz_input.public:
meilisearch.index(settings.meilisearch_index).add_documents([await get_meili_data(quiz)])
quiz.title = quiz_input.title
quiz.cover_image = quiz_input.cover_image
quiz.public = quiz_input.public
quiz.description = quiz_input.description
quiz.updated_at = datetime.now()
quiz.questions = quiz_input.dict()["questions"]
return await quiz.update()
@router.post("/import/{quiz_id}")
async def import_quiz_route(quiz_id: str, user: User = Depends(get_current_user)):
if user.storage_used > settings.free_storage_limit:
raise HTTPException(status_code=409, detail="Storage limit reached")
try:
return await import_quiz(quiz_id, user)
except ValidationError:
+13 -19
View File
@@ -52,17 +52,11 @@ async def download_file(file_name: str):
@router.post("/")
async def upload_file(file: UploadFile = File(), user: User = Depends(get_current_user)) -> PublicStorageItem:
if user.storage_used > settings.free_storage_limit:
raise HTTPException(status_code=409, detail="Storage limit reached")
file_id = uuid4()
size = 0
# if file.file.name is None:
# size = len(await file.read())
# print("MemorySize", size)
# else:
# f = file.file
# a = file.file.fileno()
# os.path.getsize(file.file.name)
# print("DiskSize", size, "name:", file.file.name, "a:", file.file.tell(), "size")
file_obj = StorageItem(
id=file_id,
uploaded_at=datetime.now(),
@@ -137,16 +131,16 @@ async def list_images(
return return_items
class ReturnStorageUsage(BaseModel):
usage: int
class ReturnGetStorageLimit(BaseModel):
limit: int
limit_reached: bool
used: int
@router.get("/usage")
async def get_storage_usage(user: User = Depends(get_current_user)) -> ReturnStorageUsage:
files: list[StorageItem] = await StorageItem.objects.filter(user=user).filter(deleted_at=None).all()
counted_size = 0
if len(files) == 0:
raise HTTPException(status_code=404, detail="No file found")
for file in files:
counted_size += file.size
return ReturnStorageUsage(usage=counted_size)
@router.get("/limit")
async def get_storage_limit(user: User = Depends(get_current_user)) -> ReturnGetStorageLimit:
user = await User.objects.get_or_none(id=user.id)
if user.storage_used > settings.free_storage_limit:
return ReturnGetStorageLimit(limit=settings.free_storage_limit, limit_reached=True, used=user.storage_used)
else:
return ReturnGetStorageLimit(limit=settings.free_storage_limit, limit_reached=False, used=user.storage_used)