canaille-globuzma/tests/test_account.py

369 lines
11 KiB
Python
Raw Normal View History

from unittest import mock
2022-05-18 09:31:26 +00:00
from canaille.ldap_backend.ldapobject import LDAPObject
2021-12-20 22:57:27 +00:00
from canaille.models import User
2020-10-22 15:37:01 +00:00
2022-12-04 11:57:59 +00:00
def test_index(testclient, user):
res = testclient.get("/", status=302)
assert res.location == "/login"
with testclient.session_transaction() as sess:
2023-02-05 18:08:25 +00:00
sess["user_id"] = [user.id]
2022-12-04 11:57:59 +00:00
res = testclient.get("/", status=302)
assert res.location == "/profile/user"
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = ["use_oidc"]
res = testclient.get("/", status=302)
assert res.location == "/consent/"
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = []
res = testclient.get("/", status=302)
assert res.location == "/about"
def test_signin_and_out(testclient, user):
2020-08-20 08:31:36 +00:00
with testclient.session_transaction() as session:
assert not session.get("user_id")
2020-08-20 08:31:36 +00:00
2020-10-30 18:19:34 +00:00
res = testclient.get("/login", status=200)
2020-08-20 08:31:36 +00:00
2021-12-06 14:40:30 +00:00
res.form["login"] = "John (johnny) Doe"
2021-01-23 21:30:43 +00:00
res = res.form.submit(status=302)
res = res.follow(status=200)
with testclient.session_transaction() as session:
2021-12-06 14:40:30 +00:00
assert "John (johnny) Doe" == session.get("attempt_login")
2021-01-23 21:30:43 +00:00
2020-08-20 08:31:36 +00:00
res.form["password"] = "correct horse battery staple"
res = res.form.submit()
2020-10-30 22:41:02 +00:00
res = res.follow(status=302)
res = res.follow(status=200)
2020-08-20 08:31:36 +00:00
with testclient.session_transaction() as session:
2023-02-05 18:08:25 +00:00
assert [user.id] == session.get("user_id")
2021-01-23 21:30:43 +00:00
assert "attempt_login" not in session
2020-08-20 08:31:36 +00:00
res = testclient.get("/login", status=302)
2020-08-20 08:31:36 +00:00
res = testclient.get("/logout")
assert (
"success",
"You have been disconnected. See you next time John (johnny) Doe",
) in res.flashes
2020-10-30 22:41:02 +00:00
res = res.follow(status=302)
res = res.follow(status=200)
def test_visitor_logout(testclient, user):
with testclient.session_transaction() as session:
assert not session.get("user_id")
res = testclient.get("/logout")
res = res.follow(status=302)
res = res.follow(status=200)
assert (
"success",
"You have been disconnected. See you next time user",
) not in res.flashes
2020-08-20 08:31:36 +00:00
with testclient.session_transaction() as session:
assert not session.get("user_id")
2020-08-20 08:31:36 +00:00
def test_signin_wrong_password(testclient, user):
2020-08-20 08:31:36 +00:00
with testclient.session_transaction() as session:
assert not session.get("user_id")
2020-08-20 08:31:36 +00:00
2020-10-30 18:19:34 +00:00
res = testclient.get("/login", status=200)
2020-08-20 08:31:36 +00:00
2021-12-06 14:40:30 +00:00
res.form["login"] = "John (johnny) Doe"
2021-01-23 21:30:43 +00:00
res = res.form.submit(status=302)
res = res.follow(status=200)
2020-08-20 08:31:36 +00:00
res.form["password"] = "incorrect horse"
2020-10-30 22:41:02 +00:00
res = res.form.submit(status=200)
assert ("error", "Login failed, please check your information") in res.flashes
2020-08-20 08:31:36 +00:00
def test_signin_with_alternate_attribute(testclient, user):
2020-10-30 18:19:34 +00:00
res = testclient.get("/login", status=200)
2020-08-20 08:45:33 +00:00
res.form["login"] = "user"
2021-01-23 21:30:43 +00:00
res = res.form.submit(status=302)
res = res.follow(status=200)
2020-08-20 08:45:33 +00:00
res.form["password"] = "correct horse battery staple"
res = res.form.submit()
2020-10-30 22:41:02 +00:00
res = res.follow(status=302)
res = res.follow(status=200)
2020-08-20 08:45:33 +00:00
with testclient.session_transaction() as session:
2023-02-05 18:08:25 +00:00
assert [user.id] == session.get("user_id")
2020-10-22 15:37:01 +00:00
def test_password_page_without_signin_in_redirects_to_login_page(testclient, user):
res = testclient.get("/password", status=302)
assert res.location == "/login"
def test_user_without_password_first_login(testclient, slapd_connection, smtpd):
assert len(smtpd.messages) == 0
u = User(
cn="Temp User",
sn="Temp",
uid="temp",
mail="john@doe.com",
)
u.save()
res = testclient.get("/login", status=200)
res.form["login"] = "Temp User"
res = res.form.submit(status=302)
assert res.location == "/firstlogin/temp"
res = res.follow(status=200)
res.mustcontain("First login")
res = res.form.submit(name="action", value="sendmail")
assert (
"success",
"A password initialization link has been sent at your email address. "
"You should receive it within a few minutes.",
) in res.flashes
assert len(smtpd.messages) == 1
assert "Password initialization" in smtpd.messages[0].get("Subject")
u.delete()
@mock.patch("smtplib.SMTP")
def test_first_login_account_initialization_mail_sending_failed(
SMTP, testclient, slapd_connection, smtpd
):
SMTP.side_effect = mock.Mock(side_effect=OSError("unit test mail error"))
assert len(smtpd.messages) == 0
u = User(
cn="Temp User",
sn="Temp",
uid="temp",
mail="john@doe.com",
)
u.save()
res = testclient.get("/firstlogin/temp")
res = res.form.submit(name="action", value="sendmail", expect_errors=True)
assert (
"success",
"A password initialization link has been sent at your email address. "
"You should receive it within a few minutes.",
) not in res.flashes
assert ("error", "Could not send the password initialization email") in res.flashes
assert len(smtpd.messages) == 0
u.delete()
2022-05-18 09:31:26 +00:00
2022-12-21 20:56:31 +00:00
def test_first_login_form_error(testclient, slapd_connection, smtpd):
assert len(smtpd.messages) == 0
u = User(
cn="Temp User",
sn="Temp",
uid="temp",
mail="john@doe.com",
)
u.save()
res = testclient.get("/firstlogin/temp", status=200)
res.form["csrf_token"] = "invalid"
res = res.form.submit(name="action", value="sendmail")
assert ("error", "Could not send the password initialization link.") in res.flashes
2022-12-21 20:56:31 +00:00
assert len(smtpd.messages) == 0
u.delete()
def test_first_login_page_unavailable_for_users_with_password(
testclient, slapd_connection, user
):
testclient.get("/firstlogin/user", status=404)
def test_user_password_deleted_during_login(testclient, slapd_connection):
u = User(
cn="Temp User",
sn="Temp",
uid="temp",
mail="john@doe.com",
userPassword="{SSHA}Yr1ZxSljRsKyaTB30suY2iZ1KRTStF1X",
)
u.save()
res = testclient.get("/login")
res.form["login"] = "Temp User"
res = res.form.submit().follow()
res.form["password"] = "correct horse battery staple"
u.userPassword = None
u.save()
res = res.form.submit(status=302)
assert res.location == "/firstlogin/temp"
u.delete()
def test_user_deleted_in_session(testclient, slapd_connection):
u = User(
cn="Jake Doe",
sn="Jake",
uid="jake",
mail="jake@doe.com",
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
)
u.save()
testclient.get("/profile/jake", status=403)
with testclient.session_transaction() as session:
2023-02-05 18:08:25 +00:00
session["user_id"] = [u.id]
testclient.get("/profile/jake", status=200)
u.delete()
testclient.get("/profile/jake", status=403)
with testclient.session_transaction() as session:
assert not session.get("user_id")
def test_impersonate(testclient, logged_admin, user):
res = testclient.get("/", status=302).follow(status=200)
assert "admin" == res.form["uid"].value
res = (
testclient.get("/impersonate/user", status=302)
.follow(status=302)
.follow(status=200)
)
assert "user" == res.form["uid"].value
testclient.get("/logout", status=302).follow(status=302).follow(status=200)
res = testclient.get("/", status=302).follow(status=200)
assert "admin" == res.form["uid"].value
def test_wrong_login(testclient, user):
testclient.app.config["HIDE_INVALID_LOGINS"] = True
res = testclient.get("/login", status=200)
res.form["login"] = "invalid"
2021-01-23 21:30:43 +00:00
res = res.form.submit(status=302)
res = res.follow(status=200)
res.form["password"] = "incorrect horse"
res = res.form.submit(status=200)
res.mustcontain(no="The login 'invalid' does not exist")
testclient.app.config["HIDE_INVALID_LOGINS"] = False
res = testclient.get("/login", status=200)
res.form["login"] = "invalid"
res = res.form.submit(status=200)
res.mustcontain("The login 'invalid' does not exist")
def test_admin_self_deletion(testclient, slapd_connection):
admin = User(
cn="Temp admin",
sn="admin",
uid="temp",
mail="temp@temp.com",
userPassword="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
)
admin.save()
with testclient.session_transaction() as sess:
2023-02-05 18:08:25 +00:00
sess["user_id"] = [admin.id]
res = testclient.get("/profile/temp")
res = (
res.form.submit(name="action", value="delete", status=302)
.follow(status=302)
.follow(status=200)
)
assert User.get("temp") is None
with testclient.session_transaction() as sess:
assert not sess.get("user_id")
def test_user_self_deletion(testclient, slapd_connection):
user = User(
cn="Temp user",
sn="user",
uid="temp",
mail="temp@temp.com",
userPassword="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
)
user.save()
with testclient.session_transaction() as sess:
2023-02-05 18:08:25 +00:00
sess["user_id"] = [user.id]
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = ["edit_self"]
res = testclient.get("/profile/temp")
res.mustcontain(no="Delete my account")
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = [
"edit_self",
"delete_account",
]
res = testclient.get("/profile/temp")
res.mustcontain("Delete my account")
res = (
res.form.submit(name="action", value="delete", status=302)
.follow(status=302)
.follow(status=200)
)
assert User.get("temp") is None
with testclient.session_transaction() as sess:
assert not sess.get("user_id")
2021-12-02 17:23:14 +00:00
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = []
def test_login_placeholder(testclient):
testclient.app.config["LDAP"]["USER_FILTER"] = "(uid={login})"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "jdoe"
testclient.app.config["LDAP"]["USER_FILTER"] = "(cn={login})"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "John Doe"
testclient.app.config["LDAP"]["USER_FILTER"] = "(mail={login})"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "john@doe.com"
testclient.app.config["LDAP"]["USER_FILTER"] = "(|(uid={login})(email={login}))"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "jdoe or john@doe.com"
2022-12-22 16:12:24 +00:00
def test_photo(testclient, user, jpeg_photo):
user.jpegPhoto = [jpeg_photo]
user.save()
res = testclient.get("/profile/user/jpegPhoto")
assert res.body == jpeg_photo
def test_photo_invalid_user(testclient, user):
res = testclient.get("/profile/invalid/jpegPhoto", status=404)
def test_photo_absent(testclient, user):
assert not user.jpegPhoto
res = testclient.get("/profile/user/jpegPhoto", status=404)
def test_photo_invalid_path(testclient, user):
testclient.get("/profile/user/invalid", status=404)