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 2015/02/28 00:19:01 UTC

[06/14] allura git commit: [#7832] ticket:731 Endpoint for creating webhook

[#7832] ticket:731 Endpoint for creating webhook


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

Branch: refs/heads/master
Commit: 9e16b0b2f7ff1c2ff112c264e4126b1696bf2b58
Parents: 41c054c
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri Feb 20 13:52:38 2015 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Feb 27 22:40:52 2015 +0000

----------------------------------------------------------------------
 Allura/allura/tests/test_webhooks.py | 65 ++++++++++++++++++++++++++++++-
 Allura/allura/webhooks.py            | 61 +++++++++++++++++++++++++++++
 2 files changed, 125 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/9e16b0b2/Allura/allura/tests/test_webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index 5bbee21..237de87 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -657,7 +657,6 @@ class TestModels(TestWebhookBase):
         dd.assert_equal(self.wh.__json__(), expected)
 
 
-
 class TestWebhookRestController(TestRestApiBase):
     def setUp(self):
         super(TestWebhookRestController, self).setUp()
@@ -730,3 +729,67 @@ class TestWebhookRestController(TestRestApiBase):
             'mod_date': unicode(webhook.mod_date),
         }
         dd.assert_equal(r.json, expected)
+
+    def test_create_validation(self):
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
+        r = self.api_get(self.url + '/repo-push', {}, status=405)
+
+        r = self.api_post(self.url + '/repo-push', {}, status=400)
+        expected = {
+            u'result': u'error',
+            u'error': {u'url': u'Please enter a value'},
+        }
+        assert_equal(r.json, expected)
+
+        data = {'url': 'qwer', 'secret': 'qwe'}
+        r = self.app.post(self.url + '/repo-push', data, status=400)
+        expected = {
+            u'result': u'error',
+            u'error': {
+                u'url': u'You must provide a full domain name (like qwer.com)'
+            },
+        }
+        assert_equal(r.json, expected)
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
+
+    def test_create(self):
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
+        data = {u'url': u'http://hook.slack.com/abcd'}
+        limit = json.dumps({'git': 10})
+        with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
+            r = self.app.post(self.url + '/repo-push', data, status=201)
+        webhook = M.Webhook.query.get(hook_url=data['url'])
+        assert_equal(webhook.secret, 'super-secret')  # secret generated
+        assert_equal(r.json['result'], 'ok')
+        assert_equal(r.json['webhook']['_id'], unicode(webhook._id))
+        assert_equal(r.json['webhook']['type'], 'repo-push')
+        assert_equal(r.json['webhook']['hook_url'], data['url'])
+        assert_equal(
+            r.json['webhook']['url'],
+            u'http://localhost/rest/adobe/adobe-1/admin'
+            u'/src/webhooks/repo-push/{}'.format(webhook._id))
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks) + 1)
+
+    def test_create_duplicates(self):
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
+        data = {u'url': self.webhooks[0].hook_url}
+        limit = json.dumps({'git': 10})
+        with h.push_config(config, **{'webhook.repo_push.max_hooks': limit}):
+            r = self.app.post(self.url + '/repo-push', data, status=400)
+        expected = {u'result': u'error',
+                    u'error': u'_the_form: "repo-push" webhook already '
+                              u'exists for Git http://httpbin.org/post/0'}
+        assert_equal(r.json, expected)
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
+
+    def test_create_limit_reached(self):
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))
+        data = {u'url': u'http://hook.slack.com/abcd'}
+        r = self.app.post(self.url + '/repo-push', data, status=400)
+        expected = {
+            u'result': u'error',
+            u'limits': {u'max': 3, u'used': 3},
+            u'error': u'You have exceeded the maximum number of webhooks '
+                      u'you are allowed to create for this project/app'}
+        assert_equal(r.json, expected)
+        assert_equal(M.Webhook.query.find().count(), len(self.webhooks))

http://git-wip-us.apache.org/repos/asf/allura/blob/9e16b0b2/Allura/allura/webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index dffaa21..fe41342 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -28,6 +28,7 @@ from bson import ObjectId
 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 pylons import response
 from formencode import validators as fev, schema, Invalid
 from ming.odm import session
 from webob import exc
@@ -199,6 +200,66 @@ class WebhookRestController(BaseController):
         self.create_form = WebhookController.create_form
         self.edit_form = WebhookController.edit_form
 
+    def _error(self, e):
+        error = getattr(e, 'error_dict', None)
+        if error:
+            _error = {}
+            for k, v in error.iteritems():
+                _error[k] = unicode(v)
+            return _error
+        error = getattr(e, 'msg', None)
+        if not error:
+            error = getattr(e, 'message', '')
+        return error
+
+    def update_webhook(self, wh, url, secret=None):
+        controller = WebhookController(self.sender.__class__, self.app)
+        controller.update_webhook(wh, url, secret)
+
+    @expose('json:')
+    @require_post()
+    def index(self, **kw):
+        response.content_type = 'application/json'
+        try:
+            params = {'secret': kw.pop('secret', ''),
+                      'url': kw.pop('url', None)}
+            valid = self.create_form().to_python(params)
+        except Exception as e:
+            response.status_int = 400
+            return {'result': 'error', 'error': self._error(e)}
+        if self.sender.enforce_limit(self.app):
+            webhook = M.Webhook(
+                type=self.sender.type,
+                app_config_id=self.app.config._id)
+            try:
+                self.update_webhook(webhook, valid['url'], valid['secret'])
+            except Invalid as e:
+                response.status_int = 400
+                return {'result': 'error', 'error': self._error(e)}
+            M.AuditLog.log('add webhook %s %s %s',
+                           webhook.type, webhook.hook_url,
+                           webhook.app_config.url())
+            response.status_int = 201
+            return {'result': 'ok', 'webhook': webhook.__json__()}
+        else:
+            limits = {
+                'max': M.Webhook.max_hooks(
+                    self.sender.type,
+                    self.app.config.tool_name),
+                'used': M.Webhook.query.find({
+                    'type': self.sender.type,
+                    'app_config_id': self.app.config._id,
+                }).count(),
+            }
+            resp = {
+                'result': 'error',
+                'error': 'You have exceeded the maximum number of webhooks '
+                         'you are allowed to create for this project/app',
+                'limits': limits,
+            }
+            response.status_int = 400
+            return resp
+
     @expose('json:')
     def _default(self, webhook, **kw):
         form = self.edit_form(self.sender, self.app)