From 9997054cbe8d33fd826188cbda7da25c4bc4cf50 Mon Sep 17 00:00:00 2001 From: Peter Vacho Date: Tue, 31 Dec 2024 14:49:42 +0100 Subject: [PATCH] Fix several issues with event edpoints --- src/api/events.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/api/events.py b/src/api/events.py index aaff7da..2d8e4dd 100644 --- a/src/api/events.py +++ b/src/api/events.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated, cast, final -from beanie import DeleteRules, Link, PydanticObjectId +from beanie import Link, PydanticObjectId from fastapi import APIRouter, Body, HTTPException, Query, status from fastapi.responses import Response from pydantic import BaseModel, StringConstraints, field_serializer, field_validator @@ -263,16 +263,25 @@ async def get_event(event_id: PydanticObjectId, user: CurrentUserDep) -> EventDa @events_router.delete("/{event_id}") async def delete_event(event_id: PydanticObjectId, user: CurrentUserDep) -> Response: """Delete an event by ID.""" - event = await Event.get(event_id) + event = await Event.get(event_id, fetch_links=True) if event is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Event with given id doesn't exist") - if event.owner != user: + + if cast(User, event.user).id != user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="You can only access your own events", ) - _ = await event.delete(link_rules=DeleteRules.DELETE_LINKS) + # First delete all related objects that use the event + invitations = await Invitation.find(expr(Invitation.event).id == event.id).to_list() + for invite in invitations: + # Some notifications may be referencing this invitation, but we don't need + # to delete them, as notifications have a handle for missing invitations + # (the same would happen if the invitor just deleted/revoked the invite) + _ = await invite.delete() + + _ = await event.delete() return Response(status_code=status.HTTP_204_NO_CONTENT) @@ -297,7 +306,7 @@ async def overwrite_event( event = await Event.get(event_id, fetch_links=True) if event is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Event with given id doesn't exist") - if event.owner != user: + if cast(User, event.user).id != user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="You can only access your own events", @@ -314,7 +323,6 @@ async def partial_update_event( partial_data: Annotated[PartialEventUpdateData, Body()], ) -> EventData: """Partially update an event.""" - # 1. Fetch the event event = await Event.get(event_id, fetch_links=True) if event is None: raise HTTPException( @@ -322,17 +330,14 @@ async def partial_update_event( detail="Event with given id doesn't exist", ) - # 2. Check ownership - if event.owner != user: + if cast(User, event.user).id != user: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="You can only access your own events", ) - # 3. Update the event with the partial data updated_event = await partial_data.update_event(event) - # 4. Return the updated data return EventData.from_event(updated_event)