Class: Gitlab::Auth::CurrentUserMode

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/auth/current_user_mode.rb

Overview

Keeps track of the current session user mode

In order to perform administrative tasks over some interfaces, an administrator must have explicitly enabled admin-mode e.g. on web access require re-authentication

Constant Summary collapse

NotRequestedError =
Class.new(StandardError)
CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY =

RequestStore entries

{ res: :current_user_mode, data: :bypass_session_admin_id }.freeze
CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY =
{ res: :current_user_mode, data: :current_admin }.freeze
SESSION_STORE_KEY =

SessionStore entries

:current_user_mode
ADMIN_MODE_START_TIME_KEY =
:admin_mode
ADMIN_MODE_REQUESTED_TIME_KEY =
:admin_mode_requested
MAX_ADMIN_MODE_TIME =
6.hours
ADMIN_MODE_REQUESTED_GRACE_PERIOD =
5.minutes

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user) ⇒ CurrentUserMode

Returns a new instance of CurrentUserMode.


72
73
74
# File 'lib/gitlab/auth/current_user_mode.rb', line 72

def initialize(user)
  @user = user
end

Class Method Details

.bypass_session!(admin_id) ⇒ Object

Admin mode activation requires storing a flag in the user session. Using this method when scheduling jobs in sessionless environments (e.g. Sidekiq, API) will bypass the session check for a user that was already in admin mode

If passed a block, it will surround the block execution and reset the session bypass at the end; otherwise use manually '.reset_bypass_session!'


31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/gitlab/auth/current_user_mode.rb', line 31

def bypass_session!(admin_id)
  Gitlab::SafeRequestStore[CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY] = admin_id

  Gitlab::AppLogger.debug("Bypassing session in admin mode for: #{admin_id}")

  if block_given?
    begin
      yield
    ensure
      reset_bypass_session!
    end
  end
end

.bypass_session_admin_idObject


49
50
51
# File 'lib/gitlab/auth/current_user_mode.rb', line 49

def bypass_session_admin_id
  Gitlab::SafeRequestStore[CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY]
end

.current_adminObject


67
68
69
# File 'lib/gitlab/auth/current_user_mode.rb', line 67

def current_admin
  Gitlab::SafeRequestStore[CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY]
end

.reset_bypass_session!Object


45
46
47
# File 'lib/gitlab/auth/current_user_mode.rb', line 45

def reset_bypass_session!
  Gitlab::SafeRequestStore.delete(CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY)
end

.with_current_admin(admin) ⇒ Object

Store in the current request the provided user model (only if in admin mode) and yield


55
56
57
58
59
60
61
62
63
64
65
# File 'lib/gitlab/auth/current_user_mode.rb', line 55

def with_current_admin(admin)
  return yield unless self.new(admin).admin_mode?

  Gitlab::SafeRequestStore[CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY] = admin

  Gitlab::AppLogger.debug("Admin mode active for: #{admin.username}")

  yield
ensure
  Gitlab::SafeRequestStore.delete(CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY)
end

Instance Method Details

#admin_mode?Boolean

Returns:

  • (Boolean)

76
77
78
79
80
81
82
# File 'lib/gitlab/auth/current_user_mode.rb', line 76

def admin_mode?
  return false unless user

  Gitlab::SafeRequestStore.fetch(admin_mode_rs_key) do
    user.admin? && session_with_admin_mode?
  end
end

#admin_mode_requested?Boolean

Returns:

  • (Boolean)

84
85
86
87
88
89
90
# File 'lib/gitlab/auth/current_user_mode.rb', line 84

def admin_mode_requested?
  return false unless user

  Gitlab::SafeRequestStore.fetch(admin_mode_requested_rs_key) do
    user.admin? && admin_mode_requested_in_grace_period?
  end
end

#disable_admin_mode!Object


104
105
106
107
108
109
110
111
# File 'lib/gitlab/auth/current_user_mode.rb', line 104

def disable_admin_mode!
  return unless user&.admin?

  reset_request_store_cache_entries

  current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY] = nil
  current_session_data[ADMIN_MODE_START_TIME_KEY] = nil
end

#enable_admin_mode!(password: nil, skip_password_validation: false) ⇒ Object

Raises:


92
93
94
95
96
97
98
99
100
101
102
# File 'lib/gitlab/auth/current_user_mode.rb', line 92

def enable_admin_mode!(password: nil, skip_password_validation: false)
  return unless user&.admin?
  return unless skip_password_validation || user&.valid_password?(password)

  raise NotRequestedError unless admin_mode_requested?

  reset_request_store_cache_entries

  current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY] = nil
  current_session_data[ADMIN_MODE_START_TIME_KEY] = Time.now
end

#request_admin_mode!Object


113
114
115
116
117
118
119
# File 'lib/gitlab/auth/current_user_mode.rb', line 113

def request_admin_mode!
  return unless user&.admin?

  reset_request_store_cache_entries

  current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY] = Time.now
end