Gracefully handle credit provider keys with unicode type
This commit is contained in:
@@ -16,17 +16,30 @@ we receive from the credit provider.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_shared_secret_key(provider_id):
|
||||
"""
|
||||
Retrieve the shared secret key for a particular credit provider.
|
||||
"""
|
||||
return getattr(settings, "CREDIT_PROVIDER_SECRET_KEYS", {}).get(provider_id)
|
||||
secret = getattr(settings, "CREDIT_PROVIDER_SECRET_KEYS", {}).get(provider_id)
|
||||
|
||||
if isinstance(secret, unicode):
|
||||
try:
|
||||
secret = str(secret)
|
||||
except UnicodeEncodeError:
|
||||
secret = None
|
||||
log.error(u'Shared secret key for credit provider "%s" contains non-ASCII unicode.', provider_id)
|
||||
|
||||
return secret
|
||||
|
||||
|
||||
def signature(params, shared_secret):
|
||||
@@ -35,6 +48,7 @@ def signature(params, shared_secret):
|
||||
|
||||
Arguments:
|
||||
params (dict): Parameters to sign. Ignores the "signature" key if present.
|
||||
shared_secret (str): The shared secret string.
|
||||
|
||||
Returns:
|
||||
str: The 32-character signature.
|
||||
|
||||
37
openedx/core/djangoapps/credit/tests/test_signature.py
Normal file
37
openedx/core/djangoapps/credit/tests/test_signature.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Tests for digital signatures used to validate messages to/from credit providers.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
|
||||
|
||||
from openedx.core.djangoapps.credit import signature
|
||||
|
||||
|
||||
class SignatureTest(TestCase):
|
||||
"""
|
||||
Tests for digital signatures.
|
||||
"""
|
||||
|
||||
@override_settings(CREDIT_PROVIDER_SECRET_KEYS={
|
||||
"asu": u'abcd1234'
|
||||
})
|
||||
def test_unicode_secret_key(self):
|
||||
# Test a key that has type `unicode` but consists of ASCII characters
|
||||
# (This can happen, for example, when loading the key from a JSON configuration file)
|
||||
# When retrieving the shared secret, the type should be converted to `str`
|
||||
key = signature.get_shared_secret_key("asu")
|
||||
sig = signature.signature({}, key)
|
||||
self.assertEqual(sig, "7d70a26b834d9881cc14466eceac8d39188fc5ef5ffad9ab281a8327c2c0d093")
|
||||
|
||||
@override_settings(CREDIT_PROVIDER_SECRET_KEYS={
|
||||
"asu": u'\u4567'
|
||||
})
|
||||
def test_non_ascii_unicode_secret_key(self):
|
||||
# Test a key that contains non-ASCII unicode characters
|
||||
# This should return `None` and log an error; the caller
|
||||
# is then responsible for logging the appropriate errors
|
||||
# so we can fix the misconfiguration.
|
||||
key = signature.get_shared_secret_key("asu")
|
||||
self.assertIs(key, None)
|
||||
Reference in New Issue
Block a user