예제 #1
0
def get_ecommerce_client(site_code=None):
    """
    Get client for fetching data from ecommerce API

    Returns:
        EdxRestApiClient object
    """
    ecommerce_api_root = get_configuration('ECOMMERCE_API_ROOT', site_code=site_code)
    signing_key = get_configuration('JWT_SECRET_KEY', site_code=site_code)
    issuer = get_configuration('JWT_ISSUER', site_code=site_code)
    service_username = get_configuration('ECOMMERCE_SERVICE_USERNAME', site_code=site_code)
    return EdxRestApiClient(ecommerce_api_root, signing_key=signing_key, issuer=issuer, username=service_username)
예제 #2
0
def create_video_pipeline_api_client(user, api_client_id, api_client_secret, api_url):
    """
    Returns an API client which can be used to make Video Pipeline API requests.

    Arguments:
        user(User): A requesting user.
        api_client_id(unicode): Video pipeline client id.
        api_client_secret(unicode): Video pipeline client secret.
        api_url(unicode): It is video pipeline's API URL.
    """
    jwt_token = create_jwt_for_user(user, secret=api_client_secret, aud=api_client_id)
    return EdxRestApiClient(api_url, jwt=jwt_token)
예제 #3
0
def create_catalog_api_client(user, site=None):
    """Returns an API client which can be used to make Catalog API requests."""
    scopes = ['email', 'profile']
    expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION
    jwt = JwtBuilder(user).build_token(scopes, expires_in)

    if site:
        url = site.configuration.get_value('COURSE_CATALOG_API_URL')
    else:
        url = CatalogIntegration.current().get_internal_api_url()

    return EdxRestApiClient(url, jwt=jwt)
예제 #4
0
    def enterprise_api_client(self):
        """
        Constructs a Slumber-based REST API client for the provided site.

        Example:
            site.siteconfiguration.enterprise_api_client.enterprise-learner(learner.username).get()

        Returns:
            EdxRestApiClient: The client to access the Enterprise service.

        """
        return EdxRestApiClient(self.enterprise_api_url, jwt=self.access_token)
예제 #5
0
 def _hubspot_endpoint(self, hubspot_object, api_url, method, body=None, **kwargs):
     """
     This function is responsible for all the calls of hubspot.
     """
     client = EdxRestApiClient('/'.join([HUBSPOT_API_BASE_URL, api_url]))
     if method == "GET":
         return getattr(client, hubspot_object).get(**kwargs)
     if method == "POST":
         return getattr(client, hubspot_object).post(**kwargs)
     if method == "PUT":
         return getattr(client, hubspot_object).put(body, **kwargs)
     raise ValueError("Unexpected method {}".format(method))
예제 #6
0
    def enterprise_catalog_api_client(self):
        """
        Returns a REST API client for the provided enterprise catalog service

        Example:
            site.siteconfiguration.enterprise_catalog_api_client.enterprise-catalog.get()

        Returns:
            EdxRestApiClient: The client to access the Enterprise Catalog service.

        """
        return EdxRestApiClient(self.enterprise_catalog_api_url, jwt=self.access_token)
예제 #7
0
    def __init__(self):
        jwt, __ = EdxRestApiClient.get_oauth_access_token(
            f'{OIDC_URL}/access_token',
            OIDC_KEY,
            OIDC_SECRET,
            token_type='jwt'
        )

        self.client = EdxRestApiClient(DISCOVERY_API_URL, jwt=jwt)

        self.deadline_empty_with_end = []
        self.deadline_empty_without_end = []
        self.deadline_after_end = []
예제 #8
0
 def __init__(self, user):
     """
     Initialize an authenticated Consent service API client by using the
     provided user.
     """
     jwt = create_jwt_for_user(user)
     url = configuration_helpers.get_value('ENTERPRISE_CONSENT_API_URL', settings.ENTERPRISE_CONSENT_API_URL)
     self.client = EdxRestApiClient(
         url,
         jwt=jwt,
         append_slash=False,
     )
     self.consent_endpoint = self.client.data_sharing_consent
예제 #9
0
def ecommerce_api_client(user):
    """ Returns an E-Commerce API client setup with authentication for the specified user. """
    jwt_auth = configuration_helpers.get_value("JWT_AUTH", settings.JWT_AUTH)
    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']
    )
예제 #10
0
 def __init__(self):
     """
     Initialize a consent service API client, authenticated using the Enterprise worker username.
     """
     self.user = User.objects.get(username=settings.ENTERPRISE_SERVICE_WORKER_USERNAME)
     jwt = JwtBuilder(self.user).build_token([])
     url = configuration_helpers.get_value('ENTERPRISE_CONSENT_API_URL', settings.ENTERPRISE_CONSENT_API_URL)
     self.client = EdxRestApiClient(
         url,
         jwt=jwt,
         append_slash=False,
     )
     self.consent_endpoint = self.client.data_sharing_consent
예제 #11
0
 def connect(self):
     """
     Connect to the REST API, authenticating with an access token retrieved with our client credentials.
     """
     access_token, expires_at = EdxRestApiClient.get_oauth_access_token(
         self.LMS_OAUTH_HOST + '/oauth2/access_token', self.client_id,
         self.client_secret, 'jwt')
     self.client = EdxRestApiClient(
         self.API_BASE_URL,
         append_slash=self.APPEND_SLASH,
         jwt=access_token,
     )
     self.expires_at = expires_at
예제 #12
0
def course_discovery_api_client(user):
    """
    Return a Course Discovery API client setup with authentication for the specified user.
    """
    if JwtBuilder is None:
        raise NotConnectedToOpenEdX(
            _("To get a Catalog API client, this package must be "
              "installed in an Open edX environment."))

    scopes = ['email', 'profile']
    expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION
    jwt = JwtBuilder(user).build_token(scopes, expires_in)
    return EdxRestApiClient(settings.COURSE_CATALOG_API_URL, jwt=jwt)
예제 #13
0
    def _get_basket(self, basket_id):
        if not basket_id:
            return None

        try:
            basket_id = int(basket_id)
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()
            # TODO: Remove as a part of REVMI-124 as this is a hacky solution
            # The problem is that orders are being created after payment processing, and the discount is not
            # saved in the database, so it needs to be calculated again in order to save the correct info to the
            # order. REVMI-124 will create the order before payment processing, when we have the discount context.
            if waffle.flag_is_active(self.request, DYNAMIC_DISCOUNT_FLAG) and basket.lines.count() == 1:  # pragma: no cover  pylint: disable=line-too-long
                discount_lms_url = get_lms_url('/api/discounts/')
                lms_discount_client = EdxRestApiClient(
                    discount_lms_url,
                    jwt=self.request.site.siteconfiguration.access_token)
                ck = basket.lines.first().product.course_id
                user_id = basket.owner.lms_user_id
                try:
                    response = lms_discount_client.user(user_id).course(
                        ck).get()
                    self.request.POST = self.request.POST.copy()
                    self.request.POST['discount_jwt'] = response.get('jwt')
                    logger.info(
                        """Received discount jwt from LMS with
                        url: [%s],
                        user_id: [%s],
                        course_id: [%s],
                        and basket_id: [%s]
                        returned [%s]""", discount_lms_url, str(user_id), ck,
                        basket.id, response)
                except (SlumberHttpBaseException,
                        requests.exceptions.Timeout) as error:
                    logger.warning(
                        """Failed to receive discount jwt from LMS with
                        url: [%s],
                        user_id: [%s],
                        course_id: [%s],
                        and basket_id: [%s]
                        returned [%s]""", discount_lms_url, str(user_id), ck,
                        basket.id,
                        vars(error.response)
                        if hasattr(error, 'response') else '')
            # End TODO
            Applicator().apply(basket, basket.owner, self.request)
            logger.info('Applicator applied, basket id: [%s]', basket.id)
            return basket
        except (ValueError, ObjectDoesNotExist) as error:
            logger.warning('Could not get basket--error: [%s]', str(error))
            return None
예제 #14
0
    def __init__(self, oauth_access_token_url, oauth_key, oauth_secret, api_url_root):
        try:
            self.access_token, expires = EdxRestApiClient.get_oauth_access_token(
                oauth_access_token_url,
                oauth_key,
                oauth_secret, token_type='jwt'
            )
        except Exception:
            logger.exception('No access token acquired through client_credential flow.')
            raise

        logger.info('Retrieved access token.')

        self.api_client = EdxRestApiClient(api_url_root, jwt=self.access_token)
def get_api_client(api_config, student):
    """
    Create and configure an API client for authenticated HTTP requests.

    Args:
        api_config: ProgramsApiConfig or CredentialsApiConfig object
        student: User object as whom to authenticate to the API

    Returns:
        EdxRestApiClient

    """
    id_token = get_id_token(student, api_config.OAUTH2_CLIENT_NAME)
    return EdxRestApiClient(api_config.internal_api_url, jwt=id_token)
예제 #16
0
    def journal_discovery_api_client(self):
        """
        Returns an Journal API client to access the Discovery service.

        Returns:
            EdxRestApiClient: The client to access the Journal API in the Discovery service.
        """
        split_url = urlsplit(self.discovery_api_url)
        journal_discovery_url = urlunsplit([
            split_url.scheme, split_url.netloc, JOURNAL_DISCOVERY_API_PATH,
            split_url.query, split_url.fragment
        ])

        return EdxRestApiClient(journal_discovery_url, jwt=self.access_token)
예제 #17
0
    def _publish_creditcourse(self, course_id, access_token):
        """Creates or updates a CreditCourse object on the LMS."""

        api = EdxRestApiClient(
            get_lms_url('api/credit/v1/'),
            oauth_access_token=access_token,
            timeout=self.timeout
        )

        data = {
            'course_key': course_id,
            'enabled': True
        }

        api.courses(course_id).put(data)
예제 #18
0
    def api_client(self):
        """
        Returns an authenticated API client ready to call the API from which data is loaded.

        Returns:
            EdxRestApiClient
        """
        kwargs = {}

        if self.token_type == 'jwt':
            kwargs['jwt'] = self.access_token
        else:
            kwargs['oauth_access_token'] = self.access_token

        return EdxRestApiClient(self.api_url, **kwargs)
예제 #19
0
def ecommerce_api_client(user, session=None):
    """ Returns an E-Commerce API client setup with authentication for the specified user. """
    claims = {'tracking_context': create_tracking_context(user)}
    scopes = [
        'user_id',
        'email',
        'profile'
    ]
    jwt = create_jwt_for_user(user, additional_claims=claims, scopes=scopes)

    return EdxRestApiClient(
        configuration_helpers.get_value('ECOMMERCE_API_URL', settings.ECOMMERCE_API_URL),
        jwt=jwt,
        session=session
    )
    def _get_courses_enrollment_info(self):
        """
        Retrieve the enrollment information for all the courses.

        Returns:
            Dictionary representing the key-value pair (course_key, enrollment_end) of course.
        """
        def _parse_response(api_response):
            response_data = api_response.get('results', [])

            # Map course_id with enrollment end date.
            courses_enrollment = dict(
                (course_info['course_id'], course_info['enrollment_end'])
                for course_info in response_data
            )
            return courses_enrollment, api_response['pagination'].get('next', None)

        querystring = {'page_size': 50}
        api = EdxRestApiClient(get_lms_url('api/courses/v1/'))
        course_enrollments = {}

        page = 0
        throttling_attempts = 0
        next_page = True
        while next_page:
            page += 1
            querystring['page'] = page
            try:
                response = api.courses().get(**querystring)
                throttling_attempts = 0
            except HttpClientError as exc:
                # this is a known limitation; If we get HTTP429, we need to pause execution for a few seconds
                # before re-requesting the data. raise any other errors
                if exc.response.status_code == 429 and throttling_attempts < self.max_tries:
                    logger.warning(
                        'API calls are being rate-limited. Waiting for [%d] seconds before retrying...',
                        self.pause_time
                    )
                    time.sleep(self.pause_time)
                    page -= 1
                    throttling_attempts += 1
                    logger.info('Retrying [%d]...', throttling_attempts)
                    continue
                else:
                    raise
            enrollment_info, next_page = _parse_response(response)
            course_enrollments.update(enrollment_info)
        return course_enrollments
예제 #21
0
def get_programs(user):
    """Given a user, get programs from the Programs service.

    Returned value is cached depending on user permissions. Staff users making requests
    against Programs will receive unpublished programs, while regular users will only receive
    published programs.

    Arguments:
        user (User): The user to authenticate as when requesting programs.

    Returns:
        list of dict, representing programs returned by the Programs service.
    """
    programs_config = ProgramsApiConfig.current()
    no_programs = []

    # Bypass caching for staff users, who may be creating Programs and want to see them displayed immediately.
    use_cache = programs_config.is_cache_enabled and not user.is_staff

    if not programs_config.enabled:
        log.warning('Programs configuration is disabled.')
        return no_programs

    if use_cache:
        cached = cache.get(programs_config.CACHE_KEY)
        if cached is not None:
            return cached

    try:
        jwt = get_id_token(user, programs_config.OAUTH2_CLIENT_NAME)
        api = EdxRestApiClient(programs_config.internal_api_url, jwt=jwt)
    except Exception:  # pylint: disable=broad-except
        log.exception('Failed to initialize the Programs API client.')
        return no_programs

    try:
        response = api.programs.get()
    except Exception:  # pylint: disable=broad-except
        log.exception('Failed to retrieve programs from the Programs API.')
        return no_programs

    results = response.get('results', no_programs)

    if use_cache:
        cache.set(programs_config.CACHE_KEY, results,
                  programs_config.cache_ttl)

    return results
def create_video_pipeline_api_client(user, api_client_id, api_client_secret, api_url):
    """
    Returns an API client which can be used to make Video Pipeline API requests.

    Arguments:
        user(User): A requesting user.
        api_client_id(unicode): Video pipeline client id.
        api_client_secret(unicode): Video pipeline client secret.
        api_url(unicode): It is video pipeline's API URL.
    """
    jwt_token = JwtBuilder(user, secret=api_client_secret).build_token(
        scopes=[],
        expires_in=settings.OAUTH_ID_TOKEN_EXPIRATION,
        aud=api_client_id
    )
    return EdxRestApiClient(api_url, jwt=jwt_token)
예제 #23
0
def get_api_client(api_config, user):
    """
    Create and configure an API client for authenticated HTTP requests.

    Args:
        api_config: CredentialsApiConfig object
        user: User object as whom to authenticate to the API

    Returns:
        EdxRestApiClient

    """
    scopes = ['email', 'profile']
    expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION
    jwt = JwtBuilder(user).build_token(scopes, expires_in)
    return EdxRestApiClient(api_config.internal_api_url, jwt=jwt)
예제 #24
0
    def connect(self):
        """
        Connect to the REST API, authenticating with a JWT for the current user.
        """
        if JwtBuilder is None:
            raise NotConnectedToOpenEdX(
                "This package must be installed in an OpenEdX environment.")

        now = int(time())
        jwt = JwtBuilder.create_jwt_for_user(self.user)
        self.client = EdxRestApiClient(
            self.API_BASE_URL,
            append_slash=self.APPEND_SLASH,
            jwt=jwt,
        )
        self.expires_at = now + self.expires_in
예제 #25
0
def get_credentials_api_client(user, org=None):
    """
    Returns an authenticated Credentials API client.

    Arguments:
        user (User): The user to authenticate as when requesting credentials.
        org (str): Optional organization to look up the site config for, rather than the current request

    """
    jwt = create_jwt_for_user(user)

    if org is None:
        url = CredentialsApiConfig.current().internal_api_url  # by current request
    else:
        url = CredentialsApiConfig.get_internal_api_url_for_org(org)  # by org
    return EdxRestApiClient(url, jwt=jwt)
예제 #26
0
    def refresh(cls, course_id, access_token):
        """
        Refresh the course data from the raw data sources.

        Args:
            course_id (str): Course ID
            access_token (str): OAuth access token

        Returns:
            Course
        """
        client = EdxRestApiClient(settings.ECOMMERCE_API_URL,
                                  oauth_access_token=access_token)
        body = client.courses(course_id).get(include_products=True)
        course = Course(course_id, body)
        course.save()
        return course
예제 #27
0
    def __init__(self):
        """
        Initialize an authenticated Journals service API client by using the
        provided user.
        """
        try:
            self.user = self.get_journals_worker()
        except ObjectDoesNotExist:
            error = 'Unable to retrieve {} service user'.format(
                JOURNAL_WORKER_USERNAME)
            LOGGER.error(error)
            raise ValueError(error)

        jwt = JwtBuilder(self.user).build_token(['email', 'profile'], 16000)
        self.client = EdxRestApiClient(configuration_helpers.get_value(
            'JOURNALS_API_URL', settings.JOURNALS_API_URL),
                                       jwt=jwt)
예제 #28
0
 def __init__(self):
     """
     Create an LMS API client, authenticated with the OAuth2 token for client in settings
     """
     # session = Session()
     # # session.headers = {"X-Edx-Api-Key": settings.OPENEDX_EDX_API_KEY}
     token = EdxRestApiClient.get_oauth_access_token(
         url="{}{}".format(settings.OPENEDX_PLATFORM_URI,
                           constants.OPENEDX_OAUTH2_TOKEN_URL),
         client_id=settings.OPENEDX_OAUTH2_CLIENT_ID,
         client_secret=settings.OPENEDX_OAUTH2_CLIENT_SECRET)
     self.cache = False
     if settings.LMS_API_USE_MEMCACHED:
         self.cache = memcache.Client([settings.MEMCACHED_ADDRESS], debug=0)
     self.client = EdxRestApiClient(self.API_BASE_URL,
                                    append_slash=self.APPEND_SLASH,
                                    username="******",
                                    oauth_access_token=token[0])
예제 #29
0
파일: utils.py 프로젝트: uzairr/ecommerce
def get_credit_provider_details(access_token, credit_provider_id, site_configuration):
    """ Returns the credit provider details from LMS.

    Args:
        access_token (str): JWT access token
        credit_provider_id (str): Identifier for the provider
        site_configuration (SiteConfiguration): Ecommerce Site Configuration

    Returns: dict
    """
    try:
        return EdxRestApiClient(
            site_configuration.build_lms_url('api/credit/v1/'),
            oauth_access_token=access_token
        ).providers(credit_provider_id).get()
    except (ConnectionError, SlumberHttpBaseException, Timeout):
        logger.exception('Failed to retrieve credit provider details for provider [%s].', credit_provider_id)
        return None
예제 #30
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.

        Raises:
            ConnectionError, SlumberBaseException and Timeout for failures in
            establishing a connection with the LMS verification status API endpoint.
        """
        try:
            cache_key = 'verification_status_{username}'.format(
                username=self.username)
            cache_key = hashlib.md5(cache_key).hexdigest()
            verification = cache.get(cache_key)
            if not verification:
                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())
                    cache.set(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.exception(msg)
            raise VerificationStatusError(msg)