首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >烧瓶-管理is_accessible的使用

烧瓶-管理is_accessible的使用
EN

Stack Overflow用户
提问于 2015-11-11 07:46:44
回答 2查看 4.2K关注 0票数 4

我已经检查了文档,如何实现is_accessible方法非常模糊。

下面是酒瓶管理员的文档。

代码语言:javascript
复制
class MicroBlogModelView(sqla.ModelView):

    def is_accessible(self):
        return login.current_user.is_authenticated()

    def inaccessible_callback(self, name, **kwargs):
        # redirect to login page if user doesn't have access
        return redirect(url_for('login', next=request.url))

但我不明白的是,你是怎么称呼它的,它是自动调用的,还是你必须自己这样称呼它:

代码语言:javascript
复制
@expose("/", methods=["GET", "POST"])
    def home(self):
        if self.is_accesible():
            return super().index()
        else:
            return self.login()

    def is_accesible(self):
        return current_user.is_authenticated and "admin" in current_user.role

因为把一个

代码语言:javascript
复制
if self.is_accesible():
                return super().index()

检查一下我们是否有很多的管理视图。那么,我们究竟如何实现它呢?文档展示了如何将其放在您的模型中,而不是如何在视图上实现它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-11 15:21:15

参见下面的示例代码-大部分代码都是从国卡CMS逐字提取的。

定义一个处理Roleddef _handle_view(self, name, *args, **kwargs)的混合程序。

在这个示例中,我使用了一个函数def is_accessible(roles_accepted=None, user=None)来处理确定角色是否可以接受的逻辑。

从sqla ModelViewRoled混联定义一个视图类,即:

代码语言:javascript
复制
class AdminView(Roled, ModelView):

    def __init__(self, *args, **kwargs):
        self.roles_accepted = kwargs.pop('roles_accepted', list())
        super(AdminView, self).__init__(*args, **kwargs)

从该类派生视图模型:

代码语言:javascript
复制
class UserView(AdminView):
    form_excluded_columns = ('password')   

class RoleView(AdminView):
    pass

class PostView(AdminView):
    pass

以正常方式将视图添加到管理类,但通过roles_accepted关键字传递允许的角色名称列表:

代码语言:javascript
复制
admin.add_view(UserView(model=User, session=db.session, category='Account', name='Users', roles_accepted=['admin']))
admin.add_view(RoleView(model=Role, session=db.session, category='Account', name='Roles', roles_accepted=['admin']))
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Editor Only)', roles_accepted=['editor']))
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Admins & Editors)', endpoint="post_special", roles_accepted=['editor', 'admin']))

请参阅下面完整的单个文件代码。这在Python2.7.9、烧瓶0.10.1、烧瓶-admin 1.1.0、烧瓶-安全1.7.4和烧瓶-登录0.2.11下进行了测试。

代码语言:javascript
复制
from datetime import datetime
from flask import Flask, redirect, current_app
from flask.ext.admin import Admin
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin.menu import MenuLink
from flask.ext.security import (
    current_user,
    url_for_security,
    UserMixin,
    RoleMixin,
    SQLAlchemyUserDatastore,
    Security
)
from flask.ext.security.utils import encrypt_password
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SECURITY_PASSWORD_HASH'] = 'pbkdf2_sha512'
app.config['SECURITY_PASSWORD_SALT'] = '16a0af319890f662055ba10aecff37e7e033db3fba737e55'
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = 'email'

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


class Role(db.Model, RoleMixin):
    __tablename__ = 'roles'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(length=64), unique=True)
    description = db.Column(db.Unicode(length=255), nullable=True)

    def __unicode__(self):
        return u"{name} ({role})".format(name=self.name, role=self.description or 'Role')

user_to_role = db.Table('user_to_role',
    db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
    db.Column('role_id', db.Integer(), db.ForeignKey('roles.id')))


class User(db.Model, UserMixin):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)

    first_name = db.Column(db.Unicode(length=255), nullable=False)
    last_name = db.Column(db.Unicode(length=255), nullable=False)

    email = db.Column(db.Unicode(length=254), unique=True, nullable=True)
    password = db.Column(db.Unicode(length=255), nullable=False)
    active = db.Column(db.Boolean(), default=False)

    roles = db.relationship('Role', secondary=user_to_role, backref=db.backref('users', lazy='select'))

    def __unicode__(self):
        return u"{first_name} ({last_name})".format(first_name=self.first_name, last_name=self.last_name)


class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255))
    content = db.Column(db.Text, nullable=False)

    def __unicode__(self):
        return self.title


def get_current_user():
    from flask.ext.security import current_user
    try:
        return User.objects.get(id=current_user.id)
    except Exception as e:
        # logger.warning("No user found: %s", str(e))
        return current_user


def is_accessible(roles_accepted=None, user=None):
    user = user or get_current_user()
    # uncomment if "admin" has access to everything
    # if user.has_role('admin'):
    #     return True
    if roles_accepted:
        accessible = any(
            [user.has_role(role) for role in roles_accepted]
        )
        return accessible
    return True


class Roled(object):

    def is_accessible(self):
        roles_accepted = getattr(self, 'roles_accepted', None)
        return is_accessible(roles_accepted=roles_accepted, user=current_user)

    def _handle_view(self, name, *args, **kwargs):
        if not current_user.is_authenticated():
            return redirect(url_for_security('login', next="/admin"))
        if not self.is_accessible():
            # return self.render("admin/denied.html")
            return "<p>Access denied</p>"

class AdminView(Roled, ModelView):

    def __init__(self, *args, **kwargs):
        self.roles_accepted = kwargs.pop('roles_accepted', list())
        super(AdminView, self).__init__(*args, **kwargs)


class UserView(AdminView):
    form_excluded_columns = ('password')


class RoleView(AdminView):
    pass


class PostView(AdminView):
    pass


# Setup Flask-Security
security = Security(app, SQLAlchemyUserDatastore(db, User, Role))

@app.route('/')
def index():
    _login = url_for_security('login', next="/admin")
    _logout = url_for_security('logout', next="/admin")
    return '''
        <a href="/admin/">Click me to get to Admin!</a><br>
        <a href="{login}">Click me to get to login!</a><br>
        <a href="{logout}">Click me to get to logout!</a>
        '''.format(login=_login, logout=_logout)


# Create admin
admin = Admin(app, name='Admin')
admin.add_view(UserView(model=User, session=db.session, category='Account', name='Users', roles_accepted=['admin']))
admin.add_view(RoleView(model=Role, session=db.session, category='Account', name='Roles', roles_accepted=['admin']))
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Editor Only)', roles_accepted=['editor']))
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Admins & Editors)', endpoint="post_special", roles_accepted=['editor', 'admin']))
admin.add_link(MenuLink(name='Public Website', category='', url='/'))


def build_db():
    users = [
        {
            'first_name': 'Super',
            'last_name': 'User',
            'email': 'admin@example.com',
            'active': True,
            'password' : encrypt_password('password'),
            'roles': ['admin']
        },
        {
            'first_name': u'Post',
            'last_name': u'Editor',
            'email': 'editor@example.com',
            'active': True,
            'password': encrypt_password('password'),
            'roles': ['editor']
        },

    ]

    posts = [
        {
            'title': "de Finibus Bonorum et Malorum - Part I",
            'content': "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut"
        },
        {
            'title': "de Finibus Bonorum et Malorum - Part II",
            'content': "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque"
        },
        {
            'title': "de Finibus Bonorum et Malorum - Part III",
            'content': "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium"
        }
    ]

    db.drop_all()
    db.create_all()

    security = current_app.extensions.get('security')

    security.datastore.create_role(name=u"admin", description=u'Administers the system')
    security.datastore.create_role(name=u"editor", description=u'Can edit posts')

    for user in users:
        roles = user.pop('roles')
        user_db = security.datastore.create_user(**user)
        for role_name in roles:
            role_from_db = security.datastore.find_role(role_name)
            security.datastore.add_role_to_user(user_db, role_from_db)
        security.datastore.activate_user(user_db)
        user_db.confirmed_at = datetime.now()

    security.datastore.commit()

    for row in posts:
        post = Post(**row)
        db.session.add(post)

    db.session.commit()


@app.before_first_request
def create_user():
    build_db()

if __name__ == '__main__':
    app.run(debug=True)
票数 7
EN

Stack Overflow用户

发布于 2016-08-23 18:07:17

每次访问视图时都会自动调用它。您可以通过使用print语句来检查这一点。运行您的应用程序并查看控制台窗口。

代码语言:javascript
复制
class MicroBlogModelView(sqla.ModelView):

def is_accessible(self):
    print "Called ME!!!!!!!!"
    return login.current_user.is_authenticated()

def inaccessible_callback(self, name, **kwargs):
    # redirect to login page if user doesn't have access
    return redirect(url_for('login', next=request.url))
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33646165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档