From cdbf3175aa4e51c75f8839b7bc539f3d118772a6 Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Fri, 6 Mar 2026 23:45:10 +0800 Subject: [PATCH] Fix remaining QA warnings: lazy=raise on CalendarMember + bidirectional connection check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W-03: invite_member now verifies the target user has a reciprocal UserConnection row before sending the invite. W-04: CalendarMember relationships changed from lazy="selectin" to lazy="raise". All queries that access .user, .calendar, or .inviter already use explicit selectinload() — verified across all routers and services. Co-Authored-By: Claude Opus 4.6 --- backend/app/models/calendar_member.py | 6 +++--- backend/app/routers/shared_calendars.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/backend/app/models/calendar_member.py b/backend/app/models/calendar_member.py index 56f647f..2f7ad26 100644 --- a/backend/app/models/calendar_member.py +++ b/backend/app/models/calendar_member.py @@ -46,8 +46,8 @@ class CalendarMember(Base): ) accepted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) - calendar: Mapped["Calendar"] = relationship(back_populates="members", lazy="selectin") - user: Mapped["User"] = relationship(foreign_keys=[user_id], lazy="selectin") + calendar: Mapped["Calendar"] = relationship(back_populates="members", lazy="raise") + user: Mapped["User"] = relationship(foreign_keys=[user_id], lazy="raise") inviter: Mapped[Optional["User"]] = relationship( - foreign_keys=[invited_by], lazy="selectin" + foreign_keys=[invited_by], lazy="raise" ) diff --git a/backend/app/routers/shared_calendars.py b/backend/app/routers/shared_calendars.py index f84edb7..b9ed123 100644 --- a/backend/app/routers/shared_calendars.py +++ b/backend/app/routers/shared_calendars.py @@ -163,6 +163,16 @@ async def invite_member( target_user_id = connection.connected_user_id + # W-03: Verify bidirectional connection still active + reverse_conn = await db.execute( + select(UserConnection.id).where( + UserConnection.user_id == target_user_id, + UserConnection.connected_user_id == current_user.id, + ) + ) + if not reverse_conn.scalar_one_or_none(): + raise HTTPException(status_code=400, detail="Connection is no longer active") + if target_user_id == calendar.user_id: raise HTTPException(status_code=400, detail="Cannot invite the calendar owner")