Fix several issues with event edpoints

This commit is contained in:
Peter Vacho 2024-12-31 14:49:42 +01:00
parent a276399e59
commit 9997054cbe
Signed by: school
GPG key ID: 8CFC3837052871B4

View file

@ -1,7 +1,7 @@
from datetime import datetime from datetime import datetime
from typing import Annotated, cast, final 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 import APIRouter, Body, HTTPException, Query, status
from fastapi.responses import Response from fastapi.responses import Response
from pydantic import BaseModel, StringConstraints, field_serializer, field_validator 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}") @events_router.delete("/{event_id}")
async def delete_event(event_id: PydanticObjectId, user: CurrentUserDep) -> Response: async def delete_event(event_id: PydanticObjectId, user: CurrentUserDep) -> Response:
"""Delete an event by ID.""" """Delete an event by ID."""
event = await Event.get(event_id) event = await Event.get(event_id, fetch_links=True)
if event is None: if event is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Event with given id doesn't exist") 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( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
detail="You can only access your own events", 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) 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) event = await Event.get(event_id, fetch_links=True)
if event is None: if event is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Event with given id doesn't exist") 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( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
detail="You can only access your own events", detail="You can only access your own events",
@ -314,7 +323,6 @@ async def partial_update_event(
partial_data: Annotated[PartialEventUpdateData, Body()], partial_data: Annotated[PartialEventUpdateData, Body()],
) -> EventData: ) -> EventData:
"""Partially update an event.""" """Partially update an event."""
# 1. Fetch the event
event = await Event.get(event_id, fetch_links=True) event = await Event.get(event_id, fetch_links=True)
if event is None: if event is None:
raise HTTPException( raise HTTPException(
@ -322,17 +330,14 @@ async def partial_update_event(
detail="Event with given id doesn't exist", detail="Event with given id doesn't exist",
) )
# 2. Check ownership if cast(User, event.user).id != user:
if event.owner != user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
detail="You can only access your own events", detail="You can only access your own events",
) )
# 3. Update the event with the partial data
updated_event = await partial_data.update_event(event) updated_event = await partial_data.update_event(event)
# 4. Return the updated data
return EventData.from_event(updated_event) return EventData.from_event(updated_event)