From bb461e866642a2041b2d711cb15fbc19f2834d47 Mon Sep 17 00:00:00 2001
From: Eugie Limpin <elimpin@gitlab.com>
Date: Thu, 4 Apr 2024 01:55:11 +0000
Subject: [PATCH] Move reusable Identity Verification controller code to a base
 controller
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Currently users go through identity verification process as part of the
registration process. Moving forward, we want to allow users that have
already started using Gitlab to go through identity verification to
complete verification methods–phone number and/or credit card
verification–that they didn't go through during registration in exchange
for in-app benefits (e.g. more CI minutes).

Here, we move controller code that are only relevant to identity
verification during registration to a new
RegistrationsIdentityVerificationController module and move all reusable
controller code from IdentityVerificationController to a new
BaseIdentityVerificationController module.
---
 .gitlab/CODEOWNERS                            |   4 +-
 .../layout/line_continuation_spacing.yml      |   1 -
 ...e_end_string_concatenation_indentation.yml |   1 -
 .../lint/assignment_in_condition.yml          |   1 -
 doc/development/identity_verification.md      |   2 +-
 .../users/identity_verification/show/index.js |   3 -
 .../arkose_labs_challenge/index.js            |   0
 .../show}/index.js                            |   0
 .../ee/omniauth_callbacks_controller.rb       |   4 +-
 ... base_identity_verification_controller.rb} | 145 ++----------------
 ...ations_identity_verification_controller.rb | 126 +++++++++++++++
 .../arkose_labs_challenge.html.haml           |   0
 .../show.html.haml                            |   0
 .../success.html.haml                         |   0
 ee/config/routes/identity_verification.rb     |   2 +-
 ee/lib/ee/gitlab/etag_caching/router/rails.rb |   2 +-
 .../arkose_content_security_policy_spec.rb    |   3 +-
 ..._identity_verification_controller_spec.rb} |  33 ++--
 .../show.html.haml_spec.rb                    |   4 +-
 .../success.html.haml_spec.rb                 |   2 +-
 20 files changed, 169 insertions(+), 164 deletions(-)
 delete mode 100644 ee/app/assets/javascripts/pages/users/identity_verification/show/index.js
 rename ee/app/assets/javascripts/pages/users/{identity_verification => registrations_identity_verification}/arkose_labs_challenge/index.js (100%)
 rename ee/app/assets/javascripts/pages/users/{identity_verification => registrations_identity_verification/show}/index.js (100%)
 rename ee/app/controllers/users/{identity_verification_controller.rb => base_identity_verification_controller.rb} (65%)
 create mode 100644 ee/app/controllers/users/registrations_identity_verification_controller.rb
 rename ee/app/views/users/{identity_verification => registrations_identity_verification}/arkose_labs_challenge.html.haml (100%)
 rename ee/app/views/users/{identity_verification => registrations_identity_verification}/show.html.haml (100%)
 rename ee/app/views/users/{identity_verification => registrations_identity_verification}/success.html.haml (100%)
 rename ee/spec/requests/users/{identity_verification_controller_spec.rb => registrations_identity_verification_controller_spec.rb} (97%)
 rename ee/spec/views/users/{identity_verification => registrations_identity_verification}/show.html.haml_spec.rb (55%)
 rename ee/spec/views/users/{identity_verification => registrations_identity_verification}/success.html.haml_spec.rb (83%)

diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 0b21628174116..e014ba4390c25 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -1181,7 +1181,7 @@ lib/gitlab/checks/**
 /ee/app/controllers/groups/scim_oauth_controller.rb
 /ee/app/controllers/oauth/
 /ee/app/controllers/omniauth_kerberos_controller.rb
-/ee/app/controllers/users/identity_verification_controller.rb
+/ee/app/controllers/users/registrations_identity_verification_controller.rb
 /ee/app/finders/auth/
 /ee/app/helpers/ee/access_tokens_helper.rb
 /ee/app/helpers/ee/auth_helper.rb
@@ -1499,7 +1499,7 @@ ee/lib/ee/api/entities/project.rb
 /ee/spec/frontend/**/remote_development/
 
 ^[Govern::Anti-abuse] @gitlab-org/modelops/anti-abuse
-/ee/app/controllers/users/identity_verification_controller.rb
+/ee/app/controllers/users/registrations_identity_verification_controller.rb
 /ee/app/models/concerns/identity_verifiable.rb
 /ee/config/routes/identity_verification.rb
 
diff --git a/.rubocop_todo/layout/line_continuation_spacing.yml b/.rubocop_todo/layout/line_continuation_spacing.yml
index 200dde0ea0bcd..5e3aa8b89928c 100644
--- a/.rubocop_todo/layout/line_continuation_spacing.yml
+++ b/.rubocop_todo/layout/line_continuation_spacing.yml
@@ -87,7 +87,6 @@ Layout/LineContinuationSpacing:
     - 'ee/spec/requests/api/graphql/mutations/users/abuse/namespace_bans/destroy_spec.rb'
     - 'ee/spec/requests/api/graphql/mutations/vulnerabilities/create_external_issue_link_spec.rb'
     - 'ee/spec/requests/api/graphql/mutations/vulnerabilities/destroy_external_issue_link_spec.rb'
-    - 'ee/spec/requests/users/identity_verification_controller_spec.rb'
     - 'ee/spec/services/boards/epic_lists/destroy_service_spec.rb'
     - 'ee/spec/services/epic_issues/create_service_spec.rb'
     - 'ee/spec/services/epics/epic_links/create_service_spec.rb'
diff --git a/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml b/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml
index 1cb814ac69160..505de78b4353c 100644
--- a/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml
+++ b/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml
@@ -124,7 +124,6 @@ Layout/LineEndStringConcatenationIndentation:
     - 'ee/spec/requests/api/graphql/mutations/iterations/cadences/update_spec.rb'
     - 'ee/spec/requests/api/graphql/mutations/iterations/create_spec.rb'
     - 'ee/spec/requests/api/graphql/mutations/security/finding/create_issue_spec.rb'
-    - 'ee/spec/requests/users/identity_verification_controller_spec.rb'
     - 'ee/spec/services/boards/epic_lists/destroy_service_spec.rb'
     - 'ee/spec/services/ee/auth/container_registry_authentication_service_spec.rb'
     - 'ee/spec/services/ee/resource_events/merge_into_notes_service_spec.rb'
diff --git a/.rubocop_todo/lint/assignment_in_condition.yml b/.rubocop_todo/lint/assignment_in_condition.yml
index c348be70c9196..282fd8b705ddb 100644
--- a/.rubocop_todo/lint/assignment_in_condition.yml
+++ b/.rubocop_todo/lint/assignment_in_condition.yml
@@ -96,7 +96,6 @@ Lint/AssignmentInCondition:
     - 'config/initializers/zz_metrics.rb'
     - 'ee/app/controllers/concerns/gitlab_subscriptions/seat_count_alert.rb'
     - 'ee/app/controllers/omniauth_kerberos_controller.rb'
-    - 'ee/app/controllers/users/identity_verification_controller.rb'
     - 'ee/app/finders/ee/projects_finder.rb'
     - 'ee/app/finders/incident_management/oncall_users_finder.rb'
     - 'ee/app/graphql/mutations/boards/update_epic_user_preferences.rb'
diff --git a/doc/development/identity_verification.md b/doc/development/identity_verification.md
index caf1a8ba34ff9..decbb2daa6f27 100644
--- a/doc/development/identity_verification.md
+++ b/doc/development/identity_verification.md
@@ -31,7 +31,7 @@ To view logs associated to the [email stage](../security/identity_verification.m
 - Query the GitLab production logs with the following KQL:
 
   ```plaintext
-  KQL: json.controller:"IdentityVerificationController" AND json.username:replace_username_here
+  KQL: json.controller:"RegistrationsIdentityVerificationController" AND json.username:replace_username_here
   ```
 
 Valuable debugging information can be found in the `json.action` and `json.location` columns.
diff --git a/ee/app/assets/javascripts/pages/users/identity_verification/show/index.js b/ee/app/assets/javascripts/pages/users/identity_verification/show/index.js
deleted file mode 100644
index 1b22113c17569..0000000000000
--- a/ee/app/assets/javascripts/pages/users/identity_verification/show/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { initIdentityVerification } from 'ee/users/identity_verification';
-
-initIdentityVerification();
diff --git a/ee/app/assets/javascripts/pages/users/identity_verification/arkose_labs_challenge/index.js b/ee/app/assets/javascripts/pages/users/registrations_identity_verification/arkose_labs_challenge/index.js
similarity index 100%
rename from ee/app/assets/javascripts/pages/users/identity_verification/arkose_labs_challenge/index.js
rename to ee/app/assets/javascripts/pages/users/registrations_identity_verification/arkose_labs_challenge/index.js
diff --git a/ee/app/assets/javascripts/pages/users/identity_verification/index.js b/ee/app/assets/javascripts/pages/users/registrations_identity_verification/show/index.js
similarity index 100%
rename from ee/app/assets/javascripts/pages/users/identity_verification/index.js
rename to ee/app/assets/javascripts/pages/users/registrations_identity_verification/show/index.js
diff --git a/ee/app/controllers/ee/omniauth_callbacks_controller.rb b/ee/app/controllers/ee/omniauth_callbacks_controller.rb
index 3c93a443deee9..dae225ea6ebe6 100644
--- a/ee/app/controllers/ee/omniauth_callbacks_controller.rb
+++ b/ee/app/controllers/ee/omniauth_callbacks_controller.rb
@@ -43,8 +43,8 @@ def log_failed_login(author, provider)
     def perform_registration_tasks(user, provider)
       # We need to do this here since the subscription flow relies on what was set in the stored_location_for(:user)
       # that was set on initial redirect from the SubscriptionsController#new and super will wipe that out.
-      # Then the IdentityVerificationController#success will get whatever is set in super instead of the subscription
-      # path we desire.
+      # Then the RegistrationsIdentityVerificationController#success will get
+      # whatever is set in super instead of the subscription path we desire.
       super unless onboarding_status.subscription?
 
       # This also protects the sub classes group saml and ldap from staring onboarding
diff --git a/ee/app/controllers/users/identity_verification_controller.rb b/ee/app/controllers/users/base_identity_verification_controller.rb
similarity index 65%
rename from ee/app/controllers/users/identity_verification_controller.rb
rename to ee/app/controllers/users/base_identity_verification_controller.rb
index 0304c0a48f0c7..f41e07bfb5fe1 100644
--- a/ee/app/controllers/users/identity_verification_controller.rb
+++ b/ee/app/controllers/users/base_identity_verification_controller.rb
@@ -1,29 +1,20 @@
 # frozen_string_literal: true
 
 module Users
-  class IdentityVerificationController < ApplicationController
-    include AcceptsPendingInvitations
-    include ActionView::Helpers::DateHelper
+  class BaseIdentityVerificationController < ApplicationController
     include Arkose::ContentSecurityPolicy
     include Arkose::TokenVerifiable
+    include ActionView::Helpers::DateHelper
     include IdentityVerificationHelper
     include ::Gitlab::RackLoadBalancingHelpers
     include Recaptcha::Adapters::ControllerMethods
-    include ::Gitlab::Utils::StrongMemoize
-
-    helper_method :onboarding_status
 
     EVENT_CATEGORIES = %i[email phone credit_card error toggle_phone_exemption].freeze
     PHONE_VERIFICATION_ACTIONS = %i[send_phone_verification_code verify_phone_verification_code].freeze
     CREDIT_CARD_VERIFICATION_ACTIONS = %i[verify_credit_card].freeze
 
-    skip_before_action :authenticate_user!
-
     before_action :require_verification_user!, except: [:restricted]
-    before_action :require_unverified_user!, except: [:verification_state, :success, :restricted]
     before_action :load_captcha, :redirect_banned_user, only: [:show]
-    before_action :require_arkose_verification!, except: [:arkose_labs_challenge, :verify_arkose_labs_session,
-      :restricted]
     before_action :ensure_verification_method_attempt_allowed!,
       only: PHONE_VERIFICATION_ACTIONS + CREDIT_CARD_VERIFICATION_ACTIONS
 
@@ -51,34 +42,7 @@ def verification_state
       # if the back button is pressed, don't cache the user's identity verification state
       no_cache_headers if params['no_cache']
 
-      render json: {
-        verification_methods: @user.required_identity_verification_methods,
-        verification_state: @user.identity_verification_state
-      }
-    end
-
-    def verify_email_code
-      result = verify_token
-
-      if result[:status] == :success
-        confirm_user
-
-        render json: { status: :success }
-      else
-        log_event(:email, :failed_attempt, result[:reason])
-
-        render json: result
-      end
-    end
-
-    def resend_email_code
-      if send_rate_limited?
-        render json: { status: :failure, message: rate_limited_error_message(:email_verification_code_send) }
-      else
-        reset_confirmation_token
-
-        render json: { status: :success }
-      end
+      render json: verification_state_json
     end
 
     def send_phone_verification_code
@@ -121,34 +85,6 @@ def verify_phone_verification_code
       render json: { status: :success }
     end
 
-    def arkose_labs_challenge; end
-
-    def verify_arkose_labs_session
-      unless verify_arkose_labs_token(user: @user)
-        flash[:alert] = s_('IdentityVerification|Complete verification to sign up.')
-        return render action: :arkose_labs_challenge
-      end
-
-      service = PhoneVerification::Users::RateLimitService
-      service.assume_user_high_risk_if_daily_limit_exceeded!(@user)
-
-      redirect_to action: :show
-    end
-
-    def success
-      return redirect_to identity_verification_path unless @user.identity_verified?
-
-      accept_pending_invitations(user: @user)
-      sign_in(@user)
-      session.delete(:verification_user_id)
-
-      # order matters here because set_redirect_url removes our ability to detect trial in the tracking label
-      @tracking_label = onboarding_status.tracking_label
-
-      set_redirect_url
-      experiment(:phone_verification_for_low_risk_users, user: @user).track(:registration_completed)
-    end
-
     def verify_credit_card
       return render_404 unless json_request? && @user.credit_card_validation.present?
 
@@ -182,13 +118,11 @@ def verify_credit_card_captcha
 
     def toggle_phone_exemption
       if @user.offer_phone_number_exemption?
+
         @user.toggle_phone_number_verification
 
         log_event(:toggle_phone_exemption, :success)
-        render json: {
-          verification_methods: @user.required_identity_verification_methods,
-          verification_state: @user.identity_verification_state
-        }
+        render json: verification_state_json
       else
         log_event(:toggle_phone_exemption, :failed)
         render status: :bad_request, json: {}
@@ -197,21 +131,6 @@ def toggle_phone_exemption
 
     private
 
-    def onboarding_status
-      Onboarding::Status.new(params.to_unsafe_h.deep_symbolize_keys, session, @user)
-    end
-    strong_memoize_attr :onboarding_status
-
-    def set_redirect_url
-      @redirect_url = if onboarding_status.subscription?
-                        # Since we need this value to stay in the stored_location_for(user) in order for
-                        # us to be properly redirected for subscription signups.
-                        onboarding_status.stored_user_location
-                      else
-                        after_sign_in_path_for(@user)
-                      end
-    end
-
     def require_verification_user!
       @user = find_verification_user || current_user
 
@@ -228,8 +147,11 @@ def find_verification_user
       User.find_by_id(verification_user_id)
     end
 
-    def require_unverified_user!
-      redirect_to success_identity_verification_path if @user.identity_verified?
+    def redirect_banned_user
+      return unless @user.banned?
+
+      session.delete(:verification_user_id)
+      redirect_to new_user_session_path, alert: user_banned_error_message
     end
 
     def ensure_verification_method_attempt_allowed!
@@ -246,19 +168,11 @@ def ensure_verification_method_attempt_allowed!
       render status: :bad_request, json: {}
     end
 
-    def redirect_banned_user
-      return unless @user.banned?
-
-      session.delete(:verification_user_id)
-      redirect_to new_user_session_path, alert: user_banned_error_message
-    end
-
-    def require_arkose_verification!
-      return unless arkose_labs_enabled?(user: @user)
-      return unless @user.identities.any?
-      return if @user.arkose_verified?
-
-      redirect_to action: :arkose_labs_challenge
+    def verification_state_json
+      {
+        verification_methods: @user.required_identity_verification_methods,
+        verification_state: @user.identity_verification_state
+      }
     end
 
     def log_event(category, event, reason = nil)
@@ -279,41 +193,16 @@ def log_event(category, event, reason = nil)
       ::Gitlab::Tracking.event(category, event.to_s, property: reason.to_s, user: user)
     end
 
-    def verify_token
-      ::Users::EmailVerification::ValidateTokenService.new(
-        attr: :confirmation_token,
-        user: @user,
-        token: params.require(:identity_verification).permit(:code)[:code]
-      ).execute
-    end
-
-    def confirm_user
-      @user.confirm
-      log_event(:email, :success)
-    end
-
-    def reset_confirmation_token
-      service = ::Users::EmailVerification::GenerateTokenService.new(attr: :confirmation_token, user: @user)
-      token, encrypted_token = service.execute
-      @user.update!(confirmation_token: encrypted_token, confirmation_sent_at: Time.current)
-      Notify.confirmation_instructions_email(@user.email, token: token).deliver_later
-      log_event(:email, :sent_instructions)
-    end
-
-    def send_rate_limited?
-      ::Gitlab::ApplicationRateLimiter.throttled?(:email_verification_code_send, scope: @user)
-    end
-
     def check_for_reuse_rate_limited?
       check_rate_limit!(:credit_card_verification_check_for_reuse, scope: request.ip) { true }
     end
 
     def phone_verification_params
-      params.require(:identity_verification).permit(:country, :international_dial_code, :phone_number)
+      required_params.permit(:country, :international_dial_code, :phone_number)
     end
 
     def verify_phone_verification_code_params
-      params.require(:identity_verification).permit(:verification_code)
+      required_params.permit(:verification_code)
     end
 
     def load_captcha
diff --git a/ee/app/controllers/users/registrations_identity_verification_controller.rb b/ee/app/controllers/users/registrations_identity_verification_controller.rb
new file mode 100644
index 0000000000000..dc71840d5d4ea
--- /dev/null
+++ b/ee/app/controllers/users/registrations_identity_verification_controller.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+module Users
+  class RegistrationsIdentityVerificationController < BaseIdentityVerificationController
+    include AcceptsPendingInvitations
+    include ::Gitlab::Utils::StrongMemoize
+
+    helper_method :onboarding_status
+
+    skip_before_action :authenticate_user!
+
+    before_action :require_unverified_user!, except: [:verification_state, :success, :restricted]
+    before_action :require_arkose_verification!, except: [:arkose_labs_challenge, :verify_arkose_labs_session,
+      :restricted]
+
+    def arkose_labs_challenge; end
+
+    def verify_arkose_labs_session
+      unless verify_arkose_labs_token(user: @user)
+        flash[:alert] = s_('IdentityVerification|Complete verification to sign up.')
+        return render action: :arkose_labs_challenge
+      end
+
+      service = PhoneVerification::Users::RateLimitService
+      service.assume_user_high_risk_if_daily_limit_exceeded!(@user)
+
+      redirect_to action: :show
+    end
+
+    def verify_email_code
+      result = verify_token
+
+      if result[:status] == :success
+        confirm_user
+
+        render json: { status: :success }
+      else
+        log_event(:email, :failed_attempt, result[:reason])
+
+        render json: result
+      end
+    end
+
+    def resend_email_code
+      if send_rate_limited?
+        render json: { status: :failure, message: rate_limited_error_message(:email_verification_code_send) }
+      else
+        reset_confirmation_token
+
+        render json: { status: :success }
+      end
+    end
+
+    def success
+      return redirect_to identity_verification_path unless @user.identity_verified?
+
+      accept_pending_invitations(user: @user)
+      sign_in(@user)
+      session.delete(:verification_user_id)
+
+      # order matters here because set_redirect_url removes our ability to detect trial in the tracking label
+      @tracking_label = onboarding_status.tracking_label
+
+      set_redirect_url
+      experiment(:phone_verification_for_low_risk_users, user: @user).track(:registration_completed)
+    end
+
+    private
+
+    def require_unverified_user!
+      redirect_to success_identity_verification_path if @user.identity_verified?
+    end
+
+    def require_arkose_verification!
+      return unless arkose_labs_enabled?
+      return unless @user.identities.any?
+      return if @user.arkose_verified?
+
+      redirect_to action: :arkose_labs_challenge
+    end
+
+    def verify_token
+      ::Users::EmailVerification::ValidateTokenService.new(
+        attr: :confirmation_token,
+        user: @user,
+        token: params.require(:registrations_identity_verification).permit(:code)[:code]
+      ).execute
+    end
+
+    def confirm_user
+      @user.confirm
+      log_event(:email, :success)
+    end
+
+    def reset_confirmation_token
+      service = ::Users::EmailVerification::GenerateTokenService.new(attr: :confirmation_token, user: @user)
+      token, encrypted_token = service.execute
+      @user.update!(confirmation_token: encrypted_token, confirmation_sent_at: Time.current)
+      Notify.confirmation_instructions_email(@user.email, token: token).deliver_later
+      log_event(:email, :sent_instructions)
+    end
+
+    def send_rate_limited?
+      ::Gitlab::ApplicationRateLimiter.throttled?(:email_verification_code_send, scope: @user)
+    end
+
+    def onboarding_status
+      Onboarding::Status.new(params.to_unsafe_h.deep_symbolize_keys, session, @user)
+    end
+    strong_memoize_attr :onboarding_status
+
+    def set_redirect_url
+      @redirect_url = if onboarding_status.subscription?
+                        # Since we need this value to stay in the stored_location_for(user) in order for
+                        # us to be properly redirected for subscription signups.
+                        onboarding_status.stored_user_location
+                      else
+                        after_sign_in_path_for(@user)
+                      end
+    end
+
+    def required_params
+      params.require(controller_name.to_sym)
+    end
+  end
+end
diff --git a/ee/app/views/users/identity_verification/arkose_labs_challenge.html.haml b/ee/app/views/users/registrations_identity_verification/arkose_labs_challenge.html.haml
similarity index 100%
rename from ee/app/views/users/identity_verification/arkose_labs_challenge.html.haml
rename to ee/app/views/users/registrations_identity_verification/arkose_labs_challenge.html.haml
diff --git a/ee/app/views/users/identity_verification/show.html.haml b/ee/app/views/users/registrations_identity_verification/show.html.haml
similarity index 100%
rename from ee/app/views/users/identity_verification/show.html.haml
rename to ee/app/views/users/registrations_identity_verification/show.html.haml
diff --git a/ee/app/views/users/identity_verification/success.html.haml b/ee/app/views/users/registrations_identity_verification/success.html.haml
similarity index 100%
rename from ee/app/views/users/identity_verification/success.html.haml
rename to ee/app/views/users/registrations_identity_verification/success.html.haml
diff --git a/ee/config/routes/identity_verification.rb b/ee/config/routes/identity_verification.rb
index 6fa3607c88669..c2aeef6151b04 100644
--- a/ee/config/routes/identity_verification.rb
+++ b/ee/config/routes/identity_verification.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 scope :users, module: :users do
-  resource :identity_verification, controller: :identity_verification, only: :show do
+  resource :identity_verification, controller: :registrations_identity_verification, only: :show do
     get :verification_state
     post :verify_email_code
     post :resend_email_code
diff --git a/ee/lib/ee/gitlab/etag_caching/router/rails.rb b/ee/lib/ee/gitlab/etag_caching/router/rails.rb
index e3965f28182d4..4c4e1953ef6eb 100644
--- a/ee/lib/ee/gitlab/etag_caching/router/rails.rb
+++ b/ee/lib/ee/gitlab/etag_caching/router/rails.rb
@@ -17,7 +17,7 @@ module Rails
             [
               %r{^/users/identity_verification/verification_state\z},
               'user_identity_verification_state',
-              ::Users::IdentityVerificationController,
+              ::Users::RegistrationsIdentityVerificationController,
               :verification_state
             ]
           ].freeze
diff --git a/ee/spec/features/users/arkose_content_security_policy_spec.rb b/ee/spec/features/users/arkose_content_security_policy_spec.rb
index a852d0cfa1965..1dc1f324ba5e0 100644
--- a/ee/spec/features/users/arkose_content_security_policy_spec.rb
+++ b/ee/spec/features/users/arkose_content_security_policy_spec.rb
@@ -41,6 +41,7 @@
       end
     end
 
-    it_behaves_like 'configures Content Security Policy headers correctly', Users::IdentityVerificationController
+    it_behaves_like 'configures Content Security Policy headers correctly',
+      Users::RegistrationsIdentityVerificationController
   end
 end
diff --git a/ee/spec/requests/users/identity_verification_controller_spec.rb b/ee/spec/requests/users/registrations_identity_verification_controller_spec.rb
similarity index 97%
rename from ee/spec/requests/users/identity_verification_controller_spec.rb
rename to ee/spec/requests/users/registrations_identity_verification_controller_spec.rb
index 599eb816d47cb..94aa8e651ee82 100644
--- a/ee/spec/requests/users/identity_verification_controller_spec.rb
+++ b/ee/spec/requests/users/registrations_identity_verification_controller_spec.rb
@@ -2,8 +2,8 @@
 
 require 'spec_helper'
 
-RSpec.describe Users::IdentityVerificationController, :clean_gitlab_redis_sessions, :clean_gitlab_redis_rate_limiting,
-  feature_category: :system_access do
+RSpec.describe Users::RegistrationsIdentityVerificationController, :clean_gitlab_redis_sessions,
+  :clean_gitlab_redis_rate_limiting, feature_category: :system_access do
   include SessionHelpers
   using RSpec::Parameterized::TableSyntax
 
@@ -41,6 +41,10 @@
     allow_next_instance_of(::Arkose::StatusService) do |instance|
       allow(instance).to receive(:execute).and_return(status_service_response)
     end
+
+    allow_next_found_instance_of(User) do |instance|
+      allow(instance).to receive(:verification_method_allowed?).and_return(true)
+    end
   end
 
   shared_examples 'it requires a valid verification_user_id' do |expected_response_code|
@@ -253,7 +257,7 @@
 
       context 'when phone verification challenge rate-limit has been reached' do
         let(:params) do
-          { arkose_labs_token: 'verification-token', identity_verification: { phone_number: '555' } }
+          { arkose_labs_token: 'verification-token', registrations_identity_verification: { phone_number: '555' } }
         end
 
         before do
@@ -563,7 +567,7 @@
 
   describe 'POST verify_email_code' do
     let_it_be(:user) { unconfirmed_user }
-    let_it_be(:params) { { identity_verification: { code: '123456' } } }
+    let_it_be(:params) { { registrations_identity_verification: { code: '123456' } } }
     let_it_be(:service_response) { { status: :success } }
 
     subject(:do_request) { post verify_email_code_identity_verification_path(params) }
@@ -632,8 +636,8 @@
       it 'renders the result as json' do
         expect(response.body).to eq({
           status: :failure,
-          message: format(s_("IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} "\
-            'and try again.'), interval: 'about 1 hour')
+          message: format(s_("IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} " \
+                             "and try again."), interval: 'about 1 hour')
         }.to_json)
       end
     end
@@ -679,7 +683,7 @@
     let_it_be(:user) { unconfirmed_user }
     let_it_be(:service_response) { ServiceResponse.success(payload: { container: 'contents' }) }
     let_it_be(:params) do
-      { identity_verification: { country: 'US', international_dial_code: '1', phone_number: '555' } }
+      { registrations_identity_verification: { country: 'US', international_dial_code: '1', phone_number: '555' } }
     end
 
     subject(:do_request) { post send_phone_verification_code_identity_verification_path(params) }
@@ -738,7 +742,7 @@
     let_it_be(:user) { unconfirmed_user }
     let_it_be(:service_response) { ServiceResponse.success }
     let_it_be(:params) do
-      { identity_verification: { verification_code: '999' } }
+      { registrations_identity_verification: { verification_code: '999' } }
     end
 
     subject(:do_request) { post verify_phone_verification_code_identity_verification_path(params) }
@@ -976,10 +980,6 @@
 
     before do
       stub_session(verification_user_id: user.id)
-
-      allow_next_found_instance_of(User) do |instance|
-        allow(instance).to receive(:verification_method_allowed?).and_return(true)
-      end
     end
 
     subject(:do_request) { get verify_credit_card_identity_verification_path(params) }
@@ -1115,18 +1115,13 @@
   end
 
   describe 'PATCH toggle_phone_exemption' do
+    let_it_be(:unconfirmed_user) { create(:user, :unconfirmed, :medium_risk) }
     let_it_be(:user) { unconfirmed_user }
 
-    let(:offer_phone_number_exemption) { true }
-
     subject(:do_request) { patch toggle_phone_exemption_identity_verification_path(format: :json) }
 
     before do
       stub_session(verification_user_id: user.id)
-
-      allow_next_found_instance_of(User) do |user|
-        allow(user).to receive(:offer_phone_number_exemption?).and_return(offer_phone_number_exemption)
-      end
     end
 
     it_behaves_like 'it requires an unconfirmed user'
@@ -1150,7 +1145,7 @@
     end
 
     context 'when not offering phone exemption' do
-      let(:offer_phone_number_exemption) { false }
+      let_it_be(:user) { create(:user, :unconfirmed, :low_risk) }
 
       it_behaves_like 'logs and tracks the event', :toggle_phone_exemption, :failed
 
diff --git a/ee/spec/views/users/identity_verification/show.html.haml_spec.rb b/ee/spec/views/users/registrations_identity_verification/show.html.haml_spec.rb
similarity index 55%
rename from ee/spec/views/users/identity_verification/show.html.haml_spec.rb
rename to ee/spec/views/users/registrations_identity_verification/show.html.haml_spec.rb
index 9b1b7701ea8fc..7986374a84df4 100644
--- a/ee/spec/views/users/identity_verification/show.html.haml_spec.rb
+++ b/ee/spec/views/users/registrations_identity_verification/show.html.haml_spec.rb
@@ -2,8 +2,8 @@
 
 require 'spec_helper'
 
-RSpec.describe 'user/identity_verification/show', feature_category: :onboarding do
-  let_it_be(:template) { 'users/identity_verification/show' }
+RSpec.describe 'user/registrations_identity_verification/show', feature_category: :onboarding do
+  let_it_be(:template) { 'users/registrations_identity_verification/show' }
   let_it_be(:user) { create_default(:user) }
 
   before do
diff --git a/ee/spec/views/users/identity_verification/success.html.haml_spec.rb b/ee/spec/views/users/registrations_identity_verification/success.html.haml_spec.rb
similarity index 83%
rename from ee/spec/views/users/identity_verification/success.html.haml_spec.rb
rename to ee/spec/views/users/registrations_identity_verification/success.html.haml_spec.rb
index 5fbb404e070d1..284f43427620c 100644
--- a/ee/spec/views/users/identity_verification/success.html.haml_spec.rb
+++ b/ee/spec/views/users/registrations_identity_verification/success.html.haml_spec.rb
@@ -2,7 +2,7 @@
 
 require 'spec_helper'
 
-RSpec.describe 'users/identity_verification/success.html.haml', feature_category: :onboarding do
+RSpec.describe 'users/registrations_identity_verification/success.html.haml', feature_category: :onboarding do
   context 'when tracking_label is set' do
     before do
       assign(:tracking_label, '_tracking_label_')
-- 
GitLab