我正在尝试在 Rails 中实现基于角色的授权。
我们需要什么:
调查结果:
pundit
gem 因为它的策略是静态的,我们不能让它动态。 cancan
gem,我们可以动态使用它,但我不知道如何完成?以及它如何与`数据库一起工作? 这是我在授权部分的第一个项目。我们有 Rails 作为后端,vue.js 作为前端。无论有什么角色,数据库上的所有数据一开始都应该是空的。我们将使用种子创建 super 管理员角色并授予所有权限。 super 管理员会创建角色、编辑角色、销毁角色,最终还会添加权限、编辑和销毁权限。
如果有任何其他有用的方法,请告诉我。
谢谢。
最佳答案
Pundit 与 CanCanCan
您关于 CanCanCan 和 Pundit 的结论纯属无稽之谈。它们都不是“静态”或“动态”,它们具有几乎相同的功能。不过,架构和设计理念完全不同。
CanCanCan(最初是 CanCan)被写成 DSL,这是自 10 年前 Ryan Bates 创建 CanCan 时预切面包以来 HitTest 门的东西。它可以很好地按比例缩小并且易于学习,但是一旦您达到任何复杂程度,它就会变得非常丑陋。如果在 CanCanCan 中进行“动态授权”的任何事情由于其架构而将是一场噩梦。 CanCanCan中的能力类是所有神对象的神。
Pundit 只是面向对象编程。在权威人士中,您的策略只是将用户和资源作为初始化参数并响应像 show?
这样的方法的类。 , create?
等等。 Pundit 最初更难理解,但由于它只是面向对象编程,您可以根据需要对其进行定制。由于您的身份验证逻辑存储在单独的对象中,因此可以更好地扩展复杂性并遵守 SOLID 原则。
如何设置动态角色系统?
这是你的标准角色系统 ala Rolify:
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles
def has_role?(role, resource = nil)
roles.where({ name: role, resource: resource }.compact).exists?
end
def add_role(role, resource = nil)
role = Role.find_or_create_by!({ name: role, resource: resource }.compact)
roles << role
end
end
# rails g model user_roles user:belongs_to role:belongs_to
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
# rails g model role name:string resource:belongs_to:polymorphic
class Role < ApplicationRecord
belongs_to :resource, polymorphic: true, optional: true
has_many :user_roles
has_many :users, through: :user_roles
end
然后,您可以将角色范围限定为资源:
class Forum < ApplicationRecord
has_many :roles, as: :resource
end
Rolify 可以让您更进一步,只需将角色定义为一个类作为资源。例如
user.add_role(:admin, Forum)
这使用户成为所有论坛的管理员。如何创建权限系统?
一个简单的RBAC系统可以构建为:
class Role < ApplicationRecord
has_many :role_permissions
has_many :permissions, through: :role_permissions
def has_permission?(permission)
permissions.where(name: permission).exists?
end
end
# rails g model permission name:string
class Permission < ApplicationRecord
end
# rails g model role_permission role:belongs_to permission:belongs_to
class RolePermission < ApplicationRecord
belongs_to :role
belongs_to :permission
end
例如,您可以在
Forum.find(1)
上向“版主”授予“销毁”权限经过:role = Role.find_by!(name: 'moderator', resource: Forum.find(1))
role.permissions.create!(name: 'destroy')
role.has_permission?('destroy') # true
虽然我怀疑它在现实中真的会如此简单。
关于ruby-on-rails - rails : Is there any way to build dynamic role based authorization in rails?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60108114/