def validate_password_confirmation(self, data): password = data.get("password") confirm = data.get("confirm") if is_admin(): pass else: current_team = get_current_team() current_user = get_current_user() if current_team.captain_id != current_user.id: raise ValidationError( "Only the captain can change the team password", field_names=["captain_id"], ) if password and (bool(confirm) is False): raise ValidationError("Please confirm your current password", field_names=["confirm"]) if password and confirm: test_team = verify_password(plaintext=confirm, ciphertext=current_team.password) test_captain = verify_password( plaintext=confirm, ciphertext=current_user.password) if test_team is True or test_captain is True: return data else: raise ValidationError( "Your previous password is incorrect", field_names=["confirm"]) else: data.pop("password", None) data.pop("confirm", None)
def login(): errors = get_errors() if request.method == "POST": name = request.form["name"] user = Users.query.filter_by(name=name).first() if user: if user and verify_password(request.form["password"], user.password): session.regenerate() login_user(user) log("logins", "[{date}] {ip} - {name} logged in") db.session.close() if request.args.get("next") and validators.is_safe_url( request.args.get("next") ): return redirect(request.args.get("next")) return redirect(url_for("challenges.listing")) else: # This user exists but the password is wrong log("logins", "[{date}] {ip} - submitted invalid password for {name}") errors.append("Your username or password is incorrect") db.session.close() return render_template("login.html", errors=errors) else: # This user just doesn't exist log("logins", "[{date}] {ip} - submitted invalid account information") errors.append("Your username or password is incorrect") db.session.close() return render_template("login.html", errors=errors) else: db.session.close() return render_template("login.html", errors=errors)
def validate_password_confirmation(self, data): password = data.get('password') confirm = data.get('confirm') if is_admin(): pass else: current_team = get_current_team() current_user = get_current_user() if current_team.captain_id != current_user.id: raise ValidationError( 'Only the captain can change the team password', field_names=['captain_id']) if password and (bool(confirm) is False): raise ValidationError('Please confirm your current password', field_names=['confirm']) if password and confirm: test = verify_password(plaintext=confirm, ciphertext=current_team.password) if test is True: return data else: raise ValidationError( 'Your previous password is incorrect', field_names=['confirm']) else: data.pop('password', None) data.pop('confirm', None)
def validate_password_confirmation(self, data): password = data.get("password") confirm = data.get("confirm") target_user = get_current_user() if is_admin(): pass else: if password and (bool(confirm) is False): raise ValidationError( "Please confirm your current password", field_names=["confirm"] ) if password and confirm: test = verify_password( plaintext=confirm, ciphertext=target_user.password ) if test is True: return data else: raise ValidationError( "Your previous password is incorrect", field_names=["confirm"] ) else: data.pop("password", None) data.pop("confirm", None)
def test_email_cannot_be_changed_without_password(): """Test that a user can't update their email address without current password""" app = create_ctfd() with app.app_context(): register_user(app) client = login_as_user(app) data = {"name": "user", "email": "*****@*****.**"} r = client.patch("/api/v1/users/me", json=data) assert r.status_code == 400 user = Users.query.filter_by(id=2).first() assert user.email == "*****@*****.**" data = {"name": "user", "email": "*****@*****.**", "confirm": "asdf"} r = client.patch("/api/v1/users/me", json=data) assert r.status_code == 400 user = Users.query.filter_by(id=2).first() assert user.email == "*****@*****.**" data = { "name": "user", "email": "*****@*****.**", "confirm": "password" } r = client.patch("/api/v1/users/me", json=data) assert r.status_code == 200 user = Users.query.filter_by(id=2).first() assert user.email == "*****@*****.**" assert verify_password(plaintext="password", ciphertext=user.password) destroy_ctfd(app)
def test_api_users_post_admin(): """Can a user post /api/v1/users if admin""" app = create_ctfd() with app.app_context(): with login_as_user(app, "admin") as client: # Create user r = client.post( "/api/v1/users", json={ "name": "user", "email": "*****@*****.**", "password": "******" }, ) assert r.status_code == 200 # Make sure password was hashed properly user = Users.query.filter_by(email="*****@*****.**").first() assert user assert verify_password("password", user.password) # Make sure user can login with the creds client = login_as_user(app) r = client.get("/profile") assert r.status_code == 200 destroy_ctfd(app)
def test_api_users_post_admin_with_attributes(): """Can a user post /api/v1/users with user settings""" app = create_ctfd() with app.app_context(): with login_as_user(app, "admin") as client: # Create user r = client.post( "/api/v1/users", json={ "name": "user", "email": "*****@*****.**", "password": "******", "banned": True, "hidden": True, "verified": True, }, ) assert r.status_code == 200 # Make sure password was hashed properly user = Users.query.filter_by(email="*****@*****.**").first() assert user assert verify_password("password", user.password) assert user.banned assert user.hidden assert user.verified destroy_ctfd(app)
def validate_password_confirmation(self, data): password = data.get("password") confirm = data.get("confirm") target_user = get_current_user() if is_admin(): pass else: if password and (bool(confirm) is False): raise ValidationError( "请确认您当前的密码", field_names=["confirm"] ) if password and confirm: test = verify_password( plaintext=confirm, ciphertext=target_user.password ) if test is True: return data else: raise ValidationError( "当前密码输入错误", field_names=["confirm"] ) else: data.pop("password", None) data.pop("confirm", None)
def test_user_can_change_password(): """Test that a user can change their password and is prompted properly""" app = create_ctfd() with app.app_context(): register_user(app) client = login_as_user(app) data = { "name": "user", "email": "*****@*****.**", "confirm": "", "password": "******", "affiliation": "", "website": "", "country": "", } r = client.patch("/api/v1/users/me", json=data) user = Users.query.filter_by(id=2).first() assert verify_password(data["password"], user.password) is False assert r.status_code == 400 assert r.get_json() == { "errors": { "confirm": ["Please confirm your current password"] }, "success": False, } data["confirm"] = "wrong_password" r = client.patch("/api/v1/users/me", json=data) user = Users.query.filter_by(id=2).first() assert verify_password(data["password"], user.password) is False assert r.status_code == 400 assert r.get_json() == { "errors": { "confirm": ["Your previous password is incorrect"] }, "success": False, } data["confirm"] = "password" r = client.patch("/api/v1/users/me", json=data) assert r.status_code == 200 user = Users.query.filter_by(id=2).first() assert verify_password(data["password"], user.password) is True destroy_ctfd(app)
def test_api_team_patch_password(): """Can a user change their team password /api/v1/teams/me if logged in as the captain""" app = create_ctfd(user_mode="teams") with app.app_context(): user1 = gen_user(app.db, name="user1", email="*****@*****.**") # ID 2 user2 = gen_user(app.db, name="user2", email="*****@*****.**") # ID 3 team = gen_team(app.db) team.members.append(user1) team.members.append(user2) team.captain_id = 2 user1.team_id = team.id user2.team_id = team.id app.db.session.commit() with login_as_user(app, name="user2") as client: r = client.patch( "/api/v1/teams/me", json={ "confirm": "password", "password": "******" }, ) assert r.status_code == 403 assert r.get_json() == { "errors": { "": ["Only team captains can edit team information"] }, "success": False, } team = Teams.query.filter_by(id=1).first() assert (verify_password(plaintext="new_password", ciphertext=team.password) is False) with login_as_user(app, name="user1") as client: r = client.patch( "/api/v1/teams/me", json={ "confirm": "password", "password": "******" }, ) assert r.status_code == 200 team = Teams.query.filter_by(id=1).first() assert verify_password(plaintext="new_password", ciphertext=team.password)
def test_user_can_change_password(): """Test that a user can change their password and is prompted properly""" app = create_ctfd() with app.app_context(): register_user(app) client = login_as_user(app) data = { 'name': 'user', 'email': '*****@*****.**', 'confirm': '', 'password': '******', 'affiliation': '', 'website': '', 'country': '', } r = client.patch('/api/v1/users/me', json=data) user = Users.query.filter_by(id=2).first() assert verify_password(data['password'], user.password) is False assert r.status_code == 400 assert r.get_json() == { 'errors': { 'confirm': ['Please confirm your current password'] }, 'success': False } data['confirm'] = 'wrong_password' r = client.patch('/api/v1/users/me', json=data) user = Users.query.filter_by(id=2).first() assert verify_password(data['password'], user.password) is False assert r.status_code == 400 assert r.get_json() == { 'errors': { 'confirm': ['Your previous password is incorrect'] }, 'success': False } data['confirm'] = 'password' r = client.patch('/api/v1/users/me', json=data) assert r.status_code == 200 user = Users.query.filter_by(id=2).first() assert verify_password(data['password'], user.password) is True destroy_ctfd(app)
def validate_email(self, data): email = data.get("email") if email is None: return email = email.strip() existing_user = Users.query.filter_by(email=email).first() current_user = get_current_user() if is_admin(): user_id = data.get("id") if user_id: if existing_user and existing_user.id != user_id: raise ValidationError( "邮箱地址已经被使用", field_names=["email"] ) else: if existing_user: if current_user: if current_user.id != existing_user.id: raise ValidationError( "邮箱地址已经被使用", field_names=["email"], ) else: raise ValidationError( "邮箱地址已经被使用", field_names=["email"] ) else: if email == current_user.email: return data else: confirm = data.get("confirm") if bool(confirm) is False: raise ValidationError( "请确认您当前的密码", field_names=["confirm"] ) test = verify_password( plaintext=confirm, ciphertext=current_user.password ) if test is False: raise ValidationError( "当前密码输入错误", field_names=["confirm"] ) if existing_user: raise ValidationError( "邮箱地址已经被使用", field_names=["email"] ) if check_email_is_whitelisted(email) is False: raise ValidationError( "只有如下电子邮件地址可以注册 {domains} ".format( domains=get_config("domain_whitelist") ), field_names=["email"], ) if get_config("verify_emails"): current_user.verified = False
def join(): infos = get_infos() errors = get_errors() user = get_current_user_attrs() if user.team_id: errors.append("You are already in a team. You cannot join another.") if request.method == "GET": team_size_limit = get_config("team_size", default=0) if team_size_limit: plural = "" if team_size_limit == 1 else "s" infos.append("Teams are limited to {limit} member{plural}".format( limit=team_size_limit, plural=plural)) return render_template("teams/join_team.html", infos=infos, errors=errors) if request.method == "POST": teamname = request.form.get("name") passphrase = request.form.get("password", "").strip() team = Teams.query.filter_by(name=teamname).first() if errors: return ( render_template("teams/join_team.html", infos=infos, errors=errors), 403, ) if team and verify_password(passphrase, team.password): team_size_limit = get_config("team_size", default=0) if team_size_limit and len(team.members) >= team_size_limit: errors.append( "{name} has already reached the team size limit of {limit}" .format(name=team.name, limit=team_size_limit)) return render_template("teams/join_team.html", infos=infos, errors=errors) user = get_current_user() user.team_id = team.id db.session.commit() if len(team.members) == 1: team.captain_id = user.id db.session.commit() clear_user_session(user_id=user.id) clear_team_session(team_id=team.id) return redirect(url_for("challenges.listing")) else: errors.append("That information is incorrect") return render_template("teams/join_team.html", infos=infos, errors=errors)
def validate_email(self, data): email = data.get("email") if email is None: return existing_user = Users.query.filter_by(email=email).first() current_user = get_current_user() if is_admin(): user_id = data.get("id") if user_id: if existing_user and existing_user.id != user_id: raise ValidationError( "Email address has already been used", field_names=["email"] ) else: if existing_user: if current_user: if current_user.id != existing_user.id: raise ValidationError( "Email address has already been used", field_names=["email"], ) else: raise ValidationError( "Email address has already been used", field_names=["email"] ) else: if email == current_user.email: return data else: confirm = data.get("confirm") if bool(confirm) is False: raise ValidationError( "Please confirm your current password", field_names=["confirm"] ) test = verify_password( plaintext=confirm, ciphertext=current_user.password ) if test is False: raise ValidationError( "Your previous password is incorrect", field_names=["confirm"] ) if existing_user: raise ValidationError( "Email address has already been used", field_names=["email"] ) if check_email_is_whitelisted(email) is False: raise ValidationError( "Only email addresses under {domains} may register".format( domains=get_config("domain_whitelist") ), field_names=["email"], ) if get_config("verify_emails"): current_user.verified = False
def validate_email(self, data): email = data.get("email") if email is None: return email = email.strip() existing_user = Users.query.filter_by(email=email).first() current_user = get_current_user() if is_admin(): user_id = data.get("id") if user_id: if existing_user and existing_user.id != user_id: raise ValidationError( "Электронный адрес уже использовался", field_names=["email"]) else: if existing_user: if current_user: if current_user.id != existing_user.id: raise ValidationError( "Электронный адрес уже использовался", field_names=["email"], ) else: raise ValidationError( "Электронный адрес уже использовался", field_names=["email"]) else: if email == current_user.email: return data else: confirm = data.get("confirm") if bool(confirm) is False: raise ValidationError( "Пожалуйста, подтвердите ваш текущий пароль", field_names=["confirm"]) test = verify_password(plaintext=confirm, ciphertext=current_user.password) if test is False: raise ValidationError("Введенный текущий пароль неверен", field_names=["confirm"]) if existing_user: raise ValidationError( "Электронный адрес уже использовался", field_names=["email"]) if check_email_is_whitelisted(email) is False: raise ValidationError( "Только адреса электронной почты в домене {domain} могут регистрироваться" .format(domains=get_config("domain_whitelist")), field_names=["email"], ) if get_config("verify_emails"): current_user.verified = False
def login(): errors = get_errors() if request.method == "POST": name = request.form["name"] # Check if the user submitted an email address or a team name if validators.validate_email(name) is True: user = Users.query.filter_by(email=name).first() else: user = Users.query.filter_by(name=name).first() if user: if user.password is None: errors.append( "Your account was registered with a 3rd party authentication provider. " "Please try logging in with a configured authentication provider." ) return render_template("login.html", errors=errors) if user and verify_password(request.form["password"], user.password): session.regenerate() login_user(user) log("logins", "[{date}] {ip} - {name} logged in", name=user.name) db.session.close() if request.args.get("next") and validators.is_safe_url( request.args.get("next")): return redirect(request.args.get("next")) return redirect(url_for("challenges.listing")) else: # This user exists but the password is wrong log( "logins", "[{date}] {ip} - submitted invalid password for {name}", name=user.name, ) errors.append("用户名或密码错误") db.session.close() return render_template("login.html", errors=errors) else: # This user just doesn't exist log("logins", "[{date}] {ip} - submitted invalid account information") errors.append("用户名或密码错误") db.session.close() return render_template("login.html", errors=errors) else: db.session.close() return render_template("login.html", errors=errors)
def join(): if request.method == 'GET': return render_template('teams/join_team.html') if request.method == 'POST': teamname = request.form.get('name') passphrase = request.form.get('password', '').strip() team = Teams.query.filter_by(name=teamname).first() user = get_current_user() if team and verify_password(passphrase, team.password): user.team_id = team.id db.session.commit() return redirect(url_for('challenges.listing')) else: errors = ['Cette information est incorrecte'] return render_template('teams/join_team.html', errors=errors)
def join(): infos = get_infos() errors = get_errors() if request.method == "GET": team_size_limit = get_config("team_size", default=0) if team_size_limit: plural = "" if team_size_limit == 1 else "s" infos.append( "Команды могут содержать не больше {limit} участников".format( limit=team_size_limit, plural=plural)) return render_template("teams/join_team.html", infos=infos, errors=errors) if request.method == "POST": teamname = request.form.get("name") passphrase = request.form.get("password", "").strip() team = Teams.query.filter_by(name=teamname).first() if team and verify_password(passphrase, team.password): team_size_limit = get_config("team_size", default=0) if team_size_limit and len(team.members) >= team_size_limit: errors.append( "Команда {name} уже достигла лимит в {limit} участников". format(name=team.name, limit=team_size_limit)) return render_template("teams/join_team.html", infos=infos, errors=errors) user = get_current_user() user.team_id = team.id db.session.commit() if len(team.members) == 1: team.captain_id = user.id db.session.commit() clear_user_session(user_id=user.id) clear_team_session(team_id=team.id) return redirect(url_for("challenges.listing")) else: errors.append("Такая информация некорректна") return render_template("teams/join_team.html", infos=infos, errors=errors)
def validate_password_confirmation(self, data): password = data.get('password') confirm = data.get('confirm') target_team = get_current_team() if is_admin(): pass else: if password and (confirm is None): raise ValidationError('Please confirm your current password', field_names=['confirm']) if password and confirm: test = verify_password(plaintext=confirm, ciphertext=target_team.password) if test is True: return data else: raise ValidationError('Your previous password is incorrect', field_names=['confirm'])
def test_api_team_patch_admin(): """Can a user patch /api/v1/teams/<team_id> if admin""" app = create_ctfd(user_mode="teams") with app.app_context(): gen_team(app.db) with login_as_user(app, 'admin') as client: r = client.patch('/api/v1/teams/1', json={ "name": "team_name", "email": "*****@*****.**", "password": "******", "affiliation": "changed" }) team = Teams.query.filter_by(id=1).first() assert r.status_code == 200 assert r.get_json()['data']['affiliation'] == 'changed' assert verify_password('password', team.password) destroy_ctfd(app)
def login(): errors = get_errors() if request.method == "POST": name = request.form["name"] # Check if the user submitted an email address or a team name if validators.validate_email(name) is True: user = Users.query.filter_by(email=name).first() else: user = Users.query.filter_by(name=name).first() if user: if user and verify_password(request.form["password"], user.password): session.regenerate() login_user(user) log("logins", "[{date}] {ip} - {name} logged in") db.session.close() if request.args.get("next") and validators.is_safe_url( request.args.get("next")): return redirect(request.args.get("next")) return redirect(url_for("challenges.listing")) else: # This user exists but the password is wrong log("logins", "[{date}] {ip} - submitted invalid password for {name}") errors.append("Неверное имя пользователя или пароль") db.session.close() return render_template("login.html", errors=errors) else: # This user just doesn't exist log("logins", "[{date}] {ip} - submitted invalid account information") errors.append("Неверное имя пользователя или пароль") db.session.close() return render_template("login.html", errors=errors) else: db.session.close() return render_template("login.html", errors=errors)
def login(): # login req = request.json if 'name' not in req or 'password' not in req: return {"success": False, "data": None} name = req['name'] if validators.validate_email(name) is True: user = Users.query.filter_by(email=name).first() else: user = Users.query.filter_by(name=name).first() if user and verify_password(request.json["password"], user.password): session.regenerate() login_user(user) db.session.close() return { "success": True, "data": { "nonce": session["nonce"], }} else: db.session.close() return {"success": False, "data": "Your username or password is incorrect"}
def test_api_team_patch_admin(): """Can a user patch /api/v1/teams/<team_id> if admin""" app = create_ctfd(user_mode="teams") with app.app_context(): gen_team(app.db) with login_as_user(app, "admin") as client: r = client.patch( "/api/v1/teams/1", json={ "name": "team_name", "email": "*****@*****.**", "password": "******", "affiliation": "changed", }, ) team = Teams.query.filter_by(id=1).first() assert r.status_code == 200 assert r.get_json()["data"]["affiliation"] == "changed" assert verify_password("password", team.password) destroy_ctfd(app)
def join(): if request.method == "GET": return render_template("teams/join_team.html") if request.method == "POST": teamname = request.form.get("name") passphrase = request.form.get("password", "").strip() team = Teams.query.filter_by(name=teamname).first() user = get_current_user() if team and verify_password(passphrase, team.password): user.team_id = team.id db.session.commit() if len(team.members) == 1: team.captain_id = user.id db.session.commit() return redirect(url_for("challenges.listing")) else: errors = ["That information is incorrect"] return render_template("teams/join_team.html", errors=errors)
def validate_password_confirmation(self, data): password = data.get('password') confirm = data.get('confirm') target_user = get_current_user() user_id = data.get('id') if is_admin(): pass else: if password and (confirm is None): raise ValidationError( 'Пожалуйста, подтвердите ваш текущий пароль', field_names=['confirm']) if password and confirm: test = verify_password(plaintext=confirm, ciphertext=target_user.password) if test is True: return data else: raise ValidationError('Ваш текущий пароль неверен', field_names=['confirm'])
def test_api_teams_post_admin(): """Can a user post /api/v1/teams if admin""" app = create_ctfd(user_mode="teams") with app.app_context(): with login_as_user(app, "admin") as client: # Create team r = client.post( "/api/v1/teams", json={ "website": "http://www.team.com", "name": "team", "country": "TW", "email": "*****@*****.**", "affiliation": "team", "password": "******", }, ) assert r.status_code == 200 # Make sure password was hashed properly team = Teams.query.filter_by(email="*****@*****.**").first() assert team assert verify_password("password", team.password) # Make sure team can actually be joined register_user(app) client = login_as_user(app) with client.session_transaction() as sess: data = { "name": "team", "password": "******", "nonce": sess.get("nonce"), } r = client.post("/teams/join", data=data) user = Users.query.filter_by(id=2).first() assert user.team_id == 1 destroy_ctfd(app)
def login(): errors = get_errors() if request.method == 'POST': name = request.form['name'] # Check if the user submitted an email address or a team name if validators.validate_email(name) is True: user = Users.query.filter_by(email=name).first() else: user = Users.query.filter_by(name=name).first() if user: if user and verify_password(request.form['password'], user.password): session.regenerate() login_user(user) log('logins', "[{date}] {ip} - {name} logged in") db.session.close() if request.args.get('next') and validators.is_safe_url(request.args.get('next')): return redirect(request.args.get('next')) return redirect(url_for('challenges.listing')) else: # This user exists but the password is wrong log('logins', "[{date}] {ip} - submitted invalid password for {name}") errors.append("Your username or password is incorrect") db.session.close() return render_template('login.html', errors=errors) else: # This user just doesn't exist log('logins', "[{date}] {ip} - submitted invalid account information") errors.append("Your username or password is incorrect") db.session.close() return render_template('login.html', errors=errors) else: db.session.close() return render_template('login.html', errors=errors)
def validate_password_confirmation(self, data): password = data.get("password") confirm = data.get("confirm") target_user = get_current_user() if is_admin(): pass else: if password and (bool(confirm) is False): raise ValidationError( "Пожалуйста, подтвердите ваш текущий пароль", field_names=["confirm"]) if password and confirm: test = verify_password(plaintext=confirm, ciphertext=target_user.password) if test is True: return data else: raise ValidationError("Введенный текущий пароль неверен", field_names=["confirm"]) else: data.pop("password", None) data.pop("confirm", None)
def test_user_can_reset_password(mock_smtp): """Test that a user is capable of resetting their password""" from email.message import EmailMessage app = create_ctfd() with app.app_context(), freeze_time("2012-01-14 03:21:34"): # Set CTFd to send emails set_config("mail_server", "localhost") set_config("mail_port", 25) set_config("mail_useauth", True) set_config("mail_username", "username") set_config("mail_password", "password") # Create a user register_user(app, name="user1", email="*****@*****.**") with app.test_client() as client: client.get("/reset_password") # Build reset password data with client.session_transaction() as sess: data = {"nonce": sess.get("nonce"), "email": "*****@*****.**"} # Issue the password reset request client.post("/reset_password", data=data) ctf_name = get_config("ctf_name") from_addr = get_config("mailfrom_addr") or app.config.get( "MAILFROM_ADDR") from_addr = "{} <{}>".format(ctf_name, from_addr) to_addr = "*****@*****.**" # Build the email msg = ( "Did you initiate a password reset on CTFd? If you didn't initiate this request you can ignore this email. " "\n\nClick the following link to reset your password:\n" "http://localhost/reset_password/InVzZXJAdXNlci5jb20i.TxD0vg.28dY_Gzqb1TH9nrcE_H7W8YFM-U\n\n" "If the link is not clickable, try copying and pasting it into your browser." ) ctf_name = get_config("ctf_name") email_msg = EmailMessage() email_msg.set_content(msg) email_msg[ "Subject"] = "Password Reset Request from {ctf_name}".format( ctf_name=ctf_name) email_msg["From"] = from_addr email_msg["To"] = to_addr # Make sure that the reset password email is sent mock_smtp.return_value.send_message.assert_called() assert str(mock_smtp.return_value.send_message.call_args[0] [0]) == str(email_msg) # Get user's original password user = Users.query.filter_by(email="*****@*****.**").first() # Build the POST data with client.session_transaction() as sess: data = {"nonce": sess.get("nonce"), "password": "******"} # Do the password reset client.get( "/reset_password/InVzZXJAdXNlci5jb20i.TxD0vg.28dY_Gzqb1TH9nrcE_H7W8YFM-U" ) client.post( "/reset_password/InVzZXJAdXNlci5jb20i.TxD0vg.28dY_Gzqb1TH9nrcE_H7W8YFM-U", data=data, ) # Make sure that the user's password changed user = Users.query.filter_by(email="*****@*****.**").first() assert verify_password("passwordtwo", user.password) destroy_ctfd(app)
def test_user_can_reset_password(mock_smtp): """Test that a user is capable of resetting their password""" from email.mime.text import MIMEText app = create_ctfd() with app.app_context(), freeze_time("2012-01-14 03:21:34"): # Set CTFd to send emails set_config("mail_server", "localhost") set_config("mail_port", 25) set_config("mail_useauth", True) set_config("mail_username", "username") set_config("mail_password", "password") # Create a user register_user(app, name="user1", email="*****@*****.**") with app.test_client() as client: client.get("/reset_password") # Build reset password data with client.session_transaction() as sess: data = {"nonce": sess.get("nonce"), "email": "*****@*****.**"} # Issue the password reset request client.post("/reset_password", data=data) from_addr = get_config("mailfrom_addr") or app.config.get( "MAILFROM_ADDR") to_addr = "*****@*****.**" # Build the email msg = ( """Did you initiate a password reset? Click the following link to reset """ """your password:\n\nhttp://localhost/reset_password/InVzZXIxIg.TxD0vg.-gvVg-KVy0RWkiclAE6JViv1I0M\n\n""" ) email_msg = MIMEText(msg) email_msg["Subject"] = "Message from CTFd" email_msg["From"] = from_addr email_msg["To"] = to_addr # Make sure that the reset password email is sent mock_smtp.return_value.sendmail.assert_called_with( from_addr, [to_addr], email_msg.as_string()) # Get user's original password user = Users.query.filter_by(email="*****@*****.**").first() # Build the POST data with client.session_transaction() as sess: data = {"nonce": sess.get("nonce"), "password": "******"} # Do the password reset client.get( "/reset_password/InVzZXIxIg.TxD0vg.-gvVg-KVy0RWkiclAE6JViv1I0M" ) client.post( "/reset_password/InVzZXIxIg.TxD0vg.-gvVg-KVy0RWkiclAE6JViv1I0M", data=data, ) # Make sure that the user's password changed user = Users.query.filter_by(email="*****@*****.**").first() assert verify_password("passwordtwo", user.password) destroy_ctfd(app)