atal_rest: accept empty files (#81518)
gitea/passerelle/pipeline/head This commit looks good
Details
gitea/passerelle/pipeline/head This commit looks good
Details
This commit is contained in:
parent
ef0b518aba
commit
898a14f821
|
@ -30,29 +30,38 @@ from passerelle.base.models import BaseResource, HTTPResource
|
|||
from passerelle.utils.api import endpoint
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
|
||||
FILE_OBJECT = {
|
||||
'type': 'object',
|
||||
'description': 'File object',
|
||||
'required': ['content'],
|
||||
'properties': {
|
||||
'filename': {
|
||||
'type': 'string',
|
||||
'description': 'Filename',
|
||||
},
|
||||
'content': {
|
||||
'type': 'string',
|
||||
'description': 'Content',
|
||||
},
|
||||
'content_type': {
|
||||
'type': 'string',
|
||||
'description': 'Content type',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SINGLE_ATTACHMENT_SCHEMA = {
|
||||
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||
'type': 'object',
|
||||
'additionalProperties': False,
|
||||
'properties': {
|
||||
'file': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'filename': {
|
||||
'type': 'string',
|
||||
'description': 'Filename',
|
||||
},
|
||||
'content': {
|
||||
'type': 'string',
|
||||
'description': 'Content',
|
||||
},
|
||||
'content_type': {
|
||||
'type': 'string',
|
||||
'description': 'Content type',
|
||||
},
|
||||
},
|
||||
'required': ['content'],
|
||||
},
|
||||
'oneOf': [
|
||||
FILE_OBJECT,
|
||||
{'type': 'string', 'description': 'empty file, do not consider', 'pattern': r'^$'},
|
||||
{'type': 'null', 'description': 'empty file, do not consider'},
|
||||
]
|
||||
}
|
||||
},
|
||||
'required': ['file'],
|
||||
}
|
||||
|
@ -66,22 +75,11 @@ ATTACHMENTS_SCHEMA = {
|
|||
'files': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'filename': {
|
||||
'type': 'string',
|
||||
'description': 'Filename',
|
||||
},
|
||||
'content': {
|
||||
'type': 'string',
|
||||
'description': 'Content',
|
||||
},
|
||||
'content_type': {
|
||||
'type': 'string',
|
||||
'description': 'Content type',
|
||||
},
|
||||
},
|
||||
'required': ['content'],
|
||||
'oneOf': [
|
||||
FILE_OBJECT,
|
||||
{'type': 'string', 'description': 'empty file, do not consider', 'pattern': r'^$'},
|
||||
{'type': 'null', 'description': 'empty file, do not consider'},
|
||||
]
|
||||
},
|
||||
},
|
||||
'worksrequests_ids': {'type': 'array', 'items': {'type': 'string'}},
|
||||
|
@ -379,6 +377,8 @@ class AtalREST(BaseResource, HTTPResource):
|
|||
},
|
||||
)
|
||||
def worksrequests_single_attachment(self, request, worksrequests_id, post_data):
|
||||
if not post_data['file']:
|
||||
return {}
|
||||
try:
|
||||
content = base64.b64decode(post_data['file']['content'])
|
||||
except (TypeError, binascii.Error):
|
||||
|
@ -428,6 +428,8 @@ class AtalREST(BaseResource, HTTPResource):
|
|||
def worksrequests_attachments(self, request, post_data):
|
||||
files = []
|
||||
for file_ in post_data.get('files', []):
|
||||
if not file_:
|
||||
continue
|
||||
try:
|
||||
content = base64.b64decode(file_['content'])
|
||||
except (TypeError, binascii.Error):
|
||||
|
@ -442,6 +444,8 @@ class AtalREST(BaseResource, HTTPResource):
|
|||
),
|
||||
)
|
||||
)
|
||||
if not files:
|
||||
return {}
|
||||
data = {'Ids': post_data['worksrequests_ids']}
|
||||
# return nothing if successful
|
||||
self._call(
|
||||
|
|
|
@ -82,6 +82,51 @@ def test_worksrequests_single_attachment(app, connector):
|
|||
assert json_resp['err'] == 0
|
||||
|
||||
|
||||
def test_worksrequests_single_attachment_no_data(app, connector):
|
||||
with responses.RequestsMock() as rsps:
|
||||
params = {
|
||||
'file': '',
|
||||
}
|
||||
resp = app.post_json(
|
||||
'/atal-rest/test/worksrequests-single-attachment?worksrequests_id=1', params=params
|
||||
)
|
||||
json_resp = resp.json
|
||||
assert json_resp['err'] == 0
|
||||
assert len(rsps.calls) == 0
|
||||
|
||||
|
||||
def test_worksrequests_single_attachment_string_not_empty(app, connector):
|
||||
params = {
|
||||
'file': 'aaa',
|
||||
}
|
||||
app.post_json(
|
||||
'/atal-rest/test/worksrequests-single-attachment?worksrequests_id=1', params=params, status=400
|
||||
)
|
||||
|
||||
|
||||
def test_worksrequests_single_attachment_error(app, connector):
|
||||
with responses.RequestsMock() as rsps:
|
||||
rsps.post(
|
||||
'https://atal.invalid/api/WorksRequests/1/Attachments',
|
||||
status=400,
|
||||
json={
|
||||
'type': 'https://tools.ietf.org/html/rfc7231#section-6.5.1',
|
||||
'title': 'Bad Request',
|
||||
'status': 400,
|
||||
'"detail': 'No content","traceId":"00-1034a23a6cfbb7c508aa7e125a8e9a52-4570fc75745b7d1d-00',
|
||||
},
|
||||
)
|
||||
params = {
|
||||
'file': {'filename': 'bla', 'content': base64.b64encode(b'bla').decode('utf-8')},
|
||||
}
|
||||
resp = app.post_json(
|
||||
'/atal-rest/test/worksrequests-single-attachment?worksrequests_id=1', params=params
|
||||
)
|
||||
json_resp = resp.json
|
||||
assert json_resp['err'] == 1
|
||||
assert json_resp['data']['title'] == 'Bad Request'
|
||||
|
||||
|
||||
def test_worksrequests_attachments(app, connector):
|
||||
with responses.RequestsMock() as rsps:
|
||||
rsps.post('https://atal.invalid/api/WorksRequests/Attachments', status=200, body=b'')
|
||||
|
@ -97,6 +142,26 @@ def test_worksrequests_attachments(app, connector):
|
|||
assert json_resp['err'] == 0
|
||||
|
||||
|
||||
def test_worksrequests_attachments_no_data(app, connector):
|
||||
with responses.RequestsMock() as rsps:
|
||||
params = {
|
||||
'files': ['', ''],
|
||||
'worksrequests_ids': ['0', '1'],
|
||||
}
|
||||
resp = app.post_json('/atal-rest/test/worksrequests-attachments', params=params)
|
||||
json_resp = resp.json
|
||||
assert json_resp['err'] == 0
|
||||
assert len(rsps.calls) == 0
|
||||
|
||||
|
||||
def test_worksrequests_attachments_string_not_empty(app, connector):
|
||||
params = {
|
||||
'files': ['aa'],
|
||||
'worksrequests_ids': ['0', '1'],
|
||||
}
|
||||
app.post_json('/atal-rest/test/worksrequests-attachments', params=params, status=400)
|
||||
|
||||
|
||||
def test_worksrequests_attachments_error(app, connector):
|
||||
with responses.RequestsMock() as rsps:
|
||||
rsps.post(
|
||||
|
|
Loading…
Reference in New Issue