diff --git a/awx/api/schema.py b/awx/api/schema.py index b0a7592c7f..05e9955b74 100644 --- a/awx/api/schema.py +++ b/awx/api/schema.py @@ -1,5 +1,6 @@ import warnings +from rest_framework.permissions import IsAuthenticated from drf_spectacular.openapi import AutoSchema from drf_spectacular.views import ( SpectacularAPIView, @@ -46,11 +47,29 @@ class CustomAutoSchema(AutoSchema): return getattr(self.view, 'deprecated', False) +class AuthenticatedSpectacularAPIView(SpectacularAPIView): + """SpectacularAPIView that requires authentication.""" + + permission_classes = [IsAuthenticated] + + +class AuthenticatedSpectacularSwaggerView(SpectacularSwaggerView): + """SpectacularSwaggerView that requires authentication.""" + + permission_classes = [IsAuthenticated] + + +class AuthenticatedSpectacularRedocView(SpectacularRedocView): + """SpectacularRedocView that requires authentication.""" + + permission_classes = [IsAuthenticated] + + # Schema view (returns OpenAPI schema JSON/YAML) -schema_view = SpectacularAPIView.as_view() +schema_view = AuthenticatedSpectacularAPIView.as_view() # Swagger UI view -swagger_ui_view = SpectacularSwaggerView.as_view(url_name='api:schema-json') +swagger_ui_view = AuthenticatedSpectacularSwaggerView.as_view(url_name='api:schema-json') # ReDoc UI view -redoc_view = SpectacularRedocView.as_view(url_name='api:schema-json') +redoc_view = AuthenticatedSpectacularRedocView.as_view(url_name='api:schema-json') diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index a88e6c95c3..c58a9d3cef 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -158,7 +158,7 @@ urlpatterns = [ re_path(r'^logout/$', LoggedLogoutView.as_view(next_page='/api/', redirect_field_name='next'), name='logout'), # Schema endpoints (available in all modes for API documentation and testing) re_path(r'^schema/$', schema_view, name='schema-json'), - re_path(r'^swagger/$', swagger_ui_view, name='schema-swagger-ui'), + re_path(r'^docs/$', swagger_ui_view, name='schema-swagger-ui'), re_path(r'^redoc/$', redoc_view, name='schema-redoc'), ] diff --git a/awx/api/views/root.py b/awx/api/views/root.py index 9b513337ad..0e369a1e97 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -59,7 +59,7 @@ class ApiRootView(APIView): data['custom_login_info'] = settings.CUSTOM_LOGIN_INFO data['login_redirect_override'] = settings.LOGIN_REDIRECT_OVERRIDE if MODE == 'development': - data['swagger'] = drf_reverse('api:schema-swagger-ui') + data['docs'] = drf_reverse('api:schema-swagger-ui') return Response(data) diff --git a/awx/main/tests/unit/api/test_schema.py b/awx/main/tests/unit/api/test_schema.py index ee6923ea4c..b6b59c2edc 100644 --- a/awx/main/tests/unit/api/test_schema.py +++ b/awx/main/tests/unit/api/test_schema.py @@ -1,7 +1,14 @@ import warnings from unittest.mock import Mock, patch -from awx.api.schema import CustomAutoSchema +from rest_framework.permissions import IsAuthenticated + +from awx.api.schema import ( + CustomAutoSchema, + AuthenticatedSpectacularAPIView, + AuthenticatedSpectacularSwaggerView, + AuthenticatedSpectacularRedocView, +) class TestCustomAutoSchema: @@ -248,3 +255,19 @@ class TestCustomAutoSchema: tags = schema.get_tags() # swagger_topic should take priority assert tags == ['Priority_Topic'] + + +class TestAuthenticatedSchemaViews: + """Unit tests for authenticated schema view classes.""" + + def test_authenticated_spectacular_api_view_requires_authentication(self): + """Test that AuthenticatedSpectacularAPIView requires authentication.""" + assert IsAuthenticated in AuthenticatedSpectacularAPIView.permission_classes + + def test_authenticated_spectacular_swagger_view_requires_authentication(self): + """Test that AuthenticatedSpectacularSwaggerView requires authentication.""" + assert IsAuthenticated in AuthenticatedSpectacularSwaggerView.permission_classes + + def test_authenticated_spectacular_redoc_view_requires_authentication(self): + """Test that AuthenticatedSpectacularRedocView requires authentication.""" + assert IsAuthenticated in AuthenticatedSpectacularRedocView.permission_classes diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 19ba236679..e05a745f10 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -1043,7 +1043,7 @@ SPECTACULAR_SETTINGS = { 'SCHEMA_PATH_PREFIX': r'/api/v[0-9]', 'DEFAULT_GENERATOR_CLASS': 'drf_spectacular.generators.SchemaGenerator', 'SCHEMA_COERCE_PATH_PK_SUFFIX': True, - 'CONTACT': {'email': 'contact@snippets.local'}, + 'CONTACT': {'email': 'controller-eng@redhat.com'}, 'LICENSE': {'name': 'Apache License'}, 'TERMS_OF_SERVICE': 'https://www.google.com/policies/terms/', # Use our custom schema class that handles swagger_topic and deprecated views