一个增强型权限系统,允许逻辑权限系统扩展到复杂权限
项目描述
- 作者
Alisue <lambdalisue@hashnote.net>
- 支持的Python版本
Python 2.7, 3.3, 3.4, 3.5, 3.6
- 支持的Django版本
Django 1.8 - 1.11b
一个增强型权限库,它支持在Django中处理复杂的权限逻辑。
文档
安装
使用pip如下
$ pip install django-permission
用法
以下内容可能有助于您理解。
配置
将 permission 添加到您的设置模块中的 INSTALLED_APPS
INSTALLED_APPS = ( # ... 'permission', )
添加我们的额外授权/身份验证后端
AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', # default 'permission.backends.PermissionBackend', )
按照以下说明将逻辑权限应用到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)
快速教程
将 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)), # ... )
在您的应用目录中编写 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_NAME 或 PERMISSION_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 了解此逻辑的工作原理。
还有 StaffPermissionLogic 和 GroupInPermissionLogic 用于基于 is_staff 或 group 的权限逻辑。
自定义权限逻辑
您的自定义权限逻辑类必须是 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
特此授予任何获得此软件及其相关文档文件(“软件”)副本的个人免费使用软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向软件提供方提供软件的人进行上述操作,前提是遵守以下条件
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、适用于特定用途和侵犯版权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是基于合同、侵权或其他原因,无论是否与软件或软件的使用或其他交易有关。