Skip to main content

简单灵活的 Flask 应用权限控制。

项目描述

最新版本 麻省理工学院许可证

简单灵活的 Flask 应用权限控制。

特征

  • 简单:您需要做的就是继承RulePermission类。

  • 灵活:支持规则继承和按位运算(&|)来构建您自己的规则。

安装

$ pip install permission

规则

Rule有 3 个可以被覆盖的方法:

  • base():定义基本规则。

  • check():确定是否应该通过此规则。

  • deny():将在check()失败时执行。

您应该始终覆盖check()deny(),同时根据需要覆盖 base()

允许

权限有 1 种可以被覆盖的方法:

  • rule():定义此权限所需的规则

您应该始终覆盖rule()

Permission有 2 个可以在代码中使用的实例方法:

  • check():调用这个来检查这个权限的规则

  • deny():当check()失败时调用它来执行代码

用法

首先,您需要通过继承Rule来定义自己的规则,然后覆盖check()deny()

# rules.py
from flask import session, flash, redirect, url_for
from permission import Rule


class UserRule(Rule):
    def check(self):
        """Check if there is a user signed in."""
        return 'user_id' in session

    def deny(self):
        """When no user signed in, redirect to signin page."""
        flash('Sign in first.')
        return redirect(url_for('signin'))

然后通过继承Permission和覆盖 rule()来定义权限:

# permissions.py
from permission import Permission
from .rules import UserRule


class UserPermission(Permission):
    """Only signin user has this permission."""
    def rule(self):
        return UserRule()

使用上面定义的UserPermission有 4 种方法:

1.用作视图装饰器

from .permissions import UserPermission


@app.route('/settings')
@UserPermission()
def settings():
    """User settings page, only accessable for sign-in user."""
    return render_template('settings.html')

2.在视图代码中使用

from .permissions import UserPermission


@app.route('/settions')
def settings():
    permission = UserPermission()
    if not permission.check()
        return permission.deny()
    return render_template('settings.html')

3.在视图代码中使用(使用``with``语句)

from .permissions import UserPermission


@app.route('/settions')
def settings():
    with UserPermission():
        return render_template('settings.html')

注意:如果您在权限检查失败时不引发异常(换句话说,将调用 规则的拒绝() ),则会引发PermissionDeniedException以停止执行 with-body 代码。顺便说一句,您可以根据需要导入此异常:

from permission import PermissionDeniedException

4.在Jinja2模板中使用

首先,您需要将定义的权限注入模板上下文:

from . import permissions


@app.context_processor
def inject_vars():
    return dict(
        permissions=permissions
    )

然后在模板中:

{% if permissions.UserPermission().check() %}
    <a href=<s>"{{ url_for('new') }}"</s>>New</a>
{% endif %}

规则继承

需要说明的是,这里的继承与 Python 类的继承不是一回事,它只是意味着你可以使用 RuleA 作为 RuleB 的基本规则。

我们通过重写base()来实现这一点。

假设管理员用户应该始终是用户:

# rules.py
from flask import session, abort, flash, redirect, url_for
from permission import Rule


class UserRule(Rule):
    def check(self):
        return 'user_id' in session

    def deny(self):
        flash('Sign in first.')
        return redirect(url_for('signin'))


class AdminRule(Rule):
    def base(self):
        return UserRule()

    def check(self):
        user_id = int(session['user_id'])
        user = User.query.filter(User.id == user_id).first()
        return user and user.is_admin

    def deny(self):
        abort(403)

规则位运算

  • RuleA & RuleB表示当 RuleA 和 RuleB 都通过时才会通过。

  • 规则A | RuleB表示将通过 RuleA 或 RuleB。

假设我们需要用 Flask 建立一个论坛。只有主题创建者和管理员用户可以编辑主题:

首先定义规则:

# rules.py
from flask import session, abort, flash, redirect, url_for
from permission import Rule
from .models import User, Topic


class UserRule(Rule):
    def check(self):
        """Check if there is a user signed in."""
        return 'user_id' in session

    def deny(self):
        """When no user signed in, redirect to signin page."""
        flash('Sign in first.')
        return redirect(url_for('signin'))


class AdminRule(Rule):
    def base(self):
        return UserRule()

    def check(self):
        user_id = int(session['user_id'])
        user = User.query.filter(User.id == user_id).first()
        return user and user.is_admin

    def deny(self):
        abort(403)


class TopicCreatorRule(Rule):
    def __init__(self, topic):
        self.topic = topic
        super(TopicCreatorRule, self).__init__()

    def base(self):
        return UserRule()

    def check(self):
        return topic.user_id == session['user_id']

    def deny(self):
        abort(403)

然后定义权限:

# permissions.py
from permission import Permission


class TopicAdminPermission(Permission):
    def __init__(self, topic):
        self.topic = topic
        super(TopicAdminPermission, self).__init__()

    def rule(self):
        return AdminRule() | TopicCreatorRule(self.topic)

所以我们可以在edit_topic视图中使用TopicAdminPermission

from .permissions import TopicAdminPermission


@app.route('topic/<int:topic_id>/edit')
def edit_topic(topic_id):
    topic = Topic.query.get_or_404(topic_id)
    permission = TopicAdminPermission(topic)
    if not permission.check():
        return permission.deny()
    ...

执照

麻省理工学院

项目详情


下载文件

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

源分布

permission-0.4.1.tar.gz (5.1 kB 查看哈希

已上传 source