2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
class Admin :: UsersController < Admin :: ApplicationController
2019-07-07 11:18:12 +05:30
include RoutableActions
2022-05-07 20:08:51 +05:30
include SortingHelper
2019-07-07 11:18:12 +05:30
2021-09-04 01:27:46 +05:30
before_action :user , except : [ :index , :new , :create ]
2019-02-15 15:39:39 +05:30
before_action :check_impersonation_availability , only : :impersonate
2020-10-04 03:57:07 +05:30
before_action :ensure_destroy_prerequisites_met , only : [ :destroy ]
2021-01-03 14:25:43 +05:30
2022-07-23 23:45:48 +05:30
feature_category :user_management
2014-09-02 18:07:02 +05:30
2021-06-08 01:23:25 +05:30
PAGINATION_WITH_COUNT_LIMIT = 1000
2014-09-02 18:07:02 +05:30
def index
2021-09-04 01:27:46 +05:30
return redirect_to admin_cohorts_path if params [ :tab ] == 'cohorts'
2021-06-08 01:23:25 +05:30
2019-07-07 11:18:12 +05:30
@users = User . filter_items ( params [ :filter ] ) . order_name_asc
2022-04-04 11:22:00 +05:30
@users = @users . search ( params [ :search_query ] , with_private_emails : true ) if params [ :search_query ] . present?
2021-04-29 21:17:54 +05:30
@users = users_with_included_associations ( @users )
2022-05-07 20:08:51 +05:30
@sort = params [ :sort ] . presence || sort_value_name
@users = @users . sort_by_attribute ( @sort )
2015-04-26 12:48:37 +05:30
@users = @users . page ( params [ :page ] )
2021-06-08 01:23:25 +05:30
@users = @users . without_count if paginate_without_count?
end
2021-03-11 19:13:27 +05:30
2014-09-02 18:07:02 +05:30
def show
2023-01-13 00:05:48 +05:30
@can_impersonate = can_impersonate_user
@impersonation_error_text = @can_impersonate ? nil : impersonation_error_text
2015-09-11 14:41:01 +05:30
end
2021-10-27 15:23:28 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2015-09-11 14:41:01 +05:30
def projects
2021-10-27 15:23:28 +05:30
@personal_projects = user . personal_projects . includes ( :topics )
@joined_projects = user . projects . joined ( @user ) . includes ( :topics )
2015-09-11 14:41:01 +05:30
end
def keys
2018-03-17 18:26:18 +05:30
@keys = user . keys . order_id_desc
2014-09-02 18:07:02 +05:30
end
def new
@user = User . new
end
def edit
user
end
2016-06-02 11:05:42 +05:30
def impersonate
2023-01-13 00:05:48 +05:30
if can_impersonate_user
2016-06-02 11:05:42 +05:30
session [ :impersonator_id ] = current_user . id
warden . set_user ( user , scope : :user )
2021-09-30 23:02:18 +05:30
clear_access_token_session_keys!
2016-06-02 11:05:42 +05:30
2019-10-12 21:52:04 +05:30
log_impersonation_event
2016-06-02 11:05:42 +05:30
2023-03-17 16:20:25 +05:30
flash [ :alert ] = format ( _ ( " You are now impersonating %{username} " ) , username : user . username )
2016-06-02 11:05:42 +05:30
redirect_to root_path
2017-08-17 22:00:37 +05:30
else
2023-01-13 00:05:48 +05:30
flash [ :alert ] = impersonation_error_text
2017-08-17 22:00:37 +05:30
redirect_to admin_user_path ( user )
2016-06-02 11:05:42 +05:30
end
end
2021-01-03 14:25:43 +05:30
def approve
result = Users :: ApproveService . new ( current_user ) . execute ( user )
if result [ :status ] == :success
redirect_back_or_admin_user ( notice : _ ( " Successfully approved " ) )
else
redirect_back_or_admin_user ( alert : result [ :message ] )
end
end
2021-02-22 17:27:13 +05:30
def reject
result = Users :: RejectService . new ( current_user ) . execute ( user )
if result [ :status ] == :success
2023-03-17 16:20:25 +05:30
redirect_back_or_admin_user ( notice : format ( _ ( " You've rejected %{user} " ) , user : user . name ) )
2021-02-22 17:27:13 +05:30
else
redirect_back_or_admin_user ( alert : result [ :message ] )
end
end
2019-12-21 20:55:43 +05:30
def activate
2023-03-04 22:38:38 +05:30
if user . blocked?
return redirect_back_or_admin_user ( notice : _ ( " Error occurred. A blocked user must be unblocked to be activated " ) )
end
2019-12-21 20:55:43 +05:30
user . activate
redirect_back_or_admin_user ( notice : _ ( " Successfully activated " ) )
end
def deactivate
2023-03-04 22:38:38 +05:30
if user . blocked?
return redirect_back_or_admin_user ( notice : _ ( " Error occurred. A blocked user cannot be deactivated " ) )
end
2019-12-21 20:55:43 +05:30
return redirect_back_or_admin_user ( notice : _ ( " Successfully deactivated " ) ) if user . deactivated?
2021-01-03 14:25:43 +05:30
return redirect_back_or_admin_user ( notice : _ ( " Internal users cannot be deactivated " ) ) if user . internal?
2023-03-04 22:38:38 +05:30
unless user . can_be_deactivated?
2023-03-17 16:20:25 +05:30
return redirect_back_or_admin_user ( notice : format ( _ ( " The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated " ) , minimum_inactive_days : Gitlab :: CurrentSettings . deactivate_dormant_users_period ) )
2023-03-04 22:38:38 +05:30
end
2019-12-21 20:55:43 +05:30
user . deactivate
redirect_back_or_admin_user ( notice : _ ( " Successfully deactivated " ) )
end
2014-09-02 18:07:02 +05:30
def block
2020-03-13 15:44:24 +05:30
result = Users :: BlockService . new ( current_user ) . execute ( user )
2023-06-20 00:43:36 +05:30
respond_to do | format |
if result [ :status ] == :success
notice = _ ( " Successfully blocked " )
format . json { render json : { notice : notice } }
format . html { redirect_back_or_admin_user ( notice : notice ) }
else
alert = _ ( " Error occurred. User was not blocked " )
format . json { render json : { error : alert } }
format . html { redirect_back_or_admin_user ( alert : alert ) }
end
2014-09-02 18:07:02 +05:30
end
end
def unblock
2016-01-19 16:12:03 +05:30
if user . ldap_blocked?
2023-03-17 16:20:25 +05:30
return redirect_back_or_admin_user ( alert : _ ( " This user cannot be unlocked manually from GitLab " ) )
end
result = Users :: UnblockService . new ( current_user ) . execute ( user )
if result . success?
2019-07-07 11:18:12 +05:30
redirect_back_or_admin_user ( notice : _ ( " Successfully unblocked " ) )
2014-09-02 18:07:02 +05:30
else
2019-07-07 11:18:12 +05:30
redirect_back_or_admin_user ( alert : _ ( " Error occurred. User was not unblocked " ) )
2014-09-02 18:07:02 +05:30
end
end
2021-06-08 01:23:25 +05:30
def ban
result = Users :: BanService . new ( current_user ) . execute ( user )
if result [ :status ] == :success
redirect_back_or_admin_user ( notice : _ ( " Successfully banned " ) )
else
redirect_back_or_admin_user ( alert : _ ( " Error occurred. User was not banned " ) )
end
end
def unban
2021-10-27 15:23:28 +05:30
result = Users :: UnbanService . new ( current_user ) . execute ( user )
if result [ :status ] == :success
2021-06-08 01:23:25 +05:30
redirect_back_or_admin_user ( notice : _ ( " Successfully unbanned " ) )
else
redirect_back_or_admin_user ( alert : _ ( " Error occurred. User was not unbanned " ) )
end
end
2015-09-11 14:41:01 +05:30
def unlock
2023-03-17 16:20:25 +05:30
if update_user ( & :unlock_access! )
2021-10-27 15:23:28 +05:30
redirect_back_or_admin_user ( notice : _ ( " Successfully unlocked " ) )
2015-09-11 14:41:01 +05:30
else
2019-07-07 11:18:12 +05:30
redirect_back_or_admin_user ( alert : _ ( " Error occurred. User was not unlocked " ) )
2015-09-11 14:41:01 +05:30
end
end
def confirm
2023-03-17 16:20:25 +05:30
if update_user ( & :force_confirm )
2019-07-07 11:18:12 +05:30
redirect_back_or_admin_user ( notice : _ ( " Successfully confirmed " ) )
2015-09-11 14:41:01 +05:30
else
2019-07-07 11:18:12 +05:30
redirect_back_or_admin_user ( alert : _ ( " Error occurred. User was not confirmed " ) )
2015-09-11 14:41:01 +05:30
end
end
def disable_two_factor
2020-11-24 15:15:51 +05:30
result = TwoFactor :: DestroyService . new ( current_user , user : user ) . execute
2017-09-10 17:25:29 +05:30
2020-11-24 15:15:51 +05:30
if result [ :status ] == :success
redirect_to admin_user_path ( user ) ,
notice : _ ( 'Two-factor authentication has been disabled for this user' )
else
redirect_to admin_user_path ( user ) , alert : result [ :message ]
end
2015-09-11 14:41:01 +05:30
end
2014-09-02 18:07:02 +05:30
def create
opts = {
2017-08-17 22:00:37 +05:30
reset_password : true ,
skip_confirmation : true
2014-09-02 18:07:02 +05:30
}
2017-08-17 22:00:37 +05:30
@user = Users :: CreateService . new ( current_user , user_params . merge ( opts ) ) . execute
2014-09-02 18:07:02 +05:30
respond_to do | format |
2017-08-17 22:00:37 +05:30
if @user . persisted?
2019-07-07 11:18:12 +05:30
format . html { redirect_to [ :admin , @user ] , notice : _ ( 'User was successfully created.' ) }
2014-09-02 18:07:02 +05:30
format . json { render json : @user , status : :created , location : @user }
else
format . html { render " new " }
format . json { render json : @user . errors , status : :unprocessable_entity }
end
end
end
def update
user_params_with_pass = user_params . dup
if params [ :user ] [ :password ] . present?
2018-03-17 18:26:18 +05:30
password_params = {
2014-09-02 18:07:02 +05:30
password : params [ :user ] [ :password ] ,
2018-03-17 18:26:18 +05:30
password_confirmation : params [ :user ] [ :password_confirmation ]
}
2020-11-24 15:15:51 +05:30
password_params [ :password_expires_at ] = Time . current if admin_making_changes_for_another_user?
2018-03-17 18:26:18 +05:30
user_params_with_pass . merge! ( password_params )
2014-09-02 18:07:02 +05:30
end
2021-09-04 01:27:46 +05:30
cc_validation_params = process_credit_card_validation_params ( user_params_with_pass . delete ( :credit_card_validation_attributes ) )
user_params_with_pass . merge! ( cc_validation_params )
2014-09-02 18:07:02 +05:30
respond_to do | format |
2018-03-17 18:26:18 +05:30
result = Users :: UpdateService . new ( current_user , user_params_with_pass . merge ( user : user ) ) . execute do | user |
2017-09-10 17:25:29 +05:30
user . skip_reconfirmation!
2020-11-24 15:15:51 +05:30
user . send_only_admin_changed_your_password_notification! if admin_making_changes_for_another_user?
2017-09-10 17:25:29 +05:30
end
if result [ :status ] == :success
2019-07-07 11:18:12 +05:30
format . html { redirect_to [ :admin , user ] , notice : _ ( 'User was successfully updated.' ) }
2014-09-02 18:07:02 +05:30
format . json { head :ok }
else
# restore username to keep form action url.
user . username = params [ :id ]
format . html { render " edit " }
2021-01-03 14:25:43 +05:30
format . json { render json : [ result [ :message ] ] , status : :internal_server_error }
2014-09-02 18:07:02 +05:30
end
end
end
def destroy
2020-10-04 03:57:07 +05:30
user . delete_async ( deleted_by : current_user , params : destroy_params )
2014-09-02 18:07:02 +05:30
respond_to do | format |
2019-12-26 22:10:19 +05:30
format . html { redirect_to admin_users_path , status : :found , notice : _ ( " The user is being deleted. " ) }
2014-09-02 18:07:02 +05:30
format . json { head :ok }
end
end
def remove_email
email = user . emails . find ( params [ :email_id ] )
2018-03-17 18:26:18 +05:30
success = Emails :: DestroyService . new ( current_user , user : user ) . execute ( email )
2015-04-26 12:48:37 +05:30
2014-09-02 18:07:02 +05:30
respond_to do | format |
2017-09-10 17:25:29 +05:30
if success
2019-07-07 11:18:12 +05:30
format . html { redirect_back_or_admin_user ( notice : _ ( 'Successfully removed email.' ) ) }
2017-09-10 17:25:29 +05:30
format . json { head :ok }
else
2019-07-07 11:18:12 +05:30
format . html { redirect_back_or_admin_user ( alert : _ ( 'There was an error removing the e-mail.' ) ) }
format . json { render json : _ ( 'There was an error removing the e-mail.' ) , status : :bad_request }
2017-09-10 17:25:29 +05:30
end
2014-09-02 18:07:02 +05:30
end
end
protected
2021-09-04 01:27:46 +05:30
def process_credit_card_validation_params ( cc_validation_params )
return unless cc_validation_params && cc_validation_params [ :credit_card_validated_at ]
cc_validation = cc_validation_params [ :credit_card_validated_at ]
if cc_validation == " 1 " && ! user . credit_card_validated_at
{
credit_card_validation_attributes : {
credit_card_validated_at : Time . zone . now
}
}
elsif cc_validation == " 0 " && user . credit_card_validated_at
{
credit_card_validation_attributes : {
_destroy : true
}
}
end
end
2021-06-08 01:23:25 +05:30
def paginate_without_count?
counts = Gitlab :: Database :: Count . approximate_counts ( [ User ] )
counts [ User ] > PAGINATION_WITH_COUNT_LIMIT
end
2021-04-29 21:17:54 +05:30
def users_with_included_associations ( users )
users . includes ( :authorized_projects ) # rubocop: disable CodeReuse/ActiveRecord
end
2020-11-24 15:15:51 +05:30
def admin_making_changes_for_another_user?
user != current_user
2018-03-17 18:26:18 +05:30
end
2020-10-04 03:57:07 +05:30
def destroy_params
params . permit ( :hard_delete )
end
def ensure_destroy_prerequisites_met
return if hard_delete?
if user . solo_owned_groups . present?
message = s_ ( 'AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account' )
redirect_to admin_user_path ( user ) , status : :see_other , alert : message
end
end
def hard_delete?
destroy_params [ :hard_delete ]
end
2014-09-02 18:07:02 +05:30
def user
2021-11-11 11:23:49 +05:30
@user || = find_routable! ( User , params [ :id ] , request . fullpath )
2019-07-07 11:18:12 +05:30
end
def build_canonical_path ( user )
url_for ( safe_params . merge ( id : user . to_param ) )
2014-09-02 18:07:02 +05:30
end
2015-10-24 18:46:33 +05:30
def redirect_back_or_admin_user ( options = { } )
redirect_back_or_default ( default : default_route , options : options )
end
def default_route
[ :admin , @user ]
end
2017-08-17 22:00:37 +05:30
def user_params
2018-11-08 19:23:39 +05:30
params . require ( :user ) . permit ( allowed_user_params )
2017-08-17 22:00:37 +05:30
end
2018-11-08 19:23:39 +05:30
def allowed_user_params
2017-08-17 22:00:37 +05:30
[
:access_level ,
:avatar ,
:bio ,
:can_create_group ,
:color_scheme_id ,
:email ,
:extern_uid ,
:external ,
:force_random_password ,
:hide_no_password ,
:hide_no_ssh_key ,
:key_id ,
:linkedin ,
:name ,
:password_expires_at ,
:projects_limit ,
:provider ,
:remember_me ,
:skype ,
2018-03-17 18:26:18 +05:30
:theme_id ,
2017-08-17 22:00:37 +05:30
:twitter ,
2023-04-23 21:23:45 +05:30
:discord ,
2017-08-17 22:00:37 +05:30
:username ,
2020-06-23 00:09:42 +05:30
:website_url ,
2021-09-04 01:27:46 +05:30
:note ,
2023-03-17 16:20:25 +05:30
:private_profile ,
2021-09-04 01:27:46 +05:30
credit_card_validation_attributes : [ :credit_card_validated_at ]
2017-08-17 22:00:37 +05:30
]
end
2017-09-10 17:25:29 +05:30
def update_user ( & block )
2018-03-17 18:26:18 +05:30
result = Users :: UpdateService . new ( current_user , user : user ) . execute ( & block )
2017-09-10 17:25:29 +05:30
result [ :status ] == :success
end
2019-02-15 15:39:39 +05:30
def check_impersonation_availability
access_denied! unless Gitlab . config . gitlab . impersonation_enabled
end
2019-10-12 21:52:04 +05:30
def log_impersonation_event
2023-03-17 16:20:25 +05:30
Gitlab :: AppLogger . info ( format ( _ ( " User %{current_user_username} has started impersonating %{username} " ) , current_user_username : current_user . username , username : user . username ) )
2019-10-12 21:52:04 +05:30
end
2023-01-13 00:05:48 +05:30
def can_impersonate_user
can? ( user , :log_in ) && ! user . password_expired? && ! impersonation_in_progress?
end
def impersonation_error_text
if impersonation_in_progress?
_ ( " You are already impersonating another user " )
elsif user . blocked?
_ ( " You cannot impersonate a blocked user " )
elsif user . password_expired?
_ ( " You cannot impersonate a user with an expired password " )
elsif user . internal?
_ ( " You cannot impersonate an internal user " )
else
_ ( " You cannot impersonate a user who cannot log in " )
end
end
2014-09-02 18:07:02 +05:30
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
Admin :: UsersController . prepend_mod_with ( 'Admin::UsersController' )