From c100a0e2e4712533c0c160e42e3d409b0d0416b4 Mon Sep 17 00:00:00 2001 From: mobeenali12 Date: Tue, 25 Jul 2023 15:36:14 +0500 Subject: [PATCH 1/3] feat: Implemented dedicated SDN service. --- ecommerce/extensions/api/v2/urls.py | 6 ++ ecommerce/extensions/api/v2/views/sdn.py | 75 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 ecommerce/extensions/api/v2/views/sdn.py diff --git a/ecommerce/extensions/api/v2/urls.py b/ecommerce/extensions/api/v2/urls.py index 36e6d0c98a5..e4258201882 100644 --- a/ecommerce/extensions/api/v2/urls.py +++ b/ecommerce/extensions/api/v2/urls.py @@ -20,6 +20,7 @@ from ecommerce.extensions.api.v2.views import publication as publication_views from ecommerce.extensions.api.v2.views import refunds as refund_views from ecommerce.extensions.api.v2.views import retirement as retirement_views +from ecommerce.extensions.api.v2.views import sdn as sdn_views from ecommerce.extensions.api.v2.views import stockrecords as stockrecords_views from ecommerce.extensions.api.v2.views import user_management as user_management_views from ecommerce.extensions.api.v2.views import vouchers as voucher_views @@ -109,6 +110,10 @@ url(r'^replace_usernames/$', user_management_views.UsernameReplacementView.as_view(), name='username_replacement'), ] +SDN_URLS = [ + url(r'^$', sdn_views.SDNView.as_view(), name='sdn') +] + urlpatterns = [ url(r'^baskets/', include((BASKET_URLS, 'baskets'))), url(r'^checkout/', include((CHECKOUT_URLS, 'checkout'))), @@ -122,6 +127,7 @@ url(r'^user_management/', include((USER_MANAGEMENT_URLS, 'user_management'))), url(r'^assignment-email/', include((ASSIGNMENT_EMAIL_URLS, 'assignment-email'))), url(r'^webhooks/', include((WEBHOOKS_URLS, 'webhooks'))), + url(r'^sdn/', include((SDN_URLS, 'sdn'))), ] router = SimpleRouter() diff --git a/ecommerce/extensions/api/v2/views/sdn.py b/ecommerce/extensions/api/v2/views/sdn.py new file mode 100644 index 00000000000..e82ecd1d07f --- /dev/null +++ b/ecommerce/extensions/api/v2/views/sdn.py @@ -0,0 +1,75 @@ +import logging +from urllib.parse import urlencode + +import requests +from django.conf import settings + +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework.permissions import IsAuthenticated + +logger = logging.getLogger(__name__) + + +class SDNView(APIView): + """A class that act as a dedicated SDN service.""" + + http_method_names = ['get'] + # permission_classes = (IsAuthenticated,) + + def get(self, request): + """ + Searches the OFAC list for an individual with the specified details. + The check returns zero hits if: + * request to the SDN API times out + * SDN API returns a non-200 status code response + * user is not found on the SDN list + + URL params: + name (str): Individual's full name. + city (str): Individual's city. + country (str): ISO 3166-1 alpha-2 country code where the individual is from. + Returns: + dict: SDN API response. + """ + name = request.GET.get('name') + city = request.GET.get('city') + country = request.GET.get('country') + sdn_list = request.site.siteconfiguration.sdn_api_list + + params_dict = { + 'sources': sdn_list, + 'type': 'individual', + 'name': str(name).encode('utf-8'), + 'city': str(city).encode('utf-8'), + 'countries': country + } + params = urlencode(params_dict) + + sdn_check_url = f'{settings.SDN_CHECK_API_URL}?{params}' + auth_header = {'subscription-key': settings.SDN_CHECK_API_KEY} + + try: + response = requests.get( + sdn_check_url, + headers=auth_header, + timeout=settings.SDN_CHECK_REQUEST_TIMEOUT + ) + except requests.exceptions.Timeout: + error_msg = f'Connection to US Treasury SDN API timed out for {name}.' + logger.warning(error_msg) + return Response({ + 'msg': error_msg + }) + + if response.status_code != 200: + logger.warning( + 'Unable to connect to US Treasury SDN API for [%s]. Status code [%d] with message: [%s]', + name, response.status_code, response.content + ) + return Response({ + 'msg': f'Unable to connect to US Treasury SDN API for {name}. Status code {response.status_code}', + 'response': response.json() + }) + + return Response(response.json()) From 6bcd57a57d5ccb33641e3d581520b8c5e27e5480 Mon Sep 17 00:00:00 2001 From: mobeenali12 Date: Tue, 25 Jul 2023 15:38:28 +0500 Subject: [PATCH 2/3] feat: Added API permissions. --- ecommerce/extensions/api/v2/views/sdn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecommerce/extensions/api/v2/views/sdn.py b/ecommerce/extensions/api/v2/views/sdn.py index e82ecd1d07f..1e0c36a9d57 100644 --- a/ecommerce/extensions/api/v2/views/sdn.py +++ b/ecommerce/extensions/api/v2/views/sdn.py @@ -15,7 +15,7 @@ class SDNView(APIView): """A class that act as a dedicated SDN service.""" http_method_names = ['get'] - # permission_classes = (IsAuthenticated,) + permission_classes = (IsAuthenticated,) def get(self, request): """ From 3990782e42a70cff5930e9080595005c12c5d511 Mon Sep 17 00:00:00 2001 From: mobeenali12 Date: Tue, 25 Jul 2023 18:51:06 +0500 Subject: [PATCH 3/3] feat: imports fixed --- ecommerce/extensions/api/v2/views/sdn.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ecommerce/extensions/api/v2/views/sdn.py b/ecommerce/extensions/api/v2/views/sdn.py index 1e0c36a9d57..b913b4801ff 100644 --- a/ecommerce/extensions/api/v2/views/sdn.py +++ b/ecommerce/extensions/api/v2/views/sdn.py @@ -3,14 +3,12 @@ import requests from django.conf import settings - -from rest_framework.views import APIView -from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView logger = logging.getLogger(__name__) - class SDNView(APIView): """A class that act as a dedicated SDN service.""" @@ -62,6 +60,8 @@ def get(self, request): 'msg': error_msg }) + sdn_response = response.json() + if response.status_code != 200: logger.warning( 'Unable to connect to US Treasury SDN API for [%s]. Status code [%d] with message: [%s]', @@ -69,7 +69,7 @@ def get(self, request): ) return Response({ 'msg': f'Unable to connect to US Treasury SDN API for {name}. Status code {response.status_code}', - 'response': response.json() + 'response': sdn_response }) - return Response(response.json()) + return Response(sdn_response)