1# frozen_string_literal: true 2 3class Admin::SessionsController < ApplicationController 4 include AuthenticatesWithTwoFactorForAdminMode 5 include InternalRedirect 6 include RendersLdapServers 7 8 before_action :user_is_admin! 9 10 feature_category :authentication_and_authorization 11 12 def new 13 if current_user_mode.admin_mode? 14 redirect_to redirect_path, notice: _('Admin mode already enabled') 15 else 16 current_user_mode.request_admin_mode! unless current_user_mode.admin_mode_requested? 17 store_location_for(:redirect, redirect_path) 18 end 19 end 20 21 def create 22 if two_factor_enabled_for_user? 23 admin_mode_authenticate_with_two_factor 24 elsif current_user_mode.enable_admin_mode!(password: user_params[:password]) 25 redirect_to redirect_path, notice: _('Admin mode enabled') 26 else 27 flash.now[:alert] = _('Invalid login or password') 28 render :new 29 end 30 rescue Gitlab::Auth::CurrentUserMode::NotRequestedError 31 redirect_to new_admin_session_path, alert: _('Re-authentication period expired or never requested. Please try again') 32 end 33 34 def destroy 35 current_user_mode.disable_admin_mode! 36 37 redirect_to root_path, status: :found, notice: _('Admin mode disabled') 38 end 39 40 private 41 42 def user_is_admin! 43 render_404 unless current_user&.admin? 44 end 45 46 def two_factor_enabled_for_user? 47 current_user&.two_factor_enabled? 48 end 49 50 def redirect_path 51 redirect_to_path = safe_redirect_path(stored_location_for(:redirect)) || safe_redirect_path_for_url(request.referer) 52 53 if redirect_to_path && 54 excluded_redirect_paths.none? { |excluded| redirect_to_path.include?(excluded) } 55 redirect_to_path 56 else 57 admin_root_path 58 end 59 end 60 61 def excluded_redirect_paths 62 [new_admin_session_path, admin_session_path] 63 end 64 65 def user_params 66 params.fetch(:user, {}).permit(:password, :otp_attempt, :device_response) 67 end 68 69 def valid_otp_attempt?(user) 70 otp_validation_result = 71 ::Users::ValidateOtpService.new(user).execute(user_params[:otp_attempt]) 72 valid_otp_attempt = otp_validation_result[:status] == :success 73 74 return valid_otp_attempt if Gitlab::Database.read_only? 75 76 valid_otp_attempt || user.invalidate_otp_backup_code!(user_params[:otp_attempt]) 77 end 78end 79