Cuando desarrollamos APIs con Django Rest Framework (DRF), uno de los aspectos más importantes es gestionar correctamente los permisos y roles para proteger los recursos y definir qué usuarios pueden realizar determinadas acciones. DRF ofrece una infraestructura robusta para controlar el acceso a las vistas y los datos expuestos por nuestra API, basándose en roles y permisos específicos.
En este artículo, exploraremos cómo gestionar permisos y roles en Django Rest Framework, abordando temas como los permisos predeterminados de DRF, la creación de permisos personalizados y cómo trabajar con un sistema de roles para controlar el acceso.
En Django Rest Framework, los permisos son clases que controlan si una solicitud tiene acceso a una vista o a un recurso específico. Están diseñados para restringir el acceso basado en el usuario autenticado, y pueden personalizarse según las necesidades de la aplicación. Los permisos son evaluados antes de que una vista maneje una solicitud, y si el permiso es denegado, se devuelve una respuesta con un código de estado HTTP 403 (Prohibido).
DRF proporciona algunos permisos predeterminados, pero también permite crear permisos personalizados para manejar situaciones más específicas.
Django Rest Framework viene con varios permisos predeterminados que cubren casos comunes de uso. Estos permisos se definen en el archivo de configuración de Django (settings.py
) y pueden aplicarse a nivel global o en vistas específicas.
1. AllowAny: Permite el acceso a cualquier usuario, autenticado o no.
from rest_framework.permissions import AllowAny
2. IsAuthenticated: Restringe el acceso solo a usuarios autenticados.
from rest_framework.permissions import IsAuthenticated
3. IsAdminUser: Restringe el acceso solo a usuarios que tengan el campo is_staff=True
.
from rest_framework.permissions import IsAdminUser
4. IsAuthenticatedOrReadOnly: Permite el acceso de solo lectura a usuarios no autenticados, y acceso completo a usuarios autenticados.
from rest_framework.permissions import IsAuthenticatedOrReadOnly
Para aplicar permisos a nivel global en toda la API, se deben definir en el archivo settings.py
. Por ejemplo, si queremos que solo los usuarios autenticados puedan acceder a la API, podríamos configurar lo siguiente:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
Con esta configuración, todas las vistas de nuestra API requerirán autenticación para ser accedidas. Sin embargo, también podemos definir permisos a nivel de vista o vista de conjunto (viewset) si necesitamos una mayor granularidad.
En lugar de aplicar permisos globalmente, podemos especificar permisos para vistas individuales. Esto se hace agregando la propiedad permission_classes
en nuestras vistas.
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.views import APIView
from rest_framework.response import Response
class PublicView(APIView):
permission_classes = [AllowAny]
def get(self, request):
return Response({"message": "Vista pública"})
class PrivateView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({"message": "Vista privada"})
En este ejemplo, la vista PublicView
estará disponible para todos los usuarios, mientras que PrivateView
requerirá que el usuario esté autenticado.
Aunque los permisos predeterminados son útiles en muchos casos, a menudo es necesario crear permisos personalizados para manejar situaciones más específicas. DRF facilita la creación de permisos personalizados, simplemente extendiendo la clase BasePermission
.
Supongamos que queremos permitir que solo los usuarios que hayan completado su perfil accedan a ciertas vistas. Para ello, podemos crear un permiso personalizado.
from rest_framework.permissions import BasePermission
class HasCompletedProfile(BasePermission):
"""
Permite el acceso solo si el usuario ha completado su perfil.
"""
def has_permission(self, request, view):
return request.user.is_authenticated and request.user.profile.is_completed
En este caso, la clase HasCompletedProfile
extiende BasePermission
y sobreescribe el método has_permission
, que se encarga de devolver True
o False
dependiendo de si el usuario cumple con la condición (en este caso, si ha completado su perfil).
Para aplicar este permiso personalizado a una vista:
from rest_framework.views import APIView
from .permissions import HasCompletedProfile
from rest_framework.response import Response
class UserProfileView(APIView):
permission_classes = [HasCompletedProfile]
def get(self, request):
return Response({"message": "Has completado tu perfil"})
Con esta configuración, solo los usuarios que hayan completado su perfil podrán acceder a la vista.
Aunque Django Rest Framework no ofrece un sistema de roles por defecto, podemos implementar uno utilizando las herramientas que ofrece Django, como los grupos y los permisos de usuario.
Django incluye un sistema de permisos basado en grupos. Los grupos permiten agrupar usuarios y asignar permisos de manera masiva, lo que resulta útil para gestionar roles.
1. Grupos: Un grupo es una colección de usuarios que comparten ciertos permisos.
2. Permisos: Son acciones específicas que los usuarios o grupos pueden realizar, como agregar, cambiar o eliminar un modelo en Django.
Podemos crear diferentes roles en nuestra aplicación utilizando los grupos de Django. Supongamos que queremos tener dos roles en nuestra aplicación: admin
y editor
.
En el Django Admin, podemos crear grupos de usuarios y asignarles permisos específicos. Para hacerlo:
1. Entra al panel de administración (/admin
).
2. Dirígete a Grupos y crea un grupo llamado Admin
.
3. Asigna los permisos que consideres necesarios a este grupo.
4. Repite el proceso para crear el grupo Editor
.
Una vez creados los grupos, podemos asignar usuarios a esos grupos. Esto también se puede hacer desde el panel de administración, editando un usuario y seleccionando el grupo al que queremos que pertenezca.
Ahora, en nuestras vistas, podemos verificar si el usuario pertenece a un grupo específico para restringir el acceso. Para hacerlo, podemos utilizar la propiedad groups
del usuario en un permiso personalizado.
from rest_framework.permissions import BasePermission
class IsAdminUserOrEditor(BasePermission):
"""
Permite el acceso a usuarios que son admin o editor.
"""
def has_permission(self, request, view):
return request.user.is_authenticated and (
request.user.groups.filter(name='Admin').exists() or
request.user.groups.filter(name='Editor').exists()
)
Una vez creado el permiso personalizado que verifica si el usuario pertenece a un grupo, podemos aplicarlo a las vistas.
class AdminOrEditorView(APIView):
permission_classes = [IsAdminUserOrEditor]
def get(self, request):
return Response({"message": "Solo admins y editores pueden ver esta vista"})
Gestionar permisos y roles en Django Rest Framework es fundamental para proteger los recursos de la API y garantizar que los usuarios solo puedan acceder a las funcionalidades para las que están autorizados. DRF ofrece una amplia gama de herramientas para implementar permisos, desde permisos predeterminados hasta permisos personalizados basados en grupos y roles.
Mediante el uso de los grupos de Django, podemos crear un sistema robusto de roles que controle el acceso a diferentes partes de nuestra API de manera eficiente. Además, la capacidad de crear permisos personalizados en DRF nos permite adaptar el control de acceso a las necesidades específicas de nuestra aplicación.
Con estos enfoques, puedes asegurar que tu API esté protegida y que los usuarios tengan acceso solo a los recursos que deben.
Jorge García
Fullstack developer