mirror of
https://github.com/discourse/discourse.git
synced 2024-11-24 13:18:33 +08:00
e704f0a541
When bulk inviting, the uploaded CSV file may contain wrong values for the user fields. This tries to automatically correct them by finding the most similar option (by ignoring the case).
214 lines
5.2 KiB
Ruby
214 lines
5.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Jobs
|
|
class BulkInvite < ::Jobs::Base
|
|
sidekiq_options retry: false
|
|
|
|
def initialize
|
|
super
|
|
|
|
@logs = []
|
|
@sent = 0
|
|
@failed = 0
|
|
@groups = {}
|
|
@user_fields = {}
|
|
@valid_groups = {}
|
|
end
|
|
|
|
def execute(args)
|
|
@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)
|
|
|
|
process_invites(@invites)
|
|
|
|
if @invites.length > Invite::BULK_INVITE_EMAIL_LIMIT
|
|
::Jobs.enqueue(:process_bulk_invite_emails)
|
|
end
|
|
ensure
|
|
notify_user
|
|
end
|
|
|
|
private
|
|
|
|
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
|
|
end
|
|
|
|
def get_groups(group_names)
|
|
groups = []
|
|
|
|
if group_names
|
|
group_names = group_names.split(';')
|
|
|
|
group_names.each { |group_name|
|
|
group = fetch_group(group_name)
|
|
|
|
if group && can_edit_group?(group)
|
|
# valid group
|
|
groups.push(group)
|
|
else
|
|
# invalid group
|
|
save_log "Invalid Group '#{group_name}'"
|
|
@failed += 1
|
|
end
|
|
}
|
|
end
|
|
|
|
groups
|
|
end
|
|
|
|
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}'"
|
|
@failed += 1
|
|
end
|
|
end
|
|
|
|
topic
|
|
end
|
|
|
|
def get_user_fields(fields)
|
|
user_fields = {}
|
|
|
|
fields.each do |key, value|
|
|
@user_fields[key] ||= UserField.includes(:user_field_options).where('name ILIKE ?', key).first || :nil
|
|
next if @user_fields[key] == :nil
|
|
|
|
# Automatically correct user field value
|
|
if @user_fields[key].field_type == "dropdown"
|
|
value = @user_fields[key].user_field_options.find { |ufo| ufo.value.casecmp?(value) }&.value
|
|
end
|
|
|
|
user_fields[@user_fields[key].id] = value
|
|
end
|
|
|
|
user_fields
|
|
end
|
|
|
|
def send_invite(invite)
|
|
email = invite[:email]
|
|
groups = get_groups(invite[:groups])
|
|
topic = get_topic(invite[:topic_id])
|
|
user_fields = get_user_fields(invite.except(:email, :groups, :topic_id))
|
|
|
|
begin
|
|
if user = Invite.find_user_by_email(email)
|
|
if groups.present?
|
|
Group.transaction do
|
|
groups.each do |group|
|
|
group.add(user)
|
|
|
|
GroupActionLogger
|
|
.new(@current_user, group)
|
|
.log_add_user_to_group(user)
|
|
end
|
|
end
|
|
end
|
|
|
|
if user_fields.present?
|
|
user_fields.each do |user_field, value|
|
|
user.set_user_field(user_field, value)
|
|
end
|
|
user.save_custom_fields
|
|
end
|
|
else
|
|
if user_fields.present?
|
|
user = User.where(staged: true).find_by_email(email)
|
|
user ||= User.new(username: UserNameSuggester.suggest(email), email: email, staged: true)
|
|
user_fields.each do |user_field, value|
|
|
user.set_user_field(user_field, value)
|
|
end
|
|
user.save!
|
|
end
|
|
|
|
invite_opts = {
|
|
email: email,
|
|
topic: topic,
|
|
group_ids: groups.map(&:id),
|
|
}
|
|
|
|
if @invites.length > Invite::BULK_INVITE_EMAIL_LIMIT
|
|
invite_opts[:emailed_status] = Invite.emailed_status_types[:bulk_pending]
|
|
end
|
|
|
|
Invite.generate(@current_user, invite_opts)
|
|
end
|
|
rescue => e
|
|
save_log "Error inviting '#{email}' -- #{Rails::Html::FullSanitizer.new.sanitize(e.message)}"
|
|
@sent -= 1
|
|
@failed += 1
|
|
end
|
|
end
|
|
|
|
def save_log(message)
|
|
@logs << "[#{Time.now}] #{message}"
|
|
end
|
|
|
|
def notify_user
|
|
if @current_user
|
|
if (@sent > 0 && @failed == 0)
|
|
SystemMessage.create_from_system_user(
|
|
@current_user,
|
|
:bulk_invite_succeeded,
|
|
sent: @sent
|
|
)
|
|
else
|
|
SystemMessage.create_from_system_user(
|
|
@current_user,
|
|
:bulk_invite_failed,
|
|
sent: @sent,
|
|
failed: @failed,
|
|
logs: @logs.join("\n")
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
def fetch_group(group_name)
|
|
group_name = group_name.downcase
|
|
group = @groups[group_name]
|
|
|
|
unless group
|
|
group = Group.find_by('lower(name) = ?', group_name)
|
|
@groups[group_name] = group
|
|
end
|
|
|
|
group
|
|
end
|
|
|
|
def can_edit_group?(group)
|
|
group_name = group.name.downcase
|
|
result = @valid_groups[group_name]
|
|
|
|
unless result
|
|
result = @guardian.can_edit_group?(group)
|
|
@valid_groups[group_name] = result
|
|
end
|
|
|
|
result
|
|
end
|
|
end
|
|
end
|