【问题标题】:Flask-Admin permissions for adding user with specific role用于添加具有特定角色的用户的 Flask-Admin 权限
【发布时间】:2019-01-26 12:54:05
【问题描述】:

我使用 Flask-Admin 和 Flask-Security 为我的 Python 应用程序实现管理面板。以下是UserRole 的模型:

class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))

    def __str__(self):
        return self.name


class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(255), unique=True, index=True)
    password = db.Column(db.String(255))
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

    def __str__(self):
        return self.username

我为用户创建了一个sqla.ModelView,仅适用于具有“admin”和“superadmin”角色的用户,因此此类用户可以使用此视图创建新用户。如何让只有角色“superadmin”的用户才能创建角色“superadmin”和“admin”的用户?换句话说,我想指定哪些变体可供具有不同角色的用户使用:https://imgur.com/a/GdhUS2Y

【问题讨论】:

    标签: python flask flask-sqlalchemy roles flask-admin


    【解决方案1】:

    为此,您必须自定义一些内容。

    我建议如下:

    在你的用户模型中添加这个方法来检查用户是否具有特定的角色:

    def has_role(self, role):
        # db is your database session. 
        query = db.query(Role).filter(Role.name == role).first()
        if query:
            if query.name in self.roles:
                return True
        return False
    

    现在您必须自定义在用户尝试创建新用户时显示的角色。为此,您需要更改角色字段的定义。为此,您需要重写 flask-admin scaffold_form() 方法。

    from flask_admin.contrib.sqla.fields import QuerySelectMultipleField
    from flask_security import current_user
    from flask_admin.form import Select2Widget
    def scaffold_form(self):
        form_class = super(YourUserAdminClass, self).scaffold_form()
        role_filter = Role.name == Role.name if current_user.has_role('superadmin') else Role.name.notin_('superadmin', 'admin')
        form_class.roles = QuerySelectMultipleField(
                query_factory=lambda: self.session.query(Role).filter(role_filter),
                allow_blank,
                blank_text='Select Role',
                widget=Select2Widget(multiple=False) # change this to True if you allow multiple roles
            )
    

    上面的代码将根据 current_user 拥有的角色呈现带有角色的下拉列表(使用过滤器中的has_role() 方法

    【讨论】:

      【解决方案2】:

      虽然@shifloni 的回答提供了一个关于需要做什么的简明想法,但根据我的观察,我认为它是不完整的。这是因为 if current_user.has_role('superadmin') 在应用程序初始化期间抛出错误,因为 current_user 仅在代码在请求上下文中执行时可用。这对我有用:

      class ViewForCreatingAdminAndOperators(sqla.ModelView):
          def _run_view(self, fn, *args, **kwargs):
              if current_user.has_role('admin'):
                  self.role_filter = Role.name.in_(['operator'])
              else:
                  self.role_filter = Role.name.in_(['superadmin', 'admin', 'operator'])
      
              return fn(self, *args, **kwargs)
      
          def scaffold_form(self):
              form = super(ViewForCreatingAdminUsers, self).scaffold_form()
              form.roles = QuerySelectMultipleField(
                  query_factory=lambda: self.session.query(Role).filter(self.role_filter),
                  widget=Select2Widget(multiple=False)  # change this to True if you allow multiple roles
              )
              return form
      

      _run_view func 总是在 request 上下文中调用,所以每当我们点击创建表单时,都会调用该 func 并且我们有可用的 role_filter。

      附:根据上述代码的用例是admin 应该只能创建operator

      【讨论】:

        猜你喜欢
        • 2020-05-14
        • 2015-10-18
        • 2017-11-21
        • 1970-01-01
        • 2014-05-16
        • 2011-09-09
        • 2013-08-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多