示例#1
0
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)
示例#2
0
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)