@@ -860,154 +860,3 @@ def test(self):
860860 self .api_version_reverse ("streaming_chat" ), TestChatView .VALID_PAYLOAD , format = "json"
861861 )
862862 self .assertEqual (response .status_code , 401 )
863-
864-
865- class TestStreamingChatViewCSRF (APIVersionTestCaseBase , WisdomServiceAPITestCaseBase ):
866- """Test CSRF validation for the streaming_chat endpoint."""
867-
868- api_version = "v1"
869-
870- def setUp (self ):
871- super ().setUp ()
872- (org , _ ) = Organization .objects .get_or_create (id = 123 , telemetry_opt_out = False )
873- self .user .organization = org
874- self .user .rh_internal = True
875- self .user .save ()
876-
877- @override_settings (CHATBOT_DEFAULT_PROVIDER = "wisdom" )
878- @mock .patch (
879- "ansible_ai_connect.ai.api.model_pipelines.http.pipelines."
880- "HttpStreamingChatBotPipeline.get_streaming_http_response" ,
881- )
882- def test_csrf_validation_fails_without_token (self , mock_response ):
883- """Test that CSRF validation fails when no CSRF token is provided."""
884-
885- mock_response .return_value = TestStreamingChatView .mocked_response (
886- json = TestChatView .VALID_PAYLOAD
887- )
888-
889- with patch .object (
890- apps .get_app_config ("ai" ),
891- "get_model_pipeline" ,
892- Mock (return_value = HttpStreamingChatBotPipeline (mock_pipeline_config ("http" ))),
893- ):
894- from rest_framework .test import APIClient
895-
896- csrf_client = APIClient (enforce_csrf_checks = True )
897- csrf_client .force_authenticate (user = self .user )
898-
899- response = csrf_client .post (
900- self .api_version_reverse ("streaming_chat" ),
901- TestChatView .VALID_PAYLOAD ,
902- format = "json" ,
903- )
904-
905- self .assertEqual (response .status_code , 403 )
906- self .assertIn ("CSRF" , str (response .data ))
907-
908- @override_settings (CHATBOT_DEFAULT_PROVIDER = "wisdom" )
909- @mock .patch (
910- "ansible_ai_connect.ai.api.model_pipelines.http.pipelines."
911- "HttpStreamingChatBotPipeline.get_streaming_http_response" ,
912- )
913- def test_csrf_validation_succeeds_with_valid_token (self , mock_response ):
914- """Test that CSRF validation succeeds when a valid CSRF token is provided."""
915- mock_response .return_value = TestStreamingChatView .mocked_response (
916- json = TestChatView .VALID_PAYLOAD
917- )
918-
919- with patch .object (
920- apps .get_app_config ("ai" ),
921- "get_model_pipeline" ,
922- Mock (return_value = HttpStreamingChatBotPipeline (mock_pipeline_config ("http" ))),
923- ):
924- from django .middleware .csrf import _get_new_csrf_string
925- from rest_framework .test import APIClient
926-
927- csrf_client = APIClient (enforce_csrf_checks = True )
928- csrf_client .force_authenticate (user = self .user )
929-
930- token = _get_new_csrf_string ()
931- csrf_client .cookies ["csrftoken" ] = token
932-
933- response = csrf_client .post (
934- self .api_version_reverse ("streaming_chat" ),
935- TestChatView .VALID_PAYLOAD ,
936- format = "json" ,
937- HTTP_X_CSRFTOKEN = token ,
938- )
939-
940- self .assertNotEqual (response .status_code , 403 )
941-
942- @override_settings (CHATBOT_DEFAULT_PROVIDER = "wisdom" )
943- @mock .patch (
944- "ansible_ai_connect.ai.api.model_pipelines.http.pipelines."
945- "HttpStreamingChatBotPipeline.get_streaming_http_response" ,
946- )
947- def test_csrf_validation_fails_with_invalid_token (self , mock_response ):
948- """Test that CSRF validation fails when an invalid CSRF token is provided."""
949- mock_response .return_value = TestStreamingChatView .mocked_response (
950- json = TestChatView .VALID_PAYLOAD
951- )
952-
953- with patch .object (
954- apps .get_app_config ("ai" ),
955- "get_model_pipeline" ,
956- Mock (return_value = HttpStreamingChatBotPipeline (mock_pipeline_config ("http" ))),
957- ):
958- from rest_framework .test import APIClient
959-
960- csrf_client = APIClient (enforce_csrf_checks = True )
961- csrf_client .force_authenticate (user = self .user )
962-
963- response = csrf_client .post (
964- self .api_version_reverse ("streaming_chat" ),
965- TestChatView .VALID_PAYLOAD ,
966- format = "json" ,
967- HTTP_X_CSRFTOKEN = "invalid_token_12345" ,
968- )
969-
970- self .assertEqual (response .status_code , 403 )
971- self .assertIn ("CSRF" , str (response .data ))
972-
973- @override_settings (CHATBOT_DEFAULT_PROVIDER = "wisdom" )
974- @mock .patch (
975- "ansible_ai_connect.ai.api.model_pipelines.http.pipelines."
976- "HttpStreamingChatBotPipeline.get_streaming_http_response" ,
977- )
978- def test_csrf_validation_fails_with_valid_session_and_invalid_token (self , mock_response ):
979- """Test that CSRF validation fails when a valid session present but the token is invalid.
980-
981- This reproduces the real-world scenario described in the PR: sessionid is valid (user
982- has a session) but the X-CSRFToken value does not match the csrftoken cookie.
983- """
984- mock_response .return_value = TestStreamingChatView .mocked_response (
985- json = TestChatView .VALID_PAYLOAD
986- )
987-
988- with patch .object (
989- apps .get_app_config ("ai" ),
990- "get_model_pipeline" ,
991- Mock (return_value = HttpStreamingChatBotPipeline (mock_pipeline_config ("http" ))),
992- ):
993- from rest_framework .test import APIClient
994-
995- csrf_client = APIClient (enforce_csrf_checks = True )
996- csrf_client .force_authenticate (user = self .user )
997-
998- # Simulate a valid session cookie being present
999- csrf_client .cookies ["sessionid" ] = "validsession123"
1000-
1001- # Simulate a csrftoken cookie that does NOT match the header token
1002- csrf_client .cookies ["csrftoken" ] = "expected_token_abc"
1003-
1004- # Send a mismatched/invalid header token
1005- response = csrf_client .post (
1006- self .api_version_reverse ("streaming_chat" ),
1007- TestChatView .VALID_PAYLOAD ,
1008- format = "json" ,
1009- HTTP_X_CSRFTOKEN = "invalid_token_12345" ,
1010- )
1011-
1012- self .assertEqual (response .status_code , 403 )
1013- self .assertIn ("CSRF" , str (response .data ))
0 commit comments