mirror of
https://github.com/discourse/discourse.git
synced 2025-06-05 10:54:41 +08:00
FIX: use hijack for processing bulk invites (#7679)
FIX: do not store bulk invite CSV file on server
This commit is contained in:
@ -172,24 +172,31 @@ class InvitesController < ApplicationController
|
||||
def upload_csv
|
||||
guardian.ensure_can_bulk_invite_to_forum!(current_user)
|
||||
|
||||
file = params[:file] || params[:files].first
|
||||
name = params[:name] || File.basename(file.original_filename, ".*")
|
||||
extension = File.extname(file.original_filename)
|
||||
hijack do
|
||||
begin
|
||||
file = params[:file] || params[:files].first
|
||||
|
||||
begin
|
||||
data = if extension.downcase == ".csv"
|
||||
path = Invite.create_csv(file, name)
|
||||
Jobs.enqueue(:bulk_invite, filename: "#{name}#{extension}", current_user_id: current_user.id)
|
||||
{ url: path }
|
||||
else
|
||||
failed_json.merge(errors: [I18n.t("bulk_invite.file_should_be_csv")])
|
||||
if File.read(file.tempfile).scan(/\n/).count.to_i > 50000
|
||||
return render json: failed_json.merge(errors: [I18n.t("bulk_invite.max_rows")]), status: 422
|
||||
end
|
||||
|
||||
invites = []
|
||||
CSV.foreach(file.tempfile) do |row|
|
||||
invite_hash = { email: row[0], groups: row[1], topic_id: row[2] }
|
||||
if invite_hash[:email].present?
|
||||
invites.push(invite_hash)
|
||||
end
|
||||
end
|
||||
if invites.present?
|
||||
Jobs.enqueue(:bulk_invite, invites: invites, current_user_id: current_user.id)
|
||||
render json: success_json
|
||||
else
|
||||
render json: failed_json.merge(errors: [I18n.t("bulk_invite.error")]), status: 422
|
||||
end
|
||||
rescue
|
||||
render json: failed_json.merge(errors: [I18n.t("bulk_invite.error")]), status: 422
|
||||
end
|
||||
rescue
|
||||
failed_json.merge(errors: [I18n.t("bulk_invite.error")])
|
||||
end
|
||||
MessageBus.publish("/uploads/csv", data.as_json, user_ids: [current_user.id])
|
||||
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def fetch_username
|
||||
|
@ -1,6 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'csv'
|
||||
require_dependency 'system_message'
|
||||
|
||||
module Jobs
|
||||
@ -18,48 +17,38 @@ module Jobs
|
||||
end
|
||||
|
||||
def execute(args)
|
||||
filename = args[:filename]
|
||||
raise Discourse::InvalidParameters.new(:filename) if filename.blank?
|
||||
invites = args[:invites]
|
||||
raise Discourse::InvalidParameters.new(:invites) if invites.blank?
|
||||
|
||||
@current_user = User.find_by(id: args[:current_user_id])
|
||||
raise Discourse::InvalidParameters.new(:current_user_id) unless @current_user
|
||||
@guardian = Guardian.new(@current_user)
|
||||
|
||||
csv_path = "#{Invite.base_directory}/#{filename}"
|
||||
|
||||
# read csv file, and send out invitations
|
||||
read_csv_file(csv_path)
|
||||
process_invites(invites)
|
||||
ensure
|
||||
# send notification to user regarding progress
|
||||
notify_user
|
||||
File.delete(csv_path) if csv_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def read_csv_file(csv_path)
|
||||
file = File.open(csv_path, encoding: 'bom|utf-8')
|
||||
CSV.new(file).each do |csv_info|
|
||||
if csv_info[0]
|
||||
if (EmailValidator.email_regex =~ csv_info[0])
|
||||
# email is valid
|
||||
send_invite(csv_info, $INPUT_LINE_NUMBER)
|
||||
@sent += 1
|
||||
else
|
||||
# invalid email
|
||||
save_log "Invalid Email '#{csv_info[0]}' at line number '#{$INPUT_LINE_NUMBER}'"
|
||||
@failed += 1
|
||||
end
|
||||
def process_invites(invites)
|
||||
invites.each do |invite|
|
||||
if (EmailValidator.email_regex =~ invite[:email])
|
||||
# email is valid
|
||||
send_invite(invite)
|
||||
@sent += 1
|
||||
else
|
||||
# invalid email
|
||||
save_log "Invalid Email '#{invite[:email]}"
|
||||
@failed += 1
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
save_log "Bulk Invite Process Failed -- '#{e.message}'"
|
||||
@failed += 1
|
||||
ensure
|
||||
file&.close
|
||||
end
|
||||
|
||||
def get_groups(group_names, csv_line_number)
|
||||
def get_groups(group_names)
|
||||
groups = []
|
||||
|
||||
if group_names
|
||||
@ -73,7 +62,7 @@ module Jobs
|
||||
groups.push(group)
|
||||
else
|
||||
# invalid group
|
||||
save_log "Invalid Group '#{group_name}' at line number '#{csv_line_number}'"
|
||||
save_log "Invalid Group '#{group_name}'"
|
||||
@failed += 1
|
||||
end
|
||||
}
|
||||
@ -82,13 +71,13 @@ module Jobs
|
||||
groups
|
||||
end
|
||||
|
||||
def get_topic(topic_id, csv_line_number)
|
||||
def get_topic(topic_id)
|
||||
topic = nil
|
||||
|
||||
if topic_id
|
||||
topic = Topic.find_by_id(topic_id)
|
||||
if topic.nil?
|
||||
save_log "Invalid Topic ID '#{topic_id}' at line number '#{csv_line_number}'"
|
||||
save_log "Invalid Topic ID '#{topic_id}'"
|
||||
@failed += 1
|
||||
end
|
||||
end
|
||||
@ -96,10 +85,10 @@ module Jobs
|
||||
return topic
|
||||
end
|
||||
|
||||
def send_invite(csv_info, csv_line_number)
|
||||
email = csv_info[0]
|
||||
groups = get_groups(csv_info[1], csv_line_number)
|
||||
topic = get_topic(csv_info[2], csv_line_number)
|
||||
def send_invite(invite)
|
||||
email = invite[:email]
|
||||
groups = get_groups(invite[:groups])
|
||||
topic = get_topic(invite[:topic_id])
|
||||
|
||||
begin
|
||||
if user = User.find_by_email(email)
|
||||
@ -171,7 +160,5 @@ module Jobs
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -242,14 +242,6 @@ class Invite < ActiveRecord::Base
|
||||
def self.base_directory
|
||||
File.join(Rails.root, "public", "uploads", "csv", RailsMultisite::ConnectionManagement.current_db)
|
||||
end
|
||||
|
||||
def self.create_csv(file, name)
|
||||
extension = File.extname(file.original_filename)
|
||||
path = "#{Invite.base_directory}/#{name}#{extension}"
|
||||
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
||||
File.open(path, "wb") { |f| f << file.tempfile.read }
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
Reference in New Issue
Block a user