Improved device logging.

This commit is contained in:
Martin Edenhofer 2015-08-19 00:36:58 +02:00
parent 2760137eef
commit 72bb0eb067
7 changed files with 145 additions and 38 deletions

View file

@ -2,6 +2,7 @@ class App.Auth
@login: (params) ->
App.Log.notice 'Auth', 'login', params
params.data['fingerprint'] = App.Browser.fingerprint()
App.Ajax.request(
id: 'login'
type: 'POST'
@ -21,12 +22,15 @@ class App.Auth
)
@loginCheck: ->
params =
fingerprint: App.Browser.fingerprint()
App.Log.debug 'Auth', 'loginCheck'
App.Ajax.request(
id: 'login_check'
async: false
type: 'GET'
type: 'POST'
url: App.Config.get('api_path') + '/signshow'
data: JSON.stringify(params)
success: (data, status, xhr) =>
# set login (config, session, ...)

View file

@ -14,10 +14,10 @@ class ApplicationController < ActionController::Base
:model_index_render
skip_before_action :verify_authenticity_token
before_action :set_user, :session_update, :check_user_device
before_action :set_user, :session_update
before_action :cors_preflight_check
after_action :set_access_control_headers
after_action :user_device_update, :set_access_control_headers
after_action :trigger_events
# For all responses in this controller, return the CORS access control headers.
@ -95,8 +95,8 @@ class ApplicationController < ActionController::Base
session[:user_agent] = request.env['HTTP_USER_AGENT']
end
# check user device
def check_user_device
# user device recent action update
def user_device_update
# return if we are in switch to user mode
return if session[:switched_from_user_id]
@ -104,21 +104,46 @@ class ApplicationController < ActionController::Base
# only if user_id exists
return if !session[:user_id]
# only if write action
# only with user device
if !session[:user_device_id]
if params[:fingerprint]
return false if !user_device_log(current_user, 'session')
end
return
end
# check if entry exists / only if write action
return if request.method == 'GET' || request.method == 'OPTIONS'
# only update if needed
return if session[:check_user_device_at] && session[:check_user_device_at] > Time.zone.now - 5.minutes
session[:check_user_device_at] = Time.zone.now
return if session[:user_device_update_at] && session[:user_device_update_at] > Time.zone.now - 5.minutes
session[:user_device_update_at] = Time.zone.now
user_device = UserDevice.add(
UserDevice.action(
session[:user_device_id],
session[:user_agent],
session[:remote_id],
session[:user_id],
)
if user_device.id != session[:check_user_device_id]
session[:check_user_device_id] = user_device.id
end
def user_device_log(user, type)
# for sessions we need the fingperprint
if !params[:fingerprint] && type == 'session'
render json: { error: 'Need fingerprint param!' }, status: :unprocessable_entity
return false
end
# add defice if needed
user_device = UserDevice.add(
request.env['HTTP_USER_AGENT'],
request.remote_ip,
user.id,
params[:fingerprint],
type,
)
session[:user_device_id] = user_device.id
end
def authentication_check_only(auth_param)
@ -130,7 +155,8 @@ class ApplicationController < ActionController::Base
# already logged in, early exit
if session.id && session[:user_id]
userdata = User.find( session[:user_id] )
userdata = User.find(session[:user_id])
current_user_set(userdata)
return {
@ -143,11 +169,10 @@ class ApplicationController < ActionController::Base
# check sso
sso_userdata = User.sso(params)
if sso_userdata
session[:persistent] = true
current_user_set(sso_userdata)
session[:persistent] = true
return {
auth: true
}
@ -161,8 +186,9 @@ class ApplicationController < ActionController::Base
next if !userdata
# set basic auth user to current user
current_user_set(userdata)
user_device_log(userdata, 'basic_auth')
return {
auth: true
}
@ -180,8 +206,8 @@ class ApplicationController < ActionController::Base
next if !userdata
# set token user to current user
current_user_set(userdata)
user_device_log(userdata, 'token_auth')
return {
auth: true
@ -216,9 +242,6 @@ class ApplicationController < ActionController::Base
return false
end
# store current user id into the session
session[:user_id] = current_user.id
# return auth ok
true
end

View file

@ -30,6 +30,9 @@ class SessionsController < ApplicationController
# set session user
current_user_set(user)
# log device
return if !user_device_log(user, 'session')
# log new session
user.activity_stream_log( 'session started', user.id, true )
@ -85,6 +88,9 @@ class SessionsController < ApplicationController
# subsequent requests
user = User.find( user_id )
# log device
return if !user_device_log(user, 'session')
# auto population of default collections
collections, assets = SessionHelper.default_collections(user)

View file

@ -4,18 +4,18 @@ class UserDevicesController < ApplicationController
before_action :authentication_check
def index
devices = UserDevice.where(user_id: current_user.id).order('updated_at DESC')
devices = UserDevice.where(user_id: current_user.id).order('created_at DESC')
devices_full = []
devices.each {|device|
attributes = device.attributes
if device.location_details['city']
attributes['location'] += ", #{device.location_details['city']}"
if device.location_details['city_name']
attributes['location'] += ", #{device.location_details['city_name']}"
end
attributes.delete('created_at')
attributes.delete('device_details')
attributes.delete('location_details')
if session[:check_user_device_id] == device.id
if session[:user_device_id] == device.id
attributes['current'] = true
end
devices_full.push attributes
@ -24,6 +24,7 @@ class UserDevicesController < ApplicationController
end
def destroy
# find device
user_device = UserDevice.find_by(user_id: current_user.id, id: params[:id])
@ -31,8 +32,8 @@ class UserDevicesController < ApplicationController
if user_device
SessionHelper.list.each {|session|
next if !session.data['user_id']
next if !session.data['check_user_device_id']
next if session.data['check_user_device_id'] != user_device.id
next if !session.data['user_device_id']
next if session.data['user_device_id'] != user_device.id
SessionHelper.destroy( session.id )
}
user_device.destroy

View file

@ -13,11 +13,37 @@ store device for user
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36',
'172.0.0.1',
user.id,
'fingerprintABC123',
'session', # session|basic_auth|token_auth|sso
)
=end
def self.add(user_agent, ip, user_id)
def self.add(user_agent, ip, user_id, fingerprint, type)
# get location info
location_details = Service::GeoIp.location(ip)
location = location_details['country_name']
# find device by fingerprint
if fingerprint
user_device = UserDevice.find_by(
user_id: user_id,
fingerprint: fingerprint,
location: location,
)
return action(user_device.id, user_agent, ip, user_id) if user_device
end
# for basic_auth|token_auth search for user agent
if type == 'basic_auth' || type == 'token_auth'
user_device = UserDevice.find_by(
user_id: user_id,
user_agent: user_agent,
location: location,
)
return action(user_device.id, user_agent, ip, user_id) if user_device
end
# get browser details
browser = Browser.new(:ua => user_agent, :accept_language => 'en-us')
@ -37,21 +63,22 @@ store device for user
name += browser[:name]
end
# get location info
location = Service::GeoIp.location(ip)
country = location['country_name']
# if not identified, use user agent
if name == 'Other, Other'
name = user_agent
browser[:name] = user_agent
end
# check if exists
exists = self.find_by(
:user_id => user_id,
user_device = self.find_by(
user_id: user_id,
os: browser[:plattform],
browser: browser[:name],
location: country,
location: location,
)
if exists
exists.touch
return exists
if user_device
return action(user_device.id, user_agent, ip, user_id) if user_device
end
# create new device
@ -60,10 +87,45 @@ store device for user
name: name,
os: browser[:plattform],
browser: browser[:name],
location: country,
location: location,
device_details: browser,
location_details: location,
location_details: location_details,
user_agent: user_agent,
ip: ip,
fingerprint: fingerprint,
)
end
=begin
log user device action
UserDevice.action(
user_device_id,
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36',
'172.0.0.1',
user.id,
)
=end
def self.action(user_device_id, user_agent, ip, user_id)
user_device = UserDevice.find(user_device_id)
# update location if needed
if user_device.ip != ip
user_device.ip = ip
location_details = Service::GeoIp.location(ip)
user_device.location_details = location_details
location = location_details['country_name']
user_device.location = location
end
# update attributes
user_device.save
user_device
end
end

View file

@ -9,7 +9,7 @@ Zammad::Application.routes.draw do
# sessions
match api_path + '/signin', to: 'sessions#create', via: :post
match api_path + '/signshow', to: 'sessions#show', via: :get
match api_path + '/signshow', to: 'sessions#show', via: [:get, :post]
match api_path + '/signout', to: 'sessions#destroy', via: [:get, :delete]
match api_path + '/sessions/switch/:id', to: 'sessions#switch_to_user', via: :get

View file

@ -0,0 +1,11 @@
class UpdateUserDevices2 < ActiveRecord::Migration
def up
add_column :user_devices, :user_agent, :string, limit: 250, null: true
add_column :user_devices, :ip, :string, limit: 160, null: true
add_column :user_devices, :fingerprint, :string, limit: 160, null: true
add_index :user_devices, [:fingerprint]
add_index :user_devices, [:created_at]
UserDevice.reset_column_information
end
end