def _create_library(request): """ Helper method for creating a new library. """ if not auth.has_access(request.user, CourseCreatorRole()): log.exception(u"User %s tried to create a library without permission", request.user.username) raise PermissionDenied() display_name = None try: display_name = request.json['display_name'] org = request.json['org'] library = request.json.get('number', None) if library is None: library = request.json['library'] store = modulestore() with store.default_store(ModuleStoreEnum.Type.split): new_lib = store.create_library( org=org, library=library, user_id=request.user.id, fields={"display_name": display_name}, ) # Give the user admin ("Instructor") role for this library: add_instructor(new_lib.location.library_key, request.user, request.user) except KeyError as error: log.exception("Unable to create library - missing required JSON key.") return JsonResponseBadRequest({ "ErrMsg": _("Unable to create library - missing required field '{field}'". format(field=error.message)) }) except InvalidKeyError as error: log.exception("Unable to create library - invalid key.") return JsonResponseBadRequest({ "ErrMsg": _("Unable to create library '{name}'.\n\n{err}").format( name=display_name, err=error.message) }) except DuplicateCourseError: log.exception( "Unable to create library - one already exists with the same key.") return JsonResponseBadRequest({ 'ErrMsg': _('There is already a library defined with the same ' 'organization and library code. Please ' 'change your library code so that it is unique within your organization.' ) }) lib_key_str = unicode(new_lib.location.library_key) return JsonResponse({ 'url': reverse_library_url('library_handler', lib_key_str), 'library_key': lib_key_str, })
def _create_library(request): """ Helper method for creating a new library. """ display_name = None try: display_name = request.json['display_name'] org = request.json['org'] library = request.json.get('number', None) # [COLARAZ_CUSTOM] if not request.user.is_superuser and not org in configuration_helpers.get_value('course_org_filter'): log.exception('Unable to create library - invalid organization ({}).'.format(org)) return JsonResponseBadRequest({ "ErrMsg": _("Unable to create library '{}'.\n\n{} is not a valid organization.").format(display_name, org) }) if library is None: library = request.json['library'] store = modulestore() with store.default_store(ModuleStoreEnum.Type.split): new_lib = store.create_library( org=org, library=library, user_id=request.user.id, fields={"display_name": display_name}, ) # Give the user admin ("Instructor") role for this library: add_instructor(new_lib.location.library_key, request.user, request.user) except KeyError as error: log.exception("Unable to create library - missing required JSON key.") return JsonResponseBadRequest({ "ErrMsg": _("Unable to create library - missing required field '{field}'").format(field=text_type(error)) }) except InvalidKeyError as error: log.exception("Unable to create library - invalid key.") return JsonResponseBadRequest({ "ErrMsg": _("Unable to create library '{name}'.\n\n{err}").format(name=display_name, err=text_type(error)) }) except DuplicateCourseError: log.exception("Unable to create library - one already exists with the same key.") return JsonResponseBadRequest({ 'ErrMsg': _( 'There is already a library defined with the same ' 'organization and library code. Please ' 'change your library code so that it is unique within your organization.' ) }) lib_key_str = unicode(new_lib.location.library_key) return JsonResponse({ 'url': reverse_library_url('library_handler', lib_key_str), 'library_key': lib_key_str, })
def edxnotes_visibility(request, course_id): """ Handle ajax call from "Show notes" checkbox. """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, "load", course_key) field_data_cache = FieldDataCache([course], course_key, request.user) course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course_key, course=course) if not is_feature_enabled(course, request.user): raise Http404 try: visibility = json.loads(request.body)["visibility"] course_module.edxnotes_visibility = visibility course_module.save() return JsonResponse(status=200) except (ValueError, KeyError): log.warning( "Could not decode request body as JSON and find a boolean visibility field: '%s'", request.body) return JsonResponseBadRequest()
def test_dict(self): obj = {"foo": "bar"} resp = JsonResponseBadRequest(obj) compare = json.loads(resp.content.decode('utf-8')) self.assertEqual(obj, compare) self.assertEqual(resp.status_code, 400) self.assertEqual(resp["content-type"], "application/json")
def test_set_status_arg(self): obj = {"error": "resource not found"} resp = JsonResponseBadRequest(obj, 404) compare = json.loads(resp.content.decode('utf-8')) self.assertEqual(obj, compare) self.assertEqual(resp.status_code, 404) self.assertEqual(resp["content-type"], "application/json")
def test_encoder(self): obj = [1, 2, 3] encoder = object() with mock.patch.object(json, "dumps", return_value="[1,2,3]") as dumps: resp = JsonResponseBadRequest(obj, encoder=encoder) self.assertEqual(resp.status_code, 400) compare = json.loads(resp.content.decode('utf-8')) self.assertEqual(obj, compare) kwargs = dumps.call_args[1] self.assertIs(kwargs["cls"], encoder)
def search_notes(request, course_id): """ Handles search requests. """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, "load", course_key) if not is_feature_enabled(course): raise Http404 if "text" not in request.GET: return HttpResponseBadRequest() query_string = request.GET["text"] try: search_results = search(request.user, course, query_string) except (EdxNotesParseError, EdxNotesServiceUnavailable) as err: return JsonResponseBadRequest({"error": err.message}, status=500) return HttpResponse(search_results)
def update_example_certificate(request): """Callback from the XQueue that updates example certificates. Example certificates are used to verify that certificate generation is configured correctly for a course. Unlike other certificates, example certificates are not associated with a particular user or displayed to students. For this reason, we need a different end-point to update the status of generated example certificates. Arguments: request (HttpRequest) Returns: HttpResponse (200): Status was updated successfully. HttpResponse (400): Invalid parameters. HttpResponse (403): Rate limit exceeded for bad requests. HttpResponse (404): Invalid certificate identifier or access key. """ logger.info(u"Received response for example certificate from XQueue.") rate_limiter = BadRequestRateLimiter() # Check the parameters and rate limits # If these are invalid, return an error response. if rate_limiter.is_rate_limit_exceeded(request): logger.info( u"Bad request rate limit exceeded for update example certificate end-point." ) return HttpResponseForbidden("Rate limit exceeded") if 'xqueue_body' not in request.POST: logger.info( u"Missing parameter 'xqueue_body' for update example certificate end-point" ) rate_limiter.tick_bad_request_counter(request) return JsonResponseBadRequest("Parameter 'xqueue_body' is required.") if 'xqueue_header' not in request.POST: logger.info( u"Missing parameter 'xqueue_header' for update example certificate end-point" ) rate_limiter.tick_bad_request_counter(request) return JsonResponseBadRequest("Parameter 'xqueue_header' is required.") try: xqueue_body = json.loads(request.POST['xqueue_body']) xqueue_header = json.loads(request.POST['xqueue_header']) except (ValueError, TypeError): logger.info( u"Could not decode params to example certificate end-point as JSON." ) rate_limiter.tick_bad_request_counter(request) return JsonResponseBadRequest("Parameters must be JSON-serialized.") # Attempt to retrieve the example certificate record # so we can update the status. try: uuid = xqueue_body.get('username') access_key = xqueue_header.get('lms_key') cert = ExampleCertificate.objects.get(uuid=uuid, access_key=access_key) except ExampleCertificate.DoesNotExist: # If we are unable to retrieve the record, it means the uuid or access key # were not valid. This most likely means that the request is NOT coming # from the XQueue. Return a 404 and increase the bad request counter # to protect against a DDOS attack. logger.info( u"Could not find example certificate with uuid '%s' and access key '%s'", uuid, access_key) rate_limiter.tick_bad_request_counter(request) raise Http404 if 'error' in xqueue_body: # If an error occurs, save the error message so we can fix the issue. error_reason = xqueue_body.get('error_reason') cert.update_status(ExampleCertificate.STATUS_ERROR, error_reason=error_reason) logger.warning(( u"Error occurred during example certificate generation for uuid '%s'. " u"The error response was '%s'."), uuid, error_reason) else: # If the certificate generated successfully, save the download URL # so we can display the example certificate. download_url = xqueue_body.get('url') if download_url is None: rate_limiter.tick_bad_request_counter(request) logger.warning( u"No download URL provided for example certificate with uuid '%s'.", uuid) return JsonResponseBadRequest( "Parameter 'download_url' is required for successfully generated certificates." ) else: cert.update_status(ExampleCertificate.STATUS_SUCCESS, download_url=download_url) logger.info( "Successfully updated example certificate with uuid '%s'.", uuid) # Let the XQueue know that we handled the response return JsonResponse({'return_code': 0})
def notes(request, course_id): """ Notes view to handle list and search requests. Query parameters: page: page number to get page_size: number of items in the page text: text string to search. If `text` param is missing then get all the notes for the current user for this course else get only those notes which contain the `text` value. Arguments: request: HTTP request object course_id: course id Returns: Paginated response as JSON. A sample response is below. { "count": 101, "num_pages": 11, "current_page": 1, "results": [ { "chapter": { "index": 4, "display_name": "About Exams and Certificates", "location": "i4x://org/course/category/name@revision", "children": [ "i4x://org/course/category/name@revision" ] }, "updated": "Dec 09, 2015 at 09:31 UTC", "tags": ["shadow","oil"], "quote": "foo bar baz", "section": { "display_name": "edX Exams", "location": "i4x://org/course/category/name@revision", "children": [ "i4x://org/course/category/name@revision", "i4x://org/course/category/name@revision", ] }, "created": "2015-12-09T09:31:17.338305Z", "ranges": [ { "start": "/div[1]/p[1]", "end": "/div[1]/p[1]", "startOffset": 0, "endOffset": 6 } ], "user": "******", "text": "first angry height hungry structure", "course_id": "edx/DemoX/Demo", "id": "1231", "unit": { "url": "/courses/edx%2FDemoX%2FDemo/courseware/1414ffd5143b4b508f739b563ab468b7/workflow/1", "display_name": "EdX Exams", "location": "i4x://org/course/category/name@revision" }, "usage_id": "i4x://org/course/category/name@revision" } ], "next": "http://0.0.0.0:8000/courses/edx%2FDemoX%2FDemo/edxnotes/notes/?page=2&page_size=10", "start": 0, "previous": null } """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, 'load', course_key) if not is_feature_enabled(course, request.user): raise Http404 page = request.GET.get('page') or DEFAULT_PAGE page_size = request.GET.get('page_size') or DEFAULT_PAGE_SIZE text = request.GET.get('text') try: notes_info = get_notes(request, course, page=page, page_size=page_size, text=text) except (EdxNotesParseError, EdxNotesServiceUnavailable) as err: return JsonResponseBadRequest({"error": text_type(err)}, status=500) return HttpResponse(json.dumps(notes_info, cls=NoteJSONEncoder), content_type="application/json")
def custom_settings_handler(request, course_key_string): """ Course settings configuration GET html: get the page json: get the model PUT, POST json: update the Course's settings. The payload is a json rep of the metadata dicts. """ course_key = CourseKey.from_string(course_key_string) with modulestore().bulk_operations(course_key): course_module = get_course_and_check_access(course_key, request.user) if 'text/html' in request.META.get('HTTP_ACCEPT', '') and request.method == 'GET': return render_to_response( 'custom_settings.html', { 'context_course': course_module, 'is_new': course_module.is_new, 'invitation_only': course_module.invitation_only, 'visible_to_manager_only': course_module.visible_to_manager_only, }) elif 'application/json' in request.META.get('HTTP_ACCEPT', ''): if request.method == 'GET': return JsonResponse(CourseMetadata.fetch(course_module)) else: try: # validate data formats and update the course module. # Note: don't update mongo yet, but wait until after any tabs are changed is_valid, errors, updated_data = CourseMetadata.validate_and_update_from_json( course_module, request.json, user=request.user, ) if is_valid: try: additional_info = { 'is_new': request.POST.get('is_new', False), 'invitation_only': request.POST.get('invitation_only', False), 'visible_to_manager_only': request.POST.get('visible_to_manager_only', False) } CourseMetadata.update_from_dict( additional_info, course_module, request.user) course_search_index_handler( request, course_key_string) except InvalidTabsException as err: log.exception(err.message) response_message = [{ 'message': _('An error occurred while trying to save your tabs' ), 'model': { 'display_name': _('Tabs Exception') } }] return JsonResponseBadRequest(response_message) return JsonResponse(updated_data) else: return JsonResponseBadRequest(errors) # Handle all errors that validation doesn't catch except (TypeError, ValueError, InvalidTabsException) as err: return HttpResponseBadRequest(django.utils.html.escape( err.message), content_type="text/plain")
def test_empty_string(self): resp = JsonResponseBadRequest("") self.assertIsInstance(resp, HttpResponse) self.assertEqual(resp.content.decode('utf-8'), "") self.assertEqual(resp.status_code, 400) self.assertEqual(resp["content-type"], "application/json")
def test_empty(self): resp = JsonResponseBadRequest() self.assertIsInstance(resp, HttpResponseBadRequest) self.assertEqual(resp.content, "") self.assertEqual(resp.status_code, 400) self.assertEqual(resp["content-type"], "application/json")