forked from Github-Mirrors/canaille
352 lines
11 KiB
Python
352 lines
11 KiB
Python
from unittest import mock
|
|
|
|
from canaille.ldap_backend.ldapobject import LDAPObject
|
|
from canaille.models import User
|
|
|
|
|
|
def test_index(testclient, user):
|
|
res = testclient.get("/", status=302)
|
|
assert res.location == "/login"
|
|
|
|
with testclient.session_transaction() as sess:
|
|
sess["user_id"] = [user.id]
|
|
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):
|
|
with testclient.session_transaction() as session:
|
|
assert not session.get("user_id")
|
|
|
|
res = testclient.get("/login", status=200)
|
|
|
|
res.form["login"] = "John (johnny) Doe"
|
|
res = res.form.submit(status=302)
|
|
res = res.follow(status=200)
|
|
|
|
with testclient.session_transaction() as session:
|
|
assert "John (johnny) Doe" == session.get("attempt_login")
|
|
|
|
res.form["password"] = "correct horse battery staple"
|
|
res = res.form.submit()
|
|
res = res.follow(status=302)
|
|
res = res.follow(status=200)
|
|
|
|
with testclient.session_transaction() as session:
|
|
assert [user.id] == session.get("user_id")
|
|
assert "attempt_login" not in session
|
|
|
|
res = testclient.get("/login", status=302)
|
|
|
|
res = testclient.get("/logout")
|
|
assert (
|
|
"success",
|
|
"You have been disconnected. See you next time John (johnny) Doe",
|
|
) in res.flashes
|
|
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
|
|
|
|
with testclient.session_transaction() as session:
|
|
assert not session.get("user_id")
|
|
|
|
|
|
def test_signin_wrong_password(testclient, user):
|
|
with testclient.session_transaction() as session:
|
|
assert not session.get("user_id")
|
|
|
|
res = testclient.get("/login", status=200)
|
|
|
|
res.form["login"] = "John (johnny) Doe"
|
|
res = res.form.submit(status=302)
|
|
res = res.follow(status=200)
|
|
res.form["password"] = "incorrect horse"
|
|
res = res.form.submit(status=200)
|
|
assert ("error", "Login failed, please check your information") in res.flashes
|
|
|
|
|
|
def test_signin_with_alternate_attribute(testclient, user):
|
|
res = testclient.get("/login", status=200)
|
|
|
|
res.form["login"] = "user"
|
|
res = res.form.submit(status=302)
|
|
res = res.follow(status=200)
|
|
|
|
res.form["password"] = "correct horse battery staple"
|
|
res = res.form.submit()
|
|
res = res.follow(status=302)
|
|
res = res.follow(status=200)
|
|
|
|
with testclient.session_transaction() as session:
|
|
assert [user.id] == session.get("user_id")
|
|
|
|
|
|
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(
|
|
formatted_name="Temp User",
|
|
family_name="Temp",
|
|
user_name="temp",
|
|
email="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(
|
|
formatted_name="Temp User",
|
|
family_name="Temp",
|
|
user_name="temp",
|
|
email="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()
|
|
|
|
|
|
def test_first_login_form_error(testclient, slapd_connection, smtpd):
|
|
assert len(smtpd.messages) == 0
|
|
u = User(
|
|
formatted_name="Temp User",
|
|
family_name="Temp",
|
|
user_name="temp",
|
|
email="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", status=400)
|
|
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(
|
|
formatted_name="Temp User",
|
|
family_name="Temp",
|
|
user_name="temp",
|
|
email="john@doe.com",
|
|
password="{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.password = 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(
|
|
formatted_name="Jake Doe",
|
|
family_name="Jake",
|
|
user_name="jake",
|
|
email="jake@doe.com",
|
|
password="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
|
|
)
|
|
u.save()
|
|
testclient.get("/profile/jake", status=403)
|
|
|
|
with testclient.session_transaction() as session:
|
|
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).click("Account information")
|
|
)
|
|
assert "admin" == res.form["user_name"].value
|
|
|
|
res = (
|
|
testclient.get("/impersonate/user", status=302)
|
|
.follow(status=302)
|
|
.follow(status=200)
|
|
.click("Account information")
|
|
)
|
|
assert "user" == res.form["user_name"].value
|
|
|
|
testclient.get("/logout", status=302).follow(status=302).follow(status=200)
|
|
|
|
res = (
|
|
testclient.get("/", status=302).follow(status=200).click("Account information")
|
|
)
|
|
assert "admin" == res.form["user_name"].value
|
|
|
|
|
|
def test_wrong_login(testclient, user):
|
|
testclient.app.config["HIDE_INVALID_LOGINS"] = True
|
|
|
|
res = testclient.get("/login", status=200)
|
|
res.form["login"] = "invalid"
|
|
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(
|
|
formatted_name="Temp admin",
|
|
family_name="admin",
|
|
user_name="temp",
|
|
email="temp@temp.com",
|
|
password="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
|
)
|
|
admin.save()
|
|
with testclient.session_transaction() as sess:
|
|
sess["user_id"] = [admin.id]
|
|
|
|
res = testclient.get("/profile/temp/settings")
|
|
res = (
|
|
res.form.submit(name="action", value="delete", status=302)
|
|
.follow(status=302)
|
|
.follow(status=200)
|
|
)
|
|
|
|
assert User.get_from_login("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(
|
|
formatted_name="Temp user",
|
|
family_name="user",
|
|
user_name="temp",
|
|
email="temp@temp.com",
|
|
password="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
|
|
)
|
|
user.save()
|
|
with testclient.session_transaction() as sess:
|
|
sess["user_id"] = [user.id]
|
|
|
|
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = ["edit_self"]
|
|
res = testclient.get("/profile/temp/settings")
|
|
res.mustcontain(no="Delete my account")
|
|
|
|
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = [
|
|
"edit_self",
|
|
"delete_account",
|
|
]
|
|
res = testclient.get("/profile/temp/settings")
|
|
res.mustcontain("Delete my account")
|
|
res = (
|
|
res.form.submit(name="action", value="delete", status=302)
|
|
.follow(status=302)
|
|
.follow(status=200)
|
|
)
|
|
|
|
assert User.get_from_login("temp") is None
|
|
|
|
with testclient.session_transaction() as sess:
|
|
assert not sess.get("user_id")
|
|
|
|
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})(mail={login}))"
|
|
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
|
|
assert placeholder == "jdoe or john@doe.com"
|