网站后端.Flask.实战-社交博客开发-角色权限?

女生的网名这么多〃 提交于 2020-03-12 20:15:00

用户角色

1.Web程序成员可能包括管理员/内容发布员/普通用户/匿名用户等,每种角色对应着拥有不同的权限控制

2.对于只有普通用户/管理员分类,只需在用户模型中添加一个is_administrator布尔值即可,对于多角色可结合权限属性绑定实现

角色权限

0b00000001

0x01

关注其它用户

0b00000010

0x02

评论其它人文章

0b00000100

0x04

写文章

0b00001000

0x08

管理其他人发表的评论

0b10000000

0x80

管理网站

0b00000000

0x00

匿名用户,未登录的用户,应该只具有阅读文章

0b00000011

0x03

普通用户,应该只具有阅读文章,发布文章,评论文章和关注其他用户的权限,新用户的默认角色

0b00000111

0x07

协管用户,应该只具有阅读文章,发布文章,评论文章和关注其他用户,审查不当评论的权限

0b11111111

0xff

管理用户,应该具有所有权限,包括修改其它用户所属角色的权限

FlaskWeb/app/models.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
from . import db, loginmanager
from flask import current_app
from flask_login import UserMixin
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from werkzeug.security import generate_password_hash, check_password_hash

@loginmanager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

class Permission(object):
    FOLLOW = 0x01
    COMMENT = 0x02
    WRITE_ARTICLES = 0x04
    MANAGE_COMMENTS = 0x08
    ADMINISTER_POWER = 0x80

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False, index=True)
    permission = db.Column(db.Integer)
    default = db.Column(db.Boolean, default=False, index=True)
    users = db.relationship('User', backref='role', lazy='dynamic')

    @staticmethod
    def insert_roles():
        roles = {
            'user': (
                Permission.FOLLOW |
                Permission.COMMENT |
                Permission.WRITE_ARTICLES, True),
            'manager': (
                Permission.FOLLOW |
                Permission.COMMENT |
                Permission.WRITE_ARTICLES |
                Permission.MANAGE_COMMENTS, False),
            'administrator': (
                Permission.ADMINISTER_POWER, False)
        }
        for cur_role in roles:
            role = Role.query.filter_by(name=cur_role).first()
            if not role:
                role = Role(name=cur_role)
            role.permission = roles[cur_role][0]
            role.default = roles[cur_role][-1]
            db.session.add(role)
            db.session.commit()

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, nullable=False, index=True)
    username = db.Column(db.String(64), unique=True, nullable=False, index=True)
    password_hash = db.Column(db.String(128), nullable=False)
    is_confirmed = db.Column(db.Boolean, default=False)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    @property
    def password(self):
        raise AttributeError(u'password 不允许读取.')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def generate_confirm_token(self, expires_in=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in=expires_in)
        data = s.dumps({'confirm_id': self.id})
        return data

    def verify_confirm_token(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except BaseException, e:
            return False
        if data.get('confirm_id') != self.id:
            return False
        self.is_confirmed = True
        db.session.add(self)
        db.session.commit()
        return True

说明:如上创建了一个Permission权限类,类权限属性用8位二进制表示权限,在Role类中增加2个字段,permission和default,分别标识角色权限和是否为默认角色,由于二进制方便与计算,所以很容易计算角色权限,insert_roles()并不直接创建新角色对象,而是通过角色名查找现有角色,如果有则更新,否则才会创建

注意:匿名角色不需要在数据库中体现,这个角色的作用是为了表示不在数据库中的用户

FlaskWeb/manager.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
from app import db as _db
from app import create_app
from config import config
from app.models import Role
from flask_script import Manager

app = create_app()
manager = Manager(app)

@manager.command
def db(command):
    if command == 'init':
        _db.create_all()
        Role.insert_roles()
    if command == 'drop':
        _db.drop_all()

if __name__ == '__main__':
    manager.run()

说明:由于更改了数据模型,需要先python manager.py db drop然后python manager.py db init,如上将Role对象引用进来在外部调用init时,将会将我们生成的角色写进数据库,后期增加角色也非常方便

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!