Skip to content

Commit 9252aa3

Browse files
committed
clean up
1 parent cceb668 commit 9252aa3

File tree

1 file changed

+59
-8
lines changed

1 file changed

+59
-8
lines changed

tests/integration/auth/test_ldap.py

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,16 +177,22 @@ async def test_authentication_and_role_mapping(
177177
status, access_token, refresh_token = _ldap_login(_app, admin.username, admin.password)
178178
_verify_ldap_login_success(status, access_token, refresh_token)
179179
admin_user = _verify_user_created(_app, admin)
180-
assert admin_user.role == UserRoleInput.ADMIN
180+
181+
# Member user (in members group)
182+
member = _create_test_user(_ldap_server, suffix, "member", UserRoleInput.MEMBER)
183+
status, access_token, refresh_token = _ldap_login(_app, member.username, member.password)
184+
_verify_ldap_login_success(status, access_token, refresh_token)
185+
member_user = _verify_user_created(_app, member)
181186

182187
# Viewer user (no groups → wildcard)
183188
viewer = _create_test_user(_ldap_server, suffix, "viewer", UserRoleInput.VIEWER, groups=[])
184189
status, access_token, refresh_token = _ldap_login(_app, viewer.username, viewer.password)
185190
_verify_ldap_login_success(status, access_token, refresh_token)
186191
viewer_user = _verify_user_created(_app, viewer)
187-
assert viewer_user.role == UserRoleInput.VIEWER
188192

189-
_delete_users(_app, _app.admin_secret, users=[admin_user.gid, viewer_user.gid])
193+
_delete_users(
194+
_app, _app.admin_secret, users=[admin_user.gid, member_user.gid, viewer_user.gid]
195+
)
190196

191197
async def test_invalid_credentials_rejected(
192198
self, _app: _AppInfo, _ldap_server: _LDAPServer
@@ -243,7 +249,17 @@ async def test_role_syncs_on_subsequent_login(
243249

244250
async def test_injection_prevention(self, _app: _AppInfo, _ldap_server: _LDAPServer) -> None:
245251
"""Test LDAP injection attempts are rejected."""
246-
for payload in ["*", "admin*", "*(objectClass=*)", "admin)(|(objectClass=*"]:
252+
payloads = [
253+
"*", # Wildcard
254+
"admin*", # Wildcard suffix
255+
"*(objectClass=*)", # Filter injection
256+
"admin)(|(objectClass=*", # Filter escape
257+
"admin\x00injected", # Null byte injection
258+
"admin\ninjected", # Newline injection
259+
"admin\r\ninjected", # CRLF injection
260+
")(cn=*", # DN injection
261+
]
262+
for payload in payloads:
247263
assert _ldap_login(_app, payload, _DEFAULT_PASSWORD)[0] == 401
248264

249265
async def test_unicode_credentials(self, _app: _AppInfo, _ldap_server: _LDAPServer) -> None:
@@ -263,6 +279,28 @@ async def test_unicode_credentials(self, _app: _AppInfo, _ldap_server: _LDAPServ
263279
assert user is not None
264280
_delete_users(_app, _app.admin_secret, users=[user.gid])
265281

282+
async def test_special_characters_in_password(
283+
self, _app: _AppInfo, _ldap_server: _LDAPServer
284+
) -> None:
285+
"""Test login with special characters in password (quotes, backslashes, etc.)."""
286+
suffix = token_hex(4)
287+
email = f"special_{suffix}@example.com"
288+
special_password = r'p@ss"word\with\'special<chars>&more!'
289+
_ldap_server.add_user(
290+
username=f"special_{suffix}",
291+
password=special_password,
292+
email=email,
293+
display_name="Special User",
294+
groups=[_MEMBER_GROUP],
295+
)
296+
status, access_token, refresh_token = _ldap_login(
297+
_app, f"special_{suffix}", special_password
298+
)
299+
_verify_ldap_login_success(status, access_token, refresh_token)
300+
user = _get_user_by_email(_app, email)
301+
assert user is not None
302+
_delete_users(_app, _app.admin_secret, users=[user.gid])
303+
266304
async def test_missing_email_rejected(self, _app: _AppInfo, _ldap_server: _LDAPServer) -> None:
267305
"""Test login fails when LDAP user has no email."""
268306
suffix = token_hex(4)
@@ -298,7 +336,11 @@ async def test_missing_display_name_uses_fallback(
298336
async def test_multiple_groups_uses_first_match(
299337
self, _app: _AppInfo, _ldap_server: _LDAPServer
300338
) -> None:
301-
"""Test user in multiple groups gets role from first matching mapping."""
339+
"""Test user in multiple groups gets role from first matching mapping.
340+
341+
group_role_mappings is evaluated in order: ADMIN, MEMBER, VIEWER (wildcard).
342+
User is in both MEMBER and ADMIN groups, but ADMIN mapping is checked first.
343+
"""
302344
suffix = token_hex(4)
303345
email = f"multi_{suffix}@example.com"
304346
_ldap_server.add_user(
@@ -312,7 +354,7 @@ async def test_multiple_groups_uses_first_match(
312354
assert status == 204
313355
user = _get_user_by_email(_app, email)
314356
assert user is not None
315-
assert user.role == UserRoleInput.ADMIN # ADMIN mapping comes first in config
357+
assert user.role == UserRoleInput.ADMIN # ADMIN mapping evaluated before MEMBER
316358
_delete_users(_app, _app.admin_secret, users=[user.gid])
317359

318360
async def test_group_dn_case_insensitive(
@@ -417,6 +459,8 @@ def test_email_change_preserves_identity_with_unique_id(
417459
},
418460
)
419461
assert response.status_code == 200
462+
response_json = response.json()
463+
assert not response_json.get("errors")
420464

421465
# First login (migrates pre-provisioned user to unique_id)
422466
_ldap_server.add_user(
@@ -449,6 +493,8 @@ def test_email_change_preserves_identity_with_unique_id(
449493
user_v2 = _get_user_by_email(app, email_v2)
450494
assert user_v2 is not None
451495
assert user_v2.gid == user_v1.gid, "Same user when unique_id is configured"
496+
assert user_v2.role == UserRoleInput.ADMIN
497+
assert user_v2.username == "Pre-Provisioned"
452498

453499
# Old email no longer exists
454500
assert _get_user_by_email(app, email_v1) is None
@@ -499,7 +545,9 @@ async def test_ldap_user_graphql_auth_method(
499545
)
500546

501547
assert graphql_response.status_code == 200
502-
data = graphql_response.json()
548+
graphql_data = graphql_response.json()
549+
assert not graphql_data.get("errors"), graphql_data.get("errors")
550+
data = graphql_data
503551

504552
# Find our LDAP user in the response
505553
users = data["data"]["users"]["edges"]
@@ -659,7 +707,9 @@ def test_ldap_allow_sign_up_false_with_email_lookup(
659707
},
660708
)
661709
assert create_response.status_code == 200
662-
user_data = create_response.json()["data"]["createUser"]["user"]
710+
create_json = create_response.json()
711+
assert not create_json.get("errors"), create_json.get("errors")
712+
user_data = create_json["data"]["createUser"]["user"]
663713
assert user_data["authMethod"] == "LDAP"
664714
created_user_gid = user_data["id"]
665715

@@ -684,6 +734,7 @@ def test_ldap_allow_sign_up_false_with_email_lookup(
684734
assert updated_user is not None
685735
# Username stays stable from admin creation (prevents collisions on displayName changes)
686736
assert updated_user.profile.username == "John Doe"
737+
assert updated_user.role == UserRoleInput.ADMIN
687738

688739
# Step 5: Verify subsequent logins work
689740
status, access_token, refresh_token = _ldap_login(

0 commit comments

Comments
 (0)