Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

FEATURE: Option to force title and flair updates for badge-group syncs #208

Merged
merged 1 commit into from Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/locales/client.en.yml
Expand Up @@ -232,6 +232,9 @@ en:
group:
label: Group
description: Target group. Users with the specified badge will be added to this group
update_user_title_and_flair:
label: Update user title and flair
description: Optional, Update user title and flair
remove_members_without_badge:
label: Remove existing members without badge
description: Optional, Remove existing group members without the specified badge
Expand Down
Expand Up @@ -11,13 +11,15 @@

field :badge_name, component: :text, required: true
field :group, component: :group, required: true
field :update_user_title_and_flair, component: :boolean
field :remove_members_without_badge, component: :boolean

triggerables %i[recurring user_first_logged_in]

script do |context, fields|
badge_name = fields.dig("badge_name", "value").strip
group_id = fields.dig("group", "value")
update_user_title_and_flair = fields.dig("update_user_title_and_flair", "value")
remove_members_without_badge = fields.dig("remove_members_without_badge", "value")
current_user = context["user"]
bulk_modify_start_count =
Expand Down Expand Up @@ -64,6 +66,14 @@
group.bulk_add(user_ids_to_add)
end

if update_user_title_and_flair && user_ids_to_add.present?
DB.exec(<<~SQL, ids: user_ids_to_add, title: group.title, flair_group_id: group.id)
UPDATE users
SET title = :title, flair_group_id = :flair_group_id
WHERE id IN (:ids)
SQL
end

next unless remove_members_without_badge

# IDs of users who are currently target group members without the badge
Expand Down Expand Up @@ -92,5 +102,13 @@
else
group.bulk_remove(user_ids_to_remove)
end

if update_user_title_and_flair && user_ids_to_remove.present?
DB.exec(<<~SQL, ids: user_ids_to_remove, title: group.title, flair_group_id: group.id)
UPDATE users
SET title = NULL, flair_group_id = NULL
WHERE id IN (:ids) AND (flair_group_id = :flair_group_id OR title = :title)
SQL
end
end
end
112 changes: 111 additions & 1 deletion spec/scripts/user_group_membership_through_badge_spec.rb
Expand Up @@ -6,7 +6,7 @@
fab!(:user) { Fabricate(:user) }
fab!(:other_users) { Fabricate.times(5, :user) }
fab!(:badge) { Fabricate(:badge) }
fab!(:target_group) { Fabricate(:group) }
fab!(:target_group) { Fabricate(:group, title: "Target Title", flair_icon: "ad") }

fab!(:automation) do
Fabricate(
Expand Down Expand Up @@ -281,5 +281,115 @@ def owns_badge?(user_ids)
expect(owns_badge?(other_users.map(&:id))).to eq(false)
end
end

context "with update_user_title_and_flair = true" do
before do
BadgeGranter.grant(badge, user)
automation.upsert_field!(
"update_user_title_and_flair",
"boolean",
{ value: true },
target: "script",
)
end

it "sets user title and flair" do
expect(user.title).to be_nil
expect(user.flair_group_id).to be_nil

automation.trigger!(
"kind" => DiscourseAutomation::Triggerable::USER_FIRST_LOGGED_IN,
"user" => user,
)

user.reload
expect(user.title).to eq("Target Title")
expect(user.flair_group_id).to eq(target_group.id)
end

it "updates existing user title and flair" do
existing_flair_group = Fabricate(:group)
user.update(title: "Existing Title", flair_group_id: existing_flair_group.id)

expect(user.title).to eq("Existing Title")
expect(user.flair_group_id).to eq(existing_flair_group.id)

automation.trigger!(
"kind" => DiscourseAutomation::Triggerable::USER_FIRST_LOGGED_IN,
"user" => user,
)

user.reload
expect(user.title).to eq("Target Title")
expect(user.flair_group_id).to eq(target_group.id)

user_badge = UserBadge.find_by(user_id: user.id, badge_id: badge.id)
user_badge.destroy

automation.upsert_field!(
"remove_members_without_badge",
"boolean",
{ value: true },
target: "script",
)

automation.trigger!(
"kind" => DiscourseAutomation::Triggerable::USER_FIRST_LOGGED_IN,
"user" => user,
)

user.reload
expect(user.title).to be_nil
expect(user.flair_group_id).to be_nil
end
end

context "with update_user_title_and_flair = false" do
before do
BadgeGranter.grant(badge, user)
automation.upsert_field!(
"update_user_title_and_flair",
"boolean",
{ value: false },
target: "script",
)
end

it "does not update existing user title and flair" do
existing_flair_group = Fabricate(:group)
user.update(title: "Existing Title", flair_group_id: existing_flair_group.id)

expect(user.title).to eq("Existing Title")
expect(user.flair_group_id).to eq(existing_flair_group.id)

automation.trigger!(
"kind" => DiscourseAutomation::Triggerable::USER_FIRST_LOGGED_IN,
"user" => user,
)

user.reload
expect(user.title).to eq("Existing Title")
expect(user.flair_group_id).to eq(existing_flair_group.id)

user_badge = UserBadge.find_by(user_id: user.id, badge_id: badge.id)
user_badge.destroy

automation.upsert_field!(
"remove_members_without_badge",
"boolean",
{ value: true },
target: "script",
)

automation.trigger!(
"kind" => DiscourseAutomation::Triggerable::USER_FIRST_LOGGED_IN,
"user" => user,
)

user.reload
expect(user.title).to eq("Existing Title")
expect(user.flair_group_id).to eq(existing_flair_group.id)
end
end
end
end