allura-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brond...@apache.org
Subject [4/5] allura git commit: [#7886] ticket:789 Rate limit wiki page creation
Date Fri, 12 Jun 2015 19:38:25 GMT
[#7886] ticket:789 Rate limit wiki page creation


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

Branch: refs/heads/master
Commit: 6936ce2df44b2b55f3940c600a023c26c2445150
Parents: 1004b07
Author: Igor Bondarenko <jetmind2@gmail.com>
Authored: Wed Jun 10 09:36:02 2015 +0000
Committer: Dave Brondsema <dbrondsema@slashdotmedia.com>
Committed: Fri Jun 12 18:44:26 2015 +0000

----------------------------------------------------------------------
 .../forgewiki/tests/functional/test_rest.py     | 20 +++++++-
 .../forgewiki/tests/functional/test_root.py     | 48 +++++++++++++++++++-
 ForgeWiki/forgewiki/wiki_main.py                | 13 ++++++
 3 files changed, 79 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/6936ce2d/ForgeWiki/forgewiki/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_rest.py b/ForgeWiki/forgewiki/tests/functional/test_rest.py
index 23021d2..6a5de3b 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_rest.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_rest.py
@@ -19,7 +19,7 @@
 
 import json
 
-from nose.tools import assert_equal, assert_in
+from nose.tools import assert_equal, assert_in, assert_not_equal
 import simplejson
 import tg
 
@@ -27,6 +27,8 @@ from allura.lib import helpers as h
 from allura.tests import decorators as td
 from alluratest.controller import TestRestApiBase
 
+from forgewiki.model import Page
+
 
 class TestWikiApi(TestRestApiBase):
 
@@ -84,6 +86,22 @@ class TestWikiApi(TestRestApiBase):
         assert_equal(r.json['text'], data['text'])
         assert_equal(r.json['labels'], data['labels'].split(','))
 
+    def test_create_page_limit(self):
+        data = {
+            'text': 'Embrace the Dark Side',
+            'labels': 'head hunting,dark side'
+        }
+        # Set rate limit to unlimit
+        with h.push_config(tg.config, **{'forgewiki.rate_limits': '{}'}):
+            r = self.api_post(u'/rest/p/test/wiki/page1/', status=200, **data)
+            p = Page.query.get(title='page1')
+            assert_not_equal(p, None)
+        # Set rate limit to 1 in first hour of project
+        with h.push_config(tg.config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
+            r = self.api_post(u'/rest/p/test/wiki/page2/', status=429, **data)
+            p = Page.query.get(title='page2')
+            assert_equal(p, None)
+
     # http://blog.watchfire.com/wfblog/2011/10/json-based-xss-exploitation.html
     def test_json_encoding_security(self):
         self.api_post('/rest/p/test/wiki/foo.html',

http://git-wip-us.apache.org/repos/asf/allura/blob/6936ce2d/ForgeWiki/forgewiki/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index f5f49e6..aea9028 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -20,11 +20,13 @@
 import os
 import StringIO
 import allura
+import json
 
 import PIL
-from nose.tools import assert_true, assert_equal, assert_in
+from nose.tools import assert_true, assert_equal, assert_in, assert_not_equal
 from ming.orm.ormsession import ThreadLocalORMSession
 from mock import patch
+from tg import config
 
 from allura import model as M
 from allura.lib import helpers as h
@@ -770,3 +772,47 @@ class TestRootController(TestController):
         r = self.app.get('/p/test/wiki/Home/', extra_environ={'username': str(user.username)})
         link = r.html.find('a', {'href': '/p/test/wiki/subscribe?subscribe=True'})
         assert link is not None
+
+    def test_rate_limit_new_page(self):
+        # Set rate limit to unlimit
+        with h.push_config(config, **{'forgewiki.rate_limits': '{}'}):
+            r = self.app.get('/p/test/wiki/new-page-title/')
+            assert_equal(r.status_int, 302)
+            assert_equal(
+                r.location,
+                'http://localhost/p/test/wiki/new-page-title/edit')
+            assert_equal(self.webflash(r), '')
+        # Set rate limit to 1 in first hour of project
+        with h.push_config(config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
+            r = self.app.get('/p/test/wiki/new-page-title/')
+            assert_equal(r.status_int, 302)
+            assert_equal(r.location, 'http://localhost/p/test/wiki/')
+            wf = json.loads(self.webflash(r))
+            assert_equal(wf['status'], 'error')
+            assert_equal(
+                wf['message'],
+                'Page creation rate limit exceeded. Please try again later.')
+
+    def test_rate_limit_update(self):
+        # Set rate limit to unlimit
+        with h.push_config(config, **{'forgewiki.rate_limits': '{}'}):
+            r = self.app.post(
+                '/p/test/wiki/page1/update',
+                dict(text='Some text', title='page1')).follow()
+            assert_in('Some text', r)
+            p = model.Page.query.get(title='page1')
+            assert_not_equal(p, None)
+        # Set rate limit to 1 in first hour of project
+        with h.push_config(config, **{'forgewiki.rate_limits': '{"3600": 1}'}):
+            r = self.app.post(
+                '/p/test/wiki/page2/update',
+                dict(text='Some text', title='page2'))
+            assert_equal(r.status_int, 302)
+            assert_equal(r.location, 'http://localhost/p/test/wiki/')
+            wf = json.loads(self.webflash(r))
+            assert_equal(wf['status'], 'error')
+            assert_equal(
+                wf['message'],
+                'Page creation rate limit exceeded. Please try again later.')
+            p = model.Page.query.get(title='page2')
+            assert_equal(p, None)

http://git-wip-us.apache.org/repos/asf/allura/blob/6936ce2d/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 8ab3f3d..cfaec31 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -37,6 +37,7 @@ from allura.app import Application, SitemapEntry, DefaultAdminController,
Config
 from allura.lib.search import search_app
 from allura.lib.decorators import require_post
 from allura.lib.security import require_access, has_access
+from allura.lib import exceptions as forge_exc
 from allura.controllers import AppDiscussionController, BaseController, AppDiscussionRestController
 from allura.controllers import DispatchIndex
 from allura.controllers import attachments as ac
@@ -489,6 +490,14 @@ class PageController(BaseController, FeedController):
                 require_access(self.page, 'delete')
         else:
             require_access(c.app, 'create')
+            self.rate_limit()
+
+    def rate_limit(self):
+        if WM.Page.is_limit_exceeded(c.app.config):
+            msg = 'Page creation rate limit exceeded. '
+            log.warn(msg + c.app.config.url())
+            flash(msg + 'Please try again later.', 'error')
+            redirect('..')
 
     def fake_page(self):
         return dict(
@@ -803,6 +812,10 @@ class PageRestController(BaseController):
         with h.notifications_disabled(c.project):
             if not self.page:
                 require_access(c.app, 'create')
+                if WM.Page.is_limit_exceeded(c.app.config):
+                    log.warn('Page creation rate limit exceeded. %s',
+                             c.app.config.url())
+                    raise forge_exc.HTTPTooManyRequests()
                 self.page = WM.Page.upsert(title)
                 self.page.viewable_by = ['all']
             else:


Mime
View raw message