Merge pull request #2470 from techAPJ/refactor-bulk-invite

FEATURE: Add groups support to Bulk Invite
This commit is contained in:
Robin Ward 2014-06-25 16:08:06 -04:00
commit 983f4829f0
2 changed files with 123 additions and 24 deletions

View File

@ -5,6 +5,7 @@ module Jobs
class BulkInvite < Jobs::Base
sidekiq_options retry: false
attr_accessor :current_user
def initialize
@logs = []
@ -16,44 +17,82 @@ module Jobs
filename = args[:filename]
identifier = args[:identifier]
chunks = args[:chunks].to_i
current_user = User.find_by(id: args[:current_user_id])
@current_user = User.find_by(id: args[:current_user_id])
raise Discourse::InvalidParameters.new(:filename) if filename.blank?
raise Discourse::InvalidParameters.new(:identifier) if identifier.blank?
raise Discourse::InvalidParameters.new(:chunks) if chunks <= 0
csv_path = "#{Invite.base_directory}/#{filename}"
tmp_csv_path = "#{csv_path}.tmp"
# path to tmp directory
tmp_directory = File.dirname(Invite.chunk_path(identifier, filename, 0))
# merge all chunks
HandleChunkUpload.merge_chunks(chunks, upload_path: csv_path, tmp_upload_path: tmp_csv_path, model: Invite, identifier: identifier, filename: filename, tmp_directory: tmp_directory)
# merge chunks, and get csv path
csv_path = get_csv_path(filename, identifier, chunks)
# read csv file, and send out invitations
CSV.foreach(csv_path) do |csv_info|
if !csv_info[0].nil?
if validate_email(csv_info[0])
Invite.invite_by_email(csv_info[0], current_user, topic=nil)
@sent += 1
else
log "Invalid email '#{csv_info[0]}' at line number '#{$INPUT_LINE_NUMBER}'"
@failed += 1
end
end
end
read_csv_file(csv_path)
# send notification to user regarding progress
notify_user(current_user)
notify_user
# since emails have already been sent out, delete the uploaded csv file
FileUtils.rm_rf(csv_path) rescue nil
end
def get_csv_path(filename, identifier, chunks)
csv_path = "#{Invite.base_directory}/#{filename}"
tmp_csv_path = "#{csv_path}.tmp"
# path to tmp directory
tmp_directory = File.dirname(Invite.chunk_path(identifier, filename, 0))
# merge all chunks
HandleChunkUpload.merge_chunks(chunks, upload_path: csv_path, tmp_upload_path: tmp_csv_path, model: Invite, identifier: identifier, filename: filename, tmp_directory: tmp_directory)
return csv_path
end
def read_csv_file(csv_path)
CSV.foreach(csv_path) do |csv_info|
if !csv_info[0].nil?
if validate_email(csv_info[0])
# email is valid, now check for groups
if !csv_info[1].nil?
# group(s) present
send_invite_with_groups(csv_info[0], csv_info[1], $INPUT_LINE_NUMBER)
else
# no group present
send_invite_without_group(csv_info[0])
end
@sent += 1
else
# invalid email
log "Invalid email '#{csv_info[0]}' at line number '#{$INPUT_LINE_NUMBER}'"
@failed += 1
end
end
end
end
def validate_email(email)
/\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/.match(email)
end
def send_invite_with_groups(email, group_names, csv_line_number)
group_ids = []
group_names = group_names.split(';')
group_names.each { |group_name|
group_detail = Group.find_by_name(group_name)
if !group_detail.nil?
# valid group
group_ids.push(group_detail.id)
else
# invalid group
log "Invalid group '#{group_name}' at line number '#{csv_line_number}'"
end
}
Invite.invite_by_email(email, @current_user, topic=nil, group_ids)
end
def send_invite_without_group(email)
Invite.invite_by_email(email, @current_user, topic=nil)
end
def log(message)
puts(message) rescue nil
save_log(message)
@ -63,12 +102,12 @@ module Jobs
@logs << "[#{Time.now}] #{message}"
end
def notify_user(current_user)
if current_user
def notify_user
if @current_user
if (@sent > 0 && @failed == 0)
SystemMessage.create(current_user, :bulk_invite_succeeded, sent: @sent)
SystemMessage.create(@current_user, :bulk_invite_succeeded, sent: @sent)
else
SystemMessage.create(current_user, :bulk_invite_failed, sent: @sent, failed: @failed, logs: @logs.join("\n"))
SystemMessage.create(@current_user, :bulk_invite_failed, sent: @sent, failed: @failed, logs: @logs.join("\n"))
end
end
end

View File

@ -0,0 +1,60 @@
require 'spec_helper'
describe Jobs::BulkInvite do
context '.execute' do
it 'raises an error when the filename is missing' do
lambda { Jobs::BulkInvite.new.execute(identifier: '46-discoursecsv', chunks: '1') }.should raise_error(Discourse::InvalidParameters)
end
it 'raises an error when the identifier is missing' do
lambda { Jobs::BulkInvite.new.execute(filename: 'discourse.csv', chunks: '1') }.should raise_error(Discourse::InvalidParameters)
end
it 'raises an error when the chunks is missing' do
lambda { Jobs::BulkInvite.new.execute(filename: 'discourse.csv', identifier: '46-discoursecsv') }.should raise_error(Discourse::InvalidParameters)
end
context '.read_csv_file' do
let(:user) { Fabricate(:user) }
let(:bulk_invite) { Jobs::BulkInvite.new }
let(:csv_file) { File.new("#{Rails.root}/spec/fixtures/csv/discourse.csv") }
it 'reads csv file' do
bulk_invite.current_user = user
bulk_invite.read_csv_file(csv_file)
Invite.where(email: 'robin@outlook.com').exists?.should be_true
end
end
context '.send_invite_with_groups' do
let(:bulk_invite) { Jobs::BulkInvite.new }
let(:user) { Fabricate(:user) }
let(:group) { Fabricate(:group) }
let(:email) { "evil@trout.com" }
it 'creates an invite to the group' do
bulk_invite.current_user = user
bulk_invite.send_invite_with_groups(email, group.name, 1)
invite = Invite.where(email: email).first
invite.should be_present
InvitedGroup.where(invite_id: invite.id, group_id: group.id).exists?.should be_true
end
end
context '.send_invite_without_group' do
let(:bulk_invite) { Jobs::BulkInvite.new }
let(:user) { Fabricate(:user) }
let(:email) { "evil@trout.com" }
it 'creates an invite' do
bulk_invite.current_user = user
bulk_invite.send_invite_without_group(email)
Invite.where(email: email).exists?.should be_true
end
end
end
end