Религиозные взгляды Джанго? - PullRequest
29 голосов
/ 10 октября 2009

Я ищу какой-то вклад в то, как другие будут это проектировать. Я собираюсь предоставить класс (django группа) представления на основе.

Например, группа пользователей будет определять, к каким представлениям / шаблонам он или она будет иметь доступ. Я думаю о возможном хранении путей для просмотра функций в таблице, чтобы определить, из чего будет состоять панель ссылок пользователя. Спецификации фильтров также могут быть сохранены, чтобы определить, какие строки будут заполнять эти шаблоны.

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

Это было сделано с помощью стороннего приложения? И как бы вы подошли к этой проблеме?

Спасибо, Пит

Ответы [ 9 ]

42 голосов
/ 10 октября 2009

Django уже имеет систему групп и разрешений, которая может быть достаточной для вашей цели.

http://docs.djangoproject.com/en/dev/topics/auth/

Обычно в своем коде вы проверяете, есть ли у пользователя разрешение. У пользователя есть свои права доступа и разрешения групп, к которым он принадлежит. Вы можете управлять этим довольно легко из консоли администратора.

Есть две части, на которые нужно посмотреть.

  1. Убедитесь, что пользователь запрашивает страницу имеет разрешение на это.
  2. Отображать ссылки на пользователя, только если он имеет разрешение.

Для 1. вы можете проверить разрешения в декораторе как таковые:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def some_view(request):

Для 2. разрешений текущего пользователя, вошедшего в систему, сохраняются в переменной шаблона {{perms}}. Этот код проверяет то же разрешение, что и выше.

{% if perms.polls.can_vote %}
    <a href="/vote">vote</a>
{% endif %}

Чтобы создать список ссылок, вы можете перебрать user.get_all_permissions () и извлечь ссылки (или функцию, которая генерирует ссылку) из dict:

def more_elaborate_list_of_links_for_a_perm(user):
    return ["/link1", ...]

_LINKS = {
    'polls.can_vote' : lambda u: ["/user/specific/link/" + u.id],
    'polls.can_close': lambda u: ['/static/link/1', 'static/link/2'],
    'polls.can_open' : more_elaborate_list_of_links_for_a_perm
}

def gen_links(user):
    # get_all_permissions also gets permissions for users groups
    perms = user.get_all_permissions()
    return sum((_LINKS[p](user) for p in perms if p in _LINKS), [])

Возможно, есть много других подходов.

5 голосов
/ 02 ноября 2009

В Django появился новый очень интересный проект о разрешениях на основе ролей: http://bitbucket.org/nabucosound/django-rbac

4 голосов
/ 29 октября 2009

У нас была похожая проблема. Группы Джанго ДЕЙСТВИТЕЛЬНО не подходят для этого, но вы можете включить их в чистку.

То, как мы это сделали, было следующим:

Каждый объект с контролем доступа имеет отношение ManyToMany к таблице групп. Каждая группа использовалась для определения определенного типа разрешений («можно просматривать основы пациента», «можно редактировать контактную информацию пациента» и т. Д.). Пользователи добавляются в группы, для которых у них должны быть разрешения (в вашем примере просмотра только пациентов в этой больнице у вас может быть группа "Больница с видом на долину").

Затем, когда вы переходите к отображению списка записей для пользователя, вы фильтруете на основе соединения двух групп. Пользователь должен иметь все связанные разрешения группы для просмотра данного объекта.

Если ваша система требует этого, вы можете оставить отдельное ManyToMany с отрицательными разрешениями или отдельными правами на чтение / запись. Вы также можете определить набор метагрупп (врач, медсестра), которые приведут к тому, что ваш поисковый фильтр получит фактическое подмножество разрешений.

Что касается проблемы с панелью ссылок, вы можете генерировать ее программно, используя ту же систему - фильтр на основе классов объектов, которые пользователь может видеть или редактировать, а затем использовать функцию типа get_absolute_url() (возможно, вызвать ее). get_index_url()) для возврата ссылок для индекса каждого класса объектов.

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

2 голосов
/ 30 октября 2009

У меня была похожая проблема не так давно. Наше решение сработало, хотя оно может быть слишком простым для вашей ситуации. Как и все предлагают, мы использовали систему разрешений django для контроля взаимодействия пользователей с моделями. Однако мы не просто пытались группировать пользователей, мы также группировали объекты с помощью GenericForeignKey.

Мы создали модель, которая была связана с самим собой, чтобы можно было разрабатывать иерархии.

class Group( models.Model ):
    name = models.CharField( ... )
    parent = models.ForeignKey( 'self', blank=True, null=True)
    content_type = models.ForeignKey( ContentType )
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey( 'content_type', 'object_id' )
    ...

Чтобы заставить его работать, мы также создали модель, которая будет служить профилем пользователя модели пользователя django. Все, что он содержал, было ManyToManyField, привязанным к модели группы выше. Это позволило нам предоставить пользователям доступ к нулю или более группам по мере необходимости. ( Документация )

class UserProfile( models.Model ):
    user = models.ForeignKey( User, unique=True )
    groups = models.ManyToManyField( Group )
    ...

Это дало нам лучшее из обоих миров и удержало нас от попыток засорять все в систему разрешений Джанго. Я использую эту базовую настройку для управления доступом пользователей к спортивному контенту (некоторые пользователи могут получить доступ к целым лигам, некоторые только к одной или двум конференциям, некоторые имеют доступ только к отдельным командам), и в этой ситуации это хорошо работает. Вероятно, он может быть достаточно обобщенным, чтобы соответствовать вашим потребностям.

1 голос
/ 07 сентября 2012

Вы можете использовать роли пользователя django

https://github.com/dabapps/django-user-roles

1 голос
/ 04 июля 2012

Этот вопрос был задан в октябре 2009 , и проблема все еще существует в Июль 2012 .

Я искал хорошее приложение на основе ролей и нашел django-permission как лучший результат.

Мне были нужны три важные функции: Роли , представление Декораторы и Templatetag ; видимо у django-permissions есть все из них. Прочитайте это документы для его использования.

Единственным недостатком является то, что он находится в стадии разработки.

1 голос
/ 30 октября 2009

На сайте для эксперта по вину Пино Нуар мы создали доступ к каждому объекту на основе ряда различных критериев. Если входящая ссылка имела поле реферера, которое соответствовало доменному имени популярного винодельни, то пользователь получал «токен винзавода», который распространялся на все статьи, заметки с дегустацией и т. Д., Относящиеся к этому винодельне. Мы используем «именные токены» для раздачи при дегустации, и они дали доступ к определенным частям сайта. Мы даже используем это для предоставления определенных типов разрешений паукам поисковых систем, а затем следим за тем, чтобы ссылки, поступающие от этих поисковых систем, имели те же разрешения, что и пауки (т. Е. Никаких игр-маскировщиков).

Короткая версия заключается в том, что вы можете создать класс (мы назвали их TokenBuckets, которые содержат токены), и каждый объект (на странице сведений, странице списка или любом другом) может запросить у TokenBucket пользователя определенный уровень доступа. разрешено.

По сути, это странная система ACL. Было не так сложно создать механику. Вся магия заключается в определении того, при каких обстоятельствах жетоны попадают в ведро.

1 голос
/ 10 октября 2009

Если вам не нужны реальные ACL для каждого объекта, вы можете просто использовать систему разрешений Django. Чтобы получить список всех доступных разрешений:

from django.contrib.auth.models import Permission
perms = Permission.objects.all()

Существует API для других источников аутентификации и авторизации , поэтому вам не нужно придерживаться этой таблицы разрешений.

Вы можете взломать эту систему Django в соответствии с вашими потребностями в соответствии с этой моделью авторизации (RBAC), или вы можете предложить решение, подобное ACL.

0 голосов
/ 02 ноября 2009

Мы использовали систему ролевой базы для аналогичной проблемы. В основном пользователи имеют разрешения на разные роли.

Просмотр функций оформления:

def needs_capability(capability,redirect_to="/cms/"):
   def view_func_wrapper(view_func):
       def wrapped_view_func(request,*args,**kwargs):
           if not request.role._can(capability):
              return HttpResponseRedirect(redirect_to)
           return view_func(request,*args,**kwargs)
       return wrapped_view_func
   return view_func_wrapper

Остальная часть магии находится внутри атрибута request.role, который получил установить внутри контекстного процессора. Прошедшие проверку пользователи получили роль для немытых масс пустышка.

Доступ к информации был ограничен внутри шаблонов:

 {% if not request.role.can.view_all_products %}
          Lots of products, yeah!
 {% endif %}

Не самое чистое решение, на мой взгляд, но сработало, как и ожидалось.

...