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/16 12:44:53 UTC
[22/37] allura git commit: [#4542] ticket:715 Add rate limits
[#4542] ticket:715 Add rate limits
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5c82af91
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5c82af91
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5c82af91
Branch: refs/heads/ib/4542
Commit: 5c82af9102913513a368f3c9db3adf5397e5f42e
Parents: e7ace57
Author: Igor Bondarenko <je...@gmail.com>
Authored: Mon Feb 2 12:01:13 2015 +0000
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Mon Feb 16 10:17:38 2015 +0000
----------------------------------------------------------------------
Allura/allura/model/webhook.py | 23 ++++++++++++++++++-
Allura/allura/tests/test_webhooks.py | 38 +++++++++++++++++++++++++++++++
Allura/allura/webhooks.py | 6 ++++-
Allura/development.ini | 6 +++++
4 files changed, 71 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/5c82af91/Allura/allura/model/webhook.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/webhook.py b/Allura/allura/model/webhook.py
index 05eb436..09cc7fa 100644
--- a/Allura/allura/model/webhook.py
+++ b/Allura/allura/model/webhook.py
@@ -15,7 +15,12 @@
# specific language governing permissions and limitations
# under the License.
-from ming.odm import FieldProperty
+import datetime as dt
+
+from ming.odm import FieldProperty, session
+from paste.deploy.converters import asint
+from tg import config
+
from allura.model import Artifact
@@ -28,6 +33,7 @@ class Webhook(Artifact):
type = FieldProperty(str)
hook_url = FieldProperty(str)
secret = FieldProperty(str)
+ last_sent = FieldProperty(dt.datetime, if_missing=None)
def url(self):
return '{}{}/{}/{}'.format(
@@ -41,3 +47,18 @@ class Webhook(Artifact):
ac_ids = [ac._id for ac in project.app_configs]
hooks = cls.query.find(dict(type=type, app_config_id={'$in': ac_ids}))
return hooks.all()
+
+ def enforce_limit(self):
+ '''Returns False if limit is reached, otherwise True'''
+ if self.last_sent is None:
+ return True
+ now = dt.datetime.utcnow()
+ config_type = self.type.replace('-', '_')
+ limit = asint(config.get('webhook.%s.limit' % config_type, 30))
+ if (now - self.last_sent) > dt.timedelta(seconds=limit):
+ return True
+ return False
+
+ def update_limit(self):
+ self.last_sent = dt.datetime.utcnow()
+ session(self).flush(self)
http://git-wip-us.apache.org/repos/asf/allura/blob/5c82af91/Allura/allura/tests/test_webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index fa0305f..99e5f91 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -1,6 +1,7 @@
import json
import hmac
import hashlib
+import datetime as dt
from mock import Mock, patch
from nose.tools import (
@@ -12,6 +13,7 @@ from nose.tools import (
from formencode import Invalid
from ming.odm import session
from pylons import tmpl_context as c
+from tg import config
from allura import model as M
from allura.lib import helpers as h
@@ -431,6 +433,18 @@ class TestRepoPushWebhookSender(TestWebhookBase):
self.wh._id,
sender.get_payload.return_value)
+ @patch('allura.webhooks.log', autospec=True)
+ @patch('allura.webhooks.send_webhook', autospec=True)
+ def test_send_limit_reached(self, send_webhook, log):
+ sender = RepoPushWebhookSender()
+ sender.get_payload = Mock()
+ self.wh.enforce_limit = Mock(return_value=False)
+ with h.push_config(c, app=self.git):
+ sender.send(arg1=1, arg2=2)
+ assert_equal(send_webhook.post.call_count, 0)
+ log.warn.assert_called_once_with(
+ 'Webhook fires too often: %s. Skipping', self.wh)
+
@patch('allura.webhooks.send_webhook', autospec=True)
def test_send_no_configured_webhooks(self, send_webhook):
self.wh.delete()
@@ -467,3 +481,27 @@ class TestModels(TestWebhookBase):
def test_webhook_url(self):
assert_equal(self.wh.url(),
'/adobe/adobe-1/admin/webhooks/repo-push/{}'.format(self.wh._id))
+
+ def test_webhook_enforce_limit(self):
+ self.wh.last_sent = None
+ assert_equal(self.wh.enforce_limit(), True)
+ # default value
+ self.wh.last_sent = dt.datetime.utcnow() - dt.timedelta(seconds=31)
+ assert_equal(self.wh.enforce_limit(), True)
+ self.wh.last_sent = dt.datetime.utcnow() - dt.timedelta(seconds=15)
+ assert_equal(self.wh.enforce_limit(), False)
+ # value from config
+ with h.push_config(config, **{'webhook.repo_push.limit': 100}):
+ self.wh.last_sent = dt.datetime.utcnow() - dt.timedelta(seconds=101)
+ assert_equal(self.wh.enforce_limit(), True)
+ self.wh.last_sent = dt.datetime.utcnow() - dt.timedelta(seconds=35)
+ assert_equal(self.wh.enforce_limit(), False)
+
+ @patch('allura.model.webhook.dt', autospec=True)
+ def test_update_limit(self, dt_mock):
+ _now = dt.datetime(2015, 02, 02, 13, 39)
+ dt_mock.datetime.utcnow.return_value = _now
+ assert_equal(self.wh.last_sent, None)
+ self.wh.update_limit()
+ session(self.wh).expunge(self.wh)
+ assert_equal(M.Webhook.query.get(_id=self.wh._id).last_sent, _now)
http://git-wip-us.apache.org/repos/asf/allura/blob/5c82af91/Allura/allura/webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index 2393acd..e13086d 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -272,7 +272,11 @@ class WebhookSender(object):
if webhooks:
payload = self.get_payload(**kw)
for webhook in webhooks:
- send_webhook.post(webhook._id, payload)
+ if webhook.enforce_limit():
+ webhook.update_limit()
+ send_webhook.post(webhook._id, payload)
+ else:
+ log.warn('Webhook fires too often: %s. Skipping', webhook)
class RepoPushWebhookSender(WebhookSender):
http://git-wip-us.apache.org/repos/asf/allura/blob/5c82af91/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index c6425a8..39a9efa 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -129,6 +129,12 @@ user_prefs_storage.ldap.fields.display_name = cn
# Limit the number of emails a user can claim.
user_prefs.maximum_claimed_emails = 20
+# Limit rate of webhook firing (in seconds, default = 30)
+# Option format: webhook.<hook type>.limit,
+# all '-' in hook type must be changed to '_'
+# e.g. for repo-push webhook:
+# webhook.repo_push.limit = 10
+
# Additional fields for admin project/user search
# Note: whitespace after comma is important!
# search.project.additional_search_fields = private, url, title