Flask-项目实操9

CMS后台权限验证
添加用户角色
封装权限判断功能
客户端权限验证
服务端权限验证

cms/models.py

# @ Time : 2020/5/18 
# @ Author : Ellen

from exts import db
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash


class CMSPermission(object):
    # 255 二进制来表示所有的权限
    ALL_PERMISSION = 0b11111111

    # 访问权限
    VISITOR        = 0b00000001

    # 管理帖子权限
    POSTER         = 0b00000010

    # 管理评论
    COMMENTER      = 0b00000100

    # 管理板块
    BOARDER        = 0b00001000

    # 管理前台用户
    FORNTUSER       = 0b00010000

    # 管理后台用户板块
    CMSUSER         = 0b00100000

    # 管理管理员用户
    ADMINER         = 0b01000000

# role与user的中间表
cms_role_user = db.Table(
    'cms_role_user',
    db.Column('cms_role_id', db.Integer, db.ForeignKey('cms_role.id'), primary_key=True),
    db.Column('cms_user_id', db.Integer, db.ForeignKey('cms_user.id'), primary_key=True),
)


# 角色
class CMSRole(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), nullable=False)
    desc = db.Column(db.String(220), nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.now)
    permissions = db.Column(db.Integer, default=CMSPermission.VISITOR)

    users = db.relationship('CMSUser', secondary=cms_role_user, backref='roles')


class CMSUser(db.Model):
    __tablename__ = "cms_user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(50), nullable=False)
    _password = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(50), nullable=False, unique=True)
    join_time = db.Column(db.DateTime, default=datetime.now)

    def __init__(self, username, password, email):
        self.username = username
        self.password = password
        self.email = email

    @property
    def password(self):
        return self._password

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

    def check_password(self, raw_password):
        result = check_password_hash(self.password, raw_password)
        return result

    # 封装权限判断功能,判断当前用户有没有这个权限

    @property
    def permissions(self):
        if not self.roles:
            return 0

        all_permissions = 0
        for role in self.roles:
            permissions = role.permissions
            # 获取角色的所有权限
            all_permissions |= permissions
        return all_permissions

    def has_permission(self, permission):
        all_permissions = self.permissions
        # 0b11111111   用户的权限 0b00001000
        result = all_permissions & permission == permission
        return result

    @property
    def is_developer(self):
        return self.has_permission(CMSPermission.ALL_PERMISSION)


manage.py

# @ Time : 2020/5/18
# @ Author : Ellen

from flask_script import Manager
from bbs import app
from flask_migrate import Migrate, MigrateCommand
from exts import db
# 导入模型
from apps.cms.models import CMSUser, CMSRole, CMSPermission

manager = Manager(app)


Migrate(app, db)
manager.add_command('db', MigrateCommand)

@manager.option('-u', '--username', dest='username')
@manager.option('-p', '--password', dest='password')
@manager.option('-e', '--email', dest='email')
def create_cms_user(username, password, email):
    user = CMSUser(username=username, password=password, email=email)
    db.session.add(user)
    db.session.commit()
    print("cms用户添加成功")


@manager.command
def create_role():
    # 访问者
    visitor = CMSRole(name='访问者', desc='只能查看数据,不能修改数据')
    visitor.permissions = CMSPermission.VISITOR

    # 运营人员
    operator = CMSRole(name='运营', desc='管理帖子,管理评论,管理前台用户')
    operator.permissions = CMSPermission.VISITOR | CMSPermission.POSTER | CMSPermission.CMSUSER | CMSPermission.COMMENTER | CMSPermission.FORNTUSER

    # 管理员
    admin = CMSRole(name='管理员', desc='拥有本系统大部分权限')
    admin.permissions = CMSPermission.VISITOR | CMSPermission.POSTER | CMSPermission.CMSUSER | CMSPermission.COMMENTER | CMSPermission.FORNTUSER | CMSPermission.BOARDER

    # 开发人员
    developer = CMSRole(name='开发者', desc='拥有所有的权限')
    developer.permissions = CMSPermission.ALL_PERMISSION

    db.session.add_all([visitor, operator, admin, developer])
    db.session.commit()

@manager.command
def test_permission():
    user = CMSUser.query.get(2)
    print(user)
    if user.has_permission(CMSPermission.VISITOR):
        print('这个用户有访问者的权限')
    else:
        print('这个用户没有访问者的权限')

# 用户添加到角色里面
@manager.option('-e', '--email', dest='email')
@manager.option('-n', '--name', dest='name')
def add_user_to_role(email, name):
    user = CMSUser.query.filter_by(email=email).first()
    if user:
        role = CMSRole.query.filter_by(name=name).first()
        if role:
            role.users.append(user)
            db.session.commit()
            print('用户添加到角色成功')
        else:
            print('角色不存在')
    else:
        print('邮箱不存在')



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

decorators.py

# 装饰器验证是否登录
from flask import session, redirect, url_for, g
from functools import wraps

def login_required(func):
    def inner(*args, **kwargs):
        if "user_id" in session:
            return func(*args, **kwargs)
        else:
            return redirect(url_for('cms.login'))
    return inner

# 装饰器传参数
def permission_required(permission):
    def outter(func):
        @wraps(func)
        def inner(*args, **kwargs):
            user = g.cms_user
            if user.has_permission(permission):
                return func(*args, **kwargs)
            else:
                return redirect(url_for('cms.index'))
        return inner
    return outter

hooks.py

@cms_bp.context_processor
def cms_context_processor():
    return {'CMSPermission': CMSPermission}

views.py

# @ Time : 2020/5/18 
# @ Author : Ellen

from flask import (
    Blueprint,
    render_template,
    views,
    request,
    redirect,
    url_for,
    session,
    jsonify,
    g
)

from apps.cms.forms import LoginForm, ResetPwdForm, ResetEmailForm
from apps.cms.models import CMSUser, CMSPermission
from exts import db, mail
from utils import restful, random_captcha, lgcache
from flask_mail import Message

from .decorators import login_required, permission_required

cms_bp = Blueprint("cms", __name__, url_prefix='/cms')
from .hooks import before_request

@cms_bp.route("/")
# @login_required
def index():
    # print(session.get('user_id'))
    # return "cms index"
    return render_template("cms/cms_index.html")

@cms_bp.route('/logout/')
def logout():
    # 删除 session  user_id
    # 重定向 登录页面
    del session['user_id']
    return redirect(url_for('cms.login'))
    


# @cms_bp.route("/text/")
# def demo():
#     return "测试是否可以访问"
    
@cms_bp.route("/profile/")
def profile():
    return render_template("cms/cms_profile.html")


class LoginView(views.MethodView):
    def get(self, message=None):
        return render_template('cms/cms_login.html', message=message)

    def post(self):
        login_form = LoginForm(request.form)
        if login_form.validate():
            # 数据库验证 接收表单发送的方式
            email = login_form.email.data
            password = login_form.password.data
            remember = login_form.remember.data
            user = CMSUser.query.filter_by(email=email).first()
            # 验证用户是否存在 密码是否正确
            if user and user.check_password(password):
                session['user_id'] = user.id
                if remember:
                    session.permanent = True
            # 登录成功 跳转首页
                return redirect(url_for('cms.index'))
            else:
                return self.get(message="邮箱或者密码错误")

        else:
            # print(login_form.errors.popitem()[1][0])
            # return "表单验证错误"
            # message = login_form.errors.popitem()[1][0]
            return self.get(message=login_form.get_error())

class ResetPwdView(views.MethodView):
    def get(self):
        return render_template('cms/cms_resetpwd.html')

    def post(self):
        form = ResetPwdForm(request.form)
        if form.validate():
            oldpwd = form.oldpwd.data
            newpwd = form.newpwd.data
            # 当前用户的对象
            user = g.cms_user
            # 用户提交的数据 ellen 秘密 是否和数据库中一致
            if user.check_password(oldpwd):
                # 更新我的密码
                user.password = newpwd
                db.session.commit()
                # return jsonify({"code": 200, "message": ""})
                return restful.success()

            else:
                # return jsonify({"code": 400, "message": "旧密码错误"})
                return restful.params_errors(message="旧密码错误")
        else:
            # ajax  要返回json类型的数据
            # message = form.errors.popitem()[1][0]
            # return jsonify({"code": 400, "message": message})
            return restful.params_errors(message=form.get_error())

class ResetEmailView(views.MethodView):

    def get(self):
        return render_template('cms/cms_resetemail.html')

    def post(self):
        form = ResetEmailForm(request.form)
        if form.validate():
            email = form.email.data
            # 查询数据库
            # CMSUser.query.filter_by(email=email).first()
            # CMSUser.query.filter(CMSUser.email == email).first()

            g.cms_user.email = email
            db.session.commit()
            return restful.success()

        else:
            return restful.params_errors(form.get_error())

# 发送邮件
@cms_bp.route("/send_mail/")
def send_mail():
    message = Message('邮件发送', recipients=['80058851@qq.com'], body='测试邮件发送')
    mail.send(message)
    return '邮件已发送'

# 邮件发送
class EmailCaptcha(views.MethodView):
    def get(self):
        email = request.args.get('email')
        if not email:
            return restful.params_errors('请传递邮箱参数')

        # 发送邮件  内容发送一个验证码 4 位或6位 数字和英文组合
        captcha = random_captcha.get_random_captcha(4)
        message = Message('论坛邮箱验证码', recipients=[email], body='您的验证码是 %s' % captcha)
        try:
            mail.send(message)
        except:
            return restful.server_errors()

        # 验证码保存 mysql  过期时间 Redis  效率 key email value 验证码
        lgcache.redis_set(email, captcha)
        return restful.success()


@cms_bp.route("/posts/")
@permission_required(CMSPermission.POSTER)
def posts():
    return render_template("cms/cms_posts.html")

@cms_bp.route("/comments/")
@permission_required(CMSPermission.COMMENTER)
def comments():
    return render_template("cms/cms_comments.html")

@cms_bp.route("/boards/")
@permission_required(CMSPermission.BOARDER)
def boards():
    return render_template("cms/cms_boards.html")

@cms_bp.route("/fusers/")
@permission_required(CMSPermission.FORNTUSER)
def fusers():
    return render_template("cms/cms_fusers.html")

@cms_bp.route("/cusers/")
@permission_required(CMSPermission.CMSUSER)
def cusers():
    return render_template("cms/cms_cusers.html")

@cms_bp.route("/croles/")
@permission_required(CMSPermission.ADMINER)
def croles():
    return render_template("cms/cms_croles.html")


cms_bp.add_url_rule("/login/", view_func=LoginView.as_view('login'))
cms_bp.add_url_rule("/resetpwd/", view_func=ResetPwdView.as_view('resetpwd'))
cms_bp.add_url_rule("/resetemail/", view_func=ResetEmailView.as_view('resetemail'))
cms_bp.add_url_rule("/email_captcha/", view_func=EmailCaptcha.as_view('email_captcha'))

cms_profile.html

{% extends 'cms/cms_base.html' %}

{% block title %}
    个人信息
{% endblock %}

{% block page_title %}
    {{ self.title() }}
{% endblock %}

{% block content %}
    {% set user = g.cms_user %}
    <table class="table table-bordered">
            <tr>
                <td>用户名:</td>
                <td>{{ user.username }}</td>
            </tr>
            <tr>
                <td>邮箱:</td>
                <td>{{ user.email }}</td>
            </tr>
            <tr>
                <td>角色:</td>
                <td>{% for role in user.roles %}
                    {{ role.name}}
                    {% if not loop.last %}
                    ,
                    {% endif %}
                {% endfor %}</td>
            </tr>
            <tr>
                <td>权限:</td>
                <td>{% for role in user.roles %}
                    {{ role.desc }}
                    {% if not loop.last %}
                    ,
                    {% endif %}
                {% endfor %}</td>
            </tr>
            <tr>
                <td>加入时间:</td>
                <td>{{ user.join_time }}</td>
            </tr>
    </table>
{% endblock %}

cms_base.html

 {% set user = g.cms_user %}
                  {% if user.has_permission(CMSPermission.POSTER) %}
                     <li class="nav-group post-manage"><a href="#">帖子管理</a></li>
                  {% endif %}

                {% if user.has_permission(CMSPermission.COMMENTER) %}
                    <li class="comments-manage"><a href="#">评论管理</a></li>
                {% endif %}

                {% if user.has_permission(CMSPermission.BOARDER) %}
                    <li class="board-manage"><a href="#">板块管理</a></li>
                {% endif %}

                {% if user.has_permission(CMSPermission.FORNTUSER) %}
                  <li class="FORNTUSER user-manage"><a href="#">前台用户管理</a></li>
                {% endif %}


                {% if user.has_permission(CMSPermission.CMSUSER) %}
                  <li class="CMSUSER-manage"><a href="#">后台用户管理</a></li>
                {% endif %}

cms_boards.html
cms_comments.html…croles , fusers, posts,cusers

{% extends 'cms/cms_base.html' %}

{% block title %}
    板块管理
{% endblock %}

{% block page_title %}
    {{ self.title() }}
{% endblock %}

{% block content %}
    板块管理
{% endblock %}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值