Skip to content

Commit dd42383

Browse files
committed
Don't send community event invites to users already attending or organizing
1 parent ee37bd2 commit dd42383

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

app/backend/src/couchers/servicers/events.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,16 @@ def generate_event_create_notifications(payload: jobs_pb2.GenerateEventCreateNot
278278
logger.error(f"Inviting user {payload.inviting_user_id} is gone while trying to send event notification?")
279279
return
280280

281+
# people already attending or organizing the event don't need an invite to it
282+
already_involved_user_ids = set(
283+
session.execute(
284+
select(EventOccurrenceAttendee.user_id).where(EventOccurrenceAttendee.occurrence_id == occurrence.id)
285+
).scalars()
286+
) | set(session.execute(select(EventOrganizer.user_id).where(EventOrganizer.event_id == event.id)).scalars())
287+
281288
for user in users:
289+
if user.id in already_involved_user_ids:
290+
continue
282291
if is_not_visible(session, user.id, creator.id):
283292
continue
284293
context = make_notification_user_context(user_id=user.id)

app/backend/src/tests/test_events.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,6 +2288,74 @@ def test_community_invite_requests(db, email_collector: EmailCollector, moderato
22882288
assert err.value.details() == "A community invite has already been sent out for this event."
22892289

22902290

2291+
def test_community_invite_not_sent_to_attendees_or_organizers(db, moderator: Moderator):
2292+
# Regression: users who already RSVP'd (or organize the event) must not get the
2293+
# community invite notification when it is approved.
2294+
organizer, organizer_token = generate_user()
2295+
attendee, attendee_token = generate_user()
2296+
member, _ = generate_user()
2297+
superuser, superuser_token = generate_user(is_superuser=True)
2298+
2299+
with session_scope() as session:
2300+
w = create_community(session, 0, 2, "World Community", [superuser], [], None)
2301+
mr = create_community(session, 0, 2, "Macroregion", [superuser], [], w)
2302+
r = create_community(session, 0, 2, "Region", [superuser], [], mr)
2303+
c_id = create_community(session, 0, 2, "Community", [organizer, attendee, member], [], r).id
2304+
2305+
enforce_community_memberships()
2306+
2307+
with events_session(organizer_token) as api:
2308+
event_id = api.CreateEvent(
2309+
events_pb2.CreateEventReq(
2310+
title="Dummy Title",
2311+
content="Dummy content.",
2312+
parent_community_id=c_id,
2313+
location=events_pb2.EventLocation(
2314+
address="Near Null Island",
2315+
lat=0.1,
2316+
lng=0.2,
2317+
),
2318+
start_time=Timestamp_from_datetime(now() + timedelta(hours=3)),
2319+
end_time=Timestamp_from_datetime(now() + timedelta(hours=4)),
2320+
timezone="UTC",
2321+
)
2322+
).event_id
2323+
2324+
moderator.approve_event_occurrence(event_id)
2325+
2326+
# the attendee RSVPs before the community invite is approved
2327+
with events_session(attendee_token) as api:
2328+
api.SetEventAttendance(
2329+
events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
2330+
)
2331+
2332+
with events_session(organizer_token) as api:
2333+
api.RequestCommunityInvite(events_pb2.RequestCommunityInviteReq(event_id=event_id))
2334+
2335+
with real_editor_session(superuser_token) as editor:
2336+
res = editor.ListEventCommunityInviteRequests(editor_pb2.ListEventCommunityInviteRequestsReq())
2337+
editor.DecideEventCommunityInviteRequest(
2338+
editor_pb2.DecideEventCommunityInviteRequestReq(
2339+
event_community_invite_request_id=res.requests[0].event_community_invite_request_id,
2340+
approve=True,
2341+
)
2342+
)
2343+
2344+
process_jobs()
2345+
2346+
with session_scope() as session:
2347+
2348+
def invite_notification_count(user_id: int) -> int:
2349+
notifications = session.execute(select(Notification).where(Notification.user_id == user_id)).scalars().all()
2350+
return len([n for n in notifications if n.topic_action == NotificationTopicAction.event__create_approved])
2351+
2352+
# a plain community member gets the invite...
2353+
assert invite_notification_count(member.id) == 1
2354+
# ...but the attendee and the organizer don't
2355+
assert invite_notification_count(attendee.id) == 0
2356+
assert invite_notification_count(organizer.id) == 0
2357+
2358+
22912359
def test_update_event_should_notify_queues_job():
22922360
user, token = generate_user()
22932361
start = now()

0 commit comments

Comments
 (0)