diff options
Diffstat (limited to 'app/services/concerns/members/bulk_create_users.rb')
-rw-r--r-- | app/services/concerns/members/bulk_create_users.rb | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/app/services/concerns/members/bulk_create_users.rb b/app/services/concerns/members/bulk_create_users.rb new file mode 100644 index 00000000000..4498f40c396 --- /dev/null +++ b/app/services/concerns/members/bulk_create_users.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +module Members + module BulkCreateUsers + extend ActiveSupport::Concern + + included do + class << self + def add_users(source, users, access_level, current_user: nil, expires_at: nil) + return [] unless users.present? + + emails, users, existing_members = parse_users_list(source, users) + + Member.transaction do + (emails + users).map! do |user| + new(source, + user, + access_level, + existing_members: existing_members, + current_user: current_user, + expires_at: expires_at) + .execute + end + end + end + + private + + def parse_users_list(source, list) + emails = [] + user_ids = [] + users = [] + existing_members = {} + + list.each do |item| + case item + when User + users << item + when Integer + user_ids << item + when /\A\d+\Z/ + user_ids << item.to_i + when Devise.email_regexp + emails << item + end + end + + if user_ids.present? + # the below will automatically discard invalid user_ids + users.concat(User.id_in(user_ids)) + # helps not have to perform another query per user id to see if the member exists later on when fetching + existing_members = source.members_and_requesters.where(user_id: user_ids).index_by(&:user_id) # rubocop:disable CodeReuse/ActiveRecord + end + + users.uniq! # de-duplicate just in case as there is no controlling if user records and ids are sent multiple times + + [emails, users, existing_members] + end + end + end + + def initialize(source, user, access_level, **args) + super + + @existing_members = args[:existing_members] || (raise ArgumentError, "existing_members must be included in the args hash") + end + + private + + attr_reader :existing_members + + def find_or_initialize_member_by_user + existing_members[user.id] || source.members.build(user_id: user.id) + end + end +end |