140 lines
5.3 KiB
Ruby
140 lines
5.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# Copyright (C) 2017 - present Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
module SIS
|
|
class AdminImporter < BaseImporter
|
|
def process
|
|
importer = Work.new(@batch, @root_account, @logger)
|
|
|
|
AccountUser.suspend_callbacks(:clear_user_cache) do
|
|
User.skip_updating_account_associations do
|
|
yield importer
|
|
end
|
|
end
|
|
|
|
User.update_account_associations(importer.account_users_to_update_associations.to_a)
|
|
user_ids = []
|
|
importer.account_users_to_set_batch_id.to_a.in_groups_of(1000, false) do |admins|
|
|
user_ids += AccountUser.where(:id => admins).distinct.pluck(:user_id)
|
|
AccountUser.where(id: admins).update_all(sis_batch_id: @batch.id, updated_at: Time.now.utc)
|
|
end
|
|
User.clear_cache_keys(user_ids, :account_users)
|
|
SisBatchRollBackData.bulk_insert_roll_back_data(importer.roll_back_data)
|
|
|
|
importer.success_count
|
|
end
|
|
|
|
class Work
|
|
attr_accessor :success_count, :roll_back_data,
|
|
:account_users_to_update_associations,
|
|
:account_users_to_set_batch_id
|
|
|
|
def initialize(batch, root_account, logger)
|
|
@batch = batch
|
|
@root_account = root_account
|
|
@account = root_account
|
|
@logger = logger
|
|
@success_count = 0
|
|
@roll_back_data = []
|
|
@account_users_to_update_associations = Set.new
|
|
@account_users_to_set_batch_id = Set.new
|
|
@account_roles_by_account_id = {}
|
|
end
|
|
|
|
def process_admin(user_id: nil, account_id: nil, role_id: nil, role: nil, status: nil, root_account: nil)
|
|
raise ImportError, "No user_id given for admin" if user_id.blank?
|
|
raise ImportError, "No status given for admin" if status.blank?
|
|
raise ImportError, "No role_id or role given for admin" if role.blank? && role_id.blank?
|
|
|
|
state = status.downcase.strip
|
|
raise ImportError, "Invalid status #{status} for admin" unless %w(active deleted).include? state
|
|
return if @batch.skip_deletes? && state == 'deleted'
|
|
|
|
get_account(account_id)
|
|
raise ImportError, "Invalid account_id given for admin" unless @account
|
|
|
|
get_role(role_id, role)
|
|
raise ImportError, "Invalid role '#{role}' for admin" if role.present? && !@role
|
|
raise ImportError, "Invalid role_id '#{role_id}' for admin" if role_id.present? && !@role
|
|
|
|
the_root_account = root_account_from_id(root_account) if root_account
|
|
raise ImportError, "Invalid or unknown user_id '#{user_id}' for admin" if root_account && !the_root_account
|
|
|
|
the_root_account ||= @root_account
|
|
|
|
user = get_user(user_id, the_root_account)
|
|
raise ImportError, "Invalid or unknown user_id '#{user_id}' for admin" unless user
|
|
|
|
if state == 'deleted' && user.id == @batch&.user_id && @account == @root_account
|
|
raise ImportError, "Can't remove yourself user_id '#{user_id}'"
|
|
end
|
|
|
|
create_or_find_admin(user, state)
|
|
@success_count += 1
|
|
end
|
|
|
|
def create_or_find_admin(user, state)
|
|
if state == 'active'
|
|
admin = @account.account_users.where(user: user, role: @role).first_or_initialize
|
|
admin.workflow_state = state
|
|
elsif state == 'deleted'
|
|
admin = @account.account_users.where(user: user, role: @role).where.not(sis_batch_id: nil).take
|
|
return unless admin
|
|
|
|
admin.workflow_state = state
|
|
end
|
|
|
|
if admin.new_record? || admin.workflow_state_changed?
|
|
@account_users_to_update_associations.add(user.id)
|
|
admin.save!
|
|
data = SisBatchRollBackData.build_data(sis_batch: @batch, context: admin)
|
|
@roll_back_data << data if data
|
|
end
|
|
@account_users_to_set_batch_id.add(admin.id)
|
|
end
|
|
|
|
def get_account(account_id)
|
|
@account = nil unless @account&.sis_source_id == account_id
|
|
@account ||= @root_account.all_accounts.active.where(sis_source_id: account_id).take if account_id.present?
|
|
@account ||= @root_account if account_id.blank?
|
|
end
|
|
|
|
def get_user(user_id, root_account)
|
|
pseudonym = root_account.pseudonyms.active.where(sis_user_id: user_id).take
|
|
user = pseudonym.user if pseudonym
|
|
user
|
|
end
|
|
|
|
def root_account_from_id(root_account_sis_id)
|
|
nil
|
|
end
|
|
|
|
def get_role(role_id, role)
|
|
# cache available account roles for this account
|
|
@account_roles_by_account_id[@account.id] ||= @account.available_account_roles
|
|
|
|
@role = nil
|
|
@role = @account_roles_by_account_id[@account.id].detect { |r| r.id.to_s == role_id } if role_id
|
|
@role ||= @account_roles_by_account_id[@account.id].detect { |r| r.name == role }
|
|
end
|
|
end
|
|
end
|
|
end
|