mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
## Summary Correctly restrict private calendar event access to current group members. The patch replaces stale invitee-row authorization with active invited-group membership checks across event detail serialization, attendance searches, RSVP mutations, and livestream chat metadata, and prunes stale invitee records when a user is removed from a group. ## Source - Patch Triage: https://patch.discourse.org/patch-triage/1377 Co-authored-by: discourse-patch-triage <272280883+discourse-patch-triage[bot]@users.noreply.github.com>
98 lines
3.3 KiB
Ruby
Vendored
98 lines
3.3 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module DiscoursePostEvent
|
|
describe "private event group invitees" do
|
|
fab!(:event_owner, :admin)
|
|
fab!(:invitee_user) { Fabricate(:user, refresh_auto_groups: true) }
|
|
fab!(:invited_group) do
|
|
Fabricate(
|
|
:group,
|
|
visibility_level: Group.visibility_levels[:owners],
|
|
members_visibility_level: Group.visibility_levels[:owners],
|
|
)
|
|
end
|
|
fab!(:topic) { Fabricate(:topic, user: event_owner, category: Fabricate(:category)) }
|
|
fab!(:post) { Fabricate(:post, user: event_owner, topic:) }
|
|
fab!(:event) do
|
|
Fabricate(
|
|
:event,
|
|
post:,
|
|
status: DiscoursePostEvent::Event.statuses[:private],
|
|
raw_invitees: [invited_group.name],
|
|
)
|
|
end
|
|
|
|
before do
|
|
Jobs.run_immediately!
|
|
SiteSetting.calendar_enabled = true
|
|
SiteSetting.discourse_post_event_enabled = true
|
|
invited_group.add(invitee_user)
|
|
end
|
|
|
|
def create_invitee
|
|
event.create_invitees(
|
|
[{ user_id: invitee_user.id, status: DiscoursePostEvent::Invitee.statuses[:going] }],
|
|
)
|
|
event.invitees.find_by(user_id: invitee_user.id)
|
|
end
|
|
|
|
it "removes invitee records when a user leaves an invited group" do
|
|
invitee = create_invitee
|
|
|
|
expect { invited_group.remove(invitee_user) }.to change {
|
|
DiscoursePostEvent::Invitee.unscoped.exists?(id: invitee.id)
|
|
}.from(true).to(false)
|
|
end
|
|
|
|
it "blocks a stale invitee from private event details, attendance listings, and RSVP updates" do
|
|
stale_invitee = create_invitee
|
|
invited_group.remove(invitee_user)
|
|
stale_invitee =
|
|
DiscoursePostEvent::Invitee
|
|
.unscoped
|
|
.find_or_create_by!(post_id: event.id, user_id: invitee_user.id) do |invitee|
|
|
invitee.status = DiscoursePostEvent::Invitee.statuses[:going]
|
|
end
|
|
|
|
sign_in(invitee_user)
|
|
|
|
get "/discourse-post-event/events/#{event.id}.json"
|
|
|
|
expect(response.status).to eq(200)
|
|
event_json = response.parsed_body["event"]
|
|
expect(event_json).not_to have_key("raw_invitees")
|
|
expect(event_json).not_to have_key("sample_invitees")
|
|
expect(event_json).not_to have_key("stats")
|
|
expect(event_json["should_display_invitees"]).to eq(false)
|
|
expect(event_json["can_update_attendance"]).to eq(false)
|
|
expect(event_json["watching_invitee"]).to be_nil
|
|
|
|
get "/discourse-post-event/events/#{event.id}/invitees.json"
|
|
|
|
expect(response.status).to eq(403)
|
|
expect(response.body).not_to include(invitee_user.username)
|
|
|
|
get "/discourse-post-event/events.json",
|
|
params: {
|
|
attending_user: invitee_user.username,
|
|
include_details: "true",
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(
|
|
response.parsed_body["events"].map { |listed_event_json| listed_event_json["id"] },
|
|
).not_to include(event.id)
|
|
|
|
put "/discourse-post-event/events/#{event.id}/invitees/#{stale_invitee.id}.json",
|
|
params: {
|
|
invitee: {
|
|
status: "interested",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(403)
|
|
expect(response.parsed_body).not_to have_key("success")
|
|
expect(stale_invitee.reload.status).to eq(DiscoursePostEvent::Invitee.statuses[:going])
|
|
end
|
|
end
|
|
end
|