Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/pan 2339 schema for response #157

Merged
merged 9 commits into from
Nov 27, 2024
5 changes: 4 additions & 1 deletion openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

from pantos.servicenode.restapi import _BidSchema
from pantos.servicenode.restapi import _BidsSchema
from pantos.servicenode.restapi import _TransferResponseSchema
from pantos.servicenode.restapi import _TransferSchema
from pantos.servicenode.restapi import _TransferStatusResponseSchema
from pantos.servicenode.restapi import _TransferStatusSchema
from pantos.servicenode.restapi import flask_app

Expand All @@ -24,7 +26,8 @@

template = spec.to_flasgger(
flask_app, definitions=[
_BidSchema, _BidsSchema, _TransferSchema, _TransferStatusSchema
_BidSchema, _BidsSchema, _TransferSchema, _TransferResponseSchema,
_TransferStatusSchema, _TransferStatusResponseSchema
])

swagger = Swagger(flask_app, template=template, parse=True)
Expand Down
83 changes: 42 additions & 41 deletions pantos/servicenode/restapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@ def make_initiate_transfer_request(
return TransferInteractor.InitiateTransferRequest(**data)


class _TransferResponseSchema(marshmallow.Schema):
"""Validation schema for the transfer response.

"""
task_id = marshmallow.fields.UUID(required=True)


class _TransferStatusSchema(marshmallow.Schema):
"""Validation schema for the transfer status endpoint parameters.

Expand All @@ -198,6 +205,28 @@ def make_task_id(self, data: typing.Dict[str, typing.Any],
return data['task_id']


class _TransferStatusResponseSchema(marshmallow.Schema):
"""Validation schema for the transfer status response.

"""
task_id = marshmallow.fields.String(required=True)
source_blockchain_id = marshmallow.fields.Integer(
required=True, validate=marshmallow.validate.OneOf(
[blockchain.value for blockchain in Blockchain]))
destination_blockchain_id = marshmallow.fields.Integer(
required=True, validate=marshmallow.validate.OneOf(
[blockchain.value for blockchain in Blockchain]))
sender_address = marshmallow.fields.String(required=True)
recipient_address = marshmallow.fields.String(required=True)
source_token_address = marshmallow.fields.String(required=True)
destination_token_address = marshmallow.fields.String(required=True)
amount = marshmallow.fields.Integer(required=True)
fee = marshmallow.fields.Integer(required=True)
status = marshmallow.fields.String(required=True)
transfer_id = marshmallow.fields.Integer(required=True)
transaction_id = marshmallow.fields.String(required=True)


class _BidsSchema(marshmallow.Schema):
"""Validation schema for the bids endpoint parameters.

Expand Down Expand Up @@ -233,27 +262,24 @@ def post(self) -> flask.Response:
content:
application/json:
schema:
type: object
properties:
task_id:
type: string
$ref: "#/components/schemas/_TransferResponse"
406:
description: Transfer request no accepted
content:
application/json:
schema:
type: array
type: string
items:
type: string
example: "[bid has been rejected by service node: \
'bid not accepted']"
example: {message': 'bid has been rejected by service \
node: bid not accepted'}
409:
description: Sender nonce from transfer request is not unique
content:
application/json:
schema:
type: string
example: sender nonce 1337 is not unique
example: {'message': 'sender nonce 1337 is not unique'}
500:
description: Internal server error
"""
Expand All @@ -265,6 +291,7 @@ def post(self) -> flask.Response:
_logger.info('new transfer request', extra=arguments)
task_id = TransferInteractor().initiate_transfer(
initiate_transfer_request)
response = _TransferResponseSchema().dump({'task_id': task_id})
except marshmallow.ValidationError as error:
not_acceptable(error.messages)
except SenderNonceNotUniqueError as error:
Expand All @@ -273,12 +300,12 @@ def post(self) -> flask.Response:
f'{initiate_transfer_request.nonce} is not unique')
except TransferInteractorBidNotAcceptedError as error:
_logger.warning(f'bid has been rejected by service node: {error}')
not_acceptable([f'bid has been rejected by service node: {error}'])
not_acceptable(f'bid has been rejected by service node: {error}')
except Exception:
_logger.critical('unable to process a transfer request',
exc_info=True)
internal_server_error()
return ok_response({'task_id': str(task_id)})
return ok_response(response)


class _TransferStatus(flask_restful.Resource):
Expand All @@ -305,34 +332,7 @@ def get(self, task_id: str) -> flask.Response:
content:
application/json:
schema:
type: object
properties:
task_id:
type: string
source_blockchain_id:
$ref: "#/components/schemas/\
_Bids/properties/source_blockchain"
destination_blockchain_id:
$ref: "#/components/schemas/\
_Bids/properties/destination_blockchain"
sender_address:
type: string
recipient_address:
type: string
source_token_address:
type: string
destination_token_address:
type: string
amount:
type: integer
fee:
type: integer
status:
type: string
transfer_id:
type: string
transaction_id:
type: string
$ref: '#/components/schemas/_TransferStatusResponse'
404:
description: 'not found'
content:
Expand Down Expand Up @@ -360,7 +360,8 @@ def get(self, task_id: str) -> flask.Response:
_logger.critical('unable to process a transfer status request',
exc_info=True)
internal_server_error()
return ok_response({

response = _TransferStatusResponseSchema().dump({
'task_id': str(task_id_uuid),
'source_blockchain_id': find_transfer_response.source_blockchain.
value,
Expand All @@ -376,11 +377,11 @@ def get(self, task_id: str) -> flask.Response:
'fee': find_transfer_response.fee,
'status': find_transfer_response.status.to_public_status().name.
lower(),
'transfer_id': '' if find_transfer_response.transfer_id is None
else find_transfer_response.transfer_id,
'transfer_id': find_transfer_response.transfer_id,
'transaction_id': '' if find_transfer_response.transaction_id
is None else find_transfer_response.transaction_id
})
return ok_response(response)


class _Bids(flask_restful.Resource):
Expand Down
5 changes: 2 additions & 3 deletions tests/restapi/test_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ def test_transfer_sender_nonce_not_unique_error(mocked_load,
406, message=error_message)

response = test_client.post('/transfer', json={})

mocked_conflict.assert_called_once_with(
f'sender nonce {mocked_load().nonce} is not unique')
assert response.status_code == 406
Expand All @@ -77,9 +76,9 @@ def test_transfer_bid_not_accepted_error(mocked_load, mocked_initiate_transfer,
406, message=error_message)

response = test_client.post('/transfer', json={})

assert response.status_code == 406
mocked_not_acceptable.assert_called_once()
mocked_not_acceptable.assert_called_once_with(
'bid has been rejected by service node: bid not accepted')


@unittest.mock.patch('pantos.servicenode.restapi.internal_server_error')
Expand Down
1 change: 0 additions & 1 deletion tests/restapi/test_transfer_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def test_transfer_status_correct(mocked_load, mocked_find_transfer,
mocked_find_transfer.return_value = find_transfer_response

response = test_client.get(f'/transfer/{uuid_}/status')

assert response.status_code == 200
assert json.loads(response.text) == expected_transfer_status

Expand Down