From 65878f07215f590ef6f21c58b9286e23d51220a5 Mon Sep 17 00:00:00 2001
From: Sam Word <sword@gitlab.com>
Date: Wed, 26 Jun 2024 17:38:42 +0000
Subject: [PATCH] User mapping - Add in-app confirmation step

---
 .../import/source_users_controller.rb         |  4 ++
 app/views/import/source_users/show.html.haml  | 37 ++++++++++++++++
 config/routes/import.rb                       |  1 +
 locale/gitlab.pot                             | 39 +++++++++++++++++
 .../import/source_users_controller_spec.rb    | 42 ++++++++++++++++++-
 5 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 app/views/import/source_users/show.html.haml

diff --git a/app/controllers/import/source_users_controller.rb b/app/controllers/import/source_users_controller.rb
index 430d170013498..560dd0c88dfe9 100644
--- a/app/controllers/import/source_users_controller.rb
+++ b/app/controllers/import/source_users_controller.rb
@@ -28,6 +28,10 @@ def decline
       end
     end
 
+    def show
+      redirect_to(root_path, alert: _('The invitation is not valid')) unless source_user.awaiting_approval?
+    end
+
     private
 
     def check_current_user_matches_invite!
diff --git a/app/views/import/source_users/show.html.haml b/app/views/import/source_users/show.html.haml
new file mode 100644
index 0000000000000..81b56709dc449
--- /dev/null
+++ b/app/views/import/source_users/show.html.haml
@@ -0,0 +1,37 @@
+- title = s_('UserMapping|Approve Contributions Reassignment')
+- page_title title
+
+- source_username = @source_user.source_username
+- source_hostname = @source_user.source_hostname
+- destination_group = @source_user.namespace.name
+- reassigned_by = @source_user.reassigned_by_user
+- reassign_to_username = @source_user.reassign_to_user.username
+- reassigned_by_name = reassigned_by.name
+
+.gl-border-solid.gl-border-gray-100.gl-border-0.gl-border-b-1
+  %h1.gl-font-size-h1.gl-my-0.gl-py-4.gl-display-flex.gl-align-items-center.gl-gap-3
+    = s_('UserMapping|Approve reassignment of contributions from %{source_username} on %{source_hostname} to you on %{destination_group}') % { source_username: source_username, source_hostname: source_hostname, destination_group: destination_group }
+
+.gl-border-solid.gl-border-gray-100.gl-border-0.gl-border-b-1.gl-py-4
+  %p.gl-mb-5
+    = s_('UserMapping|%{reassigned_by_name} (%{reassigned_by_username}) wants to reassign contributions made by %{source_name} (%{source_username}) on %{source_hostname} to you in %{destination_group}. Review details to approve or reject the reassignment. Learn more about reassignments') % { reassigned_by_name: reassigned_by_name, reassigned_by_username: reassigned_by.username, source_name: @source_user.source_name, source_username: source_username, source_hostname: source_hostname, destination_group: destination_group }
+  %h5
+    = s_('UserMapping|Contribution details:')
+  %p.gl-mb-5
+    = s_('UserMapping|Source: %{source_hostname}') % { source_hostname: source_hostname }
+    %br
+    = s_('UserMapping|Original user: %{source_name} (%{source_username})') % { source_name: @source_user.source_name, source_username: source_username }
+  %h5
+    = s_('UserMapping|Reassignment details:')
+  %p.gl-mb-0
+    = s_('UserMapping|Imported to: %{destination_group}') % { destination_group: destination_group }
+    %br
+    = s_('UserMapping|Reassigned to user: %{reassign_to_username}') % { reassign_to_username: reassign_to_username }
+    %br
+    = s_('UserMapping|Reassigned by: %{reassigned_by_name} (%{reassigned_by_username})') % { reassigned_by_name: reassigned_by_name, reassigned_by_username: reassigned_by.username }
+
+.actions.gl-mt-5
+  = render Pajamas::ButtonComponent.new(variant: :confirm, method: :post, href: accept_import_source_user_path(@source_user)) do
+    = s_('UserMapping|Approve reassignment')
+  = render Pajamas::ButtonComponent.new(method: :post, href: decline_import_source_user_path(@source_user)) do
+    = s_('UserMapping|Reject')
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 21664b1089989..5962a68c64a8b 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -91,6 +91,7 @@
 
   resources :source_users, only: [] do
     member do
+      get :show
       post :accept
       post :decline
     end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 45ebd303d0873..c010babd92965 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -53229,6 +53229,9 @@ msgstr ""
 msgid "The invitation has already been accepted."
 msgstr ""
 
+msgid "The invitation is not valid"
+msgstr ""
+
 msgid "The invitation was successfully resent."
 msgstr ""
 
@@ -57530,15 +57533,36 @@ msgstr ""
 msgid "UserList|created %{timeago}"
 msgstr ""
 
+msgid "UserMapping|%{reassigned_by_name} (%{reassigned_by_username}) wants to reassign contributions made by %{source_name} (%{source_username}) on %{source_hostname} to you in %{destination_group}. Review details to approve or reject the reassignment. Learn more about reassignments"
+msgstr ""
+
+msgid "UserMapping|Approve Contributions Reassignment"
+msgstr ""
+
+msgid "UserMapping|Approve reassignment"
+msgstr ""
+
+msgid "UserMapping|Approve reassignment of contributions from %{source_username} on %{source_hostname} to you on %{destination_group}"
+msgstr ""
+
 msgid "UserMapping|Awaiting reassignment"
 msgstr ""
 
+msgid "UserMapping|Contribution details:"
+msgstr ""
+
 msgid "UserMapping|Don't reassign"
 msgstr ""
 
+msgid "UserMapping|Imported to: %{destination_group}"
+msgstr ""
+
 msgid "UserMapping|Kept as placeholder"
 msgstr ""
 
+msgid "UserMapping|Original user: %{source_name} (%{source_username})"
+msgstr ""
+
 msgid "UserMapping|Pending approval"
 msgstr ""
 
@@ -57563,12 +57587,21 @@ msgstr ""
 msgid "UserMapping|Reassigned"
 msgstr ""
 
+msgid "UserMapping|Reassigned by: %{reassigned_by_name} (%{reassigned_by_username})"
+msgstr ""
+
 msgid "UserMapping|Reassigned to"
 msgstr ""
 
+msgid "UserMapping|Reassigned to user: %{reassign_to_username}"
+msgstr ""
+
 msgid "UserMapping|Reassigning"
 msgstr ""
 
+msgid "UserMapping|Reassignment details:"
+msgstr ""
+
 msgid "UserMapping|Reassignment failed."
 msgstr ""
 
@@ -57590,12 +57623,18 @@ msgstr ""
 msgid "UserMapping|Reassignment was rejected by user."
 msgstr ""
 
+msgid "UserMapping|Reject"
+msgstr ""
+
 msgid "UserMapping|Rejected"
 msgstr ""
 
 msgid "UserMapping|Select user"
 msgstr ""
 
+msgid "UserMapping|Source: %{source_hostname}"
+msgstr ""
+
 msgid "UserProfile|%{count} %{file}"
 msgstr ""
 
diff --git a/spec/requests/import/source_users_controller_spec.rb b/spec/requests/import/source_users_controller_spec.rb
index 54070b6029af4..e55b0cfac3ed6 100644
--- a/spec/requests/import/source_users_controller_spec.rb
+++ b/spec/requests/import/source_users_controller_spec.rb
@@ -25,7 +25,9 @@
     end
   end
 
-  let_it_be_with_reload(:source_user) { create(:import_source_user, :with_reassign_to_user, :awaiting_approval) }
+  let_it_be_with_reload(:source_user) do
+    create(:import_source_user, :with_reassign_to_user, :with_reassigned_by_user, :awaiting_approval)
+  end
 
   describe 'POST /accept' do
     let(:path) { accept_import_source_user_path(source_user) }
@@ -101,4 +103,42 @@
     it_behaves_like 'it requires feature flag'
     it_behaves_like 'it requires the user to be signed in'
   end
+
+  describe 'GET /show' do
+    let(:path) { import_source_user_path(source_user) }
+
+    subject(:show_invite) { get path }
+
+    context 'when signed in' do
+      before do
+        sign_in(source_user.reassign_to_user)
+      end
+
+      it 'returns a 200 response' do
+        show_invite
+
+        expect(response).to have_gitlab_http_status(:success)
+      end
+
+      it 'shows the reassignment invite only to reassign_to_user' do
+        source_user.update!(reassign_to_user: create(:user))
+
+        show_invite
+
+        expect(response).to have_gitlab_http_status(:not_found)
+      end
+
+      it 'is only valid to source users awaiting approval' do
+        source_user.accept!
+
+        show_invite
+
+        expect(response).to redirect_to(root_path)
+        expect(flash[:alert]).to match(/The invitation is not valid/)
+      end
+    end
+
+    it_behaves_like 'it requires feature flag'
+    it_behaves_like 'it requires the user to be signed in'
+  end
 end
-- 
GitLab