Require password for email change (#1077)

* Require password for email changes
selenium-screenshot-testing
Kevin Chung 2019-08-04 20:28:20 -04:00 committed by GitHub
parent 3453eafcab
commit 71240bb13d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 7 deletions

View File

@ -119,6 +119,21 @@ class UserSchema(ma.ModelSchema):
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"]

View File

@ -204,21 +204,21 @@ def test_api_users_patch_duplicate_information():
# Duplicate email
r = client.patch(
"/api/v1/users/me",
json={"name": "user2", "email": "user@ctfd.io", "password": "password"},
json={"name": "user1", "email": "user2@ctfd.io", "confirm": "password"},
)
resp = r.get_json()
assert r.status_code == 400
assert resp["errors"]["name"]
assert resp["errors"]["email"]
assert resp["success"] is False
# Duplicate user
r = client.patch(
"/api/v1/users/me",
json={"name": "user", "email": "user2@ctfd.io", "password": "password"},
json={"name": "user2", "email": "user1@ctfd.io", "confirm": "password"},
)
resp = r.get_json()
assert r.status_code == 400
assert resp["errors"]["email"]
assert resp["errors"]["name"]
assert resp["success"] is False
assert Users.query.count() == 3
destroy_ctfd(app)
@ -454,7 +454,7 @@ def test_api_user_change_verify_email():
user.verified = True
app.db.session.commit()
with login_as_user(app) as client:
r = client.patch("/api/v1/users/me", json={"email": "new_email@email.com"})
r = client.patch("/api/v1/users/me", json={"email": "new_email@email.com", "confirm": "password"})
assert r.status_code == 200
resp = r.get_json()
assert resp["data"]["email"] == "new_email@email.com"
@ -473,14 +473,14 @@ def test_api_user_change_email_under_whitelist():
"domain_whitelist", "whitelisted.com, whitelisted.org, whitelisted.net"
)
with login_as_user(app) as client:
r = client.patch("/api/v1/users/me", json={"email": "new_email@email.com"})
r = client.patch("/api/v1/users/me", json={"email": "new_email@email.com", "confirm": "password"})
assert r.status_code == 400
resp = r.get_json()
assert resp["errors"]["email"]
assert resp["success"] is False
r = client.patch(
"/api/v1/users/me", json={"email": "new_email@whitelisted.com"}
"/api/v1/users/me", json={"email": "new_email@whitelisted.com", "confirm": "password"}
)
assert r.status_code == 200
resp = r.get_json()

View File

@ -0,0 +1,37 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from CTFd.models import Users
from CTFd.utils.crypto import verify_password
from tests.helpers import create_ctfd, destroy_ctfd, register_user, login_as_user
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": "user2@ctfd.io"}
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 == "user@ctfd.io"
data = {"name": "user", "email": "user2@ctfd.io", "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 == "user@ctfd.io"
data = {"name": "user", "email": "user2@ctfd.io", "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 == "user2@ctfd.io"
assert verify_password(plaintext="password", ciphertext=user.password)
destroy_ctfd(app)