diff --git a/api/obs/api/app.py b/api/obs/api/app.py index 6ad6b0a..100cafa 100644 --- a/api/obs/api/app.py +++ b/api/obs/api/app.py @@ -13,7 +13,7 @@ from sanic.response import ( file as file_response, html as html_response, ) -from sanic.exceptions import Unauthorized +from sanic.exceptions import Unauthorized, SanicException from sanic_session import Session, InMemorySessionInterface from sqlalchemy import select @@ -31,6 +31,20 @@ c = app.config api = Blueprint("api", url_prefix="/api") auth = Blueprint("auth", url_prefix="") + +@api.exception(SanicException, BaseException) +def _handle_sanic_errors(_request, exception): + log.error("Exception in handler: %s", exception, exc_info=True) + return json_response( + { + "errors": { + type(exception).__name__: str(exception), + }, + }, + status=exception.status_code if hasattr(exception, "status_code") else 500, + ) + + # Configure paths def configure_paths(c): c.API_ROOT_DIR = c.get("API_ROOT_DIR") or abspath( diff --git a/api/obs/api/db.py b/api/obs/api/db.py index 09eb3af..22e4746 100644 --- a/api/obs/api/db.py +++ b/api/obs/api/db.py @@ -145,6 +145,8 @@ class Road(Base): NOW = text("NOW()") +class DuplicateTrackFileError(ValueError): + pass class Track(Base): __tablename__ = "track" @@ -262,7 +264,7 @@ class Track(Base): ) if duplicate_count: - raise ValueError("duplicate file") + raise DuplicateTrackFileError() self.original_file_hash = hex_hash diff --git a/api/obs/api/routes/tracks.py b/api/obs/api/routes/tracks.py index 1954fa8..8697724 100644 --- a/api/obs/api/routes/tracks.py +++ b/api/obs/api/routes/tracks.py @@ -6,7 +6,7 @@ from os.path import join, exists, isfile from sqlalchemy import select, func from sqlalchemy.orm import joinedload -from obs.api.db import Track, User, Comment +from obs.api.db import Track, User, Comment, DuplicateTrackFileError from obs.api.app import api, require_auth, read_api_key, json from sanic.response import file_stream, empty @@ -112,7 +112,11 @@ async def post_track(req): else req.ctx.user.are_tracks_visible_for_all, ) track.generate_slug() - await track.prevent_duplicates(req.ctx.db, file.body) + try: + await track.prevent_duplicates(req.ctx.db, file.body) + except DuplicateTrackFileError: + raise InvalidUsage("Track file is not unique") + track.uploaded_by_user_agent = normalize_user_agent(req.headers["user-agent"]) track.original_file_name = file.name await track.write_to_original_file(req.app.config, file.body) diff --git a/frontend/src/pages/UploadPage.tsx b/frontend/src/pages/UploadPage.tsx index ca74d6f..10783a5 100644 --- a/frontend/src/pages/UploadPage.tsx +++ b/frontend/src/pages/UploadPage.tsx @@ -49,7 +49,7 @@ export function FileUploadStatus({ }: { id: string file: File - onComplete: (result: FileUploadResult) => void + onComplete: (id: string, result: FileUploadResult) => void slug?: string }) { const [progress, setProgress] = React.useState(0)