FIX: User titles from translated badge names were automatically revoked

It also cleans up the denormalized data about badge titles in the user_profiles table.
This commit is contained in:
Gerhard Schlager 2020-08-19 23:23:31 +02:00 committed by Gerhard Schlager
parent 11647b79f7
commit cff68ef0dd
2 changed files with 96 additions and 23 deletions

View File

@ -397,21 +397,33 @@ class BadgeGranter
def self.revoke_ungranted_titles! def self.revoke_ungranted_titles!
DB.exec <<~SQL DB.exec <<~SQL
UPDATE users SET title = '' UPDATE users u
WHERE NOT title IS NULL AND SET title = ''
title <> '' AND FROM user_profiles up
EXISTS ( WHERE u.title IS NOT NULL
SELECT 1 AND u.title <> ''
FROM user_profiles AND up.user_id = u.id
WHERE user_id = users.id AND badge_granted_title AND up.badge_granted_title
) AND AND up.granted_title_badge_id IS NOT NULL
title NOT IN ( AND NOT EXISTS(
SELECT name SELECT 1
FROM badges FROM badges b
WHERE allow_title AND enabled AND JOIN user_badges ub ON ub.user_id = u.id AND ub.badge_id = b.id
badges.id IN (SELECT badge_id FROM user_badges ub where ub.user_id = users.id) WHERE b.id = up.granted_title_badge_id
AND b.allow_title
AND b.enabled
) )
SQL SQL
DB.exec <<~SQL
UPDATE user_profiles up
SET badge_granted_title = FALSE,
granted_title_badge_id = NULL
FROM users u
WHERE up.user_id = u.id
AND (u.title IS NULL OR u.title = '')
AND (up.badge_granted_title OR up.granted_title_badge_id IS NOT NULL)
SQL
end end
def self.notification_locale(locale) def self.notification_locale(locale)

View File

@ -17,33 +17,94 @@ describe BadgeGranter do
end end
describe 'revoke_titles' do describe 'revoke_titles' do
it 'can correctly revoke titles' do let(:user) { Fabricate(:user) }
badge = Fabricate(:badge, allow_title: true) let(:badge) { Fabricate(:badge, allow_title: true) }
user = Fabricate(:user, title: badge.name)
user.reload
user.user_profile.update_column(:badge_granted_title, true)
it 'revokes title when badge is not allowed as title' do
BadgeGranter.grant(badge, user) BadgeGranter.grant(badge, user)
BadgeGranter.revoke_ungranted_titles! user.update!(title: badge.name)
BadgeGranter.revoke_ungranted_titles!
user.reload user.reload
expect(user.title).to eq(badge.name) expect(user.title).to eq(badge.name)
expect(user.user_profile.badge_granted_title).to eq(true)
expect(user.user_profile.granted_title_badge_id).to eq(badge.id)
badge.update_column(:allow_title, false) badge.update_column(:allow_title, false)
BadgeGranter.revoke_ungranted_titles! BadgeGranter.revoke_ungranted_titles!
user.reload user.reload
expect(user.title).to eq('') expect(user.title).to be_blank
expect(user.user_profile.badge_granted_title).to eq(false)
expect(user.user_profile.granted_title_badge_id).to be_nil
end
it 'revokes title when badge is disabled' do
BadgeGranter.grant(badge, user)
user.update!(title: badge.name)
BadgeGranter.revoke_ungranted_titles!
user.reload
expect(user.title).to eq(badge.name)
expect(user.user_profile.badge_granted_title).to eq(true)
expect(user.user_profile.granted_title_badge_id).to eq(badge.id)
badge.update_column(:enabled, false)
BadgeGranter.revoke_ungranted_titles!
user.reload
expect(user.title).to be_blank
expect(user.user_profile.badge_granted_title).to eq(false)
expect(user.user_profile.granted_title_badge_id).to be_nil
end
it 'revokes title when user badge is revoked' do
BadgeGranter.grant(badge, user)
user.update!(title: badge.name)
BadgeGranter.revoke_ungranted_titles!
user.reload
expect(user.title).to eq(badge.name)
expect(user.user_profile.badge_granted_title).to eq(true)
expect(user.user_profile.granted_title_badge_id).to eq(badge.id)
BadgeGranter.revoke(user.user_badges.first)
BadgeGranter.revoke_ungranted_titles!
user.reload
expect(user.title).to be_blank
expect(user.user_profile.badge_granted_title).to eq(false)
expect(user.user_profile.granted_title_badge_id).to be_nil
end
it 'does not revoke custom title' do
user.title = "CEO" user.title = "CEO"
user.save user.save!
BadgeGranter.revoke_ungranted_titles! BadgeGranter.revoke_ungranted_titles!
user.reload user.reload
expect(user.title).to eq("CEO") expect(user.title).to eq("CEO")
end end
it 'does not revoke localized title' do
badge = Badge.find(Badge::Regular)
badge_name = nil
BadgeGranter.grant(badge, user)
I18n.with_locale(:de) do
badge_name = badge.display_name
user.update!(title: badge_name)
end
user.reload
expect(user.title).to eq(badge_name)
expect(user.user_profile.badge_granted_title).to eq(true)
expect(user.user_profile.granted_title_badge_id).to eq(badge.id)
BadgeGranter.revoke_ungranted_titles!
user.reload
expect(user.title).to eq(badge_name)
expect(user.user_profile.badge_granted_title).to eq(true)
expect(user.user_profile.granted_title_badge_id).to eq(badge.id)
end
end end
describe 'preview' do describe 'preview' do