Skip to content

Commit

Permalink
refactor: sms vendor with notification-gateway api (#191)
Browse files Browse the repository at this point in the history
* refactor: sms vendor OAUTH2Basic authenticator

* refactor: extende OAUTH2Basic authenticator
  • Loading branch information
johanseto committed Jul 16, 2024
1 parent a640038 commit 1973b74
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
34 changes: 34 additions & 0 deletions eox_nelp/api_clients/authenticators.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,37 @@ def authenticate(self, api_client):
)

return session


class Oauth2BasicAuthenticator(BasicAuthAuthenticator):
"""Authenticator for custom use using basic auth to get a Oauth2 Token (Bearer or JWT).
Token_type on depends of the response used after the oauth2 token request.
Then the token is used for the next requests.
"""

def authenticate(self, api_client):
"""Authenticate the session with basic auth in order to get token(Bearer or JWT).
Then the token is added to a new session Headers.
Is needed the user, password and token_path class atrributes to the get oauth2 token,
based on the client configuration.
"""
auth_session = super().authenticate(api_client)
key = f"oauth2-basic-{api_client.user}-{api_client.password}"
headers = cache.get(key)

if not headers:
authenticate_url = f"{api_client.base_url}/{api_client.token_path}"
response = auth_session.post(
url=authenticate_url,
data={"grant_type": "client_credentials", "scope": "notification"}
).json()
headers = {
"Authorization": f"{response.get('token_type')} {response.get('access_token')}"
}

cache.set(key, headers, int(response.get("expires_in", 300)))

session = requests.Session()
session.headers.update(headers)

return session
16 changes: 11 additions & 5 deletions eox_nelp/api_clients/sms_vendor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.conf import settings

from eox_nelp.api_clients import AbstractAPIRestClient
from eox_nelp.api_clients.authenticators import Oauth2BasicAuthenticator

try:
from eox_audit_model.decorators import audit_method
Expand All @@ -17,11 +18,19 @@ def audit_method(action): # pylint: disable=unused-argument

class SMSVendorApiClient(AbstractAPIRestClient):
"""Allow to perform SMS send operations."""
authentication_class = Oauth2BasicAuthenticator

@property
def base_url(self):
return getattr(settings, "SMS_VENDOR_URL")

def __init__(self):
self.user = getattr(settings, "SMS_VENDOR_USERNAME")
self.password = getattr(settings, "SMS_VENDOR_PASSWORD")
self.token_path = getattr(settings, "SMS_VENDOR_TOKEN_PATH")

super().__init__()

def send_sms(self, recipient, message):
"""This send SMS using an external Vendor via API.
Expand All @@ -37,11 +46,8 @@ def send_sms_request(recipient, message):
"""This is a wrapper that allows to make audit-able the send_SMS method."""
path = getattr(settings, "SMS_VENDOR_SEND_SMS_PATH", "")
payload = {
"message": message,
"number": recipient,
"username": getattr(settings, "SMS_VENDOR_USERNAME"),
"password": getattr(settings, "SMS_VENDOR_PASSWORD"),
"sender": getattr(settings, "SMS_VENDOR_MSG_SENDER", "NELC"),
"sms_message": message,
"recipient_number": recipient,
}
return self.make_post(path, payload)

Expand Down
22 changes: 11 additions & 11 deletions eox_nelp/api_clients/tests/test_sms_vendor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"""
import unittest

from django.conf import settings
from mock import patch
from mock import Mock, patch

from eox_nelp.api_clients.sms_vendor import SMSVendorApiClient
from eox_nelp.api_clients.tests.mixins import TestRestApiClientMixin
Expand All @@ -20,28 +19,29 @@ def setUp(self):
self.api_class = SMSVendorApiClient

@patch.object(SMSVendorApiClient, "make_post")
@patch.object(SMSVendorApiClient, "_authenticate", Mock())
def test_send_sms(self, post_mock):
"""Test successful post request.
Expected behavior:
- Response is the expected value
"""
expected_value = {
"message": "SMS sent =), waiting what would be this field.",
"responseCode": 200,
"message": "Operation completed successfully",
"transaction_id": "50693df-665d-47e1-affb-01076a83b9023427",
"recipient": "+573219990000",
"timestamp": "1720220972275"
}
post_mock.return_value = expected_value
recipient = 3219802890
recipient = "+573219990000"
message = "This is a message to test SMS integration."
api_client = self.api_class()
expected_payload = {
"message": message,
"number": recipient,
"username": settings.SMS_VENDOR_USERNAME,
"password": settings.SMS_VENDOR_PASSWORD,
"sender": settings.SMS_VENDOR_MSG_SENDER,
"sms_message": message,
"recipient_number": recipient,
}

response = api_client.send_sms(recipient, message)

self.assertDictEqual(response, expected_value)
post_mock.assert_called_once_with("", expected_payload)
post_mock.assert_called_once_with("sms/send", expected_payload)
3 changes: 2 additions & 1 deletion eox_nelp/settings/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def plugin_settings(settings): # pylint: disable=function-redefined
settings.SMS_VENDOR_URL = 'https://testing.com'
settings.SMS_VENDOR_USERNAME = 'test-user'
settings.SMS_VENDOR_PASSWORD = 'test-password'
settings.SMS_VENDOR_MSG_SENDER = 'Nelc-test'
settings.SMS_VENDOR_TOKEN_PATH = "oauth2/v1/token"
settings.SMS_VENDOR_SEND_SMS_PATH = 'sms/send'

settings.PEARSON_RTI_WSDL_URL = 'https://testing.com'
settings.PEARSON_RTI_CERT = '/openedx/certs/cert.p12'
Expand Down

0 comments on commit 1973b74

Please sign in to comment.