diff --git a/app/assets/javascripts/discourse/models/badge.js b/app/assets/javascripts/discourse/models/badge.js index 0d629d17568..0326351207f 100644 --- a/app/assets/javascripts/discourse/models/badge.js +++ b/app/assets/javascripts/discourse/models/badge.js @@ -35,7 +35,7 @@ Discourse.Badge = Discourse.Model.extend({ @type {String} **/ displayName: function() { - var i18nKey = "badges." + this.get('i18nNameKey') + ".name"; + var i18nKey = "badges.badge." + this.get('i18nNameKey') + ".name"; return I18n.t(i18nKey, {defaultValue: this.get('name')}); }.property('name', 'i18nNameKey'), @@ -46,7 +46,7 @@ Discourse.Badge = Discourse.Model.extend({ @type {String} **/ translatedDescription: function() { - var i18nKey = "badges." + this.get('i18nNameKey') + ".description", + var i18nKey = "badges.badge." + this.get('i18nNameKey') + ".description", translation = I18n.t(i18nKey); if (translation.indexOf(i18nKey) !== -1) { translation = null; diff --git a/app/assets/javascripts/discourse/templates/badges/index.js.handlebars b/app/assets/javascripts/discourse/templates/badges/index.js.handlebars index 2317de8a9b0..0551537fea3 100644 --- a/app/assets/javascripts/discourse/templates/badges/index.js.handlebars +++ b/app/assets/javascripts/discourse/templates/badges/index.js.handlebars @@ -5,7 +5,7 @@ {{#each}} {{user-badge badge=this}} - {{description}} + {{translatedDescription}} {{i18n badges.granted count=grant_count}} {{/each}} diff --git a/app/assets/javascripts/discourse/templates/badges/show.js.handlebars b/app/assets/javascripts/discourse/templates/badges/show.js.handlebars index 35638c72d85..980975093d9 100644 --- a/app/assets/javascripts/discourse/templates/badges/show.js.handlebars +++ b/app/assets/javascripts/discourse/templates/badges/show.js.handlebars @@ -8,7 +8,7 @@ - +
{{user-badge badge=this}}{{description}}{{translatedDescription}} {{i18n badges.granted count=grant_count}}
diff --git a/app/assets/javascripts/discourse/templates/components/user-badge.js.handlebars b/app/assets/javascripts/discourse/templates/components/user-badge.js.handlebars index ca2070b7e3d..64419e5278d 100644 --- a/app/assets/javascripts/discourse/templates/components/user-badge.js.handlebars +++ b/app/assets/javascripts/discourse/templates/components/user-badge.js.handlebars @@ -1,6 +1,6 @@ {{#link-to 'badges.show' badge}} - + - {{badge.name}} + {{badge.displayName}} {{/link-to}} diff --git a/app/models/badge.rb b/app/models/badge.rb index 70e18460836..2ae330bc4d6 100644 --- a/app/models/badge.rb +++ b/app/models/badge.rb @@ -5,6 +5,10 @@ class Badge < ActiveRecord::Base validates :name, presence: true, uniqueness: true validates :badge_type, presence: true validates :allow_title, inclusion: [true, false] + + def self.trust_level_badge_ids + (1..4).to_a + end end # == Schema Information diff --git a/app/models/user.rb b/app/models/user.rb index 9eae13b2b49..e064afac344 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -447,6 +447,7 @@ class User < ActiveRecord::Base transaction do self.save! Group.user_trust_level_change!(self.id, self.trust_level) + BadgeGranter.update_trust_level_badges!(self) end end diff --git a/app/services/badge_granter.rb b/app/services/badge_granter.rb index 8b4de1a54f7..fb0e07a7c75 100644 --- a/app/services/badge_granter.rb +++ b/app/services/badge_granter.rb @@ -24,9 +24,11 @@ class BadgeGranter StaffActionLogger.new(@granted_by).log_badge_grant(user_badge) end - @user.notifications.create(notification_type: Notification.types[:granted_badge], - data: { badge_id: @badge.id, - badge_name: @badge.name }.to_json) + if SiteSetting.enable_badges? + @user.notifications.create(notification_type: Notification.types[:granted_badge], + data: { badge_id: @badge.id, + badge_name: @badge.name }.to_json) + end end end @@ -54,4 +56,19 @@ class BadgeGranter end end + + def self.update_trust_level_badges!(user) + Badge.trust_level_badge_ids.each do |badge_id| + user_badge = UserBadge.where(user_id: user.id, badge_id: badge_id).first + if user_badge + # Revoke the badge if the user is not supposed to have it. + BadgeGranter.revoke(user_badge) if user.trust_level < badge_id + else + # Grant the badge if the user is supposed to have it. + badge = Badge.find(badge_id) + BadgeGranter.grant(badge, user) if user.trust_level >= badge_id + end + end + end + end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 2f8bb0519c1..edc52ccc61e 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1850,6 +1850,16 @@ en: one: "1 granted" other: "%{count} granted" select_badge_for_title: Select a badge to use as your title - example_badge: - name: Example Badge - description: This is a generic example badge. + badge: + basic_user: + name: Basic User + description: Trusted as a basic user. + regular_user: + name: Regular User + description: Trusted as a regular user. + leader: + name: Leader + description: One of the most active and prolific users. + elder: + name: Elder + description: Long term community leader who has been around and seen everything. diff --git a/db/fixtures/700_badge_types.rb b/db/fixtures/600_badge_types.rb similarity index 100% rename from db/fixtures/700_badge_types.rb rename to db/fixtures/600_badge_types.rb diff --git a/db/fixtures/601_badges.rb b/db/fixtures/601_badges.rb new file mode 100644 index 00000000000..bffbfa18d95 --- /dev/null +++ b/db/fixtures/601_badges.rb @@ -0,0 +1,47 @@ +def reset_badge_grant_count(badge) + badge.grant_count = UserBadge.where(badge_id: badge.id).count + badge.save! +end + +def grant_trust_level_badges_to_user(user) + return if user.id == Discourse.system_user.id + Badge.trust_level_badge_ids.each do |badge_id| + user_badge = UserBadge.where(user_id: user.id, badge_id: badge_id).first + if user_badge + # Revoke the badge if the user is not supposed to have it. + if user.trust_level < badge_id + user_badge.destroy! + end + else + # Grant the badge if the user is supposed to have it. + badge = Badge.find(badge_id) + if user.trust_level >= badge_id + UserBadge.create!(badge: badge, user: user, granted_by: Discourse.system_user, granted_at: Time.now) + end + end + end +end + +trust_level_badges = [ + {id: 1, name: "Basic User", type: 3}, + {id: 2, name: "Regular User", type: 3}, + {id: 3, name: "Leader", type: 2}, + {id: 4, name: "Elder", type: 1} +] + +backfill_trust_level_badges = false + +trust_level_badges.each do |spec| + backfill_trust_level_badges ||= Badge.where(id: spec[:id]).first.nil? + + Badge.seed do |b| + b.id = spec[:id] + b.name = spec[:name] + b.badge_type_id = spec[:type] + end +end + +if backfill_trust_level_badges + User.find_each {|user| grant_trust_level_badges_to_user(user) } + Badge.where(id: Badge.trust_level_badge_ids).each {|badge| reset_badge_grant_count(badge) } +end diff --git a/db/migrate/20120809201855_migrate_bookmarks_to_post_actions.rb b/db/migrate/20120809201855_migrate_bookmarks_to_post_actions.rb index 597a015a57f..89db3302139 100644 --- a/db/migrate/20120809201855_migrate_bookmarks_to_post_actions.rb +++ b/db/migrate/20120809201855_migrate_bookmarks_to_post_actions.rb @@ -5,6 +5,6 @@ class MigrateBookmarksToPostActions < ActiveRecord::Migration def down # I can reverse this, but not really worth the work - raise ActiveRecord::IrriversableMigration + raise ActiveRecord::IrreversibleMigration end end diff --git a/db/migrate/20120812235417_retire_expressions.rb b/db/migrate/20120812235417_retire_expressions.rb index 164e1999098..696d9a39f89 100644 --- a/db/migrate/20120812235417_retire_expressions.rb +++ b/db/migrate/20120812235417_retire_expressions.rb @@ -15,6 +15,6 @@ select end def down - raise ActiveRecord::IrriversableMigration + raise ActiveRecord::IrreversibleMigration end end diff --git a/db/migrate/20130120222728_fix_search.rb b/db/migrate/20130120222728_fix_search.rb index 2ca0bf7c8a2..ee44ea1ae80 100644 --- a/db/migrate/20130120222728_fix_search.rb +++ b/db/migrate/20130120222728_fix_search.rb @@ -13,6 +13,6 @@ class FixSearch < ActiveRecord::Migration end def down - raise ActiveRecord::IrriversableMigration + raise ActiveRecord::IrreversibleMigration end end diff --git a/db/migrate/20140504174212_increment_reserved_trust_level_badge_ids.rb b/db/migrate/20140504174212_increment_reserved_trust_level_badge_ids.rb new file mode 100644 index 00000000000..ff3e00f1939 --- /dev/null +++ b/db/migrate/20140504174212_increment_reserved_trust_level_badge_ids.rb @@ -0,0 +1,16 @@ +class IncrementReservedTrustLevelBadgeIds < ActiveRecord::Migration + def up + execute "ALTER SEQUENCE badges_id_seq START WITH 100" + + max_badge_id = Badge.order('id DESC').limit(1).first.try(:id) + Badge.where('id > 0 AND id <= 100').find_each do |badge| + new_id = badge.id + max_badge_id + 100 + UserBadge.where(badge_id: badge.id).update_all badge_id: new_id + badge.update_column :id, new_id + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/lib/boost_trust_level.rb b/lib/boost_trust_level.rb index bb06aa0eae8..e36eab8b4ca 100644 --- a/lib/boost_trust_level.rb +++ b/lib/boost_trust_level.rb @@ -18,6 +18,7 @@ class BoostTrustLevel @user.update_attributes!(trust_level: @level) end @logger.log_trust_level_change(@user, previous_level, @level) + BadgeGranter.update_trust_level_badges!(@user) success end diff --git a/spec/controllers/badges_controller_spec.rb b/spec/controllers/badges_controller_spec.rb index adc3957d0c9..61b6994c716 100644 --- a/spec/controllers/badges_controller_spec.rb +++ b/spec/controllers/badges_controller_spec.rb @@ -9,7 +9,7 @@ describe BadgesController do response.status.should == 200 parsed = JSON.parse(response.body) - parsed["badges"].length.should == 1 + parsed["badges"].length.should == Badge.count end end diff --git a/spec/services/badge_granter_spec.rb b/spec/services/badge_granter_spec.rb index a186d6f85a4..b441097a8d4 100644 --- a/spec/services/badge_granter_spec.rb +++ b/spec/services/badge_granter_spec.rb @@ -1,10 +1,15 @@ require 'spec_helper' +require_dependency 'boost_trust_level' describe BadgeGranter do let(:badge) { Fabricate(:badge) } let(:user) { Fabricate(:user) } + before do + SiteSetting.enable_badges = true + end + describe 'grant' do it 'grants a badge' do @@ -66,4 +71,27 @@ describe BadgeGranter do end + context "revoke" do + let(:user) { Fabricate(:user) } + let(:logger) { StaffActionLogger.new(Fabricate(:admin)) } + + it "is called by User#change_trust_level!" do + BadgeGranter.expects(:update_trust_level_badges!) + user.change_trust_level!(:basic) + end + + it "is called by BoostTrustLevel#save!" do + BadgeGranter.expects(:update_trust_level_badges!) + BoostTrustLevel.new(user: user, level: 1, logger: logger).save! + end + + it "grants and revokes badges" do + user.change_trust_level!(:elder) + UserBadge.where(user_id: user.id, badge_id: Badge.trust_level_badge_ids).count.should eq(4) + BoostTrustLevel.new(user: user, level: 1, logger: logger).save! + UserBadge.where(user_id: user.id, badge_id: 1).first.should_not be_nil + UserBadge.where(user_id: user.id, badge_id: 2).first.should be_nil + end + end + end diff --git a/test/javascripts/models/badge_test.js b/test/javascripts/models/badge_test.js index a4365e352a4..9e4eed9aeea 100644 --- a/test/javascripts/models/badge_test.js +++ b/test/javascripts/models/badge_test.js @@ -13,7 +13,7 @@ test('displayName', function() { this.stub(I18n, "t").returnsArg(0); var badge2 = Discourse.Badge.create({id: 2, name: "Test Badge 2"}); - equal(badge2.get('displayName'), "badges.test_badge_2.name", "uses translation when available"); + equal(badge2.get('displayName'), "badges.badge.test_badge_2.name", "uses translation when available"); }); test('translatedDescription', function() {