2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-05-28 04:14:37 +08:00
|
|
|
module Jobs
|
2019-10-02 12:01:53 +08:00
|
|
|
class BulkInvite < ::Jobs::Base
|
2014-05-28 04:14:37 +08:00
|
|
|
sidekiq_options retry: false
|
|
|
|
|
|
|
|
def initialize
|
2018-08-30 15:34:58 +08:00
|
|
|
super
|
2021-03-29 19:03:19 +08:00
|
|
|
|
|
|
|
@logs = []
|
|
|
|
@sent = 0
|
|
|
|
@failed = 0
|
|
|
|
@groups = {}
|
|
|
|
@user_fields = {}
|
2019-04-16 09:31:51 +08:00
|
|
|
@valid_groups = {}
|
2014-05-28 04:14:37 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def execute(args)
|
2021-03-29 19:03:19 +08:00
|
|
|
@invites = args[:invites]
|
|
|
|
raise Discourse::InvalidParameters.new(:invites) if @invites.blank?
|
2019-04-15 21:13:53 +08:00
|
|
|
|
|
|
|
@current_user = User.find_by(id: args[:current_user_id])
|
|
|
|
raise Discourse::InvalidParameters.new(:current_user_id) unless @current_user
|
2021-03-29 19:03:19 +08:00
|
|
|
|
2019-04-16 09:31:51 +08:00
|
|
|
@guardian = Guardian.new(@current_user)
|
2019-04-15 21:13:53 +08:00
|
|
|
|
2021-03-29 19:03:19 +08:00
|
|
|
process_invites(@invites)
|
2019-07-19 13:59:12 +08:00
|
|
|
|
2021-03-29 19:03:19 +08:00
|
|
|
if @invites.length > Invite::BULK_INVITE_EMAIL_LIMIT
|
2019-10-22 01:25:35 +08:00
|
|
|
::Jobs.enqueue(:process_bulk_invite_emails)
|
2019-07-19 13:59:12 +08:00
|
|
|
end
|
2016-10-18 03:00:29 +08:00
|
|
|
ensure
|
2014-06-26 04:04:26 +08:00
|
|
|
notify_user
|
2014-06-26 02:35:11 +08:00
|
|
|
end
|
|
|
|
|
2019-04-15 21:13:53 +08:00
|
|
|
private
|
|
|
|
|
2019-06-04 22:49:46 +08:00
|
|
|
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
|
2014-05-28 04:14:37 +08:00
|
|
|
end
|
|
|
|
end
|
2016-10-18 03:00:29 +08:00
|
|
|
rescue Exception => e
|
2018-08-30 15:34:58 +08:00
|
|
|
save_log "Bulk Invite Process Failed -- '#{e.message}'"
|
2016-10-18 03:00:29 +08:00
|
|
|
@failed += 1
|
2014-05-28 04:14:37 +08:00
|
|
|
end
|
|
|
|
|
2019-06-04 22:49:46 +08:00
|
|
|
def get_groups(group_names)
|
2019-04-15 21:26:03 +08:00
|
|
|
groups = []
|
2019-04-15 21:13:53 +08:00
|
|
|
|
2014-06-27 01:19:34 +08:00
|
|
|
if group_names
|
2014-06-26 23:16:53 +08:00
|
|
|
group_names = group_names.split(';')
|
2019-04-15 21:13:53 +08:00
|
|
|
|
2014-06-26 23:16:53 +08:00
|
|
|
group_names.each { |group_name|
|
2019-04-16 09:31:51 +08:00
|
|
|
group = fetch_group(group_name)
|
2019-04-15 21:13:53 +08:00
|
|
|
|
2019-04-16 09:31:51 +08:00
|
|
|
if group && can_edit_group?(group)
|
2014-06-26 23:16:53 +08:00
|
|
|
# valid group
|
2019-04-16 09:31:51 +08:00
|
|
|
groups.push(group)
|
2014-06-26 23:16:53 +08:00
|
|
|
else
|
|
|
|
# invalid group
|
2019-06-04 22:49:46 +08:00
|
|
|
save_log "Invalid Group '#{group_name}'"
|
2014-06-27 01:19:34 +08:00
|
|
|
@failed += 1
|
2014-06-26 23:16:53 +08:00
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
2019-04-15 21:26:03 +08:00
|
|
|
|
|
|
|
groups
|
2014-05-28 04:14:37 +08:00
|
|
|
end
|
|
|
|
|
2019-06-04 22:49:46 +08:00
|
|
|
def get_topic(topic_id)
|
2014-06-26 23:16:53 +08:00
|
|
|
topic = nil
|
2019-04-15 21:26:03 +08:00
|
|
|
|
2014-06-27 01:19:34 +08:00
|
|
|
if topic_id
|
2014-06-26 23:16:53 +08:00
|
|
|
topic = Topic.find_by_id(topic_id)
|
|
|
|
if topic.nil?
|
2019-06-04 22:49:46 +08:00
|
|
|
save_log "Invalid Topic ID '#{topic_id}'"
|
2014-06-27 01:19:34 +08:00
|
|
|
@failed += 1
|
2014-06-26 02:35:11 +08:00
|
|
|
end
|
2014-06-26 23:16:53 +08:00
|
|
|
end
|
2019-04-15 21:26:03 +08:00
|
|
|
|
2019-11-15 04:10:51 +08:00
|
|
|
topic
|
2014-06-26 02:35:11 +08:00
|
|
|
end
|
|
|
|
|
2021-03-29 19:03:19 +08:00
|
|
|
def get_user_fields(fields)
|
|
|
|
user_fields = {}
|
|
|
|
|
|
|
|
fields.each do |key, value|
|
2021-04-01 00:19:57 +08:00
|
|
|
@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
|
2021-03-29 19:03:19 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
user_fields
|
|
|
|
end
|
|
|
|
|
2019-06-04 22:49:46 +08:00
|
|
|
def send_invite(invite)
|
|
|
|
email = invite[:email]
|
|
|
|
groups = get_groups(invite[:groups])
|
|
|
|
topic = get_topic(invite[:topic_id])
|
2021-03-29 19:03:19 +08:00
|
|
|
user_fields = get_user_fields(invite.except(:email, :groups, :topic_id))
|
2019-04-15 21:26:03 +08:00
|
|
|
|
2014-10-09 22:44:15 +08:00
|
|
|
begin
|
2019-10-30 14:08:47 +08:00
|
|
|
if user = Invite.find_user_by_email(email)
|
2019-04-15 21:26:03 +08:00
|
|
|
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
|
2021-03-29 19:03:19 +08:00
|
|
|
|
|
|
|
if user_fields.present?
|
|
|
|
user_fields.each do |user_field, value|
|
|
|
|
user.set_user_field(user_field, value)
|
|
|
|
end
|
|
|
|
user.save_custom_fields
|
|
|
|
end
|
2019-04-15 21:26:03 +08:00
|
|
|
else
|
2021-03-29 19:03:19 +08:00
|
|
|
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!
|
2019-07-19 13:59:12 +08:00
|
|
|
end
|
2021-03-29 19:03:19 +08:00
|
|
|
|
|
|
|
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)
|
2019-04-15 21:26:03 +08:00
|
|
|
end
|
2014-10-09 22:44:15 +08:00
|
|
|
rescue => e
|
2018-08-30 15:34:58 +08:00
|
|
|
save_log "Error inviting '#{email}' -- #{Rails::Html::FullSanitizer.new.sanitize(e.message)}"
|
2014-10-09 22:44:15 +08:00
|
|
|
@sent -= 1
|
|
|
|
@failed += 1
|
|
|
|
end
|
2014-06-26 02:35:11 +08:00
|
|
|
end
|
|
|
|
|
2014-05-28 04:14:37 +08:00
|
|
|
def save_log(message)
|
|
|
|
@logs << "[#{Time.now}] #{message}"
|
|
|
|
end
|
|
|
|
|
2014-06-26 04:04:26 +08:00
|
|
|
def notify_user
|
|
|
|
if @current_user
|
2014-05-28 04:14:37 +08:00
|
|
|
if (@sent > 0 && @failed == 0)
|
2018-08-30 15:34:58 +08:00
|
|
|
SystemMessage.create_from_system_user(
|
|
|
|
@current_user,
|
|
|
|
:bulk_invite_succeeded,
|
|
|
|
sent: @sent
|
|
|
|
)
|
2014-05-28 04:14:37 +08:00
|
|
|
else
|
2018-08-30 15:34:58 +08:00
|
|
|
SystemMessage.create_from_system_user(
|
|
|
|
@current_user,
|
|
|
|
:bulk_invite_failed,
|
|
|
|
sent: @sent,
|
|
|
|
failed: @failed,
|
|
|
|
logs: @logs.join("\n")
|
|
|
|
)
|
2014-05-28 04:14:37 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-04-16 09:31:51 +08:00
|
|
|
def fetch_group(group_name)
|
|
|
|
group_name = group_name.downcase
|
|
|
|
group = @groups[group_name]
|
|
|
|
|
|
|
|
unless group
|
2021-03-29 19:03:19 +08:00
|
|
|
group = Group.find_by('lower(name) = ?', group_name)
|
2019-04-16 09:31:51 +08:00
|
|
|
@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
|
2014-05-28 04:14:37 +08:00
|
|
|
end
|
|
|
|
end
|