esup_signature: add new-with-workflow endpoint (#77670) #251

Merged
ecazenave merged 3 commits from wip/77670-esup-workflow into main 2023-05-30 14:35:13 +02:00
2 changed files with 160 additions and 2 deletions
Showing only changes of commit 7102c3150a - Show all commits

View File

@ -69,6 +69,69 @@ SIGN_REQUEST_SCHEMA = {
}
SIGN_REQUEST_WITH_WORKFLOW_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',

Est-ce que pour plus de clarté on n’a pas intérêt à décider d’une valeur par défaut pour tous ces paramètres booléens nouvellement ajoutés au schéma ?

Est-ce que pour plus de clarté on n’a pas intérêt à décider d’une valeur par défaut pour tous ces paramètres booléens nouvellement ajoutés au schéma ?

Fait.

Fait.
'title': '',
'description': '',
'type': 'object',
'required': ['file', 'eppn', 'workflow_id'],
'unflatten': True,
'properties': collections.OrderedDict(
{
'file': {
'type': 'object',
'description': 'File object',
'required': ['filename', 'content_type', 'content'],
'properties': {
'filename': {
'type': 'string',
},
'content_type': {
'type': 'string',
'description': 'MIME content-type',
},
'content': {
'type': 'string',
'description': 'Content, base64 encoded',
},
},
},
'recipients_emails': {
'type': 'array',
'description': 'Recipients emails at each step',
'items': {'type': 'string'},
},
'target_emails': {
'type': 'array',
'description': 'Target emails',
'items': {'type': 'string'},
},
'all_sign_to_completes': {

Typo ici (s/WTIH/WITH), à reporter dans le test aussi.

Typo ici (s/WTIH/WITH), à reporter dans le test aussi.

Corrigé.

Corrigé.
'type': 'array',
'description': 'Steps numbers were every recipient has to sign',
'items': {'type': 'string'},
},
'eppn': {'type': 'string', 'description': 'EPPN of the sign request owner'},
'workflow_id': {'type': 'string', 'description': 'Identifier of the workflow'},
'title': {'type': 'string', 'description': 'Title'},
'target_urls': {
'type': 'array',
'description': 'End locations',
'items': {'type': 'string'},
},
'signrequest_params_jsonstring': {
'type': 'string',
'description': 'Signature parameters',
},
}
),
}
def clean_list(some_list):
return [elem for elem in some_list if elem]
class EsupSignature(BaseResource, HTTPResource):
base_url = models.URLField(_('API URL'))
@ -143,10 +206,9 @@ class EsupSignature(BaseResource, HTTPResource):
)
}
recipients_emails = [email for email in post_data['recipients_emails'] if email]
data = {
'signType': 'pdfImageStamp',
'recipientsEmails': recipients_emails,
'recipientsEmails': clean_list(post_data['recipients_emails']),
'eppn': post_data['eppn'],
'title': post_data.get('title', ''),
'pending': True,
@ -154,6 +216,69 @@ class EsupSignature(BaseResource, HTTPResource):
return {'data': self._call('ws/signrequests/new', method='post', data=data, files=files)}
@endpoint(
name='new-with-workflow',
description=_('Create a sign request'),
perm='can_access',
post={
'request_body': {
'schema': {
'application/json': SIGN_REQUEST_WITH_WORKFLOW_SCHEMA,
}
},
'input_example': {
'file': {
'filename': 'example-1.pdf',
'content_type': 'application/pdf',
'content': 'JVBERi0xL...(base64 PDF)...',
},
'workflow_id': '99',
'eppn': 'aa@foo.com',
'title': 'a title',
'recipients_emails/0': '0*xx@foo.com',
'recipients_emails/1': '0*yy@foo.com',
'recipients_emails/2': '1*zz@foo.com',
'all_sign_to_completes/0': '12',
'all_sign_to_completes/1': '13',
'target_emails/0': 'xx@foo.com',
'target_emails/1': 'yy@foo.com',
'target_emails/2': 'zz@foo.com',
'signrequest_params_jsonstring': 'List [ OrderedMap { "xPos": 100, "yPos": 100, "signPageNumber": 1 }, '
'OrderedMap { "xPos": 200, "yPos": 200, "signPageNumber": 1 } ]',
'target_urls/0': 'smb://foo.bar/location-1/',
'target_urls/1': 'smb://foo.bar/location-2/',
},
},
)
def new_with_workflow(self, request, post_data):
try:
file_bytes = io.BytesIO(base64.b64decode(post_data['file']['content']))
except (TypeError, binascii.Error):
raise APIError("Can't decode file")
files = {
'multipartFiles': (
post_data['file']['filename'],
file_bytes,
post_data['file']['content_type'],
)
}
data = {
'createByEppn': post_data['eppn'],
'title': post_data.get('title', ''),
'recipientsEmails': clean_list(post_data.get('recipients_emails', [])),
'allSignToCompletes': clean_list(post_data.get('all_sign_to_completes', [])),
'targetEmails': clean_list(post_data.get('target_emails', [])),
'signRequestParamsJsonString': post_data.get('signrequest_params_jsonstring', ''),
'targetUrls': clean_list(post_data.get('target_urls', [])),

Du détail, mais pas compris pourquoi la valeur par défaut est en dur ici et ne reprend pas celle définie dans le schéma.

Du détail, mais pas compris pourquoi la valeur par défaut est en dur ici et ne reprend pas celle définie dans le schéma.

Dans la norme JSON schema : "The default keyword specifies a default value. This value is not used to fill in missing values during the validation process."

Charge donc à l'application de "fournir" les valeurs par défaut.

Dans la norme JSON schema : "The default keyword specifies a default value. This value is not used to fill in missing values during the validation process." Charge donc à l'application de "fournir" les valeurs par défaut.

Cool, j’ignorais ça, merci pour la clarification.

Cool, j’ignorais ça, merci pour la clarification.
}
return {
'data': self._call(
'/ws/workflows/%s/new' % post_data['workflow_id'], method='post', data=data, files=files
)
}
@endpoint(
methods=['get'],
name='status',

View File

@ -44,6 +44,39 @@ def test_new(app, connector):
assert json_resp['data'] == 9
def test_new_with_workflow(app, connector):
params = {
'file': {
'filename': 'bla',
'content': base64.b64encode(b'who what').decode(),
'content_type': 'text/plain',
},
'workflow_id': '99',
'eppn': 'aa@foo.com',
'title': 'a title',
'recipients_emails/0': '0*xx@foo.com',
'recipients_emails/1': '0*yy@foo.com',
'recipients_emails/2': '1*zz@foo.com',
'all_sign_to_completes/0': '12',
'all_sign_to_completes/1': '13',
'target_emails/0': 'xx@foo.com',
'target_emails/1': 'yy@foo.com',
'target_emails/2': 'zz@foo.com',
'signrequest_params_jsonstring': 'List [ OrderedMap { "xPos": 100, "yPos": 100, "signPageNumber": 1 }, '
'OrderedMap { "xPos": 200, "yPos": 200, "signPageNumber": 1 } ]',
'target_urls/0': 'smb://foo.bar/location-1/',
'target_urls/1': 'smb://foo.bar/location-2/',
}
with responses.RequestsMock() as rsps:
rsps.post('https://esup-signature.invalid/ws/workflows/99/new', status=200, json=9)
resp = app.post_json('/esup-signature/esup-signature/new-with-workflow', params=params)
assert len(rsps.calls) == 1
assert rsps.calls[0].request.headers['Content-Type'].startswith('multipart/form-data')
json_resp = resp.json
assert json_resp['err'] == 0
assert json_resp['data'] == 9
def test_status(app, connector):
with responses.RequestsMock() as rsps:
rsps.get('https://esup-signature.invalid/ws/signrequests/1', status=200, json={'status': 'completed'})