2018-01-15 05:10:48 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
|
|
module Auth
|
|
|
|
class BlockedUserTracker
|
2018-07-20 14:00:28 +00:00
|
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
|
2018-01-15 05:10:48 +00:00
|
|
|
ACTIVE_RECORD_REQUEST_PARAMS = 'action_dispatch.request.request_parameters'
|
|
|
|
|
2018-07-20 14:00:28 +00:00
|
|
|
def initialize(env)
|
|
|
|
@env = env
|
|
|
|
end
|
2018-01-15 05:10:48 +00:00
|
|
|
|
2018-07-27 11:54:31 +00:00
|
|
|
def user_blocked?
|
|
|
|
user&.blocked?
|
2018-07-20 14:00:28 +00:00
|
|
|
end
|
2018-01-15 05:10:48 +00:00
|
|
|
|
2018-07-20 14:00:28 +00:00
|
|
|
def user
|
|
|
|
return unless has_user_blocked_message?
|
2018-01-15 05:10:48 +00:00
|
|
|
|
2018-07-20 14:00:28 +00:00
|
|
|
strong_memoize(:user) do
|
|
|
|
# Check for either LDAP or regular GitLab account logins
|
|
|
|
login = @env.dig(ACTIVE_RECORD_REQUEST_PARAMS, 'username') ||
|
|
|
|
@env.dig(ACTIVE_RECORD_REQUEST_PARAMS, 'user', 'login')
|
2018-01-15 05:10:48 +00:00
|
|
|
|
2018-07-20 14:00:28 +00:00
|
|
|
User.by_login(login) if login.present?
|
|
|
|
end
|
2018-07-27 11:54:31 +00:00
|
|
|
rescue TypeError
|
2018-07-20 14:00:28 +00:00
|
|
|
end
|
2018-01-15 05:10:48 +00:00
|
|
|
|
2018-07-20 14:00:28 +00:00
|
|
|
def log_blocked_user_activity!
|
|
|
|
return unless user_blocked?
|
2018-01-15 05:10:48 +00:00
|
|
|
|
2018-07-20 14:00:28 +00:00
|
|
|
Gitlab::AppLogger.info("Failed login for blocked user: user=#{user.username} ip=#{@env['REMOTE_ADDR']}")
|
|
|
|
SystemHooksService.new.execute_hooks_for(user, :failed_login)
|
2018-01-15 05:10:48 +00:00
|
|
|
true
|
|
|
|
rescue TypeError
|
|
|
|
end
|
2018-07-27 11:54:31 +00:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
##
|
|
|
|
# Devise calls User#active_for_authentication? on the User model and then
|
|
|
|
# throws an exception to Warden with User#inactive_message:
|
|
|
|
# https://github.com/plataformatec/devise/blob/v4.2.1/lib/devise/hooks/activatable.rb#L8
|
|
|
|
#
|
|
|
|
# Since Warden doesn't pass the user record to the failure handler, we
|
|
|
|
# need to do a database lookup with the username. We can limit the
|
|
|
|
# lookups to happen when the user was blocked by checking the inactive
|
|
|
|
# message passed along by Warden.
|
|
|
|
#
|
|
|
|
def has_user_blocked_message?
|
|
|
|
strong_memoize(:user_blocked_message) do
|
|
|
|
message = @env.dig('warden.options', :message)
|
|
|
|
message == User::BLOCKED_MESSAGE
|
|
|
|
end
|
|
|
|
end
|
2018-01-15 05:10:48 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|