You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by ke...@apache.org on 2018/03/07 17:06:28 UTC
allura git commit: [#8193] Adds ability to rate-limit comments
Repository: allura
Updated Branches:
refs/heads/kt/8193 [created] cf6bdb395
[#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/cf6bdb39
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/cf6bdb39
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/cf6bdb39
Branch: refs/heads/kt/8193
Commit: cf6bdb395eaad635ea0bcce8c9bf6bde21e54210
Parents: 880090c
Author: Kenton Taylor <kt...@slashdotmedia.com>
Authored: Wed Mar 7 12:06:15 2018 -0500
Committer: Kenton Taylor <kt...@slashdotmedia.com>
Committed: Wed Mar 7 12:06:15 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/cf6bdb39/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/cf6bdb39/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/cf6bdb39/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/cf6bdb39/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 4a7b9d9..81ebe6c 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -529,6 +529,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/cf6bdb39/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/cf6bdb39/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/cf6bdb39/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)