You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by je...@apache.org on 2014/07/25 09:55:11 UTC
[08/28] git commit: [#7480] ticket:610 Track last active session
[#7480] ticket:610 Track last active session
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/273dcf22
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/273dcf22
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/273dcf22
Branch: refs/heads/je/42cc_7451
Commit: 273dcf229cfe8df37ea3ef6dfbf3a2b58fff3a89
Parents: 2664ba7
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jul 17 14:27:43 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Jul 21 14:57:46 2014 +0000
----------------------------------------------------------------------
Allura/allura/controllers/root.py | 2 ++
Allura/allura/model/auth.py | 14 ++++++++
Allura/allura/tests/model/test_auth.py | 50 +++++++++++++++++++++++++++--
3 files changed, 64 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/273dcf22/Allura/allura/controllers/root.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/root.py b/Allura/allura/controllers/root.py
index 9c0b147..f354872 100644
--- a/Allura/allura/controllers/root.py
+++ b/Allura/allura/controllers/root.py
@@ -87,6 +87,8 @@ class RootController(WsgiDispatchController):
c.user = plugin.AuthenticationProvider.get(request).authenticate_request()
assert c.user is not None, ('c.user should always be at least User.anonymous(). '
'Did you run `paster setup-app` to create the database?')
+ if not c.user.is_anonymous():
+ c.user.track_active(request)
def _cleanup_request(self):
pass
http://git-wip-us.apache.org/repos/asf/allura/blob/273dcf22/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index ff4acea..f0ad1c2 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -290,6 +290,20 @@ class User(MappedClass, ActivityNode, ActivityObject):
self.last_access['login_ua'] = user_agent
session(self).flush(self)
+ def track_active(self, req):
+ user_ip = req.headers.get('X_FORWARDED_FOR', req.remote_addr)
+ user_agent = req.headers.get('User-Agent')
+ now = datetime.utcnow()
+ last_date = self.last_access['session_date']
+ date_changed = last_date is None or last_date.date() != now.date()
+ ip_changed = user_ip != self.last_access['session_ip']
+ ua_changed = user_agent != self.last_access['session_ua']
+ if date_changed or ip_changed or ua_changed:
+ self.last_access['session_date'] = datetime.utcnow()
+ self.last_access['session_ip'] = user_ip
+ self.last_access['session_ua'] = user_agent
+ session(self).flush(self)
+
def can_send_user_message(self):
"""Return true if User is permitted to send a mesage to another user.
http://git-wip-us.apache.org/repos/asf/allura/blob/273dcf22/Allura/allura/tests/model/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 56ffca1..f3869ee 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -24,20 +24,23 @@ Model tests for auth
from nose.tools import (
with_setup,
assert_equal,
+ assert_not_equal,
+ assert_true,
assert_not_in,
assert_in,
)
from pylons import tmpl_context as c, app_globals as g
from webob import Request
-from mock import patch
+from mock import patch, Mock
from datetime import datetime, timedelta
from ming.orm.ormsession import ThreadLocalORMSession
+from ming.odm import session
from allura import model as M
from allura.lib import plugin
from allura.tests import decorators as td
-from alluratest.controller import setup_basic_test, setup_global_objects
+from alluratest.controller import setup_basic_test, setup_global_objects, setup_functional_test
def setUp():
@@ -229,3 +232,46 @@ def test_check_sent_user_message_times():
user1.sent_user_message_times.append(
datetime.utcnow() - timedelta(minutes=15))
assert not user1.can_send_user_message()
+
+
+@td.with_user_project('test-admin')
+@with_setup(setUp)
+def test_user_track_active():
+ # without this session flushing inside track_active raises Exception
+ setup_functional_test()
+ c.user = M.User.by_username('test-admin')
+
+ assert_equal(c.user.last_access['session_date'], None)
+ assert_equal(c.user.last_access['session_ip'], None)
+ assert_equal(c.user.last_access['session_ua'], None)
+
+ req = Mock(headers={'User-Agent': 'browser'}, remote_addr='addr')
+ c.user.track_active(req)
+ c.user = M.User.by_username(c.user.username)
+ assert_not_equal(c.user.last_access['session_date'], None)
+ assert_equal(c.user.last_access['session_ip'], 'addr')
+ assert_equal(c.user.last_access['session_ua'], 'browser')
+
+ # ensure that session activity tracked with a whole-day granularity
+ prev_date = c.user.last_access['session_date']
+ c.user.track_active(req)
+ c.user = M.User.by_username(c.user.username)
+ assert_equal(c.user.last_access['session_date'], prev_date)
+ yesterday = datetime.utcnow() - timedelta(1)
+ c.user.last_access['session_date'] = yesterday
+ session(c.user).flush(c.user)
+ c.user.track_active(req)
+ c.user = M.User.by_username(c.user.username)
+ assert_true(c.user.last_access['session_date'] > yesterday)
+
+ # ...or if IP or User Agent has changed
+ req.remote_addr = 'new addr'
+ c.user.track_active(req)
+ c.user = M.User.by_username(c.user.username)
+ assert_equal(c.user.last_access['session_ip'], 'new addr')
+ assert_equal(c.user.last_access['session_ua'], 'browser')
+ req.headers['User-Agent'] = 'new browser'
+ c.user.track_active(req)
+ c.user = M.User.by_username(c.user.username)
+ assert_equal(c.user.last_access['session_ip'], 'new addr')
+ assert_equal(c.user.last_access['session_ua'], 'new browser')