forked from val-lop20/Pagina-de-Asistencia-MAC
167 lines
6.6 KiB
Python
167 lines
6.6 KiB
Python
from rest_framework import generics, status
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
|
from rest_framework.response import Response
|
|
from django_ratelimit.decorators import ratelimit
|
|
from django.utils import timezone
|
|
from django.db import models
|
|
from .models import Event
|
|
from authentication.models import ExternalUser
|
|
from .serializers import EventSerializer, ExternalUserSerializer
|
|
import re
|
|
|
|
class EventListView(generics.ListCreateAPIView):
|
|
queryset = Event.objects.filter(is_active=True)
|
|
serializer_class = EventSerializer
|
|
|
|
def get_permissions(self):
|
|
"""Permitir lectura pública, pero creación solo para autenticados"""
|
|
if self.request.method == 'POST':
|
|
return [IsAuthenticated()]
|
|
return [AllowAny()]
|
|
|
|
def get_queryset(self):
|
|
return Event.objects.filter(is_active=True).order_by('date', 'start_time')
|
|
|
|
def perform_create(self, serializer):
|
|
"""Verificar que solo asistentes puedan crear eventos"""
|
|
try:
|
|
user_profile = self.request.user.userprofile
|
|
if user_profile.user_type != 'assistant':
|
|
from rest_framework.exceptions import PermissionDenied
|
|
raise PermissionDenied('Solo los asistentes pueden crear eventos')
|
|
except:
|
|
from rest_framework.exceptions import PermissionDenied
|
|
raise PermissionDenied('Usuario sin perfil válido')
|
|
|
|
serializer.save()
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
@ratelimit(key='user', rate='30/m', method='POST', block=True)
|
|
def register_external_user(request):
|
|
"""Crear un usuario externo - Solo asistentes: 30 creaciones por minuto"""
|
|
# Verificar que el usuario sea asistente
|
|
try:
|
|
user_profile = request.user.userprofile
|
|
if user_profile.user_type != 'assistant':
|
|
return Response({'error': 'Solo los asistentes pueden crear usuarios externos'}, status=403)
|
|
except:
|
|
return Response({'error': 'Usuario sin perfil válido'}, status=403)
|
|
|
|
data = request.data
|
|
account_number = data.get('account_number')
|
|
full_name = data.get('full_name')
|
|
|
|
if not account_number or not full_name:
|
|
return Response({'error': 'Número de cuenta y nombre completo son requeridos'}, status=400)
|
|
|
|
# Validar formato de número de cuenta (8 dígitos)
|
|
if not re.match(r'^\d{8}$', account_number):
|
|
return Response({'error': 'El número de cuenta debe tener exactamente 8 dígitos'}, status=400)
|
|
|
|
# Verificar que no exista en usuarios regulares
|
|
from authentication.models import UserProfile
|
|
if UserProfile.objects.filter(account_number=account_number).exists():
|
|
return Response({'error': 'Este número de cuenta ya está registrado como usuario regular'}, status=400)
|
|
|
|
# Verificar que no exista en usuarios externos
|
|
if ExternalUser.objects.filter(account_number=account_number).exists():
|
|
return Response({'error': 'Este número de cuenta ya está registrado como usuario externo'}, status=400)
|
|
|
|
try:
|
|
external_user = ExternalUser.objects.create(
|
|
full_name=full_name,
|
|
account_number=account_number,
|
|
status='approved',
|
|
approved_by=user_profile
|
|
)
|
|
|
|
return Response({
|
|
'message': 'Usuario externo creado exitosamente',
|
|
'account_number': account_number,
|
|
'full_name': full_name,
|
|
'status': 'approved'
|
|
}, status=status.HTTP_201_CREATED)
|
|
|
|
except Exception as e:
|
|
return Response({
|
|
'error': f'Error al crear usuario externo: {str(e)}'
|
|
}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
@ratelimit(key='user', rate='60/m', method='GET', block=True)
|
|
def search_external_users(request):
|
|
"""Buscar usuarios externos por nombre o número de cuenta - Solo asistentes: 60 búsquedas por minuto"""
|
|
# Verificar que el usuario sea asistente
|
|
try:
|
|
user_profile = request.user.userprofile
|
|
if user_profile.user_type != 'assistant':
|
|
return Response({'error': 'Solo los asistentes pueden buscar usuarios externos'}, status=403)
|
|
except:
|
|
return Response({'error': 'Usuario sin perfil válido'}, status=403)
|
|
|
|
search_query = request.GET.get('q', '').strip()
|
|
|
|
if not search_query:
|
|
return Response({'error': 'Parámetro de búsqueda "q" requerido'}, status=400)
|
|
|
|
# Buscar por número de cuenta o nombre (contiene)
|
|
external_users = ExternalUser.objects.filter(
|
|
status='approved'
|
|
).filter(
|
|
models.Q(account_number__icontains=search_query) |
|
|
models.Q(full_name__icontains=search_query)
|
|
)[:10] # Limitar a 10 resultados
|
|
|
|
results = []
|
|
for user in external_users:
|
|
results.append({
|
|
'id': user.id,
|
|
'account_number': user.account_number,
|
|
'full_name': user.full_name,
|
|
'created_at': user.created_at.strftime('%Y-%m-%d')
|
|
})
|
|
|
|
return Response({
|
|
'count': len(results),
|
|
'results': results
|
|
})
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
@ratelimit(key='user', rate='30/m', method='POST', block=True)
|
|
def approve_external_user(request, user_id):
|
|
"""Aprobar/rechazar usuario externo - Solo asistentes: 30 acciones por minuto"""
|
|
# Verificar que el usuario sea asistente
|
|
try:
|
|
user_profile = request.user.userprofile
|
|
if user_profile.user_type != 'assistant':
|
|
return Response({'error': 'Solo los asistentes pueden aprobar usuarios externos'}, status=403)
|
|
except:
|
|
return Response({'error': 'Usuario sin perfil válido'}, status=403)
|
|
|
|
try:
|
|
external_user = ExternalUser.objects.get(id=user_id)
|
|
action = request.data.get('action') # 'approve' o 'reject'
|
|
|
|
if action == 'approve':
|
|
external_user.status = 'approved'
|
|
external_user.approved_by = user_profile
|
|
external_user.processed_at = timezone.now()
|
|
external_user.save()
|
|
return Response({'message': 'Usuario aprobado'})
|
|
elif action == 'reject':
|
|
reason = request.data.get('reason', '')
|
|
external_user.status = 'rejected'
|
|
external_user.approved_by = user_profile
|
|
external_user.rejection_reason = reason
|
|
external_user.processed_at = timezone.now()
|
|
external_user.save()
|
|
return Response({'message': 'Usuario rechazado'})
|
|
else:
|
|
return Response({'error': 'Acción inválida'}, status=400)
|
|
|
|
except ExternalUser.DoesNotExist:
|
|
return Response({'error': 'Usuario no encontrado'}, status=404) |