diff --git a/plugins/discourse-calendar/app/models/discourse_post_event/invitee.rb b/plugins/discourse-calendar/app/models/discourse_post_event/invitee.rb index 92b298a06ff43..44b0bb8af1932 100644 --- a/plugins/discourse-calendar/app/models/discourse_post_event/invitee.rb +++ b/plugins/discourse-calendar/app/models/discourse_post_event/invitee.rb @@ -9,7 +9,14 @@ class Invitee < ActiveRecord::Base belongs_to :event, foreign_key: :post_id belongs_to :user - default_scope { joins(:user).includes(:user).where.not(users: { id: nil }) } + default_scope do + joins(:user) + .includes(:user) + .merge(User.not_suspended) + .merge(User.not_silenced) + .merge(User.not_staged) + .where.not(users: { id: nil }) + end scope :with_status, ->(status) { where(status: Invitee.statuses[status]) } after_commit :sync_chat_channel_members diff --git a/plugins/discourse-calendar/app/services/discourse_post_event/chat_channel_sync.rb b/plugins/discourse-calendar/app/services/discourse_post_event/chat_channel_sync.rb index b981f39b41ef2..5adefca8ff1d9 100644 --- a/plugins/discourse-calendar/app/services/discourse_post_event/chat_channel_sync.rb +++ b/plugins/discourse-calendar/app/services/discourse_post_event/chat_channel_sync.rb @@ -12,11 +12,15 @@ def self.sync(event, guardian: nil) def self.sync_chat_channel_members!(event) missing_members_sql = <<~SQL - SELECT user_id - FROM discourse_post_event_invitees - WHERE post_id = :post_id - AND status in (:statuses) - AND user_id NOT IN ( + SELECT i.user_id + FROM discourse_post_event_invitees i + INNER JOIN users u ON u.id = i.user_id + WHERE i.post_id = :post_id + AND i.status IN (:statuses) + AND (u.suspended_till IS NULL OR u.suspended_till <= :now) + AND (u.silenced_till IS NULL OR u.silenced_till <= :now) + AND u.staged = false + AND i.user_id NOT IN ( SELECT user_id FROM user_chat_channel_memberships WHERE chat_channel_id = :chat_channel_id @@ -32,6 +36,7 @@ def self.sync_chat_channel_members!(event) DiscoursePostEvent::Invitee.statuses[:interested], ], chat_channel_id: event.chat_channel_id, + now: Time.zone.now, ) if missing_user_ids.present? diff --git a/plugins/discourse-calendar/spec/integration/invitee_spec.rb b/plugins/discourse-calendar/spec/integration/invitee_spec.rb index 2ee61c79a53bc..9f9382c79b148 100644 --- a/plugins/discourse-calendar/spec/integration/invitee_spec.rb +++ b/plugins/discourse-calendar/spec/integration/invitee_spec.rb @@ -27,4 +27,48 @@ end end end + + describe "default scope filtering" do + fab!(:regular_user, :user) + fab!(:suspended_user) { Fabricate(:user, suspended_till: 1.year.from_now) } + fab!(:silenced_user) { Fabricate(:user, silenced_till: 1.year.from_now) } + fab!(:staged_user) { Fabricate(:user, staged: true) } + + before do + post_event.create_invitees( + [ + { user_id: regular_user.id, status: DiscoursePostEvent::Invitee.statuses[:going] }, + { user_id: suspended_user.id, status: DiscoursePostEvent::Invitee.statuses[:going] }, + { user_id: silenced_user.id, status: DiscoursePostEvent::Invitee.statuses[:going] }, + { user_id: staged_user.id, status: DiscoursePostEvent::Invitee.statuses[:going] }, + ], + ) + end + + it "excludes suspended users from invitees" do + expect(post_event.invitees.map(&:user_id)).not_to include(suspended_user.id) + end + + it "excludes silenced users from invitees" do + expect(post_event.invitees.map(&:user_id)).not_to include(silenced_user.id) + end + + it "excludes staged users from invitees" do + expect(post_event.invitees.map(&:user_id)).not_to include(staged_user.id) + end + + it "includes regular users in invitees" do + expect(post_event.invitees.map(&:user_id)).to include(regular_user.id) + end + + it "includes users whose suspension has expired" do + suspended_user.update!(suspended_till: 1.day.ago) + expect(post_event.invitees.map(&:user_id)).to include(suspended_user.id) + end + + it "includes users whose silence has expired" do + silenced_user.update!(silenced_till: 1.day.ago) + expect(post_event.invitees.map(&:user_id)).to include(silenced_user.id) + end + end end diff --git a/plugins/discourse-calendar/spec/services/discourse_post_event/chat_channel_sync_spec.rb b/plugins/discourse-calendar/spec/services/discourse_post_event/chat_channel_sync_spec.rb index 2879e23c94d05..f75ecc351232d 100644 --- a/plugins/discourse-calendar/spec/services/discourse_post_event/chat_channel_sync_spec.rb +++ b/plugins/discourse-calendar/spec/services/discourse_post_event/chat_channel_sync_spec.rb @@ -33,4 +33,72 @@ expect(event.chat_channel.name).to eq(admin_post.topic.title) end + + describe "user filtering" do + fab!(:suspended_user) { Fabricate(:user, suspended_till: 1.year.from_now) } + fab!(:silenced_user) { Fabricate(:user, silenced_till: 1.year.from_now) } + fab!(:staged_user) { Fabricate(:user, staged: true) } + fab!(:regular_user, :user) + + it "does not add suspended users to the chat channel" do + event = Fabricate(:event, chat_enabled: true, post: admin_post, name: "Test Event") + event.create_invitees( + [user_id: suspended_user.id, status: DiscoursePostEvent::Invitee.statuses[:going]], + ) + event.save! + + expect(event.chat_channel.user_chat_channel_memberships.pluck(:user_id)).not_to include( + suspended_user.id, + ) + end + + it "does not add silenced users to the chat channel" do + event = Fabricate(:event, chat_enabled: true, post: admin_post, name: "Test Event") + event.create_invitees( + [user_id: silenced_user.id, status: DiscoursePostEvent::Invitee.statuses[:going]], + ) + event.save! + + expect(event.chat_channel.user_chat_channel_memberships.pluck(:user_id)).not_to include( + silenced_user.id, + ) + end + + it "does not add staged users to the chat channel" do + event = Fabricate(:event, chat_enabled: true, post: admin_post, name: "Test Event") + event.create_invitees( + [user_id: staged_user.id, status: DiscoursePostEvent::Invitee.statuses[:going]], + ) + event.save! + + expect(event.chat_channel.user_chat_channel_memberships.pluck(:user_id)).not_to include( + staged_user.id, + ) + end + + it "adds regular users to the chat channel" do + event = Fabricate(:event, chat_enabled: true, post: admin_post, name: "Test Event") + event.create_invitees( + [user_id: regular_user.id, status: DiscoursePostEvent::Invitee.statuses[:going]], + ) + event.save! + + expect(event.chat_channel.user_chat_channel_memberships.pluck(:user_id)).to include( + regular_user.id, + ) + end + + it "adds users whose suspension has expired to the chat channel" do + formerly_suspended = Fabricate(:user, suspended_till: 1.day.ago) + event = Fabricate(:event, chat_enabled: true, post: admin_post, name: "Test Event") + event.create_invitees( + [user_id: formerly_suspended.id, status: DiscoursePostEvent::Invitee.statuses[:going]], + ) + event.save! + + expect(event.chat_channel.user_chat_channel_memberships.pluck(:user_id)).to include( + formerly_suspended.id, + ) + end + end end