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}".')
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'))
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, })
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'))
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, })
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'))
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
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, )
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)
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), })
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')
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')
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
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, })
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
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)), )
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}".')
def test_successful_registration(client: FlaskClient, captured_templates): conftest.signup_client_user( client, '*****@*****.**', 'some_user', 'some_name', 'some_password', 'some_password', ) template, _ = captured_templates[-1] assert template.name == 'login.html' conftest.login_client_user(client, 'some_user', 'some_password') fail_login_response = client.get('/exercises') assert fail_login_response.status_code == 302 user = User.get_or_none(User.username == 'some_user') token = generate_user_token(user) client.get(f'/confirm-email/{user.id}/{token}', follow_redirects=True) conftest.login_client_user(client, 'some_user', 'some_password') success_login_response = client.get('/exercises') assert success_login_response.status_code == 200
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.') is_manager = current_user.role.is_manager return render_template( 'user.html', solutions=Solution.of_user( target_user.id, with_archived=True, from_all_courses=True, ), user=target_user, is_manager=is_manager, notes_options=Note.get_note_options(), public_course_exists=Course.public_course_exists(), )
def recover_password(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.') try: SERIALIZER.loads( token, salt=retrieve_salt(user), max_age=CONFIRMATION_TIME, ) except SignatureExpired: return redirect(url_for( 'login', login_message=( _('Reset password link is expired'), ), )) except BadSignature: return fail(404, 'The authentication code is invalid.') else: return recover_password_check(user, token)
def login(login_error: Optional[str] = None): 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') login_error = request.args.get('login_error') user = User.get_or_none(username=username) if request.method == 'POST': if user is not None and user.is_password_valid(password): login_user(user) return get_next_url(next_page) elif user is None or not user.is_password_valid(password): login_error = 'Invalid username or password' error_details = {'next': next_page, 'login_error': login_error} return redirect(url_for('login', **error_details)) return render_template('login.html', login_error=login_error)
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', ), ), ))
def test_expired_token(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) fake_time = time.time() + CONFIRMATION_TIME + 1 with patch('time.time', Mock(return_value=fake_time)): client.get( f'/confirm-email/{user.id}/{token}', follow_redirects=True, ) conftest.login_client_user(client, 'some_user', 'some_password') fail_login_response = client.get('/exercises') assert fail_login_response.status_code == 302 token = generate_user_token(user) client.get( f'/confirm-email/{user.id}/{token}', follow_redirects=True, ) conftest.login_client_user(client, 'some_user', 'some_password') success_login_response = client.get('/exercises') assert success_login_response.status_code == 200
def load_user(user_id): return User.get_or_none(id=user_id)
def load_user(uuid): return User.get_or_none(uuid=uuid)