diff --git a/authentik/blueprints/api.py b/authentik/blueprints/api.py index 764945f7b42e..cd5860297f9a 100644 --- a/authentik/blueprints/api.py +++ b/authentik/blueprints/api.py @@ -217,10 +217,7 @@ def apply(self, request: Request, *args, **kwargs) -> Response: @extend_schema( request={"multipart/form-data": BlueprintUploadSerializer}, - responses={ - 204: BlueprintImportResultSerializer, - 400: BlueprintImportResultSerializer, - }, + responses={200: BlueprintImportResultSerializer}, ) @action(url_path="import", detail=False, methods=["POST"], parser_classes=(MultiPartParser,)) @validate( @@ -247,21 +244,13 @@ def import_(self, request: Request, body: BlueprintUploadSerializer) -> Response import_response = self.BlueprintImportResultSerializer( data={ - "logs": [], - "success": False, + "logs": [LogEventSerializer(log).data for log in logs], + "success": valid, } ) import_response.is_valid(raise_exception=True) - import_response.initial_data["logs"] = [LogEventSerializer(log).data for log in logs] - import_response.initial_data["success"] = valid - import_response.is_valid() - if not valid: - return Response(data=import_response.initial_data, status=200) - - successful = importer.apply() - import_response.initial_data["success"] = successful - import_response.is_valid() - if not successful: - return Response(data=import_response.initial_data, status=200) + if valid: + import_response.initial_data["success"] = importer.apply() + import_response.is_valid() return Response(data=import_response.initial_data, status=200) diff --git a/authentik/blueprints/tests/test_v1_api.py b/authentik/blueprints/tests/test_v1_api.py index cf3d3aaa99e5..a889ac6a3eb5 100644 --- a/authentik/blueprints/tests/test_v1_api.py +++ b/authentik/blueprints/tests/test_v1_api.py @@ -3,6 +3,7 @@ from json import dumps, loads from tempfile import NamedTemporaryFile, mkdtemp +from django.core.files.uploadedfile import SimpleUploadedFile from django.urls import reverse from rest_framework.test import APITestCase from yaml import dump @@ -141,6 +142,20 @@ def test_api_import_blank_path(self): ) self.assertEqual(res.status_code, 200) + def test_api_import_invalid_blueprint_returns_result_payload(self): + """Invalid blueprint content returns a result payload instead of a 400 response.""" + file = SimpleUploadedFile("invalid-blueprint.yaml", b'{"version": 3}') + + res = self.client.post( + reverse("authentik_api:blueprintinstance-import-"), + data={"file": file}, + format="multipart", + ) + + self.assertEqual(res.status_code, 200) + self.assertFalse(res.json()["success"]) + self.assertGreater(len(res.json()["logs"]), 0) + def test_api_import_unknown_path(self): """Path not in available blueprints is rejected (covers api.py:56).""" res = self.client.post( diff --git a/schema.yml b/schema.yml index 33583bf01aa8..a6792331fc0e 100644 --- a/schema.yml +++ b/schema.yml @@ -9678,18 +9678,14 @@ paths: security: - authentik: [] responses: - '204': + '200': content: application/json: schema: $ref: '#/components/schemas/BlueprintImportResult' description: '' '400': - content: - application/json: - schema: - $ref: '#/components/schemas/BlueprintImportResult' - description: '' + $ref: '#/components/responses/ValidationErrorResponse' '403': $ref: '#/components/responses/GenericErrorResponse' /oauth2/access_tokens/: