mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-27 13:45:29 +08:00
This optimizes a hot path when users are being removed from one or more groups since we use the `on(:user_removed_from_group)` event to call the `Chat::AutoLeaveChannels` with a `user_id` parameter. In such case, we don't need to clear the membership of all users, just that one user. DEBUG: Also added a "-- event = <event>" comment on top of the SQL queries used by the "AutoLeaveChannels" so they show up in the logs and hopefully facilitate any performance issues that might arise in the future.
293 lines
9.5 KiB
Ruby
Vendored
293 lines
9.5 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
describe "Automatic user removal from channels" do
|
|
fab!(:user_1) { Fabricate(:user, trust_level: 1) }
|
|
fab!(:user_2) { Fabricate(:user, trust_level: 3) }
|
|
|
|
fab!(:user_1_guardian) { Guardian.new(user_1) }
|
|
|
|
fab!(:secret_group) { Fabricate(:group) }
|
|
fab!(:private_category) { Fabricate(:private_category, group: secret_group) }
|
|
|
|
fab!(:public_channel) { Fabricate(:chat_channel) }
|
|
fab!(:private_channel) { Fabricate(:chat_channel, chatable: private_category) }
|
|
fab!(:dm_channel) { Fabricate(:direct_message_channel, users: [user_1, user_2]) }
|
|
|
|
before do
|
|
SiteSetting.chat_enabled = true
|
|
Jobs.run_immediately!
|
|
|
|
secret_group.add(user_1)
|
|
public_channel.add(user_1)
|
|
private_channel.add(user_1)
|
|
public_channel.add(user_2)
|
|
|
|
CategoryGroup.create(category: public_channel.chatable, group_id: Group::AUTO_GROUPS[:everyone])
|
|
end
|
|
|
|
context "when the chat_allowed_groups site setting changes" do
|
|
it "removes the user who is no longer in chat_allowed_groups" do
|
|
expect { SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:trust_level_3] }.to change {
|
|
Chat::UserChatChannelMembership.count
|
|
}.by(-3)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: public_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).not_to include(
|
|
public_channel.id,
|
|
)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).not_to include(
|
|
private_channel.id,
|
|
)
|
|
end
|
|
|
|
it "does not remove the user who is in one of the chat_allowed_groups" do
|
|
user_2.change_trust_level!(4)
|
|
|
|
expect { SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:trust_level_3] }.to change {
|
|
Chat::UserChatChannelMembership.count
|
|
}.by(-3)
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_2, chat_channel: public_channel),
|
|
).to eq(true)
|
|
end
|
|
|
|
it "removes users from their DM channels" do
|
|
expect { SiteSetting.chat_allowed_groups = "" }.to change {
|
|
Chat::UserChatChannelMembership.count
|
|
}.by(-5)
|
|
|
|
expect(Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: dm_channel)).to eq(
|
|
false,
|
|
)
|
|
expect(Chat::UserChatChannelMembership.exists?(user: user_2, chat_channel: dm_channel)).to eq(
|
|
false,
|
|
)
|
|
end
|
|
|
|
context "for staff users" do
|
|
fab!(:staff_user) { Fabricate(:admin) }
|
|
|
|
it "does not remove them from chat channels" do
|
|
public_channel.add(staff_user)
|
|
private_channel.add(staff_user)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.where(
|
|
user: staff_user,
|
|
chat_channel: [public_channel, private_channel],
|
|
).count,
|
|
).to eq(2)
|
|
|
|
SiteSetting.chat_allowed_groups = ""
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.where(
|
|
user: staff_user,
|
|
chat_channel: [public_channel, private_channel],
|
|
).count,
|
|
).to eq(2)
|
|
end
|
|
|
|
it "does not remove them from DM channels" do
|
|
staff_dm_channel = Fabricate(:direct_message_channel, users: [user_1, staff_user])
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.where(
|
|
user: staff_user,
|
|
chat_channel: [staff_dm_channel],
|
|
).count,
|
|
).to eq(1)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a user is removed from a group" do
|
|
context "when the user is no longer in any chat_allowed_groups" do
|
|
fab!(:group)
|
|
|
|
before do
|
|
group.add(user_1)
|
|
SiteSetting.chat_allowed_groups = group.id
|
|
end
|
|
|
|
it "removes the user from all channels" do
|
|
expect(Chat::UserChatChannelMembership.where(user: user_1).count).to eq(3)
|
|
|
|
group.remove(user_1)
|
|
|
|
expect(Chat::UserChatChannelMembership.where(user: user_1).count).to eq(0)
|
|
end
|
|
|
|
context "for staff users" do
|
|
fab!(:staff_user) { Fabricate(:admin) }
|
|
|
|
it "does not remove them from public channels" do
|
|
public_channel.add(staff_user)
|
|
private_channel.add(staff_user)
|
|
group.add(staff_user)
|
|
group.remove(staff_user)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.where(
|
|
user: staff_user,
|
|
chat_channel: [public_channel, private_channel],
|
|
).count,
|
|
).to eq(2)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a user is removed from a private category group" do
|
|
context "when the user is in another group that can interact with the channel" do
|
|
fab!(:stealth_group) { Fabricate(:group) }
|
|
|
|
before do
|
|
CategoryGroup.create!(
|
|
category: private_category,
|
|
group: stealth_group,
|
|
permission_type: CategoryGroup.permission_types[:full],
|
|
)
|
|
stealth_group.add(user_1)
|
|
end
|
|
|
|
it "does not remove them from the corresponding channel" do
|
|
secret_group.remove(user_1)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(true)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).to include(
|
|
private_channel.id,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when the user is in no other groups that can interact with the channel" do
|
|
it "removes them from the corresponding channel" do
|
|
secret_group.remove(user_1)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).not_to include(
|
|
private_channel.id,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a category is updated" do
|
|
context "when the group's permission changes from reply+see to just see for the category" do
|
|
it "removes the user from the corresponding category channel" do
|
|
private_category.update!(permissions: { secret_group.id => :readonly })
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).not_to include(
|
|
private_channel.id,
|
|
)
|
|
end
|
|
|
|
context "for staff users" do
|
|
fab!(:staff_user) { Fabricate(:admin) }
|
|
|
|
it "does not remove them from the channel" do
|
|
secret_group.add(staff_user)
|
|
private_channel.add(staff_user)
|
|
private_category.update!(permissions: { secret_group.id => :readonly })
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(
|
|
user: staff_user,
|
|
chat_channel: private_channel,
|
|
),
|
|
).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the secret_group is no longer allowed to access the private category" do
|
|
it "removes the user from the corresponding category channel" do
|
|
private_category.update!(permissions: { Group::AUTO_GROUPS[:staff] => :full })
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).not_to include(
|
|
private_channel.id,
|
|
)
|
|
end
|
|
|
|
context "for staff users" do
|
|
fab!(:staff_user) { Fabricate(:admin) }
|
|
|
|
it "does not remove them from the channel" do
|
|
secret_group.add(staff_user)
|
|
private_channel.add(staff_user)
|
|
private_category.update!(permissions: {})
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(
|
|
user: staff_user,
|
|
chat_channel: private_channel,
|
|
),
|
|
).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a group is destroyed" do
|
|
context "when it was the last group on the private category" do
|
|
it "remove users because the category defaults to staff having full access" do
|
|
secret_group.destroy!
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).to_not include(
|
|
private_channel.id,
|
|
)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: public_channel),
|
|
).to eq(true)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).to include(
|
|
public_channel.id,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when there is another group on the private category" do
|
|
before do
|
|
CategoryGroup.create(group_id: Group::AUTO_GROUPS[:staff], category: private_category)
|
|
end
|
|
|
|
it "only removes users who are not in that group" do
|
|
secret_group.destroy!
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: private_channel),
|
|
).to eq(false)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).not_to include(
|
|
private_channel.id,
|
|
)
|
|
|
|
expect(
|
|
Chat::UserChatChannelMembership.exists?(user: user_1, chat_channel: public_channel),
|
|
).to eq(true)
|
|
expect(Chat::ChannelFetcher.all_secured_channel_ids(user_1_guardian)).to include(
|
|
public_channel.id,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|