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 2015/02/02 17:40:36 UTC

[09/10] allura git commit: [#4542] ticket:715 Add thresholds

[#4542] ticket:715 Add thresholds


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

Branch: refs/heads/ib/4542
Commit: 648f805db593b91e2661a5266d0bc2c27c6458cc
Parents: 120780d
Author: Igor Bondarenko <je...@gmail.com>
Authored: Mon Feb 2 12:53:03 2015 +0000
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Mon Feb 2 15:44:38 2015 +0000

----------------------------------------------------------------------
 Allura/allura/tests/test_webhooks.py | 42 +++++++++++++++++++++++++++++++
 Allura/allura/webhooks.py            | 31 +++++++++++++++++------
 Allura/development.ini               |  6 +++++
 3 files changed, 72 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/648f805d/Allura/allura/tests/test_webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index 99e5f91..791128e 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -202,6 +202,25 @@ class TestWebhookController(TestController):
             '"repo-push" webhook already exists for Git http://httpbin.org/post')
         assert_equal(M.Webhook.query.find().count(), 1)
 
+    def test_create_limit_reached(self):
+        assert_equal(M.Webhook.query.find().count(), 0)
+        limit = json.dumps({'git': 1})
+        with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
+            data = {'url': u'http://httpbin.org/post',
+                    'app': unicode(self.git.config._id),
+                    'secret': ''}
+            r = self.create_webhook(data).follow().follow(status=200)
+            assert_equal(M.Webhook.query.find().count(), 1)
+
+            r = self.app.post(self.url + '/repo-push/create', data)
+            wf = json.loads(self.webflash(r))
+            assert_equal(wf['status'], 'error')
+            assert_equal(
+                wf['message'],
+                'You have exceeded the maximum number of projects '
+                'you are allowed to create for this project/app')
+            assert_equal(M.Webhook.query.find().count(), 1)
+
     def test_create_validation(self):
         assert_equal(M.Webhook.query.find().count(), 0)
         r = self.app.post(
@@ -468,6 +487,29 @@ class TestRepoPushWebhookSender(TestWebhookBase):
         }
         assert_equal(result, expected_result)
 
+    def test_enforce_limit(self):
+        def add_webhooks(suffix, n):
+            for i in range(n):
+                webhook = M.Webhook(
+                    type='repo-push',
+                    app_config_id=self.git.config._id,
+                    hook_url='http://httpbin.org/{}/{}'.format(suffix, i),
+                    secret='secret')
+                session(webhook).flush(webhook)
+
+        sender = RepoPushWebhookSender()
+        # default
+        assert_equal(sender.enforce_limit(self.git.config), True)
+        add_webhooks('one', 3)
+        assert_equal(sender.enforce_limit(self.git.config), False)
+
+        # config
+        limit = json.dumps({'git': 5})
+        with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
+            assert_equal(sender.enforce_limit(self.git.config), True)
+            add_webhooks('two', 3)
+            assert_equal(sender.enforce_limit(self.git.config), False)
+
 
 class TestModels(TestWebhookBase):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/648f805d/Allura/allura/webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index e13086d..7df8a42 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -22,7 +22,7 @@ import hashlib
 
 import requests
 from bson import ObjectId
-from tg import expose, validate, redirect, flash
+from tg import expose, validate, redirect, flash, config
 from tg.decorators import with_trailing_slash, without_trailing_slash
 from pylons import tmpl_context as c
 from formencode import validators as fev, schema, Invalid
@@ -125,7 +125,7 @@ class WebhookController(BaseController):
 
     def __init__(self, sender):
         super(WebhookController, self).__init__()
-        self.sender = sender
+        self.sender = sender()
 
     def gen_secret(self):
         return h.cryptographic_nonce(20)
@@ -169,11 +169,15 @@ class WebhookController(BaseController):
     @expose()
     @require_post()
     def create(self, url, app, secret):
-        wh = M.Webhook(type=self.sender.type)
-        self.update_webhook(wh, url, app, secret)
-        M.AuditLog.log('add webhook %s %s %s',
-                       wh.type, wh.hook_url, wh.app_config.url())
-        flash('Created successfully', 'ok')
+        if self.sender.enforce_limit(app):
+            wh = M.Webhook(type=self.sender.type)
+            self.update_webhook(wh, url, app, secret)
+            M.AuditLog.log('add webhook %s %s %s',
+                           wh.type, wh.hook_url, wh.app_config.url())
+            flash('Created successfully', 'ok')
+        else:
+            flash('You have exceeded the maximum number of projects '
+                  'you are allowed to create for this project/app', 'error')
         redirect(c.project.url() + 'admin/webhooks/')
 
     @expose()
@@ -278,6 +282,19 @@ class WebhookSender(object):
                 else:
                     log.warn('Webhook fires too often: %s. Skipping', webhook)
 
+    def enforce_limit(self, app_config):
+        '''
+        Checks if limit of webhooks created for given project/app is reached.
+        Returns False if limit is reached, True otherwise.
+        '''
+        _type = self.type.replace('-', '_')
+        limits = json.loads(config.get('webhook.%s.max_hooks' % _type, '{}'))
+        count = M.Webhook.query.find(dict(
+            app_config_id=app_config._id,
+            type=self.type,
+        )).count()
+        return count < limits.get(app_config.tool_name.lower(), 3)
+
 
 class RepoPushWebhookSender(WebhookSender):
     type = 'repo-push'

http://git-wip-us.apache.org/repos/asf/allura/blob/648f805d/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index aacc7d2..8258c7c 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -131,6 +131,12 @@ user_prefs.maximum_claimed_emails = 20
 # e.g. for repo-push webhook:
 # webhook.repo_push.limit = 10
 
+# Limit max number of hooks that can be created for given project/app
+# Option name format: same as above.
+# Value format: json dict, where keys are app names (as appears in
+# `WebhookSender.triggered_by`) and values are actual limits (default=3), e.g.:
+# webhook.repo_push.max_hooks = {"git": 3, "hg": 3, "svn": 3}
+
 # Additional fields for admin project/user search
 # Note: whitespace after comma is important!
 # search.project.additional_search_fields = private, url, title