"""Unit tests for the lumi2.ldap module.""" import pytest import lumi2.ldap as ll import lumi2.usermodel as lu import lumi2.exceptions as le def test_assert_is_valid_base_dn(): for invalid_type in [None, 0, True, ("x",), ["x"]]: with pytest.raises(TypeError): ll._assert_is_valid_base_dn(invalid_type) for invalid_string in [ "", " ", "ou=foo", "abc", "\u1337", "a,b", "dc=,dc=", "dc=a,dc=b", "ou=example,dc=com", "dc=example,dc=" "dc=,dc=com", "dc=EXAMPLE,dc=com", "dc=example,dc=COM", "dc=example$,dc=com", "dc=foo,dc=com$", "dc=exa%,dc=com%", "dc=ex-ample,dc=com", "dc=f_oo,dc=com", ]: with pytest.raises(ll.InvalidStringFormatException): ll._assert_is_valid_base_dn(invalid_string) for valid_string in ["dc=example,dc=com", "dc=a,dc=de"]: assert ll._assert_is_valid_base_dn(valid_string) == None def test_assert_is_valid_ou_dn(): for invalid_type in [None, 0, True, ("x",), ["x"]]: with pytest.raises(TypeError): ll._assert_is_valid_ou_dn(invalid_type) for invalid_string in [ "", " ", "ou=foo", "abc", "\u1337", "ou=,dc=example,dc=com", "ou=foo,dc=example,dc=", "ou=foo,dc=example,", "ou=foo,dc=example", "ou=foo,ou=bar,dc=example", "ou=foo,ou=bar,dc=example,dc=com", "cn=foo,dc=example,dc=com", "ou=abc%,dc=example,dc=com", ]: with pytest.raises(ll.InvalidStringFormatException): print(invalid_string) ll._assert_is_valid_ou_dn(invalid_string) for valid_string in [ "ou=users,dc=example,dc=com", "ou=users,dc=a,dc=de", "ou=Users,dc=example,dc=com", "ou=abcdABCD,dc=example,dc=com", ]: assert ll._assert_is_valid_ou_dn(valid_string) == None def test_assert_is_valid_user_dn(): for invalid_type in [None, 0, True, ("x",), ["x"]]: with pytest.raises(TypeError): ll._assert_is_valid_user_dn(invalid_type) for invalid_string in [ "", " ", "uid=foo", "abc", "\u1337", "uid=,ou=foo,dc=bar,dc=baz", "uid=foo,ou=,dc=bar,dc=baz", "uid=foo,ou=bar,dc=,dc=baz", "uid=foo,ou=bar,dc=baz,dc=", "uid=foo,dc=example,dc=com", "uid=1foo,ou=bar,dc=example,dc=com", "uid=.bob,ou=foo,dc=bar,dc=baz", "uid=_foo,ou=foo,dc=bar,dc=baz", "uid=foo,uid=bar,ou=bar,dc=com", "cn=foo,ou=bar,dc=example,dc=com", "uid=abc%,ou=foo,dc=example,dc=com", ]: with pytest.raises(ll.InvalidStringFormatException): print(invalid_string) ll._assert_is_valid_user_dn(invalid_string) for valid_string in [ "uid=foo,ou=users,dc=example,dc=com", "uid=Foo-bar.baz_,ou=users,dc=a,dc=de", "uid=bOb_.-,ou=Users,dc=example,dc=com", "uid=foo,ou=foo,dc=bar,dc=baz", ]: assert ll._assert_is_valid_user_dn(valid_string) == None def test_assert_is_valid_group_dn(): for invalid_type in [None, 0, True, ("x",), ["x"]]: with pytest.raises(TypeError): ll._assert_is_valid_group_dn(invalid_type) for invalid_string in [ "", " ", "cn=foo", "abc", "\u1337", "cn=,ou=foo,dc=bar,dc=baz", "cn=foo,ou=,dc=bar,dc=baz", "cn=foo,ou=bar,dc=,dc=baz", "cn=foo,ou=bar,dc=baz,dc=", "cn=foo,dc=example,dc=com", "cn=1foo,ou=bar,dc=example,dc=com", "cn=.bob,ou=foo,dc=bar,dc=baz", "cn=_foo,ou=foo,dc=bar,dc=baz", "cn=foo,cn=bar,ou=bar,dc=com", "cn=abc%,ou=foo,dc=bar,dc=baz", "cn=abc1,ou=foo,dc=bar,dc=baz", "cn=ab-c,ou=foo,dc=bar,dc=baz", ]: with pytest.raises(ll.InvalidStringFormatException): print(invalid_string) ll._assert_is_valid_group_dn(invalid_string) for valid_string in [ "cn=foo,ou=groups,dc=example,dc=com", "cn=foo,ou=bar,dc=a,dc=de", "cn=Abc,ou=foo,dc=bar,dc=baz", ]: assert ll._assert_is_valid_group_dn(valid_string) == None def test_assert_is_valid_user_object_class(): for invalid_type in [None, 0, True, ("x",), ["x"]]: with pytest.raises(TypeError): ll._assert_is_valid_user_object_class(invalid_type) for invalid_string in [ "", " ", "\u1337", "organizationalUnit", "INETORGPERSON", "inetorgperson", ]: with pytest.raises(ll.InvalidStringFormatException): ll._assert_is_valid_user_object_class(invalid_string) assert ll._assert_is_valid_user_object_class("inetOrgPerson") == None def test_assert_is_valid_group_object_class(): for invalid_type in [None, 0, True, ("x",), ["x"]]: with pytest.raises(TypeError): ll._assert_is_valid_group_object_class(invalid_type) for invalid_string in [ "", " ", "\u1337", "organizationalUnit", "inetOrgPerson", "groupofuniquenames", "GROUPOFUNIQUENAMES", ]: with pytest.raises(ll.InvalidStringFormatException): ll._assert_is_valid_group_object_class(invalid_string) assert ll._assert_is_valid_group_object_class("groupOfUniqueNames") == None def test_assert_is_valid_connection(connection): for invalid_type in [1, "", None, (connection,)]: with pytest.raises(TypeError): ll._assert_is_valid_connection(invalid_type) assert ll._assert_is_valid_connection(connection) == None with pytest.raises(ll.InvalidConnectionException): connection.unbind() ll._assert_is_valid_connection(connection) def test_ou_exists(app, connection): with app.app_context(): for invalid_type in [1, True, None]: with pytest.raises(TypeError): ll.ou_exists(connection, invalid_type) with pytest.raises(ll.InvalidStringFormatException): ll.ou_exists(connection, "cn=foo,dc=example,dc=com") assert ll.ou_exists(connection, "ou=users,dc=example,dc=com") assert ll.ou_exists(connection, "ou=groups,dc=example,dc=com") assert not ll.ou_exists(connection, "ou=nonexsistent,dc=example,dc=com") def test_ou_exists_unpopulated(app, connection_empty_dit): with app.app_context(): assert not ll.ou_exists(connection_empty_dit, "ou=users,dc=example,dc=com") assert not ll.ou_exists(connection_empty_dit, "ou=groups,dc=example,dc=com") def test_create_ou(app, connection): with app.app_context(): with pytest.raises(ll.EntryExistsException): ll.create_ou(connection, "ou=users,dc=example,dc=com") assert not ll.ou_exists(connection, "ou=foo,dc=example,dc=com") ll.create_ou(connection, "ou=foo,dc=example,dc=com") assert ll.ou_exists(connection, "ou=foo,dc=example,dc=com") def test_user_exists(app, connection): with app.app_context(): assert ll.user_exists(connection, "uid=alice,ou=users,dc=example,dc=com") assert not ll.user_exists(connection, "uid=nonexistent,ou=users,dc=example,dc=com") def test_get_user(app, connection): with app.app_context(): for invalid_type in [1, True, None]: with pytest.raises(TypeError): ll.get_user(connection, invalid_type) with pytest.raises(ll.EntryNotFoundException): ll.get_user(connection, "nonexistent") assert ll.get_user(connection, "alice").username == "alice" def test_create_user(app, connection): with app.app_context(): user0 = lu.User( username="user0", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ) alice_duplicate = lu.User( username="alice", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ) with pytest.raises(ll.EntryExistsException): ll.create_user(connection, alice_duplicate) assert ll.create_user(connection, user0) == None def test_update_user(app, connection): with app.app_context(): user0 = lu.User( username="user0", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ) with pytest.raises(TypeError): ll.update_user(connection, None) with pytest.raises(ll.EntryNotFoundException): ll.update_user(connection, user0) ll.create_user(connection, user0) assert ll.get_user(connection, "user0").email == "valid@example.com" user0.email = "other@example.com" ll.update_user(connection, user0) assert ll.get_user(connection, "user0").email == "other@example.com" def test_delete_user(app, connection): with app.app_context(): user0 = lu.User( username="user0", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ) with pytest.raises(ll.EntryNotFoundException): ll.delete_user(connection, "user0") ll.create_user(connection, user0) assert ll.user_exists(connection, user0.get_dn()) ll.delete_user(connection, "user0") assert not ll.user_exists(connection, user0.get_dn()) # TODO check that group deletion works def test_get_users(app, connection): with app.app_context(): assert len(ll.get_users(connection)) == 2 for user in ll.get_users(connection): assert user.username in ["alice", "bobbuilder"] ll.create_user( connection, lu.User( username="user0", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ), ) assert len(ll.get_users(connection)) == 3 for user in ll.get_users(connection): assert user.username in ["alice", "bobbuilder", "user0"] def test_group_exists(app, connection): with app.app_context(): assert ll.group_exists( connection, "cn=employees,ou=groups,dc=example,dc=com" ) assert not ll.group_exists( connection, "cn=nonexistent,ou=groups,dc=example,dc=com" ) def test_create_group(app, connection): with app.app_context(): alice = ll.get_user(connection, "alice") testgroup = lu.Group("testgroup", {alice}) ll.create_group(connection, testgroup) assert ll.group_exists(connection, "cn=testgroup,ou=groups,dc=example,dc=com") with pytest.raises(ll.EntryExistsException): ll.create_group(connection, testgroup) user0 = lu.User( username="user0", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ) with pytest.raises(ll.EntryNotFoundException): ll.create_group(connection, lu.Group("invalidgroup", {user0})) def test_delete_group(app, connection): with app.app_context(): assert ll.group_exists(connection, "cn=employees,ou=groups,dc=example,dc=com") ll.delete_group(connection, "employees") assert not ll.group_exists(connection, "cn=employees,ou=groups,dc=example,dc=com") with pytest.raises(ll.EntryNotFoundException): ll.delete_group(connection, "employees") def test_update_group(app, connection): with app.app_context(): employees = ll.get_group(connection, "employees") user0 = lu.User( username="user0", password_hash=lu.User.generate_password_hash("password"), email="valid@example.com", first_name="Test", last_name="User", ) employees.members.add(user0) with pytest.raises(ll.EntryNotFoundException): ll.update_group(connection, employees) ll.create_user(connection, user0) ll.update_group(connection, employees) assert user0 in ll.get_group(connection, "employees").members def test_get_group(app, connection): with app.app_context(): employees = ll.get_group(connection, "employees") assert len(employees.members) == 2 with pytest.raises(ll.EntryNotFoundException): ll.get_group(connection, "nonexistent") def test_get_groups(app, connection): with app.app_context(): groups = ll.get_groups(connection) assert len(groups) == 2 for group in groups: ll.delete_group(connection, group.groupname) assert len(ll.get_groups(connection)) == 0 def test_get_groups_of_user(app, connection): with app.app_context(): alice = ll.get_user(connection, "alice") bobbuilder = ll.get_user(connection, "bobbuilder") assert len(ll.get_groups_of_user(connection, alice)) == 2 assert len(ll.get_groups_of_user(connection, bobbuilder)) == 1