Example #1
0
def comment():
    act = request.args.get('act') or request.json.get('act')

    if request.method == 'POST':
        file_id = int(request.json.get('fileId', 0))
    else:  # it's a GET
        file_id = int(request.args.get('fileId', 0))

    file = SolutionFile.get_or_none(file_id)
    if file is None:
        return fail(404, f'No such file {file_id}.')

    solver_id = file.solution.solver.id
    if solver_id != current_user.id and not current_user.role.is_manager:
        return fail(403, "You aren't allowed to access this page.")

    if act == 'fetch':
        return jsonify(Comment.by_file(file_id))

    if (
        not webapp.config.get('USERS_COMMENTS', False)
        and not current_user.role.is_manager
    ):
        return fail(403, "You aren't allowed to access this page.")

    if act == 'delete':
        comment_id = int(request.args.get('commentId'))
        comment_ = Comment.get_or_none(Comment.id == comment_id)
        if (
            comment_.commenter.id != current_user.id
            and not current_user.role.is_manager
        ):
            return fail(403, "You aren't allowed to access this page.")
        if comment_ is not None:
            comment_.delete_instance()
        return jsonify({'success': 'true'})

    if act == 'create':
        kind = request.json.get('kind', '')
        comment_id, comment_text = None, None
        try:
            line_number = int(request.json.get('line', 0))
        except ValueError:
            line_number = 0
        if kind.lower() == 'id':
            comment_id = int(request.json.get('comment', 0))
        if kind.lower() == 'text':
            comment_text = request.json.get('comment', '')
        return comments._create_comment(
            current_user.id,
            file,
            kind,
            line_number,
            comment_text,
            comment_id,
        )

    return fail(400, f'Unknown or unset act value "{act}".')
Example #2
0
 def test_valid_solution(self, solution: Solution):
     solution_file = solution.solution_files.get()
     solution_file.code = VALID_CODE
     solution_file.save()
     tasks.run_linter_on_solution(solution.id)
     comments = tuple(Comment.by_solution(solution))
     assert not comments
Example #3
0
def comment():
    act = request.args.get('act') or request.json.get('act')

    if request.method == 'POST':
        solution_id = int(request.json.get('solutionId', 0))
    else:  # it's a GET
        solution_id = int(request.args.get('solutionId', 0))

    solution = Solution.get_or_none(Solution.id == solution_id)
    if solution is None:
        return fail(404, f'No such solution {solution_id}')

    solver_id = solution.solver.id
    if solver_id != current_user.id and not current_user.role.is_manager:
        return fail(401, "You aren't allowed to watch this page.")

    if act == 'fetch':
        return jsonify(Comment.get_solutions(solution_id))

    if act == 'delete':
        comment_id = int(request.args.get('commentId'))
        comment_ = Comment.get_or_none(Comment.id == comment_id)
        if comment_ is not None:
            comment_.delete_instance()
        return jsonify({'success': 'true'})

    if act == 'create':
        kind = request.json.get('kind', '')
        comment_id, comment_text = None, None
        try:
            line_number = int(request.json.get('line', 0))
        except ValueError:
            line_number = 0
        if kind.lower() == 'id':
            comment_id = int(request.json.get('comment', 0))
        if kind.lower() == 'text':
            comment_text = request.json.get('comment', '')
        return _create_comment(
            current_user.id,
            solution,
            kind,
            line_number,
            comment_text,
            comment_id,
        )

    return fail(400, f'Unknown or unset act value "{act}"')
Example #4
0
def comment(staff_user, solution):
    return Comment.create_comment(
        commenter=staff_user,
        file=solution.solution_files.get(),
        comment_text=CommentText.create_comment(text='very good!'),
        line_number=1,
        is_auto=False,
    )[0]
Example #5
0
 def test_pyflake_wont_execute_code(self, solution: Solution):
     solution_file = solution.solution_files.get()
     solution_file.code = self.execute_script
     solution_file.save()
     tasks.run_linter_on_solution(solution.id)
     comments = tuple(Comment.by_solution(solution))
     assert not os.listdir(self.test_directory)
     assert len(comments) == 2
     exec(compile(self.execute_script, '', 'exec'))  # noqa S102
     assert os.listdir(self.test_directory) == ['some-file']
Example #6
0
 def test_invalid_solution(self, solution: Solution):
     solution_file = solution.solution_files.get()
     solution_file.path = 'sql.sql'
     solution_file.code = INVALID_CODE
     solution_file.save()
     tasks.run_linter_on_solution(solution.id)
     comments = tuple(Comment.by_solution(solution))
     assert comments
     assert len(comments) == 1
     assert comments[0].comment.text == INVALID_CODE_MESSAGE
Example #7
0
def delete():
    comment_id = int(request.args.get('commentId'))
    comment_ = Comment.get_or_none(Comment.id == comment_id)
    if (comment_.commenter.id != current_user.id
            and not current_user.role.is_manager):
        raise ForbiddenPermission(
            "You aren't allowed to access this page.",
            403,
        )
    if comment_ is not None:
        comment_.delete_instance()
Example #8
0
 def test_invalid_solution(self, solution: Solution):
     solution_file = solution.solution_files.get()
     solution_file.path = 'index.html'
     solution_file.code = INVALID_CODE
     solution_file.save()
     tasks.run_linter_on_solution(solution.id)
     comments = tuple(Comment.by_solution(solution))
     assert comments
     assert len(comments) == 3
     comment_texts = {comment.comment.text for comment in comments}
     assert comment_texts == INVALID_CODE_MESSAGES
Example #9
0
def _create_comment(
        user_id: int,
        file: SolutionFile,
        kind: str,
        line_number: int,
        comment_text: Optional[str] = None,  # set when kind == text
        comment_id: Optional[int] = None,  # set when kind == id
):
    user = User.get_or_none(User.id == user_id)
    if user is None:
        # should never happen, we checked session_id == solver_id
        return fail(404, 'No such user.')

    if (not kind) or (kind not in ('id', 'text')):
        return fail(400, 'Invalid kind.')

    if line_number <= 0:
        return fail(422, f'Invalid line number: {line_number}.')

    if kind == 'id':
        new_comment_id = comment_id
    elif kind == 'text':
        if not comment_text:
            return fail(422, 'Empty comments are not allowed.')
        new_comment_id = CommentText.create_comment(text=comment_text).id
    else:
        # should never happend, kind was checked before
        return fail(400, 'Invalid kind.')

    solutions.notify_comment_after_check(user, file.solution)

    comment_ = Comment.create(
        commenter=user,
        line_number=line_number,
        comment=new_comment_id,
        file=file,
    )

    return jsonify({
        'success': 'true',
        'text': comment_.comment.text,
        'author_name': user.fullname,
        'author_role': user.role.id,
        'is_auto': False,
        'id': comment_.id,
        'line_number': line_number,
    })
Example #10
0
 def test_invalid_solution(self, solution: Solution):
     solution_file = solution.solution_files.get()
     solution_file.code = INVALID_CODE
     solution_file.save()
     tasks.run_linter_on_solution(solution.id)
     comments = tuple(Comment.by_solution(solution))
     assert comments
     assert len(comments) == 1
     comment = comments[0].comment
     assert comment.text == INVALID_CODE_MESSAGE
     assert comment.flake8_key == INVALID_CODE_KEY
     user_notifications = notifications.get(user=solution.solver)
     assert len(user_notifications) == 1
     assert user_notifications
     subject = user_notifications[0].message
     assert solution.exercise.subject in subject
     assert '1' in subject
Example #11
0
File: views.py Project: ry-v1/lms
def comment():
    act = request.args.get('act') or request.json.get('act')

    if request.method == 'POST':
        file_id = int(request.json.get('fileId', 0))
    else:  # it's a GET
        file_id = int(request.args.get('fileId', 0))

    file = SolutionFile.get_or_none(file_id)
    if file is None:
        return fail(404, f'No such file {file_id}.')

    solver_id = file.solution.solver.id
    if solver_id != current_user.id and not current_user.role.is_manager:
        return fail(403, "You aren't allowed to access this page.")

    if act == 'fetch':
        return jsonify(Comment.by_file(file_id))

    if (not webapp.config.get('USERS_COMMENTS', False)
            and not current_user.role.is_manager):
        return fail(403, "You aren't allowed to access this page.")

    if act == 'delete':
        return try_or_fail(comments.delete)

    if act == 'create':
        user = User.get_or_none(User.id == current_user.id)
        try:
            comment_ = comments.create(file=file, user=user)
        except LmsError as e:
            error_message, status_code = e.args
            return fail(status_code, error_message)

        return jsonify({
            'success': 'true',
            'text': comment_.comment.text,
            'is_auto': False,
            'author_name': user.fullname,
            'author_role': user.role.id,
            'id': comment_.id,
            'line_number': comment_.line_number,
        })

    return fail(400, f'Unknown or unset act value "{act}".')
Example #12
0
    def test_next_exercise_with_cleanest_code(
        self,
        comment: Comment,
        staff_user: User,
    ):
        student_user: User = conftest.create_student_user(index=1)
        first_solution = comment.solution
        comment_text = comment.comment
        second_solution = conftest.create_solution(comment.solution.exercise,
                                                   student_user)

        # comment exists on first solution - second one should be the first
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == second_solution.id

        # delete the comment should give us back the first solution
        Comment.delete_by_id(comment.id)
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == first_solution.id

        # if second_solution has comments we should get first solution
        Comment.create_comment(
            commenter=staff_user,
            line_number=1,
            comment_text=comment_text,
            file=second_solution.solution_files.get(),
            is_auto=False,
        )
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == first_solution.id

        # both have comments - the first one should be the first solution
        Comment.create_comment(
            commenter=staff_user,
            line_number=1,
            comment_text=comment_text,
            file=first_solution.solution_files.get(),
            is_auto=False,
        )
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == first_solution.id
Example #13
0
def _create_comment(
        user: User,
        file: SolutionFile,
        kind: str,
        line_number: int,
        comment_text: Optional[str] = None,  # set when kind == text
        comment_id: Optional[int] = None,  # set when kind == id
):
    if user is None:
        # should never happen, we checked session_id == solver_id
        raise ResourceNotFound('No such user.', 404)

    if (not kind) or (kind not in ('id', 'text')):
        raise NotValidRequest('Invalid kind.', 400)

    if line_number <= 0:
        raise UnprocessableRequest(f'Invalid line number: {line_number}.', 422)

    if kind == 'id':
        new_comment_id = comment_id
    elif kind == 'text':
        if not comment_text:
            raise UnprocessableRequest('Empty comments are not allowed.', 422)
        new_comment_id = CommentText.create_comment(text=comment_text).id
    else:
        # should never happend, kind was checked before
        raise NotValidRequest('Invalid kind.', 400)

    solutions.notify_comment_after_check(user, file.solution)

    return Comment.create(
        commenter=user,
        line_number=line_number,
        comment=new_comment_id,
        file=file,
    )