[ADD] HORILLA_API: Add swagger
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
"""
|
||||
ASGI config for horilla project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "horilla.settings")
|
||||
|
||||
application = get_asgi_application()
|
||||
"""
|
||||
ASGI config for horilla project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "horilla.settings")
|
||||
|
||||
application = get_asgi_application()
|
||||
|
||||
@@ -106,6 +106,7 @@ NO_PERMISSION_MODALS = [
|
||||
"recruitmentgeneralsetting",
|
||||
"resume",
|
||||
"recruitmentmailtemplate",
|
||||
"profileeditfeature",
|
||||
]
|
||||
|
||||
if settings.env("AWS_ACCESS_KEY_ID", default=None):
|
||||
@@ -115,7 +116,6 @@ if settings.env("AWS_ACCESS_KEY_ID", default=None):
|
||||
AWS_S3_REGION_NAME = settings.env("AWS_S3_REGION_NAME")
|
||||
DEFAULT_FILE_STORAGE = settings.env("DEFAULT_FILE_STORAGE")
|
||||
AWS_S3_ADDRESSING_STYLE = settings.env("AWS_S3_ADDRESSING_STYLE")
|
||||
AWS_S3_ENDPOINT_URL = settings.env("AWS_S3_ENDPOINT_URL", default=None)
|
||||
|
||||
settings.AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID
|
||||
settings.AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY
|
||||
@@ -123,7 +123,6 @@ if settings.env("AWS_ACCESS_KEY_ID", default=None):
|
||||
settings.AWS_S3_REGION_NAME = AWS_S3_REGION_NAME
|
||||
settings.DEFAULT_FILE_STORAGE = DEFAULT_FILE_STORAGE
|
||||
settings.AWS_S3_ADDRESSING_STYLE = AWS_S3_ADDRESSING_STYLE
|
||||
settings.AWS_S3_ENDPOINT_URL = AWS_S3_ENDPOINT_URL
|
||||
|
||||
|
||||
if settings.env("AWS_ACCESS_KEY_ID", default=None) and "storages" in INSTALLED_APPS:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@ REST_FRAMEWORK_SETTINGS = {
|
||||
"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
|
||||
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||
"horilla_api.auth.RejectBasicAuthentication",
|
||||
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
||||
),
|
||||
"PAGE_SIZE": 20,
|
||||
@@ -32,13 +33,9 @@ SWAGGER_SETTINGS = {
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"description": "Enter your Bearer token here",
|
||||
},
|
||||
"Basic": {
|
||||
"type": "basic",
|
||||
"description": "Basic authentication. Enter your username and password.",
|
||||
},
|
||||
}
|
||||
},
|
||||
"SECURITY": [{"Bearer": []}, {"Basic": []}],
|
||||
"SECURITY": [{"Bearer": []}],
|
||||
}
|
||||
# Inject the REST framework settings into the Django project settings
|
||||
setattr(settings, "REST_FRAMEWORK", REST_FRAMEWORK_SETTINGS)
|
||||
|
||||
@@ -79,6 +79,7 @@ MIDDLEWARE = [
|
||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"horilla_api.middleware.RejectBasicAuthMiddleware",
|
||||
"corsheaders.middleware.CorsMiddleware",
|
||||
"simple_history.middleware.HistoryRequestMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
|
||||
@@ -37,6 +37,7 @@ urlpatterns = [
|
||||
path("", include("horilla_views.urls")),
|
||||
path("employee/", include("employee.urls")),
|
||||
path("horilla-widget/", include("horilla_widgets.urls")),
|
||||
path("api/", include("horilla_api.urls")),
|
||||
re_path(
|
||||
"^inbox/notifications/", include(notifications.urls, namespace="notifications")
|
||||
),
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
"""
|
||||
WSGI config for horilla project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "horilla.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
"""
|
||||
WSGI config for horilla project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "horilla.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
|
||||
79
horilla_api/README_API_DOCS.md
Normal file
79
horilla_api/README_API_DOCS.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Horilla API Documentation
|
||||
|
||||
This document provides information on how to use and maintain the API documentation for Horilla HRMS.
|
||||
|
||||
## Accessing API Documentation
|
||||
|
||||
The API documentation is available at the following URLs:
|
||||
|
||||
- **Swagger UI**: `/api/swagger/` - Interactive documentation with testing capabilities
|
||||
- **ReDoc**: `/api/redoc/` - Clean, responsive documentation for easier reading
|
||||
- **JSON Schema**: `/api/swagger.json` - Raw schema for integration with other tools
|
||||
|
||||
## Features
|
||||
|
||||
- **Interactive Documentation**: Test API endpoints directly from the browser
|
||||
- **Module Organization**: Endpoints are grouped by module (employee, attendance, etc.)
|
||||
- **Authentication Support**: Bearer (JWT) only. Basic authentication is disabled.
|
||||
- **Request/Response Examples**: Clear examples of data formats
|
||||
- **Versioning**: API versions are clearly indicated
|
||||
|
||||
## For Developers: Adding Documentation to New Endpoints
|
||||
|
||||
### Using the `document_api` Decorator
|
||||
|
||||
```python
|
||||
from horilla_api.docs import document_api
|
||||
|
||||
class MyAPIView(APIView):
|
||||
@document_api(
|
||||
operation_description="Description of what this endpoint does",
|
||||
request_body=MyRequestSerializer,
|
||||
responses={
|
||||
200: MyResponseSerializer,
|
||||
400: "Bad request error description"
|
||||
},
|
||||
tags=['Module Name']
|
||||
)
|
||||
def get(self, request):
|
||||
# Your view logic here
|
||||
pass
|
||||
```
|
||||
|
||||
### Common Parameters
|
||||
|
||||
For paginated list views:
|
||||
|
||||
```python
|
||||
@document_api(
|
||||
operation_description="List all items with pagination",
|
||||
responses={200: MySerializer(many=True)},
|
||||
query_params='paginated'
|
||||
)
|
||||
```
|
||||
|
||||
## Maintaining Documentation
|
||||
|
||||
- Documentation automatically updates when API endpoints change
|
||||
- Security schemes (Bearer/JWT) are configured in `rest_conf.py`
|
||||
- Basic authentication has been removed across all interfaces`
|
||||
- Module tags are defined in `horilla_api/docs.py`
|
||||
|
||||
## Testing Documentation
|
||||
|
||||
1. Start the development server
|
||||
2. Navigate to `/api/swagger/` or `/api/redoc/`
|
||||
3. Verify all endpoints are properly documented
|
||||
4. Test authentication flows
|
||||
5. Check that all modules are properly organized
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If endpoints are not appearing in documentation:
|
||||
- Ensure the URL is included in the `patterns` list in `horilla_api/urls.py`
|
||||
- Check that the view is using proper decorators
|
||||
- Verify the serializer is correctly defined
|
||||
|
||||
If you see a Basic authorization option in Swagger:
|
||||
- Clear your browser cache and refresh `/api/swagger/`
|
||||
- Confirm `SWAGGER_SETTINGS` only contains the `Bearer` scheme
|
||||
@@ -2,3 +2,6 @@ from horilla.settings import INSTALLED_APPS
|
||||
|
||||
INSTALLED_APPS.append("geofencing")
|
||||
INSTALLED_APPS.append("facedetection")
|
||||
|
||||
# Import Swagger settings to ensure they're applied
|
||||
from . import swagger_settings
|
||||
|
||||
@@ -12,3 +12,10 @@ class GetEmployeeSerializer(serializers.ModelSerializer):
|
||||
|
||||
def get_full_name(self, obj):
|
||||
return obj.get_full_name()
|
||||
|
||||
|
||||
class LoginRequestSerializer(serializers.Serializer):
|
||||
"""Simple request body for the login endpoint."""
|
||||
|
||||
username = serializers.CharField()
|
||||
password = serializers.CharField()
|
||||
|
||||
@@ -1,12 +1,54 @@
|
||||
from django.contrib.auth import authenticate
|
||||
from drf_yasg import openapi
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
from ...api_serializers.auth.serializers import GetEmployeeSerializer
|
||||
from horilla_api.docs import document_api
|
||||
|
||||
from ...api_serializers.auth.serializers import (
|
||||
GetEmployeeSerializer,
|
||||
LoginRequestSerializer,
|
||||
)
|
||||
|
||||
|
||||
class LoginAPIView(APIView):
|
||||
@document_api(
|
||||
operation_description="Authenticate user and return JWT access token with employee info",
|
||||
request_body=LoginRequestSerializer,
|
||||
responses={
|
||||
200: openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
"employee": openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
"id": openapi.Schema(type=openapi.TYPE_INTEGER),
|
||||
"full_name": openapi.Schema(type=openapi.TYPE_STRING),
|
||||
"employee_profile": openapi.Schema(
|
||||
type=openapi.TYPE_STRING,
|
||||
description="Profile image URL",
|
||||
),
|
||||
},
|
||||
),
|
||||
"access": openapi.Schema(
|
||||
type=openapi.TYPE_STRING, description="JWT access token"
|
||||
),
|
||||
"face_detection": openapi.Schema(type=openapi.TYPE_BOOLEAN),
|
||||
"face_detection_image": openapi.Schema(
|
||||
type=openapi.TYPE_STRING,
|
||||
description="Face detection image URL",
|
||||
nullable=True,
|
||||
),
|
||||
"geo_fencing": openapi.Schema(type=openapi.TYPE_BOOLEAN),
|
||||
"company_id": openapi.Schema(
|
||||
type=openapi.TYPE_INTEGER, nullable=True
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
tags=["auth"],
|
||||
)
|
||||
def post(self, request):
|
||||
if "username" and "password" in request.data.keys():
|
||||
username = request.data.get("username")
|
||||
|
||||
29
horilla_api/api_views/base/example_view.py
Normal file
29
horilla_api/api_views/base/example_view.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Example API view with documentation
|
||||
"""
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from horilla_api.docs import document_api
|
||||
|
||||
class ExampleDocumentedView(APIView):
|
||||
"""
|
||||
Example view demonstrating API documentation
|
||||
"""
|
||||
|
||||
@document_api(
|
||||
operation_description="Get API documentation example",
|
||||
responses={
|
||||
200: "Example response with documentation",
|
||||
404: "Not found error"
|
||||
},
|
||||
tags=['Documentation Example']
|
||||
)
|
||||
def get(self, request):
|
||||
"""
|
||||
Example GET method with documentation
|
||||
"""
|
||||
return Response(
|
||||
{"message": "API documentation is working correctly"},
|
||||
status=status.HTTP_200_OK
|
||||
)
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Any
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
@@ -163,7 +165,7 @@ class DepartmentView(APIView):
|
||||
|
||||
departments = Department.objects.all()
|
||||
paginator = PageNumberPagination()
|
||||
page = paginator.paginate_queryset(departments, request)
|
||||
page: list[Any] | None = paginator.paginate_queryset(departments, request)
|
||||
serializer = self.serializer_class(page, many=True)
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
|
||||
|
||||
@@ -6,11 +6,8 @@ class HorillaApiConfig(AppConfig):
|
||||
name = "horilla_api"
|
||||
|
||||
def ready(self):
|
||||
from django.urls import include, path
|
||||
|
||||
from horilla.urls import urlpatterns
|
||||
|
||||
urlpatterns.append(
|
||||
path("api/", include("horilla_api.urls")),
|
||||
)
|
||||
super().ready()
|
||||
"""
|
||||
Initialize API documentation when the app is ready
|
||||
"""
|
||||
# Import and register API documentation components
|
||||
import horilla_api.schema # noqa
|
||||
|
||||
39
horilla_api/auth.py
Normal file
39
horilla_api/auth.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
Authentication utilities for the API
|
||||
"""
|
||||
from rest_framework import authentication
|
||||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
|
||||
class SwaggerAuthentication(authentication.BaseAuthentication):
|
||||
"""
|
||||
Custom authentication class for Swagger UI
|
||||
"""
|
||||
def authenticate(self, request):
|
||||
# Get the authentication header
|
||||
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
|
||||
|
||||
# Try JWT authentication first
|
||||
if auth_header.startswith('Bearer '):
|
||||
jwt_auth = JWTAuthentication()
|
||||
try:
|
||||
return jwt_auth.authenticate(request)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Fall back to session authentication
|
||||
if request.user and request.user.is_authenticated:
|
||||
return (request.user, None)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class RejectBasicAuthentication(authentication.BaseAuthentication):
|
||||
"""
|
||||
Explicitly reject HTTP Basic Auth across the API with a clear error message.
|
||||
"""
|
||||
def authenticate(self, request):
|
||||
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
|
||||
if auth_header.startswith('Basic '):
|
||||
raise AuthenticationFailed('Basic authentication is disabled. Use Bearer token (JWT) in the Authorization header.')
|
||||
return None
|
||||
20
horilla_api/decorators.py
Normal file
20
horilla_api/decorators.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
Decorators for API views
|
||||
"""
|
||||
from functools import wraps
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
|
||||
def api_authentication_required(view_func):
|
||||
"""
|
||||
Decorator to ensure API views require authentication
|
||||
"""
|
||||
@wraps(view_func)
|
||||
def wrapped_view(request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return Response(
|
||||
{"detail": "Authentication credentials were not provided."},
|
||||
status=status.HTTP_401_UNAUTHORIZED
|
||||
)
|
||||
return view_func(request, *args, **kwargs)
|
||||
return wrapped_view
|
||||
88
horilla_api/docs.py
Normal file
88
horilla_api/docs.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""
|
||||
Documentation helpers for API views
|
||||
"""
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from drf_yasg import openapi
|
||||
from rest_framework import authentication
|
||||
|
||||
# Module tags for organizing endpoints
|
||||
MODULE_TAGS = {
|
||||
'auth': 'Authentication',
|
||||
'asset': 'Asset Management',
|
||||
'base': 'Base',
|
||||
'employee': 'Employee Management',
|
||||
'notifications': 'Notifications',
|
||||
'payroll': 'Payroll',
|
||||
'attendance': 'Attendance',
|
||||
'leave': 'Leave Management',
|
||||
}
|
||||
|
||||
# Common response schemas
|
||||
error_response = openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
'error': openapi.Schema(type=openapi.TYPE_STRING),
|
||||
'detail': openapi.Schema(type=openapi.TYPE_STRING),
|
||||
}
|
||||
)
|
||||
|
||||
success_response = openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
'success': openapi.Schema(type=openapi.TYPE_BOOLEAN),
|
||||
'message': openapi.Schema(type=openapi.TYPE_STRING),
|
||||
}
|
||||
)
|
||||
|
||||
# Common parameters
|
||||
pagination_params = [
|
||||
openapi.Parameter('page', openapi.IN_QUERY, description="Page number", type=openapi.TYPE_INTEGER),
|
||||
openapi.Parameter('page_size', openapi.IN_QUERY, description="Number of results per page", type=openapi.TYPE_INTEGER),
|
||||
]
|
||||
|
||||
def document_api(
|
||||
operation_description=None,
|
||||
request_body=None,
|
||||
responses=None,
|
||||
query_params=None,
|
||||
tags=None,
|
||||
manual_parameters=None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Decorator for documenting API views with authentication
|
||||
|
||||
Example usage:
|
||||
|
||||
@document_api(
|
||||
operation_description="List all employees",
|
||||
responses={200: EmployeeSerializer(many=True)},
|
||||
tags=['Employee']
|
||||
)
|
||||
def get(self, request):
|
||||
...
|
||||
"""
|
||||
# Add pagination parameters for list views
|
||||
if manual_parameters is None and query_params == 'paginated':
|
||||
manual_parameters = pagination_params
|
||||
|
||||
# Add common error responses
|
||||
if responses and 400 not in responses:
|
||||
responses[400] = error_response
|
||||
if responses and 401 not in responses:
|
||||
responses[401] = error_response
|
||||
if responses and 403 not in responses:
|
||||
responses[403] = error_response
|
||||
|
||||
# Add security requirement (Bearer only)
|
||||
security = [{'Bearer': []}]
|
||||
|
||||
return swagger_auto_schema(
|
||||
operation_description=operation_description,
|
||||
request_body=request_body,
|
||||
responses=responses,
|
||||
manual_parameters=manual_parameters,
|
||||
tags=tags,
|
||||
security=security,
|
||||
**kwargs
|
||||
)
|
||||
23
horilla_api/middleware.py
Normal file
23
horilla_api/middleware.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from django.http import JsonResponse
|
||||
|
||||
|
||||
class RejectBasicAuthMiddleware:
|
||||
"""
|
||||
Middleware that rejects HTTP Basic Authentication globally with a consistent message.
|
||||
This ensures endpoints that override DRF authentication classes still reject Basic.
|
||||
"""
|
||||
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
|
||||
if isinstance(auth_header, str) and auth_header.startswith('Basic '):
|
||||
return JsonResponse(
|
||||
{
|
||||
"error": "Basic authentication is disabled",
|
||||
"detail": "Use Bearer token (JWT) in the Authorization header."
|
||||
},
|
||||
status=401
|
||||
)
|
||||
return self.get_response(request)
|
||||
86
horilla_api/schema.py
Normal file
86
horilla_api/schema.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""
|
||||
Schema configuration for API documentation
|
||||
"""
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.inspectors import SwaggerAutoSchema
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from drf_yasg.generators import OpenAPISchemaGenerator
|
||||
|
||||
class ModuleTaggingAutoSchema(SwaggerAutoSchema):
|
||||
"""
|
||||
Custom schema generator that automatically tags operations based on their module
|
||||
"""
|
||||
def get_tags(self, operation_keys):
|
||||
# Extract module name from the operation keys
|
||||
if len(operation_keys) > 1:
|
||||
# Use the first part of the URL path as the tag (e.g., 'employee', 'attendance')
|
||||
return [operation_keys[0]]
|
||||
return super().get_tags(operation_keys)
|
||||
|
||||
|
||||
class OrderedTagSchemaGenerator(OpenAPISchemaGenerator):
|
||||
"""
|
||||
Custom schema generator to enforce tag ordering.
|
||||
|
||||
Places 'auth' first, followed by remaining tags sorted alphabetically.
|
||||
"""
|
||||
def get_schema(self, request=None, public=False):
|
||||
schema = super().get_schema(request=request, public=public)
|
||||
|
||||
# Collect all tag names used in operations
|
||||
tag_names = set()
|
||||
for path_item in schema.paths.values():
|
||||
for method_name in ("get", "put", "post", "delete", "options", "head", "patch", "trace"):
|
||||
operation = getattr(path_item, method_name, None)
|
||||
if operation and getattr(operation, "tags", None):
|
||||
for t in operation.tags:
|
||||
if t:
|
||||
tag_names.add(t)
|
||||
|
||||
# Desired order: 'auth' first, then others alphabetically
|
||||
ordered_names = ["auth"] + sorted([t for t in tag_names if t != "auth"])
|
||||
|
||||
# Build top-level tags list in the specified order
|
||||
schema.tags = [{"name": name} for name in ordered_names]
|
||||
return schema
|
||||
|
||||
def api_doc(**kwargs):
|
||||
"""
|
||||
Decorator for documenting API views
|
||||
|
||||
Example usage:
|
||||
|
||||
@api_doc(
|
||||
responses={200: EmployeeSerializer(many=True)},
|
||||
operation_description="List all employees",
|
||||
tags=['Employee']
|
||||
)
|
||||
def get(self, request):
|
||||
...
|
||||
"""
|
||||
return swagger_auto_schema(**kwargs)
|
||||
|
||||
# Common response schemas
|
||||
error_response = openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
'error': openapi.Schema(type=openapi.TYPE_STRING),
|
||||
'detail': openapi.Schema(type=openapi.TYPE_STRING),
|
||||
}
|
||||
)
|
||||
|
||||
success_response = openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
properties={
|
||||
'success': openapi.Schema(type=openapi.TYPE_BOOLEAN),
|
||||
'message': openapi.Schema(type=openapi.TYPE_STRING),
|
||||
}
|
||||
)
|
||||
|
||||
# Common parameters
|
||||
pagination_params = [
|
||||
openapi.Parameter('page', openapi.IN_QUERY, description="Page number", type=openapi.TYPE_INTEGER),
|
||||
openapi.Parameter('page_size', openapi.IN_QUERY, description="Number of results per page", type=openapi.TYPE_INTEGER),
|
||||
]
|
||||
|
||||
# Security definitions are already configured in rest_conf.py
|
||||
30
horilla_api/swagger_settings.py
Normal file
30
horilla_api/swagger_settings.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Custom Swagger settings for the API
|
||||
"""
|
||||
from django.conf import settings
|
||||
|
||||
# Define security definitions for Swagger UI
|
||||
SWAGGER_SETTINGS = {
|
||||
'SECURITY_DEFINITIONS': {
|
||||
'Bearer': {
|
||||
'type': 'apiKey',
|
||||
'name': 'Authorization',
|
||||
'in': 'header',
|
||||
'description': 'JWT Token Authentication: Enter your token with the "Bearer " prefix, e.g. "Bearer abcde12345"'
|
||||
}
|
||||
},
|
||||
'USE_SESSION_AUTH': False,
|
||||
'DEFAULT_UI_SETTINGS': {
|
||||
# Keep tag order as defined in the generated spec
|
||||
'tagsSorter': 'none'
|
||||
},
|
||||
'SECURITY_REQUIREMENTS': [
|
||||
{'Bearer': []}
|
||||
],
|
||||
}
|
||||
|
||||
# Apply settings
|
||||
if hasattr(settings, 'SWAGGER_SETTINGS'):
|
||||
settings.SWAGGER_SETTINGS.update(SWAGGER_SETTINGS)
|
||||
else:
|
||||
setattr(settings, 'SWAGGER_SETTINGS', SWAGGER_SETTINGS)
|
||||
@@ -1,6 +1,39 @@
|
||||
from django.conf import settings
|
||||
from django.urls import include, path
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.views import get_schema_view
|
||||
from rest_framework import permissions
|
||||
|
||||
from horilla_api.schema import OrderedTagSchemaGenerator
|
||||
|
||||
# Create schema view for Swagger and ReDoc
|
||||
schema_view = get_schema_view(
|
||||
openapi.Info(
|
||||
title="Horilla API",
|
||||
default_version="v1",
|
||||
description="API documentation for Horilla HRMS. Click the 'Authorize' button at the top to authenticate.",
|
||||
terms_of_service="https://www.horilla.com/terms/",
|
||||
contact=openapi.Contact(email="contact@horilla.com"),
|
||||
license=openapi.License(name="BSD License"),
|
||||
),
|
||||
public=True,
|
||||
permission_classes=(permissions.AllowAny,),
|
||||
generator_class=OrderedTagSchemaGenerator,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
# API Documentation URLs
|
||||
path(
|
||||
"swagger<format>/", schema_view.without_ui(cache_timeout=0), name="schema-json"
|
||||
),
|
||||
path(
|
||||
"swagger/",
|
||||
schema_view.with_ui("swagger", cache_timeout=0),
|
||||
name="schema-swagger-ui",
|
||||
),
|
||||
path("redoc/", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc"),
|
||||
path("docs/", schema_view.with_ui("swagger", cache_timeout=0), name="schema-docs"),
|
||||
# API Endpoints (static configuration)
|
||||
path("auth/", include("horilla_api.api_urls.auth.urls")),
|
||||
path("asset/", include("horilla_api.api_urls.asset.urls")),
|
||||
path("base/", include("horilla_api.api_urls.base.urls")),
|
||||
|
||||
Reference in New Issue
Block a user