Как реализовать динамическое создание групп разрешений с разным набором конечных точек Django Rest Framework

#rest #design-patterns #django-rest-framework #architecture #django-permissions

#отдых #дизайн-шаблоны #django-rest-фреймворк #архитектура #django-разрешения

Вопрос:

В моем проекте у меня много представлений конечных точек (APIViews, ViewSets). Для всех из них теперь я устанавливаю разрешения, некоторые из них являются разрешениями по умолчанию (например, AllowAny), а некоторые созданы на заказ:

permission_classes = (IsUserHaveSomePermission,)

Теперь я хочу внедрить некоторую гибкую систему, которая позволит мне указать набор разрешенных конечных точек для каждого пользователя, например:

Во внешнем интерфейсе я хочу выбрать какого-либо пользователя и иметь список флажков, соответствующих конечным точкам проекта.

введите описание изображения здесь

Это просто утопическое решение, некоторые детали могут быть изменены, но главный вопрос заключается в том, как сделать что-то подобное, чтобы администраторы могли динамически изменять список разрешенных конечных точек / представлений для пользователя? заранее спасибо

Ответ №1:

Это решение может быть реализовано путем сохранения, если у пользователя есть разрешение на доступ к текущему методу запроса и пути запроса.

Создайте новую модель базы данных для хранения пользователя, метода запроса и пути запроса. Допустим, имя модели — requestPermission

Вместо пути вы можете сохранить константу, представляющую URL-адрес, чтобы у вас была возможность редактировать путь позже. Эта константа может быть именем URL-адреса, которое поддерживается django.

 class RequestPermission(models.Model):
    user = user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='request_permissions')
    method = models.CharField(max_length=10)
    path_name = models.CharField(max_length=200)
 

создайте пользовательский класс разрешений:

 class IsUserResuestAllowed(permissions.BasePermission):

    def has_permission(self, request, view):
        user = request.user
        # you can choose how to get the path_name from the path
        path_name = get_path_name(request.path)
        return RequestPermission.objects.filter(user=user, method=request.method, path_name=path_name).exists()
 

Теперь вы можете использовать этот класс в качестве класса разрешений по умолчанию в настройках rest Framework или использовать его для каждого представления.

Комментарии:

1. Да, я рассматривал подобное решение, но здесь мне все еще нужно жестко закодировать все существующие имена путей и их http-методы. Я хотел бы, чтобы у меня была какая-нибудь функция get_api_endpoints() , которая возвращала бы какой-нибудь список, например [{url: 'api/v1/endpoint', name: 'url-path-name', methods: ['post', 'delete',...]}, ....] , чтобы я мог легко отобразить их где-нибудь.

2. Для тех, кому нужна такая функция, я частично взял ее из github.com/django-extensions/django-extensions/blob/master /… Примечание: все ваши URL-адреса должны иметь имена