@@ -433,6 +433,110 @@ def test_api_v3_permission_no_groups_found(client, permissions, mock_ldap, caplo
433433 assert f"Permission denied: { expected_error } " in caplog .text
434434
435435
436+ def test_api_v3_permission_oidc_groups_match (client , permissions , mock_ldap , app ):
437+ """OIDC groups match — authorized without LDAP."""
438+ permissions .append (
439+ {
440+ "groups" : ["testgroup1" ],
441+ "testcases" : ["testcase1*" ],
442+ }
443+ )
444+ app .oidc .current_token_identity = {
445+ "uid" : "testuser1" ,
446+ "realm_access" : {"roles" : ["testgroup1" ]},
447+ }
448+ data = brew_build_request_data ()
449+ r = client .post ("/api/v3/results/brew-builds" , json = data )
450+ assert r .status_code == 201 , r .text
451+ mock_ldap .search_s .assert_not_called ()
452+ app .oidc .current_token_identity = {"uid" : "testuser1" }
453+
454+
455+ def test_api_v3_permission_oidc_groups_no_match_ldap_fallback (
456+ client , permissions , mock_ldap , caplog , app
457+ ):
458+ """OIDC groups don't match, LDAP authorizes with deprecation warning."""
459+ permissions .append (
460+ {
461+ "groups" : ["testgroup1" ],
462+ "testcases" : ["testcase1*" ],
463+ }
464+ )
465+ app .oidc .current_token_identity = {
466+ "uid" : "testuser1" ,
467+ "realm_access" : {"roles" : ["other_group" ]},
468+ }
469+ data = brew_build_request_data ()
470+ r = client .post ("/api/v3/results/brew-builds" , json = data )
471+ assert r .status_code == 201 , r .text
472+ mock_ldap .search_s .assert_called_once ()
473+ assert "falling back to LDAP" in caplog .text
474+ assert "LDAP authorized" in caplog .text
475+ app .oidc .current_token_identity = {"uid" : "testuser1" }
476+
477+
478+ def test_api_v3_permission_oidc_groups_no_match_ldap_denies (
479+ client , permissions , mock_ldap , caplog , app
480+ ):
481+ """OIDC groups don't match, LDAP doesn't authorize — Forbidden."""
482+ permissions .append (
483+ {
484+ "groups" : ["testgroup1" ],
485+ "testcases" : ["testcase1*" ],
486+ }
487+ )
488+ app .oidc .current_token_identity = {
489+ "uid" : "testuser1" ,
490+ "realm_access" : {"roles" : ["other_group" ]},
491+ }
492+ mock_ldap .search_s .return_value = []
493+ data = brew_build_request_data ()
494+ r = client .post ("/api/v3/results/brew-builds" , json = data )
495+ assert r .status_code == 403 , r .text
496+ assert "falling back to LDAP" in caplog .text
497+ app .oidc .current_token_identity = {"uid" : "testuser1" }
498+
499+
500+ def test_api_v3_permission_oidc_groups_match_without_ldap (
501+ client , permissions , mock_ldap , app
502+ ):
503+ """OIDC groups match — authorized even when LDAP is not configured."""
504+ permissions .append (
505+ {
506+ "groups" : ["testgroup1" ],
507+ "testcases" : ["testcase1*" ],
508+ }
509+ )
510+ app .oidc .current_token_identity = {
511+ "uid" : "testuser1" ,
512+ "realm_access" : {"roles" : ["testgroup1" ]},
513+ }
514+ data = brew_build_request_data ()
515+ with patch .dict (app .config , {"LDAP_HOST" : None , "LDAP_SEARCHES" : None }):
516+ r = client .post ("/api/v3/results/brew-builds" , json = data )
517+ assert r .status_code == 201 , r .text
518+ mock_ldap .search_s .assert_not_called ()
519+ app .oidc .current_token_identity = {"uid" : "testuser1" }
520+
521+
522+ def test_api_v3_permission_oidc_groups_none_falls_back_to_ldap (
523+ client , permissions , mock_ldap , app
524+ ):
525+ """No OIDC groups claim — falls back to LDAP as before."""
526+ permissions .append (
527+ {
528+ "groups" : ["testgroup1" ],
529+ "testcases" : ["testcase1*" ],
530+ }
531+ )
532+ # current_token_identity has no realm_access — so get_oidc_groups returns None
533+ app .oidc .current_token_identity = {"uid" : "testuser1" }
534+ data = brew_build_request_data ()
535+ r = client .post ("/api/v3/results/brew-builds" , json = data )
536+ assert r .status_code == 201 , r .text
537+ mock_ldap .search_s .assert_called_once ()
538+
539+
436540@pytest .mark .parametrize ("params_class" , RESULTS_PARAMS_CLASSES )
437541def test_api_v3_consistency (params_class , client ):
438542 """
0 commit comments