Added admin session management.
This commit is contained in:
parent
e47b20ec03
commit
cbca117f72
9 changed files with 200 additions and 7 deletions
55
app/assets/javascripts/app/controllers/session.js.coffee
Normal file
55
app/assets/javascripts/app/controllers/session.js.coffee
Normal file
|
@ -0,0 +1,55 @@
|
|||
class Session extends App.ControllerContent
|
||||
events:
|
||||
'click [data-type="delete"]': 'destroy'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
# check authentication
|
||||
return if !@authenticate()
|
||||
|
||||
@load()
|
||||
@interval(
|
||||
=>
|
||||
@load
|
||||
10000
|
||||
)
|
||||
|
||||
# fetch data, render view
|
||||
load: ->
|
||||
App.Com.ajax(
|
||||
id: 'sessions'
|
||||
type: 'GET'
|
||||
url: 'api/sessions'
|
||||
success: (data) =>
|
||||
@render(data)
|
||||
)
|
||||
|
||||
render: (data) ->
|
||||
App.Collection.load( type: 'User', data: data.users )
|
||||
|
||||
# fill users
|
||||
for session in data.sessions
|
||||
if session.data && session.data.user_id
|
||||
session.data.user = App.User.find( session.data.user_id )
|
||||
|
||||
@html App.view('session')(
|
||||
sessions: data.sessions
|
||||
)
|
||||
|
||||
# show frontend times
|
||||
@frontendTimeUpdate()
|
||||
|
||||
destroy: (e) ->
|
||||
e.preventDefault()
|
||||
sessionId = $( e.target ).data('session-id')
|
||||
App.Com.ajax(
|
||||
id: 'sessions/' + sessionId
|
||||
type: 'DELETE'
|
||||
url: 'api/sessions/' + sessionId
|
||||
success: (data) =>
|
||||
@load()
|
||||
)
|
||||
|
||||
|
||||
App.Config.set( 'session', Session, 'Routes' )
|
||||
App.Config.set( 'session', { prio: 3700, parent: '#admin', name: 'Sessions', target: '#session', role: ['Admin'] }, 'NavBar' )
|
28
app/assets/javascripts/app/views/session.jst.eco
Normal file
28
app/assets/javascripts/app/views/session.jst.eco
Normal file
|
@ -0,0 +1,28 @@
|
|||
<div class="page-header">
|
||||
<h1><%- @T('Sessions') %><small></small></h1>
|
||||
</div>
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="span4"><%- @T('User') %></th>
|
||||
<th class="span3"><%- @T('Browser') %></th>
|
||||
<th class="span3"><%- @T('Location') %></th>
|
||||
<th class="span1"><%- @T('Age') %></th>
|
||||
<th class="span1"><%- @T('Update') %></th>
|
||||
<th class="span1"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for session in @sessions: %>
|
||||
<tr>
|
||||
<td><% if session.data.user: %><%= session.data.user.displayName() %><% end %></td>
|
||||
<td><% if session.data.user_agent: %><%= session.data.user_agent %><% end %></td>
|
||||
<td><% if session.data.geo: %><%= session.data.geo.country_code %> <%= session.data.geo.city %><% end %></td>
|
||||
<td><span class="humanTimeFromNow" data-time="<%- session.created_at %>">?</span></td>
|
||||
<td><span class="humanTimeFromNow" data-time="<%- session.updated_at %>">?</span></td>
|
||||
<td><a href="#" data-session-id="<%- session.id %>" data-type="delete" class="icon-trash" title="<%- @T('Delete') %>"></a></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -14,7 +14,7 @@ class ApplicationController < ActionController::Base
|
|||
:mode_show_rendeder,
|
||||
:model_index_render
|
||||
|
||||
before_filter :set_user
|
||||
before_filter :set_user, :session_update
|
||||
before_filter :cors_preflight_check
|
||||
|
||||
after_filter :set_access_control_headers
|
||||
|
@ -73,9 +73,26 @@ class ApplicationController < ActionController::Base
|
|||
UserInfo.current_user_id = current_user.id
|
||||
end
|
||||
|
||||
# update session updated_at
|
||||
def session_update
|
||||
session[:ping] = Time.now.utc.iso8601
|
||||
|
||||
# check if remote ip need to be updated
|
||||
if !session[:remote_id] || session[:remote_id] != request.remote_ip
|
||||
session[:remote_id] = request.remote_ip
|
||||
session[:geo] = Geoip.location( request.remote_ip )
|
||||
end
|
||||
|
||||
# fill user agent
|
||||
if !session[:user_agent]
|
||||
session[:user_agent] = request.env['HTTP_USER_AGENT']
|
||||
end
|
||||
end
|
||||
|
||||
def authentication_check_only
|
||||
|
||||
puts 'authentication_check'
|
||||
session[:request_type] = 1
|
||||
#puts params.inspect
|
||||
#puts session.inspect
|
||||
#puts cookies.inspect
|
||||
|
@ -83,6 +100,8 @@ class ApplicationController < ActionController::Base
|
|||
# check http basic auth
|
||||
authenticate_with_http_basic do |username, password|
|
||||
puts 'http basic auth check'
|
||||
session[:request_type] = 2
|
||||
|
||||
userdata = User.authenticate( username, password )
|
||||
message = ''
|
||||
if !userdata
|
||||
|
@ -113,6 +132,8 @@ class ApplicationController < ActionController::Base
|
|||
userdata = User.find( logon_session.data[:user_id] )
|
||||
end
|
||||
|
||||
session[:request_type] = 3
|
||||
|
||||
# set logon session user to current user
|
||||
current_user_set(userdata)
|
||||
return {
|
||||
|
|
|
@ -148,4 +148,30 @@ class SessionsController < ApplicationController
|
|||
redirect_to '/#'
|
||||
end
|
||||
|
||||
def list
|
||||
return if deny_if_not_role('Admin')
|
||||
sessions = ActiveRecord::SessionStore::Session.order('created_at DESC').limit(10000)
|
||||
users = {}
|
||||
sessions_clean = []
|
||||
sessions.each {|session|
|
||||
next if !session.data['user_id']
|
||||
sessions_clean.push session
|
||||
if session.data['user_id']
|
||||
if !users[ session.data['user_id'] ]
|
||||
users[ session.data['user_id'] ] = User.user_data_full( session.data['user_id'] )
|
||||
end
|
||||
end
|
||||
}
|
||||
render :json => {
|
||||
:sessions => sessions_clean,
|
||||
:users => users,
|
||||
}
|
||||
end
|
||||
|
||||
def delete
|
||||
return if deny_if_not_role('Admin')
|
||||
session = ActiveRecord::SessionStore::Session.find(params[:id])
|
||||
session.destroy
|
||||
render :json => {}
|
||||
end
|
||||
end
|
||||
|
|
25
app/models/observer/session.rb
Normal file
25
app/models/observer/session.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
require 'history'
|
||||
|
||||
class Observer::Session < ActiveRecord::Observer
|
||||
observe 'active_record::_session_store::_session'
|
||||
|
||||
def before_create(record)
|
||||
check(record)
|
||||
end
|
||||
def before_update(record)
|
||||
check(record)
|
||||
end
|
||||
|
||||
def check(record)
|
||||
return if !record.data
|
||||
|
||||
# remember request type
|
||||
if record.data['request_type']
|
||||
record[:request_type] = record.data['request_type']
|
||||
record.data.delete('request_type')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -26,6 +26,7 @@ module Zammad
|
|||
# Activate observers that should always be running.
|
||||
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
|
||||
config.active_record.observers =
|
||||
'observer::_session',
|
||||
'observer::_history',
|
||||
'observer::_ticket::_first_response',
|
||||
'observer::_ticket::_last_contact',
|
||||
|
|
|
@ -2,16 +2,18 @@ module ExtraRoutes
|
|||
def add(map)
|
||||
|
||||
# omniauth
|
||||
map.match '/auth/:provider/callback', :to => 'sessions#create_omniauth'
|
||||
map.match '/auth/:provider/callback', :to => 'sessions#create_omniauth',:via => [:post, :get, :puts, :delete]
|
||||
|
||||
# sso
|
||||
map.match '/auth/sso', :to => 'sessions#create_sso'
|
||||
map.match '/auth/sso', :to => 'sessions#create_sso', :via => [:post, :get]
|
||||
|
||||
# sessions
|
||||
map.match '/signin', :to => 'sessions#create'
|
||||
map.match '/signshow', :to => 'sessions#show'
|
||||
map.match '/signout', :to => 'sessions#destroy'
|
||||
map.match '/signin', :to => 'sessions#create', :via => :post
|
||||
map.match '/signshow', :to => 'sessions#show', :via => :get
|
||||
map.match '/signout', :to => 'sessions#destroy', :via => [:get, :delete]
|
||||
|
||||
map.match '/api/sessions', :to => 'sessions#list', :via => :get
|
||||
map.match '/api/sessions/:id', :to => 'sessions#delete', :via => :delete
|
||||
end
|
||||
module_function :add
|
||||
end
|
||||
end
|
||||
|
|
9
db/migrate/20130726000001_update_session.rb
Normal file
9
db/migrate/20130726000001_update_session.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class UpdateSession < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :sessions, :request_type, :integer, :null => true
|
||||
add_index :sessions, :request_type
|
||||
end
|
||||
def down
|
||||
end
|
||||
end
|
||||
|
26
lib/geoip.rb
Normal file
26
lib/geoip.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
require 'faraday'
|
||||
require 'cache'
|
||||
|
||||
module Geoip
|
||||
def self.location(address)
|
||||
|
||||
# check cache
|
||||
cache_key = "geoip::#{address}"
|
||||
cache = Cache.get( cache_key )
|
||||
return cache if cache
|
||||
|
||||
# do lookup
|
||||
host = "http://freegeoip.net"
|
||||
url = "/json/#{CGI::escape address}"
|
||||
data = {}
|
||||
begin
|
||||
conn = Faraday.new( :url => host )
|
||||
response = conn.get url
|
||||
data = JSON.parse( response.body )
|
||||
Cache.write( cache_key, data, { :expires_in => 90.days } )
|
||||
rescue
|
||||
Cache.write( cache_key, data, { :expires_in => 60.minutes } )
|
||||
end
|
||||
data
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue