2009-10-10 2 views
25

Я ищу информацию о том, как другие могли бы это сделать. Я собираюсь предоставить представления класса (django group).Представления на основе ролей Django?

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

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

Это было сделано через стороннее приложение? И как бы вы подошли к этой проблеме?

Спасибо, Пит

+1

Ребята, система разрешения Джанго не соответствует моим потребностям. Вот почему я прошу обратиться за помощью к архитектуре: P – slypete

ответ

38

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

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. разрешения вошедшего в данный момент пользователя хранятся в переменной шаблона {{завивки}}. Этот код проверяет то же разрешение, что и выше.

{% 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), []) 

Есть, вероятно, многие другие подходы.

+1

Как вы создадите список ссылок, чтобы предоставить пользователю возможность использовать встроенную систему разрешений django? – slypete

+1

Для записи я не выбрал этот ответ как лучший. Я не думаю, что это так. – slypete

1

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

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

Там является API for other authentication and authorization sources, так что вам не нужно придерживаться этой таблицы разрешений.

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

+0

какой-либо намек на каждый объект acl? – gpilotino

4

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

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

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

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

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

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

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

+0

Я закончил этот маршрут с нашим приложением, но его не идеально. Я обнаружил, что производительность немного снизилась. Я ищу в другом месте для лучшего решения ACL. – Gevious

+0

Это не масштабируемо вообще. Любые идеи по ACL? – user710907

2

У меня была аналогичная проблема не так давно. Наше решение сделало трюк, хотя это может быть слишком просто для вашей ситуации. Как и каждый, мы использовали систему разрешения 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, связанный с моделью Группы выше. Это позволило нам предоставить пользователям доступ к нулевым или более группам по мере необходимости. (documentation)

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

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

1

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

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

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

0

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

функции просмотра получил украшен:

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, который получил набор внутри контекста процессора. Аутентифицированные пользователи получили роль для немытых масс a DummyRole.

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

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

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

1

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

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

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

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

Смежные вопросы