def aside_handler(request, aside_id, handler_slug, suffix='', authenticated=True): """The view function for authenticated handler requests.""" if authenticated: student_id = get_student_id(request) log.info(u"Start handler %s/%s for student %s", aside_id, handler_slug, student_id) else: student_id = "none" log.info(u"Start handler %s/%s", aside_id, handler_slug) runtime = WorkbenchRuntime(student_id) try: block = runtime.get_aside(aside_id) except NoSuchUsage: raise Http404 request = django_to_webob_request(request) request.path_info_pop() request.path_info_pop() result = block.runtime.handle(block, handler_slug, request, suffix) log.info(u"End handler %s/%s", aside_id, handler_slug) return webob_to_django_response(result)
def component_handler(request, usage_id, handler, suffix=""): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to, passed through `quote_slashes` handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ location = unquote_slashes(usage_id) descriptor = modulestore().get_item(location) # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info("XBlock %s attempted to access missing handler %r", descriptor, handler, exc_info=True) raise Http404 modulestore().save_xmodule(descriptor) return webob_to_django_response(resp)
def component_handler(request, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ usage_key = UsageKey.from_string(usage_key_string) descriptor = get_modulestore(usage_key).get_item(usage_key) # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info("XBlock %s attempted to access missing handler %r", descriptor, handler, exc_info=True) raise Http404 # unintentional update to handle any side effects of handle call; so, request user didn't author # the change get_modulestore(usage_key).update_item(descriptor, None) return webob_to_django_response(resp)
def preview_handler(request, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock usage_key_string: The usage_key_string-id of the block to dispatch to, passed through `quote_slashes` handler: The handler to execute suffix: The remainder of the url to be passed to the handler """ usage_key = UsageKey.from_string(usage_key_string) descriptor = modulestore().get_item(usage_key) instance = _load_preview_module(request, descriptor) # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 except ProcessingError: log.warning("Module raised an error while processing AJAX request", exc_info=True) return HttpResponseBadRequest() except Exception: log.exception("error processing ajax call") raise return webob_to_django_response(resp)
def component_handler(request, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ usage_key = UsageKey.from_string(usage_key_string) descriptor = modulestore().get_item(usage_key) # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info("XBlock %s attempted to access missing handler %r", descriptor, handler, exc_info=True) raise Http404 # unintentional update to handle any side effects of handle call # could potentially be updating actual course data or simply caching its values modulestore().update_item(descriptor, request.user.id) return webob_to_django_response(resp)
def component_handler(request, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ usage_key = UsageKey.from_string(usage_key_string) descriptor = modulestore().get_item(usage_key) descriptor.xmodule_runtime = StudioEditModuleRuntime(request.user) # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info("XBlock %s attempted to access missing handler %r", descriptor, handler, exc_info=True) raise Http404 # unintentional update to handle any side effects of handle call # could potentially be updating actual course data or simply caching its values modulestore().update_item(descriptor, request.user.id) return webob_to_django_response(resp)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, user): """ Invoke an XBlock handler, either authenticated or not. """ location = unquote_slashes(usage_id) # Check parameters and fail fast if there's a problem if not Location.is_valid(location): raise Http404("Invalid location") # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return HttpResponse(json.dumps({"success": error_msg})) try: descriptor = modulestore().get_instance(course_id, location) except ItemNotFoundError: log.warn( "Invalid location for course id {course_id}: {location}".format(course_id=course_id, location=location) ) raise Http404 field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, user, descriptor) instance = get_module(user, request, location, field_data_cache, course_id, grade_bucket_type="ajax") if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. log.debug("No module %s for user %s -- access denied?", location, user) raise Http404 req = django_to_webob_request(request) try: resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={"success": err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def xblock_handler(request, user_id, secure_token, usage_key_str, handler_name, suffix): """ Run an XBlock's handler and return the result This endpoint has a unique authentication scheme that involves a temporary auth token included in the URL (see below). As a result it can be exempt from CSRF, session auth, and JWT/OAuth. """ try: usage_key = UsageKey.from_string(usage_key_str) except InvalidKeyError as e: raise Http404 from e # To support sandboxed XBlocks, custom frontends, and other use cases, we # authenticate requests using a secure token in the URL. see # openedx.core.djangoapps.xblock.utils.get_secure_hash_for_xblock_handler # for details and rationale. if not validate_secure_token_for_xblock_handler(user_id, usage_key_str, secure_token): raise PermissionDenied("Invalid/expired auth token.") if request.user.is_authenticated: # The user authenticated twice, e.g. with session auth and the token. # This can happen if not running the XBlock in a sandboxed iframe. # Just make sure the session auth matches the token: if request.user.id != int(user_id): raise AuthenticationFailed("Authentication conflict.") user = request.user elif user_id.isdigit(): # This is a normal (integer) user ID for a registered user. # This is the "normal" way this view gets used, with a sandboxed iframe. user = User.objects.get(pk=int(user_id)) elif user_id.startswith("anon"): # This is a non-registered (anonymous) user: assert request.user.is_anonymous assert not hasattr(request.user, 'xblock_id_for_anonymous_user') user = request.user # An AnonymousUser # Since this particular view usually gets called from a sandboxed iframe # we won't have access to the LMS session data for this user (the iframe # has a new, empty session). So we need to save the identifier for this # anonymous user (from the URL) on the user object, so that the runtime # can get it (instead of generating a new one and saving it into this # new empty session) # See djangoapps.xblock.utils.get_xblock_id_for_anonymous_user() user.xblock_id_for_anonymous_user = user_id else: raise AuthenticationFailed("Invalid user ID format.") request_webob = DjangoWebobRequest( request ) # Convert from django request to the webob format that XBlocks expect block = load_block(usage_key, user) # Run the handler, and save any resulting XBlock field value changes: response_webob = block.handle(handler_name, request_webob, suffix) response = webob_to_django_response(response_webob) return response
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked """ # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return JsonResponse(object={ 'success': False, 'msg': error_msg }, status=413) instance, tracking_context = _get_module_by_usage_id( request, course_id, usage_id) tracking_context_name = 'module_callback_handler' req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def xblock_handler(request, course_key_string, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response Example: POST ${STUDIO_URL}/sn-api/courses/{course_key}/xblocks/{usage_key}/handler/{handler}/ See https://github.com/edx/edx-platform/blob/open-release/juniper.master/cms/djangoapps/contentstore/views/component.py#L449 """ usage_key = UsageKey.from_string(usage_key_string) # Let the module handle the AJAX req = django_to_webob_request(request) try: if is_xblock_aside(usage_key): # Get the descriptor for the block being wrapped by the aside (not the aside itself) descriptor = modulestore().get_item(usage_key.usage_key) handler_descriptor = get_aside_from_xblock(descriptor, usage_key.aside_type) asides = [handler_descriptor] else: descriptor = modulestore().get_item(usage_key) handler_descriptor = descriptor asides = [] handler_descriptor.xmodule_runtime = StudioEditModuleRuntime( request.user) resp = handler_descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info(u"XBlock %s attempted to access missing handler %r", handler_descriptor, handler, exc_info=True) raise Http404 # unintentional update to handle any side effects of handle call # could potentially be updating actual course data or simply caching its values modulestore().update_item(descriptor, request.user.id, asides=asides) log.info('xblock content is updated (course_id: {}, xblock_id: {})'.format( course_key_string, usage_key_string)) return webob_to_django_response(resp)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked """ # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return JsonResponse(object={'success': error_msg}, status=413) instance, tracking_context = get_module_by_usage_id(request, course_id, usage_id) # Name the transaction so that we can view XBlock handlers separately in # New Relic. The suffix is necessary for XModule handlers because the # "handler" in those cases is always just "xmodule_handler". nr_tx_name = "{}.{}".format(instance.__class__.__name__, handler) nr_tx_name += "/{}".format(suffix) if suffix else "" newrelic.agent.set_transaction_name(nr_tx_name, group="Python/XBlock/Handler") tracking_context_name = 'module_callback_handler' req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def handler(request, usage_id, handler_slug): """Provide a handler for the request.""" student_id = get_student_id(request) log.info("Start handler %s/%s for student %s", usage_id, handler_slug, student_id) runtime = WorkbenchRuntime(student_id) block = runtime.get_block(usage_id) request = django_to_webob_request(request) request.path_info_pop() request.path_info_pop() result = block.runtime.handle(block, handler_slug, request) log.info("End handler %s/%s", usage_id, handler_slug) return webob_to_django_response(result)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked """ # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return JsonResponse(object={'success': error_msg}, status=413) instance, tracking_context = _get_module_by_usage_id(request, course_id, usage_id) tracking_context_name = 'module_callback_handler' req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def handler(request, usage_id, handler_slug, suffix=''): """Provide a handler for the request.""" student_id = get_student_id(request) log.info("Start handler %s/%s for student %s", usage_id, handler_slug, student_id) runtime = WorkbenchRuntime(student_id) try: block = runtime.get_block(usage_id) except KeyError: raise Http404 request = django_to_webob_request(request) request.path_info_pop() request.path_info_pop() result = block.runtime.handle(block, handler_slug, request, suffix) log.info("End handler %s/%s", usage_id, handler_slug) return webob_to_django_response(result)
def preview_handler(request, usage_key_string, handler, suffix=""): """ Dispatch an AJAX action to an xblock usage_key_string: The usage_key_string-id of the block to dispatch to, passed through `quote_slashes` handler: The handler to execute suffix: The remainder of the url to be passed to the handler """ usage_key = UsageKey.from_string(usage_key_string) if isinstance(usage_key, AsideUsageKeyV1): descriptor = modulestore().get_item(usage_key.usage_key) for aside in descriptor.runtime.get_asides(descriptor): if aside.scope_ids.block_type == usage_key.aside_type: asides = [aside] instance = aside break else: descriptor = modulestore().get_item(usage_key) instance = _load_preview_module(request, descriptor) asides = [] # Let the module handle the AJAX req = django_to_webob_request(request) try: resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 except ProcessingError: log.warning("Module raised an error while processing AJAX request", exc_info=True) return HttpResponseBadRequest() except Exception: log.exception("error processing ajax call") raise modulestore().update_item(descriptor, request.user.id, asides=asides) return webob_to_django_response(resp)
def component_handler(request, usage_key_string, handler, suffix=''): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ usage_key = UsageKey.from_string(usage_key_string) # Let the module handle the AJAX req = django_to_webob_request(request) try: if is_xblock_aside(usage_key): # Get the descriptor for the block being wrapped by the aside (not the aside itself) descriptor = modulestore().get_item(usage_key.usage_key) handler_descriptor = get_aside_from_xblock(descriptor, usage_key.aside_type) asides = [handler_descriptor] else: descriptor = modulestore().get_item(usage_key) handler_descriptor = descriptor asides = [] handler_descriptor.xmodule_runtime = StudioEditModuleRuntime( request.user) resp = handler_descriptor.handle(handler, req, suffix) except NoSuchHandlerError: log.info(u"XBlock %s attempted to access missing handler %r", handler_descriptor, handler, exc_info=True) raise Http404 # unintentional update to handle any side effects of handle call # could potentially be updating actual course data or simply caching its values modulestore().update_item(descriptor, request.user.id, asides=asides) return webob_to_django_response(resp)
def post(self, request, usage_key_string): """ Dispatch an AJAX action to an xblock Args: usage_id: The usage-id of the block to dispatch to handler (str): The handler to execute suffix (str): The remainder of the url to be passed to the handler Returns: :class:`django.http.HttpResponse`: The response from the handler, converted to a django response """ handler = 'submit_studio_edits' suffix = '' usage_key = UsageKey.from_string(usage_key_string) # Let the module handle the AJAX req = django_to_webob_request(request) asides = [] try: if isinstance(usage_key, (AsideUsageKeyV1, AsideUsageKeyV2)): descriptor = modulestore().get_item(usage_key.usage_key) aside_instance = get_xblock_aside_instance(usage_key) asides = [aside_instance] if aside_instance else [] resp = aside_instance.handle(handler, req, suffix) else: descriptor = modulestore().get_item(usage_key) descriptor.xmodule_runtime = StudioEditModuleRuntime( request.user) resp = descriptor.handle(handler, req, suffix) except NoSuchHandlerError: raise Http404 # unintentional update to handle any side effects of handle call # could potentially be updating actual course data or simply caching its values modulestore().update_item(descriptor, request.user.id, asides=asides) return webob_to_django_response(resp)
def handler(request, usage_id, handler_slug, suffix='', authenticated=True): """The view function for authenticated handler requests.""" if authenticated: student_id = get_student_id(request) log.info("Start handler %s/%s for student %s", usage_id, handler_slug, student_id) else: student_id = "none" log.info("Start handler %s/%s", usage_id, handler_slug) runtime = WorkbenchRuntime(student_id) try: block = runtime.get_block(usage_id) except NoSuchUsage: raise Http404 request = django_to_webob_request(request) request.path_info_pop() request.path_info_pop() result = block.runtime.handle(block, handler_slug, request, suffix) log.info("End handler %s/%s", usage_id, handler_slug) return webob_to_django_response(result)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course=None): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked """ # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return JsonResponse({'success': error_msg}, status=413) # Make a CourseKey from the course_id, raising a 404 upon parse error. try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: raise Http404 set_custom_metrics_for_course_key(course_key) with modulestore().bulk_operations(course_key): instance, tracking_context = get_module_by_usage_id(request, course_id, usage_id, course=course) # Name the transaction so that we can view XBlock handlers separately in # New Relic. The suffix is necessary for XModule handlers because the # "handler" in those cases is always just "xmodule_handler". nr_tx_name = "{}.{}".format(instance.__class__.__name__, handler) nr_tx_name += "/{}".format(suffix) if (suffix and handler == "xmodule_handler") else "" set_monitoring_transaction_name(nr_tx_name, group="Python/XBlock/Handler") tracking_context_name = 'module_callback_handler' req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) if suffix == 'problem_check' \ and course \ and getattr(course, 'entrance_exam_enabled', False) \ and getattr(instance, 'in_entrance_exam', False): ee_data = {'entrance_exam_passed': user_has_passed_entrance_exam(request.user, course)} resp = append_data_to_webob_response(resp, ee_data) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse({'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def handle_xblock_callback(request, course_id, usage_id, handler, suffix=None): """ Generic view for extensions. This is where AJAX calls go. Arguments: - request -- the django request. - location -- the module location. Used to look up the XModule instance - course_id -- defines the course context for this request. Raises PermissionDenied if the user is not logged in. Raises Http404 if the location and course_id do not identify a valid module, the module is not accessible by the user, or the module raises NotFoundError. If the module raises any other error, it will escape this function. """ location = unquote_slashes(usage_id) # Check parameters and fail fast if there's a problem if not Location.is_valid(location): raise Http404("Invalid location") if not request.user.is_authenticated(): raise PermissionDenied # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return HttpResponse(json.dumps({'success': error_msg})) try: descriptor = modulestore().get_instance(course_id, location) except ItemNotFoundError: log.warn( "Invalid location for course id {course_id}: {location}".format( course_id=course_id, location=location ) ) raise Http404 field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, request.user, descriptor ) instance = get_module(request.user, request, location, field_data_cache, course_id, grade_bucket_type='ajax') if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. log.debug("No module %s for user %s -- access denied?", location, request.user) raise Http404 req = django_to_webob_request(request) try: resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, user): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked user (User): The currently logged in user """ try: course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id) usage_key = course_id.make_usage_key_from_deprecated_string( unquote_slashes(usage_id)) except InvalidKeyError: raise Http404("Invalid location") # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return HttpResponse(json.dumps({'success': error_msg})) try: descriptor = modulestore().get_item(usage_key) except ItemNotFoundError: log.warn( "Invalid location for course id {course_id}: {usage_key}".format( course_id=usage_key.course_key, usage_key=usage_key)) raise Http404 tracking_context_name = 'module_callback_handler' tracking_context = { 'module': { 'display_name': descriptor.display_name_with_default, } } field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, user, descriptor) instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type='ajax') if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. log.debug("No module %s for user %s -- access denied?", usage_key, user) raise Http404 req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, user): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked user (User): The currently logged in user """ try: course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id) usage_key = course_id.make_usage_key_from_deprecated_string(unquote_slashes(usage_id)) except InvalidKeyError: raise Http404("Invalid location") # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return HttpResponse(json.dumps({'success': error_msg})) try: descriptor = modulestore().get_item(usage_key) except ItemNotFoundError: log.warn( "Invalid location for course id {course_id}: {usage_key}".format( course_id=usage_key.course_key, usage_key=usage_key ) ) raise Http404 tracking_context_name = 'module_callback_handler' tracking_context = { 'module': { 'display_name': descriptor.display_name_with_default, } } field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, user, descriptor ) instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type='ajax') if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. log.debug("No module %s for user %s -- access denied?", usage_key, user) raise Http404 req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def _as_django(self, *args, **kwargs): """ Return a :class:`django.http.HttpResponse` created from a `webob.Response` initialized with `*args` and `**kwargs` """ return webob_to_django_response(Response(*args, **kwargs))
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course=None): """ Invoke an XBlock handler, either authenticated or not. Arguments: request (HttpRequest): the current request course_id (str): A string of the form org/course/run usage_id (str): A string of the form i4x://org/course/category/name@revision handler (str): The name of the handler to invoke suffix (str): The suffix to pass to the handler when invoked """ # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return JsonResponse({'success': error_msg}, status=413) # Make a CourseKey from the course_id, raising a 404 upon parse error. try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: raise Http404 # Gather metrics for New Relic so we can slice data in New Relic Insights newrelic.agent.add_custom_parameter('course_id', unicode(course_key)) newrelic.agent.add_custom_parameter('org', unicode(course_key.org)) with modulestore().bulk_operations(course_key): instance, tracking_context = get_module_by_usage_id(request, course_id, usage_id, course=course) # Name the transaction so that we can view XBlock handlers separately in # New Relic. The suffix is necessary for XModule handlers because the # "handler" in those cases is always just "xmodule_handler". nr_tx_name = "{}.{}".format(instance.__class__.__name__, handler) nr_tx_name += "/{}".format(suffix) if (suffix and handler == "xmodule_handler") else "" newrelic.agent.set_transaction_name(nr_tx_name, group="Python/XBlock/Handler") tracking_context_name = 'module_callback_handler' req = django_to_webob_request(request) try: with tracker.get_tracker().context(tracking_context_name, tracking_context): resp = instance.handle(handler, req, suffix) if suffix == 'problem_check' \ and course \ and getattr(course, 'entrance_exam_enabled', False) \ and getattr(instance, 'in_entrance_exam', False): ee_data = {'entrance_exam_passed': user_has_passed_entrance_exam(request, course)} resp = append_data_to_webob_response(resp, ee_data) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse({'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)
def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, user): """ Invoke an XBlock handler, either authenticated or not. """ location = unquote_slashes(usage_id) # Check parameters and fail fast if there's a problem if not Location.is_valid(location): raise Http404("Invalid location") # Check submitted files files = request.FILES or {} error_msg = _check_files_limits(files) if error_msg: return HttpResponse(json.dumps({'success': error_msg})) try: descriptor = modulestore().get_instance(course_id, location) except ItemNotFoundError: log.warn( "Invalid location for course id {course_id}: {location}".format( course_id=course_id, location=location)) raise Http404 field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, user, descriptor) instance = get_module(user, request, location, field_data_cache, course_id, grade_bucket_type='ajax') if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. log.debug("No module %s for user %s -- access denied?", location, user) raise Http404 req = django_to_webob_request(request) try: resp = instance.handle(handler, req, suffix) except NoSuchHandlerError: log.exception("XBlock %s attempted to access missing handler %r", instance, handler) raise Http404 # If we can't find the module, respond with a 404 except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 # For XModule-specific errors, we log the error and respond with an error message except ProcessingError as err: log.warning("Module encountered an error while processing AJAX call", exc_info=True) return JsonResponse(object={'success': err.args[0]}, status=200) # If any other error occurred, re-raise it to trigger a 500 response except Exception: log.exception("error executing xblock handler") raise return webob_to_django_response(resp)