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:04 UTC

[01/28] git commit: [#7562] remove unused "args" index that can be large

Repository: allura
Updated Branches:
  refs/heads/je/42cc_7451 67d7fc308 -> 5e066d9cd (forced update)


[#7562] remove unused "args" index that can be large


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/09685f88
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/09685f88
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/09685f88

Branch: refs/heads/je/42cc_7451
Commit: 09685f889f4fd2920698d314c095f62b6f3dc60e
Parents: c22f378
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Thu Jul 10 19:33:34 2014 +0000
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Fri Jul 18 08:39:25 2014 +0000

----------------------------------------------------------------------
 Allura/allura/model/monq_model.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/09685f88/Allura/allura/model/monq_model.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/monq_model.py b/Allura/allura/model/monq_model.py
index a04bc38..fb33216 100644
--- a/Allura/allura/model/monq_model.py
+++ b/Allura/allura/model/monq_model.py
@@ -74,11 +74,9 @@ class MonQTask(MappedClass):
                 ('time_queue', ming.ASCENDING)
             ],
             [
-                # used by SF internal tool, but could be generally useful to
-                # have an index on task_name
+                # used by repo tarball status check, etc
                 'state', 'task_name', 'time_queue'
             ],
-            'args',
         ]
 
     _id = FieldProperty(S.ObjectId)


[09/28] git commit: [#7480] ticket:610 Track login info

Posted by je...@apache.org.
[#7480] ticket:610 Track login info


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2664ba72
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2664ba72
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2664ba72

Branch: refs/heads/je/42cc_7451
Commit: 2664ba72792b6bc80fe26f033ad1e10476eefb79
Parents: e297862
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jul 17 13:08:53 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Jul 21 14:57:46 2014 +0000

----------------------------------------------------------------------
 Allura/allura/lib/plugin.py                 |  1 +
 Allura/allura/model/auth.py                 | 15 +++++++++++++++
 Allura/allura/tests/functional/test_auth.py | 14 ++++++++++++++
 3 files changed, 30 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/2664ba72/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index eb1fb43..a5c3f65 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -144,6 +144,7 @@ class AuthenticationProvider(object):
             self.session.save()
             g.zarkov_event('login', user=user)
             g.statsUpdater.addUserLogin(user)
+            user.track_login(self.request)
             return user
         except exc.HTTPUnauthorized:
             self.logout()

http://git-wip-us.apache.org/repos/asf/allura/blob/2664ba72/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index ed3c4d0..ff4acea 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -274,6 +274,21 @@ class User(MappedClass, ActivityNode, ActivityObject):
 
     # Statistics
     stats_id = FieldProperty(S.ObjectId, if_missing=None)
+    last_access = FieldProperty(dict(
+        login_date=S.DateTime,
+        login_ip=str,
+        login_ua=str,
+        session_date=S.DateTime,
+        session_ip=str,
+        session_ua=str))
+
+    def track_login(self, req):
+        user_ip = req.headers.get('X_FORWARDED_FOR', req.remote_addr)
+        user_agent = req.headers.get('User-Agent')
+        self.last_access['login_date'] = datetime.utcnow()
+        self.last_access['login_ip'] = user_ip
+        self.last_access['login_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/2664ba72/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 1c41e8a..a200352 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -78,6 +78,20 @@ class TestAuth(TestController):
             username='test-usera', password='foo'))
         assert 'Invalid login' in str(r), r.showbrowser()
 
+    def test_track_login(self):
+        user = M.User.by_username('test-user')
+        assert_equal(user.last_access['login_date'], None)
+        assert_equal(user.last_access['login_ip'], None)
+        assert_equal(user.last_access['login_ua'], None)
+
+        self.app.post('/auth/do_login', params=dict(
+            username='test-user', password='foo'),
+            headers={'X_FORWARDED_FOR': 'addr', 'User-Agent': 'browser'})
+        user = M.User.by_username('test-user')
+        assert_not_equal(user.last_access['login_date'], None)
+        assert_equal(user.last_access['login_ip'], 'addr')
+        assert_equal(user.last_access['login_ua'], 'browser')
+
     @td.with_user_project('test-admin')
     def test_prefs(self):
         r = self.app.get('/auth/preferences/',


[21/28] git commit: [#7451] ticket:605 Use custom middleware to handle cookie expiration

Posted by je...@apache.org.
[#7451] ticket:605 Use custom middleware to handle cookie expiration


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a40f29a0
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a40f29a0
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a40f29a0

Branch: refs/heads/je/42cc_7451
Commit: a40f29a0d5e77df79a7fb92d00e11d0f7c5545d9
Parents: dedd58c
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Wed Jul 16 18:10:02 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:14:46 2014 +0300

----------------------------------------------------------------------
 Allura/allura/config/middleware.py     |  4 +--
 Allura/allura/lib/custom_middleware.py | 39 +++++++++++++++++++++++++++++
 Allura/development.ini                 |  1 +
 3 files changed, 42 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a40f29a0/Allura/allura/config/middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/config/middleware.py b/Allura/allura/config/middleware.py
index be0ef26..2fe2b88 100644
--- a/Allura/allura/config/middleware.py
+++ b/Allura/allura/config/middleware.py
@@ -27,7 +27,6 @@ import pkg_resources
 from tg import config
 from paste.deploy.converters import asbool
 from paste.registry import RegistryManager
-from beaker.middleware import SessionMiddleware
 from routes.middleware import RoutesMiddleware
 from pylons.middleware import StatusCodeRedirect
 
@@ -45,6 +44,7 @@ from allura.lib.custom_middleware import SSLMiddleware
 from allura.lib.custom_middleware import StaticFilesMiddleware
 from allura.lib.custom_middleware import CSRFMiddleware
 from allura.lib.custom_middleware import LoginRedirectMiddleware
+from allura.lib.custom_middleware import RememberLoginSessionMiddleware
 from allura.lib import patches
 from allura.lib import helpers as h
 
@@ -131,7 +131,7 @@ def _make_core_app(root, global_conf, full_stack=True, **app_conf):
     # Required for pylons
     app = RoutesMiddleware(app, config['routes.map'])
     # Required for sessions
-    app = SessionMiddleware(app, config)
+    app = RememberLoginSessionMiddleware(app, config)
     # Redirect 401 to the login page
     app = LoginRedirectMiddleware(app)
     # Add instrumentation

http://git-wip-us.apache.org/repos/asf/allura/blob/a40f29a0/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 511c5c3..73cfef3 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -28,6 +28,8 @@ from pylons.util import call_wsgi_application
 from timermiddleware import Timer, TimerMiddleware
 from webob import exc, Request
 import pysolr
+from beaker.middleware import SessionMiddleware
+from beaker.session import SessionObject
 
 from allura.lib import helpers as h
 import allura.model.repository
@@ -281,3 +283,40 @@ class AlluraTimerMiddleware(TimerMiddleware):
             func = ep.load()
             timers += aslist(func())
         return timers
+
+
+class RememberLoginSessionMiddleware(SessionMiddleware):
+    
+    def __call__(self, environ, start_response):
+        session = SessionObject(environ, **self.options)
+        if environ.get('paste.registry'):
+            if environ['paste.registry'].reglist:
+                environ['paste.registry'].register(self.session, session)
+        environ[self.environ_key] = session
+        environ['beaker.get_session'] = self._get_session
+
+        if 'paste.testing_variables' in environ and 'webtest_varname' in self.options:
+            environ['paste.testing_variables'][self.options['webtest_varname']] = session
+
+        def session_start_response(status, headers, exc_info=None):
+            if session.accessed():
+                session.persist()
+                cookie_out = None
+                login_expires = session.get('login_expires')
+                if login_expires is not None:
+                    session.cookie_expires = login_expires
+                    if login_expires == True:
+                        session.cookie[session.key]['expires'] = ''
+                    else:
+                        session._set_cookie_expires(None)
+                    cookie_out = session.cookie[session.key].output(header='')
+
+                if session.__dict__['_headers']['set_cookie']:
+                    if cookie_out:
+                        cookie = cookie_out
+                    else:
+                        cookie = session.__dict__['_headers']['cookie_out']
+                    if cookie:
+                        headers.append(('Set-cookie', cookie))
+            return start_response(status, headers, exc_info)
+        return self.wrap_app(environ, session_start_response)

http://git-wip-us.apache.org/repos/asf/allura/blob/a40f29a0/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index b7c52e0..71855c7 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -60,6 +60,7 @@ cache_dir = %(here)s/data
 beaker.session.key = allura
 beaker.session.type = cookie
 beaker.session.httponly = true
+beaker.session.cookie_expires = false
 ; CHANGE THIS VALUE FOR YOUR SITE
 beaker.session.validate_key = 714bfe3612c42390726f
 


[04/28] git commit: [#7526] Corrected headers for verification emails

Posted by je...@apache.org.
[#7526] Corrected headers for verification emails


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/02347376
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/02347376
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/02347376

Branch: refs/heads/je/42cc_7451
Commit: 0234737659022200a5ade36f9db7af2a20f931de
Parents: b6d0bc0
Author: Alexander Luberg <al...@slashdotmedia.com>
Authored: Thu Jul 17 14:46:03 2014 -0700
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Jul 18 18:54:09 2014 +0000

----------------------------------------------------------------------
 Allura/allura/model/auth.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/02347376/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 932dd17..ed3c4d0 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -155,11 +155,11 @@ please visit the following URL:
     %s
 ''' % (self._id, self.claimed_by_user().username, g.url('/auth/verify_addr', a=self.nonce))
         log.info('Verification email:\n%s', text)
-        allura.tasks.mail_tasks.sendmail.post(
-            destinations=[self._id],
-            fromaddr=self._id,
-            reply_to='',
-            subject='Email address verification',
+        allura.tasks.mail_tasks.sendsimplemail.post(
+            fromaddr=g.noreply,
+            reply_to=g.noreply,
+            toaddr=self._id,
+            subject='%s - Email address verification' % config['site_name'],
             message_id=h.gen_message_id(),
             text=text)
 


[15/28] git commit: [#7581] don't try to get commit sizes for log views of non-files

Posted by je...@apache.org.
[#7581] don't try to get commit sizes for log views of non-files

We don't show 'size' values for directory commit logs anyway, and svn
1.8 started returning -1 instead of 0 causing a test to fail.


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/0e18d9fc
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/0e18d9fc
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/0e18d9fc

Branch: refs/heads/je/42cc_7451
Commit: 0e18d9fc45c75e5d3b0c9a3d9db637539152230d
Parents: 9828de9
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Jul 22 16:21:10 2014 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jul 22 16:21:10 2014 -0400

----------------------------------------------------------------------
 ForgeSVN/forgesvn/model/svn.py                   | 12 +++++++-----
 ForgeSVN/forgesvn/tests/model/test_repository.py | 12 ++++++------
 2 files changed, 13 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/0e18d9fc/ForgeSVN/forgesvn/model/svn.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index af05713..92dc292 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -585,11 +585,13 @@ class SVNImplementation(M.RepositoryImplementation):
     def _map_log(self, ci, url, path=None):
         revno = ci.revision.number
         rev = pysvn.Revision(pysvn.opt_revision_kind.number, revno)
-        try:
-            size = int(
-                self._svn.list(url, revision=rev, peg_revision=rev)[0][0].size)
-        except pysvn.ClientError:
-            size = None
+        size = None
+        if path:
+            try:
+                size = int(
+                    self._svn.list(url, revision=rev, peg_revision=rev)[0][0].size)
+            except pysvn.ClientError:
+                pass
         rename_details = {}
         changed_paths = ci.get('changed_paths', [])
         for changed_path in changed_paths:

http://git-wip-us.apache.org/repos/asf/allura/blob/0e18d9fc/ForgeSVN/forgesvn/tests/model/test_repository.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index a9d712d..70c34ac 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -247,7 +247,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                  'date': datetime(2013, 11, 8, 13, 38, 11, 152821),
                  'name': u'coldmind',
                  'email': ''
-             }, 'size': 0},
+             }, 'size': None},
             {'parents': [4],
              'refs': [],
              'committed': {
@@ -261,7 +261,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                  'date': datetime(2010, 11, 18, 20, 14, 21, 515743),
                  'name': u'rick446',
                  'email': ''},
-             'size': 0},
+             'size': None},
             {'parents': [3],
              'refs': [],
              'committed': {
@@ -275,7 +275,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                  'date': datetime(2010, 10, 8, 15, 32, 59, 383719),
                  'name': u'rick446',
                  'email': ''},
-             'size': 0},
+             'size': None},
             {'parents': [2],
              'refs': [],
              'committed': {
@@ -289,7 +289,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
              {'date': datetime(2010, 10, 8, 15, 32, 48, 272296),
               'name': u'rick446',
               'email': ''},
-             'size': 0},
+             'size': None},
             {'parents': [1],
              'refs': [],
              'committed': {
@@ -303,7 +303,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                  'date': datetime(2010, 10, 8, 15, 32, 36, 221863),
                  'name': u'rick446',
                  'email': ''},
-             'size': 0},
+             'size': None},
             {'parents': [],
              'refs': [],
              'committed': {
@@ -317,7 +317,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
                  'date': datetime(2010, 10, 8, 15, 32, 7, 238375),
                  'name': u'rick446',
                  'email': ''},
-             'size': 0}])
+             'size': None}])
 
     def test_log_file(self):
         entries = list(self.repo.log(path='/README', id_only=False))


[27/28] git commit: [#7451] ticket:605 Remember rememberme value if validation fails

Posted by je...@apache.org.
[#7451] ticket:605 Remember rememberme value if validation fails


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e7f1bf38
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e7f1bf38
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e7f1bf38

Branch: refs/heads/je/42cc_7451
Commit: e7f1bf3808560526c19235139cec41c0256fc17d
Parents: 4a7253d
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 17 17:38:34 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:16:21 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/widgets/auth_widgets.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e7f1bf38/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 7ea416f..7f5079f 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -56,7 +56,8 @@ class LoginForm(ForgeForm):
             msg = 'Invalid login'
             raise Invalid(
                 msg,
-                dict(username=value['username'], return_to=value.get('return_to')),
+                dict(username=value['username'], rememberme=value.get('rememberme'),
+                     return_to=value.get('return_to')),
                 None)
         return value
 


[19/28] git commit: [#7451] ticket:605 Use utcnow()

Posted by je...@apache.org.
[#7451] ticket:605 Use utcnow()


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/12aaf70b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/12aaf70b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/12aaf70b

Branch: refs/heads/je/42cc_7451
Commit: 12aaf70b702e3e6373c6da0fceacd8205ec42372
Parents: 798a40c
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Tue Jul 15 12:59:16 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:14:46 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/plugin.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/12aaf70b/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index cd8419d..051b795 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -142,7 +142,7 @@ class AuthenticationProvider(object):
             if self.is_password_expired(user):
                 self.session['pwd-expired'] = True
             if 'rememberme' in self.request.params:
-                self.session.cookie_expires = datetime.now() + timedelta(365)
+                self.session.cookie_expires = datetime.utcnow() + timedelta(365)
             else:
                 self.session.cookie_expires = True
             self.session.save()


[08/28] git commit: [#7480] ticket:610 Track last active session

Posted by je...@apache.org.
[#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')


[26/28] git commit: [#7451] ticket:605 Added comment to RememberLoginSessionMiddleware

Posted by je...@apache.org.
[#7451] ticket:605 Added comment to RememberLoginSessionMiddleware


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/4a7253d7
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/4a7253d7
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/4a7253d7

Branch: refs/heads/je/42cc_7451
Commit: 4a7253d720b6d70ecdeee4e30fdacde41d17255f
Parents: 4809319
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 17 17:24:38 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:16:21 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/custom_middleware.py | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/4a7253d7/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index a8fc04e..cbaa94d 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -286,6 +286,9 @@ class AlluraTimerMiddleware(TimerMiddleware):
 
 
 class RememberLoginSessionMiddleware(SessionMiddleware):
+    '''Modified version of beaker's SessionMiddleware.
+    This middleware changes session's cookie expiration time according to login_expires
+    session variable'''
     
     def __call__(self, environ, start_response):
         session = SessionObject(environ, **self.options)


[23/28] git commit: [#7451] ticket:616 Moved login expiration check to a separate middleware

Posted by je...@apache.org.
[#7451] ticket:616 Moved login expiration check to a separate middleware


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/335843ed
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/335843ed
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/335843ed

Branch: refs/heads/je/42cc_7451
Commit: 335843ed21ccf7ee3777d1f671c5bc6c61149da1
Parents: e7f1bf3
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 24 19:18:42 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:16:21 2014 +0300

----------------------------------------------------------------------
 Allura/allura/config/middleware.py     |  7 ++--
 Allura/allura/lib/custom_middleware.py | 54 +++++++++++++----------------
 2 files changed, 29 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/335843ed/Allura/allura/config/middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/config/middleware.py b/Allura/allura/config/middleware.py
index 2fe2b88..91a3575 100644
--- a/Allura/allura/config/middleware.py
+++ b/Allura/allura/config/middleware.py
@@ -29,6 +29,7 @@ from paste.deploy.converters import asbool
 from paste.registry import RegistryManager
 from routes.middleware import RoutesMiddleware
 from pylons.middleware import StatusCodeRedirect
+from beaker.middleware import SessionMiddleware
 
 import activitystream
 import ew
@@ -44,7 +45,7 @@ from allura.lib.custom_middleware import SSLMiddleware
 from allura.lib.custom_middleware import StaticFilesMiddleware
 from allura.lib.custom_middleware import CSRFMiddleware
 from allura.lib.custom_middleware import LoginRedirectMiddleware
-from allura.lib.custom_middleware import RememberLoginSessionMiddleware
+from allura.lib.custom_middleware import RememberLoginMiddleware
 from allura.lib import patches
 from allura.lib import helpers as h
 
@@ -131,7 +132,9 @@ def _make_core_app(root, global_conf, full_stack=True, **app_conf):
     # Required for pylons
     app = RoutesMiddleware(app, config['routes.map'])
     # Required for sessions
-    app = RememberLoginSessionMiddleware(app, config)
+    app = SessionMiddleware(app, config)
+    # Handle "Remember me" functionality
+    app = RememberLoginMiddleware(app, config)
     # Redirect 401 to the login page
     app = LoginRedirectMiddleware(app)
     # Add instrumentation

http://git-wip-us.apache.org/repos/asf/allura/blob/335843ed/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index cbaa94d..656e9a4 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -28,8 +28,6 @@ from pylons.util import call_wsgi_application
 from timermiddleware import Timer, TimerMiddleware
 from webob import exc, Request
 import pysolr
-from beaker.middleware import SessionMiddleware
-from beaker.session import SessionObject
 
 from allura.lib import helpers as h
 import allura.model.repository
@@ -285,37 +283,33 @@ class AlluraTimerMiddleware(TimerMiddleware):
         return timers
 
 
-class RememberLoginSessionMiddleware(SessionMiddleware):
+class RememberLoginMiddleware(object):
     '''Modified version of beaker's SessionMiddleware.
     This middleware changes session's cookie expiration time according to login_expires
     session variable'''
-    
-    def __call__(self, environ, start_response):
-        session = SessionObject(environ, **self.options)
-        if environ.get('paste.registry'):
-            if environ['paste.registry'].reglist:
-                environ['paste.registry'].register(self.session, session)
-        environ[self.environ_key] = session
-        environ['beaker.get_session'] = self._get_session
 
-        if 'paste.testing_variables' in environ and 'webtest_varname' in self.options:
-            environ['paste.testing_variables'][self.options['webtest_varname']] = session
+    def __init__(self, app, config):
+        self.app = app
+        self.config = config
 
-        def session_start_response(status, headers, exc_info=None):
-            if session.accessed():
-                session.persist()
-
-                if session.__dict__['_headers']['set_cookie']:
-                    login_expires = session.get('login_expires')
-                    if login_expires is not None:
-                        session.cookie_expires = login_expires
-                        if login_expires == True:
-                            session.cookie[session.key]['expires'] = ''
-                        else:
-                            session._set_cookie_expires(None)
-                    cookie = session.cookie[session.key].output(header='')
-
-                    if cookie:
-                        headers.append(('Set-cookie', cookie))
+    def __call__(self, environ, start_response):
+
+        def remember_login_start_response(status, headers, exc_info=None):
+            session = environ.get('beaker.session')
+            userid = session.get('userid')
+            login_expires = session.get('login_expires')
+            if userid and login_expires is not None:
+                if login_expires is True:
+                    session.cookie[session.key]['expires'] = ''
+                else:
+                    session._set_cookie_expires(login_expires)
+                cookie = session.cookie[session.key].output(header='')
+                for i in range(len(headers)):
+                    header, contents = headers[i]
+                    if header == 'Set-cookie' and \
+                            contents.lstrip().startswith(session.key):
+                        headers[i] = ('Set-cookie', cookie)
+                        break
             return start_response(status, headers, exc_info)
-        return self.wrap_app(environ, session_start_response)
+
+        return self.app(environ, remember_login_start_response)


[14/28] git commit: [#7510] add license header and docstring to new script

Posted by je...@apache.org.
[#7510] add license header and docstring to new script


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/9828de98
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/9828de98
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/9828de98

Branch: refs/heads/je/42cc_7451
Commit: 9828de98139affa2ed0f9d5b684744566a7267e0
Parents: 9a1ea57
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Tue Jul 22 17:22:36 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jul 22 17:22:36 2014 +0000

----------------------------------------------------------------------
 scripts/prepare-allura-tickets-for-import.py | 24 ++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/9828de98/scripts/prepare-allura-tickets-for-import.py
----------------------------------------------------------------------
diff --git a/scripts/prepare-allura-tickets-for-import.py b/scripts/prepare-allura-tickets-for-import.py
index 16dd662..dc6a695 100644
--- a/scripts/prepare-allura-tickets-for-import.py
+++ b/scripts/prepare-allura-tickets-for-import.py
@@ -1,10 +1,32 @@
 #!/usr/bin/env python
+#       Licensed to the Apache Software Foundation (ASF) under one
+#       or more contributor license agreements.  See the NOTICE file
+#       distributed with this work for additional information
+#       regarding copyright ownership.  The ASF licenses this file
+#       to you under the Apache License, Version 2.0 (the
+#       "License"); you may not use this file except in compliance
+#       with the License.  You may obtain a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#       Unless required by applicable law or agreed to in writing,
+#       software distributed under the License is distributed on an
+#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#       KIND, either express or implied.  See the License for the
+#       specific language governing permissions and limitations
+#       under the License.
+
 from itertools import tee, izip, chain
 import json
 import git
 from collections import Counter
-from random import randint
 
+'''
+This script is for one-time conversion of Allura's own tickets from SourceForge
+host to forge-allura.apache.org hosting
+
+Change path variables here:
+'''
 
 filename = "/var/local/allura/tickets.json"  # Absolute path to exported tickets.json
 output = "/var/local/allura/updated_tickets.json"  # Absolute path to the output


[07/28] git commit: [#7523] change landing URL after email verification

Posted by je...@apache.org.
[#7523] change landing URL after email verification


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e2978623
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e2978623
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e2978623

Branch: refs/heads/je/42cc_7451
Commit: e2978623c63af48963cb1f7bd1232d12eaa7168f
Parents: 447d6a6
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Jul 2 21:49:38 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Jul 18 19:01:25 2014 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e2978623/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 72737cb..4d15a9a 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -239,7 +239,7 @@ class AuthController(BaseController):
             flash('Email address confirmed')
         else:
             flash('Unknown verification link', 'error')
-        redirect('/')
+        redirect('/auth/preferences/')
 
     @expose()
     def logout(self):


[13/28] git commit: [#7510] saved_bins bugfix, fixed milestone detection

Posted by je...@apache.org.
[#7510] saved_bins bugfix, fixed milestone detection


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/9a1ea57c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/9a1ea57c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/9a1ea57c

Branch: refs/heads/je/42cc_7451
Commit: 9a1ea57cdf64e34dfc1001d015597fcea195f3b7
Parents: eed1a39
Author: Alexander Luberg <al...@slashdotmedia.com>
Authored: Mon Jul 21 19:02:46 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jul 22 16:28:08 2014 +0000

----------------------------------------------------------------------
 Allura/allura/tasks/index_tasks.py           | 2 +-
 scripts/prepare-allura-tickets-for-import.py | 9 +++++----
 2 files changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/9a1ea57c/Allura/allura/tasks/index_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/index_tasks.py b/Allura/allura/tasks/index_tasks.py
index 2248855..3f02cef 100644
--- a/Allura/allura/tasks/index_tasks.py
+++ b/Allura/allura/tasks/index_tasks.py
@@ -73,7 +73,7 @@ def add_artifacts(ref_ids, update_solr=True, update_refs=True, solr_hosts=None):
         for ref in M.ArtifactReference.query.find(dict(_id={'$in': ref_ids})):
             try:
                 artifact = ref.artifact
-                if not artifact:
+                if artifact is None:
                     continue
                 s = artifact.solarize()
                 if s is None:

http://git-wip-us.apache.org/repos/asf/allura/blob/9a1ea57c/scripts/prepare-allura-tickets-for-import.py
----------------------------------------------------------------------
diff --git a/scripts/prepare-allura-tickets-for-import.py b/scripts/prepare-allura-tickets-for-import.py
index f1812ed..16dd662 100644
--- a/scripts/prepare-allura-tickets-for-import.py
+++ b/scripts/prepare-allura-tickets-for-import.py
@@ -3,6 +3,7 @@ from itertools import tee, izip, chain
 import json
 import git
 from collections import Counter
+from random import randint
 
 
 filename = "/var/local/allura/tickets.json"  # Absolute path to exported tickets.json
@@ -13,8 +14,6 @@ gitrepository = "/var/local/allura"  # Path to allura repository
 g = git.Git(gitrepository)
 
 reviews = ['code-review', 'design-review']
-backlog = ['open', 'in-progress', 'validation', 'review', 'blocked']
-released = ['closed', 'wont-fix', 'invalid']
 
 with open(filename, 'r') as json_file:
     data = json.loads(json_file.read())
@@ -53,9 +52,9 @@ for ticket in tickets:
 
         milestone = ticket_tag.get(ticket['ticket_num'], None)
         if not milestone:
-            if ticket['status'] in released:
+            if ticket['status'] == 'closed':
                 milestone = tags[0]
-        ticket['custom_fields']['_milestone'] = milestone if milestone != 'HEAD' else 'unreleased'
+        ticket['custom_fields']['_milestone'] = milestone if milestone and milestone != 'HEAD' else 'unreleased'
         if '_size' in ticket['custom_fields'].keys():
             size = ticket['custom_fields']['_size']
             if size:
@@ -98,6 +97,8 @@ data['custom_fields'].append({
     "options": "",
     "name": "_reviewer"
 })
+data['milestones'] = milestones
+data['saved_bins'] = []
 
 # Count top used usernames
 


[06/28] git commit: [#7523] add option to require an email address, which prevents deleting your last verified addr

Posted by je...@apache.org.
[#7523] add option to require an email address, which prevents deleting your last verified addr


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a707e7f2
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a707e7f2
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a707e7f2

Branch: refs/heads/je/42cc_7451
Commit: a707e7f2a2ef70664e62a3dba75ecf9428401bd9
Parents: 0234737
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Jul 2 20:59:49 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Jul 18 19:01:24 2014 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py | 23 ++++++++++++++++-------
 Allura/development.ini            |  1 +
 2 files changed, 17 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a707e7f2/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index f574730..1538c0b 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -373,6 +373,13 @@ class AuthController(BaseController):
             redirect('/')
 
 
+def select_new_primary_addr(user, ignore_emails=[]):
+    for obj_e in user.email_addresses:
+        obj = user.address_object(obj_e)
+        if obj and obj.confirmed and obj_e not in ignore_emails:
+            return obj_e
+
+
 class PreferencesController(BaseController):
 
     def _check_security(self):
@@ -407,8 +414,14 @@ class PreferencesController(BaseController):
                 obj = c.user.address_object(old_a)
                 if data.get('delete') or not obj:
                     if primary_addr == c.user.email_addresses[i]:
-                        c.user.set_pref('email_address', None)
-                        primary_addr = None
+                        if select_new_primary_addr(c.user, ignore_emails=primary_addr) is None \
+                                and asbool(config.get('auth.require_email_addr', False)):
+                            flash('You must have at least one verified email address.', 'error')
+                            redirect('.')
+                        else:
+                            # clear it now, a new one will get set below
+                            c.user.set_pref('email_address', None)
+                            primary_addr = None
                     del c.user.email_addresses[i]
                     if obj:
                         obj.delete()
@@ -423,11 +436,7 @@ class PreferencesController(BaseController):
                 else:
                     flash('Email address %s is invalid' % new_addr['addr'], 'error')
             if not primary_addr and not c.user.get_pref('email_address') and c.user.email_addresses:
-                for obj_e in c.user.email_addresses:
-                    obj = c.user.address_object(obj_e)
-                    if obj:
-                        if obj.confirmed:
-                            primary_addr = obj_e
+                primary_addr = select_new_primary_addr(c.user)
             if primary_addr:
                 c.user.set_pref('email_address', primary_addr)
             for k, v in preferences.iteritems():

http://git-wip-us.apache.org/repos/asf/allura/blob/a707e7f2/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 3010aa6..8c5e766 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -107,6 +107,7 @@ auth.allow_edit_prefs = true
 auth.allow_password_change = true
 auth.allow_upload_ssh_key = false
 auth.allow_user_messages_config = true
+auth.require_email_addr = true
 
 # In seconds
 auth.recovery_hash_expiry_period = 600


[11/28] git commit: [#7510] Script to prepare exported tickets for importing. Fixes for solr indexing.

Posted by je...@apache.org.
[#7510] Script to prepare exported tickets for importing. Fixes for solr indexing.


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/fdefd40d
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/fdefd40d
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/fdefd40d

Branch: refs/heads/je/42cc_7451
Commit: fdefd40d5b309d75ff3968c974829461f77fde17
Parents: 27e3d6a
Author: Alexander Luberg <al...@slashdotmedia.com>
Authored: Thu Jul 10 22:34:15 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jul 22 16:24:24 2014 +0000

----------------------------------------------------------------------
 Allura/allura/lib/markdown_extensions.py     |  2 +-
 Allura/allura/tasks/index_tasks.py           |  2 +
 scripts/prepare-allura-tickets-for-import.py | 72 +++++++++++++++++++++++
 3 files changed, 75 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/fdefd40d/Allura/allura/lib/markdown_extensions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/markdown_extensions.py b/Allura/allura/lib/markdown_extensions.py
index d2922c5..055a74a 100644
--- a/Allura/allura/lib/markdown_extensions.py
+++ b/Allura/allura/lib/markdown_extensions.py
@@ -335,7 +335,7 @@ class ForgeLinkPattern(markdown.inlinepatterns.LinkPattern):
             classes = 'alink'
         href = link
         shortlink = M.Shortlink.lookup(link)
-        if shortlink and not getattr(shortlink.ref.artifact, 'deleted', False):
+        if shortlink and shortlink.ref and not getattr(shortlink.ref.artifact, 'deleted', False):
             href = shortlink.url
             if getattr(shortlink.ref.artifact, 'is_closed', False):
                 classes += ' strikethrough'

http://git-wip-us.apache.org/repos/asf/allura/blob/fdefd40d/Allura/allura/tasks/index_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/index_tasks.py b/Allura/allura/tasks/index_tasks.py
index 3daf4ec..2248855 100644
--- a/Allura/allura/tasks/index_tasks.py
+++ b/Allura/allura/tasks/index_tasks.py
@@ -73,6 +73,8 @@ def add_artifacts(ref_ids, update_solr=True, update_refs=True, solr_hosts=None):
         for ref in M.ArtifactReference.query.find(dict(_id={'$in': ref_ids})):
             try:
                 artifact = ref.artifact
+                if not artifact:
+                    continue
                 s = artifact.solarize()
                 if s is None:
                     continue

http://git-wip-us.apache.org/repos/asf/allura/blob/fdefd40d/scripts/prepare-allura-tickets-for-import.py
----------------------------------------------------------------------
diff --git a/scripts/prepare-allura-tickets-for-import.py b/scripts/prepare-allura-tickets-for-import.py
new file mode 100644
index 0000000..da436d1
--- /dev/null
+++ b/scripts/prepare-allura-tickets-for-import.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+from itertools import tee, izip
+import json
+import git
+
+
+filename = "/Users/alexl/Code/allura-backup-2014-07-09-183025/tickets.json"  # Absolute path to exported tickets.json
+output = "/Users/alexl/Code/allura-backup-2014-07-09-183025/updated_tickets_100.json"  # Absolute path to the output
+
+gitrepository = "/Users/alexl/Code/allura-git"  # Path to allura repository
+g = git.Git(gitrepository)
+
+reviews = ['code-review', 'design-review']
+backlog = ['open', 'in-progress', 'validation', 'review', 'blocked']
+released = ['closed', 'wontfix', 'invalid']
+
+with open(filename, 'r') as json_file:
+    data = json.loads(json_file.read())
+
+
+def pairwise(iterable):
+    """s -> (s0,s1), (s1,s2), (s2, s3), ..."""
+    a, b = tee(iterable)
+    next(b, None)
+    return izip(a, b)
+
+
+tags = ['asf_release_1.0.0', 'asf_release_1.0.0-RC1', 'asf_release_1.0.1', 'asf_release_1.1.0']
+
+tag_log = dict()
+for tag1, tag2 in pairwise(tags):
+    log = g.log('%s...%s' % (tag1, tag2), '--pretty=oneline')
+    tag_log[tag2] = log
+
+ticket_tag = dict()
+tickets = data.pop('tickets')
+for ticket in tickets:
+    for key, value in tag_log.iteritems():
+        if "[#%s]" % ticket['ticket_num'] in value:
+            ticket_tag[ticket['ticket_num']] = key
+            continue
+
+del data['milestones']
+del data['saved_bins']
+
+updated = []
+for ticket in tickets:
+    if ticket['ticket_num'] == 6054 or (ticket['status'] != 'deleted' and not ticket['private']):
+        if ticket['status'] in reviews:
+            ticket['status'] = 'review'
+
+        milestone = ticket_tag.get(ticket['ticket_num'], None)
+        if not milestone:
+            if ticket['status'] in released:
+                milestone = tags[0]
+        ticket['custom_fields']['_milestone'] = milestone or 'unreleased'
+        if '_size' in ticket['custom_fields'].keys():
+            size = ticket['custom_fields']['_size']
+            if size:
+                ticket['labels'].append("sf-%d" % int(size))
+            del ticket['custom_fields']['_size']
+
+        if '_qa' in ticket['custom_fields'].keys():
+            ticket['custom_fields']['Reviewer'] = ticket['custom_fields']['_qa']
+            del ticket['custom_fields']['_qa']
+        updated.append(ticket)
+
+data['tickets'] = updated
+data['saved_bins'] = []
+data['milestones'] = []
+with open(output, 'w') as outfile:
+    json.dump(data, outfile)


[22/28] git commit: [#7451] ticket:605 Test for remember me function

Posted by je...@apache.org.
[#7451] ticket:605 Test for remember me function


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/47bb6775
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/47bb6775
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/47bb6775

Branch: refs/heads/je/42cc_7451
Commit: 47bb6775c974e961f942d8be506463438ebc0a8a
Parents: e694221
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 17 15:53:35 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:16:21 2014 +0300

----------------------------------------------------------------------
 Allura/allura/tests/functional/test_auth.py | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/47bb6775/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index c5c0330..698a73f 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -92,6 +92,29 @@ class TestAuth(TestController):
         assert_equal(user.last_access['login_ip'], 'addr')
         assert_equal(user.last_access['login_ua'], 'browser')
 
+    def test_rememberme(self):
+        userid = M.User.query.get(username='test-user')._id
+
+        # Login as test-user with remember me checkbox off
+        r = self.app.post('/auth/do_login', params=dict(
+            username='test-user', password='foo'))
+        assert_equal(r.session['userid'], userid)
+        assert_equal(r.session['login_expires'], True)
+
+        for header, contents in r.headerlist:
+            if header == 'Set-cookie':
+                assert_not_in('expires', contents)
+
+        # Login as test-user with remember me checkbox on
+        r = self.app.post('/auth/do_login', params=dict(
+            username='test-user', password='foo', rememberme='on'))
+        assert_equal(r.session['userid'], userid)
+        assert_not_equal(r.session['login_expires'], True)
+
+        for header, contents in r.headerlist:
+            if header == 'Set-cookie':
+                assert_in('expires', contents)
+
     @td.with_user_project('test-admin')
     def test_prefs(self):
         r = self.app.get('/auth/preferences/',


[16/28] git commit: [#7579] Send mails with sendsimplemail to have correct To: header

Posted by je...@apache.org.
[#7579] Send mails with sendsimplemail to have correct To: header


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2e1735cb
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2e1735cb
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2e1735cb

Branch: refs/heads/je/42cc_7451
Commit: 2e1735cbc4f59b274d74eac0620f3e937c3b649b
Parents: 0e18d9f
Author: Alexander Luberg <al...@slashdotmedia.com>
Authored: Wed Jul 23 20:44:57 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Jul 24 15:15:59 2014 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py           |  4 ++--
 Allura/allura/tasks/export_tasks.py         | 10 ++++++----
 Allura/allura/tasks/mail_tasks.py           | 19 +++++++++++++++++++
 Allura/allura/tests/functional/test_auth.py |  6 +++---
 Allura/allura/tests/test_tasks.py           |  2 +-
 Allura/docs/api/tasks.rst                   |  6 ++++++
 6 files changed, 37 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/2e1735cb/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 4d15a9a..8835b33 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -196,8 +196,8 @@ class AuthController(BaseController):
                 hash=hash,
             ))
 
-            allura.tasks.mail_tasks.sendmail.post(
-                destinations=[email],
+            allura.tasks.mail_tasks.sendsimplemail.post(
+                toaddr=email,
                 fromaddr=config['forgemail.return_path'],
                 reply_to=config['forgemail.return_path'],
                 subject=subject,

http://git-wip-us.apache.org/repos/asf/allura/blob/2e1735cb/Allura/allura/tasks/export_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/export_tasks.py b/Allura/allura/tasks/export_tasks.py
index d50d22b..eb9ff4d 100644
--- a/Allura/allura/tasks/export_tasks.py
+++ b/Allura/allura/tasks/export_tasks.py
@@ -83,16 +83,18 @@ class BulkExport(object):
             'tools': exported_names,
             'not_exported_tools': list(set(tools) - set(exported_names)),
         }
+
         email = {
-            'sender': unicode(tg.config['forgemail.return_path']),
+            'toaddr': unicode(user._id),
             'fromaddr': unicode(tg.config['forgemail.return_path']),
+            'sender': unicode(tg.config['forgemail.return_path']),
             'reply_to': unicode(tg.config['forgemail.return_path']),
             'message_id': h.gen_message_id(),
-            'destinations': [unicode(user._id)],
             'subject': u'Bulk export for project %s completed' % project.shortname,
-            'text': tmpl.render(tmpl_context),
+            'text': tmpl.render(tmpl_context)
         }
-        mail_tasks.sendmail.post(**email)
+
+        mail_tasks.sendsimplemail.post(**email)
 
     def get_export_path(self, export_base_path, export_filename):
         """Create temporary directory for export files"""

http://git-wip-us.apache.org/repos/asf/allura/blob/2e1735cb/Allura/allura/tasks/mail_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/mail_tasks.py b/Allura/allura/tasks/mail_tasks.py
index 9676842..4fce0d7 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -85,6 +85,10 @@ def route_email(
 @task
 def sendmail(fromaddr, destinations, text, reply_to, subject,
              message_id, in_reply_to=None, sender=None, references=None):
+    '''
+    Send an email to the specified list of destinations with respect to the preferred email format specified by user.
+    It is best for broadcast messages.
+    '''
     from allura import model as M
     addrs_plain = []
     addrs_html = []
@@ -157,6 +161,10 @@ def sendsimplemail(
         sender=None,
         references=None,
         cc=None):
+    '''
+    Send a single mail to the specified address.
+    It is best for single user notifications.
+    '''
     from allura import model as M
     if fromaddr is None:
         fromaddr = g.noreply
@@ -168,6 +176,17 @@ def sendsimplemail(
             fromaddr = g.noreply
         else:
             fromaddr = user.email_address_header()
+
+
+    if '@' not in toaddr:
+        log.warning('Looking up user with toaddr: %s', toaddr)
+        user = M.User.query.get(_id=ObjectId(toaddr), disabled=False)
+        if not user:
+            log.warning('Cannot find user with ID: %s', toaddr)
+            toaddr = g.noreply
+        else:
+            toaddr = user.email_address_header()
+
     htmlparser = HTMLParser.HTMLParser()
     plain_msg = mail_util.encode_email_part(htmlparser.unescape(text), 'plain')
     html_text = g.forge_markdown(email=True).convert(text)

http://git-wip-us.apache.org/repos/asf/allura/blob/2e1735cb/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index a200352..c5c0330 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -706,7 +706,7 @@ class TestPasswordReset(TestController):
         hash = user.get_tool_data('AuthPasswordReset', 'hash')
         assert hash is None
 
-    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.tasks.mail_tasks.sendsimplemail')
     @patch('allura.lib.helpers.gen_message_id')
     def test_password_reset(self, gen_message_id, sendmail):
         user = M.User.query.get(username='test-admin')
@@ -740,7 +740,7 @@ To reset your password on %s, please visit the following URL:
 %s/auth/forgotten_password/%s''' % (config['site_name'], config['base_url'], hash)
 
         sendmail.post.assert_called_once_with(
-            destinations=[email._id],
+            toaddr=email._id,
             fromaddr=config['forgemail.return_path'],
             reply_to=config['forgemail.return_path'],
             subject='Allura Password recovery',
@@ -752,7 +752,7 @@ To reset your password on %s, please visit the following URL:
         assert_equal(hash, '')
         assert_equal(hash_expiry, '')
 
-    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.tasks.mail_tasks.sendsimplemail')
     @patch('allura.lib.helpers.gen_message_id')
     def test_hash_expired(self, gen_message_id, sendmail):
         user = M.User.query.get(username='test-admin')

http://git-wip-us.apache.org/repos/asf/allura/blob/2e1735cb/Allura/allura/tests/test_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 97c7699..5dd70b6 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -516,7 +516,7 @@ class TestExportTasks(unittest.TestCase):
         # check notification
         M.MonQTask.run_ready()
         tasks = M.MonQTask.query.find(
-            dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
+            dict(task_name='allura.tasks.mail_tasks.sendsimplemail')).all()
         assert_equal(len(tasks), 1)
         assert_equal(tasks[0].kwargs['subject'],
                      'Bulk export for project test completed')

http://git-wip-us.apache.org/repos/asf/allura/blob/2e1735cb/Allura/docs/api/tasks.rst
----------------------------------------------------------------------
diff --git a/Allura/docs/api/tasks.rst b/Allura/docs/api/tasks.rst
index d49b8af..0ae3b1d 100644
--- a/Allura/docs/api/tasks.rst
+++ b/Allura/docs/api/tasks.rst
@@ -28,3 +28,9 @@
   .. automodule:: allura.tasks.export_tasks
 
         .. autofunction:: allura.tasks.export_tasks.bulk_export
+
+  .. automodule:: allura.tasks.mail_tasks
+
+        .. autofunction:: allura.tasks.mail_tasks.sendmail
+
+        .. autofunction:: allura.tasks.mail_tasks.sendsimplemail
\ No newline at end of file


[17/28] git commit: [#7451] ticket:605 Cleaned up code of session middleware

Posted by je...@apache.org.
[#7451] ticket:605 Cleaned up code of session middleware


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e694221b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e694221b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e694221b

Branch: refs/heads/je/42cc_7451
Commit: e694221b9e08ebbedc5bd1b2d04cd3588a873120
Parents: a40f29a
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 17 14:35:57 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:14:46 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/custom_middleware.py | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e694221b/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 73cfef3..a8fc04e 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -301,21 +301,17 @@ class RememberLoginSessionMiddleware(SessionMiddleware):
         def session_start_response(status, headers, exc_info=None):
             if session.accessed():
                 session.persist()
-                cookie_out = None
-                login_expires = session.get('login_expires')
-                if login_expires is not None:
-                    session.cookie_expires = login_expires
-                    if login_expires == True:
-                        session.cookie[session.key]['expires'] = ''
-                    else:
-                        session._set_cookie_expires(None)
-                    cookie_out = session.cookie[session.key].output(header='')
 
                 if session.__dict__['_headers']['set_cookie']:
-                    if cookie_out:
-                        cookie = cookie_out
-                    else:
-                        cookie = session.__dict__['_headers']['cookie_out']
+                    login_expires = session.get('login_expires')
+                    if login_expires is not None:
+                        session.cookie_expires = login_expires
+                        if login_expires == True:
+                            session.cookie[session.key]['expires'] = ''
+                        else:
+                            session._set_cookie_expires(None)
+                    cookie = session.cookie[session.key].output(header='')
+
                     if cookie:
                         headers.append(('Set-cookie', cookie))
             return start_response(status, headers, exc_info)


[05/28] git commit: [#7523] tell user verification email is coming, so they dont click the verify link and reset the hash

Posted by je...@apache.org.
[#7523] tell user verification email is coming, so they dont click the verify link and reset the hash


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/447d6a64
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/447d6a64
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/447d6a64

Branch: refs/heads/je/42cc_7451
Commit: 447d6a64a2f98b654cc0a354c2b85c10117dde49
Parents: a707e7f
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Jul 2 21:00:19 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Jul 18 19:01:24 2014 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/447d6a64/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 1538c0b..72737cb 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -433,6 +433,7 @@ class PreferencesController(BaseController):
                     em = M.EmailAddress.upsert(new_addr['addr'])
                     em.claimed_by_user_id = c.user._id
                     em.send_verification_link()
+                    flash('A verification email has been sent.  Please check your email and click to confirm.')
                 else:
                     flash('Email address %s is invalid' % new_addr['addr'], 'error')
             if not primary_addr and not c.user.get_pref('email_address') and c.user.email_addresses:


[24/28] git commit: [#7451] ticket:605 Removed unnecessary option in config

Posted by je...@apache.org.
[#7451] ticket:605 Removed unnecessary option in config


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/4809319e
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/4809319e
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/4809319e

Branch: refs/heads/je/42cc_7451
Commit: 4809319e4721e7c568f4f866b67ebdaf1fdbc507
Parents: 47bb677
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 17 17:11:28 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:16:21 2014 +0300

----------------------------------------------------------------------
 Allura/development.ini | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/4809319e/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 71855c7..b7c52e0 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -60,7 +60,6 @@ cache_dir = %(here)s/data
 beaker.session.key = allura
 beaker.session.type = cookie
 beaker.session.httponly = true
-beaker.session.cookie_expires = false
 ; CHANGE THIS VALUE FOR YOUR SITE
 beaker.session.validate_key = 714bfe3612c42390726f
 


[25/28] git commit: [#7451] ticket:616 Tweaked styling of login form

Posted by je...@apache.org.
[#7451] ticket:616 Tweaked styling of login form


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5d508404
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5d508404
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5d508404

Branch: refs/heads/je/42cc_7451
Commit: 5d5084045124c4789e85dcc441b471a2eddfa56b
Parents: 335843e
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Thu Jul 24 22:04:17 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:16:21 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/widgets/auth_widgets.py  | 4 +++-
 Allura/allura/nf/allura/css/site_style.css | 4 ++++
 2 files changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/5d508404/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 7f5079f..7f7a011 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -44,7 +44,9 @@ class LoginForm(ForgeForm):
         if plugin.AuthenticationProvider.get(request).forgotten_password_process:
             # only show link if auth provider has method of recovering password
             fields.append(
-                ew.HTMLField(name='link', text='<a href="forgotten_password">Forgot password?</a>'))
+                ew.HTMLField(
+                    name='link', text='<div class="forgotten-password">'
+                    '<a href="forgotten_password">Forgot password?</a></div>'))
         return fields
 
     @validator

http://git-wip-us.apache.org/repos/asf/allura/blob/5d508404/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index 8f8d5ab..7fd7528 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -3497,3 +3497,7 @@ ul.dropdown ul li a:hover {
     top: 10px;
 }
 .strikethrough { text-decoration: line-through; }
+/* Login form */
+#loginform input[name="rememberme"], #loginform .forgotten-password {
+  margin-left: 162px;
+}


[02/28] git commit: [#5939] fix icon sprites on project permission page

Posted by je...@apache.org.
[#5939] fix icon sprites on project permission page


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/12b1649e
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/12b1649e
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/12b1649e

Branch: refs/heads/je/42cc_7451
Commit: 12b1649e10848fa480cc921e2bf0c7ca571875cf
Parents: 09685f8
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Tue Jul 1 14:54:14 2014 +0000
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Fri Jul 18 08:40:38 2014 +0000

----------------------------------------------------------------------
 Allura/allura/nf/allura/css/allura.css     | 3 ++-
 Allura/allura/nf/allura/css/site_style.css | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/12b1649e/Allura/allura/nf/allura/css/allura.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/allura.css b/Allura/allura/nf/allura/css/allura.css
index b7579bf..4087e1e 100644
--- a/Allura/allura/nf/allura/css/allura.css
+++ b/Allura/allura/nf/allura/css/allura.css
@@ -48,7 +48,7 @@ b.ico.ico-plus { background-position: -16px -128px; }
 b.ico.ico-minus { background-position: -48px -128px; }
 b.ico.ico-minuscirc { background-position: -48px -128px; }
 b.ico.ico-undelete { background-position: 0px -64px; }
-b.ico.ico-delete { background-position: -80px -128px; }
+b.ico.ico-delete, b.ico.ico-noentry { background-position: -80px -128px; }
 b.ico.ico-help { background-position: -48px -144px; }
 b.ico.ico-pin { background-position: -144px -144px; }
 b.ico.ico-feed { background-position: -16px -176px; }
@@ -56,6 +56,7 @@ b.ico.ico-close { background-position: -80px -128px; }
 b.ico.ico-vote-up { background-image: url('../images/vote_up.png'); }
 b.ico.ico-vote-down { background-image: url('../images/vote_down.png'); }
 b.ico.ico-star { background-position: -240px -96px; }
+b.ico.ico-check, b.ico.ico-checkcircle { background-position: -64px -144px; } /* TODO: these should be separate images */
 
 
 #ticket_search_results_holder{

http://git-wip-us.apache.org/repos/asf/allura/blob/12b1649e/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index c4b7326..8f8d5ab 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -1213,6 +1213,7 @@ nav .ico {
   text-transform: none;
 }
 
+/* these don't work with sprite images (only if the icons were font-based)
 .x16 {
   font-size: 16px;
   width: 16px;
@@ -1242,6 +1243,7 @@ nav .ico {
   width: 64px;
   height: 64px;
 }
+*/
 
 .modal b.close {
   position: absolute;


[03/28] git commit: [#7378] ticket:611 Don't include comments held for moderation into feed

Posted by je...@apache.org.
[#7378] ticket:611 Don't include comments held for moderation into feed


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/b6d0bc0d
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/b6d0bc0d
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/b6d0bc0d

Branch: refs/heads/je/42cc_7451
Commit: b6d0bc0d4df02024d66b81bf2da1aef2ca1f12eb
Parents: 12b1649
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri Jul 18 13:50:14 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Jul 18 18:49:30 2014 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/discuss.py           |  9 ++++++---
 Allura/allura/model/discuss.py                 | 20 ++++++++++++++------
 Allura/allura/tests/functional/test_discuss.py | 18 ++++++++++++++++++
 3 files changed, 38 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/b6d0bc0d/Allura/allura/controllers/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index cd4e8a1..c7fe163 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -356,9 +356,11 @@ class PostController(BaseController):
         elif kw.pop('spam', None):
             self.post.spam()
         elif kw.pop('approve', None):
-            self.post.status = 'ok'
-            g.spam_checker.submit_ham(
-                self.post.text, artifact=self.post, user=c.user)
+            if self.post.status != 'ok':
+                self.post.status = 'ok'
+                g.spam_checker.submit_ham(
+                    self.post.text, artifact=self.post, user=c.user)
+                self.post.thread.post_to_feed(self.post)
         self.thread.update_stats()
         return dict(result='success')
 
@@ -480,6 +482,7 @@ class ModerationController(BaseController):
                             posted.thread.last_post_date,
                             posted.mod_date)
                         posted.thread.num_replies += 1
+                        posted.thread.post_to_feed(posted)
         redirect(request.referer)
 
 

http://git-wip-us.apache.org/repos/asf/allura/blob/b6d0bc0d/Allura/allura/model/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 1f19208..22456e5 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -235,6 +235,19 @@ class Thread(Artifact, ActivityObject):
             return self
         return self.ref.artifact
 
+    def post_to_feed(self, post):
+        if self.ref and post.status == 'ok':
+            link = None
+            if self.app.tool_label.lower() == 'tickets':
+                link = post.url_paginated()
+            Feed.post(
+                self.primary(),
+                title=post.subject,
+                description=post.text,
+                link=link,
+                pubdate=post.mod_date,
+            )
+
     def add_post(self, **kw):
         """Helper function to avoid code duplication."""
         p = self.post(**kw)
@@ -242,12 +255,7 @@ class Thread(Artifact, ActivityObject):
         self.num_replies += 1
         if not self.first_post:
             self.first_post_id = p._id
-        link = None
-        if self.app.tool_label.lower() == 'tickets':
-            link = p.url_paginated()
-        if self.ref:
-            Feed.post(self.primary(), title=p.subject,
-                      description=p.text, link=link)
+        self.post_to_feed(p)
         return p
 
     def is_spam(self, post):

http://git-wip-us.apache.org/repos/asf/allura/blob/b6d0bc0d/Allura/allura/tests/functional/test_discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index ca3fcbd..31e454e 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 from mock import patch
+from nose.tools import assert_in, assert_not_in, assert_equal
 
 from allura.tests import TestController
 from allura import model as M
@@ -172,6 +173,23 @@ class TestDiscuss(TestController):
         self.app.post(post_link + 'moderate', params=dict(delete='delete'))
         assert M.Post.query.find().count() == 0
 
+    @patch.object(M.Thread, 'is_spam')
+    def test_feed_does_not_include_comments_held_for_moderation(self, is_spam):
+        is_spam.return_value = True
+        r = self._make_post('Post needs moderation!')
+        post_link = str(
+            r.html.find('div', {'class': 'edit_post_form reply'}).find('form')['action'])
+        post = M.Post.query.find().first()
+        assert_equal(post.status, 'pending')
+        r = self.app.get('/wiki/feed.rss')
+        assert_not_in('Post needs moderation!', r)
+
+        self.app.post(post_link + 'moderate', params=dict(approve='approve'))
+        post = M.Post.query.find().first()
+        assert_equal(post.status, 'ok')
+        r = self.app.get('/wiki/feed.rss')
+        assert_in('Post needs moderation!', r)
+
     def test_post_paging(self):
         home = self.app.get('/wiki/_discuss/')
         thread_link = [a for a in home.html.findAll('a')


[20/28] git commit: [#7451] ticket:605 Save login expiration date in session

Posted by je...@apache.org.
[#7451] ticket:605 Save login expiration date in session


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/dedd58c5
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/dedd58c5
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/dedd58c5

Branch: refs/heads/je/42cc_7451
Commit: dedd58c5f64c2201ab49cd3b100fa4832c6430c0
Parents: 12aaf70
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Wed Jul 16 13:43:09 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:14:46 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/plugin.py | 6 ++++--
 Allura/development.ini      | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/dedd58c5/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 051b795..4fd6583 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -142,9 +142,10 @@ class AuthenticationProvider(object):
             if self.is_password_expired(user):
                 self.session['pwd-expired'] = True
             if 'rememberme' in self.request.params:
-                self.session.cookie_expires = datetime.utcnow() + timedelta(365)
+                remember_for = int(config.get('auth.remember_for', 365))
+                self.session['login_expires'] = datetime.utcnow() + timedelta(remember_for)
             else:
-                self.session.cookie_expires = True
+                self.session['login_expires'] = True
             self.session.save()
             g.zarkov_event('login', user=user)
             g.statsUpdater.addUserLogin(user)
@@ -156,6 +157,7 @@ class AuthenticationProvider(object):
 
     def logout(self):
         self.session['userid'] = None
+        self.session['login_expires'] = None
         self.session['pwd-expired'] = False
         self.session.save()
 

http://git-wip-us.apache.org/repos/asf/allura/blob/dedd58c5/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 8c5e766..b7c52e0 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -73,6 +73,7 @@ show_export_control = false
 
 # auth.method = ldap
 auth.method = local
+auth.remember_for = 365
 # auth.login_url = /auth/
 # auth.logout_url = /auth/logout
 # auth.login_fragment_url = /auth/login_fragment


[18/28] git commit: [#7451] ticket:605 Added Remember me option to login form

Posted by je...@apache.org.
[#7451] ticket:605 Added Remember me option to login form


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/798a40cb
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/798a40cb
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/798a40cb

Branch: refs/heads/je/42cc_7451
Commit: 798a40cb6952b2fedbd475fb5fcee1076e82b0aa
Parents: 2e1735c
Author: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Authored: Mon Jul 14 21:17:39 2014 +0300
Committer: Aleksey 'LXj' Alekseyev <go...@gmail.com>
Committed: Thu Jul 24 22:14:46 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/plugin.py               | 4 ++++
 Allura/allura/lib/widgets/auth_widgets.py | 1 +
 2 files changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/798a40cb/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index a5c3f65..cd8419d 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -141,6 +141,10 @@ class AuthenticationProvider(object):
             self.session['userid'] = user._id
             if self.is_password_expired(user):
                 self.session['pwd-expired'] = True
+            if 'rememberme' in self.request.params:
+                self.session.cookie_expires = datetime.now() + timedelta(365)
+            else:
+                self.session.cookie_expires = True
             self.session.save()
             g.zarkov_event('login', user=user)
             g.statsUpdater.addUserLogin(user)

http://git-wip-us.apache.org/repos/asf/allura/blob/798a40cb/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 567cd54..7ea416f 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -38,6 +38,7 @@ class LoginForm(ForgeForm):
         fields = [
             ew.TextField(name='username', label='Username'),
             ew.PasswordField(name='password', label='Password'),
+            ew.Checkbox(name='rememberme', label='Remember Me'),
             ew.HiddenField(name='return_to'),
         ]
         if plugin.AuthenticationProvider.get(request).forgotten_password_process:


[10/28] git commit: [#7480] ticket:610 Add last_access field to scrub-allura-data script

Posted by je...@apache.org.
[#7480] ticket:610 Add last_access field to scrub-allura-data script


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/27e3d6ab
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/27e3d6ab
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/27e3d6ab

Branch: refs/heads/je/42cc_7451
Commit: 27e3d6abc9b45c1d6d4dc653bb10b6062befb3e2
Parents: 273dcf2
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jul 17 16:33:19 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Jul 21 14:57:47 2014 +0000

----------------------------------------------------------------------
 scripts/scrub-allura-data.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/27e3d6ab/scripts/scrub-allura-data.py
----------------------------------------------------------------------
diff --git a/scripts/scrub-allura-data.py b/scripts/scrub-allura-data.py
index 3864c42..337e8ae 100644
--- a/scripts/scrub-allura-data.py
+++ b/scripts/scrub-allura-data.py
@@ -125,7 +125,10 @@ def main(options):
 
     if not options.dry_run:
         M.EmailAddress.query.remove()
-        M.User.query.update({}, {"$set": {"email_addresses": []}}, multi=True)
+        M.User.query.update({}, {
+            "$set": {"email_addresses": [],
+                     "last_access": {}},
+        }, multi=True)
         DM.Forum.query.update({"monitoring_email": {"$nin": [None, ""]}},
                               {"$set": {"monitoring_email": None}}, multi=True)
     return 0


[28/28] git commit: [#7451] ticket:616 Inline login form specific styles

Posted by je...@apache.org.
[#7451] ticket:616 Inline login form specific styles


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5e066d9c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5e066d9c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5e066d9c

Branch: refs/heads/je/42cc_7451
Commit: 5e066d9cd4ca9c77959fbda4c65520871d4c4df0
Parents: 5d50840
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri Jul 25 10:52:37 2014 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Fri Jul 25 10:52:37 2014 +0300

----------------------------------------------------------------------
 Allura/allura/lib/widgets/auth_widgets.py  | 10 +++++++---
 Allura/allura/nf/allura/css/site_style.css |  4 ----
 2 files changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/5e066d9c/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 7f7a011..3f3d66a 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -38,15 +38,19 @@ class LoginForm(ForgeForm):
         fields = [
             ew.TextField(name='username', label='Username'),
             ew.PasswordField(name='password', label='Password'),
-            ew.Checkbox(name='rememberme', label='Remember Me'),
+            ew.Checkbox(
+                name='rememberme',
+                label='Remember Me',
+                attrs={'style': 'margin-left: 162px;'}),
             ew.HiddenField(name='return_to'),
         ]
         if plugin.AuthenticationProvider.get(request).forgotten_password_process:
             # only show link if auth provider has method of recovering password
             fields.append(
                 ew.HTMLField(
-                    name='link', text='<div class="forgotten-password">'
-                    '<a href="forgotten_password">Forgot password?</a></div>'))
+                    name='link',
+                    text='<a href="forgotten_password" style="margin-left:162px">'
+                         'Forgot password?</a>'))
         return fields
 
     @validator

http://git-wip-us.apache.org/repos/asf/allura/blob/5e066d9c/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index 7fd7528..8f8d5ab 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -3497,7 +3497,3 @@ ul.dropdown ul li a:hover {
     top: 10px;
 }
 .strikethrough { text-decoration: line-through; }
-/* Login form */
-#loginform input[name="rememberme"], #loginform .forgotten-password {
-  margin-left: 162px;
-}


[12/28] git commit: [#7510] output top usernames, fixed milestone detection, updated custom_fields

Posted by je...@apache.org.
[#7510] output top usernames, fixed milestone detection, updated custom_fields


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/eed1a399
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/eed1a399
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/eed1a399

Branch: refs/heads/je/42cc_7451
Commit: eed1a3990fdef7c6a6e8ae7ad4f466293bea6319
Parents: fdefd40
Author: Alexander Luberg <al...@slashdotmedia.com>
Authored: Thu Jul 17 12:28:45 2014 -0700
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Tue Jul 22 16:24:25 2014 +0000

----------------------------------------------------------------------
 scripts/prepare-allura-tickets-for-import.py | 86 ++++++++++++++++++-----
 1 file changed, 69 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/eed1a399/scripts/prepare-allura-tickets-for-import.py
----------------------------------------------------------------------
diff --git a/scripts/prepare-allura-tickets-for-import.py b/scripts/prepare-allura-tickets-for-import.py
index da436d1..f1812ed 100644
--- a/scripts/prepare-allura-tickets-for-import.py
+++ b/scripts/prepare-allura-tickets-for-import.py
@@ -1,18 +1,20 @@
 #!/usr/bin/env python
-from itertools import tee, izip
+from itertools import tee, izip, chain
 import json
 import git
+from collections import Counter
 
 
-filename = "/Users/alexl/Code/allura-backup-2014-07-09-183025/tickets.json"  # Absolute path to exported tickets.json
-output = "/Users/alexl/Code/allura-backup-2014-07-09-183025/updated_tickets_100.json"  # Absolute path to the output
-
-gitrepository = "/Users/alexl/Code/allura-git"  # Path to allura repository
+filename = "/var/local/allura/tickets.json"  # Absolute path to exported tickets.json
+output = "/var/local/allura/updated_tickets.json"  # Absolute path to the output
+ticket_list = "/var/local/allura/ticket_ids.list"
+top_usernames = "/var/local/allura/top_usernames.list"
+gitrepository = "/var/local/allura"  # Path to allura repository
 g = git.Git(gitrepository)
 
 reviews = ['code-review', 'design-review']
 backlog = ['open', 'in-progress', 'validation', 'review', 'blocked']
-released = ['closed', 'wontfix', 'invalid']
+released = ['closed', 'wont-fix', 'invalid']
 
 with open(filename, 'r') as json_file:
     data = json.loads(json_file.read())
@@ -25,7 +27,7 @@ def pairwise(iterable):
     return izip(a, b)
 
 
-tags = ['asf_release_1.0.0', 'asf_release_1.0.0-RC1', 'asf_release_1.0.1', 'asf_release_1.1.0']
+tags = ['asf_release_1.0.0', 'asf_release_1.0.0-RC1', 'asf_release_1.0.1', 'asf_release_1.1.0', 'HEAD']
 
 tag_log = dict()
 for tag1, tag2 in pairwise(tags):
@@ -40,12 +42,12 @@ for ticket in tickets:
             ticket_tag[ticket['ticket_num']] = key
             continue
 
-del data['milestones']
-del data['saved_bins']
+data.pop('milestones', None)
+data.pop('saved_bins', None)
 
 updated = []
 for ticket in tickets:
-    if ticket['ticket_num'] == 6054 or (ticket['status'] != 'deleted' and not ticket['private']):
+    if not ticket['private'] or ticket['ticket_num'] == 6054:
         if ticket['status'] in reviews:
             ticket['status'] = 'review'
 
@@ -53,20 +55,70 @@ for ticket in tickets:
         if not milestone:
             if ticket['status'] in released:
                 milestone = tags[0]
-        ticket['custom_fields']['_milestone'] = milestone or 'unreleased'
+        ticket['custom_fields']['_milestone'] = milestone if milestone != 'HEAD' else 'unreleased'
         if '_size' in ticket['custom_fields'].keys():
             size = ticket['custom_fields']['_size']
             if size:
                 ticket['labels'].append("sf-%d" % int(size))
-            del ticket['custom_fields']['_size']
+            ticket['custom_fields'].pop('_size', None)
 
         if '_qa' in ticket['custom_fields'].keys():
-            ticket['custom_fields']['Reviewer'] = ticket['custom_fields']['_qa']
-            del ticket['custom_fields']['_qa']
+            ticket['custom_fields']['_reviewer'] = ticket['custom_fields']['_qa']
+            ticket['custom_fields'].pop('_qa', None)
         updated.append(ticket)
+tags[-1] = 'unreleased'
 
 data['tickets'] = updated
-data['saved_bins'] = []
-data['milestones'] = []
+
+# Remove milestones from the list
+custom_fields = filter(lambda d: d.get('name') not in ['_milestone', 'name', '_size', '_qa'], data['custom_fields'])
+data['custom_fields'] = custom_fields
+
+milestones = {
+    "milestones": [
+        dict(name=milestone_name,
+             old_name=milestone_name,
+             default=False,
+             complete=False,
+             due_date="",
+             description="")
+        for milestone_name in tags
+    ],
+    "name": "_milestone",
+    "show_in_search": False,
+    "label": "Milestone",
+    "type": "milestone",
+    "options": ""
+}
+data['custom_fields'].append(milestones)
+data['custom_fields'].append({
+    "show_in_search": True,
+    "label": "Reviewer",
+    "type": "user",
+    "options": "",
+    "name": "_reviewer"
+})
+
+# Count top used usernames
+
+assigned_to = [ticket.get('assigned_to', None) for ticket in updated]
+reported_by = [ticket.get('reported_by', None) for ticket in updated]
+reviewed_by = [ticket['custom_fields'].get('_reviewer', None) for ticket in updated]
+
+posts = [ticket['discussion_thread']['posts'] for ticket in updated]
+
+post_authors = [post.get('author', None) for post in list(chain(*posts))]
+
+usernames = filter(lambda x: bool(x), chain(assigned_to, reported_by, reviewed_by, post_authors))
+
+top_users = Counter(usernames).most_common(50)
+
 with open(output, 'w') as outfile:
-    json.dump(data, outfile)
+    json.dump(data, outfile, indent=2)
+
+with open(ticket_list, 'w') as outfile:
+    outfile.write('\n'.join(sorted([str(ticket['ticket_num']) for ticket in updated])))
+
+with open(top_usernames, 'w') as outfile:
+    lines = ["%s - %s" % (username, frequency) for username, frequency in top_users]
+    outfile.write('\n'.join(lines))
\ No newline at end of file