From 9322052f9d62bf9f367c3f17ee93d70266524f6c Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Mon, 10 Oct 2022 15:27:42 +0200 Subject: [PATCH] Add logic for user role updates for team child objects [SCI-7292] --- .../remove_team_user_assignment_job.rb | 13 +++++ .../remove_user_assignment_job.rb | 16 ------ .../update_team_user_assignment_job.rb | 13 +++++ app/models/concerns/assignable.rb | 4 ++ app/models/user_assignment.rb | 11 +++- .../remove_team_user_assignment_service.rb | 55 +++++++++++++++++++ .../update_team_user_assignment_service.rb | 55 +++++++++++++++++++ 7 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 app/jobs/user_assignments/remove_team_user_assignment_job.rb delete mode 100644 app/jobs/user_assignments/remove_user_assignment_job.rb create mode 100644 app/jobs/user_assignments/update_team_user_assignment_job.rb create mode 100644 app/services/user_assignments/remove_team_user_assignment_service.rb create mode 100644 app/services/user_assignments/update_team_user_assignment_service.rb diff --git a/app/jobs/user_assignments/remove_team_user_assignment_job.rb b/app/jobs/user_assignments/remove_team_user_assignment_job.rb new file mode 100644 index 000000000..6e82a52ff --- /dev/null +++ b/app/jobs/user_assignments/remove_team_user_assignment_job.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module UserAssignments + class RemoveTeamUserAssignmentJob < ApplicationJob + queue_as :high_priority + + def perform(user, team) + ActiveRecord::Base.transaction do + RemoveTeamUserAssignmentService.new(user, team).call + end + end + end +end diff --git a/app/jobs/user_assignments/remove_user_assignment_job.rb b/app/jobs/user_assignments/remove_user_assignment_job.rb deleted file mode 100644 index d03d13325..000000000 --- a/app/jobs/user_assignments/remove_user_assignment_job.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -module UserAssignments - class RemoveUserAssignmentJob < ApplicationJob - queue_as :high_priority - - def perform(user, team) - ActiveRecord::Base.transaction do - team.projects.each do |project| - UserAssignments::PropagateAssignmentJob - .perform_now(project, user, nil, nil, destroy: true, remove_from_team: true) - end - end - end - end -end diff --git a/app/jobs/user_assignments/update_team_user_assignment_job.rb b/app/jobs/user_assignments/update_team_user_assignment_job.rb new file mode 100644 index 000000000..29c75ca3c --- /dev/null +++ b/app/jobs/user_assignments/update_team_user_assignment_job.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module UserAssignments + class UpdateTeamUserAssignmentJob < ApplicationJob + queue_as :high_priority + + def perform(user, team, user_role) + ActiveRecord::Base.transaction do + UpdateTeamUserAssignmentService.new(user, team, user_role).call + end + end + end +end diff --git a/app/models/concerns/assignable.rb b/app/models/concerns/assignable.rb index ab65aa0fd..10b0671c6 100644 --- a/app/models/concerns/assignable.rb +++ b/app/models/concerns/assignable.rb @@ -9,6 +9,10 @@ module Assignable attr_accessor :skip_user_assignments has_many :user_assignments, as: :assignable, dependent: :destroy + has_many :automatic_user_assignments, -> { automatically_assigned }, + as: :assignable, + class_name: 'UserAssignment', + inverse_of: :assignable scope :readable_by_user, lambda { |user| joins(user_assignments: :user_role) diff --git a/app/models/user_assignment.rb b/app/models/user_assignment.rb index 8271dee63..dec881e50 100644 --- a/app/models/user_assignment.rb +++ b/app/models/user_assignment.rb @@ -4,8 +4,9 @@ class UserAssignment < ApplicationRecord before_validation -> { self.team ||= (assignable.is_a?(Team) ? assignable : assignable.team) } after_create :assign_shared_inventories, if: -> { assignable.is_a?(Team) } after_create :assign_public_projects, if: -> { assignable.is_a?(Team) } + after_update :update_team_children_assignments, if: -> { assignable.is_a?(Team) && saved_change_to_user_role_id? } before_destroy :unassign_shared_inventories, if: -> { assignable.is_a?(Team) } - before_destroy :unassign_public_projects, if: -> { assignable.is_a?(Team) } + before_destroy :unassign_team_child_objects, if: -> { assignable.is_a?(Team) } belongs_to :assignable, polymorphic: true, touch: true belongs_to :user_role @@ -50,11 +51,15 @@ class UserAssignment < ApplicationRecord end end + def update_team_children_assignments + UserAssignments::UpdateTeamUserAssignmentService.new(user, assignable, user_role).call + end + def unassign_shared_inventories assignable.repository_sharing_user_assignments.where(user: user).find_each(&:destroy!) end - def unassign_public_projects - UserAssignments::RemoveUserAssignmentJob.perform_now(user, assignable) + def unassign_team_child_objects + UserAssignments::RemoveTeamUserAssignmentService.new(user, assignable).call end end diff --git a/app/services/user_assignments/remove_team_user_assignment_service.rb b/app/services/user_assignments/remove_team_user_assignment_service.rb new file mode 100644 index 000000000..403f1ae60 --- /dev/null +++ b/app/services/user_assignments/remove_team_user_assignment_service.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module UserAssignments + class RemoveTeamUserAssignmentService + def initialize(user, team) + @user = user + @team = team + end + + def call + @team.projects.find_each do |project| + UserAssignments::PropagateAssignmentJob + .perform_now(project, @user, nil, nil, destroy: true, remove_from_team: true) + end + remove_repositories_assignments + remove_protocols_assignments + remove_reports_assignments + end + + private + + def remove_repositories_assignments + @team.repositories + .joins(:user_assignments) + .preload(:user_assignments) + .where(user_assignments: { user: @user, team: @team }).find_each do |repository| + repository.user_assignments + .select { |assignment| assignment.user_id == @user.id && assignment.team_id == @team.id } + .each(&:destroy!) + end + end + + def remove_protocols_assignments + @team.repository_protocols + .joins(:user_assignments) + .preload(:user_assignments) + .where(user_assignments: { user: @user }).find_each do |protocol| + protocol.user_assignments + .select { |assignment| assignment.user_id == @user.id } + .each(&:destroy!) + end + end + + def remove_reports_assignments + @team.reports + .joins(:user_assignments) + .preload(:user_assignments) + .where(user_assignments: { user: @user }).find_each do |report| + report.user_assignments + .select { |assignment| assignment.user_id == @user.id } + .each(&:destroy!) + end + end + end +end diff --git a/app/services/user_assignments/update_team_user_assignment_service.rb b/app/services/user_assignments/update_team_user_assignment_service.rb new file mode 100644 index 000000000..7a29251fe --- /dev/null +++ b/app/services/user_assignments/update_team_user_assignment_service.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module UserAssignments + class UpdateTeamUserAssignmentService + def initialize(user, team, user_role) + @user = user + @team = team + @user_role = user_role + end + + def call + update_repositories_assignments + update_protocols_assignments + update_reports_assignments + end + + private + + def update_repositories_assignments + @team.repositories + .joins(:automatic_user_assignments) + .preload(:automatic_user_assignments) + .where(automatic_user_assignments: { user: @user, team: @team }) + .find_each do |repository| + repository.automatic_user_assignments + .select { |assignment| assignment.user_id == @user.id && assignment.team_id == @team.id } + .each { |assignment| assignment.update!(user_role: @user_role) } + end + end + + def update_protocols_assignments + @team.repository_protocols + .joins(:automatic_user_assignments) + .preload(:automatic_user_assignments) + .where(automatic_user_assignments: { user: @user }) + .find_each do |protocol| + protocol.automatic_user_assignments + .select { |assignment| assignment.user_id == @user.id } + .each { |assignment| assignment.update!(user_role: @user_role) } + end + end + + def update_reports_assignments + @team.reports + .joins(:automatic_user_assignments) + .preload(:automatic_user_assignments) + .where(automatic_user_assignments: { user: @user }) + .find_each do |report| + report.automatic_user_assignments + .select { |assignment| assignment.user_id == @user.id && assignment.automatically_assigned? } + .each { |assignment| assignment.update!(user_role: @user_role) } + end + end + end +end