def wims_class(request: HttpRequest, wims_pk: int) -> HttpResponse: """Redirect the client to the WIMS server corresponding to <pk>. Will retrieve/create the right WIMS' class/user according to informations in request.POST. Raises: - Http404 if no LMS corresponding to request.POST["tool_consumer_instance_guid"] has been found in the database. - PermissionDenied if the class corresponding to request.POST['context_id'] does not exists and roles in request.POST['context_id'] are not one of settings.ROLES_ALLOWED_CREATE_WIMS_CLASS. Returns: - HttpResponseRedirect redirecting the user to WIMS, logged in his WIMS' class. - HttpResponse(status=502) if an error occured while communicating with the WIMS server. - HttpResponse(status=504) if the WIMS server could not be joined.""" if request.method == "GET": uri = request.build_absolute_uri() return HttpResponseNotAllowed(["POST"], GET_ERROR_MSG % (uri[:-1], uri)) if request.method != "POST": return HttpResponseNotAllowed( ["POST"], "405 Method Not Allowed: '%s'" % request.method) try: parameters = parse_parameters(request.POST) logger.info("Request received from '%s'" % request.META.get('HTTP_REFERER', "Unknown")) check_parameters(parameters) check_custom_parameters(parameters) is_valid_request(request) except BadRequestException as e: logger.info(str(e)) return HttpResponseBadRequest(str(e)) # Retrieve the WIMS server try: wims_srv = WIMS.objects.get(pk=wims_pk) except WIMS.DoesNotExist: raise Http404("Unknown WIMS server of id '%d'" % wims_pk) # Retrieve the LMS try: lms = LMS.objects.get(guid=parameters["tool_consumer_instance_guid"]) except LMS.DoesNotExist: raise Http404("No LMS found with guid '%s'" % parameters["tool_consumer_instance_guid"]) wapi = wimsapi.WimsAPI(wims_srv.url, wims_srv.ident, wims_srv.passwd) try: # Check that the WIMS server is available bol, response = wapi.checkident(verbose=True) if not bol: raise wimsapi.WimsAPIError(response['message']) # Check whether the class already exists, creating it otherwise wclass_db, wclass = get_or_create_class(lms, wims_srv, wapi, parameters) # Check whether the user already exists, creating it otherwise user_db, user = get_or_create_user(wclass_db, wclass, parameters) # Trying to authenticate the user on the WIMS server bol, response = wapi.authuser(wclass.qclass, wclass.rclass, user.quser) if not bol: # pragma: no cover raise wimsapi.WimsAPIError(response['message']) url = response["home_url"] + ("&lang=%s" % wclass.lang) except wimsapi.WimsAPIError as e: # WIMS server responded with ERROR logger.info(str(e)) return HttpResponse(str(e), status=502) except requests.RequestException: logger.exception("Could not join the WIMS server '%s'" % wims_srv.url) return HttpResponse("Could not join the WIMS server '%s'" % wims_srv.url, status=504) return redirect(url)
def wims_exam(request: HttpRequest, wims_pk: int, exam_pk: int) -> HttpResponse: """Redirect the client to the WIMS server corresponding to <wims_pk> and exam <exam_pk>. Will retrieve/create the right WIMS' class/user according to informations in request.POST. Raises: - Http404 if no LMS corresponding to request.POST["tool_consumer_instance_guid"] has been found in the database. - PermissionDenied if the class corresponding to request.POST['context_id'] does not exists and roles in request.POST['context_id'] are not one of settings.ROLES_ALLOWED_CREATE_WIMS_CLASS. Returns: - HttpResponseRedirect redirecting the user to WIMS, logged in his WIMS' class. - HttpResponse(status=502) if an error occured while communicating with the WIMS. - HttpResponse(status=504) if the WIMS server could not be joined.""" if request.method == "GET": uri = request.build_absolute_uri() return HttpResponseNotAllowed(["POST"], GET_ERROR_MSG % (uri[:-1], uri)) if request.method != "POST": return HttpResponseNotAllowed( ["POST"], "405 Method Not Allowed: '%s'" % request.method) try: parameters = parse_parameters(request.POST) logger.info("Request received from '%s'" % request.META.get('HTTP_REFERER', "Unknown")) check_parameters(parameters) check_custom_parameters(parameters) is_valid_request(request) except BadRequestException as e: logger.info(str(e)) return HttpResponseBadRequest(str(e)) # Retrieve the WIMS server try: wims_srv = WIMS.objects.get(pk=wims_pk) except WIMS.DoesNotExist: raise Http404("Unknown WIMS server of id '%d'" % wims_pk) # Retrieve the LMS try: lms = LMS.objects.get(guid=parameters["tool_consumer_instance_guid"]) except LMS.DoesNotExist: raise Http404("No LMS found with guid '%s'" % parameters["tool_consumer_instance_guid"]) wapi = wimsapi.WimsAPI(wims_srv.url, wims_srv.ident, wims_srv.passwd) try: # Check that the WIMS server is available bol, response = wapi.checkident(verbose=True) if not bol: raise wimsapi.WimsAPIError(response['message']) # Get the class wclass_db = WimsClass.objects.get(wims=wims_srv, lms=lms, lms_guid=parameters['context_id']) try: wclass = wimsapi.Class.get(wims_srv.url, wims_srv.ident, wims_srv.passwd, wclass_db.qclass, wims_srv.rclass, timeout=settings.WIMSAPI_TIMEOUT) except wimsapi.WimsAPIError as e: if "not existing" in str( e): # Class was deleted on the WIMS server qclass = wclass_db.qclass logger.info(( "Deleting class (id : %d - wims id : %s - lms id : %s) as it was" "deleted from the WIMS server") % (wclass_db.id, str( wclass_db.qclass), str(wclass_db.lms_guid))) wclass_db.delete() return HttpResponseNotFound(( "Class of ID %s could not be found on the WIMS server. Maybe it has been " "deleted from the WIMS server. Use this LTI link on your LMS to create a new " "WIMS class: %s") % (qclass, request.build_absolute_uri( reverse("lti:wims_class", args=[wims_pk])))) raise # Unknown error (pragma: no cover) # Check whether the user already exists, creating it otherwise user_db, user = get_or_create_user(wclass_db, wclass, parameters) # Check whether the exam already exists, creating it otherwise exam_db, exam = get_exam(wclass_db, wclass, exam_pk, parameters) if int(exam.exammode) not in [1, 2]: # not active or expired return HttpResponseForbidden( "This exam (%s) is currently unavailable (%s)" % (str(exam.qexam), MODE[int(exam.exammode)])) # Storing the URL and ID to send the grade back to the LMS try: gl = GradeLinkExam.objects.get(user=user_db, activity=exam_db) gl.sourcedid = parameters["lis_result_sourcedid"] gl.url = parameters["lis_outcome_service_url"] gl.save() except GradeLinkExam.DoesNotExist: GradeLinkExam.objects.create( user=user_db, activity=exam_db, lms=lms, sourcedid=parameters["lis_result_sourcedid"], url=parameters["lis_outcome_service_url"]) # If user is a teacher, send all grade back to the LMS role = Role.parse_role_lti(parameters["roles"]) if is_teacher(role): GradeLinkExam.send_back_all(exam_db) # Trying to authenticate the user on the WIMS server bol, response = wapi.authuser(wclass.qclass, wclass.rclass, user.quser) if not bol: # pragma: no cover raise wimsapi.WimsAPIError(response['message']) params = ( "&lang=%s&module=adm%%2Fclass%%2Fexam&+job=student&+exam=%s" % (wclass.lang, str(exam.qexam))) url = response["home_url"] + params except WimsClass.DoesNotExist as e: logger.info(str(e)) return HttpResponseNotFound("Could not find class of id '%s'" % parameters['context_id']) except wimsapi.WimsAPIError as e: # WIMS server responded with ERROR logger.info(str(e)) return HttpResponse(str(e), status=502) except requests.RequestException: logger.exception("Could not join the WIMS server '%s'" % wims_srv.url) return HttpResponse("Could not join the WIMS server '%s'" % wims_srv.url, status=504) return redirect(url)