From b8258ce9254227e029010d3f13b62351e753c6ee Mon Sep 17 00:00:00 2001 From: AdalbertoCV <34152734@uaz.edu.mx> Date: Tue, 9 Jul 2024 13:14:12 -0600 Subject: [PATCH] =?UTF-8?q?nombres=20de=20urls=20estandarizadas,=20nombres?= =?UTF-8?q?=20de=20clases=20en=20CamelCase=20y=20documentaci=C3=B3n=20de?= =?UTF-8?q?=20clases=20mejorada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cosiap_api/users/admin_views.py | 6 +- cosiap_api/users/serializers.py | 9 ++- cosiap_api/users/urls.py | 16 ++--- cosiap_api/users/views.py | 111 +++++++++++++++++++++++++------- 4 files changed, 103 insertions(+), 39 deletions(-) diff --git a/cosiap_api/users/admin_views.py b/cosiap_api/users/admin_views.py index 60d9c97..95ada56 100644 --- a/cosiap_api/users/admin_views.py +++ b/cosiap_api/users/admin_views.py @@ -2,7 +2,7 @@ # Autores: Adalberto Cerrillo Vázquez, Rafael Uribe Caldera # Versión: 1.0 from rest_framework.views import APIView -from .serializers import admin_serializer +from .serializers import AdminSerializer from .permisos import es_admin from .models import Usuario from .views import enviar_correo_verificacion @@ -22,7 +22,7 @@ class administrador(APIView): # indicamos el query set de todos los usuarios queryset = Usuario.objects.filter(is_staff=True) # indicamos el serializer a utilizar y enviamos el queryset - serializer = admin_serializer(queryset, many=True) + serializer = AdminSerializer(queryset, many=True) # retornamos la lista de usuarios return Response(serializer.data) @@ -38,7 +38,7 @@ class administrador(APIView): # si no hay datos duplicado procedemos con el registro del admin if email_exist is None: # inicializamos el serializer de admin - serializer = admin_serializer(data=request.data) + serializer = AdminSerializer(data=request.data) # verificamos que los datos sean válidos if serializer.is_valid(): # creamos la instancia del nuevo usuario como inactivo diff --git a/cosiap_api/users/serializers.py b/cosiap_api/users/serializers.py index aa289e7..67dbc99 100644 --- a/cosiap_api/users/serializers.py +++ b/cosiap_api/users/serializers.py @@ -6,8 +6,7 @@ from rest_framework import serializers from .models import Usuario, Solicitante, DatosBancarios -# serializar para el administrador -class admin_serializer(serializers.ModelSerializer): +class AdminSerializer(serializers.ModelSerializer): # campo para la confirmación del password confirmar_password = serializers.CharField(write_only=True) @@ -40,7 +39,7 @@ class admin_serializer(serializers.ModelSerializer): return user # serializer para el usuario solicitante -class usuario_serializer(serializers.ModelSerializer): +class UsuarioSerializer(serializers.ModelSerializer): # Creamos un campo de confirmación de la contraseña del solicitante confirmar_password = serializers.CharField(write_only=True) @@ -78,7 +77,7 @@ class usuario_serializer(serializers.ModelSerializer): # Serializer para el registro y edición de los datos bancarios del usuario -class datos_bancarios_serializer(serializers.ModelSerializer): +class DatosBancariosSerializer(serializers.ModelSerializer): class Meta: # indicamos el modelo model = DatosBancarios @@ -87,7 +86,7 @@ class datos_bancarios_serializer(serializers.ModelSerializer): # Serializer para el registro y actualización de los datos del solicitante -class solicitante_serializer(serializers.ModelSerializer): +class SolicitanteSerializer(serializers.ModelSerializer): class Meta: # indicamos el modelo a utilziar model = Solicitante diff --git a/cosiap_api/users/urls.py b/cosiap_api/users/urls.py index 5ecef73..0e773a5 100644 --- a/cosiap_api/users/urls.py +++ b/cosiap_api/users/urls.py @@ -10,12 +10,12 @@ urlpatterns = [ path('token/', CustomTokenObtainPairView.as_view(), name='token_obtain'), path('token/refresh/', CustomTokenRefreshView.as_view(), name='token_refresh'), - path('', views.usuario.as_view(), name = 'usuario-lista-crear'), - path('/', views.usuario.as_view(), name = 'ver-eliminar-usuario'), - path('solicitantes/', views.solicitante.as_view(), name = 'solicitante-lista-crear'), - path('solicitantes/', views.solicitante.as_view(), name = 'solicitante-detalle'), - path('verificar-correo///', views.verificar_correo.as_view(), name='verificar-correo'), - path('restablecer-password/', views.reset_password.as_view(), name='reset-password'), - path('nueva-password///', views.nueva_password.as_view(), name='nueva-password'), - path('administradores/', administrador.as_view() , name = 'administrador-lista-crear'), + path('', views.Usuario.as_view(), name = 'usuario_list_create'), + path('/', views.Usuario.as_view(), name = 'usuario_get_delete'), + path('solicitantes/', views.Solicitante.as_view(), name = 'solicitante_list_create'), + path('solicitantes/', views.Solicitante.as_view(), name = 'solicitante_get'), + path('verificar-correo///', views.VerificarCorreo.as_view(), name='verificar_correo'), + path('restablecer-password/', views.ResetPassword.as_view(), name='reset_password'), + path('nueva-password///', views.NuevaPassword.as_view(), name='nueva_password'), + path('administradores/', administrador.as_view() , name = 'administrador_list_create'), ] \ No newline at end of file diff --git a/cosiap_api/users/views.py b/cosiap_api/users/views.py index 27a7d06..9633fb0 100644 --- a/cosiap_api/users/views.py +++ b/cosiap_api/users/views.py @@ -9,7 +9,7 @@ from rest_framework.response import Response from rest_framework.permissions import AllowAny, IsAuthenticated from .models import Usuario, Solicitante from django.contrib import messages -from .serializers import usuario_serializer, solicitante_serializer +from .serializers import UsuarioSerializer, SolicitanteSerializer from django.contrib.auth import authenticate from django.core.mail import send_mail from django.conf import settings @@ -24,6 +24,7 @@ from rest_framework import status from django.conf import settings from datetime import datetime, timedelta from .permisos import es_admin, primer_login +from notificaciones.Mensajes import Mensaje class CustomTokenObtainPairView(TokenObtainPairView): def post(self, request, *args, **kwargs): @@ -57,8 +58,14 @@ class CustomTokenRefreshView(TokenRefreshView): return response -# Clase abstracta para la verificación de los permisos de usuario class BasePermissionAPIView(APIView): + """ + Clase abstracta que maneja la verificación de los permisos de usuarios + Es utilizada para no escribir permisos específicos en cada clase de usuario + + Herencia: + - APIView (Heréda de la clase APIView básica) + """ # permisos para la creación de nuevos usuarios permission_classes_create = [AllowAny] # permisos para eliminar usuarios @@ -106,7 +113,18 @@ class BasePermissionAPIView(APIView): # Funcionalidad para crear un usuario en el sistema, ver sus datos o eliminarlo -class usuario(BasePermissionAPIView): +class Usuario(BasePermissionAPIView): + """ + Clase Usuario para manejar las solicitudes de los usuarios básicos + + Tipos de Solicitud: + - GET (Obtiene la lista de usuarios o a un usuario específico) + - POST (Para la creación de un nuevo usuario) + - DELETE (Borrar un usuario) + + Herencia: + - BasePermissionAPIView (Heréda de la clase con los permisos predefinidos) + """ # Función para la obtención de la lista de usuarios def get( self, request, *args, **kwargs ): # si se quiere observar solo un usuario @@ -116,7 +134,7 @@ class usuario(BasePermissionAPIView): instance = get_object_or_404(Usuario, pk=kwargs['pk']) self.check_object_permissions(request, instance) # indicamos el serializer a utilizar y enviamos la instancia - serializer = usuario_serializer(instance) + serializer = UsuarioSerializer(instance) # devolvemos los datos del usuario return Response(serializer.data) # si se desea ver la lista completa @@ -124,7 +142,7 @@ class usuario(BasePermissionAPIView): # indicamos el query set de todos los usuarios queryset = Usuario.objects.all() # indicamos el serializer a utilizar y enviamos el queryset - serializer = usuario_serializer(queryset, many=True) + serializer = UsuarioSerializer(queryset, many=True) # retornamos la lista de usuarios return Response(serializer.data) @@ -149,7 +167,7 @@ class usuario(BasePermissionAPIView): # eliminamos el usuario asociado a el email_exist = Usuario.objects.get(email=email).delete() # sobreescribimos el serializer enviando la instancia encontrada - serializer = usuario_serializer(data=request.data, instance=curp_exist) + serializer = UsuarioSerializer(data=request.data, instance=curp_exist) # verificamos los datos enviados if serializer.is_valid(): # creamos la instancia del nuevo usuario como inactivo @@ -163,7 +181,8 @@ class usuario(BasePermissionAPIView): # enviamos el correo de verificación con el token enviar_correo_verificacion(usuario_nuevo.email, uid, token) # retornamos la respuesta de creación - response_data = {'data': serializer.data, 'message': {'success': 'Creación del usuario exitosa.'}} + response_data = {'data': serializer.data} + Mensaje.success(response_data, 'Usuario creado exitosamente.') return Response(response_data, status=status.HTTP_201_CREATED) # en caso de que los datos sean incorrectos, retornamos un error. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -179,12 +198,21 @@ class usuario(BasePermissionAPIView): # eliminamos la intancia instance.delete() # devolvemos una respuesta sin contenido confirmando la eliminación - response_data = {'message': {'success': 'Eliminación exitosa.'}} - return Response(response_data, status=status.HTTP_204_NO_CONTENT) + return Response({"message": {'success': 'Eliminación exitosa'}}, status=status.HTTP_204_NO_CONTENT) -# Clase para manejar la lógica del solicitante (Creación, edición) -class solicitante(BasePermissionAPIView): +class Solicitante(BasePermissionAPIView): + """ + Clase Solicitante + + Tipo de solicitud: + - GET (Obtiene la lista de solicitantes o a un solicitante específico) + - POST (Crear un nuevo solicitante) + - PUT (Editar los datos de un solicitante) + + Herencia: + - BasePermissionAPIView (Heréda de la clase con los permisos predefinidos) + """ # Indicamos que solo los usuarios logeados puedan acceder a esta función permission_classes = [IsAuthenticated, primer_login] permission_classes_create = [IsAuthenticated] @@ -198,7 +226,7 @@ class solicitante(BasePermissionAPIView): instance = get_object_or_404(Solicitante, pk=kwargs['pk']) self.check_object_permissions(request, instance) # indicamos el serializer a utilizar y enviamos la instancia - serializer = solicitante_serializer(instance) + serializer = SolicitanteSerializer(instance) # devolvemos los datos del usuario return Response(serializer.data) # si se desea ver la lista completa @@ -206,7 +234,7 @@ class solicitante(BasePermissionAPIView): # indicamos el query set de todos los usuarios queryset = Solicitante.objects.all() # indicamos el serializer a utilizar y enviamos el queryset - serializer = solicitante_serializer(queryset, many=True) + serializer = SolicitanteSerializer(queryset, many=True) # retornamos la lista de usuarios return Response(serializer.data) @@ -226,7 +254,7 @@ class solicitante(BasePermissionAPIView): } ) # Verificar que los datos del solicitante estén completos - serializer = solicitante_serializer(instance= solicitante, data=request.data) + serializer = SolicitanteSerializer(instance= solicitante, data=request.data) if serializer.is_valid(): # Guardamos los datos del solicitante serializer.save() @@ -252,7 +280,7 @@ class solicitante(BasePermissionAPIView): # recuperamos el solicitante de la base de datos, enviando un error si no se encuentra solicitante = get_object_or_404(Solicitante, id=request.user.id) # inicializamos el serializer con los datos precargados - serializer = solicitante_serializer(instance=solicitante, data=request.data) + serializer = SolicitanteSerializer(instance=solicitante, data=request.data) # si el serilizer es valido if serializer.is_valid(): # guardamos los cambios @@ -263,9 +291,13 @@ class solicitante(BasePermissionAPIView): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) +class ResetPassword(APIView): + """ + Clase ResetPassword para enviar un correo de restablecimiento de contraseña -# Clase para realizar el restablecimiento de una contraseña olvidada -class reset_password(APIView): + Tipo de solicitud: + - GET (Recibe el email del usuario y envia un correo de restablecimiento) + """ # esta view la puede ejecutar cualquiera permission_classes = [AllowAny] @@ -291,11 +323,24 @@ class reset_password(APIView): return Response({"message": {'error': 'El correo no está registrado.'}}, status=status.HTTP_400_BAD_REQUEST) -# Clase para ingresar la nueva password una vez el usuario confirmó la acción vía email -class nueva_password(APIView): +class NuevaPassword(APIView): + """ + Clase NuevaPassword para registrar una nueva password + + Tipo de solicitud: + - POST (Se envía la nueva contraseña y se le asigna al usuario una vez confirme el restablecimiento por correo) + """ permission_classes = [AllowAny] # método post donde se enviará las nueva password def post(self, request, uidb64, token): + """ + Método post para guardar la nueva contraseña + + Parámetros: + - request (la solicitud realizada por el usuario) + - uidb64 (el id del usuario que restablece su contraseña encriptado en base64) + - token (el token de reestablecimiento de contraseña) + """ # intentamos extraer los datos del usuario try: # decodificamos el id recibido @@ -321,8 +366,15 @@ class nueva_password(APIView): return Response({"message": {'error': 'El enlace no es válido.'}}, status=status.HTTP_400_BAD_REQUEST) -# método para enviar el correo de reestablecimiento de contraseña def enviar_correo_reset_password(email, uid, token): + """ + Método para enviar el correo de restablecimiento de contraseña + + parámetros: + - email (email al que se enviará el enlace de restablecimiento de contraseña) + - uid (id del usuario) + - token (token de restablecimiento de contraseña) + """ # título del correo subject = 'Restablecer contraseña' # Cuerpo del correo electrónico @@ -334,8 +386,16 @@ def enviar_correo_reset_password(email, uid, token): # enviamos el email de restablecimiento de contraseña send_mail(subject, message, from_email, recipient_list) -# Función para enviar el correo de confirmación + def enviar_correo_verificacion(email, uid, token): + """ + Método para enviar el correo de verificación de correo + + parámetros: + - email (email al que se enviará el enlace de verificación de correo) + - uid (id del usuario) + - token (token de verificación de correo) + """ # tema o título del correo subject = 'Verificación de la cuenta' # cuerpo del correo con el enlace de verificación, que incluye el token y el id del usuario @@ -347,8 +407,13 @@ def enviar_correo_verificacion(email, uid, token): # enviamos el email de verificación send_mail(subject, message, from_email, recipient_list) -# clase para manejar la verificación del correo electrónico -class verificar_correo(APIView): +class VerificarCorreo(APIView): + """ + clase para verificar el correo del ususario y hacerlo usuario activo + + Tipo de solicitud: + - GET (Recupera el token del usario y cambia si estatus a is_active = True) + """ permission_classes = [AllowAny] def get(self, request, uidb64, token ): -- GitLab