forked from Github-Mirrors/canaille
adds new tests for compromised_password_check_failure situation.
This commit is contained in:
parent
9844818280
commit
f173a66793
4 changed files with 109 additions and 24 deletions
|
@ -86,6 +86,37 @@ def password_strength_calculator(password):
|
|||
return strength_score
|
||||
|
||||
|
||||
def check_if_send_mail_to_admins(form, api_url, hashed_password_suffix):
|
||||
if current_app.features.has_smtp and not request_is_htmx():
|
||||
flash(
|
||||
_(
|
||||
"Password compromise investigation failed. Please contact the administrators."
|
||||
),
|
||||
"error",
|
||||
)
|
||||
|
||||
group_user = Backend.instance.query(models.User)
|
||||
emails_of_admins = [
|
||||
user.emails[0]
|
||||
for user in group_user
|
||||
if any(group.display_name == "admins" for group in user.groups)
|
||||
]
|
||||
|
||||
if form.user is not None:
|
||||
user_name = form.user.user_name
|
||||
user_email = form.user.emails[0]
|
||||
else:
|
||||
user_name = form["user_name"].data
|
||||
user_email = form["emails"].data[0]
|
||||
|
||||
for admin_email in emails_of_admins:
|
||||
send_compromised_password_check_failure_mail(
|
||||
api_url, user_name, user_email, hashed_password_suffix, admin_email
|
||||
)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
def compromised_password_validator(form, field):
|
||||
try:
|
||||
from hashlib import sha1
|
||||
|
@ -94,13 +125,6 @@ def compromised_password_validator(form, field):
|
|||
except ImportError:
|
||||
return None
|
||||
|
||||
group_user = Backend.instance.query(models.User)
|
||||
emails_of_admins = []
|
||||
for user in group_user:
|
||||
for group in user.groups:
|
||||
if "admins" == group.display_name:
|
||||
emails_of_admins.append(user.emails[0])
|
||||
|
||||
hashed_password = sha1(field.data.encode("utf-8")).hexdigest()
|
||||
hashed_password_prefix, hashed_password_suffix = (
|
||||
hashed_password[:5].upper(),
|
||||
|
@ -113,23 +137,8 @@ def compromised_password_validator(form, field):
|
|||
response = requests.api.get(api_url, timeout=10)
|
||||
except Exception as e:
|
||||
print("Error: " + str(e))
|
||||
if current_app.features.has_smtp and not request_is_htmx():
|
||||
flash(
|
||||
_(
|
||||
"Password compromise investigation failed. Please contact the administrators."
|
||||
),
|
||||
"error",
|
||||
)
|
||||
if form.user is not None:
|
||||
user_name = form.user.user_name
|
||||
user_email = form.user.emails[0]
|
||||
else:
|
||||
user_name = form["user_name"].data
|
||||
user_email = form["emails"].data[0]
|
||||
for admin_email in emails_of_admins:
|
||||
send_compromised_password_check_failure_mail(
|
||||
api_url, user_name, user_email, hashed_password_suffix, admin_email
|
||||
)
|
||||
|
||||
check_if_send_mail_to_admins(form, api_url, hashed_password_suffix)
|
||||
|
||||
return None
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from flask import current_app
|
|||
from werkzeug.datastructures import ImmutableMultiDict
|
||||
|
||||
from canaille.app.forms import DateTimeUTCField
|
||||
from canaille.app.forms import compromised_password_validator
|
||||
from canaille.app.forms import password_length_validator
|
||||
from canaille.app.forms import password_too_long_validator
|
||||
from canaille.app.forms import phone_number
|
||||
|
@ -333,3 +334,23 @@ def test_maximum_password_length_config(testclient):
|
|||
password_too_long_validator(None, Field("a" * 4096))
|
||||
with pytest.raises(wtforms.ValidationError):
|
||||
password_too_long_validator(None, Field("a" * 4097))
|
||||
|
||||
|
||||
def test_compromised_password_validator(testclient):
|
||||
class Field:
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
compromised_password_validator(None, Field("i'm a little pea"))
|
||||
compromised_password_validator(None, Field("i'm a little chickpea"))
|
||||
compromised_password_validator(None, Field("i'm singing in the rain"))
|
||||
with pytest.raises(wtforms.ValidationError):
|
||||
compromised_password_validator(None, Field("password"))
|
||||
with pytest.raises(wtforms.ValidationError):
|
||||
compromised_password_validator(None, Field("987654321"))
|
||||
with pytest.raises(wtforms.ValidationError):
|
||||
compromised_password_validator(None, Field("correct horse battery staple"))
|
||||
with pytest.raises(wtforms.ValidationError):
|
||||
compromised_password_validator(None, Field("zxcvbn123"))
|
||||
with pytest.raises(wtforms.ValidationError):
|
||||
compromised_password_validator(None, Field("azertyuiop123"))
|
||||
|
|
|
@ -180,6 +180,31 @@ def test_profile_settings_compromised_password(testclient, logged_user):
|
|||
with_different_values("i'm a little pea", 'data-percent="100"')
|
||||
|
||||
|
||||
@mock.patch("requests.api.get")
|
||||
def test_profile_settings_compromised_password_request_api_failed_but_password_updated(
|
||||
api_get, testclient, user, logged_user, backend
|
||||
):
|
||||
api_get.side_effect = mock.Mock(side_effect=Exception())
|
||||
|
||||
res = testclient.get("/profile/user/settings", status=200)
|
||||
|
||||
res.form["password1"] = "123456789"
|
||||
res.form["password2"] = "123456789"
|
||||
|
||||
res = res.form.submit(name="action", value="edit-settings")
|
||||
|
||||
assert (
|
||||
"error",
|
||||
"Password compromise investigation failed. Please contact the administrators.",
|
||||
) in res.flashes
|
||||
assert ("success", "Profile updated successfully.") in res.flashes
|
||||
|
||||
backend.reload(logged_user)
|
||||
|
||||
assert logged_user.user_name == "user"
|
||||
assert backend.check_user_password(logged_user, "123456789")[0]
|
||||
|
||||
|
||||
def test_edition_without_groups(
|
||||
testclient,
|
||||
logged_user,
|
||||
|
|
|
@ -169,3 +169,33 @@ def test_registration_with_compromised_password(testclient, backend, foo_group):
|
|||
|
||||
user = backend.get(models.User, user_name="newuser")
|
||||
assert user is None
|
||||
|
||||
|
||||
@mock.patch("requests.api.get")
|
||||
def test_registration_with_compromised_password_request_api_failed_but_account_created(
|
||||
api_get, testclient, backend
|
||||
):
|
||||
api_get.side_effect = mock.Mock(side_effect=Exception())
|
||||
|
||||
testclient.app.config["CANAILLE"]["ENABLE_REGISTRATION"] = True
|
||||
testclient.app.config["CANAILLE"]["EMAIL_CONFIRMATION"] = False
|
||||
|
||||
assert not backend.query(models.User, user_name="newuser")
|
||||
res = testclient.get(url_for("core.account.registration"), status=200)
|
||||
res.form["user_name"] = "newuser"
|
||||
res.form["password1"] = "123456789"
|
||||
res.form["password2"] = "123456789"
|
||||
res.form["family_name"] = "newuser"
|
||||
res.form["emails-0"] = "newuser@example.com"
|
||||
|
||||
res = res.form.submit()
|
||||
|
||||
assert (
|
||||
"error",
|
||||
"Password compromise investigation failed. Please contact the administrators.",
|
||||
) in res.flashes
|
||||
assert ("success", "Your account has been created successfully.") in res.flashes
|
||||
|
||||
user = backend.get(models.User, user_name="newuser")
|
||||
assert user
|
||||
backend.delete(user)
|
||||
|
|
Loading…
Reference in a new issue