You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2018/03/08 20:43:27 UTC

[1/2] allura git commit: [#8193] Adds ability to rate-limit comments

Repository: allura
Updated Branches:
  refs/heads/master 6742f0f15 -> 334868b5f


[#8193] Adds ability to rate-limit comments


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

Branch: refs/heads/master
Commit: 5359a3bc3034375264c88e0134fb570157fb3e29
Parents: 6742f0f
Author: Kenton Taylor <kt...@slashdotmedia.com>
Authored: Wed Mar 7 12:06:15 2018 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Mar 8 15:37:48 2018 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/base.py              | 14 ++++++++++++++
 Allura/allura/controllers/discuss.py           |  2 ++
 Allura/allura/tests/functional/test_discuss.py | 15 +++++++++++++--
 Allura/development.ini                         |  2 ++
 ForgeBlog/forgeblog/main.py                    | 16 ++++------------
 ForgeTracker/forgetracker/tracker_main.py      | 10 ++--------
 ForgeWiki/forgewiki/wiki_main.py               | 13 +++----------
 7 files changed, 40 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/Allura/allura/controllers/base.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/base.py b/Allura/allura/controllers/base.py
index 215b19d..2cf0c70 100644
--- a/Allura/allura/controllers/base.py
+++ b/Allura/allura/controllers/base.py
@@ -15,9 +15,16 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+import logging
+
 from tg import expose
 from webob import exc
 from tg.controllers.dispatcher import ObjectDispatcher
+from tg import redirect, flash
+from pylons import tmpl_context as c
+
+
+log = logging.getLogger(__name__)
 
 
 class BaseController(object):
@@ -28,6 +35,13 @@ class BaseController(object):
         and possible loops."""
         raise exc.HTTPNotFound, name
 
+    def rate_limit(self, artifact_class, message, redir='..'):
+        if artifact_class.is_limit_exceeded(c.app.config, user=c.user):
+            msg = '{} rate limit exceeded. '.format(message)
+            log.warn(msg + c.app.config.url())
+            flash(msg + 'Please try again later.', 'error')
+            redirect(redir)
+
 
 class DispatchIndex(object):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/Allura/allura/controllers/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index a61a9e1..ba31409 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -209,6 +209,7 @@ class ThreadController(BaseController, FeedController):
     @utils.AntiSpam.validate('Spambot protection engaged')
     def post(self, **kw):
         require_access(self.thread, 'post')
+        self.rate_limit(M.Post, "Comment", redir='..')
         if self.thread.ref:
             require_access(self.thread.ref.artifact, 'post')
         kw = self.W.edit_post.to_python(kw, None)
@@ -344,6 +345,7 @@ class PostController(BaseController):
     @require_post(redir='.')
     def reply(self, file_info=None, **kw):
         require_access(self.thread, 'post')
+        self.rate_limit(M.Post, "Comment", redir='..')
         kw = self.W.edit_post.to_python(kw, None)
         p = self.thread.add_post(parent_id=self.post._id, **kw)
         p.add_multiple_attachments(file_info)

http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/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 d6af6c9..8f3c968 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -17,12 +17,15 @@
 
 import os
 from mock import patch
-from nose.tools import assert_in, assert_not_in, assert_equal, assert_false, assert_true
-
+from nose.tools import assert_in, assert_not_in, assert_equal, assert_false, assert_true, assert_raises
+from webtest.app import AppError
 from ming.odm import session
 
 from allura.tests import TestController
 from allura import model as M
+from allura.lib import helpers as h
+from tg import config
+
 
 
 class TestDiscussBase(TestController):
@@ -128,6 +131,14 @@ class TestDiscuss(TestDiscussBase):
         assert submit_spam.call_args[0] == (
             'This is a new post',), submit_spam.call_args[0]
 
+    def test_rate_limit(self):
+        with h.push_config(config, **{'allura.rate_limits_per_user': '{"3600": 2}'}):
+            for i in range(0, 2):
+                self._make_post('This is a post {}'.format(i))
+            with assert_raises(AppError):
+                self._make_post('This is a post that should fail.')
+            return 'foo'
+
     def test_permissions(self):
         thread_url = self._thread_link()
         thread_id = thread_url.rstrip('/').split('/')[-1]

http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index d3f2700..e43be7d 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -532,6 +532,8 @@ forgemail.domain = .in.localhost
 ;forgewiki.rate_limits_per_user =    {"60": 3, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}
 ;forgetracker.rate_limits_per_user = {"60": 1, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}
 ;forgeblog.rate_limits_per_user =    {"60": 1, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}
+;allura.rate_limits_per_user =    {"60": 1, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}
+
 
 ; set this to "false" if you are deploying to production and want performance improvements
 auto_reload_templates = true

http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/ForgeBlog/forgeblog/main.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index a227ca8..578432c 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -233,14 +233,6 @@ class ForgeBlogApp(Application):
                 self.save_attachments(post_path, post.attachments)
 
 
-def rate_limit():
-    if BM.BlogPost.is_limit_exceeded(c.app.config, user=c.user):
-        msg = 'Create/edit rate limit exceeded. '
-        log.warn(msg + c.app.config.url())
-        flash(msg + 'Please try again later.', 'error')
-        redirect(c.app.config.url())
-
-
 class RootController(BaseController, FeedController):
 
     def __init__(self):
@@ -293,7 +285,7 @@ class RootController(BaseController, FeedController):
     @without_trailing_slash
     def new(self, **kw):
         require_access(c.app, 'write')
-        rate_limit()
+        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
         post = dict(
             state='published')
         c.form = W.new_post_form
@@ -305,7 +297,7 @@ class RootController(BaseController, FeedController):
     @without_trailing_slash
     def save(self, **kw):
         require_access(c.app, 'write')
-        rate_limit()
+        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
         post = BM.BlogPost.new(**kw)
         g.spam_checker.check(kw['title'] + u'\n' + kw['text'], artifact=post,
                              user=c.user, content_type='blog-post')
@@ -373,7 +365,7 @@ class PostController(BaseController, FeedController):
     @without_trailing_slash
     def edit(self, **kw):
         require_access(self.post, 'write')
-        rate_limit()
+        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
         c.form = W.edit_post_form
         c.attachment_add = W.attachment_add
         c.attachment_list = W.attachment_list
@@ -400,7 +392,7 @@ class PostController(BaseController, FeedController):
     @without_trailing_slash
     def save(self, delete=None, **kw):
         require_access(self.post, 'write')
-        rate_limit()
+        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
         if delete:
             self.post.delete()
             flash('Post deleted', 'info')

http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 1f9822b..8c8e626 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -652,12 +652,6 @@ class RootController(BaseController, FeedController):
     def _check_security(self):
         require_access(c.app, 'read')
 
-    def rate_limit(self, redir='..'):
-        if TM.Ticket.is_limit_exceeded(c.app.config, user=c.user):
-            msg = 'Ticket creation rate limit exceeded. '
-            log.warn(msg + c.app.config.url())
-            flash(msg + 'Please try again later.', 'error')
-            redirect(redir)
 
     @expose('json:')
     def bin_counts(self, *args, **kw):
@@ -905,7 +899,7 @@ class RootController(BaseController, FeedController):
     @expose('jinja:forgetracker:templates/tracker/new_ticket.html')
     def new(self, description=None, summary=None, labels=None, **kw):
         require_access(c.app, 'create')
-        self.rate_limit(redir='..')
+        self.rate_limit(TM.Ticket, 'Ticket creation', redir='..')
         c.ticket_form = W.ticket_form
         help_msg = c.app.config.options.get('TicketHelpNew', '').strip()
         return dict(action=c.app.config.url() + 'save_ticket',
@@ -942,7 +936,7 @@ class RootController(BaseController, FeedController):
             require_access(ticket, 'update')
         else:
             require_access(c.app, 'create')
-            self.rate_limit(redir='.')
+            self.rate_limit(TM.Ticket, 'Ticket creation', redir='.')
             ticket = TM.Ticket.new()
         g.spam_checker.check(ticket_form['summary'] + u'\n' + ticket_form.get('description', ''), artifact=ticket,
                              user=c.user, content_type='ticket')

http://git-wip-us.apache.org/repos/asf/allura/blob/5359a3bc/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 7c55221..377c50c 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -530,17 +530,10 @@ class PageController(BaseController, FeedController):
             if self.page.deleted:
                 require_access(self.page, 'delete')
         elif has_access(c.app, 'create'):
-            self.rate_limit()
+            self.rate_limit(WM.Page, 'Page create/edit')
         else:
             raise exc.HTTPNotFound
 
-    def rate_limit(self):
-        if WM.Page.is_limit_exceeded(c.app.config, user=c.user):
-            msg = 'Page create/edit rate limit exceeded. '
-            log.warn(msg + c.app.config.url())
-            flash(msg + 'Please try again later.', 'error')
-            redirect('..')
-
     def fake_page(self):
         return dict(
             title=self.title,
@@ -613,7 +606,7 @@ class PageController(BaseController, FeedController):
             page = self.page
         else:
             page = self.fake_page()
-        self.rate_limit()  # check before trying to save
+        self.rate_limit(WM.Page, 'Page create/edit')  # check before trying to save
         c.confirmation = W.confirmation
         c.markdown_editor = W.markdown_editor
         c.attachment_add = W.attachment_add
@@ -719,7 +712,7 @@ class PageController(BaseController, FeedController):
             flash('You must provide a title for the page.', 'error')
             redirect('edit')
         title = title.replace('/', '-')
-        self.rate_limit()
+        self.rate_limit(WM.Page, 'Page create/edit')
         if not self.page:
             # the page doesn't exist yet, so create it
             self.page = WM.Page.upsert(self.title)


[2/2] allura git commit: [#8193] Include rate limiting on forum topics, fix minor tickets UI bug

Posted by br...@apache.org.
[#8193] Include rate limiting on forum topics, fix minor tickets UI bug


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

Branch: refs/heads/master
Commit: 334868b5f2f86c0087dd08410486ed033442679c
Parents: 5359a3b
Author: Kenton Taylor <kt...@slashdotmedia.com>
Authored: Thu Mar 8 13:37:38 2018 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Mar 8 15:37:49 2018 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/discuss.py                    | 4 ++--
 Allura/allura/model/artifact.py                         | 1 +
 Allura/allura/tests/functional/test_discuss.py          | 9 +++++----
 Allura/development.ini                                  | 1 +
 ForgeDiscussion/forgediscussion/controllers/root.py     | 1 +
 ForgeTracker/forgetracker/templates/tracker/ticket.html | 7 ++++---
 6 files changed, 14 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/334868b5/Allura/allura/controllers/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index ba31409..100ce44 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -209,7 +209,7 @@ class ThreadController(BaseController, FeedController):
     @utils.AntiSpam.validate('Spambot protection engaged')
     def post(self, **kw):
         require_access(self.thread, 'post')
-        self.rate_limit(M.Post, "Comment", redir='..')
+        self.rate_limit(M.Post, "Comment", redir=request.referrer)
         if self.thread.ref:
             require_access(self.thread.ref.artifact, 'post')
         kw = self.W.edit_post.to_python(kw, None)
@@ -345,7 +345,7 @@ class PostController(BaseController):
     @require_post(redir='.')
     def reply(self, file_info=None, **kw):
         require_access(self.thread, 'post')
-        self.rate_limit(M.Post, "Comment", redir='..')
+        self.rate_limit(M.Post, "Comment", redir=request.referrer)
         kw = self.W.edit_post.to_python(kw, None)
         p = self.thread.add_post(parent_id=self.post._id, **kw)
         p.add_multiple_attachments(file_info)

http://git-wip-us.apache.org/repos/asf/allura/blob/334868b5/Allura/allura/model/artifact.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index 30836f1..7933e7f 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -646,6 +646,7 @@ class VersionedArtifact(Artifact):
         if 'user' in kwargs:
             def distinct_artifacts_by_user():
                 # count distinct items, not total (e.g. many edits to a single wiki page doesn't count against you)
+                # query history here, as regular base artifacts have no author information
                 HC = cls.__mongometa__.history_class
                 artifacts = HC.query.find({'author.id': kwargs['user']._id}).distinct('artifact_id')
                 """

http://git-wip-us.apache.org/repos/asf/allura/blob/334868b5/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 8f3c968..50eecd6 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -134,10 +134,11 @@ class TestDiscuss(TestDiscussBase):
     def test_rate_limit(self):
         with h.push_config(config, **{'allura.rate_limits_per_user': '{"3600": 2}'}):
             for i in range(0, 2):
-                self._make_post('This is a post {}'.format(i))
-            with assert_raises(AppError):
-                self._make_post('This is a post that should fail.')
-            return 'foo'
+                r = self._make_post('This is a post {}'.format(i))
+                assert 'rate limit exceeded' not in r.body
+
+            r = self._make_post('This is a post that should fail.')
+            assert 'rate limit exceeded' in r.body
 
     def test_permissions(self):
         thread_url = self._thread_link()

http://git-wip-us.apache.org/repos/asf/allura/blob/334868b5/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index e43be7d..0aa0bcd 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -529,6 +529,7 @@ forgemail.domain = .in.localhost
 ; Number of different wiki pages, tickets, etc that a user can create or edit, per time period, across all projects
 ; Keys are number of seconds, values are max number allowed until that time period is reached
 ; NOTE: wiki pages include the default "Home" page created for the user-project and any other projects created by the user
+; NOTE: allura.rate_limits* cover posts to threads across all tools.
 ;forgewiki.rate_limits_per_user =    {"60": 3, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}
 ;forgetracker.rate_limits_per_user = {"60": 1, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}
 ;forgeblog.rate_limits_per_user =    {"60": 1, "120": 3, "900": 5, "1800": 7, "3600": 10, "7200": 15, "86400": 20, "604800": 50, "2592000": 200}

http://git-wip-us.apache.org/repos/asf/allura/blob/334868b5/ForgeDiscussion/forgediscussion/controllers/root.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index 4b35254..176156f 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -123,6 +123,7 @@ class RootController(BaseController, DispatchIndex, FeedController):
     @validate(W.new_topic, error_handler=create_topic)
     @AntiSpam.validate('Spambot protection engaged')
     def save_new_topic(self, subject=None, text=None, forum=None, **kw):
+        self.rate_limit(model.ForumPost, 'Topic creation', request.referer)
         discussion = model.Forum.query.get(
             app_config_id=c.app.config._id,
             shortname=forum)

http://git-wip-us.apache.org/repos/asf/allura/blob/334868b5/ForgeTracker/forgetracker/templates/tracker/ticket.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker/ticket.html b/ForgeTracker/forgetracker/templates/tracker/ticket.html
index 8665611..2895829 100644
--- a/ForgeTracker/forgetracker/templates/tracker/ticket.html
+++ b/ForgeTracker/forgetracker/templates/tracker/ticket.html
@@ -189,7 +189,7 @@
           var discussion_holder = $('#discussion_holder');
           var ticket_content = $('#ticket_content');
           var title_holder = $('h2.dark');
-          var original_title = title_holder.text();
+          var original_title = title_holder.html();
           var title_actions = title_holder.find('small');
           var vote = $('#vote');
 
@@ -218,7 +218,8 @@
             $(this).trigger('editTicket');
             return false;
           });
-          if ($('div > div.error').hasClass('error')){
+          var flashErrors = $('div > div.error');
+          if (flashErrors.hasClass('error') && flashErrors.html().indexOf('rate limit') < 0){
             $('a.edit_ticket').click();
           }
           $('a.cancel_form').click(function () {
@@ -226,7 +227,7 @@
             view_holder.show();
             discussion_holder.show();
             ticket_content.show();
-            title_holder.text(original_title);
+            title_holder.html(original_title);
             title_actions.appendTo(title_holder);
             title_actions.show();
             vote.show();