diff --git a/app/assets/javascripts/admin/controllers/admin-badges-award.js.es6 b/app/assets/javascripts/admin/controllers/admin-badges-award.js.es6 index af3afd528b1..ef141ccac12 100644 --- a/app/assets/javascripts/admin/controllers/admin-badges-award.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-badges-award.js.es6 @@ -4,6 +4,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; export default Controller.extend({ saving: false, + replaceBadgeOwners: false, actions: { massAward() { @@ -18,6 +19,7 @@ export default Controller.extend({ }; options.data.append("file", file); + options.data.append("replace_badge_owners", this.replaceBadgeOwners); this.set("saving", true); diff --git a/app/assets/javascripts/admin/templates/badges-award.hbs b/app/assets/javascripts/admin/templates/badges-award.hbs index 66ef70365a9..d7a24e0651c 100644 --- a/app/assets/javascripts/admin/templates/badges-award.hbs +++ b/app/assets/javascripts/admin/templates/badges-award.hbs @@ -16,6 +16,12 @@

{{I18n 'admin.badges.mass_award.upload_csv'}}

+
+ +
{{d-button class="btn-primary" action=(action 'massAward') diff --git a/app/controllers/admin/badges_controller.rb b/app/controllers/admin/badges_controller.rb index a63d33bda64..f494fb921ef 100644 --- a/app/controllers/admin/badges_controller.rb +++ b/app/controllers/admin/badges_controller.rb @@ -43,6 +43,9 @@ class Admin::BadgesController < Admin::AdminController badge = Badge.find_by(id: params[:badge_id]) raise Discourse::InvalidParameters if csv_file.try(:tempfile).nil? || badge.nil? + replace_badge_owners = params[:replace_badge_owners] == 'true' + BadgeGranter.revoke_all(badge) if replace_badge_owners + batch_number = 1 line_number = 1 batch = [] diff --git a/app/services/badge_granter.rb b/app/services/badge_granter.rb index 620e3cd0b17..18dc48493ff 100644 --- a/app/services/badge_granter.rb +++ b/app/services/badge_granter.rb @@ -104,6 +104,16 @@ class BadgeGranter end end + def self.revoke_all(badge) + custom_badge_names = TranslationOverride.where(translation_key: badge.translation_key).pluck(:value) + + users = User.joins(:user_badges).where(user_badges: { badge_id: badge.id }).where(title: badge.name) + users = users.or(User.joins(:user_badges).where(title: custom_badge_names)) unless custom_badge_names.empty? + users.update_all(title: nil) + + UserBadge.where(badge: badge).delete_all + end + def self.queue_badge_grant(type, opt) return unless SiteSetting.enable_badges payload = nil diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index b447c667577..e22d930491d 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -4505,6 +4505,7 @@ en: upload_csv: Upload a CSV with user emails aborted: Please upload a CSV containing user emails success: Your CSV was received and users will receive their badge shortly. + replace_owners: Remove the badge from previous owners emoji: title: "Emoji" diff --git a/spec/services/badge_granter_spec.rb b/spec/services/badge_granter_spec.rb index e91b755e628..6bfd968e4ca 100644 --- a/spec/services/badge_granter_spec.rb +++ b/spec/services/badge_granter_spec.rb @@ -225,6 +225,39 @@ describe BadgeGranter do end end + describe 'revoke_all' do + it 'deletes every user_badge record associated with that badge' do + described_class.grant(badge, user) + + described_class.revoke_all(badge) + + expect(UserBadge.exists?(badge: badge, user: user)).to eq(false) + end + + it 'removes titles' do + another_title = 'another title' + described_class.grant(badge, user) + user.update!(title: badge.name) + user2 = Fabricate(:user, title: another_title) + + described_class.revoke_all(badge) + + expect(user.reload.title).to be_nil + expect(user2.reload.title).to eq(another_title) + end + + it 'removes custom badge titles' do + custom_badge_title = 'this is a badge title' + TranslationOverride.create!(translation_key: badge.translation_key, value: custom_badge_title, locale: 'en_US') + described_class.grant(badge, user) + user.update!(title: custom_badge_title) + + described_class.revoke_all(badge) + + expect(user.reload.title).to be_nil + end + end + context "update_badges" do fab!(:user) { Fabricate(:user) } fab!(:liker) { Fabricate(:user) }