JavaRush /Курсы /Модуль 3: Django /Ограничение доступа к эндпоинтам на основе ролей

Ограничение доступа к эндпоинтам на основе ролей

Модуль 3: Django
21 уровень , 5 лекция
Открыта

Роль — это категория пользователей, которая определяет их уровень доступа к функциональности вашего приложения. Роли помогают разделить права доступа для разных типов пользователей, например:

  • Администратор: доступ к административным функциям.
  • Редактор: доступ к созданию и редактированию контента.
  • Пользователь: доступ только к базовому функционалу приложения.

В реальных проектах ролевой доступ используется почти везде: от корпоративных систем до онлайн-магазинов и социальных сетей. Роли делают систему более безопасной, понятной и управляемой. Например, в интернет-магазине администратор может видеть все заказы, а продавец — только свои.

Реализация ролей в проекте Django

Для начала создадим модель Role, чтобы хранить доступные роли в базе данных. Она будет связываться с моделью пользователя через связь ForeignKey.

Откроем приложение, где у нас расположены модели пользователей (например, приложение accounts).

# accounts/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class Role(models.Model):
    name = models.CharField(max_length=64, unique=True)  # Название роли (например, 'admin', 'editor')
    description = models.TextField(blank=True)  # Описание роли (опционально)

    def __str__(self):
        return self.name


class CustomUser(AbstractUser):
    role = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True, blank=True)  # Роль пользователя

Объяснение кода:

  1. Мы добавляем модель Role, которая содержит название роли (name) и её описание (description).
  2. В стандартную модель пользователя (AbstractUser) мы добавили поле role, ссылающееся на модель Role. Таким образом, у каждого пользователя будет своя роль (или её отсутствие).

Теперь создадим и применим миграции:

python manage.py makemigrations
python manage.py migrate

Добавление ролей через Django Admin

Теперь добавим модель Role в админ-зону, чтобы роли можно было создавать и управлять ими:

# accounts/admin.py

from django.contrib import admin
from .models import Role, CustomUser

admin.site.register(Role)
admin.site.register(CustomUser)

После этого зайдите в админ-зону Django и создайте несколько ролей:

  1. Администратор (admin).
  2. Редактор (editor).
  3. Пользователь (user).

Создание кастомного разрешения на основе ролей

Теперь создадим кастомное разрешение для проверки ролей пользователя. Для этого напишем класс разрешения в файле permissions.py:

# accounts/permissions.py

from rest_framework.permissions import BasePermission

class RolePermission(BasePermission):
    """
    Кастомное разрешение для проверки ролей пользователя.
    """
    allowed_roles = []  # Список разрешённых ролей

    def has_permission(self, request, view):
        user = request.user

        # Проверяем, что пользователь аутентифицирован
        if not user.is_authenticated:
            return False

        # Проверяем, что роль пользователя входит в список разрешённых ролей
        if user.role and user.role.name in self.allowed_roles:
            return True

        return False
  1. Класс RolePermission наследуется от BasePermission.
  2. Мы определяем список разрешённых ролей в атрибуте allowed_roles (например, ['admin', 'editor']).
  3. Метод has_permission возвращает True, если пользователь имеет одну из разрешённых ролей, иначе — False.

Использование кастомного разрешения в представлениях

Теперь применим наше разрешение в представлении. Например, у нас есть API для управления статьями, к которому должны иметь доступ только пользователи с ролями admin или editor.

# articles/views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from accounts.permissions import RolePermission

class ArticleView(APIView):
    """
    Эндпоинт для работы со статьями.
    Доступ разрешён только для ролей 'admin' и 'editor'.
    """
    permission_classes = [RolePermission]
    RolePermission.allowed_roles = ['admin', 'editor']  # Задаём разрешённые роли

    def get(self, request):
        return Response({"message": "Доступ разрешён для администраторов и редакторов!"})

Теперь, если пользователь с ролью, например, user, попытается обратиться к этому эндпоинту, он получит ошибку 403 Forbidden.

Дополнительные аспекты ролевой модели

В некоторых случаях нужно настроить доступ для разных эндпоинтов или операций внутри одного представления. Например, администратор может читать, создавать и удалять статьи, а редактор — только читать и редактировать.

Для этого разделим операции по ролям:

# articles/permissions.py

class RolePermissionWithActions(BasePermission):
    """
    Кастомное разрешение для проверки ролей с учётом типов операций.
    """
    role_action_map = {}  # Словарь с ролями и разрешёнными действиями

    def has_permission(self, request, view):
        user = request.user

        # Проверяем, что пользователь аутентифицирован
        if not user.is_authenticated:
            return False

        # Определяем действие (метод HTTP-запроса)
        action = request.method.lower()

        # Проверяем, что роль пользователя разрешает текущее действие
        if user.role and action in self.role_action_map.get(user.role.name, []):
            return True

        return False

Теперь в вашем представлении вы можете задать разрешённые действия для каждой роли:

# articles/views.py

from articles.permissions import RolePermissionWithActions

class MultiActionArticleView(APIView):
    """
    Эндпоинт для работы со статьями.
    Доступ к операциям зависит от роли пользователя.
    """
    permission_classes = [RolePermissionWithActions]
    RolePermissionWithActions.role_action_map = {
        'admin': ['get', 'post', 'delete'],  # Администратор: читать, создавать, удалять
        'editor': ['get', 'put'],  # Редактор: читать, редактировать
    }

    def get(self, request):
        return Response({"message": "Чтение статьи."})

    def post(self, request):
        return Response({"message": "Создание статьи."})

    def delete(self, request):
        return Response({"message": "Удаление статьи."})

Тестирование ролевой модели

Теперь протестируем наши разрешения. Для этого мы можем использовать Postman или любой другой клиент для работы с API. Попробуйте зайти на эндпоинты под разными пользователями и убедитесь, что доступ работает согласно ролям.

Как это помогает в реальной жизни?

Настройка ролевой модели полезна в любом проекте, где есть разделение прав доступа. Например:

  • В корпоративной CRM системе роли помогают изолировать данные между сотрудниками разных отделов.
  • В онлайн-магазине доступ к административной панели ограничивается только для сотрудников магазина.
  • В социальных сетях — права модераторов позволяют модерировать контент, недоступный для обычных пользователей.

Бонус: на собеседованиях умение реализовать ролевую модель — это часто встречающийся вопрос, поэтому не забудьте заготовить истории о том, как вы это освоили и внедрили!

Теперь вы официально готовы добавлять роли в своём API! 🎉

1
Задача
Модуль 3: Django, 21 уровень, 5 лекция
Недоступна
Создание кастомного класса разрешений для заказов
Создание кастомного класса разрешений для заказов
1
Задача
Модуль 3: Django, 21 уровень, 5 лекция
Недоступна
Проверка доступа к API для разных типов клиентов
Проверка доступа к API для разных типов клиентов
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ