Example #1
0
    def _get_rest(course: models.Course) -> t.Mapping[str, t.Any]:
        if helpers.extended_requested():
            snippets: t.Sequence[models.CourseSnippet] = []
            if (current_user.has_permission(GPerm.can_use_snippets)
                    and current_user.has_permission(
                        CPerm.can_view_course_snippets, course_id=course.id)):
                snippets = course.snippets

            return {
                'assignments': course.get_all_visible_assignments(),
                'group_sets': course.group_sets,
                'snippets': snippets,
                **course.__to_json__(),
            }
        return course.__to_json__()
Example #2
0
def get_feedback_from_submission(submission_id: int) -> JSONResponse[Feedback]:
    """Get all feedback for a submission

    .. :quickref: Submission; Get all (linter, user and general) feedback.

    :>json general: The general feedback given on this submission.
    :>json user: A mapping between file id and a mapping that is between line
        and feedback. So for example: ``{5: {0: 'Nice job!'}}`` means that file
        with ``id`` 5 has feedback on line 0.
    :>json linter: A mapping that is almost the same the user feedback mapping,
        only the final key is not a string but a list of tuples where the first
        item is the linter code and the second item is a
        :class:`.models.LinterComment`.
    :>json authors: The authors of the user feedback. In the example above the
        author of the feedback 'Nice job!' would be at ``{5: {0: $USER}}``.
    """
    work = helpers.get_or_404(models.Work, submission_id)
    auth.ensure_can_see_grade(work)
    can_view_author = current_user.has_permission(CPerm.can_see_assignee,
                                                  work.assignment.course_id)

    # The authors dict gets filled if `can_view_authors` is set to `True`. This
    # value is used so that `mypy` wont complain about indexing null values.
    authors: t.MutableMapping[int, t.MutableMapping[
        int, models.User]] = defaultdict(dict)
    res: Feedback = {
        'general': work.comment or '',
        'user': defaultdict(dict),
        'linter': defaultdict(lambda: defaultdict(list)),
        'authors': authors if can_view_author else None,
    }

    comments = models.Comment.query.filter(
        t.cast(DbColumn[models.File],
               models.Comment.file).has(work=work), ).order_by(
                   t.cast(DbColumn[int], models.Comment.file_id).asc(),
                   t.cast(DbColumn[int], models.Comment.line).asc(),
               )

    for comment in comments:
        res['user'][comment.file_id][comment.line] = comment.comment
        if can_view_author:
            authors[comment.file_id][comment.line] = comment.user

    linter_comments = models.LinterComment.query.filter(
        t.cast(DbColumn[models.File],
               models.LinterComment.file).has(work=work)).order_by(
                   t.cast(DbColumn[int], models.LinterComment.file_id).asc(),
                   t.cast(DbColumn[int], models.LinterComment.line).asc(),
               )
    if features.has_feature(features.Feature.LINTERS):
        for lcomment in linter_comments:
            res['linter'][lcomment.file_id][lcomment.line].append(
                (lcomment.linter_code, lcomment))

    return jsonify(res)
Example #3
0
def get_all_works_for_assignment(
    assignment_id: int
) -> t.Union[JSONResponse[WorkList], ExtendedJSONResponse[WorkList]]:
    """Return all :class:`.models.Work` objects for the given
    :class:`.models.Assignment`.

    .. :quickref: Assignment; Get all works for an assignment.

    :qparam boolean extended: Whether to get extended or normal
        :class:`.models.Work` objects. The default value is ``false``, you can
        enable extended by passing ``true``, ``1`` or an empty string.

    :param int assignment_id: The id of the assignment
    :returns: A response containing the JSON serialized submissions.

    :raises PermissionException: If there is no logged in user. (NOT_LOGGED_IN)
    :raises PermissionException: If the assignment is hidden and the user is
                                 not allowed to view it. (INCORRECT_PERMISSION)
    """
    assignment = helpers.get_or_404(models.Assignment, assignment_id)

    auth.ensure_permission('can_see_assignments', assignment.course_id)

    if assignment.is_hidden:
        auth.ensure_permission(
            'can_see_hidden_assignments', assignment.course_id
        )

    obj = models.Work.query.filter_by(
        assignment_id=assignment_id,
    ).options(joinedload(
        models.Work.selected_items,
    )).order_by(t.cast(t.Any, models.Work.created_at).desc())

    if not current_user.has_permission(
        'can_see_others_work', course_id=assignment.course_id
    ):
        obj = obj.filter_by(user_id=current_user.id)

    extended = request.args.get('extended', 'false').lower()

    if extended in {'true', '1', ''}:
        obj = obj.options(undefer(models.Work.comment))
        return extended_jsonify(
            obj.all(),
            use_extended=lambda obj: isinstance(obj, models.Work),
        )
    else:
        return jsonify(obj.all())
Example #4
0
def get_all_assignments() -> JSONResponse[t.Sequence[models.Assignment]]:
    """Get all the :class:`.models.Assignment` objects that the current user
    can see.

    .. :quickref: Assignment; Get all assignments.

    :returns: An array of :py:class:`.models.Assignment` items encoded in JSON.

    :raises PermissionException: If there is no logged in user. (NOT_LOGGED_IN)
    """
    perm_can_see: models.Permission = models.Permission.query.filter_by(
        name='can_see_assignments'
    ).first()
    courses = []

    for course_role in current_user.courses.values():
        if course_role.has_permission(perm_can_see):
            courses.append(course_role.course_id)

    res = []

    if courses:
        for assignment, has_linter in db.session.query(
            models.Assignment,
            t.cast(models.DbColumn[str],
                   models.AssignmentLinter.id).isnot(None)
        ).filter(
            t.cast(
                models.DbColumn[int],
                models.Assignment.course_id,
            ).in_(courses)
        ).join(
            models.AssignmentLinter,
            sql.expression.and_(
                models.Assignment.id == models.AssignmentLinter.assignment_id,
                models.AssignmentLinter.name == 'MixedWhitespace'
            ),
            isouter=True
        ).all():
            has_perm = current_user.has_permission(
                'can_see_hidden_assignments', assignment.course_id
            )
            assignment.whitespace_linter_exists = has_linter
            if ((not assignment.is_hidden) or has_perm):
                res.append(assignment)

    return jsonify(res)