# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ module ApplicationController::HandlesDevices extend ActiveSupport::Concern included do before_action :user_device_log end def user_device_log(user = current_user, type = 'session') switched_from_user_id = ENV['SWITCHED_FROM_USER_ID'] || session[:switched_from_user_id] return true if %w[init mobile].include?(params[:controller]) # do no device logging on static initial page return true if switched_from_user_id return true if current_user_on_behalf # do no device logging for the user on behalf feature return true if !user return true if !policy(UserDevice).log? return true if type == 'SSO' time_to_check = true user_device_updated_at = session[:user_device_updated_at] if ENV['USER_DEVICE_UPDATED_AT'] user_device_updated_at = Time.zone.parse(ENV['USER_DEVICE_UPDATED_AT']) end if user_device_updated_at # check if entry exists / only if write action diff = 10.minutes.ago if %w[GET OPTIONS HEAD].include?(request.method) diff = 30.minutes.ago end # only update if needed if user_device_updated_at > diff time_to_check = false end end # if ip has not changed and ttl in still valid remote_ip = ENV['TEST_REMOTE_IP'] || request.remote_ip return true if time_to_check == false && session[:user_device_remote_ip] == remote_ip session[:user_device_remote_ip] = remote_ip # for sessions we need the fingperprint if type == 'session' fingerprint = params[:fingerprint] || request.headers['X-Browser-Fingerprint'] if !session[:user_device_updated_at] && !fingerprint && !session[:user_device_fingerprint] raise Exceptions::UnprocessableEntity, __('Need fingerprint param!') end if fingerprint UserDevice.fingerprint_validation(fingerprint) session[:user_device_fingerprint] = fingerprint end end session[:user_device_updated_at] = Time.zone.now # add device if needed http_user_agent = ENV['HTTP_USER_AGENT'] || request.env['HTTP_USER_AGENT'] UserDeviceLogJob.perform_later( http_user_agent, remote_ip, user.id, session[:user_device_fingerprint], type, ) end end