Esempio n. 1
0
def student_reputation(req):
    args = get_json_params(req, args=["id"])
    if isinstance(args, HttpResponse):
        return args
    (student_id, ), __ = args

    if req.user.student.pk != student_id:
        return response_403(
            req,
            msg=_("You don't have access to this resource."),
            logger_msg=(
                "Access to reputation of student {} from student {}.".format(
                    student_id, req.user.student.pk)),
            log=logger.warning,
        )

    try:
        student = Student.objects.get(pk=student_id)
    except Student.DoesNotExist:
        return response_400(
            req,
            msg=_("This student doesn't exist."),
            logger_msg=(
                "Tried to obtain student with pk {}".format(student_id)),
            log=logger.warning,
        )

    if student.reputation is None:
        student.reputation = Reputation.create(student)
        student.save()

    reputation, reputations = student.reputation.evaluate()

    data = {"reputation": reputation, "reputations": reputations}
    return JsonResponse(data, status=200)
Esempio n. 2
0
 def wrapper(req, *args, **kwargs):
     if not isinstance(req.user, User):
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from a non teacher user.".format(
                 req.path)),
             log=logger.warning,
         )
     if req.user.is_staff:
         return fct(req, *args, **kwargs)
     else:
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from a non teacher user.".format(
                 req.path)),
             log=logger.warning,
         )
Esempio n. 3
0
 def wrapper(req, *args, **kwargs):
     if not isinstance(req.user, User) or hasattr(req.user, "student"):
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from student {}.".format(
                 req.path, req.user)),
             log=logger.warning,
         )
     return fct(req, *args, **kwargs)
Esempio n. 4
0
 def wrapper(req, *args, **kwargs):
     if not Teacher.objects.filter(user=req.user).exists():
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from a non teacher user.".format(
                 req.path)),
             log=logger.warning,
         )
     return fct(req, *args, **kwargs)
Esempio n. 5
0
 def wrapper(req, *args, **kwargs):
     if not isinstance(req.user, User):
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from a non teacher user.".format(
                 req.path)),
             log=logger.warning,
         )
     try:
         teacher = Teacher.objects.get(user=req.user)
         return fct(req, *args, teacher=teacher, **kwargs)
     except Teacher.DoesNotExist:
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from a non teacher user.".format(
                 req.path)),
             log=logger.warning,
         )
Esempio n. 6
0
 def wrapper(req, *args, **kwargs):
     if not isinstance(req.user, User):
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from a non student user.".format(
                 req.path)),
             log=logger.warning,
         )
     try:
         student = Student.objects.get(student=req.user)
         return fct(req, *args, student=student, **kwargs)
     except Student.DoesNotExist:
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} with a non student user.".format(
                 req.path)),
             log=logger.warning,
         )
Esempio n. 7
0
    def wrapper(req, *args, **kwargs):
        if not hasattr(req.user, "student"):
            return response_403(
                req,
                msg=_("You don't have access to this resource."),
                logger_msg=("Access to {} with a non student user.".format(
                    req.path)),
                log=logger.warning,
            )

        return fct(req, *args, **kwargs)
Esempio n. 8
0
 def wrapper(req, *args, **kwargs):
     if (not isinstance(req.user, User)
             or Student.objects.filter(student=req.user).exists()):
         return response_403(
             req,
             msg=_("You don't have access to this resource."),
             logger_msg=("Access to {} from student {}.".format(
                 req.path, req.user)),
             log=logger.warning,
         )
     return fct(req, *args, **kwargs)
Esempio n. 9
0
def verify_teacher(req, type_):
    """
    Verifies if the teacher exists , returning it if that's the case and an
    error response if not.

    Parameters
    ----------
    req : HttpRequest
        Request
    type_ : str
        Which use type it the quality for

    Returns
    -------
    Either
        Quality
            Quality corresponding to the group
        HttpResponse
            400 or 403 error response
    """
    try:
        teacher = Teacher.objects.get(user=req.user)
    except (Teacher.DoesNotExist, AttributeError):
        return response_403(
            req,
            msg=_("You don't have access to this resource."),
            logger_msg=("Access to {} from user {}.".format(
                req.path,
                req.user.pk if hasattr(req, "user")
                and isinstance(req.user, User) else "anonymous",
            )),
            log=logger.warning,
        )

    if teacher.quality is None:
        quality_type = QualityType.objects.get(type="teacher")
        try:
            quality_use_type = QualityUseType.objects.get(type=type_)
        except QualityUseType.DoesNotExist:
            return response_400(
                req,
                msg=_("Some parameters are wrong"),
                logger_msg=("An access to {} was tried with the wrong ".format(
                    req.path) + "quality use type{}.".format(type_)),
                log=logger.warning,
            )

        teacher.quality = Quality.objects.create(
            quality_type=quality_type, quality_use_type=quality_use_type)
        teacher.save()

    return teacher.quality
Esempio n. 10
0
def test_response_403__default_message(rf, caplog):
    logger = logging.getLogger("test")
    req = rf.get("/test")
    req.user = AnonymousUser()

    resp = response_403(req,
                        msg="test1",
                        log=logger.warning,
                        use_template=True)

    assert isinstance(resp, TemplateResponse)
    assert resp.status_code == 403
    assert len(caplog.records) == 1
    assert (caplog.records[0].message ==
            "403 error for user AnonymousUser on path /test.")
Esempio n. 11
0
def test_response_403(rf, caplog):
    logger = logging.getLogger("test")
    req = rf.get("/test")

    resp = response_403(
        req,
        msg="test1",
        logger_msg="test2",
        log=logger.warning,
        use_template=True,
    )

    assert isinstance(resp, TemplateResponse)
    assert resp.status_code == 403
    assert len(caplog.records) == 1
    assert caplog.records[0].message == "test2"
Esempio n. 12
0
    def wrapper(req, *args, **kwargs):
        group_hash = kwargs.get("group_hash", None)
        assignment_hash = kwargs.get("assignment_hash", None)
        return_assignment = assignment_hash is not None

        if group_hash is None and assignment_hash is None:
            return response_403(
                req,
                msg=_("You don't have access to this resource."),
                logger_msg=(
                    "Access to {} without a group or assignment hash.".format(
                        req.path)),
                log=logger.warning,
            )

        try:
            teacher = Teacher.objects.get(user=req.user)
        except Teacher.DoesNotExist:
            return response_403(
                req,
                msg=_("You don't have access to this resource."),
                logger_msg=("Access to {} with a non teacher user.".format(
                    req.path)),
                log=logger.warning,
            )

        if assignment_hash is not None:
            assignment = StudentGroupAssignment.get(assignment_hash)
            if assignment is None:
                return response_400(
                    req,
                    msg=_('There is no assignment with hash "{}".'.format(
                        assignment_hash)),
                    logger_msg=(
                        "Access to {} with a invalid assignment hash.".format(
                            req.path)),
                    log=logger.warning,
                )
            group = assignment.group
        else:
            group = StudentGroup.get(group_hash)
            if group is None:
                return response_400(
                    req,
                    msg=_('There is no group with hash "{}".'.format(
                        group_hash)),
                    logger_msg=(
                        "Access to {} with a invalid group hash.".format(
                            req.path)),
                    log=logger.warning,
                )

        if teacher not in group.teacher.all():
            return response_403(
                req,
                msg=_("You don't have access to this resource. You must be "
                      "registered as a teacher for the group {}.".format(
                          group.name)),
                logger_msg=(
                    "Invalid access to group {} from teacher {}.".format(
                        group.pk, teacher.pk)),
                log=logger.warning,
            )

        if return_assignment:
            return fct(req,
                       *args,
                       teacher=teacher,
                       group=group,
                       assignment=assignment,
                       **kwargs)
        else:
            return fct(req, *args, teacher=teacher, group=group, **kwargs)
Esempio n. 13
0
def verify_assignment(req, type_, assignment_pk):
    """
    Verifies if the assignment exists and the user is allowed to change the
    assignment, returning it if that's the case and an error response if not.

    Parameters
    ----------
    req : HttpRequest
        Request
    type_ : str
        Which use type it the quality for
    assignment_pk : int
        Primary key for the assignment

    Returns
    -------
    Either
        Quality
            Quality corresponding to the assignment
        HttpResponse
            400 or 403 error response
    """
    try:
        assignment = StudentGroupAssignment.objects.get(pk=assignment_pk)
    except StudentGroupAssignment.DoesNotExist:
        return response_400(
            req,
            msg=_("Some parameters are wrong"),
            logger_msg=(
                "An access to {} was tried with the wrong ".format(req.path) +
                "assignment primary key {}.".format(assignment_pk)),
            log=logger.warning,
        )

    try:
        teacher = Teacher.objects.get(user=req.user)
    except Teacher.DoesNotExist:
        return response_403(
            req,
            msg=_("You don't have access to this resource."),
            logger_msg=("Access to {} from user {}.".format(
                req.path, req.user.pk)),
            log=logger.warning,
        )

    if not assignment.group.teacher.filter(pk=teacher.pk).exists():
        return response_403(
            req,
            msg=_("You don't have access to this resource."),
            logger_msg=("Access to {} from user {}.".format(
                req.path, req.user.pk)),
            log=logger.warning,
        )

    if assignment.quality is None:
        quality_type = QualityType.objects.get(type="studentgroupassignment")
        try:
            quality_use_type = QualityUseType.objects.get(type=type_)
        except QualityUseType.DoesNotExist:
            return response_400(
                req,
                msg=_("Some parameters are wrong"),
                logger_msg=("An access to {} was tried with the wrong ".format(
                    req.path) + "quality use type{}.".format(type_)),
                log=logger.warning,
            )

        assignment.quality = Quality.objects.create(
            quality_type=quality_type, quality_use_type=quality_use_type)
        assignment.save()

    return assignment.quality
Esempio n. 14
0
def request_gradebook(req, teacher):
    """
    Request the generation of a gradebook. An response containing the task id
    is returned so the client can poll the server for the result until it's
    ready.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters
                group_id: int
                    Primary key of the group for which the gradebook is wanted
            optional parameters:
                assignment_id: int (default : None)
                    Primary key of the assignment for which the gradebook is
                    wanted
    teacher : Teacher
        Teacher instance returned by `teacher_required`

    Returns
    -------
    Either
        JsonResponse with json data
            Response 201 (created) with json data if computation run
            asynchronously
                {
                    task_id: str
                        Id corresponding to the celery task for use in polling
                }
            Response 200 with json data if computation run synchronously
                Either
                    If group gradebook wanted
                        {
                            assignments: List[str]
                                Assignment identifier
                            school_id_needed: bool
                                If a school id is needed
                            results: [{
                                school_id: Optional[str]
                                    School id if needed
                                email: str
                                    Student email
                                assignments: [{
                                    n_completed: int
                                        Number of completed questions
                                    n_correct: int
                                        Number of correct questions
                                }]
                            }]
                        }
                    If assignment gradebook wanted
                        {
                            questions: List[str]
                                Question title
                            school_id_needed: bool
                                If a school id is needed
                            results: [{
                                school_id: Optional[str]
                                    School id if needed
                                email: str
                                    Student email
                                questions: List[float]
                                    Grade for each question
                            }]
                        }
        HttpResponse
            Error response
    """
    args = get_json_params(req, args=["group_id"], opt_args=["assignment_id"])
    if isinstance(args, HttpResponse):
        return args
    (group_pk, ), (assignment_pk, ) = args

    try:
        group = StudentGroup.objects.get(pk=group_pk)
    except StudentGroup.DoesNotExist:
        return response_400(
            req,
            msg=translate("The group doesn't exist."),
            logger_msg=("Access to {} with an invalid group {}.".format(
                req.path, group_pk)),
            log=logger.warning,
        )

    if teacher not in group.teacher.all():
        return response_403(
            req,
            msg=translate(
                "You don't have access to this resource. You must be "
                "registered as a teacher for the group."),
            logger_msg=(
                "Unauthorized access to group {} from teacher {}.".format(
                    group.pk, teacher.pk)),
            log=logger.warning,
        )

    if assignment_pk is not None:
        try:
            assignment = StudentGroupAssignment.objects.get(pk=assignment_pk)
        except StudentGroupAssignment.DoesNotExist:
            return response_400(
                req,
                msg=translate("The group or assignment don't exist."),
                logger_msg=(
                    "Access to {} with an invalid assignment {}.".format(
                        req.path, assignment_pk)),
                log=logger.warning,
            )

    result = compute_gradebook_async(group_pk, assignment_pk)

    if assignment_pk is None:
        description = format_html("gradebook for group <strong>{}</strong>",
                                  group.name)
    else:
        description = "gradebook for assignment {} and group {}".format(
            assignment.assignment.identifier, group.name)

    if isinstance(result, AsyncResult):
        task = RunningTask.objects.create(id=result.id,
                                          description=description,
                                          teacher=teacher)
        data = {
            "id": task.id,
            "description": task.description,
            "completed": False,
            "datetime": task.datetime.strftime("%Y-%m-%d %H:%M:%S.%f"),
        }
        return JsonResponse(data, status=201)
    else:
        return download_gradebook(req, results=result)
Esempio n. 15
0
def validate_group_data(req):
    """
    Checks if the request is a well formed json, contains the data to get group
    information and the group exists.  The group is obtained with either a
    field `group_name` or `group_link`.

    Returns
    -------
    Either:
    StudentGroup
        Student and group corresponding for the request
    HttpResponse
        Response corresponding to the obtained error
    """
    try:
        data = json.loads(req.body)
    except ValueError:
        return response_400(
            req,
            msg=_("Wrong data type was sent."),
            logger_msg=("The sent data wasn't in a valid JSON format."),
            log=logger.warning,
        )

    try:
        group_name = data["group_name"].strip()
        group_link = None
    except KeyError:
        try:
            group_link = data["group_link"].strip()
            group_name = None
        except KeyError:
            return response_400(
                req,
                msg=_("There are missing parameters."),
                logger_msg=(
                    "The arguments 'group_name' or 'group_link' were missing."
                ),
                log=logger.warning,
            )

    if group_name is None:
        try:
            hash_ = re.match(
                rf"^{req.scheme}://[^/]+/\w*/live/signup/form/([0-9A-Za-z=_-]+)$",  # noqa E501
                group_link,
            ).group(1)
        except AttributeError:
            return response_400(
                req,
                msg=_("There pas an error parsing the sent link. Please try "
                      "again."),
                logger_msg=(
                    "A student signup was tried with the link %s.",
                    group_link,
                ),
                log=logger.warning,
            )
        group = StudentGroup.get(hash_)
        if group is None:
            return response_400(
                req,
                msg=_("There doesn't seem to be any group corresponding to"
                      "the link. Please try again."),
                logger_msg=(
                    "There is no group corresponding to the hash %s.",
                    hash_,
                ),
                log=logger.warning,
            )

    else:
        try:
            group = StudentGroup.objects.get(name=group_name)
        except StudentGroup.DoesNotExist:
            return response_403(
                req,
                msg=_("The group doesn't seem to exist. Refresh the page "
                      "and try again"),
                logger_msg=(
                    "There is no group corresponding to the name %s.",
                    group_name,
                ),
                log=logger.warning,
            )

    return group
Esempio n. 16
0
def login_student(req, token=None):
    """
    Logs in the user depending on the given token and req.user. For lti users,
    the student corresponding to the email is used, creating it if necessary.

    Parameters
    ----------
    req : HttpRequest
        Request with a logged in user or not
    token : Optional[str] (default : None)
        Student token

    Parameters
    ----------
    Either
        Student
            Logged in student
        HttpResponse
            Error response
    bool
        If this is a new student
    """

    if token is None:
        if not isinstance(req.user, User):
            return (
                response_403(
                    req,
                    msg=_("You must be a logged in student to access this "
                          "resource."),
                    logger_msg=(
                        "Student index page accessed without a token or being "
                        "logged in."),
                    log=logger.warning,
                ),
                None,
            )

        user = req.user
        username, password = get_student_username_and_password(user.email)

        is_lti = user.username != username

    else:
        user, is_lti = authenticate_student(req, token)
        if isinstance(user, HttpResponse):
            return user, None

        if is_lti:
            username, password = get_student_username_and_password(user.email)

    if is_lti:
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            user = User.objects.create_user(username=username,
                                            password=password,
                                            email=user.email)

    try:
        student = Student.objects.get(student=user)
        new_student = False
    except Student.DoesNotExist:
        if is_lti:
            return (
                response_403(
                    req,
                    msg=_("You must be a logged in student to access this "
                          "resource."),
                    logger_msg=(
                        "Student index page accessed without a token or being "
                        "logged in."),
                    log=logger.warning,
                ),
                None,
            )
        student = Student.objects.create(student=user)
        new_student = True

    if not user.is_active or new_student:
        user.is_active = True
        user.save()
        new_student = True

    logout(req)
    login(req, user, backend="peerinst.backends.CustomPermissionsBackend")

    return student, new_student