Pundit против CanCanCan
Ваши выводы о CanCanCan и Pundit просто бессмыслица. Ни один из них не является "stati c" или "Dynami c", и они имеют почти одинаковые функции. Архитектура и философия дизайна радикально отличаются.
CanCanCan (первоначально CanCan) написан как DSL, что было самой горячей вещью со времен нарезанного хлеба назад, когда Райан Бейтс создал CanCan 10 лет go. Он очень хорошо масштабируется и его легко освоить, но он становится очень уродливым, как только вы достигнете любого уровня сложности. Если что-либо, выполняющее «авторизацию Dynami c» в CanCanCan, станет кошмаром из-за его архитектуры. Класс способностей в CanCanCan - это бог всех объектов бога.
Pundit - это просто объектно-ориентированное программирование. В pundit ваши политики - это просто классы, которые принимают пользователя и ресурс в качестве аргументов инициализатора и отвечают на методы, такие как show?
, create?
et c. Изначально Pundit сложнее понять, но, поскольку он всего лишь OOP, вы можете адаптировать его так, как хотите. А поскольку ваши логины аутентификации c хранятся в отдельных объектах, они гораздо лучше масштабируются до сложности и придерживаются принципов SOLID.
Как настроить систему ролей Dynami c?
Это стандартная система ролей аля 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 позволяет вам go сделать шаг вперед и просто определить роли с классом в качестве ресурса. Например, user.add_role(:admin, Forum)
, который делает пользователя администратором на всех форумах.
Как мне создать систему разрешений?
Простая RBA C система может быть построенным как:
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
Хотя я сомневаюсь, что это действительно так просто в реальности.