跳转到主要内容

一个增强型权限系统,允许逻辑权限系统扩展到复杂权限

项目描述

Build status Coverage Requirements Status Inspection Version License Format Supported python versions Status
作者

Alisue <lambdalisue@hashnote.net>

支持的Python版本

Python 2.7, 3.3, 3.4, 3.5, 3.6

支持的Django版本

Django 1.8 - 1.11b

一个增强型权限库,它支持在Django中处理复杂的权限逻辑。

文档

http://django-permission.readthedocs.org/zh/latest/

安装

使用pip如下

$ pip install django-permission

用法

以下内容可能有助于您理解。

配置

  1. permission 添加到您的设置模块中的 INSTALLED_APPS

    INSTALLED_APPS = (
        # ...
        'permission',
    )
  2. 添加我们的额外授权/身份验证后端

    AUTHENTICATION_BACKENDS = (
        'django.contrib.auth.backends.ModelBackend', # default
        'permission.backends.PermissionBackend',
    )
  3. 按照以下说明将逻辑权限应用到Django模型中

自动发现

类似于Django的admin包,django-permission会自动发现应用目录中的 perms.py 文件,通过运行 ``permission.autodiscover()``。此外,如果 perms.py 模块包含一个 PERMISSION_LOGICS 变量,django-permission将自动运行以下函数来应用权限逻辑。

for model, permission_logic_instance in PERMISSION_LOGICS:
    if isinstance(model, str):
        model = get_model(*model.split(".", 1))
    add_permission_logic(model, permission_logic_instance)

快速教程

  1. import permission; permission.autodiscover() 添加到您的 urls.py

    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    
    admin.autodiscover()
    # add this line
    import permission; permission.autodiscover()
    
    urlpatterns = patterns('',
        url(r'^admin/', include(admin.site.urls)),
        # ...
    )
  2. 在您的应用目录中编写 perms.py

    from permission.logics import AuthorPermissionLogic
    from permission.logics import CollaboratorsPermissionLogic
    
    PERMISSION_LOGICS = (
        ('your_app.Article', AuthorPermissionLogic()),
        ('your_app.Article', CollaboratorsPermissionLogic()),
    )

您可以使用 PERMISSION_AUTODISCOVER_MODULE_NAMEPERMISSION_AUTODISCOVER_VARIABLE_NAME 分别指定不同的模块或变量名称。

应用权限逻辑

假设您编写了一个文章模型,该模型有一个 author 属性来存储文章的创建者,并且您想授予该创建者完整的控制权限(例如添加、更改和删除权限)。

您需要做的就是将 permission.logics.AuthorPermissionLogic 应用到 Article 模型,如下所示

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


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic
from permission import add_permission_logic
from permission.logics import AuthorPermissionLogic
add_permission_logic(Article, AuthorPermissionLogic())
from django.db import models
from django.contrib.auth.models import User


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    project = models.ForeignKey('permission.Project')

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

class Project(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic to Article
from permission import add_permission_logic
from permission.logics import AuthorPermissionLogic
add_permission_logic(Article, AuthorPermissionLogic(
    field_name='project__author',
))

就是这样。现在以下代码将按预期工作

user1 = User.objects.create_user(
    username='john',
    email='john@test.com',
    password='password',
)
user2 = User.objects.create_user(
    username='alice',
    email='alice@test.com',
    password='password',
)

art1 = Article.objects.create(
    title="Article 1",
    body="foobar hogehoge",
    author=user1
)
art2 = Article.objects.create(
    title="Article 2",
    body="foobar hogehoge",
    author=user2
)

# You have to apply 'permission.add_article' to users manually because it
# is not an object permission.
from permission.utils.permissions import perm_to_permission
user1.user_permissions.add(perm_to_permission('permission.add_article'))

assert user1.has_perm('permission.add_article') == True
assert user1.has_perm('permission.change_article') == False
assert user1.has_perm('permission.change_article', art1) == True
assert user1.has_perm('permission.change_article', art2) == False

assert user2.has_perm('permission.add_article') == False
assert user2.has_perm('permission.delete_article') == False
assert user2.has_perm('permission.delete_article', art1) == False
assert user2.has_perm('permission.delete_article', art2) == True

#
# You may also be interested in django signals to apply 'add' permissions to the
# newly created users.
# https://docs.django.ac.cn/en/dev/ref/signals/#django.db.models.signals.post_save
#
from django.db.models.signals.post_save
from django.dispatch import receiver
from permission.utils.permissions import perm_to_permission

@receiver(post_save, sender=User)
def apply_permissions_to_new_user(sender, instance, created, **kwargs):
    if not created:
        return
    #
    # permissions you want to apply to the newly created user
    # YOU SHOULD NOT APPLY PERMISSIONS EXCEPT PERMISSIONS FOR 'ADD'
    # in this way, the applied permissions are not object permission so
    # if you apply 'permission.change_article' then the user can change
    # any article object.
    #
    permissions = [
        'permission.add_article',
    ]
    for permission in permissions:
        # apply permission
        # perm_to_permission is a utility to convert string permission
        # to permission instance.
        instance.user_permissions.add(perm_to_permission(permission))

请参阅http://django-permission.readthedocs.org/en/latest/_modules/permission/logics/author.html#AuthorPermissionLogic 了解此逻辑的工作原理。

现在,假设您为文章添加了一个 collaborators 属性来存储合作者,并且您想授予他们更改权限。

您需要做的就是将 permission.logics.CollaboratorsPermissionLogic 应用到 Article 模型,如下所示

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


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(User)
    collaborators = models.ManyToManyField(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic and CollaboratorsPermissionLogic
from permission import add_permission_logic
from permission.logics import AuthorPermissionLogic
from permission.logics import CollaboratorsPermissionLogic
add_permission_logic(Article, AuthorPermissionLogic())
add_permission_logic(Article, CollaboratorsPermissionLogic(
    field_name='collaborators',
    any_permission=False,
    change_permission=True,
    delete_permission=False,
))
from django.db import models
from django.contrib.auth.models import User


class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    project = models.ForeignKey('permission.Project')

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

class Project(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    collaborators = models.ManyToManyField(User)

    # this is just required for easy explanation
    class Meta:
        app_label='permission'

# apply AuthorPermissionLogic to Article
from permission import add_permission_logic
from permission.logics import CollaboratorsPermissionLogic
add_permission_logic(Article, CollaboratorsPermissionLogic(
    field_name='project__collaborators',
))

就是这样。现在以下代码将按预期工作

user1 = User.objects.create_user(
    username='john',
    email='john@test.com',
    password='password',
)
user2 = User.objects.create_user(
    username='alice',
    email='alice@test.com',
    password='password',
)

art1 = Article.objects.create(
    title="Article 1",
    body="foobar hogehoge",
    author=user1
)
art1.collaborators.add(user2)

assert user1.has_perm('permission.change_article') == False
assert user1.has_perm('permission.change_article', art1) == True
assert user1.has_perm('permission.delete_article', art1) == True

assert user2.has_perm('permission.change_article') == False
assert user2.has_perm('permission.change_article', art1) == True
assert user2.has_perm('permission.delete_article', art1) == False

请参阅http://django-permission.readthedocs.org/en/latest/_modules/permission/logics/collaborators.html#CollaboratorsPermissionLogic 了解此逻辑的工作原理。

还有 StaffPermissionLogicGroupInPermissionLogic 用于基于 is_staffgroup 的权限逻辑。

自定义权限逻辑

您的自定义权限逻辑类必须是 permission.logics.PermissionLogic 的子类,并且必须重写 has_perm(user_obj, perm, obj=None) 方法,该方法返回布尔值。

类、方法或函数装饰器

类似于Django的permission_required,但可用于对象权限,并且可以作为类、方法或函数装饰器使用。此外,您无需为此装饰器指定对象即可进行对象权限。此装饰器会自动从请求中确定对象(因此您不能为此装饰器使用非视图类/方法/函数,但在那种情况下您仍然可以使用user.has_perm)。

>>> from permission.decorators import permission_required
>>> # As class decorator
>>> @permission_required('auth.change_user')
>>> class UpdateAuthUserView(UpdateView):
...     pass
>>> # As method decorator
>>> class UpdateAuthUserView(UpdateView):
...     @permission_required('auth.change_user')
...     def dispatch(self, request, *args, **kwargs):
...         pass
>>> # As function decorator
>>> @permission_required('auth.change_user')
>>> def update_auth_user(request, *args, **kwargs):
...     pass

覆盖内置的if 模板标签

django-permission覆盖了内置的if 标签,增加了两个操作符以处理模板中的权限。您可以使用has 关键字编写权限测试,并使用以下方式指定目标对象。

{% if user has 'blogs.add_article' %}
    <p>This user have 'blogs.add_article' permission</p>
{% elif user has 'blog.change_article' of object %}
    <p>This user have 'blogs.change_article' permission of {{object}}</p>
{% endif %}

{# If you set 'PERMISSION_REPLACE_BUILTIN_IF = False' in settings #}
{% permission user has 'blogs.add_article' %}
    <p>This user have 'blogs.add_article' permission</p>
{% elpermission user has 'blog.change_article' of object %}
    <p>This user have 'blogs.change_article' permission of {{object}}</p>
{% endpermission %}

许可证

MIT许可协议(MIT)

版权所有(c)2015 Alisue, hashnote.net

特此授予任何获得此软件及其相关文档文件(“软件”)副本的个人免费使用软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向软件提供方提供软件的人进行上述操作,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、适用于特定用途和侵犯版权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是基于合同、侵权或其他原因,无论是否与软件或软件的使用或其他交易有关。

项目详情


下载文件

下载适用于您平台的应用程序。如果您不确定要选择哪个,请了解有关安装软件包的更多信息。

源分发

django-permission-1.0.5.tar.gz (33.3 kB 查看哈希值)

上传时间

由以下支持