Ejemplo n.º 1
0
def fetch_journal_bundle(site, journal_bundle_uuid):
    """
    Retrieve journal bundle for given uuid.
    Retrieve it from cache if present, otherwise send GET request to journal bundle
        discovery api and store in cache.

    Args:
        site (Site): site for current request
        journal_bundle_uuid (str): uuid for desired journal bundle

    Returns:
        (dict): contains dict of journal_bundle attributes

    Raises:
        ConnectionError: raised if ecommerce is unable to connect to enterprise api server.
        SlumberBaseException: raised if API response contains http error status like 4xx, 5xx etc...
        Timeout: request is raised if API is taking too long to respond
    """

    api_resource = 'journal_bundle'
    cache_key = get_cache_key(site_domain=site.domain,
                              resource=api_resource,
                              journal_bundle_uuid=journal_bundle_uuid)

    journal_bundle_cached_response = TieredCache.get_cached_response(cache_key)
    if journal_bundle_cached_response.is_hit:
        return journal_bundle_cached_response.value

    client = site.siteconfiguration.journal_discovery_api_client
    journal_bundle = client.journal_bundles(journal_bundle_uuid).get()
    TieredCache.set_all_tiers(cache_key, journal_bundle,
                              JOURNAL_BUNDLE_CACHE_TIMEOUT)

    return journal_bundle
Ejemplo n.º 2
0
    def test_get_course_run_info_from_catalog(self, course_run):
        """ Check to see if course info gets cached """
        self.mock_access_token_response()
        if course_run:
            course = CourseFactory()
            product = course.create_or_update_seat(
                'verified', None, 100, self.site.siteconfiguration.partner)
            key = CourseKey.from_string(product.attr.course_key)
            self.mock_course_run_detail_endpoint(
                course,
                discovery_api_url=self.site_configuration.discovery_api_url)
        else:
            product = create_or_update_course_entitlement(
                'verified', 100, self.partner, 'foo-bar',
                'Foo Bar Entitlement')
            key = product.attr.UUID
            self.mock_course_detail_endpoint(
                product,
                discovery_api_url=self.site_configuration.discovery_api_url)

        cache_key = 'courses_api_detail_{}{}'.format(
            key, self.site.siteconfiguration.partner.short_code)
        cache_key = hashlib.md5(cache_key).hexdigest()
        course_cached_response = TieredCache.get_cached_response(cache_key)
        self.assertTrue(course_cached_response.is_miss)

        response = get_course_info_from_catalog(self.request.site, product)

        if course_run:
            self.assertEqual(response['title'], course.name)
        else:
            self.assertEqual(response['title'], product.title)

        course_cached_response = TieredCache.get_cached_response(cache_key)
        self.assertEqual(course_cached_response.value, response)
Ejemplo n.º 3
0
 def process_request(self, request):
     """
     Stores whether or not FORCE_DJANGO_CACHE_MISS_KEY was supplied in the
     request. Also, clears the request cache.
     """
     RequestCache.clear()
     TieredCache._get_and_set_force_cache_miss(request)  # pylint: disable=protected-access
Ejemplo n.º 4
0
    def catalog_contains_product(self, product):
        """
        Retrieve the results from using the catalog contains endpoint for
        catalog service for the catalog id contained in field "course_catalog".
        """
        request = get_current_request()
        partner_code = request.site.siteconfiguration.partner.short_code
        cache_key = get_cache_key(site_domain=request.site.domain,
                                  partner_code=partner_code,
                                  resource='catalogs.contains',
                                  course_id=product.course_id,
                                  catalog_id=self.course_catalog)
        cached_response = TieredCache.get_cached_response(cache_key)
        if cached_response.is_hit:
            return cached_response.value

        discovery_api_client = request.site.siteconfiguration.discovery_api_client
        try:
            # GET: /api/v1/catalogs/{catalog_id}/contains?course_run_id={course_run_ids}
            response = discovery_api_client.catalogs(
                self.course_catalog).contains.get(
                    course_run_id=product.course_id)

            TieredCache.set_all_tiers(cache_key, response,
                                      settings.COURSES_API_CACHE_TIMEOUT)
            return response
        except (ConnectionError, SlumberBaseException, Timeout):
            raise Exception(
                'Unable to connect to Discovery Service for catalog contains endpoint.'
            )
Ejemplo n.º 5
0
    def access_token(self):
        """ Returns an access token for this site's service user.

        The access token is retrieved using the current site's OAuth credentials and the client credentials grant.
        The token is cached for the lifetime of the token, as specified by the OAuth provider's response. The token
        type is JWT.

        Returns:
            str: JWT access token
        """
        key = 'siteconfiguration_access_token_{}'.format(self.id)
        access_token_cached_response = TieredCache.get_cached_response(key)
        if access_token_cached_response.is_hit:
            return access_token_cached_response.value

        url = '{root}/access_token'.format(root=self.oauth2_provider_url)
        access_token, expiration_datetime = EdxRestApiClient.get_oauth_access_token(
            url,
            self.oauth_settings['SOCIAL_AUTH_EDX_OIDC_KEY'],  # pylint: disable=unsubscriptable-object
            self.oauth_settings['SOCIAL_AUTH_EDX_OIDC_SECRET'],  # pylint: disable=unsubscriptable-object
            token_type='jwt')

        expires = (expiration_datetime - datetime.datetime.utcnow()).seconds
        TieredCache.set_all_tiers(key, access_token, expires)
        return access_token
Ejemplo n.º 6
0
    def get_credit_providers(self):
        """
        Retrieve all credit providers from LMS.

        Results will be sorted alphabetically by display name.
        """
        key = 'credit_providers'
        credit_providers_cache_response = TieredCache.get_cached_response(key)
        if credit_providers_cache_response.is_hit:
            return credit_providers_cache_response.value

        try:
            credit_api = EdxRestApiClient(
                get_lms_url('/api/credit/v1/'),
                oauth_access_token=self.request.user.access_token)
            credit_providers = credit_api.providers.get()
            credit_providers.sort(
                key=lambda provider: provider['display_name'])

            # Update the cache
            TieredCache.set_all_tiers(key, credit_providers,
                                      settings.CREDIT_PROVIDER_CACHE_TIMEOUT)
        except (SlumberBaseException, Timeout):
            logger.exception('Failed to retrieve credit providers!')
            credit_providers = []
        return credit_providers
Ejemplo n.º 7
0
    def get_program(self, uuid):
        """
        Retrieve the details for a single program.

        Args:
            uuid (str|uuid): Program UUID.

        Returns:
            dict
        """
        program_uuid = str(uuid)
        cache_key = '{site_domain}-program-{uuid}'.format(
            site_domain=self.site_domain, uuid=program_uuid)

        program_cached_response = TieredCache.get_cached_response(cache_key)

        if program_cached_response.is_hit:  # pragma: no cover
            logger.debug('Program [%s] was found in the cache.', program_uuid)
            return program_cached_response.value

        logging.info('Retrieving details of of program [%s]...', program_uuid)
        program = self.client.programs(program_uuid).get()

        TieredCache.set_all_tiers(cache_key, program, self.cache_ttl)
        logging.info('Program [%s] was successfully retrieved and cached.',
                     program_uuid)
        return program
Ejemplo n.º 8
0
    def is_entitlement_expired(entitlement_uuid, site):
        """
        Checks to see if a given entitlement is expired.

        Args:
            entitlement_uuid: UUID
            site: (Site)

        Returns:
            bool: True if the entitlement is expired

        """
        entitlement_api_client = EdxRestApiClient(get_lms_entitlement_api_url(),
                                                  jwt=site.siteconfiguration.access_token)
        partner_short_code = site.siteconfiguration.partner.short_code
        key = 'course_entitlement_detail_{}{}'.format(entitlement_uuid, partner_short_code)
        entitlement_cached_response = TieredCache.get_cached_response(key)
        if entitlement_cached_response.is_hit:
            entitlement = entitlement_cached_response.value
        else:
            logger.debug('Trying to get entitlement {%s}', entitlement_uuid)
            entitlement = entitlement_api_client.entitlements(entitlement_uuid).get()
            TieredCache.set_all_tiers(key, entitlement, settings.COURSES_API_CACHE_TIMEOUT)

        expired = entitlement.get('expired_at')
        logger.debug('Entitlement {%s} expired = {%s}', entitlement_uuid, expired)

        return expired
Ejemplo n.º 9
0
    def test_get_course_catalogs_for_single_catalog_with_id(self):
        """
        Verify that method "get_course_catalogs" returns proper response for a
        single catalog by its id.
        """
        self.mock_access_token_response()
        self.mock_catalog_detail_endpoint(
            self.site_configuration.discovery_api_url)

        catalog_id = 1
        cache_key = '{}.catalog.api.data.{}'.format(self.request.site.domain,
                                                    catalog_id)
        cache_key = hashlib.md5(cache_key).hexdigest()
        course_catalogs_cached_response = TieredCache.get_cached_response(
            cache_key)
        self.assertTrue(course_catalogs_cached_response.is_miss)

        response = get_course_catalogs(self.request.site, catalog_id)
        self.assertEqual(response['name'], 'All Courses')

        course_cached_response = TieredCache.get_cached_response(cache_key)
        self.assertEqual(course_cached_response.value, response)

        # Verify the API was actually hit (not the cache)
        self._assert_num_requests(2)
Ejemplo n.º 10
0
 def test_set_all_tiers(self, mock_cache_set):
     mock_cache_set.return_value = EXPECTED_VALUE
     TieredCache.set_all_tiers(TEST_KEY, EXPECTED_VALUE,
                               TEST_DJANGO_TIMEOUT_CACHE)
     mock_cache_set.assert_called_with(TEST_KEY, EXPECTED_VALUE,
                                       TEST_DJANGO_TIMEOUT_CACHE)
     self.assertEqual(
         RequestCache.get_cached_response(TEST_KEY).value, EXPECTED_VALUE)
Ejemplo n.º 11
0
def fetch_course_catalog(site, catalog_id):
    """
    Fetch course catalog for the given catalog id.

    This method will fetch catalog for given catalog id, if there is no catalog with the given
    catalog id, method will return `None`.

    Arguments:
        site (Site): Instance of the current site.
        catalog_id (int): An integer specifying the primary key value of catalog to fetch.

    Example:
        >>> fetch_course_catalog(site, catalog_id=1)
        {
            "id": 1,
            "name": "All Courses",
            "query": "*:*",
            ...
        }
    Returns:
        (dict): A dictionary containing key/value pairs corresponding to catalog attribute/values.

    Raises:
        ConnectionError: requests exception "ConnectionError", raised if if ecommerce is unable to connect
            to enterprise api server.
        SlumberBaseException: base slumber exception "SlumberBaseException", raised if API response contains
            http error status like 4xx, 5xx etc.
        Timeout: requests exception "Timeout", raised if enterprise API is taking too long for returning
            a response. This exception is raised for both connection timeout and read timeout.

    """
    api_resource = 'catalogs'

    cache_key = get_cache_key(
        site_domain=site.domain,
        resource=api_resource,
        catalog_id=catalog_id,
    )

    cached_response = TieredCache.get_cached_response(cache_key)
    if cached_response.is_hit:
        return cached_response.value

    api = site.siteconfiguration.discovery_api_client
    endpoint = getattr(api, api_resource)

    try:
        response = endpoint(catalog_id).get()
    except HttpNotFoundError:
        logger.exception("Catalog '%s' not found.", catalog_id)
        raise

    TieredCache.set_all_tiers(cache_key, response, settings.COURSES_API_CACHE_TIMEOUT)
    return response
Ejemplo n.º 12
0
def invalidate_processor_cache(*_args, **kwargs):
    """
    When Waffle switches for payment processors are toggled, the
    payment processor list view cache must be invalidated.
    """
    switch = kwargs['instance']
    parts = switch.name.split(settings.PAYMENT_PROCESSOR_SWITCH_PREFIX)
    if len(parts) == 2:
        processor = parts[1]
        logger.info('Switched payment processor [%s] %s.', processor, 'on' if switch.active else 'off')
        TieredCache.delete_all_tiers(PAYMENT_PROCESSOR_CACHE_KEY)
        logger.info('Invalidated payment processor cache after toggling [%s].', switch.name)
Ejemplo n.º 13
0
def fetch_enterprise_learner_entitlements(site, learner_id):
    """
    Fetch enterprise learner entitlements along-with data sharing consent requirement.

    Arguments:
        site (Site): site instance.
        learner_id (int): Primary key identifier for the enterprise learner.

    Example:
        >>> from django.contrib.sites.shortcuts import get_current_site
        >>> site  = get_current_site()
        >>> fetch_enterprise_learner_entitlements(site, 1)
        [
            {
                "requires_consent": False,
                "entitlement_id": 1
            },
        ]

    Returns:
         (list): Containing dicts of the following structure
            {
                "requires_consent": True,
                "entitlement_id": 1
            }

    Raises:
        ConnectionError: requests exception "ConnectionError", raised if if ecommerce is unable to connect
            to enterprise api server.
        SlumberBaseException: base slumber exception "SlumberBaseException", raised if API response contains
            http error status like 4xx, 5xx etc.
        Timeout: requests exception "Timeout", raised if enterprise API is taking too long for returning
            a response. This exception is raised for both connection timeout and read timeout.
    """
    resource_url = 'enterprise-learner/{learner_id}/entitlements'.format(
        learner_id=learner_id)
    cache_key = get_cache_key(
        site_domain=site.domain,
        partner_code=site.siteconfiguration.partner.short_code,
        resource=resource_url,
        learner_id=learner_id)

    entitlements_cached_response = TieredCache.get_cached_response(cache_key)
    if entitlements_cached_response.is_hit:
        return entitlements_cached_response.value

    api = site.siteconfiguration.enterprise_api_client
    entitlements = getattr(api, resource_url).get()

    TieredCache.set_all_tiers(cache_key, entitlements,
                              settings.ENTERPRISE_API_CACHE_TIMEOUT)
    return entitlements
Ejemplo n.º 14
0
def catalog_contains_course_runs(site,
                                 course_run_ids,
                                 enterprise_customer_uuid,
                                 enterprise_customer_catalog_uuid=None):
    """
    Determine if course runs are associated with the EnterpriseCustomer.
    """
    query_params = {'course_run_ids': course_run_ids}
    api_resource_name = 'enterprise-customer'
    api_resource_id = enterprise_customer_uuid
    if enterprise_customer_catalog_uuid:
        api_resource_name = 'enterprise_catalogs'
        api_resource_id = enterprise_customer_catalog_uuid

    cache_key = get_cache_key(
        site_domain=site.domain,
        resource='{resource}-{resource_id}-contains_content_items'.format(
            resource=api_resource_name,
            resource_id=api_resource_id,
        ),
        query_params=urlencode(query_params, True))

    contains_content_cached_response = TieredCache.get_cached_response(
        cache_key)
    if contains_content_cached_response.is_hit:
        return contains_content_cached_response.value

    api = site.siteconfiguration.enterprise_api_client
    endpoint = getattr(api, api_resource_name)(api_resource_id)
    try:
        contains_content = endpoint.contains_content_items.get(
            **query_params)['contains_content_items']

        TieredCache.set_all_tiers(cache_key, contains_content,
                                  settings.ENTERPRISE_API_CACHE_TIMEOUT)
    except (ConnectionError, KeyError, SlumberHttpBaseException, Timeout):
        logger.exception(
            'Failed to check if course_runs [%s] exist in '
            'EnterpriseCustomerCatalog [%s]'
            'for EnterpriseCustomer [%s].',
            course_run_ids,
            enterprise_customer_catalog_uuid,
            enterprise_customer_uuid,
        )
        contains_content = False
    return contains_content
Ejemplo n.º 15
0
    def test_invalidate_processor_cache(self):
        """ Verify the payment processor cache is invalidated when payment processor switches are toggled. """
        user = self.create_user()
        self.client.login(username=user.username, password=self.password)

        # Make a call that triggers cache creation
        response = self.client.get(reverse('api:v2:payment:list_processors'))
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            TieredCache.get_cached_response(
                PAYMENT_PROCESSOR_CACHE_KEY).is_hit)

        # Toggle a switch to trigger cache deletion
        Switch.objects.get_or_create(
            name=settings.PAYMENT_PROCESSOR_SWITCH_PREFIX + 'dummy')
        self.assertTrue(
            TieredCache.get_cached_response(
                PAYMENT_PROCESSOR_CACHE_KEY).is_miss)
Ejemplo n.º 16
0
    def _assert_get_course_catalogs(self, catalog_name_list):
        """
        Helper method to validate the response from the method
        "get_course_catalogs".
        """
        cache_key = '{}.catalog.api.data'.format(self.request.site.domain)
        cache_key = hashlib.md5(cache_key).hexdigest()
        course_catalogs_cached_response = TieredCache.get_cached_response(
            cache_key)
        self.assertTrue(course_catalogs_cached_response.is_miss)

        response = get_course_catalogs(self.request.site)

        self.assertEqual(len(response), len(catalog_name_list))
        for catalog_index, catalog in enumerate(response):
            self.assertEqual(catalog['name'], catalog_name_list[catalog_index])

        course_cached_response = TieredCache.get_cached_response(cache_key)
        self.assertEqual(course_cached_response.value, response)
Ejemplo n.º 17
0
    def _get_lms_resource_for_user(self, basket, resource_name, endpoint):
        cache_key = get_cache_key(
            site_domain=basket.site.domain,
            resource=resource_name,
            username=basket.owner.username,
        )
        data_list_cached_response = TieredCache.get_cached_response(cache_key)
        if data_list_cached_response.is_hit:
            return data_list_cached_response.value

        user = basket.owner.username
        try:
            data_list = endpoint.get(user=user) or []
            TieredCache.set_all_tiers(cache_key, data_list,
                                      settings.LMS_API_CACHE_TIMEOUT)
        except (ConnectionError, SlumberBaseException, Timeout) as exc:
            logger.error('Failed to retrieve %s : %s', resource_name, str(exc))
            data_list = []
        return data_list
Ejemplo n.º 18
0
    def test_get_cached_response_django_cache_hit(self, mock_cache_get):
        mock_cache_get.return_value = EXPECTED_VALUE
        cached_response = TieredCache.get_cached_response(TEST_KEY)
        self.assertTrue(cached_response.is_hit)
        self.assertEqual(cached_response.value, EXPECTED_VALUE)

        cached_response = RequestCache.get_cached_response(TEST_KEY)
        self.assertTrue(
            cached_response.is_hit,
            'Django cache hit should cache value in request cache.')
Ejemplo n.º 19
0
    def is_verified(self, site):
        """
        Check if a user has verified his/her identity.
        Calls the LMS verification status API endpoint and returns the verification status information.
        The status information is stored in cache, if the user is verified, until the verification expires.

        Args:
            site (Site): The site object from which the LMS account API endpoint is created.

        Returns:
            True if the user is verified, false otherwise.
        """
        try:
            cache_key = 'verification_status_{username}'.format(
                username=self.username)
            cache_key = hashlib.md5(cache_key).hexdigest()
            verification_cached_response = TieredCache.get_cached_response(
                cache_key)
            if verification_cached_response.is_hit:
                return verification_cached_response.value

            api = EdxRestApiClient(
                site.siteconfiguration.build_lms_url('api/user/v1/'),
                oauth_access_token=self.access_token)
            response = api.accounts(self.username).verification_status().get()

            verification = response.get('is_verified', False)
            if verification:
                cache_timeout = int(
                    (parse(response.get('expiration_datetime')) -
                     now()).total_seconds())
                TieredCache.set_all_tiers(cache_key, verification,
                                          cache_timeout)
            return verification
        except HttpNotFoundError:
            log.debug('No verification data found for [%s]', self.username)
            return False
        except (ConnectionError, SlumberBaseException, Timeout):
            msg = 'Failed to retrieve verification status details for [{username}]'.format(
                username=self.username)
            log.warning(msg)
            return False
Ejemplo n.º 20
0
    def get_applicable_lines(self, offer, basket, range=None):  # pylint: disable=redefined-builtin
        applicable_range = range if range else self.range
        if applicable_range and applicable_range.catalog_query is not None:
            query = applicable_range.catalog_query
            applicable_lines = self._filter_for_paid_course_products(
                basket.all_lines(), applicable_range)
            site = basket.site
            partner_code = site.siteconfiguration.partner.short_code
            course_run_ids, course_uuids, applicable_lines = self._identify_uncached_product_identifiers(
                applicable_lines, site.domain, partner_code, query)
            if course_run_ids or course_uuids:
                # Hit Discovery Service to determine if remaining courses and runs are in the range.
                try:
                    response = site.siteconfiguration.discovery_api_client.catalog.query_contains.get(
                        course_run_ids=','.join(
                            [metadata['id'] for metadata in course_run_ids]),
                        course_uuids=','.join(
                            [metadata['id'] for metadata in course_uuids]),
                        query=query,
                        partner=partner_code)
                except Exception as err:  # pylint: disable=bare-except
                    logger.warning(
                        '%s raised while attempting to contact Discovery Service for offer catalog_range data.',
                        err)
                    raise Exception(
                        'Failed to contact Discovery Service to retrieve offer catalog_range data.'
                    )

                # Cache range-state individually for each course or run identifier and remove lines not in the range.
                for metadata in course_run_ids + course_uuids:
                    in_range = response[str(metadata['id'])]
                    TieredCache.set_all_tiers(
                        metadata['cache_key'], in_range,
                        settings.COURSES_API_CACHE_TIMEOUT)
                    if not in_range:
                        applicable_lines.remove(metadata['line'])
            return [(line.product.stockrecords.first().price_excl_tax, line)
                    for line in applicable_lines]
        else:
            return super(Benefit, self).get_applicable_lines(offer,
                                                             basket,
                                                             range=range)  # pylint: disable=bad-super-call
Ejemplo n.º 21
0
    def test_get_cached_response_force_django_cache_miss(self, mock_cache_get):
        RequestCache.set(SHOULD_FORCE_CACHE_MISS_KEY, True)
        mock_cache_get.return_value = EXPECTED_VALUE
        cached_response = TieredCache.get_cached_response(TEST_KEY)
        self.assertTrue(cached_response.is_miss)

        cached_response = RequestCache.get_cached_response(TEST_KEY)
        self.assertTrue(
            cached_response.is_miss,
            'Forced Django cache miss should not cache value in request cache.'
        )
Ejemplo n.º 22
0
    def _assert_fetch_enterprise_learner_data(self):
        """
        Helper method to validate the response from the method
        "fetch_enterprise_learner_data".
        """
        cache_key = get_cache_key(site_domain=self.request.site.domain,
                                  partner_code=self.request.site.
                                  siteconfiguration.partner.short_code,
                                  resource='enterprise-learner',
                                  username=self.learner.username)

        enterprise_learner_cached_response = TieredCache.get_cached_response(
            cache_key)
        self.assertTrue(enterprise_learner_cached_response.is_miss)

        response = enterprise_api.fetch_enterprise_learner_data(
            self.request.site, self.learner)
        self.assertEqual(len(response['results']), 1)

        course_cached_response = TieredCache.get_cached_response(cache_key)
        self.assertEqual(course_cached_response.value, response)
Ejemplo n.º 23
0
def get_course_catalogs(site, resource_id=None):
    """
    Get details related to course catalogs from Discovery Service.

    Arguments:
        site (Site): Site object containing Site Configuration data
        resource_id (int or str): Identifies a specific resource to be retrieved

    Returns:
        dict: Course catalogs received from Discovery API

    Raises:
        ConnectionError: requests exception "ConnectionError"
        SlumberBaseException: slumber exception "SlumberBaseException"
        Timeout: requests exception "Timeout"

    """
    resource = 'catalogs'
    base_cache_key = '{}.catalog.api.data'.format(site.domain)

    cache_key = '{}.{}'.format(base_cache_key,
                               resource_id) if resource_id else base_cache_key
    cache_key = hashlib.md5(cache_key).hexdigest()

    cached_response = TieredCache.get_cached_response(cache_key)
    if cached_response.is_hit:
        return cached_response.value

    api = site.siteconfiguration.discovery_api_client
    endpoint = getattr(api, resource)
    response = endpoint(resource_id).get()

    if resource_id:
        results = response
    else:
        results = deprecated_traverse_pagination(response, endpoint)

    TieredCache.set_all_tiers(cache_key, results,
                              settings.COURSES_API_CACHE_TIMEOUT)
    return results
Ejemplo n.º 24
0
def is_course_in_enterprise_catalog(site, course_id, enterprise_catalog_id):
    """
    Verify that the provided course id exists in the site base list of course
    run keys from the provided enterprise course catalog.

    Arguments:
        course_id (str): The course ID.
        site: (django.contrib.sites.Site) site instance
        enterprise_catalog_id (Int): Course catalog id of enterprise

    Returns:
        Boolean

    """
    partner_code = site.siteconfiguration.partner.short_code
    cache_key = get_cache_key(site_domain=site.domain,
                              partner_code=partner_code,
                              resource='catalogs.contains',
                              course_id=course_id,
                              catalog_id=enterprise_catalog_id)
    cached_response = TieredCache.get_cached_response(cache_key)
    if cached_response.is_hit:
        response = cached_response.value
    else:
        try:
            response = site.siteconfiguration.discovery_api_client.catalogs(
                enterprise_catalog_id).contains.get(course_run_id=course_id)
            TieredCache.set_all_tiers(cache_key, response,
                                      settings.COURSES_API_CACHE_TIMEOUT)
        except (ConnectionError, SlumberBaseException, Timeout):
            logger.exception(
                'Unable to connect to Discovery Service for catalog contains endpoint.'
            )
            return False

    try:
        return response['courses'][course_id]
    except KeyError:
        return False
Ejemplo n.º 25
0
    def setUp(self):
        super(PaymentProcessorListViewTests, self).setUp()
        self.token = self.generate_jwt_token_header(self.create_user())
        self.toggle_payment_processor(DummyProcessor.NAME, True)
        self.toggle_payment_processor(AnotherDummyProcessor.NAME, True)

        site_config, __ = SiteConfiguration.objects.get_or_create(site__id=1)

        old_payment_processors = site_config.payment_processors
        site_config.payment_processors = ",".join(
            [DummyProcessor.NAME, AnotherDummyProcessor.NAME])
        site_config.save()

        def reset_site_config():
            """ Reset method - resets site_config to pre-test state """
            site_config.payment_processors = old_payment_processors
            site_config.save()

        self.addCleanup(reset_site_config)

        # Clear the view cache
        TieredCache.clear_all_tiers()
Ejemplo n.º 26
0
 def test_delete(self, mock_cache_delete):
     TieredCache.set_all_tiers(TEST_KEY, EXPECTED_VALUE)
     TieredCache.set_all_tiers(TEST_KEY_2, EXPECTED_VALUE)
     TieredCache.delete_all_tiers(TEST_KEY)
     self.assertTrue(RequestCache.get_cached_response(TEST_KEY).is_miss)
     self.assertEqual(
         RequestCache.get_cached_response(TEST_KEY_2).value, EXPECTED_VALUE)
     mock_cache_delete.assert_called_with(TEST_KEY)
Ejemplo n.º 27
0
    def test_cached_course(self):
        """ Verify that the course info is cached. """
        seat = self.create_seat(self.course, 50)
        basket = self.create_basket_and_add_product(seat)
        self.mock_access_token_response()
        self.assertEqual(basket.lines.count(), 1)
        self.mock_course_run_detail_endpoint(
            self.course,
            discovery_api_url=self.site_configuration.discovery_api_url)

        cache_key = 'courses_api_detail_{}{}'.format(
            self.course.id, self.site.siteconfiguration.partner.short_code)
        cache_key = hashlib.md5(cache_key).hexdigest()
        course_before_cached_response = TieredCache.get_cached_response(
            cache_key)
        self.assertTrue(course_before_cached_response.is_miss)

        response = self.client.get(self.path)
        self.assertEqual(response.status_code, 200)
        course_after_cached_response = TieredCache.get_cached_response(
            cache_key)
        self.assertEqual(course_after_cached_response.value['title'],
                         self.course.name)
Ejemplo n.º 28
0
def get_course_info_from_catalog(site, product):
    """ Get course or course_run information from Discovery Service and cache """
    if product.is_course_entitlement_product:
        key = product.attr.UUID
    else:
        key = CourseKey.from_string(product.attr.course_key)

    api = site.siteconfiguration.discovery_api_client
    partner_short_code = site.siteconfiguration.partner.short_code

    cache_key = 'courses_api_detail_{}{}'.format(key, partner_short_code)
    cache_key = hashlib.md5(cache_key).hexdigest()
    course_cached_response = TieredCache.get_cached_response(cache_key)
    if course_cached_response.is_hit:
        return course_cached_response.value

    if product.is_course_entitlement_product:
        course = api.courses(key).get()
    else:
        course = api.course_runs(key).get(partner=partner_short_code)

    TieredCache.set_all_tiers(cache_key, course,
                              settings.COURSES_API_CACHE_TIMEOUT)
    return course
Ejemplo n.º 29
0
def get_cached_voucher(code):
    """
    Returns a voucher from cache if one is stored to cache, if not the voucher
    is retrieved from database and stored to cache.

    Arguments:
        code (str): The code of a coupon voucher.

    Returns:
        voucher (Voucher): The Voucher for the passed code.

    Raises:
        Voucher.DoesNotExist: When no vouchers with provided code exist.
    """
    voucher_code = 'voucher_{code}'.format(code=code)
    cache_key = hashlib.md5(voucher_code).hexdigest()
    voucher_cached_response = TieredCache.get_cached_response(cache_key)
    if voucher_cached_response.is_hit:
        return voucher_cached_response.value

    voucher = Voucher.objects.get(code=code)

    TieredCache.set_all_tiers(cache_key, voucher, settings.VOUCHER_CACHE_TIMEOUT)
    return voucher
Ejemplo n.º 30
0
 def _identify_uncached_product_identifiers(self, lines, domain,
                                            partner_code, query):
     """
     Checks the cache to see if each line is in the catalog range specified by the given query
     and tracks identifiers for which discovery service data is still needed.
     """
     course_run_ids = []
     course_uuids = []
     applicable_lines = lines
     for line in applicable_lines:
         if line.product.is_seat_product:
             product_id = line.product.course.id
         else:  # All lines passed to this method should either have a seat or an entitlement product
             product_id = line.product.attr.UUID
         cache_key = get_cache_key(site_domain=domain,
                                   partner_code=partner_code,
                                   resource='catalog_query.contains',
                                   course_id=product_id,
                                   query=query)
         cached_response = TieredCache.get_cached_response(cache_key)
         if cached_response.is_miss:
             if line.product.is_seat_product:
                 course_run_ids.append({
                     'id': product_id,
                     'cache_key': cache_key,
                     'line': line
                 })
             else:
                 course_uuids.append({
                     'id': product_id,
                     'cache_key': cache_key,
                     'line': line
                 })
         elif cached_response.value is False:
             applicable_lines.remove(line)
     return course_run_ids, course_uuids, applicable_lines