mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 10:40:48 +08:00
Pt. 2 of the performance update to group add/remove users, building on #38737 This PR moves the bulk_add/remove logic from the `Group` model into `GroupManager`, making `GroupManager` the single owner of membership mutation logic. `Group#bulk_add` and `Group#bulk_remove` become thin delegators. The controller's per-user `add_user_to_group` loop is replaced with a single bulk `add_users_to_group` call. `GroupActionLogger` gets `bulk_log_add_users_to_group` / `bulk_log_remove_users_from_group` backed by `insert_all`. `DiscourseConnect` routes through `GroupManager` instead of raw `GroupUser.create!/destroy_all` Also moves notifications for adding users to a group to a background job, as that was running synchronously and causing performance issues when `notify_users: true` There will be a Pt. 3 (#39091) that updates all callers using some variation of `GroupUser.create` and removes callbacks from `GroupUser`
212 lines
6.9 KiB
Ruby
Vendored
212 lines
6.9 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe GroupActionLogger do
|
|
subject(:logger) { described_class.new(group_owner, group) }
|
|
|
|
fab!(:group_owner, :user)
|
|
fab!(:group)
|
|
fab!(:user)
|
|
|
|
before { group.add_owner(group_owner) }
|
|
|
|
describe "#log_make_user_group_owner" do
|
|
it "should create the right record" do
|
|
logger.log_make_user_group_owner(user)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:make_user_group_owner])
|
|
expect(group_history.acting_user).to eq(group_owner)
|
|
expect(group_history.target_user).to eq(user)
|
|
end
|
|
end
|
|
|
|
describe "#log_remove_user_as_group_owner" do
|
|
it "should create the right record" do
|
|
logger.log_remove_user_as_group_owner(user)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:remove_user_as_group_owner])
|
|
expect(group_history.acting_user).to eq(group_owner)
|
|
expect(group_history.target_user).to eq(user)
|
|
end
|
|
end
|
|
|
|
describe "#log_add_user_to_group" do
|
|
context "as a group owner" do
|
|
it "should create the right record" do
|
|
logger.log_add_user_to_group(user)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:add_user_to_group])
|
|
expect(group_history.acting_user).to eq(group_owner)
|
|
expect(group_history.target_user).to eq(user)
|
|
end
|
|
end
|
|
|
|
context "as a normal user" do
|
|
subject(:logger) { described_class.new(user, group) }
|
|
|
|
before { group.update!(public_admission: true) }
|
|
|
|
it "should create the right record" do
|
|
logger.log_add_user_to_group(user)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:add_user_to_group])
|
|
expect(group_history.acting_user).to eq(user)
|
|
expect(group_history.target_user).to eq(user)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#log_remove_user_from_group" do
|
|
context "as group owner" do
|
|
it "should create the right record" do
|
|
logger.log_remove_user_from_group(user)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:remove_user_from_group])
|
|
expect(group_history.acting_user).to eq(group_owner)
|
|
expect(group_history.target_user).to eq(user)
|
|
end
|
|
end
|
|
|
|
context "as a normal user" do
|
|
subject(:logger) { described_class.new(user, group) }
|
|
|
|
before { group.update!(public_exit: true) }
|
|
|
|
it "should create the right record" do
|
|
logger.log_remove_user_from_group(user)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:remove_user_from_group])
|
|
expect(group_history.acting_user).to eq(user)
|
|
expect(group_history.target_user).to eq(user)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#bulk_log_add_users_to_group" do
|
|
fab!(:user2, :user)
|
|
|
|
it "creates a record for each user" do
|
|
expect { logger.bulk_log_add_users_to_group([user.id, user2.id]) }.to change {
|
|
GroupHistory.where(action: GroupHistory.actions[:add_user_to_group]).count
|
|
}.by(2)
|
|
|
|
records =
|
|
GroupHistory.where(action: GroupHistory.actions[:add_user_to_group], group: group).last(2)
|
|
|
|
expect(records.map(&:acting_user)).to all(eq(group_owner))
|
|
expect(records.map(&:target_user)).to contain_exactly(user, user2)
|
|
end
|
|
|
|
it "does nothing when target_users is empty" do
|
|
expect { logger.bulk_log_add_users_to_group([]) }.not_to change { GroupHistory.count }
|
|
end
|
|
|
|
it "forwards the subject when present" do
|
|
logger.bulk_log_add_users_to_group([user.id], "added_users")
|
|
|
|
expect(GroupHistory.last.subject).to eq("added_users")
|
|
end
|
|
end
|
|
|
|
describe "#bulk_log_remove_users_from_group" do
|
|
fab!(:user2, :user)
|
|
|
|
it "creates a record for each user" do
|
|
expect { logger.bulk_log_remove_users_from_group([user.id, user2.id]) }.to change {
|
|
GroupHistory.where(action: GroupHistory.actions[:remove_user_from_group]).count
|
|
}.by(2)
|
|
|
|
records =
|
|
GroupHistory.where(
|
|
action: GroupHistory.actions[:remove_user_from_group],
|
|
group: group,
|
|
).last(2)
|
|
|
|
expect(records.map(&:acting_user)).to all(eq(group_owner))
|
|
expect(records.map(&:target_user)).to contain_exactly(user, user2)
|
|
end
|
|
|
|
it "does nothing when target_users is empty" do
|
|
expect { logger.bulk_log_remove_users_from_group([]) }.not_to change { GroupHistory.count }
|
|
end
|
|
|
|
it "forwards the subject when present" do
|
|
logger.bulk_log_remove_users_from_group([user.id], "remove_users")
|
|
|
|
expect(GroupHistory.last.subject).to eq("remove_users")
|
|
end
|
|
end
|
|
|
|
describe "#log_group_creation" do
|
|
subject(:log_creation) { logger.log_group_creation }
|
|
|
|
let(:owner_history) do
|
|
GroupHistory.where(group:, action: GroupHistory.actions[:make_user_group_owner])
|
|
end
|
|
let(:member_history) do
|
|
GroupHistory.where(group:, action: GroupHistory.actions[:add_user_to_group])
|
|
end
|
|
|
|
context "when group has only an owner" do
|
|
it "logs make_user_group_owner for the owner" do
|
|
expect { log_creation }.to change { owner_history.count }.by(1)
|
|
expect(owner_history).to contain_exactly(
|
|
an_object_having_attributes(acting_user: group_owner, target_user: group_owner),
|
|
)
|
|
end
|
|
|
|
it "logs add_user_to_group for the owner" do
|
|
expect { log_creation }.to change { member_history.count }.by(1)
|
|
expect(member_history).to contain_exactly(
|
|
an_object_having_attributes(acting_user: group_owner, target_user: group_owner),
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when group has an owner and a member" do
|
|
before { group.add(user) }
|
|
|
|
it "logs make_user_group_owner only for the owner" do
|
|
expect { log_creation }.to change { owner_history.count }.by(1)
|
|
expect(owner_history).to contain_exactly(
|
|
an_object_having_attributes(acting_user: group_owner, target_user: group_owner),
|
|
)
|
|
end
|
|
|
|
it "logs add_user_to_group for both owner and member" do
|
|
expect { log_creation }.to change { member_history.count }.by(2)
|
|
expect(member_history).to contain_exactly(
|
|
an_object_having_attributes(acting_user: group_owner, target_user: group_owner),
|
|
an_object_having_attributes(acting_user: group_owner, target_user: user),
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#log_change_group_settings" do
|
|
it "should create the right record" do
|
|
group.update!(public_admission: true, created_at: Time.zone.now)
|
|
|
|
expect { logger.log_change_group_settings }.to change { GroupHistory.count }.by(1)
|
|
|
|
group_history = GroupHistory.last
|
|
|
|
expect(group_history.action).to eq(GroupHistory.actions[:change_group_setting])
|
|
expect(group_history.acting_user).to eq(group_owner)
|
|
expect(group_history.subject).to eq("public_admission")
|
|
expect(group_history.prev_value).to eq("f")
|
|
expect(group_history.new_value).to eq("t")
|
|
end
|
|
end
|
|
end
|