Integrate OpenAPI/Swagger documentation using drf-spectacular, enhancing API documentation with comprehensive guides and schema generation. Add multiple documentation files covering authentication, error codes, rate limiting, and migration strategies. Update settings and URLs to support new documentation endpoints and schema configurations.
This commit is contained in:
37
backend/=0.27.0
Normal file
37
backend/=0.27.0
Normal file
@@ -0,0 +1,37 @@
|
||||
Collecting drf-spectacular
|
||||
Downloading drf_spectacular-0.29.0-py3-none-any.whl.metadata (14 kB)
|
||||
Requirement already satisfied: Django>=2.2 in /usr/local/lib/python3.11/site-packages (from drf-spectacular) (5.2.8)
|
||||
Requirement already satisfied: djangorestframework>=3.10.3 in /usr/local/lib/python3.11/site-packages (from drf-spectacular) (3.16.1)
|
||||
Collecting uritemplate>=2.0.0 (from drf-spectacular)
|
||||
Downloading uritemplate-4.2.0-py3-none-any.whl.metadata (2.6 kB)
|
||||
Collecting PyYAML>=5.1 (from drf-spectacular)
|
||||
Downloading pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (2.4 kB)
|
||||
Collecting jsonschema>=2.6.0 (from drf-spectacular)
|
||||
Downloading jsonschema-4.25.1-py3-none-any.whl.metadata (7.6 kB)
|
||||
Collecting inflection>=0.3.1 (from drf-spectacular)
|
||||
Downloading inflection-0.5.1-py2.py3-none-any.whl.metadata (1.7 kB)
|
||||
Requirement already satisfied: asgiref>=3.8.1 in /usr/local/lib/python3.11/site-packages (from Django>=2.2->drf-spectacular) (3.10.0)
|
||||
Requirement already satisfied: sqlparse>=0.3.1 in /usr/local/lib/python3.11/site-packages (from Django>=2.2->drf-spectacular) (0.5.3)
|
||||
Collecting attrs>=22.2.0 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading attrs-25.4.0-py3-none-any.whl.metadata (10 kB)
|
||||
Collecting jsonschema-specifications>=2023.03.6 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl.metadata (2.9 kB)
|
||||
Collecting referencing>=0.28.4 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading referencing-0.37.0-py3-none-any.whl.metadata (2.8 kB)
|
||||
Collecting rpds-py>=0.7.1 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading rpds_py-0.28.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.1 kB)
|
||||
Requirement already satisfied: typing-extensions>=4.4.0 in /usr/local/lib/python3.11/site-packages (from referencing>=0.28.4->jsonschema>=2.6.0->drf-spectacular) (4.15.0)
|
||||
Downloading drf_spectacular-0.29.0-py3-none-any.whl (105 kB)
|
||||
Downloading inflection-0.5.1-py2.py3-none-any.whl (9.5 kB)
|
||||
Downloading jsonschema-4.25.1-py3-none-any.whl (90 kB)
|
||||
Downloading attrs-25.4.0-py3-none-any.whl (67 kB)
|
||||
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl (18 kB)
|
||||
Downloading pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (806 kB)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 806.6/806.6 kB 36.0 MB/s 0:00:00
|
||||
Downloading referencing-0.37.0-py3-none-any.whl (26 kB)
|
||||
Downloading rpds_py-0.28.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (382 kB)
|
||||
Downloading uritemplate-4.2.0-py3-none-any.whl (11 kB)
|
||||
Installing collected packages: uritemplate, rpds-py, PyYAML, inflection, attrs, referencing, jsonschema-specifications, jsonschema, drf-spectacular
|
||||
|
||||
Successfully installed PyYAML-6.0.3 attrs-25.4.0 drf-spectacular-0.29.0 inflection-0.5.1 jsonschema-4.25.1 jsonschema-specifications-2025.9.1 referencing-0.37.0 rpds-py-0.28.0 uritemplate-4.2.0
|
||||
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
|
||||
@@ -1,4 +1,6 @@
|
||||
"""
|
||||
IGNY8 API Module
|
||||
IGNY8 API Package
|
||||
Unified API Standard v1.0
|
||||
"""
|
||||
|
||||
# Import schema extensions to register them with drf-spectacular
|
||||
from igny8_core.api import schema_extensions # noqa
|
||||
|
||||
39
backend/igny8_core/api/schema_extensions.py
Normal file
39
backend/igny8_core/api/schema_extensions.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
OpenAPI Schema Extensions for drf-spectacular
|
||||
Custom extensions for JWT authentication and unified response format
|
||||
"""
|
||||
from drf_spectacular.extensions import OpenApiAuthenticationExtension
|
||||
from drf_spectacular.plumbing import build_bearer_security_scheme_object
|
||||
from drf_spectacular.utils import extend_schema, OpenApiResponse
|
||||
from rest_framework import status
|
||||
|
||||
|
||||
class JWTAuthenticationExtension(OpenApiAuthenticationExtension):
|
||||
"""
|
||||
OpenAPI extension for JWT Bearer Token authentication
|
||||
"""
|
||||
target_class = 'igny8_core.api.authentication.JWTAuthentication'
|
||||
name = 'JWTAuthentication'
|
||||
|
||||
def get_security_definition(self, auto_schema):
|
||||
return build_bearer_security_scheme_object(
|
||||
header_name='Authorization',
|
||||
token_prefix='Bearer',
|
||||
bearer_format='JWT'
|
||||
)
|
||||
|
||||
|
||||
class CSRFExemptSessionAuthenticationExtension(OpenApiAuthenticationExtension):
|
||||
"""
|
||||
OpenAPI extension for CSRF-exempt session authentication
|
||||
"""
|
||||
target_class = 'igny8_core.api.authentication.CSRFExemptSessionAuthentication'
|
||||
name = 'SessionAuthentication'
|
||||
|
||||
def get_security_definition(self, auto_schema):
|
||||
return {
|
||||
'type': 'apiKey',
|
||||
'in': 'cookie',
|
||||
'name': 'sessionid'
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ INSTALLED_APPS = [
|
||||
'rest_framework',
|
||||
'django_filters',
|
||||
'corsheaders',
|
||||
'drf_spectacular', # OpenAPI 3.0 schema generation
|
||||
'igny8_core.auth.apps.Igny8CoreAuthConfig', # Use app config with custom label
|
||||
'igny8_core.ai.apps.AIConfig', # AI Framework
|
||||
'igny8_core.modules.planner.apps.PlannerConfig',
|
||||
@@ -245,6 +246,142 @@ REST_FRAMEWORK = {
|
||||
# Default fallback
|
||||
'default': '100/min', # Default for endpoints without scope
|
||||
},
|
||||
# OpenAPI Schema Generation (drf-spectacular)
|
||||
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
|
||||
}
|
||||
|
||||
# drf-spectacular Settings for OpenAPI 3.0 Schema Generation
|
||||
SPECTACULAR_SETTINGS = {
|
||||
'TITLE': 'IGNY8 API v1.0',
|
||||
'DESCRIPTION': '''
|
||||
IGNY8 Unified API Standard v1.0
|
||||
|
||||
A comprehensive REST API for content planning, creation, and management.
|
||||
|
||||
## Features
|
||||
- **Unified Response Format**: All endpoints return consistent JSON structure
|
||||
- **Layered Authorization**: Authentication → Tenant Access → Role → Site/Sector
|
||||
- **Centralized Error Handling**: All errors wrapped in unified format
|
||||
- **Scoped Rate Limiting**: Different limits for different operation types
|
||||
- **Tenant Isolation**: All resources scoped by account/site/sector
|
||||
- **Request Tracking**: Every request has a unique ID for debugging
|
||||
|
||||
## Authentication
|
||||
All endpoints require JWT Bearer token authentication except:
|
||||
- `POST /api/v1/auth/login/` - User login
|
||||
- `POST /api/v1/auth/register/` - User registration
|
||||
|
||||
Include token in Authorization header:
|
||||
```
|
||||
Authorization: Bearer <your_access_token>
|
||||
```
|
||||
|
||||
## Response Format
|
||||
All successful responses follow this format:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {...},
|
||||
"message": "Optional success message",
|
||||
"request_id": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
All error responses follow this format:
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Error message",
|
||||
"errors": {
|
||||
"field_name": ["Field-specific errors"]
|
||||
},
|
||||
"request_id": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
## Rate Limiting
|
||||
Rate limits are scoped by operation type. Check response headers:
|
||||
- `X-Throttle-Limit`: Maximum requests allowed
|
||||
- `X-Throttle-Remaining`: Remaining requests in current window
|
||||
- `X-Throttle-Reset`: Time when limit resets (Unix timestamp)
|
||||
|
||||
## Pagination
|
||||
List endpoints support pagination with query parameters:
|
||||
- `page`: Page number (default: 1)
|
||||
- `page_size`: Items per page (default: 10, max: 100)
|
||||
|
||||
Paginated responses include:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"count": 100,
|
||||
"next": "http://api.igny8.com/api/v1/endpoint/?page=2",
|
||||
"previous": null,
|
||||
"results": [...]
|
||||
}
|
||||
```
|
||||
''',
|
||||
'VERSION': '1.0.0',
|
||||
'SERVE_INCLUDE_SCHEMA': False,
|
||||
'SCHEMA_PATH_PREFIX': '/api/v1',
|
||||
'COMPONENT_SPLIT_REQUEST': True,
|
||||
'COMPONENT_NO_READ_ONLY_REQUIRED': True,
|
||||
# Custom schema generator to include unified response format
|
||||
'SCHEMA_GENERATOR_CLASS': 'drf_spectacular.generators.SchemaGenerator',
|
||||
# Include request/response examples
|
||||
'SERVE_PERMISSIONS': ['rest_framework.permissions.AllowAny'],
|
||||
'SERVE_AUTHENTICATION': None, # Allow unauthenticated access to docs
|
||||
# Tags for grouping endpoints
|
||||
'TAGS': [
|
||||
{'name': 'Authentication', 'description': 'User authentication and registration'},
|
||||
{'name': 'Planner', 'description': 'Keywords, clusters, and content ideas'},
|
||||
{'name': 'Writer', 'description': 'Tasks, content, and images'},
|
||||
{'name': 'System', 'description': 'Settings, prompts, and integrations'},
|
||||
{'name': 'Billing', 'description': 'Credits, usage, and transactions'},
|
||||
],
|
||||
# Custom response format documentation
|
||||
'EXTENSIONS_INFO': {
|
||||
'x-code-samples': [
|
||||
{
|
||||
'lang': 'Python',
|
||||
'source': '''
|
||||
import requests
|
||||
|
||||
headers = {
|
||||
'Authorization': 'Bearer <your_token>',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
response = requests.get('https://api.igny8.com/api/v1/planner/keywords/', headers=headers)
|
||||
data = response.json()
|
||||
|
||||
if data['success']:
|
||||
keywords = data['results'] # or data['data'] for single objects
|
||||
else:
|
||||
print(f"Error: {data['error']}")
|
||||
'''
|
||||
},
|
||||
{
|
||||
'lang': 'JavaScript',
|
||||
'source': '''
|
||||
const response = await fetch('https://api.igny8.com/api/v1/planner/keywords/', {
|
||||
headers: {
|
||||
'Authorization': 'Bearer <your_token>',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
const keywords = data.results || data.data;
|
||||
} else {
|
||||
console.error('Error:', data.error);
|
||||
}
|
||||
'''
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# CORS Configuration
|
||||
|
||||
@@ -16,6 +16,11 @@ Including another URLconf
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from drf_spectacular.views import (
|
||||
SpectacularAPIView,
|
||||
SpectacularRedocView,
|
||||
SpectacularSwaggerView,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
@@ -24,4 +29,8 @@ urlpatterns = [
|
||||
path('api/v1/writer/', include('igny8_core.modules.writer.urls')),
|
||||
path('api/v1/system/', include('igny8_core.modules.system.urls')),
|
||||
path('api/v1/billing/', include('igny8_core.modules.billing.urls')), # Billing endpoints
|
||||
# OpenAPI Schema and Documentation
|
||||
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
|
||||
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
|
||||
path('api/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
|
||||
]
|
||||
|
||||
@@ -12,3 +12,4 @@ celery>=5.3.0
|
||||
beautifulsoup4>=4.12.0
|
||||
psutil>=5.9.0
|
||||
docker>=7.0.0
|
||||
drf-spectacular>=0.27.0
|
||||
|
||||
Reference in New Issue
Block a user