mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 22:43:42 +00:00
integrations: Add webhook code, API endpoint, and tests for HelloSign.
This commit is contained in:
BIN
static/images/integrations/logos/hellosign.png
Normal file
BIN
static/images/integrations/logos/hellosign.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
49
zerver/fixtures/hellosign/hellosign_signatures.json
Normal file
49
zerver/fixtures/hellosign/hellosign_signatures.json
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"signature_request": {
|
||||||
|
"signature_request_id": "2b388914e3ae3b738bd4e2ee2850c677e6dc53d2",
|
||||||
|
"title": "NDA with Acme Co.",
|
||||||
|
"subject": "The NDA we talked about",
|
||||||
|
"message": "Please sign this NDA and then we can discuss more. Let me know if you have any questions.",
|
||||||
|
"test_mode": true,
|
||||||
|
"metadata": {
|
||||||
|
"custom_id": "1234",
|
||||||
|
"custom_text": "NDA #9"
|
||||||
|
},
|
||||||
|
"is_complete": false,
|
||||||
|
"is_declined": false,
|
||||||
|
"has_error": false,
|
||||||
|
"custom_fields": [],
|
||||||
|
"response_data": [],
|
||||||
|
"signing_url": "https://www.hellosign.com/sign/2b388914e3ae3b738bd4e2ee2850c677e6dc53d2",
|
||||||
|
"signing_redirect_url": null,
|
||||||
|
"final_copy_uri": "/v3/signature_request/final_copy/2b388914e3ae3b738bd4e2ee2850c677e6dc53d2",
|
||||||
|
"files_url": "https://api.hellosign.com/v3/signature_request/files/2b388914e3ae3b738bd4e2ee2850c677e6dc53d2",
|
||||||
|
"details_url": "https://www.hellosign.com/home/manage?guid=2b388914e3ae3b738bd4e2ee2850c677e6dc53d2",
|
||||||
|
"requester_email_address": "me@hellosign.com",
|
||||||
|
"signatures": [{
|
||||||
|
"signature_id": "78caf2a1d01cd39cea2bc1cbb340dac3",
|
||||||
|
"signer_email_address": "jack@example.com",
|
||||||
|
"signer_name": "Jack",
|
||||||
|
"order": 0,
|
||||||
|
"status_code": "awaiting_signature",
|
||||||
|
"signed_at": null,
|
||||||
|
"last_viewed_at": null,
|
||||||
|
"last_reminded_at": null,
|
||||||
|
"has_pin": false
|
||||||
|
}, {
|
||||||
|
"signature_id": "616629ed37f8588d28600be17ab5d6b7",
|
||||||
|
"signer_email_address": "jill@example.com",
|
||||||
|
"signer_name": "Jill",
|
||||||
|
"order": 1,
|
||||||
|
"status_code": "signed",
|
||||||
|
"signed_at": null,
|
||||||
|
"last_viewed_at": null,
|
||||||
|
"last_reminded_at": null,
|
||||||
|
"has_pin": false
|
||||||
|
}],
|
||||||
|
"cc_email_addresses": [
|
||||||
|
"lawyer1@hellosign.com",
|
||||||
|
"lawyer2@example.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -126,6 +126,7 @@ WEBHOOK_INTEGRATIONS = [
|
|||||||
),
|
),
|
||||||
WebhookIntegration('gitlab', display_name='GitLab'),
|
WebhookIntegration('gitlab', display_name='GitLab'),
|
||||||
WebhookIntegration('gosquared', display_name='GoSquared'),
|
WebhookIntegration('gosquared', display_name='GoSquared'),
|
||||||
|
WebhookIntegration('hellosign', display_name='HelloSign'),
|
||||||
WebhookIntegration('helloworld', display_name='Hello World'),
|
WebhookIntegration('helloworld', display_name='Hello World'),
|
||||||
WebhookIntegration('heroku', display_name='Heroku'),
|
WebhookIntegration('heroku', display_name='Heroku'),
|
||||||
WebhookIntegration('ifttt', function='zerver.views.webhooks.ifttt.api_iftt_app_webhook', display_name='IFTTT'),
|
WebhookIntegration('ifttt', function='zerver.views.webhooks.ifttt.api_iftt_app_webhook', display_name='IFTTT'),
|
||||||
|
|||||||
20
zerver/tests/webhooks/test_hellosign.py
Normal file
20
zerver/tests/webhooks/test_hellosign.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from typing import Text
|
||||||
|
from zerver.lib.test_classes import WebhookTestCase
|
||||||
|
|
||||||
|
class HelloSignHookTests(WebhookTestCase):
|
||||||
|
STREAM_NAME = 'hellosign'
|
||||||
|
URL_TEMPLATE = "/api/v1/external/hellosign?stream={stream}&api_key={api_key}"
|
||||||
|
FIXTURE_DIR_NAME = 'hellosign'
|
||||||
|
|
||||||
|
def test_signatures_message(self):
|
||||||
|
# type: () -> None
|
||||||
|
expected_subject = "NDA with Acme Co."
|
||||||
|
expected_message = ("The NDA with Acme Co. is awaiting the signature of "
|
||||||
|
"Jack and was just signed by Jill.")
|
||||||
|
self.send_and_test_stream_message('signatures', expected_subject, expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def get_body(self, fixture_name):
|
||||||
|
# type: (Text) -> Text
|
||||||
|
return self.fixture_data("hellosign", fixture_name, file_type="json")
|
||||||
63
zerver/views/webhooks/hellosign.py
Normal file
63
zerver/views/webhooks/hellosign.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from zerver.lib.actions import check_send_message
|
||||||
|
from zerver.lib.response import json_success, json_error
|
||||||
|
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
|
||||||
|
|
||||||
|
from zerver.models import Client, UserProfile
|
||||||
|
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from six import text_type
|
||||||
|
from six.moves import range
|
||||||
|
from typing import Dict, Any, Optional, Tuple, Union
|
||||||
|
|
||||||
|
def format_body(signatories, model_payload):
|
||||||
|
# type: (List[Dict[str, Any]], Dict[str, Any]) -> str
|
||||||
|
def append_separator(i, len_sig):
|
||||||
|
# type: (int, int) -> None
|
||||||
|
if i + 1 == len(signatories):
|
||||||
|
result.append('.')
|
||||||
|
elif i + 2 == len(signatories):
|
||||||
|
result.append(' and')
|
||||||
|
elif i + 3 != len(signatories):
|
||||||
|
result.append(',')
|
||||||
|
|
||||||
|
result = ["The {}".format(model_payload['contract_title'])] # type: Any
|
||||||
|
for i, signatory in enumerate(signatories):
|
||||||
|
name = model_payload['name_{}'.format(i)]
|
||||||
|
if signatory['status_code'] == 'awaiting_signature':
|
||||||
|
result.append(" is awaiting the signature of {}".format(name))
|
||||||
|
elif signatory['status_code'] in ['signed', 'declined']:
|
||||||
|
status = model_payload['status_{}'.format(i)]
|
||||||
|
result.append(" was just {} by {}".format(status, name))
|
||||||
|
|
||||||
|
append_separator(i, len(signatories))
|
||||||
|
result = ''.join(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def ready_payload(signatories, payload):
|
||||||
|
# type: (List[Dict[str, Any]], Dict[str, Dict[str, Any]]) -> Dict[str, Any]
|
||||||
|
model_payload = {'contract_title': payload['signature_request']['title']}
|
||||||
|
for i, signatory in enumerate(signatories):
|
||||||
|
model_payload['name_{}'.format(i)] = signatory['signer_name']
|
||||||
|
model_payload['status_{}'.format(i)] = signatory['status_code']
|
||||||
|
return model_payload
|
||||||
|
|
||||||
|
@api_key_only_webhook_view('HelloSign')
|
||||||
|
@has_request_variables
|
||||||
|
def api_hellosign_webhook(request, user_profile, client,
|
||||||
|
payload=REQ(argument_type='body'),
|
||||||
|
stream=REQ(default='hellosign'),
|
||||||
|
topic=REQ(default=None)):
|
||||||
|
# type: (HttpRequest, UserProfile, Client, Dict[str, Dict[str, Any]], text_type, text_type) -> HttpResponse
|
||||||
|
try:
|
||||||
|
model_payload = ready_payload(payload['signature_request']['signatures'],
|
||||||
|
payload)
|
||||||
|
except KeyError as e:
|
||||||
|
return json_error(_("Missing key {} in JSON").format(str(e)))
|
||||||
|
|
||||||
|
body = format_body(payload['signature_request']['signatures'], model_payload)
|
||||||
|
topic = model_payload['contract_title']
|
||||||
|
check_send_message(user_profile, client, 'stream', [stream],
|
||||||
|
topic, body)
|
||||||
|
return json_success()
|
||||||
Reference in New Issue
Block a user