From d558e4967e3f517dcd779e90a52c037324b2dfa6 Mon Sep 17 00:00:00 2001 From: Jagaraganti Date: Tue, 19 Feb 2019 16:29:15 +0530 Subject: [PATCH] POC implementation done --- CyberSource/api_client.py | 79 ++++++++++++++++-- CyberSource/apis/instrument_identifier_api.py | 14 +++- .../apis/instrument_identifiers_api.py | 13 ++- .../apis/notification_of_changes_api.py | 6 +- CyberSource/apis/payment_instruments_api.py | 13 +++ CyberSource/apis/payments_api.py | 2 + .../apis/purchase_and_refund_details_api.py | 6 +- CyberSource/apis/report_subscriptions_api.py | 4 +- CyberSource/apis/reports_api.py | 6 +- CyberSource/apis/transaction_batches_api.py | 6 +- CyberSource/configuration.py | 3 +- .../models/generate_public_key_request.py | 4 +- CyberSource/models/request_body.py | 6 +- CyberSource/rest.py | 37 ++++++-- Resources/__init__.py | 0 Resources/testrest.p12 | Bin 0 -> 3553 bytes .../core/MerchantConfiguration.py | 9 +- authenticationsdk/logger/Log.py | 72 +++++++++------- authenticationsdk/test/test_Authorization.py | 57 +++++++++---- setup.py | 3 +- 20 files changed, 253 insertions(+), 87 deletions(-) create mode 100644 Resources/__init__.py create mode 100644 Resources/testrest.p12 diff --git a/CyberSource/api_client.py b/CyberSource/api_client.py index f46b52ba..7b7e1271 100644 --- a/CyberSource/api_client.py +++ b/CyberSource/api_client.py @@ -69,10 +69,14 @@ def __init__(self, host=None, header_name=None, header_value=None, cookie=None): """ self.rest_client = RESTClientObject() self.default_headers = {} + self.request_headers={} + #self.request_body={} + if header_name is not None: self.default_headers[header_name] = header_value - if host is None: + + if host is None: self.host = Configuration().host else: self.host = host @@ -94,8 +98,12 @@ def user_agent(self, value): """ self.default_headers['User-Agent'] = value + + + def set_default_header(self, header_name, header_value): self.default_headers[header_name] = header_value + # replace the underscore def replace_underscore(self, d): @@ -141,8 +149,8 @@ def call_authentication_header(self,method, header_params, body): if method.upper() == GlobalLabelParameters.POST or method.upper() == GlobalLabelParameters.PUT or method.upper() == GlobalLabelParameters.PATCH: mconfig.request_json_path_data = body - logger = mconfig.log - + logger = MyLogger.__call__(mconfig).get_logger() + Configuration().merchantconfig=mconfig auth = Authorization() token = auth.get_token(mconfig, mconfig.get_time(), logger) if mconfig.authentication_type.upper() == GlobalLabelParameters.HTTP.upper(): @@ -152,7 +160,7 @@ def call_authentication_header(self,method, header_params, body): header_params["Host"] = mconfig.request_host header_params["User-Agent"] = GlobalLabelParameters.USER_AGENT_VALUE if method.upper() == GlobalLabelParameters.POST or method.upper() == GlobalLabelParameters.PUT or method.upper() == GlobalLabelParameters.PATCH: - '''print((ast.literal_eval(json.dumps(self.del_none(json.loads(body))))))''' + digest_header = self.set_digest((body)) header_params[ @@ -164,6 +172,7 @@ def call_authentication_header(self,method, header_params, body): token = "Bearer " + token.decode("utf-8") header_params['Authorization'] = str(token) + # Set the digest def set_digest(self, body): digest_obj = DigestAndPayload() @@ -180,6 +189,36 @@ def set_query_params(self, path, query_param): return path + # This method reads the items to be masked and accordingly masks the response from the server + def masking(self,unmasked_data): + try: + unmasked_data_dict = json.loads(unmasked_data) + maskdata = json.dumps( + self.remove_key(unmasked_data_dict, "expirationMonth", "expirationYear", "email", "firstName", "lastName", "phoneNumber", + "number", "securityCode", "type")) + + + return maskdata + except Exception : + return unmasked_data + + + # This function replaces the value of the items to be masked to "XXXXX" + def remove_key(self,obj, *keys): + if type(obj) is dict: + for key, value in list(obj.items()): + if key not in keys: + obj[key] = self.remove_key(value, *keys) + obj[key] = value + else: + obj[key] = GlobalLabelParameters.MASKING_VALUE + elif type(obj) is list: + for i in range(len(obj)): + obj[i] = self.remove_key(obj[i],*keys) + + + return obj + def __call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, @@ -191,7 +230,10 @@ def __call_api(self, resource_path, method, # header parameters header_params = header_params or {} - header_params.update(self.default_headers) + #header_params.update(self.default_headers) + # sankalp + self.request_headers.update(header_params) + #self.request_body.update(body) if self.cookie: header_params['Cookie'] = self.cookie if header_params: @@ -231,8 +273,6 @@ def __call_api(self, resource_path, method, # request url url = GlobalLabelParameters.HTTP_URL_PREFIX+self.host + resource_path - - # perform request and return response response_data = self.request(method, url, query_params=query_params, @@ -242,14 +282,31 @@ def __call_api(self, resource_path, method, _request_timeout=_request_timeout) self.last_response = response_data - return_data = response_data + + if _preload_content: # deserialize response data if response_type: return_data = self.deserialize(response_data, response_type) + else: return_data = None + # Calling the masking logic + if response_data.data: + mask_values = self.masking(response_data.data) + response_data.data = mask_values + # Logging the details + '''if mconfig.enable_log is True: + self.logger.info("User Agent : "+(self.request_headers["User-Agent"])) + if body: + self.logger.info("Request Body : "+body) + self.logger.info("Request Headers : " + str(self.request_headers)) + self.logger.info("Response Code : " + str(response_data.status)) + self.logger.info("Response Message : "+response_data.data) + self.logger.info("Response Headers : "+str(response_data.getheaders())) + self.logger.info("END> =======================================")''' + if callback: if _return_http_data_only: @@ -257,7 +314,7 @@ def __call_api(self, resource_path, method, else: callback((return_data, response_data.status, response_data.getheaders())) elif _return_http_data_only: - return (return_data, response_data.status, response_data.data) + return (response_data) else: return (return_data, response_data.status, response_data.getheaders()) @@ -367,6 +424,7 @@ def __deserialize(self, data, klass): else: return self.__deserialize_model(data, klass) + def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, @@ -377,6 +435,7 @@ def call_api(self, resource_path, method, request_body = self.replace_underscore(json.loads(body)) body = json.dumps(request_body) query_param_path = self.set_query_params(resource_path, query_params) + if query_param_path: mconfig.request_target = query_param_path else: @@ -416,6 +475,7 @@ def call_api(self, resource_path, method, If parameter callback is None, then the method will return the response directly. """ + if callback is None: return self.__call_api(resource_path, method, path_params, query_params, header_params, @@ -431,6 +491,7 @@ def call_api(self, resource_path, method, response_type, auth_settings, callback, _return_http_data_only, collection_formats, _preload_content, _request_timeout)) + thread.start() return thread diff --git a/CyberSource/apis/instrument_identifier_api.py b/CyberSource/apis/instrument_identifier_api.py index 1cae96a4..b684cde8 100644 --- a/CyberSource/apis/instrument_identifier_api.py +++ b/CyberSource/apis/instrument_identifier_api.py @@ -22,7 +22,7 @@ from ..configuration import Configuration from ..api_client import ApiClient - +import json class InstrumentIdentifierApi(object): """ @@ -391,6 +391,9 @@ def tms_v1_instrumentidentifiers_token_id_patch_with_http_info(self, profile_id, # Authentication setting auth_settings = [] + # Check to delete null values in Input request json + body_params= json.dumps(self.del_none(json.loads(body_params))) + return self.api_client.call_api('/tms/v1/instrumentidentifiers/'+token_id, 'PATCH', path_params, query_params, @@ -405,3 +408,12 @@ def tms_v1_instrumentidentifiers_token_id_patch_with_http_info(self, profile_id, _preload_content=params.get('_preload_content', True), _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) + + # To delete None values in Input Request Json body(This code needs to be added through mustache changes) + def del_none(self,body): + for key, value in list(body.items()): + if value is None: + del body[key] + elif isinstance(value, dict): + self.del_none(value) + return body diff --git a/CyberSource/apis/instrument_identifiers_api.py b/CyberSource/apis/instrument_identifiers_api.py index fd416127..5d36941b 100644 --- a/CyberSource/apis/instrument_identifiers_api.py +++ b/CyberSource/apis/instrument_identifiers_api.py @@ -22,7 +22,7 @@ from ..configuration import Configuration from ..api_client import ApiClient - +import json class InstrumentIdentifiersApi(object): """ @@ -141,6 +141,8 @@ def tms_v1_instrumentidentifiers_post_with_http_info(self, profile_id, body, **k # Authentication setting auth_settings = [] + # Check to delete null values in Input request json + body_params = json.dumps(self.del_none(json.loads(body_params))) return self.api_client.call_api('/tms/v1/instrumentidentifiers', 'POST', path_params, @@ -156,3 +158,12 @@ def tms_v1_instrumentidentifiers_post_with_http_info(self, profile_id, body, **k _preload_content=params.get('_preload_content', True), _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) + + # To delete None values in Input Request Json body(This code needs to be added through mustache changes) + def del_none(self, body): + for key, value in list(body.items()): + if value is None: + del body[key] + elif isinstance(value, dict): + self.del_none(value) + return body diff --git a/CyberSource/apis/notification_of_changes_api.py b/CyberSource/apis/notification_of_changes_api.py index a7feb445..40465e55 100644 --- a/CyberSource/apis/notification_of_changes_api.py +++ b/CyberSource/apis/notification_of_changes_api.py @@ -118,10 +118,10 @@ def get_notification_of_change_report_with_http_info(self, start_time, end_time, path_params = {} query_params = [] - '''if 'start_time' in params: + if 'start_time' in params: query_params.append(('startTime', params['start_time'])) if 'end_time' in params: - query_params.append(('endTime', params['end_time']))''' + query_params.append(('endTime', params['end_time'])) header_params = {} @@ -140,7 +140,7 @@ def get_notification_of_change_report_with_http_info(self, start_time, end_time, # Authentication setting auth_settings = [] - return self.api_client.call_api('/reporting/v3/notification-of-changes?startTime='+start_time+'&endTime='+end_time, 'GET', + return self.api_client.call_api('/reporting/v3/notification-of-changes', 'GET', path_params, query_params, header_params, diff --git a/CyberSource/apis/payment_instruments_api.py b/CyberSource/apis/payment_instruments_api.py index 72a927d4..1c5de5ac 100644 --- a/CyberSource/apis/payment_instruments_api.py +++ b/CyberSource/apis/payment_instruments_api.py @@ -22,6 +22,7 @@ from ..configuration import Configuration from ..api_client import ApiClient +import json class PaymentInstrumentsApi(object): @@ -274,6 +275,8 @@ def tms_v1_paymentinstruments_post_with_http_info(self, profile_id, body, **kwar # Authentication setting auth_settings = [] + # Check to delete null values in Input request json + body_params = json.dumps(self.del_none(json.loads(body_params))) return self.api_client.call_api('/tms/v1/paymentinstruments', 'POST', path_params, @@ -638,6 +641,8 @@ def tms_v1_paymentinstruments_token_id_patch_with_http_info(self, profile_id, to # Authentication setting auth_settings = [] + # Check to delete null values in Input request json + body_params = json.dumps(self.del_none(json.loads(body_params))) return self.api_client.call_api('/tms/v1/paymentinstruments/'+token_id, 'PATCH', path_params, @@ -653,3 +658,11 @@ def tms_v1_paymentinstruments_token_id_patch_with_http_info(self, profile_id, to _preload_content=params.get('_preload_content', True), _request_timeout=params.get('_request_timeout'), collection_formats=collection_formats) + # To delete None values in Input Request Json body(This code needs to be added through mustache changes) + def del_none(self,body): + for key, value in list(body.items()): + if value is None: + del body[key] + elif isinstance(value, dict): + self.del_none(value) + return body diff --git a/CyberSource/apis/payments_api.py b/CyberSource/apis/payments_api.py index d15e382b..df649e01 100644 --- a/CyberSource/apis/payments_api.py +++ b/CyberSource/apis/payments_api.py @@ -36,6 +36,7 @@ def __init__(self, merchant_config, api_client=None): if api_client: self.api_client = api_client else: + if not config.api_client: config.api_client = ApiClient() self.api_client = config.api_client @@ -66,6 +67,7 @@ def create_payment(self, create_payment_request, **kwargs): return self.create_payment_with_http_info(create_payment_request, **kwargs) else: (data) = self.create_payment_with_http_info(create_payment_request, **kwargs) + return data def create_payment_with_http_info(self, create_payment_request, **kwargs): diff --git a/CyberSource/apis/purchase_and_refund_details_api.py b/CyberSource/apis/purchase_and_refund_details_api.py index 9958f9d9..61ee0195 100644 --- a/CyberSource/apis/purchase_and_refund_details_api.py +++ b/CyberSource/apis/purchase_and_refund_details_api.py @@ -140,10 +140,10 @@ def get_purchase_and_refund_details_with_http_info(self, start_time, end_time, * path_params = {} query_params = [] - '''if 'start_time' in params: + if 'start_time' in params: query_params.append(('startTime', params['start_time'])) if 'end_time' in params: - query_params.append(('endTime', params['end_time']))''' + query_params.append(('endTime', params['end_time'])) if 'organization_id' in params: query_params.append(('organizationId', params['organization_id'])) if 'payment_subtype' in params: @@ -174,7 +174,7 @@ def get_purchase_and_refund_details_with_http_info(self, start_time, end_time, * # Authentication setting auth_settings = [] - return self.api_client.call_api('/reporting/v3/purchase-refund-details?startTime='+start_time+'&endTime='+end_time, 'GET', + return self.api_client.call_api('/reporting/v3/purchase-refund-details', 'GET', path_params, query_params, header_params, diff --git a/CyberSource/apis/report_subscriptions_api.py b/CyberSource/apis/report_subscriptions_api.py index 5b101daf..d7964d21 100644 --- a/CyberSource/apis/report_subscriptions_api.py +++ b/CyberSource/apis/report_subscriptions_api.py @@ -106,8 +106,8 @@ def create_subscription_with_http_info(self,request_body, **kwargs): params[key] = val del params['kwargs'] # verify the required parameter 'report_name' is set - #if ('report_name' not in params) or (params['report_name'] is None): - #raise ValueError("Missing the required parameter `report_name` when calling `create_subscription`") + if ('report_name' not in params) or (params['report_name'] is None): + raise ValueError("Missing the required parameter `report_name` when calling `create_subscription`") # verify the required parameter 'request_body' is set if ('request_body' not in params) or (params['request_body'] is None): raise ValueError("Missing the required parameter `request_body` when calling `create_subscription`") diff --git a/CyberSource/apis/reports_api.py b/CyberSource/apis/reports_api.py index 60c9390a..7257aca0 100644 --- a/CyberSource/apis/reports_api.py +++ b/CyberSource/apis/reports_api.py @@ -365,12 +365,12 @@ def search_reports_with_http_info(self, start_time, end_time, time_query_type, * query_params = [] if 'organization_id' in params: query_params.append(('organizationId', params['organization_id'])) - '''if 'start_time' in params: + if 'start_time' in params: query_params.append(('startTime', params['start_time'])) if 'end_time' in params: query_params.append(('endTime', params['end_time'])) if 'time_query_type' in params: - query_params.append(('timeQueryType', params['time_query_type']))''' + query_params.append(('timeQueryType', params['time_query_type'])) if 'report_mime_type' in params: query_params.append(('reportMimeType', params['report_mime_type'])) if 'report_frequency' in params: @@ -399,7 +399,7 @@ def search_reports_with_http_info(self, start_time, end_time, time_query_type, * # Authentication setting auth_settings = [] - return self.api_client.call_api('/reporting/v3/reports?startTime='+start_time+'&endTime='+end_time+'&timeQueryType='+time_query_type, 'GET', + return self.api_client.call_api('/reporting/v3/reports', 'GET', path_params, query_params, header_params, diff --git a/CyberSource/apis/transaction_batches_api.py b/CyberSource/apis/transaction_batches_api.py index 40d5aa91..2b9f0fb4 100644 --- a/CyberSource/apis/transaction_batches_api.py +++ b/CyberSource/apis/transaction_batches_api.py @@ -118,10 +118,10 @@ def pts_v1_transaction_batches_get_with_http_info(self, start_time, end_time, ** path_params = {} query_params = [] - '''if 'start_time' in params: + if 'start_time' in params: query_params.append(('startTime', params['start_time'])) if 'end_time' in params: - query_params.append(('endTime', params['end_time']))''' + query_params.append(('endTime', params['end_time'])) header_params = {} @@ -140,7 +140,7 @@ def pts_v1_transaction_batches_get_with_http_info(self, start_time, end_time, ** # Authentication setting auth_settings = [] - return self.api_client.call_api('/pts/v1/transaction-batches?startTime='+start_time+'&endTime='+end_time, 'GET', + return self.api_client.call_api('/pts/v1/transaction-batches', 'GET', path_params, query_params, header_params, diff --git a/CyberSource/configuration.py b/CyberSource/configuration.py index 8c678830..76a85ceb 100644 --- a/CyberSource/configuration.py +++ b/CyberSource/configuration.py @@ -60,7 +60,6 @@ def __init__(self): self.username = "" # Password for HTTP basic authentication self.password = "" - # Logging Settings self.logger = {} self.logger["package_logger"] = logging.getLogger("CyberSource") @@ -90,6 +89,8 @@ def __init__(self): self.proxy = None # Safe chars for path_param self.safe_chars_for_path_param = '' + #merchantconfig obj of authsdk + self.merchantconfig=None @property def logger_file(self): diff --git a/CyberSource/models/generate_public_key_request.py b/CyberSource/models/generate_public_key_request.py index 4a84fd74..936c0e74 100644 --- a/CyberSource/models/generate_public_key_request.py +++ b/CyberSource/models/generate_public_key_request.py @@ -97,8 +97,8 @@ def encryption_type(self, encryption_type): :param encryption_type: The encryption_type of this GeneratePublicKeyRequest. :type: str """ - #if encryption_type is None: - #raise ValueError("Invalid value for `encryption_type`, must not be `None`") + if encryption_type is None: + raise ValueError("Invalid value for `encryption_type`, must not be `None`") self._encryption_type = encryption_type diff --git a/CyberSource/models/request_body.py b/CyberSource/models/request_body.py index 56677bd1..b8fda00b 100644 --- a/CyberSource/models/request_body.py +++ b/CyberSource/models/request_body.py @@ -80,13 +80,13 @@ def __init__(self, organization_id=None, report_definition_name=None, report_fie if organization_id is not None: self.organization_id = organization_id - #self.report_definition_name = report_definition_name - #self.report_fields = report_fields + self.report_definition_name = report_definition_name + self.report_fields = report_fields if report_mime_type is not None: self.report_mime_type = report_mime_type if report_frequency is not None: self.report_frequency = report_frequency - #self.report_name = report_name + self.report_name = report_name if timezone is not None: self.timezone = timezone if start_time is not None: diff --git a/CyberSource/rest.py b/CyberSource/rest.py index 6a86b90b..1dbc0ad2 100644 --- a/CyberSource/rest.py +++ b/CyberSource/rest.py @@ -25,7 +25,7 @@ from six.moves.urllib.parse import urlencode from .configuration import Configuration - +from authenticationsdk.logger.Log import MyLogger try: import urllib3 except ImportError: @@ -147,6 +147,7 @@ def request(self, method, url, query_params=None, headers=None, if 'Content-Type' not in headers: headers['Content-Type'] = 'application/json' + try: # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: @@ -162,6 +163,7 @@ def request(self, method, url, query_params=None, headers=None, preload_content=_preload_content, timeout=timeout, headers=headers) + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': r = self.pool_manager.request(method, url, fields=post_params, @@ -179,6 +181,7 @@ def request(self, method, url, query_params=None, headers=None, preload_content=_preload_content, timeout=timeout, headers=headers) + # Pass a `string` parameter directly in the body to support # other content types than Json when `body` argument is provided # in serialized form @@ -208,17 +211,28 @@ def request(self, method, url, query_params=None, headers=None, if _preload_content: r = RESTResponse(r) + # In the python 3, the response.data is bytes. # we need to decode it to string. if PY3: r.data = r.data.decode('utf8') # log response body - logger.debug("response body: %s", r.data) + if Configuration().merchantconfig.enable_log is True: + logger = MyLogger.__call__(Configuration().merchantconfig).get_logger() + #logger=Configuration().merchantconfig.log + if body: + logger.info("Request Body: %s", Configuration().api_client.masking(body)) + logger.info("Request Headers: %s",str(Configuration().api_client.request_headers)) + logger.info("Response Body: %s",str(Configuration().api_client.masking(r.data))) + logger.info("Response Status: %s",r.status) + logger.info("Response Headers: %s",r.getheaders()) + logger.info("END> =======================================") if not 200 <= r.status <= 299: raise ApiException(http_resp=r) + return r def GET(self, url, headers=None, query_params=None, _preload_content=True, _request_timeout=None): @@ -292,6 +306,8 @@ def __init__(self, status=None, reason=None, http_resp=None): self.reason = http_resp.reason self.body = http_resp.data self.headers = http_resp.getheaders() + + else: self.status = status self.reason = reason @@ -302,12 +318,19 @@ def __str__(self): """ Custom error messages for exception """ - error_message = "({0})\n"\ - "Reason: {1}\n".format(self.status, self.reason) + error_message="" + if Configuration().api_client.request_headers: + error_message += "\nAPI REQUEST HEADERS: {0}\n".format(Configuration().api_client.request_headers) + error_message += "\nAPI RESPONSE CODE: {0}\n"\ + "\nReason: {1}\n".format(self.status, self.reason) + if self.body: + error_message += "\nAPI RESPONSE BODY: {0}\n".format(self.body) + if self.headers: - error_message += "HTTP response headers: {0}\n".format(self.headers) + error_message += "\nAPI RESPONSE HEADERS: {0}".format(self.headers) + + #Configuration().logger_obj.info(error_message) + - if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) return error_message diff --git a/Resources/__init__.py b/Resources/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/testrest.p12 b/Resources/testrest.p12 new file mode 100644 index 0000000000000000000000000000000000000000..3d09e55046312f3bef42e7cb484a136f634fa58a GIT binary patch literal 3553 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 literal 0 HcmV?d00001 diff --git a/authenticationsdk/core/MerchantConfiguration.py b/authenticationsdk/core/MerchantConfiguration.py index d5fdcbd1..f5420dc8 100644 --- a/authenticationsdk/core/MerchantConfiguration.py +++ b/authenticationsdk/core/MerchantConfiguration.py @@ -6,8 +6,8 @@ import json import authenticationsdk.util.ExceptionAuth import os -import authenticationsdk.logger.Log - +#import authenticationsdk.logger.Log +from authenticationsdk.logger.Log import MyLogger class MerchantConfiguration: @@ -152,8 +152,9 @@ def get_time(self): # This validates the Merchant details def validate_merchant_details(self, details, mconfig): # verify Mandatory Properties - logger = authenticationsdk.logger.Log.setup_logger(mconfig) - mconfig.log = logger + #logger = authenticationsdk.logger.Log.setup_logger(mconfig) + #mconfig.log = logger + logger = MyLogger.__call__(mconfig).get_logger() if self.enable_log is True: logger.info("START> ======================================= ") if self.merchant_id is None or self.merchant_id == "": diff --git a/authenticationsdk/logger/Log.py b/authenticationsdk/logger/Log.py index 1f06bea4..41749a24 100644 --- a/authenticationsdk/logger/Log.py +++ b/authenticationsdk/logger/Log.py @@ -3,31 +3,47 @@ import os -def setup_logger(mconfig): - # Creating a log directory if the directory is not present - # If the directory is present then just append in the file - if mconfig.enable_log is True: - logger_folder = mconfig.log_directory - logger_file = os.path.join(logger_folder , mconfig.log_file_name)+ ".log" - if not os.path.exists(logger_folder): - os.makedirs(logger_folder) - if not os.path.exists(logger_file): - open(logger_file, "a+") - if logger_file: - if os.stat(logger_file).st_size > int(mconfig.maximum_size): - updated_file = os.path.join(logger_folder , mconfig.log_file_name)+"_" + datetime.now().strftime("%Y%m%d%H%M%S") + ".log" - os.rename(logger_file, updated_file) - # setting the logger object - logger = logging.getLogger() - if not logger.handlers: - # add a File handler - handler = logging.FileHandler(filename=logger_file) - # create a logging format - formatter = logging.Formatter('%(asctime)s- %(message)s') - handler.setFormatter(formatter) - - logger.setLevel(logging.INFO) - # add the handlers to the logger - logger.addHandler(handler) - - return logger +class SingletonType(type): + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(SingletonType, cls).__call__(*args, **kwargs) + return cls._instances[cls] + + +# python 3 style +class MyLogger(object, metaclass=SingletonType): + # __metaclass__ = SingletonType # python 2 Style + + def __init__(self, mconfig): + self.mconfig = mconfig + + if mconfig.enable_log is True: + logger_folder = mconfig.log_directory + logger_file = os.path.join(logger_folder, mconfig.log_file_name) + ".log" + if not os.path.exists(logger_folder): + os.makedirs(logger_folder) + if not os.path.exists(logger_file): + open(logger_file, "a+") + if logger_file: + if os.stat(logger_file).st_size > int(mconfig.maximum_size): + updated_file = os.path.join(logger_folder, mconfig.log_file_name) + "_" + datetime.now().strftime( + "%Y%m%d%H%M%S") + ".log" + os.rename(logger_file, updated_file) + # setting the logger object + self.logger = logging.getLogger() + if not self.logger.handlers: + # add a File handler + handler = logging.FileHandler(filename=logger_file) + # create a logging format + formatter = logging.Formatter('%(asctime)s- %(message)s') + handler.setFormatter(formatter) + + self.logger.setLevel(logging.INFO) + # add the handlers to the logger + self.logger.addHandler(handler) + + def get_logger(self): + if self.mconfig.enable_log is True: + return self.logger diff --git a/authenticationsdk/test/test_Authorization.py b/authenticationsdk/test/test_Authorization.py index af9db01f..606929b7 100644 --- a/authenticationsdk/test/test_Authorization.py +++ b/authenticationsdk/test/test_Authorization.py @@ -1,11 +1,9 @@ import unittest from authenticationsdk.core.MerchantConfiguration import * from authenticationsdk.core.Authorization import * -import authenticationsdk.logger.Log -import authenticationsdk.util.PropertiesUtil import logging from authenticationsdk.core.MockData import * - +from authenticationsdk.logger.Log import MyLogger class TestBasicFunction(unittest.TestCase): def setUp(self): @@ -24,7 +22,7 @@ def test_token_for_get_http(self): self.get_id = "5246387105766473203529" self.merchant_config.request_target = "/pts/v2/payments/" + self.get_id - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) @@ -35,7 +33,7 @@ def test_get_http_enable_log(self): self.merchant_config.request_type_method = "GET" self.get_id = "5246387105766473203529" self.merchant_config.request_target = "/pts/v2/payments/" + self.get_id - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.merchant_config.validate_merchant_details(MockData.HTTP_DEFAULT_VALUES, self.merchant_config) self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) @@ -47,7 +45,7 @@ def test_get_jwt_production_url(self): self.merchant_config.request_type_method = "GET" self.get_id = "5246387105766473203529" self.merchant_config.request_target = "/pts/v2/payments/" + self.get_id - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.merchant_config.validate_merchant_details(MockData.JWT_VALUES_FOR_PRODUCTION, self.merchant_config) @@ -59,7 +57,7 @@ def test_token_for_post_http(self): self.merchant_config.request_type_method = "POST" self.merchant_config.request_target = "/pts/v2/payments" - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.merchant_config.request_json_path_data = json.dumps(MockData.REQUEST_DATA) @@ -72,7 +70,7 @@ def test_token_for_put_http(self): self.merchant_config.request_target = "/reporting/v2/reportSubscriptions/TRRReport?organizationId=testrest" - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.merchant_config.request_json_path_data = json.dumps(MockData.TRR_DATA) @@ -83,9 +81,22 @@ def test_token_for_delete_http(self): self.merchant_config.set_merchantconfig(MockData.HTTP_VALUES) self.merchant_config.request_type_method = "DELETE" - self.merchant_config.request_target = "/reporting/v2/reportSubscriptions/TRRReport?organizationId=testrest/5246387105766473203529" + self.merchant_config.request_target = "/tms/v1/instrumentidentifiers/7010000000004750123" + + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() + + self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) + + # This method checks the HTTP_Patch token Generation Unit Testing + def test_token_for_patch_http(self): + self.merchant_config.set_merchantconfig(MockData.JWT_VALUES) + self.merchant_config.request_type_method = "PATCH" + + self.merchant_config.request_target = "/tms/v1/instrumentidentifiers/7010000000004750123" + + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.merchant_config.request_json_path_data = json.dumps(MockData.REQUEST_DATA) self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) @@ -96,7 +107,7 @@ def test_token_for_get_jwt(self): self.get_id = "5246387105766473203529" self.merchant_config.request_target = "/pts/v2/payments/" + self.get_id - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) @@ -105,8 +116,8 @@ def test_token_for_post_jwt(self): self.merchant_config.set_merchantconfig(MockData.JWT_VALUES) self.merchant_config.request_type_method = "POST" self.merchant_config.request_target = "/pts/v2/payments/5246387105766473203529" - - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.merchant_config.request_json_path_data = json.dumps(MockData.REQUEST_DATA) @@ -119,7 +130,7 @@ def test_token_for_put_jwt(self): self.merchant_config.request_target = "/reporting/v2/reportSubscriptions/TRRReport?organizationId=testrest" - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.merchant_config.request_json_path_data =json.dumps(MockData.TRR_DATA) @@ -131,10 +142,26 @@ def test_token_for_delete_jwt(self): self.merchant_config.request_type_method = "DELETE" self.merchant_config.request_target = "/reporting/v2/reportSubscriptions/TRRReport?organizationId=testrest/5246387105766473203529" - self.logger = authenticationsdk.logger.Log.setup_logger(self.merchant_config) + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) + # This method checks the JWT_Patch token Generation Unit Testing + def test_token_for_patch_jwt(self): + self.merchant_config.set_merchantconfig(MockData.JWT_VALUES) + self.merchant_config.request_type_method = "PATCH" + + self.merchant_config.request_target = "/tms/v1/instrumentidentifiers/7010000000004750123" + + self.logger = MyLogger.__call__(mconfig=self.merchant_config).get_logger() + + self.merchant_config.request_json_path_data = json.dumps(MockData.REQUEST_DATA) + + self.assertIsNotNone(self.func.get_token(self.merchant_config, self.date, self.logger)) + + + + if __name__ == '__main__': unittest.main() diff --git a/setup.py b/setup.py index 51cee81b..1450e689 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ # prerequisite: setuptools # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3", "six", "certifi", "DateTime", "Naked", "PyJWT", "PyNaCl", "PyYAML", +REQUIRES = ["pycryptodome","urllib3", "six", "certifi", "DateTime", "Naked", "PyJWT", "PyNaCl", "PyYAML", "asn1crypto", "bcrypt", "certifi", @@ -38,7 +38,6 @@ "pyOpenSSL", "pyasn1", "pycparser", - "pycryptodome", "pycryptodomex", "pypi", "python-mimeparse",