init
This commit is contained in:
127
backend/apps/authentication/views.py
Normal file
127
backend/apps/authentication/views.py
Normal file
@@ -0,0 +1,127 @@
|
||||
# authentication/views.py - Authentication API views
|
||||
import hashlib
|
||||
from django.contrib.auth import login, logout
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sessions.models import Session
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import api_view, permission_classes
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.response import Response
|
||||
from django_ratelimit.decorators import ratelimit
|
||||
from apps.core.models import SystemSettings
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_client_ip(request):
|
||||
"""Extract client IP address from request"""
|
||||
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
||||
if x_forwarded_for:
|
||||
ip = x_forwarded_for.split(',')[0].strip()
|
||||
else:
|
||||
ip = request.META.get('REMOTE_ADDR')
|
||||
return ip
|
||||
|
||||
|
||||
@api_view(['POST'])
|
||||
@permission_classes([AllowAny])
|
||||
@csrf_exempt
|
||||
@ratelimit(key='ip', rate='10/min', method='POST', block=True)
|
||||
def login_view(request):
|
||||
"""
|
||||
Authenticate user with system password.
|
||||
Rate limited to prevent brute force attacks.
|
||||
"""
|
||||
try:
|
||||
password = request.data.get('password')
|
||||
|
||||
if not password:
|
||||
return Response(
|
||||
{'error': 'Password is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
settings_obj = SystemSettings.get_settings()
|
||||
|
||||
if settings_obj.check_password(password):
|
||||
# Create or get session
|
||||
if not request.session.session_key:
|
||||
request.session.create()
|
||||
|
||||
# Store authentication in session
|
||||
request.session['authenticated'] = True
|
||||
request.session['auth_timestamp'] = timezone.now().isoformat()
|
||||
request.session['client_ip'] = get_client_ip(request)
|
||||
request.session.save()
|
||||
|
||||
logger.info(f"Successful login from IP: {get_client_ip(request)}")
|
||||
|
||||
return Response({
|
||||
'success': True,
|
||||
'message': 'Authentication successful',
|
||||
'session_key': request.session.session_key
|
||||
})
|
||||
else:
|
||||
logger.warning(f"Failed login attempt from IP: {get_client_ip(request)}")
|
||||
return Response(
|
||||
{'error': 'Invalid password'},
|
||||
status=status.HTTP_401_UNAUTHORIZED
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Login failed: {e}")
|
||||
return Response(
|
||||
{'error': 'Authentication failed'},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
|
||||
@api_view(['POST'])
|
||||
@permission_classes([AllowAny])
|
||||
@csrf_exempt
|
||||
def logout_view(request):
|
||||
"""Clear user session and log out"""
|
||||
try:
|
||||
request.session.flush()
|
||||
logger.info("User logged out successfully")
|
||||
return Response({
|
||||
'success': True,
|
||||
'message': 'Logged out successfully'
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Logout failed: {e}")
|
||||
return Response(
|
||||
{'error': 'Logout failed'},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
|
||||
@api_view(['GET'])
|
||||
@permission_classes([AllowAny])
|
||||
@csrf_exempt
|
||||
def check_auth_view(request):
|
||||
"""Check if user is authenticated"""
|
||||
is_authenticated = request.session.get('authenticated', False)
|
||||
|
||||
if is_authenticated:
|
||||
# Optional: Check session age for additional security
|
||||
auth_timestamp = request.session.get('auth_timestamp')
|
||||
if auth_timestamp:
|
||||
try:
|
||||
auth_time = timezone.datetime.fromisoformat(auth_timestamp)
|
||||
if timezone.now() - auth_time > timedelta(hours=24):
|
||||
request.session.flush()
|
||||
is_authenticated = False
|
||||
except (ValueError, TypeError):
|
||||
request.session.flush()
|
||||
is_authenticated = False
|
||||
|
||||
return Response({
|
||||
'authenticated': is_authenticated,
|
||||
'session_key': request.session.session_key if is_authenticated else None
|
||||
})
|
||||
Reference in New Issue
Block a user