Ejemplo n.º 1
0
 def test_password_hashed_on_mmultiple_saves(self, staff_user: User):
     new_password = '******'  # noqa S105
     staff_user.password = new_password
     staff_user.save()
     staff_user.save()
     self.assert_password(staff_user, new_password)
     staff_user.save()
     self.assert_password(staff_user, new_password)
Ejemplo n.º 2
0
def recover_password_check(user: User, token: str):
    form = RecoverPassForm()
    if not form.validate_on_submit():
        return render_template(
            'recover-password.html', form=form, id=user.id, token=token,
        )
    user.password = form.password.data
    user.save()
    return redirect(url_for(
        'login', login_message=(
            _('Your password has successfully changed'),
        ),
    ))
Ejemplo n.º 3
0
def upload_page():
    user_id = current_user.id
    user = User.get_or_none(User.id == user_id)  # should never happen
    if user is None:
        return fail(404, 'User not found')
    if request.content_length > MAX_REQUEST_SIZE:
        return fail(
            413,
            f'File is too big. {MAX_REQUEST_SIZE // 1000000}MB allowed',
        )

    file: Optional[FileStorage] = request.files.get('file')
    if file is None:
        return fail(422, 'No file was given')

    try:
        matches, misses = upload.new(user, file)
    except (AlreadyExists, BadUploadFile) as e:
        logger.debug(e)
        return fail(400, str(e))

    return jsonify({
        'exercise_matches': matches,
        'exercise_misses': misses,
    })
Ejemplo n.º 4
0
def upload_page(course_id: int):
    user_id = current_user.id
    user = User.get_or_none(User.id == user_id)  # should never happen
    if user is None:
        return fail(404, 'User not found.')
    if request.content_length > MAX_UPLOAD_SIZE:
        return fail(
            413, f'File is too big. {MAX_UPLOAD_SIZE // 1000000}MB allowed.',
        )

    file: Optional[FileStorage] = request.files.get('file')
    if file is None:
        return fail(422, 'No file was given.')

    try:
        matches, misses = upload.new(user.id, course_id, file)
    except UploadError as e:
        log.debug(e)
        return fail(400, str(e))
    except FileSizeError as e:
        log.debug(e)
        return fail(413, str(e))

    return jsonify({
        'exercise_matches': matches,
        'exercise_misses': misses,
    })
Ejemplo n.º 5
0
def note(user_id: int):
    act = request.args.get('act') or request.json.get('act')

    user = User.get_or_none(User.id == user_id)
    if user is None:
        return fail(404, f'No such user {user_id}.')

    if act == 'fetch':
        return jsonify(tuple(user.notes().dicts()))

    if not current_user.role.is_manager:
        return fail(403, "You aren't allowed to access this page.")

    if act == 'delete':
        note_id = int(request.args.get('noteId'))
        return try_or_fail(notes.delete, note_id=note_id)

    if act == 'create':
        note_text = request.args.get('note', '')
        note_exercise = request.args.get('exercise', '')
        privacy = request.args.get('privacy', '0')
        return try_or_fail(
            notes.create,
            user=user,
            note_text=note_text,
            note_exercise=note_exercise,
            privacy=privacy,
        )

    return fail(400, f'Unknown or unset act value "{act}".')
Ejemplo n.º 6
0
def UniqueEmailRequired(
        _form: 'RegisterForm',
        field: StringField,  # type: ignore # NOQA: F821
) -> None:
    email_exists = User.get_or_none(User.mail_address == field.data)
    if email_exists:
        raise ValidationError(_('The email is already in use'))
Ejemplo n.º 7
0
def EmailNotExists(
        _form: 'ResetPassForm',
        field: StringField,  # type: ignore # NOQA: F821
) -> None:
    email_exists = User.get_or_none(User.mail_address == field.data)
    if not email_exists:
        raise ValidationError(_('Invalid email'))
Ejemplo n.º 8
0
def UniqueUsernameRequired(
        _form: 'RegisterForm',
        field: StringField,  # type: ignore # NOQA: F821
) -> None:
    username_exists = User.get_or_none(User.username == field.data)
    if username_exists:
        raise ValidationError(_('The username is already in use'))
Ejemplo n.º 9
0
def _upload_to_db(
    exercise_number: int,
    course_id: int,
    user_id: int,
    files: List[File],
    solution_hash: Optional[str] = None,
) -> Solution:
    exercise = Exercise.get_or_none(course=course_id, number=exercise_number)
    user = User.get_by_id(user_id)
    if exercise is None:
        raise UploadError(f'No such exercise id: {exercise_number}')
    elif not user.has_course(course_id):
        raise UploadError(
            f'Exercise {exercise_number} is invalid for this user.', )
    elif not exercise.open_for_new_solutions():
        raise UploadError(
            f'Exercise {exercise_number} is closed for new solutions.')

    if solution_hash and _is_uploaded_before(user, exercise, solution_hash):
        raise AlreadyExists('You try to reupload an old solution.')
    elif not files:
        raise UploadError(
            f'There are no files to upload for {exercise_number}.', )

    return Solution.create_solution(
        exercise=exercise,
        solver=user,
        files=files,
        hash_=solution_hash,
    )
Ejemplo n.º 10
0
def create_student_user(index=0):
    return User.create(  # NOQA: S106
        username=f'student-{index}',
        fullname='Astudent',
        mail_address=f'so-student-{index}@mail.com',
        password='******',
        role=Role.get_student_role(),
    )
Ejemplo n.º 11
0
def admin_user():
    admin_role = Role.get(Role.name == RoleOptions.ADMINISTRATOR.value)
    return User.create(  # NOQA: B106, S106
        username='******',
        fullname='Buya',
        mail_address='*****@*****.**',
        password='******',
        role=admin_role,
    )
Ejemplo n.º 12
0
def staff_user(staff_password):
    staff_role = Role.get(Role.name == RoleOptions.STAFF.value)
    return User.create(  # NOQA: S106
        username='******',
        fullname='Elk',
        mail_address='*****@*****.**',
        password=staff_password,
        role=staff_role,
    )
Ejemplo n.º 13
0
def change_last_course_viewed(course_id: int):
    course = Course.get_or_none(course_id)
    if course is None:
        return fail(404, f'No such course {course_id}.')
    user = User.get(User.id == current_user.id)
    if not UserCourse.is_user_registered(user.id, course.id):
        return fail(403, "You're not allowed to access this page.")
    user.last_course_viewed = course
    user.save()
    return redirect(url_for('exercises_page'))
Ejemplo n.º 14
0
def reset_password():
    form = ResetPassForm()
    if not form.validate_on_submit():
        return render_template('reset-password.html', form=form)

    user = User.get(User.mail_address == form.email.data)

    send_reset_password_mail(user)
    return redirect(url_for(
        'login', login_message=_('Password reset link has successfully sent'),
    ))
Ejemplo n.º 15
0
def create_user(
    role_name: str = RoleOptions.STUDENT.value,
    index: int = 1,
) -> User:
    return User.create(  # NOQA: S106
        username=f'{role_name}-{index}',
        fullname=f'A{role_name}',
        mail_address=f'so-{role_name}-{index}@mail.com',
        password='******',
        role=Role.by_name(role_name),
    )
Ejemplo n.º 16
0
def admin_user():
    admin_role = Role.get(Role.name == RoleOptions.ADMINISTRATOR.value)
    username = '******'
    return User.create(  # NOQA: B106, S106
        username=username,
        fullname='Buya',
        mail_address='*****@*****.**',
        password=FAKE_PASSWORD,
        api_key='fake key',
        role=admin_role,
    )
Ejemplo n.º 17
0
def user(user_id):
    if user_id != current_user.id and not current_user.role.is_manager:
        return fail(403, "You aren't allowed to watch this page.")
    target_user = User.get_or_none(User.id == user_id)
    if target_user is None:
        return fail(404, 'There is no such user.')

    return render_template(
        'user.html',
        solutions=Solution.of_user(target_user.id, with_archived=True),
        user=target_user,
    )
Ejemplo n.º 18
0
def auth(username: str, password: str) -> User:
    user = User.get_or_none(username=username)
    if user is None or not user.is_password_valid(password):
        raise UnauthorizedError(_('Invalid username or password'), 400)
    elif user.role.is_unverified:
        raise ForbiddenPermission(
            _(
                'You have to confirm your registration with the link sent '
                'to your email', ),
            403,
        )
    return user
Ejemplo n.º 19
0
def signup():
    if not webapp.config.get('REGISTRATION_OPEN', False):
        return redirect(url_for(
            'login', login_message=_('Can not register now'),
        ))

    form = RegisterForm()
    if not form.validate_on_submit():
        return render_template('signup.html', form=form)

    user = User.create(**{
        User.mail_address.name: form.email.data,
        User.username.name: form.username.data,
        User.fullname.name: form.fullname.data,
        User.role.name: Role.get_unverified_role(),
        User.password.name: form.password.data,
        User.api_key.name: User.random_password(),
    })
    send_confirmation_mail(user)
    return redirect(url_for(
        'login', login_message=_('Registration successfully'),
    ))
Ejemplo n.º 20
0
    def test_registartion_closed(client: FlaskClient, captured_templates):
        conftest.disable_registration()
        conftest.signup_client_user(
            client, '*****@*****.**', 'some_user',
            'some_name', 'some_password', 'some_password',
        )
        user = User.get_or_none(User.username == 'some_user')
        assert user is None

        response = client.get('/signup')
        template, _ = captured_templates[-1]
        assert template.name == 'login.html'
        assert '/signup' not in response.get_data(as_text=True)
Ejemplo n.º 21
0
def confirm_email(user_id: int, token: str):
    user = User.get_or_none(User.id == user_id)
    if user is None:
        return fail(404, 'The authentication code is invalid.')

    if not user.role.is_unverified:
        return fail(403, 'User has been already confirmed.')

    try:
        SERIALIZER.loads(
            token, salt=retrieve_salt(user), max_age=CONFIRMATION_TIME,
        )

    except SignatureExpired:
        send_confirmation_mail(user)
        return redirect(url_for(
            'login', login_message=(
                _(
                    'The confirmation link is expired, new link has been '
                    'sent to your email',
                ),
            ),
        ))
    except BadSignature:
        return fail(404, 'The authentication code is invalid.')

    else:
        update = User.update(
            role=Role.get_student_role(),
        ).where(User.username == user.username)
        update.execute()
        return redirect(url_for(
            'login', login_message=(
                _(
                    'Your user has been successfully confirmed, '
                    'you can now login',
                ),
            ),
        ))
Ejemplo n.º 22
0
def upload():
    user_id = current_user.id
    user = User.get_or_none(User.id == user_id)  # should never happen
    if user is None:
        return fail(404, 'user not found')
    if request.content_length > MAX_REQUEST_SIZE:
        return fail(413, 'File is too heavy. 500KB allowed')

    file: FileStorage = request.files.get('file')
    if not file:
        return fail(422, 'No file was given')

    json_file_data = file.read()
    try:
        file_content = json.loads(json_file_data)
        exercises = list(extract_exercises(file_content))
    except (ValueError, json.JSONDecodeError):
        return fail(422, 'Invalid file format - must be ipynb')
    if not exercises:
        msg = 'No exercises were found in the notebook'
        desc = 'did you use Upload <number of exercise> ? (example: Upload 1)'
        return fail(422, f'{msg}, {desc}')
    matches, misses = set(), set()
    for exercise_id, code in exercises:
        exercise = Exercise.get_or_none(Exercise.id == exercise_id)
        if exercise is None:
            misses.add(exercise_id)
            continue
        if not exercise.open_for_new_solutions():
            misses.add(exercise_id)
            continue

        if Solution.solution_exists(
                exercise=exercise,
                solver=user,
                json_data_str=code,
        ):
            continue
        solution = Solution.create_solution(
            exercise=exercise,
            solver=user,
            json_data_str=code,
        )
        flake8_tasks.run_flake8_on_solution.apply_async(args=(solution.id, ))
        identical_tests_tasks.solve_solution_with_identical_code.apply_async(
            args=(solution.id, ))
        matches.add(exercise_id)
    return jsonify({
        'exercise_matches': list(matches),
        'exercise_misses': list(misses),
    })
Ejemplo n.º 23
0
    def test_use_token_twice(client: FlaskClient):
        conftest.signup_client_user(
            client, '*****@*****.**', 'some_user',
            'some_name', 'some_password', 'some_password',
        )
        user = User.get_or_none(User.username == 'some_user')
        token = generate_user_token(user)
        success_token_response = client.get(
            f'/confirm-email/{user.id}/{token}', follow_redirects=True,
        )
        assert success_token_response.status_code == 200

        fail_token_response = client.get(
            f'/confirm-email/{user.id}/{token}', follow_redirects=True,
        )
        assert fail_token_response.status_code == 403
Ejemplo n.º 24
0
def login():
    if current_user.is_authenticated:
        return redirect(url_for('main'))

    username = request.form.get('username')
    password = request.form.get('password')
    user = User.get_or_none(username=username)

    if user is not None and user.is_password_valid(password):
        login_user(user)
        next_url = request.args.get('next_url')
        if not is_safe_url(next_url):
            return fail(400, "The URL isn't safe.")
        return redirect(next_url or url_for('main'))

    return render_template('login.html')
Ejemplo n.º 25
0
def change_password():
    user = User.get(User.id == current_user.id)

    form = ChangePasswordForm(user)
    if not form.validate_on_submit():
        return render_template('change-password.html', form=form)

    user.password = form.password.data
    user.save()
    logout_user()
    send_change_password_mail(user)
    return redirect(url_for(
        'login', login_message=(
            _('Your password has successfully changed'),
        ),
    ))
Ejemplo n.º 26
0
def login():
    if current_user.is_authenticated:
        return get_next_url(request.args.get('next'))

    username = request.form.get('username')
    password = request.form.get('password')
    next_page = request.form.get('next')
    user = User.get_or_none(username=username)

    if user is not None and user.is_password_valid(password):
        login_user(user)
        return get_next_url(next_page)
    elif user is not None:
        return redirect(url_for('login', **{'next': next_page}))

    return render_template('login.html')
Ejemplo n.º 27
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,
    })
Ejemplo n.º 28
0
def create(
    user: User,
    note_text: str,
    note_exercise: str,
    privacy: str,
) -> None:
    if not note_text:
        raise UnprocessableRequest('Empty notes are not allowed.', 422)
    new_note_id = CommentText.create_comment(text=note_text).id

    Note.create(
        creator=User.get_or_none(User.id == current_user.id),
        user=user,
        note=new_note_id,
        exercise=Exercise.get_or_none(Exercise.subject == note_exercise),
        privacy=Note.get_privacy_level(int(privacy)),
    )
Ejemplo n.º 29
0
    def test_bad_token_or_id(client: FlaskClient):
        conftest.signup_client_user(
            client, '*****@*****.**', 'some_user',
            'some_name', 'some_password', 'some_password',
        )
        user = User.get_or_none(User.username == 'some_user')
        bad_token = 'fake-token43@$@'  # noqa: S105
        fail_confirm_response = client.get(
            f'/confirm-email/{user.id}/{bad_token}', follow_redirects=True,
        )
        assert fail_confirm_response.status_code == 404

        # No such 999 user id
        another_fail_response = client.get(
            f'/confirm-email/999/{bad_token}', follow_redirects=True,
        )
        assert another_fail_response.status_code == 404
Ejemplo n.º 30
0
Archivo: views.py Proyecto: 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}".')