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/16 22:15:53 UTC
[03/23] allura git commit: [#4542] ticket:714 Handle DuplicateKeyError
[#4542] ticket:714 Handle DuplicateKeyError
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ba555ec4
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ba555ec4
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ba555ec4
Branch: refs/heads/master
Commit: ba555ec4743d46dad2bd1c70121d6e437ff202dd
Parents: ad60782
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jan 29 14:34:19 2015 +0000
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Mon Feb 16 10:16:48 2015 +0000
----------------------------------------------------------------------
.../allura/templates/webhooks/create_form.html | 1 +
Allura/allura/webhooks.py | 76 ++++++++++++++------
2 files changed, 55 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/ba555ec4/Allura/allura/templates/webhooks/create_form.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/webhooks/create_form.html b/Allura/allura/templates/webhooks/create_form.html
index c5ccdfb..6653985 100644
--- a/Allura/allura/templates/webhooks/create_form.html
+++ b/Allura/allura/templates/webhooks/create_form.html
@@ -64,6 +64,7 @@
{%- endmacro %}
{% block content %}
+{{ error('_the_form') }}
<form action="{{action}}" method="post" enctype="multipart/form-data">
<div>
<label for="url">url</label>
http://git-wip-us.apache.org/repos/asf/allura/blob/ba555ec4/Allura/allura/webhooks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/webhooks.py b/Allura/allura/webhooks.py
index c4c6ca6..8495786 100644
--- a/Allura/allura/webhooks.py
+++ b/Allura/allura/webhooks.py
@@ -21,12 +21,14 @@ import hmac
import hashlib
import requests
+from bson import ObjectId
from tg import expose, validate, redirect, flash
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
from ming.odm import session
from webob import exc
+from pymongo.errors import DuplicateKeyError
from allura.controllers import BaseController
from allura.lib import helpers as h
@@ -53,14 +55,23 @@ class MingOneOf(av.Ming):
value, state)
-class WebhookValidator(av.Ming):
+class WebhookValidator(fev.FancyValidator):
def __init__(self, sender, ac_ids, **kw):
self.ac_ids = ac_ids
self.sender = sender
- super(WebhookValidator, self).__init__(cls=M.Webhook, **kw)
+ super(WebhookValidator, self).__init__(**kw)
def _to_python(self, value, state):
- wh = super(WebhookValidator, self)._to_python(value, state)
+ wh = None
+ if isinstance(value, M.Webhook):
+ wh = value
+ elif isinstance(value, ObjectId):
+ wh = M.Webhook.query.get(_id=value)
+ else:
+ try:
+ wh = M.Webhook.query.get(_id=ObjectId(value))
+ except:
+ pass
if wh and wh.type == self.sender.type and wh.app_config_id in self.ac_ids:
return wh
raise Invalid(u'Invalid webhook', value, state)
@@ -72,7 +83,9 @@ class WebhookCreateForm(schema.Schema):
self.triggered_by = [ac for ac in c.project.app_configs
if ac.tool_name.lower() in sender.triggered_by]
self.add_field('app', MingOneOf(
- cls=M.AppConfig, ids=[ac._id for ac in self.triggered_by]))
+ cls=M.AppConfig,
+ ids=[ac._id for ac in self.triggered_by],
+ not_empty=True))
url = fev.URL(not_empty=True)
secret = fev.UnicodeString()
@@ -82,7 +95,9 @@ class WebhookEditForm(WebhookCreateForm):
def __init__(self, sender):
super(WebhookEditForm, self).__init__(sender)
self.add_field('webhook', WebhookValidator(
- sender=sender, ac_ids=[ac._id for ac in self.triggered_by]))
+ sender=sender,
+ ac_ids=[ac._id for ac in self.triggered_by],
+ not_empty=True))
class WebhookControllerMeta(type):
@@ -115,9 +130,38 @@ class WebhookController(BaseController):
def gen_secret(self):
return h.cryptographic_nonce(20)
+ def update_webhook(self, wh, url, ac, secret=None):
+ if not secret:
+ secret = self.gen_secret()
+ wh.hook_url = url
+ wh.app_config_id = ac._id
+ wh.secret = secret
+ try:
+ session(wh).flush(wh)
+ except DuplicateKeyError:
+ session(wh).expunge(wh)
+ msg = u'_the_form: "{}" webhook already exists for {} {}'.format(
+ wh.type, ac.options.mount_label, url)
+ raise Invalid(msg, None, None)
+
+ def form_app_id(self, app):
+ if app and isinstance(app, M.AppConfig):
+ _app = unicode(app._id)
+ elif app:
+ _app = unicode(app)
+ else:
+ _app = None
+ return _app
+
@with_trailing_slash
@expose('jinja:allura:templates/webhooks/create_form.html')
def index(self, **kw):
+ if not c.form_values and kw:
+ # Executes if update_webhook raises an error
+ _app = self.form_app_id(kw.get('app'))
+ c.form_values = {'url': kw.get('url'),
+ 'app': _app,
+ 'secret': kw.get('secret')}
return {'sender': self.sender,
'action': 'create',
'form': self.create_form(self.sender)}
@@ -125,15 +169,8 @@ class WebhookController(BaseController):
@expose()
@require_post()
def create(self, url, app, secret):
- if not secret:
- secret = self.gen_secret()
- # TODO: catch DuplicateKeyError
- wh = M.Webhook(
- hook_url=url,
- secret=secret,
- app_config_id=app._id,
- type=self.sender.type)
- session(wh).flush(wh)
+ 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')
@@ -142,16 +179,10 @@ class WebhookController(BaseController):
@expose()
@require_post()
def edit(self, webhook, url, app, secret):
- if not secret:
- secret = self.gen_secret()
old_url = webhook.hook_url
old_app = webhook.app_config.url()
old_secret = webhook.secret
- webhook.hook_url = url
- webhook.app_config_id = app._id
- webhook.secret = secret
- # TODO: duplicate
- session(webhook).flush(webhook)
+ self.update_webhook(webhook, url, app, secret)
M.AuditLog.log('edit webhook %s\n%s => %s\n%s => %s\n%s',
webhook.type, old_url, url, old_app, app.url(),
'secret changed' if old_secret != secret else '')
@@ -179,8 +210,9 @@ class WebhookController(BaseController):
wh = form.fields['webhook'].to_python(webhook)
except Invalid:
raise exc.HTTPNotFound()
+ _app = self.form_app_id(kw.get('app')) or unicode(wh.app_config._id)
c.form_values = {'url': kw.get('url') or wh.hook_url,
- 'app': kw.get('app') or unicode(wh.app_config_id),
+ 'app': _app,
'secret': kw.get('secret') or wh.secret,
'webhook': unicode(wh._id)}
return {'sender': self.sender,