Browse Source
feat: implement Swagger authentication and permissions for admin and token users
shokhmgar
feat: implement Swagger authentication and permissions for admin and token users
shokhmgar
5 changed files with 128 additions and 6 deletions
-
42apps/api/decorators.py
-
60apps/api/permissions.py
-
13apps/api/views/swagger_views.py
-
10config/urls.py
-
9templates/swagger/ui.html
@ -0,0 +1,42 @@ |
|||||
|
from functools import wraps |
||||
|
from django.http import HttpResponseForbidden |
||||
|
from django.contrib.auth.models import AnonymousUser |
||||
|
from django.views.decorators.csrf import csrf_exempt |
||||
|
from rest_framework.authtoken.models import Token |
||||
|
|
||||
|
|
||||
|
def swagger_auth_required(view_func): |
||||
|
""" |
||||
|
Decorator that requires either admin authentication or valid swagger token |
||||
|
""" |
||||
|
@csrf_exempt |
||||
|
@wraps(view_func) |
||||
|
def _wrapped_view(request, *args, **kwargs): |
||||
|
# Check if user is admin |
||||
|
if request.user and request.user.is_authenticated and request.user.is_staff: |
||||
|
return view_func(request, *args, **kwargs) |
||||
|
|
||||
|
# Check swagger token in session |
||||
|
swagger_token = request.session.get('swagger_token') |
||||
|
if swagger_token: |
||||
|
try: |
||||
|
token_obj = Token.objects.get(key=swagger_token) |
||||
|
if token_obj.user.is_active: |
||||
|
return view_func(request, *args, **kwargs) |
||||
|
except Token.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
# Check Authorization header |
||||
|
auth_header = request.META.get('HTTP_AUTHORIZATION', '') |
||||
|
if auth_header.startswith('Token '): |
||||
|
token = auth_header.split(' ')[1] |
||||
|
try: |
||||
|
token_obj = Token.objects.get(key=token) |
||||
|
if token_obj.user.is_active: |
||||
|
return view_func(request, *args, **kwargs) |
||||
|
except Token.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
return HttpResponseForbidden("Access denied. Admin authentication or valid token required.") |
||||
|
|
||||
|
return _wrapped_view |
||||
@ -0,0 +1,60 @@ |
|||||
|
from rest_framework import permissions |
||||
|
from rest_framework.authtoken.models import Token |
||||
|
from django.contrib.auth.models import AnonymousUser |
||||
|
|
||||
|
|
||||
|
class SwaggerTokenPermission(permissions.BasePermission): |
||||
|
""" |
||||
|
Custom permission for Swagger that allows access to authenticated users via token |
||||
|
or admin users via session authentication |
||||
|
""" |
||||
|
|
||||
|
def has_permission(self, request, view): |
||||
|
# Check if user is admin (for session-based access) |
||||
|
if request.user and request.user.is_authenticated and request.user.is_staff: |
||||
|
return True |
||||
|
|
||||
|
# Check for token in session (from our custom auth system) |
||||
|
swagger_token = request.session.get('swagger_token') |
||||
|
if swagger_token: |
||||
|
try: |
||||
|
token_obj = Token.objects.get(key=swagger_token) |
||||
|
if token_obj.user.is_active: |
||||
|
return True |
||||
|
except Token.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
# Check for Authorization header |
||||
|
auth_header = request.META.get('HTTP_AUTHORIZATION', '') |
||||
|
if auth_header.startswith('Token '): |
||||
|
token = auth_header.split(' ')[1] |
||||
|
try: |
||||
|
token_obj = Token.objects.get(key=token) |
||||
|
if token_obj.user.is_active: |
||||
|
return True |
||||
|
except Token.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
return False |
||||
|
|
||||
|
|
||||
|
class IsAdminOrSwaggerToken(permissions.BasePermission): |
||||
|
""" |
||||
|
Permission that allows access to admin users or users with valid swagger token |
||||
|
""" |
||||
|
|
||||
|
def has_permission(self, request, view): |
||||
|
# Allow admin users |
||||
|
if request.user and request.user.is_authenticated and request.user.is_staff: |
||||
|
return True |
||||
|
|
||||
|
# Check swagger token in session |
||||
|
swagger_token = request.session.get('swagger_token') |
||||
|
if swagger_token: |
||||
|
try: |
||||
|
token_obj = Token.objects.get(key=swagger_token) |
||||
|
return token_obj.user.is_active |
||||
|
except Token.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
return False |
||||
@ -1,9 +1,11 @@ |
|||||
|
{% load static %} |
||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||
<html lang="en"> |
<html lang="en"> |
||||
<head> |
<head> |
||||
<meta charset="UTF-8"> |
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Imam Javad API - Swagger UI</title> |
<title>Imam Javad API - Swagger UI</title> |
||||
|
{% csrf_token %} |
||||
|
|
||||
<!-- Swagger UI CSS --> |
<!-- Swagger UI CSS --> |
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/swagger-ui.css" /> |
<link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/swagger-ui.css" /> |
||||
@ -310,6 +312,13 @@ |
|||||
{% if request.session.swagger_token %} |
{% if request.session.swagger_token %} |
||||
request.headers['Authorization'] = 'Token {{ request.session.swagger_token }}'; |
request.headers['Authorization'] = 'Token {{ request.session.swagger_token }}'; |
||||
{% endif %} |
{% endif %} |
||||
|
|
||||
|
// Add CSRF token for Django |
||||
|
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]'); |
||||
|
if (csrfToken) { |
||||
|
request.headers['X-CSRFToken'] = csrfToken.value; |
||||
|
} |
||||
|
|
||||
return request; |
return request; |
||||
}, |
}, |
||||
responseInterceptor: function(response) { |
responseInterceptor: function(response) { |
||||
|
|||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue