Last active
February 22, 2019 17:42
-
-
Save hustlzp/8468273 to your computer and use it in GitHub Desktop.
Simple permission control in Flask.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
from flask import request, g | |
from functools import wraps | |
from flask import abort, session, redirect, url_for, flash | |
from .models import Topic, Attachment | |
from . import roles | |
def require_visitor(func): | |
"""仅允许非登陆用户访问,如signin页面""" | |
@wraps(func) | |
def decorator(*args, **kwargs): | |
if g.current_user: | |
return redirect(url_for('forum.index')) | |
return func(*args, **kwargs) | |
return decorator | |
class Permission(object): | |
def __init__(self, role, extra=True, super_extra=True): | |
"""extra用于在同级别user中筛选,super_extra用于允许高级别用户获取此权限""" | |
self.role = role | |
self.extra = extra | |
self.super_extra = super_extra | |
def __call__(self, func): | |
@wraps(func) | |
def decorator(*args, **kwargs): | |
if not self.check(): | |
return self.deny() | |
return func(*args, **kwargs) | |
return decorator | |
def check(self): | |
"""判断是否满足权限条件""" | |
if g.current_role < self.role: | |
return False | |
elif g.current_role == self.role: | |
return self.extra | |
return self.super_extra | |
def deny(self, next_url=""): | |
"""针对不同的role进行不同的处理""" | |
if g.current_role == roles.VisitorRole: | |
flash('此操作需要登录账户') | |
return redirect(url_for('account.signin', next=next_url or request.url)) | |
elif g.current_role == roles.NewUserRole: | |
flash('请登录邮箱激活账户') | |
return redirect(url_for('forum.index')) | |
abort(403) | |
new_user_permission = Permission(roles.NewUserRole) | |
user_permission = Permission(roles.UserRole) | |
admin_permission = Permission(roles.AdminRole) | |
super_admin_permission = Permission(roles.SuperAdminRole) | |
class TopicOwnerPermission(Permission): | |
def __init__(self, topic_id): | |
can = g.current_user and Topic.query.filter(Topic.id == topic_id).filter( | |
Topic.user_id == g.current_user.id).count() > 0 | |
Permission.__init__(self, roles.UserRole, can) | |
class AttachmentOwnerPermission(Permission): | |
def __init__(self, attachment_id): | |
can = g.current_user and Attachment.query.filter(Attachment.id == attachment_id).filter( | |
Attachment.user_id == g.current_user.id).count() > 0 | |
Permission.__init__(self, roles.UserRole, can) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
SuperAdminRole = 5 | |
AdminRole = 4 | |
UserRole = 3 | |
NewUserRole = 2 | |
BanUserRole = 1 | |
VisitorRole = 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 装饰action | |
@bp.route('/reply/<int:reply_id>/ban') | |
@admin_permission | |
def ban_reply(reply_id): | |
"""Proc: ban reply""" | |
reply = Reply.query.get_or_404(reply_id) | |
reply.ban = True | |
reply.baned = datetime.datetime.now() | |
db.session.add(reply) | |
db.session.commit() | |
flash('已将此回复移入回收站') | |
return redirect(url_for('.topic', topic_id=reply.topic_id)) | |
# 在action中使用 | |
@bp.route('/attachment/delete', methods=['POST']) | |
def delete_attachment(): | |
attachment_id = request.form.get('attachment_id') | |
permission = AttachmentOwnerPermission(attachment_id) | |
if not permission.check(): | |
return permission.deny() | |
attachment = Attachment.query.get_or_404(attachment_id) | |
db.session.delete(attachment) | |
db.session.commit() | |
return json.dumps({'result': 'ok'}) | |
# 用于jinja模板 | |
@app.context_processor | |
def inject_vars(): | |
from . import roles, permissions | |
return dict( | |
roles=roles, | |
permissions=permissions | |
) | |
""" | |
{% if permissions.TopicOwnerPermission(topic.id).check() %} | |
<div class="btn-group btn-group-xs"> | |
<a class="btn btn-default btn-ban-topic" | |
href="{{ url_for('forum.ban_topic', topic_id=topic.id) }}" title="移入回收站"> | |
<i class="fa fa-trash-o"></i> | |
</a> | |
<a class="btn btn-default" | |
href="{{ url_for('forum.edit_topic', topic_id=topic.id) }}" title="编辑"> | |
<i class="fa fa-pencil"></i> | |
</a> | |
</div> | |
{% endif %} | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment