Commit 1189867d by Clinton Blackburn Committed by Clinton Blackburn

Removed references to ECOMMERCE_API_SIGNING_KEY

We should not be using custom signing keys for each service at this time. We may want to return to this strategy in the future; but, this is not the direction any of our other services are going in.

ECOM-6541
parent e5112bd3
......@@ -49,7 +49,6 @@ import request_cache
from certificates.models import GeneratedCertificate
from course_modes.models import CourseMode
from enrollment.api import _default_course_mode
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client, ECOMMERCE_DATE_FORMAT
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.xmodule_django.models import CourseKeyField, NoneToEmptyManager
......@@ -1537,6 +1536,9 @@ class CourseEnrollment(models.Model):
def refund_cutoff_date(self):
""" Calculate and return the refund window end date. """
# NOTE: This is here to avoid circular references
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client, ECOMMERCE_DATE_FORMAT
try:
attribute = self.attributes.get(namespace='order', name='order_number')
except ObjectDoesNotExist:
......
......@@ -30,7 +30,6 @@ from config_models.models import cache
log = logging.getLogger(__name__)
TEST_API_URL = 'http://www-internal.example.com/api'
TEST_API_SIGNING_KEY = 'edx'
JSON = 'application/json'
......@@ -131,7 +130,7 @@ class RefundableTest(SharedModuleStoreTestCase):
)
@ddt.unpack
@httpretty.activate
@override_settings(ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY, ECOMMERCE_API_URL=TEST_API_URL)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
def test_refund_cutoff_date(self, order_date_delta, course_start_delta, expected_date_delta, days):
"""
Assert that the later date is used with the configurable refund period in calculating the returned cutoff date.
......@@ -172,7 +171,7 @@ class RefundableTest(SharedModuleStoreTestCase):
self.assertIsNone(self.enrollment.refund_cutoff_date())
@httpretty.activate
@override_settings(ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY, ECOMMERCE_API_URL=TEST_API_URL)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
def test_multiple_refunds_dashbaord_page_error(self):
""" Order with mutiple refunds will not throw 500 error when dashboard page will access."""
now = datetime.now(pytz.UTC).replace(microsecond=0)
......
......@@ -18,7 +18,7 @@ from social import actions, exceptions
from social.apps.django_app import utils as social_utils
from social.apps.django_app import views as social_views
from lms.djangoapps.commerce.tests import TEST_API_URL, TEST_API_SIGNING_KEY
from lms.djangoapps.commerce.tests import TEST_API_URL
from student import models as student_models
from student import views as student_views
from student.tests.factories import UserFactory
......@@ -911,7 +911,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase):
# pylint: disable=test-inherits-tests, abstract-method
@django_utils.override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
@django_utils.override_settings(ECOMMERCE_API_URL=TEST_API_URL)
class Oauth2IntegrationTest(IntegrationTest):
"""Base test case for integration tests of Oauth2 providers."""
......
......@@ -17,7 +17,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from commerce.constants import Messages
from commerce.tests import TEST_BASKET_ID, TEST_ORDER_NUMBER, TEST_PAYMENT_DATA, TEST_API_URL, TEST_API_SIGNING_KEY
from commerce.tests import TEST_BASKET_ID, TEST_ORDER_NUMBER, TEST_PAYMENT_DATA
from commerce.tests.mocks import mock_basket_order, mock_create_basket
from commerce.tests.test_views import UserMixin
from course_modes.models import CourseMode
......@@ -39,7 +39,6 @@ UTM_COOKIE_CONTENTS = {
@attr(shard=1)
@ddt.ddt
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase):
"""
Tests for the commerce orders view.
......@@ -276,7 +275,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
# We should be enrolled in honor mode
self._test_course_without_sku(enrollment_mode=CourseMode.HONOR)
@override_settings(ECOMMERCE_API_URL=None, ECOMMERCE_API_SIGNING_KEY=None)
@override_settings(ECOMMERCE_API_URL=None)
def test_ecommerce_service_not_configured(self):
"""
If the E-Commerce Service is not configured, the view should enroll the user.
......@@ -313,7 +312,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
""" Verifies that the view behaves appropriately when the course only has a professional mode. """
self.assertProfessionalModeBypassed()
@override_settings(ECOMMERCE_API_URL=None, ECOMMERCE_API_SIGNING_KEY=None)
@override_settings(ECOMMERCE_API_URL=None)
def test_professional_mode_only_and_ecommerce_service_not_configured(self):
"""
Verifies that the view behaves appropriately when the course only has a professional mode and
......@@ -390,7 +389,6 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
@attr(shard=1)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
class BasketOrderViewTests(UserMixin, TestCase):
""" Tests for the basket order view. """
view_name = 'commerce_api:v0:baskets:retrieve_order'
......
......@@ -17,7 +17,6 @@ from rest_framework.utils.encoders import JSONEncoder
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from commerce.tests import TEST_API_URL, TEST_API_SIGNING_KEY
from commerce.tests.mocks import mock_order_endpoint
from commerce.tests.test_views import UserMixin
from course_modes.models import CourseMode
......@@ -391,7 +390,6 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase)
@attr(shard=1)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
class OrderViewTests(UserMixin, TestCase):
""" Tests for the basket order view. """
view_name = 'commerce_api:v1:orders:detail'
......
# -*- coding: utf-8 -*-
""" Commerce app tests package. """
import datetime
import json
import httpretty
import mock
from django.conf import settings
from django.contrib.auth.models import User
from django.test import TestCase
from django.test.utils import override_settings
from freezegun import freeze_time
import httpretty
import jwt
import mock
from edx_rest_api_client import auth
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
from openedx.core.lib.token_utils import JwtBuilder
from student.tests.factories import UserFactory
JSON = 'application/json'
TEST_PUBLIC_URL_ROOT = 'http://www.example.com'
TEST_API_URL = 'http://www-internal.example.com/api'
TEST_API_SIGNING_KEY = 'edx'
TEST_BASKET_ID = 7
TEST_ORDER_NUMBER = '100004'
TEST_PAYMENT_DATA = {
......@@ -29,33 +23,27 @@ TEST_PAYMENT_DATA = {
}
@override_settings(ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY, ECOMMERCE_API_URL=TEST_API_URL)
class EdxRestApiClientTest(TestCase):
""" Tests to ensure the client is initialized properly. """
TEST_USER_EMAIL = 'test@example.com'
TEST_CLIENT_ID = 'test-client-id'
def setUp(self):
super(EdxRestApiClientTest, self).setUp()
self.user = UserFactory()
self.user.email = self.TEST_USER_EMAIL
self.user.save() # pylint: disable=no-member
@httpretty.activate
@freeze_time('2015-7-2')
@override_settings(JWT_AUTH={'JWT_ISSUER': 'http://example.com/oauth', 'JWT_EXPIRATION': 30})
def test_tracking_context(self):
"""
Ensure the tracking context is set up in the api client correctly and
automatically.
"""
# fake an ecommerce api request.
# fake an E-Commerce API request.
httpretty.register_uri(
httpretty.POST,
'{}/baskets/1/'.format(TEST_API_URL),
'{}/baskets/1/'.format(settings.ECOMMERCE_API_URL.strip('/')),
status=200, body='{}',
adding_headers={'Content-Type': JSON}
)
......@@ -65,23 +53,18 @@ class EdxRestApiClientTest(TestCase):
with mock.patch('openedx.core.djangoapps.commerce.utils.tracker.get_tracker', return_value=mock_tracker):
ecommerce_api_client(self.user).baskets(1).post()
# make sure the request's JWT token payload included correct tracking context values.
# Verify the JWT includes the tracking context for the user
actual_header = httpretty.last_request().headers['Authorization']
expected_payload = {
'username': self.user.username,
'full_name': self.user.profile.name,
'email': self.user.email,
'iss': settings.JWT_AUTH['JWT_ISSUER'],
'iat': datetime.datetime.utcnow(),
'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=settings.JWT_AUTH['JWT_EXPIRATION']),
claims = {
'tracking_context': {
'lms_user_id': self.user.id, # pylint: disable=no-member
'lms_client_id': self.TEST_CLIENT_ID,
'lms_ip': '127.0.0.1',
},
}
}
expected_header = 'JWT {}'.format(jwt.encode(expected_payload, TEST_API_SIGNING_KEY))
expected_jwt = JwtBuilder(self.user).build_token(['email', 'profile'], additional_claims=claims)
expected_header = 'JWT {}'.format(expected_jwt)
self.assertEqual(actual_header, expected_header)
@httpretty.activate
......@@ -95,19 +78,9 @@ class EdxRestApiClientTest(TestCase):
expected_content = '{"result": "Préparatoire"}'
httpretty.register_uri(
httpretty.GET,
'{}/baskets/1/order/'.format(TEST_API_URL),
'{}/baskets/1/order/'.format(settings.ECOMMERCE_API_URL.strip('/')),
status=200, body=expected_content,
adding_headers={'Content-Type': JSON},
)
actual_object = ecommerce_api_client(self.user).baskets(1).order.get()
self.assertEqual(actual_object, {u"result": u"Préparatoire"})
def test_client_with_user_without_profile(self):
"""
Verify client initialize successfully for users having no profile.
"""
worker = User.objects.create_user(username='test_worker', email='test@example.com')
api_client = ecommerce_api_client(worker)
self.assertEqual(api_client._store['session'].auth.__dict__['username'], worker.username) # pylint: disable=protected-access
self.assertIsNone(api_client._store['session'].auth.__dict__['full_name']) # pylint: disable=protected-access
......@@ -2,11 +2,14 @@
import json
import httpretty
from django.conf import settings
from commerce.tests import TEST_API_URL, factories
from commerce.tests import factories
class mock_ecommerce_api_endpoint(object): # pylint: disable=invalid-name
# pylint: disable=invalid-name
class mock_ecommerce_api_endpoint(object):
"""
Base class for contextmanagers used to mock calls to api endpoints.
......@@ -21,6 +24,8 @@ class mock_ecommerce_api_endpoint(object): # pylint: disable=invalid-name
# override this in subclasses, using one of httpretty's method constants
method = None
host = settings.ECOMMERCE_API_URL.strip('/')
def __init__(self, response=None, status=200, expect_called=True, exception=None):
"""
Keyword Arguments:
......@@ -37,9 +42,18 @@ class mock_ecommerce_api_endpoint(object): # pylint: disable=invalid-name
def get_uri(self):
"""
Return the uri to register with httpretty for this contextmanager.
Returns the uri to register with httpretty for this contextmanager.
"""
return self.host + '/' + self.get_path().lstrip('/')
def get_path(self):
"""
Returns the path of the URI to register with httpretty for this contextmanager.
Subclasses must override this method.
Returns:
str
"""
raise NotImplementedError
......@@ -48,7 +62,6 @@ class mock_ecommerce_api_endpoint(object): # pylint: disable=invalid-name
raise self.exception # pylint: disable=raising-bad-type
def __enter__(self):
httpretty.reset()
httpretty.enable()
httpretty.register_uri(
self.method,
......@@ -61,9 +74,10 @@ class mock_ecommerce_api_endpoint(object): # pylint: disable=invalid-name
def __exit__(self, exc_type, exc_val, exc_tb):
assert self.expect_called == (httpretty.last_request().headers != {})
httpretty.disable()
httpretty.reset()
class mock_create_basket(mock_ecommerce_api_endpoint): # pylint: disable=invalid-name
class mock_create_basket(mock_ecommerce_api_endpoint):
""" Mocks calls to E-Commerce API client basket creation method. """
default_response = {
......@@ -77,11 +91,11 @@ class mock_create_basket(mock_ecommerce_api_endpoint): # pylint: disable=invali
}
method = httpretty.POST
def get_uri(self):
return TEST_API_URL + '/baskets/'
def get_path(self):
return '/baskets/'
class mock_basket_order(mock_ecommerce_api_endpoint): # pylint: disable=invalid-name
class mock_basket_order(mock_ecommerce_api_endpoint):
""" Mocks calls to E-Commerce API client basket order method. """
default_response = {'number': 1}
......@@ -91,21 +105,21 @@ class mock_basket_order(mock_ecommerce_api_endpoint): # pylint: disable=invalid
super(mock_basket_order, self).__init__(**kwargs)
self.basket_id = basket_id
def get_uri(self):
return TEST_API_URL + '/baskets/{}/order/'.format(self.basket_id)
def get_path(self):
return '/baskets/{}/order/'.format(self.basket_id)
class mock_create_refund(mock_ecommerce_api_endpoint): # pylint: disable=invalid-name
class mock_create_refund(mock_ecommerce_api_endpoint):
""" Mocks calls to E-Commerce API client refund creation method. """
default_response = []
method = httpretty.POST
def get_uri(self):
return TEST_API_URL + '/refunds/'
def get_path(self):
return '/refunds/'
class mock_order_endpoint(mock_ecommerce_api_endpoint): # pylint: disable=invalid-name
class mock_order_endpoint(mock_ecommerce_api_endpoint):
""" Mocks calls to E-Commerce API client basket order method. """
default_response = {'number': 'EDX-100001'}
......@@ -115,11 +129,11 @@ class mock_order_endpoint(mock_ecommerce_api_endpoint): # pylint: disable=inval
super(mock_order_endpoint, self).__init__(**kwargs)
self.order_number = order_number
def get_uri(self):
return TEST_API_URL + '/orders/{}/'.format(self.order_number)
def get_path(self):
return '/orders/{}/'.format(self.order_number)
class mock_get_orders(mock_ecommerce_api_endpoint): # pylint: disable=invalid-name
class mock_get_orders(mock_ecommerce_api_endpoint):
""" Mocks calls to E-Commerce API client order get method. """
default_response = {
......@@ -138,5 +152,5 @@ class mock_get_orders(mock_ecommerce_api_endpoint): # pylint: disable=invalid-n
}
method = httpretty.GET
def get_uri(self):
return TEST_API_URL + '/orders/'
def get_path(self):
return '/orders/'
......@@ -9,21 +9,22 @@ import json
from urlparse import urljoin
import ddt
import httpretty
import mock
from django.contrib.auth.models import AnonymousUser
from django.test import TestCase
from django.test.utils import override_settings
import httpretty
import mock
from opaque_keys.edx.keys import CourseKey
from requests import Timeout
from student.models import UNENROLL_DONE
from student.tests.factories import UserFactory, CourseEnrollmentFactory
from commerce.signals import (refund_seat, send_refund_notification, generate_refund_notification_body,
create_zendesk_ticket)
from commerce.tests import TEST_PUBLIC_URL_ROOT, TEST_API_URL, TEST_API_SIGNING_KEY, JSON
from commerce.signals import (
refund_seat, send_refund_notification, generate_refund_notification_body, create_zendesk_ticket
)
from commerce.tests import JSON
from commerce.tests.mocks import mock_create_refund
from course_modes.models import CourseMode
from student.models import UNENROLL_DONE
from student.tests.factories import UserFactory, CourseEnrollmentFactory
ZENDESK_URL = 'http://zendesk.example.com/'
ZENDESK_USER = 'test@example.com'
......@@ -31,11 +32,7 @@ ZENDESK_API_KEY = 'abc123'
@ddt.ddt
@override_settings(
ECOMMERCE_PUBLIC_URL_ROOT=TEST_PUBLIC_URL_ROOT,
ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY,
ZENDESK_URL=ZENDESK_URL, ZENDESK_USER=ZENDESK_USER, ZENDESK_API_KEY=ZENDESK_API_KEY
)
@override_settings(ZENDESK_URL=ZENDESK_URL, ZENDESK_USER=ZENDESK_USER, ZENDESK_API_KEY=ZENDESK_API_KEY)
class TestRefundSignal(TestCase):
"""
Exercises logic triggered by the UNENROLL_DONE signal.
......@@ -65,7 +62,6 @@ class TestRefundSignal(TestCase):
@override_settings(
ECOMMERCE_PUBLIC_URL_ROOT=None,
ECOMMERCE_API_URL=None,
ECOMMERCE_API_SIGNING_KEY=None,
)
def test_no_service(self):
"""
......
......@@ -32,7 +32,7 @@ from provider.oauth2.models import (
from testfixtures import LogCapture
from commerce.models import CommerceConfiguration
from commerce.tests import TEST_API_URL, TEST_API_SIGNING_KEY, factories
from commerce.tests import factories
from commerce.tests.mocks import mock_get_orders
from course_modes.models import CourseMode
from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories
......@@ -506,7 +506,6 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
})
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConfigMixin):
""" Tests for the account settings view. """
......
......@@ -36,7 +36,7 @@ from course_modes.tests.factories import CourseModeFactory
from courseware.url_helpers import get_redirect_url
from common.test.utils import XssTestMixin
from commerce.models import CommerceConfiguration
from commerce.tests import TEST_PAYMENT_DATA, TEST_API_URL, TEST_API_SIGNING_KEY, TEST_PUBLIC_URL_ROOT
from commerce.tests import TEST_PAYMENT_DATA, TEST_API_URL, TEST_PUBLIC_URL_ROOT
from openedx.core.djangoapps.embargo.test_utils import restrict_course
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
......@@ -140,7 +140,6 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
@httpretty.activate
@override_settings(
ECOMMERCE_API_URL=TEST_API_URL,
ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY,
ECOMMERCE_PUBLIC_URL_ROOT=TEST_PUBLIC_URL_ROOT
)
def test_start_flow_with_ecommerce(self):
......@@ -1053,7 +1052,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
self.assertEqual(response_dict['course_name'], mode_display_name)
@httpretty.activate
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
@ddt.data("verify_student_start_flow", "verify_student_begin_flow")
def test_processors_api(self, payment_flow):
"""
......@@ -1223,7 +1222,7 @@ class TestCreateOrderShoppingCart(CheckoutTestMixin, ModuleStoreTestCase):
@attr(shard=2)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
@patch(
'lms.djangoapps.verify_student.views.checkout_with_ecommerce_service',
return_value=TEST_PAYMENT_DATA,
......@@ -1248,7 +1247,7 @@ class TestCheckoutWithEcommerceService(ModuleStoreTestCase):
"""
@httpretty.activate
@override_settings(ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
def test_create_basket(self):
"""
Check that when working with a product being processed by the
......
......@@ -776,7 +776,6 @@ ONLOAD_BEACON_SAMPLE_RATE = ENV_TOKENS.get('ONLOAD_BEACON_SAMPLE_RATE', ONLOAD_B
##### ECOMMERCE API CONFIGURATION SETTINGS #####
ECOMMERCE_PUBLIC_URL_ROOT = ENV_TOKENS.get('ECOMMERCE_PUBLIC_URL_ROOT', ECOMMERCE_PUBLIC_URL_ROOT)
ECOMMERCE_API_URL = ENV_TOKENS.get('ECOMMERCE_API_URL', ECOMMERCE_API_URL)
ECOMMERCE_API_SIGNING_KEY = AUTH_TOKENS.get('ECOMMERCE_API_SIGNING_KEY', ECOMMERCE_API_SIGNING_KEY)
ECOMMERCE_API_TIMEOUT = ENV_TOKENS.get('ECOMMERCE_API_TIMEOUT', ECOMMERCE_API_TIMEOUT)
COURSE_CATALOG_API_URL = ENV_TOKENS.get('COURSE_CATALOG_API_URL', COURSE_CATALOG_API_URL)
......
......@@ -218,7 +218,6 @@ BADGING_BACKEND = 'lms.djangoapps.badges.backends.tests.dummy_backend.DummyBacke
# Configure the LMS to use our stub eCommerce implementation
ECOMMERCE_API_URL = 'http://localhost:8043/api/v2/'
ECOMMERCE_API_SIGNING_KEY = 'ecommerce-key'
LMS_ROOT_URL = "http://localhost:8000"
DOC_LINK_BASE_URL = 'http://edx.readthedocs.io/projects/edx-guide-for-students'
......
......@@ -2831,7 +2831,6 @@ ACCOUNT_VISIBILITY_CONFIGURATION = {
# E-Commerce API Configuration
ECOMMERCE_PUBLIC_URL_ROOT = None
ECOMMERCE_API_URL = None
ECOMMERCE_API_SIGNING_KEY = None
ECOMMERCE_API_TIMEOUT = 5
ECOMMERCE_SERVICE_WORKER_USERNAME = 'ecommerce_worker'
ENTERPRISE_SERVICE_WORKER_USERNAME = 'enterprise_worker'
......
......@@ -588,3 +588,5 @@ COMPREHENSIVE_THEME_DIRS = [REPO_ROOT / "themes", REPO_ROOT / "common/test"]
COMPREHENSIVE_THEME_LOCALE_PATHS = [REPO_ROOT / "themes/conf/locale", ]
LMS_ROOT_URL = "http://localhost:8000"
ECOMMERCE_API_URL = 'https://ecommerce.example.com/api/v2/'
......@@ -4,13 +4,14 @@ from edx_rest_api_client.client import EdxRestApiClient
from eventtracking import tracker
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.lib.token_utils import JwtBuilder
ECOMMERCE_DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
ECOMMERCE_DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
def create_tracking_context(user):
""" Assembles attributes from user and request objects to be sent along
in ecommerce api calls for tracking purposes. """
in E-Commerce API calls for tracking purposes. """
context_tracker = tracker.get_tracker().resolve_context()
return {
......@@ -22,27 +23,19 @@ def create_tracking_context(user):
def is_commerce_service_configured():
"""
Return a Boolean indicating whether or not configuration is present to use
the external commerce service.
Return a Boolean indicating whether or not configuration is present to use the external commerce service.
"""
ecommerce_api_url = configuration_helpers.get_value("ECOMMERCE_API_URL", settings.ECOMMERCE_API_URL)
ecommerce_api_signing_key = configuration_helpers.get_value(
"ECOMMERCE_API_SIGNING_KEY", settings.ECOMMERCE_API_SIGNING_KEY,
)
return bool(ecommerce_api_url and ecommerce_api_signing_key)
ecommerce_api_url = configuration_helpers.get_value('ECOMMERCE_API_URL', settings.ECOMMERCE_API_URL)
return bool(ecommerce_api_url)
def ecommerce_api_client(user, session=None):
def ecommerce_api_client(user, session=None, token_expiration=None):
""" Returns an E-Commerce API client setup with authentication for the specified user. """
jwt_auth = configuration_helpers.get_value("JWT_AUTH", settings.JWT_AUTH)
claims = {'tracking_context': create_tracking_context(user)}
jwt = JwtBuilder(user).build_token(['email', 'profile'], expires_in=token_expiration, additional_claims=claims)
return EdxRestApiClient(
configuration_helpers.get_value("ECOMMERCE_API_URL", settings.ECOMMERCE_API_URL),
configuration_helpers.get_value("ECOMMERCE_API_SIGNING_KEY", settings.ECOMMERCE_API_SIGNING_KEY),
user.username,
user.profile.name if hasattr(user, 'profile') else None,
user.email,
tracking_context=create_tracking_context(user),
issuer=jwt_auth['JWT_ISSUER'],
expires_in=jwt_auth['JWT_EXPIRATION'],
configuration_helpers.get_value('ECOMMERCE_API_URL', settings.ECOMMERCE_API_URL),
jwt=jwt,
session=session
)
......@@ -11,7 +11,7 @@ from django.test.utils import override_settings
from django.db import connection
from nose.plugins.attrib import attr
import httpretty
from lms.djangoapps.commerce.tests import TEST_API_SIGNING_KEY, TEST_API_URL
from lms.djangoapps.commerce.tests import TEST_API_URL
import mock
import pytz
from opaque_keys.edx.keys import CourseKey
......@@ -575,7 +575,6 @@ class CreditRequirementApiTests(CreditApiTestBase):
@httpretty.activate
@override_settings(
ECOMMERCE_API_URL=TEST_API_URL,
ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY,
ECOMMERCE_SERVICE_WORKER_USERNAME=TEST_ECOMMERCE_WORKER
)
def test_satisfy_all_requirements(self):
......@@ -622,7 +621,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
self.assertFalse(api.is_user_eligible_for_credit(user.username, self.course_key))
# Satisfy the other requirement
with self.assertNumQueries(21):
with self.assertNumQueries(25):
api.set_credit_requirement_status(
user,
self.course_key,
......@@ -676,7 +675,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
# Delete the eligibility entries and satisfy the user's eligibility
# requirement again to trigger eligibility notification
CreditEligibility.objects.all().delete()
with self.assertNumQueries(16):
with self.assertNumQueries(17):
api.set_credit_requirement_status(
user,
self.course_key,
......@@ -1167,7 +1166,6 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase):
@skip_unless_lms
@override_settings(
ECOMMERCE_API_URL=TEST_API_URL,
ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY,
ECOMMERCE_SERVICE_WORKER_USERNAME=TEST_ECOMMERCE_WORKER
)
@ddt.ddt
......
......@@ -19,7 +19,6 @@ from student.tests.factories import UserFactory
UTILITY_MODULE = 'openedx.core.lib.edx_api_utils'
TEST_API_URL = 'http://www-internal.example.com/api'
TEST_API_SIGNING_KEY = 'edx'
@skip_unless_lms
......@@ -200,8 +199,7 @@ class TestGetEdxApiData(ProgramsApiConfigMixin, CacheIsolationTestCase):
self.assertTrue(mock_exception.called)
self.assertEqual(actual, [])
@override_settings(JWT_AUTH={'JWT_ISSUER': 'http://example.com/oauth', 'JWT_EXPIRATION': 30},
ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY, ECOMMERCE_API_URL=TEST_API_URL)
@override_settings(ECOMMERCE_API_URL=TEST_API_URL)
def test_client_passed(self):
""" Verify that when API client is passed edx_rest_api_client is not
used.
......
......@@ -33,17 +33,22 @@ class JwtBuilder(object):
self.secret = secret
self.jwt_auth = configuration_helpers.get_value('JWT_AUTH', settings.JWT_AUTH)
def build_token(self, scopes, expires_in, aud=None):
def build_token(self, scopes, expires_in=None, aud=None, additional_claims=None):
"""Returns a JWT access token.
Arguments:
scopes (list): Scopes controlling which optional claims are included in the token.
expires_in (int): Time to token expiry, specified in seconds.
Keyword Arguments:
expires_in (int): Time to token expiry, specified in seconds.
aud (string): Overrides configured JWT audience claim.
additional_claims (dict): Additional claims to include in the token.
Returns:
str: Encoded JWT
"""
now = int(time())
expires_in = expires_in or self.jwt_auth['JWT_EXPIRATION']
payload = {
'aud': aud if aud else self.jwt_auth['JWT_AUDIENCE'],
'exp': now + expires_in,
......@@ -54,6 +59,9 @@ class JwtBuilder(object):
'sub': anonymous_id_for_user(self.user, None),
}
if additional_claims:
payload.update(additional_claims)
for scope in scopes:
handler = self.claim_handlers.get(scope)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment