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/03/06 13:35:16 UTC

[09/26] allura git commit: [#7832] ticket:731 Endpoint for editing webhooks

[#7832] ticket:731 Endpoint for editing webhooks


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

Branch: refs/heads/ib/7830
Commit: 0979146633b40f75329695b1e2b27e4721ea20cd
Parents: 9e16b0b
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri Feb 20 16:27:06 2015 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Feb 27 22:40:52 2015 +0000

----------------------------------------------------------------------
 Allura/allura/tests/test_webhooks.py | 125 +++++++++++++++++++++++++-----
 Allura/allura/webhooks.py            |  38 ++++++++-
 2 files changed, 140 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/09791466/Allura/allura/tests/test_webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_webhooks.py b/Allura/allura/tests/test_webhooks.py
index 237de87..ee9cd0b 100644
--- a/Allura/allura/tests/test_webhooks.py
+++ b/Allura/allura/tests/test_webhooks.py
@@ -721,20 +721,23 @@ class TestWebhookRestController(TestRestApiBase):
         webhook = self.webhooks[0]
         r = self.api_get('{}/repo-push/{}'.format(self.url, webhook._id))
         expected = {
-            '_id': unicode(webhook._id),
-            'url': 'http://localhost/rest/adobe/adobe-1/admin'
-                   '/src/webhooks/repo-push/{}'.format(webhook._id),
-            'type': 'repo-push',
-            'hook_url': 'http://httpbin.org/post/0',
-            'mod_date': unicode(webhook.mod_date),
+            u'result': u'ok',
+            u'webhook': {
+                '_id': unicode(webhook._id),
+                'url': 'http://localhost/rest/adobe/adobe-1/admin'
+                       '/src/webhooks/repo-push/{}'.format(webhook._id),
+                'type': 'repo-push',
+                'hook_url': 'http://httpbin.org/post/0',
+                '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_get(self.url + '/repo-push', status=405)
 
-        r = self.api_post(self.url + '/repo-push', {}, status=400)
+        r = self.api_post(self.url + '/repo-push', status=400)
         expected = {
             u'result': u'error',
             u'error': {u'url': u'Please enter a value'},
@@ -742,7 +745,7 @@ class TestWebhookRestController(TestRestApiBase):
         assert_equal(r.json, expected)
 
         data = {'url': 'qwer', 'secret': 'qwe'}
-        r = self.app.post(self.url + '/repo-push', data, status=400)
+        r = self.api_post(self.url + '/repo-push', status=400, **data)
         expected = {
             u'result': u'error',
             u'error': {
@@ -757,17 +760,24 @@ class TestWebhookRestController(TestRestApiBase):
         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)
+            msg = 'add webhook repo-push {} {}'.format(
+                data['url'], self.git.config.url())
+            with td.audits(msg):
+                r = self.api_post(self.url + '/repo-push', status=201, **data)
         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))
+        expected = {
+            u'result': u'ok',
+            u'webhook': {
+                '_id': unicode(webhook._id),
+                'url': 'http://localhost/rest/adobe/adobe-1/admin'
+                       '/src/webhooks/repo-push/{}'.format(webhook._id),
+                'type': 'repo-push',
+                'hook_url': data['url'],
+                'mod_date': unicode(webhook.mod_date),
+            },
+        }
+        dd.assert_equal(r.json, expected)
         assert_equal(M.Webhook.query.find().count(), len(self.webhooks) + 1)
 
     def test_create_duplicates(self):
@@ -775,7 +785,7 @@ class TestWebhookRestController(TestRestApiBase):
         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)
+            r = self.api_post(self.url + '/repo-push', status=400, **data)
         expected = {u'result': u'error',
                     u'error': u'_the_form: "repo-push" webhook already '
                               u'exists for Git http://httpbin.org/post/0'}
@@ -785,7 +795,7 @@ class TestWebhookRestController(TestRestApiBase):
     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)
+        r = self.api_post(self.url + '/repo-push', status=400, **data)
         expected = {
             u'result': u'error',
             u'limits': {u'max': 3, u'used': 3},
@@ -793,3 +803,78 @@ class TestWebhookRestController(TestRestApiBase):
                       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))
+
+    def test_edit_validation(self):
+        webhook = self.webhooks[0]
+        url = u'{}/repo-push/{}'.format(self.url, webhook._id)
+        data = {'url': 'qwe', 'secret': 'qwe'}
+        r = self.api_post(url, status=400, **data)
+        expected = {
+            u'result': u'error',
+            u'error': {
+                u'url': u'You must provide a full domain name (like qwe.com)'
+            },
+        }
+        assert_equal(r.json, expected)
+
+    def test_edit(self):
+        webhook = self.webhooks[0]
+        url = '{}/repo-push/{}'.format(self.url, webhook._id)
+        # change only url
+        data = {'url': 'http://hook.slack.com/abcd'}
+        msg = ('edit webhook repo-push\n'
+               'http://httpbin.org/post/0 => http://hook.slack.com/abcd\n')
+        with td.audits(msg):
+            r = self.api_post(url, status=200, **data)
+        webhook = M.Webhook.query.get(_id=webhook._id)
+        assert_equal(webhook.hook_url, data['url'])
+        assert_equal(webhook.secret, 'secret-0')
+        expected = {
+            u'result': u'ok',
+            u'webhook': {
+                '_id': unicode(webhook._id),
+                'url': 'http://localhost/rest/adobe/adobe-1/admin'
+                       '/src/webhooks/repo-push/{}'.format(webhook._id),
+                'type': 'repo-push',
+                'hook_url': data['url'],
+                'mod_date': unicode(webhook.mod_date),
+            },
+        }
+        dd.assert_equal(r.json, expected)
+
+        # change only secret
+        data = {'secret': 'new-secret'}
+        msg = ('edit webhook repo-push\n'
+               'http://hook.slack.com/abcd => http://hook.slack.com/abcd\n'
+               'secret changed')
+        with td.audits(msg):
+            r = self.api_post(url, status=200, **data)
+        webhook = M.Webhook.query.get(_id=webhook._id)
+        assert_equal(webhook.hook_url, 'http://hook.slack.com/abcd')
+        assert_equal(webhook.secret, 'new-secret')
+        expected = {
+            u'result': u'ok',
+            u'webhook': {
+                '_id': unicode(webhook._id),
+                'url': 'http://localhost/rest/adobe/adobe-1/admin'
+                       '/src/webhooks/repo-push/{}'.format(webhook._id),
+                'type': 'repo-push',
+                'hook_url': 'http://hook.slack.com/abcd',
+                'mod_date': unicode(webhook.mod_date),
+            },
+        }
+        dd.assert_equal(r.json, expected)
+
+    def test_edit_duplicates(self):
+        webhook = self.webhooks[0]
+        url = '{}/repo-push/{}'.format(self.url, webhook._id)
+        # change only url
+        data = {'url': 'http://httpbin.org/post/1'}
+        r = self.api_post(url, status=400, **data)
+        expected = {u'result': u'error',
+                    u'error': u'_the_form: "repo-push" webhook already '
+                              u'exists for Git http://httpbin.org/post/1'}
+        assert_equal(r.json, expected)
+        webhook = M.Webhook.query.get(_id=webhook._id)
+        assert_equal(webhook.hook_url, 'http://httpbin.org/post/0')
+        assert_equal(webhook.secret, 'secret-0')

http://git-wip-us.apache.org/repos/asf/allura/blob/09791466/Allura/allura/webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index fe41342..f30994f 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -28,7 +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 pylons import response, request
 from formencode import validators as fev, schema, Invalid
 from ming.odm import session
 from webob import exc
@@ -240,7 +240,10 @@ class WebhookRestController(BaseController):
                            webhook.type, webhook.hook_url,
                            webhook.app_config.url())
             response.status_int = 201
-            return {'result': 'ok', 'webhook': webhook.__json__()}
+            # refetch updated values (e.g. mod_date)
+            session(webhook).expunge(webhook)
+            webhook = M.Webhook.query.get(_id=webhook._id)
+            return {'result': 'ok', 'webhook': webhook}
         else:
             limits = {
                 'max': M.Webhook.max_hooks(
@@ -267,7 +270,36 @@ class WebhookRestController(BaseController):
             wh = form.fields['webhook'].to_python(webhook)
         except Invalid:
             raise exc.HTTPNotFound()
-        return wh.__json__()
+        if request.method == 'POST':
+            return self._edit(wh, form, **kw)
+        else:
+            return {'result': 'ok', 'webhook': wh}
+
+    def _edit(self, webhook, form, **kw):
+        old_secret = webhook.secret
+        old_url = webhook.hook_url
+        try:
+            params = {'secret': kw.pop('secret', old_secret),
+                      'url': kw.pop('url', old_url),
+                      'webhook': unicode(webhook._id)}
+            valid = form.to_python(params)
+        except Exception as e:
+            response.status_int = 400
+            return {'result': 'error', 'error': self._error(e)}
+        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(
+            'edit webhook %s\n%s => %s\n%s',
+            webhook.type, old_url, valid['url'],
+            'secret changed' if old_secret != valid['secret'] else '')
+        # refetch updated values (e.g. mod_date)
+        session(webhook).expunge(webhook)
+        webhook = M.Webhook.query.get(_id=webhook._id)
+        return {'result': 'ok',
+                'webhook': webhook}
 
 
 class SendWebhookHelper(object):