2022-01-01 13:38:12 +00:00
|
|
|
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
|
2021-06-01 12:20:20 +00:00
|
|
|
|
2017-03-09 11:44:51 +00:00
|
|
|
module ApplicationController::HasUser
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
included do
|
|
|
|
before_action :set_user, :session_update
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2018-02-13 16:19:22 +00:00
|
|
|
def current_user
|
2021-07-23 13:07:16 +00:00
|
|
|
current_user_on_behalf || current_user_real
|
2018-02-13 16:19:22 +00:00
|
|
|
end
|
|
|
|
|
2017-03-09 11:44:51 +00:00
|
|
|
# Finds the User with the ID stored in the session with the key
|
|
|
|
# :current_user_id This is a common way to handle user login in
|
|
|
|
# a Rails application; logging in sets the session value and
|
|
|
|
# logging out removes it.
|
2018-02-13 16:19:22 +00:00
|
|
|
def current_user_real
|
2021-07-23 13:07:16 +00:00
|
|
|
@_current_user ||= User.lookup(id: session[:user_id]) # rubocop:disable Naming/MemoizedInstanceVariableName
|
2017-03-09 11:44:51 +00:00
|
|
|
end
|
|
|
|
|
2021-08-10 12:00:34 +00:00
|
|
|
def request_header_from
|
|
|
|
@request_header_from ||= begin
|
|
|
|
if request.headers['X-On-Behalf-Of'].present?
|
|
|
|
ActiveSupport::Deprecation.warn("Header 'X-On-Behalf-Of' is deprecated. Please use header 'From' instead.")
|
|
|
|
end
|
|
|
|
|
|
|
|
request.headers['From'] || request.headers['X-On-Behalf-Of']
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-02-13 16:19:22 +00:00
|
|
|
# Finds the user based on the id, login or email which is given
|
|
|
|
# in the headers. If it is found then all api activities are done
|
|
|
|
# with the behalf of user. With this functionality it is possible
|
|
|
|
# to do changes with a user which is different from the admin user.
|
|
|
|
# E.g. create a ticket as a customer user based on a user with admin rights.
|
|
|
|
def current_user_on_behalf
|
2021-08-10 12:00:34 +00:00
|
|
|
return if request_header_from.blank? # require header
|
2021-07-23 13:07:16 +00:00
|
|
|
return @_user_on_behalf if @_user_on_behalf # return memoized user
|
|
|
|
return if !current_user_real # require session user
|
|
|
|
if !SessionsPolicy.new(current_user_real, Sessions).impersonate?
|
2021-11-15 15:58:19 +00:00
|
|
|
raise Exceptions::Forbidden, __("Current user has no permission to use 'From'/'X-On-Behalf-Of'!")
|
2021-07-23 13:07:16 +00:00
|
|
|
end
|
2018-02-13 16:19:22 +00:00
|
|
|
|
2021-08-10 12:00:34 +00:00
|
|
|
@_user_on_behalf = find_on_behalf_user request_header_from.to_s.downcase.strip
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2021-08-05 13:57:00 +00:00
|
|
|
# no behalf of user found
|
|
|
|
if !@_user_on_behalf
|
2021-08-10 12:00:34 +00:00
|
|
|
raise Exceptions::Forbidden, "No such user '#{request_header_from}'"
|
2018-02-13 16:19:22 +00:00
|
|
|
end
|
|
|
|
|
2021-08-05 13:57:00 +00:00
|
|
|
@_user_on_behalf
|
2018-02-13 16:19:22 +00:00
|
|
|
end
|
|
|
|
|
2017-03-09 11:44:51 +00:00
|
|
|
def current_user_set(user, auth_type = 'session')
|
|
|
|
session[:user_id] = user.id
|
|
|
|
@_auth_type = auth_type
|
|
|
|
@_current_user = user
|
|
|
|
set_user
|
|
|
|
end
|
|
|
|
|
|
|
|
# Sets the current user into a named Thread location so that it can be accessed
|
|
|
|
# by models and observers
|
|
|
|
def set_user
|
2021-07-23 13:07:16 +00:00
|
|
|
UserInfo.current_user_id = current_user&.id || 1
|
2017-03-09 11:44:51 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# update session updated_at
|
|
|
|
def session_update
|
2021-07-16 13:44:10 +00:00
|
|
|
# sleep 0.6
|
2017-03-09 11:44:51 +00:00
|
|
|
|
|
|
|
session[:ping] = Time.zone.now.iso8601
|
|
|
|
|
2021-12-07 09:55:00 +00:00
|
|
|
# check if remote ip needs to be updated
|
2017-03-09 11:44:51 +00:00
|
|
|
if session[:user_id]
|
2020-09-30 09:07:01 +00:00
|
|
|
if !session[:remote_ip] || session[:remote_ip] != request.remote_ip # rubocop:disable Style/SoleNestedConditional
|
2017-03-09 11:44:51 +00:00
|
|
|
session[:remote_ip] = request.remote_ip
|
|
|
|
session[:geo] = Service::GeoIp.location(request.remote_ip)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# fill user agent
|
|
|
|
return if session[:user_agent]
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2017-03-09 11:44:51 +00:00
|
|
|
session[:user_agent] = request.env['HTTP_USER_AGENT']
|
|
|
|
end
|
2021-08-05 13:57:00 +00:00
|
|
|
|
|
|
|
# find on behalf user by ID, login or email
|
|
|
|
def find_on_behalf_user(identifier)
|
|
|
|
# ActiveRecord casts string beginning with a numeric characters
|
|
|
|
# to numeric characters by dropping textual bits altogether
|
|
|
|
# thus 123@example.com returns user with ID 123
|
|
|
|
if identifier.match?(%r{^\d+$})
|
|
|
|
user = User.find_by(id: identifier)
|
|
|
|
return user if user
|
|
|
|
end
|
|
|
|
|
|
|
|
# find user for execution based on the header
|
|
|
|
User.where('login = :param OR email = :param', param: identifier).first
|
|
|
|
end
|
2017-03-09 11:44:51 +00:00
|
|
|
end
|