FEATURE: Support uploading a csv with either user emails or usernames (#8971)

This commit is contained in:
Roman Rizzi 2020-02-18 10:53:12 -03:00 committed by GitHub
parent be3e4ab3f5
commit 9441362c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 9 deletions

View File

@ -51,6 +51,9 @@ class Admin::BadgesController < Admin::AdminController
batch = []
File.open(csv_file) do |csv|
mode = Email.is_valid?(CSV.parse_line(csv.first).first) ? 'email' : 'username'
csv.rewind
csv.each_line do |email_line|
batch.concat CSV.parse_line(email_line)
line_number += 1
@ -60,7 +63,7 @@ class Admin::BadgesController < Admin::AdminController
last_batch_item = full_batch || csv.eof?
if last_batch_item
Jobs.enqueue(:mass_award_badge, user_emails: batch, badge_id: badge.id)
Jobs.enqueue(:mass_award_badge, users_batch: batch, badge_id: badge.id, mode: mode)
batch = []
batch_number += 1
end

View File

@ -3,8 +3,16 @@
module Jobs
class MassAwardBadge < ::Jobs::Base
def execute(args)
return unless mode = args[:mode]
badge = Badge.find_by(id: args[:badge_id])
users = User.select(:id, :username, :locale).with_email(args[:user_emails])
users = User.select(:id, :username, :locale)
if mode == 'email'
users = users.with_email(args[:users_batch])
else
users = users.where(username_lower: args[:users_batch].map!(&:downcase))
end
return if users.empty? || badge.nil?

View File

@ -4502,8 +4502,8 @@ en:
description: Award the same badge to many users at once.
no_badge_selected: Please select a badge to get started.
perform: "Award Badge to Users"
upload_csv: Upload a CSV with user emails
aborted: Please upload a CSV containing user emails
upload_csv: Upload a CSV with either user emails or usernames
aborted: Please upload a CSV containing either user emails or usernames
success: Your CSV was received and users will receive their badge shortly.
replace_owners: Remove the badge from previous owners

3
spec/fixtures/csv/usernames.csv vendored Normal file
View File

@ -0,0 +1,3 @@
username1
username2
username3
1 username1
2 username2
3 username3

View File

@ -6,9 +6,10 @@ describe Jobs::MassAwardBadge do
describe '#execute' do
fab!(:badge) { Fabricate(:badge) }
fab!(:user) { Fabricate(:user) }
let(:email_mode) { 'email' }
it 'creates the badge for an existing user' do
subject.execute(user_emails: [user.email], badge_id: badge.id)
execute_job([user.email])
expect(UserBadge.where(user: user, badge: badge).exists?).to eq(true)
end
@ -16,14 +17,14 @@ describe Jobs::MassAwardBadge do
it 'works with multiple users' do
user_2 = Fabricate(:user)
subject.execute(user_emails: [user.email, user_2.email], badge_id: badge.id)
execute_job([user.email, user_2.email])
expect(UserBadge.exists?(user: user, badge: badge)).to eq(true)
expect(UserBadge.exists?(user: user_2, badge: badge)).to eq(true)
end
it 'also creates a notification for the user' do
subject.execute(user_emails: [user.email], badge_id: badge.id)
execute_job([user.email])
expect(Notification.exists?(user: user)).to eq(true)
expect(UserBadge.where.not(notification_id: nil).exists?(user: user, badge: badge)).to eq(true)
@ -34,10 +35,14 @@ describe Jobs::MassAwardBadge do
UserBadge.create!(badge_id: Badge::Member, user: user, granted_by: Discourse.system_user, granted_at: Time.now)
subject.execute(user_emails: [user.email, user_2.email], badge_id: badge.id)
execute_job([user.email, user_2.email])
expect(UserBadge.find_by(user: user, badge: badge).featured_rank).to eq(2)
expect(UserBadge.find_by(user: user_2, badge: badge).featured_rank).to eq(1)
end
def execute_job(emails)
subject.execute(users_batch: emails, badge_id: badge.id, mode: 'email')
end
end
end

View File

@ -199,7 +199,7 @@ describe Admin::BadgesController do
expect(response.status).to eq(400)
end
it 'creates the badge for an existing user' do
it 'awards the badge using a list of user emails' do
Jobs.run_immediately!
user = Fabricate(:user, email: 'user1@test.com')
@ -209,6 +209,17 @@ describe Admin::BadgesController do
expect(UserBadge.exists?(user: user, badge: badge)).to eq(true)
end
it 'awards the badge using a list of usernames' do
Jobs.run_immediately!
user = Fabricate(:user, username: 'username1')
file = file_from_fixtures('usernames.csv', 'csv')
post "/admin/badges/award/#{badge.id}.json", params: { file: fixture_file_upload(file) }
expect(UserBadge.exists?(user: user, badge: badge)).to eq(true)
end
end
end
end