Пример #1
0
    def test_cannot_make_credit_request_after_response(self, status):
        # Create the first request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Provider updates the status
        api.update_credit_request_status(request["parameters"]["request_uuid"], self.PROVIDER_ID, status)

        # Attempting a second request raises an exception
        with self.assertRaises(RequestAlreadyCompleted):
            api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])
Пример #2
0
    def test_cannot_make_credit_request_after_response(self, status):
        # Create the first request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Provider updates the status
        api.update_credit_request_status(request["parameters"]["request_uuid"], self.PROVIDER_ID, status)

        # Attempting a second request raises an exception
        with self.assertRaises(RequestAlreadyCompleted):
            api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])
Пример #3
0
    def test_user_is_not_eligible(self, requirement_status):
        # Simulate a user who is not eligible for credit
        CreditEligibility.objects.all().delete()
        status = CreditRequirementStatus.objects.get(username=self.USER_INFO['username'])
        status.status = requirement_status
        status.reason = {}
        status.save()

        with self.assertRaises(UserIsNotEligible):
            api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])
Пример #4
0
    def test_user_is_not_eligible(self, status):
        # Simulate a user who is not eligible for credit
        CreditEligibility.objects.all().delete()
        status = CreditRequirementStatus.objects.get(username=self.USER_INFO['username'])
        status.status = status
        status.reason = {}
        status.save()

        with self.assertRaises(UserIsNotEligible):
            api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])
Пример #5
0
    def test_create_credit_request_for_second_course(self):
        # Create the first request
        first_request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Create a request for a second course
        other_course_key = CourseKey.from_string("edX/other/2015")
        self._configure_credit(course_key=other_course_key)
        second_request = api.create_credit_request(other_course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Check that the requests have the correct course number
        self.assertEqual(first_request["parameters"]["course_num"], self.course_key.course)
        self.assertEqual(second_request["parameters"]["course_num"], other_course_key.course)
Пример #6
0
    def test_create_credit_request_for_second_course(self):
        # Create the first request
        first_request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Create a request for a second course
        other_course_key = CourseKey.from_string("edX/other/2015")
        self._configure_credit(course_key=other_course_key)
        second_request = api.create_credit_request(other_course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Check that the requests have the correct course number
        self.assertEqual(first_request["parameters"]["course_num"], self.course_key.course)
        self.assertEqual(second_request["parameters"]["course_num"], other_course_key.course)
Пример #7
0
    def test_user_has_no_final_grade(self):
        # Simulate an error condition that should never happen:
        # a user is eligible for credit, but doesn't have a final
        # grade recorded in the eligibility requirement.
        grade_status = CreditRequirementStatus.objects.get(
            username=self.USER_INFO["username"], requirement__namespace="grade", requirement__name="grade"
        )
        grade_status.reason = {}
        grade_status.save()

        with self.assertRaises(UserIsNotEligible):
            api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])
Пример #8
0
    def test_reuse_credit_request(self):
        # Create the first request
        first_request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # Update the user's profile information, then attempt a second request
        self.user.profile.name = "Bobby"
        self.user.profile.save()
        second_request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # Request UUID should be the same
        self.assertEqual(first_request['uuid'], second_request['uuid'])

        # Request should use the updated information
        self.assertEqual(second_request['user_full_name'], "Bobby")
Пример #9
0
    def test_user_has_no_final_grade(self):
        # Simulate an error condition that should never happen:
        # a user is eligible for credit, but doesn't have a final
        # grade recorded in the eligibility requirement.
        grade_status = CreditRequirementStatus.objects.get(
            username=self.USER_INFO['username'],
            requirement__namespace="grade",
            requirement__name="grade")
        grade_status.reason = {}
        grade_status.save()

        with self.assertRaises(UserIsNotEligible):
            api.create_credit_request(self.course_key, self.PROVIDER_ID,
                                      self.USER_INFO["username"])
Пример #10
0
    def test_credit_request(self):
        # Initiate a credit request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # Validate the URL and method
        self.assertIn('url', request)
        self.assertEqual(request['url'], self.PROVIDER_URL)
        self.assertIn('method', request)
        self.assertEqual(request['method'], "POST")

        self.assertIn('parameters', request)
        parameters = request['parameters']

        # Validate the UUID
        self.assertIn('request_uuid', parameters)
        self.assertEqual(len(parameters['request_uuid']), 32)

        # Validate the timestamp
        self.assertIn('timestamp', parameters)
        parsed_date = from_timestamp(parameters['timestamp'])
        self.assertLess(parsed_date, datetime.datetime.now(pytz.UTC))

        # Validate course information
        self.assertEqual(parameters['course_org'], self.course_key.org)
        self.assertEqual(parameters['course_num'], self.course_key.course)
        self.assertEqual(parameters['course_run'], self.course_key.run)
        self.assertEqual(parameters['final_grade'], unicode(self.FINAL_GRADE))

        # Validate user information
        for key in self.USER_INFO.keys():
            param_key = 'user_{key}'.format(key=key)
            self.assertIn(param_key, parameters)
            expected = '' if key == 'mailing_address' else self.USER_INFO[key]
            self.assertEqual(parameters[param_key], expected)
Пример #11
0
    def post(self, request, provider_id):
        """ POST handler. """
        # Get the provider, or return HTTP 404 if it doesn't exist
        provider = generics.get_object_or_404(CreditProvider,
                                              provider_id=provider_id)

        # Validate the course key
        course_key = request.data.get('course_key')
        try:
            course_key = CourseKey.from_string(course_key)
        except InvalidKeyError:
            raise InvalidCourseKey(course_key)

        # Validate the username
        username = request.data.get('username')
        if not username:
            raise ValidationError({'detail': 'A username must be specified.'})

        # Ensure the user is actually eligible to receive credit
        if not CreditEligibility.is_user_eligible_for_credit(
                course_key, username):
            raise UserNotEligibleException(course_key, username)

        try:
            credit_request = create_credit_request(course_key,
                                                   provider.provider_id,
                                                   username)
            return Response(credit_request)
        except CreditApiBadRequest as ex:
            raise InvalidCreditRequest(text_type(ex))
Пример #12
0
    def test_credit_request(self):
        # Initiate a credit request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # Validate the UUID
        self.assertIn('uuid', request)
        self.assertEqual(len(request['uuid']), 32)

        # Validate the timestamp
        self.assertIn('timestamp', request)
        parsed_date = date_parser.parse(request['timestamp'])
        self.assertTrue(parsed_date < datetime.datetime.now(pytz.UTC))

        # Validate course information
        self.assertIn('course_org', request)
        self.assertEqual(request['course_org'], self.course_key.org)
        self.assertIn('course_num', request)
        self.assertEqual(request['course_num'], self.course_key.course)
        self.assertIn('course_run', request)
        self.assertEqual(request['course_run'], self.course_key.run)
        self.assertIn('final_grade', request)
        self.assertEqual(request['final_grade'], self.FINAL_GRADE)

        # Validate user information
        for key in self.USER_INFO.keys():
            request_key = 'user_{key}'.format(key=key)
            self.assertIn(request_key, request)
            self.assertEqual(request[request_key], self.USER_INFO[key])
Пример #13
0
    def test_query_counts(self):
        # Yes, this is a lot of queries, but this API call is also doing a lot of work :)
        # - 1 query: Check the user's eligibility and retrieve the credit course
        # - 1 Get the provider of the credit course.
        # - 2 queries: Get-or-create the credit request.
        # - 1 query: Retrieve user account and profile information from the user API.
        # - 1 query: Look up the user's final grade from the credit requirements table.
        # - 1 query: Look up the user's enrollment date in the course.
        # - 2 query: Look up the user's completion date in the course.
        # - 1 query: Update the request.
        # - 2 queries: Update the history table for the request.
        # - 4 Django savepoints
        with self.assertNumQueries(16):
            request = api.create_credit_request(self.course_key,
                                                self.PROVIDER_ID,
                                                self.USER_INFO['username'])

        # - 2 queries: Retrieve and update the request
        # - 1 query: Update the history table for the request.
        uuid = request["parameters"]["request_uuid"]
        with self.assertNumQueries(3):
            api.update_credit_request_status(uuid, self.PROVIDER_ID,
                                             "approved")

        with self.assertNumQueries(1):
            api.get_credit_requests_for_user(self.USER_INFO["username"])
Пример #14
0
    def post(self, request, provider_id):
        """ POST handler. """
        # Get the provider, or return HTTP 404 if it doesn't exist
        provider = generics.get_object_or_404(CreditProvider, provider_id=provider_id)

        # Validate the course key
        course_key = request.data.get('course_key')
        try:
            course_key = CourseKey.from_string(course_key)
        except InvalidKeyError:
            raise InvalidCourseKey(course_key)

        # Validate the username
        username = request.data.get('username')
        if not username:
            raise ValidationError({'detail': 'A username must be specified.'})

        # Ensure the user is actually eligible to receive credit
        if not CreditEligibility.is_user_eligible_for_credit(course_key, username):
            raise UserNotEligibleException(course_key, username)

        try:
            credit_request = create_credit_request(course_key, provider.provider_id, username)
            return Response(credit_request)
        except CreditApiBadRequest as ex:
            raise InvalidCreditRequest(text_type(ex))
Пример #15
0
    def test_credit_request(self):
        # Initiate a credit request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID,
                                            self.USER_INFO['username'])

        # Validate the URL and method
        self.assertIn('url', request)
        self.assertEqual(request['url'], self.PROVIDER_URL)
        self.assertIn('method', request)
        self.assertEqual(request['method'], "POST")

        self.assertIn('parameters', request)
        parameters = request['parameters']

        # Validate the UUID
        self.assertIn('request_uuid', parameters)
        self.assertEqual(len(parameters['request_uuid']), 32)

        # Validate the timestamp
        self.assertIn('timestamp', parameters)
        parsed_date = from_timestamp(parameters['timestamp'])
        self.assertTrue(parsed_date < datetime.datetime.now(pytz.UTC))

        # Validate course information
        self.assertEqual(parameters['course_org'], self.course_key.org)
        self.assertEqual(parameters['course_num'], self.course_key.course)
        self.assertEqual(parameters['course_run'], self.course_key.run)
        self.assertEqual(parameters['final_grade'], unicode(self.FINAL_GRADE))

        # Validate user information
        for key in self.USER_INFO.keys():
            param_key = 'user_{key}'.format(key=key)
            self.assertIn(param_key, parameters)
            expected = '' if key == 'mailing_address' else self.USER_INFO[key]
            self.assertEqual(parameters[param_key], expected)
Пример #16
0
 def _initiate_request(self):
     """Initiate a request for credit from a provider. """
     request = credit_api.create_credit_request(
         self.course.id,  # pylint: disable=no-member
         self.PROVIDER_ID,
         self.USERNAME)
     return request["parameters"]["request_uuid"]
Пример #17
0
    def test_credit_request(self):
        # Initiate a credit request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Validate the URL and method
        self.assertIn("url", request)
        self.assertEqual(request["url"], self.PROVIDER_URL)
        self.assertIn("method", request)
        self.assertEqual(request["method"], "POST")

        self.assertIn("parameters", request)
        parameters = request["parameters"]

        # Validate the UUID
        self.assertIn("request_uuid", parameters)
        self.assertEqual(len(parameters["request_uuid"]), 32)

        # Validate the timestamp
        self.assertIn("timestamp", parameters)
        parsed_date = from_timestamp(parameters["timestamp"])
        self.assertLess(parsed_date, datetime.datetime.now(pytz.UTC))

        # Validate course information
        self.assertEqual(parameters["course_org"], self.course_key.org)
        self.assertEqual(parameters["course_num"], self.course_key.course)
        self.assertEqual(parameters["course_run"], self.course_key.run)
        self.assertEqual(parameters["final_grade"], unicode(self.FINAL_GRADE))

        # Validate user information
        for key in self.USER_INFO.keys():
            param_key = "user_{key}".format(key=key)
            self.assertIn(param_key, parameters)
            expected = "" if key == "mailing_address" else self.USER_INFO[key]
            self.assertEqual(parameters[param_key], expected)
Пример #18
0
 def _initiate_request(self):
     """Initiate a request for credit from a provider. """
     request = credit_api.create_credit_request(
         self.course.id,  # pylint: disable=no-member
         self.PROVIDER_ID,
         self.USERNAME
     )
     return request["parameters"]["request_uuid"]
Пример #19
0
    def test_create_request_null_mailing_address(self):
        # User did not specify a mailing address
        self.user.profile.mailing_address = None
        self.user.profile.save()

        # Request should include an empty mailing address field
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])
        self.assertEqual(request["parameters"]["user_mailing_address"], "")
Пример #20
0
    def test_reuse_credit_request(self):
        # Create the first request
        first_request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Update the user's profile information, then attempt a second request
        self.user.profile.name = "Bobby"
        self.user.profile.save()
        second_request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Request UUID should be the same
        self.assertEqual(
            first_request["parameters"]["request_uuid"],
            second_request["parameters"]["request_uuid"]
        )

        # Request should use the updated information
        self.assertEqual(second_request["parameters"]["user_full_name"], "Bobby")
Пример #21
0
 def test_update_invalid_credit_status(self):
     # The request status must be either "approved" or "rejected"
     request = api.create_credit_request(self.course_key, self.PROVIDER_ID,
                                         self.USER_INFO["username"])
     with self.assertRaises(InvalidCreditStatus):
         api.update_credit_request_status(
             request["parameters"]["request_uuid"], self.PROVIDER_ID,
             "invalid")
Пример #22
0
    def test_create_request_null_mailing_address(self):
        # User did not specify a mailing address
        self.user.profile.mailing_address = None
        self.user.profile.save()

        # Request should include an empty mailing address field
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])
        self.assertEqual(request["parameters"]["user_mailing_address"], "")
Пример #23
0
    def test_credit_request_status(self, status):
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # Initial status should be "pending"
        self._assert_credit_status("pending")

        # Update the status
        api.update_credit_request_status(request['uuid'], status)
        self._assert_credit_status(status)
Пример #24
0
    def test_create_request_null_country(self):
        # Simulate users who registered accounts before the country field was introduced.
        # We need to manipulate the database directly because the country Django field
        # coerces None values to empty strings.
        query = "UPDATE auth_userprofile SET country = NULL WHERE id = %s"
        connection.cursor().execute(query, [str(self.user.profile.id)])

        # Request should include an empty country field
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])
        self.assertEqual(request["parameters"]["user_country"], "")
Пример #25
0
    def test_create_request_null_country(self):
        # Simulate users who registered accounts before the country field was introduced.
        # We need to manipulate the database directly because the country Django field
        # coerces None values to empty strings.
        query = "UPDATE auth_userprofile SET country = NULL WHERE id = %s"
        connection.cursor().execute(query, [str(self.user.profile.id)])

        # Request should include an empty country field
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])
        self.assertEqual(request["parameters"]["user_country"], "")
Пример #26
0
    def test_credit_request_disable_integration(self):
        CreditProvider.objects.all().update(enable_integration=False)

        # Initiate a request with automatic integration disabled
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # We get a URL and a GET method, so we can provide students
        # with a link to the credit provider, where they can request
        # credit directly.
        self.assertIn("url", request)
        self.assertEqual(request["url"], self.PROVIDER_URL)
        self.assertIn("method", request)
        self.assertEqual(request["method"], "GET")
Пример #27
0
    def test_credit_request_disable_integration(self):
        CreditProvider.objects.all().update(enable_integration=False)

        # Initiate a request with automatic integration disabled
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # We get a URL and a GET method, so we can provide students
        # with a link to the credit provider, where they can request
        # credit directly.
        self.assertIn("url", request)
        self.assertEqual(request["url"], self.PROVIDER_URL)
        self.assertIn("method", request)
        self.assertEqual(request["method"], "GET")
Пример #28
0
    def test_credit_messages(self):
        self._set_creditcourse()

        requirement = CreditRequirement.objects.create(
            course=self.credit_course,
            namespace="grade",
            name="grade",
            active=True
        )
        status = CreditRequirementStatus.objects.create(
            username=self.student.username,
            requirement=requirement,
        )
        status.status = "satisfied"
        status.reason = {"final_grade": self.FINAL_GRADE}
        status.save()

        self._set_user_eligible(self.credit_course, self.student.username)
        response = self.client.get(reverse("dashboard"))
        self.assertContains(
            response,
            "<b>Congratulations</b> {}, You have meet requirements for credit.".format(
                self.student.get_full_name()  # pylint: disable=no-member
            )
        )

        api.create_credit_request(self.course.id, self.first_provider.provider_id, self.student.username)

        response = self.client.get(reverse("dashboard"))
        self.assertContains(
            response,
            'Thank you, your payment is complete, your credit is processing. '
            'Please see {provider_link} for more information.'.format(
                provider_link='<a href="#" target="_blank">{provider_name}</a>'.format(
                    provider_name=self.first_provider.display_name
                )
            )
        )
Пример #29
0
    def test_credit_messages(self):
        self._set_creditcourse()

        requirement = CreditRequirement.objects.create(
            course=self.credit_course,
            namespace="grade",
            name="grade",
            active=True
        )
        status = CreditRequirementStatus.objects.create(
            username=self.student.username,
            requirement=requirement,
        )
        status.status = "satisfied"
        status.reason = {"final_grade": self.FINAL_GRADE}
        status.save()

        self._set_user_eligible(self.credit_course, self.student.username)
        response = self.client.get(reverse("dashboard"))
        self.assertContains(
            response,
            "<b>Congratulations</b> {}, You have meet requirements for credit.".format(
                self.student.get_full_name()  # pylint: disable=no-member
            )
        )

        api.create_credit_request(self.course.id, self.first_provider.provider_id, self.student.username)

        response = self.client.get(reverse("dashboard"))
        self.assertContains(
            response,
            'Thank you, your payment is complete, your credit is processing. '
            'Please see {provider_link} for more information.'.format(
                provider_link='<a href="#" target="_blank">{provider_name}</a>'.format(
                    provider_name=self.first_provider.display_name
                )
            )
        )
Пример #30
0
    def test_create_credit_request_grade_length(self):
        """ Verify the length of the final grade is limited to seven (7) characters total.

        This is a hack for ASU.
        """
        # Update the user's grade
        status = CreditRequirementStatus.objects.get(username=self.USER_INFO["username"])
        status.status = "satisfied"
        status.reason = {"final_grade": 1.0 / 3.0}
        status.save()

        # Initiate a credit request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])
        self.assertEqual(request['parameters']['final_grade'], u'0.33333')
Пример #31
0
    def test_create_credit_request_grade_length(self):
        """ Verify the length of the final grade is limited to seven (7) characters total.

        This is a hack for ASU.
        """
        # Update the user's grade
        status = CreditRequirementStatus.objects.get(username=self.USER_INFO["username"])
        status.status = "satisfied"
        status.reason = {"final_grade": 1.0 / 3.0}
        status.save()

        # Initiate a credit request
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])
        self.assertEqual(request['parameters']['final_grade'], u'0.33333')
Пример #32
0
    def test_credit_request_status(self, status):
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Initial status should be "pending"
        self._assert_credit_status("pending")

        credit_request_status = api.get_credit_request_status(self.USER_INFO['username'], self.course_key)
        self.assertEqual(credit_request_status["status"], "pending")

        # Update the status
        api.update_credit_request_status(request["parameters"]["request_uuid"], self.PROVIDER_ID, status)
        self._assert_credit_status(status)

        credit_request_status = api.get_credit_request_status(self.USER_INFO['username'], self.course_key)
        self.assertEqual(credit_request_status["status"], status)
Пример #33
0
    def test_credit_request_status(self, status):
        request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # Initial status should be "pending"
        self._assert_credit_status("pending")

        credit_request_status = api.get_credit_request_status(self.USER_INFO['username'], self.course_key)
        self.assertEqual(credit_request_status["status"], "pending")

        # Update the status
        api.update_credit_request_status(request["parameters"]["request_uuid"], self.PROVIDER_ID, status)
        self._assert_credit_status(status)

        credit_request_status = api.get_credit_request_status(self.USER_INFO['username'], self.course_key)
        self.assertEqual(credit_request_status["status"], status)
Пример #34
0
    def test_query_counts(self):
        # Yes, this is a lot of queries, but this API call is also doing a lot of work :)
        # - 1 query: Check the user's eligibility and retrieve the credit course and provider.
        # - 2 queries: Get-or-create the credit request.
        # - 1 query: Retrieve user account and profile information from the user API.
        # - 1 query: Look up the user's final grade from the credit requirements table.
        # - 2 queries: Update the request.
        # - 2 queries: Update the history table for the request.
        with self.assertNumQueries(9):
            request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO['username'])

        # - 3 queries: Retrieve and update the request
        # - 1 query: Update the history table for the request.
        with self.assertNumQueries(4):
            api.update_credit_request_status(request['uuid'], "approved")

        with self.assertNumQueries(1):
            api.get_credit_requests_for_user(self.USER_INFO['username'])
Пример #35
0
    def test_query_counts(self):
        # Yes, this is a lot of queries, but this API call is also doing a lot of work :)
        # - 1 query: Check the user's eligibility and retrieve the credit course
        # - 1 Get the provider of the credit course.
        # - 2 queries: Get-or-create the credit request.
        # - 1 query: Retrieve user account and profile information from the user API.
        # - 1 query: Look up the user's final grade from the credit requirements table.
        # - 1 query: Update the request.
        # - 2 queries: Update the history table for the request.
        # - 4 Django savepoints
        with self.assertNumQueries(13):
            request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])

        # - 2 queries: Retrieve and update the request
        # - 1 query: Update the history table for the request.
        uuid = request["parameters"]["request_uuid"]
        with self.assertNumQueries(3):
            api.update_credit_request_status(uuid, self.PROVIDER_ID, "approved")

        with self.assertNumQueries(1):
            api.get_credit_requests_for_user(self.USER_INFO["username"])
Пример #36
0
def create_credit_request(request, provider_id):
    """
    Initiate a request for credit in a course.

    This end-point will get-or-create a record in the database to track
    the request.  It will then calculate the parameters to send to
    the credit provider and digitally sign the parameters, using a secret
    key shared with the credit provider.

    The user's browser is responsible for POSTing these parameters
    directly to the credit provider.

    **Example Usage:**

        POST /api/credit/v1/providers/hogwarts/request/
        {
            "username": "******",
            "course_key": "edX/DemoX/Demo_Course"
        }

        Response: 200 OK
        Content-Type: application/json
        {
            "url": "http://example.com/request-credit",
            "method": "POST",
            "parameters": {
                request_uuid: "557168d0f7664fe59097106c67c3f847"
                timestamp: 1434631630,
                course_org: "ASUx"
                course_num: "DemoX"
                course_run: "1T2015"
                final_grade: 0.95,
                user_username: "******",
                user_email: "*****@*****.**"
                user_full_name: "John Smith"
                user_mailing_address: "",
                user_country: "US",
                signature: "cRCNjkE4IzY+erIjRwOQCpRILgOvXx4q2qvx141BCqI="
            }
        }

    **Parameters:**

        * username (unicode): The username of the user requesting credit.

        * course_key (unicode): The identifier for the course for which the user
            is requesting credit.

    **Responses:**

        * 200 OK: The request was created successfully.  Returned content
            is a JSON-encoded dictionary describing what the client should
            send to the credit provider.

        * 400 Bad Request:
            - The provided course key did not correspond to a valid credit course.
            - The user already has a completed credit request for this course and provider.

        * 403 Not Authorized:
            - The username does not match the name of the logged in user.
            - The user is not eligible for credit in the course.

        * 404 Not Found:
            - The provider does not exist.

    """
    response, parameters = _validate_json_parameters(request.body, ["username", "course_key"])
    if response is not None:
        return response

    try:
        course_key = CourseKey.from_string(parameters["course_key"])
    except InvalidKeyError:
        return HttpResponseBadRequest(
            u'Could not parse "{course_key}" as a course key'.format(
                course_key=parameters["course_key"]
            )
        )

    # Check user authorization
    if not (request.user and request.user.username == parameters["username"]):
        log.warning(
            u'User with ID %s attempted to initiate a credit request for user with username "%s"',
            request.user.id if request.user else "[Anonymous]",
            parameters["username"]
        )
        return HttpResponseForbidden("Users are not allowed to initiate credit requests for other users.")

    # Initiate the request
    try:
        credit_request = api.create_credit_request(course_key, provider_id, parameters["username"])
    except CreditApiBadRequest as ex:
        return HttpResponseBadRequest(ex)
    else:
        return JsonResponse(credit_request)
Пример #37
0
 def test_create_credit_request_address_empty(self):
     """ Verify the mailing address is always empty. """
     request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.user.username)
     self.assertEqual(request['parameters']['user_mailing_address'], '')
Пример #38
0
 def test_update_invalid_credit_status(self):
     # The request status must be either "approved" or "rejected"
     request = api.create_credit_request(self.course_key, self.PROVIDER_ID, self.USER_INFO["username"])
     with self.assertRaises(InvalidCreditStatus):
         api.update_credit_request_status(request["parameters"]["request_uuid"], self.PROVIDER_ID, "invalid")
Пример #39
0
 def test_create_credit_request_address_empty(self):
     """ Verify the mailing address is always empty. """
     request = api.create_credit_request(self.course_key, self.PROVIDER_ID,
                                         self.user.username)
     self.assertEqual(request['parameters']['user_mailing_address'], '')
Пример #40
0
def create_credit_request(request, provider_id):
    """
    Initiate a request for credit in a course.

    This end-point will get-or-create a record in the database to track
    the request.  It will then calculate the parameters to send to
    the credit provider and digitally sign the parameters, using a secret
    key shared with the credit provider.

    The user's browser is responsible for POSTing these parameters
    directly to the credit provider.

    **Example Usage:**

        POST /api/credit/v1/providers/hogwarts/request/
        {
            "username": "******",
            "course_key": "edX/DemoX/Demo_Course"
        }

        Response: 200 OK
        Content-Type: application/json
        {
            "url": "http://example.com/request-credit",
            "method": "POST",
            "parameters": {
                request_uuid: "557168d0f7664fe59097106c67c3f847"
                timestamp: 1434631630,
                course_org: "ASUx"
                course_num: "DemoX"
                course_run: "1T2015"
                final_grade: "0.95",
                user_username: "******",
                user_email: "*****@*****.**"
                user_full_name: "John Smith"
                user_mailing_address: "",
                user_country: "US",
                signature: "cRCNjkE4IzY+erIjRwOQCpRILgOvXx4q2qvx141BCqI="
            }
        }

    **Parameters:**

        * username (unicode): The username of the user requesting credit.

        * course_key (unicode): The identifier for the course for which the user
            is requesting credit.

    **Responses:**

        * 200 OK: The request was created successfully.  Returned content
            is a JSON-encoded dictionary describing what the client should
            send to the credit provider.

        * 400 Bad Request:
            - The provided course key did not correspond to a valid credit course.
            - The user already has a completed credit request for this course and provider.

        * 403 Not Authorized:
            - The username does not match the name of the logged in user.
            - The user is not eligible for credit in the course.

        * 404 Not Found:
            - The provider does not exist.

    """
    response, parameters = _validate_json_parameters(
        request.body, ["username", "course_key"])
    if response is not None:
        return response

    try:
        course_key = CourseKey.from_string(parameters["course_key"])
    except InvalidKeyError:
        return HttpResponseBadRequest(
            u'Could not parse "{course_key}" as a course key'.format(
                course_key=parameters["course_key"]))

    # Check user authorization
    if not (request.user and request.user.username == parameters["username"]):
        log.warning(
            u'User with ID %s attempted to initiate a credit request for user with username "%s"',
            request.user.id if request.user else "[Anonymous]",
            parameters["username"])
        return HttpResponseForbidden(
            "Users are not allowed to initiate credit requests for other users."
        )

    # Initiate the request
    try:
        credit_request = api.create_credit_request(course_key, provider_id,
                                                   parameters["username"])
    except CreditApiBadRequest as ex:
        return HttpResponseBadRequest(ex)
    else:
        return JsonResponse(credit_request)