Skip to content

Commit

Permalink
Merge pull request #33 from ITVaan/add_source_date
Browse files Browse the repository at this point in the history
Add source date
  • Loading branch information
kroman0 committed May 11, 2017
2 parents 9b5c97a + 03e3031 commit 24c82a1
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 20 deletions.
26 changes: 26 additions & 0 deletions openprocurement/integrations/edr/tests/_server.py
Expand Up @@ -3,6 +3,9 @@
from simplejson import dumps


SOURCEDATE = 'Tue, 25 Apr 2017 11:56:36 GMT'


def setup_routing(app, func, path='/1.0/subjects', method='GET'):
""" Setup routs """
app.routes = []
Expand All @@ -13,9 +16,11 @@ def response_code():
code = request.query.code
if not code.isdigit() or not (len(code) == 10 or len(code) == 8):
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps([])
response.status = 200
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps([{"code": code,
"name": "АКЦІОНЕРНЕ ТОВАРИСТВО КОМЕРЦІЙНИЙ БАНК \"ПРИВАТБАНК\"",
"url": "https://zqedr-api.nais.gov.ua/1.0/subjects/2842335",
Expand All @@ -29,13 +34,16 @@ def response_passport():
if passport.isdigit() and len(passport) == 11:
response.status = 400
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 11, "message": "`passport` parameter has wrong value."}]})
if passport.isalpha():
response.status = 400
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 11, "message": "`passport` parameter has wrong value."}]})
response.status = 200
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps([{"code": passport,
"name": passport,
"url": "https://zqedr-api.nais.gov.ua/1.0/subjects/2842336",
Expand All @@ -48,65 +56,76 @@ def check_headers():
if request.headers.get('Authorization') == 'Token':
response.status = 401
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 1, "message": "Authentication credentials were not provided."}]})
elif request.headers.get('Authorization') == 'Token 123':
response.status = 401
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 2, "message": "Invalid or expired token."}]})


def payment_required():
response.status = 402
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 5, "message": "Payment required."}]})


def forbidden():
response.status = 403
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 3, "message": "Your account is not permitted to access this resource."}]})


def not_found():
response.status = 404
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 4, "message": "Sorry, that page does not exist."}]})


def not_acceptable():
response.status = 406
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"message": "Message."}]})


def too_many_requests():
response.status = 429
response.set_header('Retry-After', 26)
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 9, "message": "Request was throttled. Expected available in 26 seconds."}]})


def server_error():
response.status = 500
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 20, "message": "Internal error."}]})


def bad_gateway():
response.status = 502
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"message": "Message."}]})


def two_error_messages():
response.status = 404
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 0, "message": "Message1."}, {"code": 0, "message": "Message2."}]})


def response_details():
response.status = 200
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({
"id": 2842335,
"state": 1,
Expand Down Expand Up @@ -250,30 +269,35 @@ def too_many_requests_details():
response.status = 429
response.set_header('Retry-After', 26)
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"code": 9, "message": "Request was throttled. Expected available in 26 seconds."}]})


def bad_gateway_details():
response.status = 502
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({"errors": [{"message": "Message."}]})


def wrong_ip_address():
response.status = 403
response.content_type = 'text/html'
response.headers['Date'] = SOURCEDATE
return '<html>\r\n<head><title>403 Forbidden</title></head>\r\n<body bgcolor="white">\r\n<center><h1>403 Forbidden</h1></center>\r\n<hr><center>nginx/1.10.1</center>\r\n</body>\r\n</html>\r\n'


def wrong_ip_address_detailed_request():
response.status = 403
response.content_type = 'text/html'
response.headers['Date'] = SOURCEDATE
return '<html>\r\n<head><title>403 Forbidden</title></head>\r\n<body bgcolor="white">\r\n<center><h1>403 Forbidden</h1></center>\r\n<hr><center>nginx/1.10.1</center>\r\n</body>\r\n</html>\r\n'


def null_fields():
response.status = 200
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({
"id": 2842335,
"state": 1,
Expand Down Expand Up @@ -383,6 +407,7 @@ def null_fields():
def sandbox_mode_data():
response.status = 200
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps([{
"url": "https://zqedr-api.nais.gov.ua/1.0/subjects/999186",
"id": 999186,
Expand All @@ -395,6 +420,7 @@ def sandbox_mode_data():
def sandbox_mode_data_details():
response.status = 200
response.content_type = 'application/json'
response.headers['Date'] = SOURCEDATE
return dumps({
"id": 999186,
"state": 1,
Expand Down
2 changes: 2 additions & 0 deletions openprocurement/integrations/edr/tests/test_data.yaml
Expand Up @@ -7,3 +7,5 @@ data:
registrationStatus: registered
registrationStatusDetails: зареєстровано
x_edrInternalId: 2842335
meta:
sourceDate: '2017-04-25T11:56:36+00:00'
2 changes: 2 additions & 0 deletions openprocurement/integrations/edr/tests/test_data_details.yaml
Expand Up @@ -35,3 +35,5 @@ data:
scheme: UA-EDR
management: ЗАГАЛЬНІ ЗБОРИ
name: ПАТ КБ "ПРИВАТБАНК"
meta:
sourceDate: '2017-04-25T11:56:36+00:00'
36 changes: 25 additions & 11 deletions openprocurement/integrations/edr/tests/verify.py
@@ -1,13 +1,15 @@
# -*- coding: utf-8 -*-
import webtest
import os
import datetime
import iso8601

from openprocurement.integrations.edr.tests.base import BaseWebTest
from openprocurement.integrations.edr.tests._server import (setup_routing, response_code, response_passport,
check_headers, payment_required, forbidden, not_acceptable, too_many_requests, two_error_messages, bad_gateway,
server_error, response_details, too_many_requests_details, bad_gateway_details, wrong_ip_address,
wrong_ip_address_detailed_request, null_fields, sandbox_mode_data, sandbox_mode_data_details)
from openprocurement.integrations.edr.utils import SANDBOX_MODE
from openprocurement.integrations.edr.utils import SANDBOX_MODE, TZ


class TestVerify(BaseWebTest):
Expand Down Expand Up @@ -51,15 +53,15 @@ def test_edrpou(self):
response = self.app.get('/verify?id=14360570')
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(
response.json['data'],
[{u'registrationStatusDetails': u'зареєстровано',
u'registrationStatus': u'registered',
u'identification': {u'url': u'https://zqedr-api.nais.gov.ua/1.0/subjects/2842335',
u'schema': u'UA-EDR',
u'id': u'14360570',
u'legalName': u"АКЦІОНЕРНЕ ТОВАРИСТВО КОМЕРЦІЙНИЙ БАНК \"ПРИВАТБАНК\""},
u'x_edrInternalId': 2842335}])
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})
self.assertEqual(response.json['data'],
[{u'registrationStatusDetails': u'зареєстровано',
u'registrationStatus': u'registered',
u'identification': {u'url': u'https://zqedr-api.nais.gov.ua/1.0/subjects/2842335',
u'schema': u'UA-EDR',
u'id': u'14360570',
u'legalName': u"АКЦІОНЕРНЕ ТОВАРИСТВО КОМЕРЦІЙНИЙ БАНК \"ПРИВАТБАНК\""},
u'x_edrInternalId': 2842335}])

def test_passport(self):
""" Get info by passport number """
Expand Down Expand Up @@ -92,6 +94,7 @@ def test_new_passport(self):
u'id': u'123456789',
u'legalName': u'123456789'},
u'x_edrInternalId': 2842336}])
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})

def test_ipn(self):
""" Get info by IPN (physical entity-entrepreneur)"""
Expand All @@ -106,6 +109,7 @@ def test_ipn(self):
u'schema': u'UA-EDR', u'id': u'1234567891',
u'legalName': u"АКЦІОНЕРНЕ ТОВАРИСТВО КОМЕРЦІЙНИЙ БАНК \"ПРИВАТБАНК\""},
u'x_edrInternalId': 2842335}])
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})

def test_invalid_passport(self):
"""Check invalid passport number АБВ"""
Expand All @@ -122,7 +126,9 @@ def test_invalid_code(self):
response = self.app.get('/verify?id=123', status=404)
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.status, '404 Not Found')
self.assertEqual(response.json['errors'][0]['description'], [{u'message': u'EDRPOU not found'}])
self.assertEqual(response.json['errors'][0]['description'],
[{u'message': u'EDRPOU not found',
u'meta': {u'sourceDate': u'2017-04-25T11:56:36+00:00'}}])

def test_unauthorized(self):
"""Send request without token using tests_copy.ini conf file"""
Expand Down Expand Up @@ -255,6 +261,8 @@ def test_sandbox_mode_data(self):
u'id': u'00037256',
u'legalName': u"ДЕРЖАВНЕ УПРАВЛІННЯ СПРАВАМИ"},
u'x_edrInternalId': 999186}])
self.assertEqual(iso8601.parse_date(response.json['meta']['sourceDate']).replace(second=0, microsecond=0),
datetime.datetime.now(tz=TZ).replace(second=0, microsecond=0))
else:
setup_routing(self.edr_api_app, func=sandbox_mode_data)
response = self.app.get('/verify?id=00037256')
Expand All @@ -269,6 +277,7 @@ def test_sandbox_mode_data(self):
u'id': u'00037256',
u'legalName': u"ДЕРЖАВНЕ УПРАВЛІННЯ СПРАВАМИ"},
u'x_edrInternalId': 999186}])
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})


class TestDetails(BaseWebTest):
Expand Down Expand Up @@ -314,6 +323,7 @@ def test_details(self):
u"id": u"64.19",
u"description": u"Інші види грошового посередництва"}
})
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})

def test_too_many_requests_details(self):
"""Check 429 status EDR response(too many requests) for details request"""
Expand Down Expand Up @@ -369,6 +379,7 @@ def test_null_fields(self):
u"activityKind": {u"scheme": u"КВЕД",
u"id": u"64.19",
u"description": u"Інші види грошового посередництва"}})
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})

def test_sandbox_mode_data_details(self):
"""If SANDBOX_MODE=True define func=response_code and check that returns data from test_data_details.json.
Expand Down Expand Up @@ -403,6 +414,8 @@ def test_sandbox_mode_data_details(self):
u"id": u"84.11",
u"description": u"Державне управління загального характеру"
}})
self.assertEqual(iso8601.parse_date(response.json['meta']['sourceDate']).replace(second=0, microsecond=0),
datetime.datetime.now(tz=TZ).replace(second=0, microsecond=0))
else:
setup_routing(self.edr_api_app, path='/1.0/subjects/999186', func=sandbox_mode_data_details)
response = self.app.get('/details/999186')
Expand Down Expand Up @@ -433,6 +446,7 @@ def test_sandbox_mode_data_details(self):
u"id": u"84.11",
u"description": u"Державне управління загального характеру"
}})
self.assertEqual(response.json['meta'], {'sourceDate': '2017-04-25T11:56:36+00:00'})


class TestVerifyPlatform(TestVerify):
Expand Down
7 changes: 6 additions & 1 deletion openprocurement/integrations/edr/utils.py
Expand Up @@ -5,7 +5,7 @@
from pkg_resources import get_distribution
from webob.multidict import NestedMultiDict
from datetime import datetime
from pytz import timezone
from pytz import timezone, UTC
from hashlib import sha512
from ConfigParser import ConfigParser
from pyramid.security import Allow
Expand Down Expand Up @@ -247,3 +247,8 @@ def read_json(name):

TEST_DATA_VERIFY = read_json('test_data_verify.json')
TEST_DATA_DETAILS = read_json('test_data_details.json')


def meta_data(date):
"""return sourceDate in ISO 8601format """
return {'sourceDate': datetime.strptime(date, '%a, %d %b %Y %H:%M:%S %Z').replace(tzinfo=UTC).isoformat()}
22 changes: 14 additions & 8 deletions openprocurement/integrations/edr/views/verify.py
Expand Up @@ -3,17 +3,20 @@
from collections import namedtuple
from pyramid.view import view_config
from logging import getLogger
from datetime import datetime
from openprocurement.integrations.edr.utils import prepare_data_details, prepare_data, error_handler, SANDBOX_MODE, \
TEST_DATA_VERIFY, TEST_DATA_DETAILS
TEST_DATA_VERIFY, TEST_DATA_DETAILS, meta_data, TZ


LOGGER = getLogger(__name__)
EDRDetails = namedtuple("EDRDetails", ['param', 'code'])


def handle_error(request, message, status=403):
LOGGER.info('Error on processing request "{}"'.format(message))
return error_handler(request, status, {"location": "body",
"name": "data",
"description": message})
"name": "data",
"description": message})


@view_config(route_name='verify', renderer='json',
Expand All @@ -28,7 +31,8 @@ def verify_user(request):
details = EDRDetails('passport', passport)
if SANDBOX_MODE and TEST_DATA_VERIFY.get(details.code):
LOGGER.info('Return test data for {}'.format(details.code))
return {'data': [prepare_data(d) for d in TEST_DATA_VERIFY[details.code]]}
return {'data': [prepare_data(d) for d in TEST_DATA_VERIFY[details.code]],
'meta': {'sourceDate': datetime.now(tz=TZ).isoformat()}}
try:
response = request.registry.edr_client.get_subject(**details._asdict())
except (requests.exceptions.ReadTimeout,
Expand All @@ -40,9 +44,10 @@ def verify_user(request):
data = response.json()
if not data:
LOGGER.warning('Accept empty response from EDR service for {}'.format(details.code))
return handle_error(request, [{u'message': u'EDRPOU not found'}], 404)
return handle_error(request, [{u'message': u'EDRPOU not found',
u'meta': meta_data(response.headers['Date'])}], 404)
LOGGER.info('Return data from EDR service for {}'.format(details.code))
return {'data': [prepare_data(d) for d in data]}
return {'data': [prepare_data(d) for d in data], 'meta': meta_data(response.headers['Date'])}
elif response.status_code == 429:
request.response.headers['Retry-After'] = response.headers.get('Retry-After')
return handle_error(request, [{u'message': u'Retry request after {} seconds.'.format(response.headers.get('Retry-After'))}], status=429)
Expand All @@ -58,7 +63,8 @@ def user_details(request):
id = request.matchdict.get('id')
if SANDBOX_MODE and TEST_DATA_DETAILS.get(id):
LOGGER.info('Return test data for {}'.format(id))
return {'data': prepare_data_details(TEST_DATA_DETAILS[id])}
return {'data': prepare_data_details(TEST_DATA_DETAILS[id]),
'meta': {'sourceDate': datetime.now(tz=TZ).isoformat()}}
try:
response = request.registry.edr_client.get_subject_details(id)
except (requests.exceptions.ReadTimeout,
Expand All @@ -69,7 +75,7 @@ def user_details(request):
if response.status_code == 200:
data = response.json()
LOGGER.info('Return detailed data from EDR service for {}'.format(id))
return {'data': prepare_data_details(data)}
return {'data': prepare_data_details(data), 'meta': meta_data(response.headers['Date'])}
elif response.status_code == 429:
request.response.headers['Retry-After'] = response.headers.get('Retry-After')
return handle_error(request, [{u'message': u'Retry request after {} seconds.'.format(response.headers.get('Retry-After'))}], status=429)
Expand Down

0 comments on commit 24c82a1

Please sign in to comment.