From 56f19e122da0c1d46bdacfef283c537693903763 Mon Sep 17 00:00:00 2001 From: Sergey Moiseev Date: Thu, 28 Nov 2024 18:37:38 +0200 Subject: [PATCH] Implement proper STI support in Rolify --- .../adapters/active_record/role_adapter.rb | 18 +++++++++++------- lib/rolify/adapters/mongoid/role_adapter.rb | 4 ++++ lib/rolify/dynamic.rb | 2 +- lib/rolify/resource.rb | 8 ++++---- lib/rolify/role.rb | 2 +- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/rolify/adapters/active_record/role_adapter.rb b/lib/rolify/adapters/active_record/role_adapter.rb index a1f01fb3..3371716e 100644 --- a/lib/rolify/adapters/active_record/role_adapter.rb +++ b/lib/rolify/adapters/active_record/role_adapter.rb @@ -12,9 +12,9 @@ def where_strict(relation, args) wrap_conditions = relation.name != role_class.name conditions = if args[:resource].is_a?(Class) - {:resource_type => args[:resource].to_s, :resource_id => nil } + {:resource_type => resource_base_class(args[:resource]), :resource_id => nil } elsif args[:resource].present? - {:resource_type => args[:resource].class.name, :resource_id => args[:resource].id} + {:resource_type => resource_base_class(args[:resource]), :resource_id => args[:resource].id} else {} end @@ -27,7 +27,7 @@ def where_strict(relation, args) def find_cached(relation, args) resource_id = (args[:resource].nil? || args[:resource].is_a?(Class) || args[:resource] == :any) ? nil : args[:resource].id - resource_type = args[:resource].is_a?(Class) ? args[:resource].to_s : args[:resource].class.name + resource_type = resource_base_class(args[:resource]) return relation.find_all { |role| role.name == args[:name].to_s } if args[:resource] == :any @@ -40,7 +40,7 @@ def find_cached(relation, args) def find_cached_strict(relation, args) resource_id = (args[:resource].nil? || args[:resource].is_a?(Class)) ? nil : args[:resource].id - resource_type = args[:resource].is_a?(Class) ? args[:resource].to_s : args[:resource].class.name + resource_type = resource_base_class(args[:resource]) relation.find_all do |role| role.resource_id == resource_id && role.resource_type == resource_type && role.name == args[:name].to_s @@ -57,7 +57,7 @@ def add(relation, role) def remove(relation, role_name, resource = nil) cond = { :name => role_name } - cond[:resource_type] = (resource.is_a?(Class) ? resource.to_s : resource.class.name) if resource + cond[:resource_type] = resource_base_class(resource) if resource cond[:resource_id] = resource.id if resource && !resource.is_a?(Class) roles = relation.roles.where(cond) if roles @@ -83,6 +83,10 @@ def all_except(user, excluded_obj) user.where.not(user.primary_key => excluded_obj) end + def resource_base_class(resource) + (resource.is_a?(Class) ? resource : resource.class).polymorphic_name + end + private def build_conditions(relation, args) @@ -110,10 +114,10 @@ def build_query(role, resource = nil) if resource query.insert(0, "(") query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id IS NULL))" - values << role << (resource.is_a?(Class) ? resource.to_s : resource.class.name) + values << role << resource_base_class(resource) if !resource.is_a? Class query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id = ?))" - values << role << resource.class.name << resource.id + values << role << resource_base_class(resource) << resource.id end query += ")" end diff --git a/lib/rolify/adapters/mongoid/role_adapter.rb b/lib/rolify/adapters/mongoid/role_adapter.rb index a3fb0486..15a1255d 100644 --- a/lib/rolify/adapters/mongoid/role_adapter.rb +++ b/lib/rolify/adapters/mongoid/role_adapter.rb @@ -102,6 +102,10 @@ def all_except(user, excluded_obj) user.not_in(_id: excluded_obj.to_a) end + def resource_base_class(resource) + resource.is_a?(Class) ? resource.to_s : resource.class.name + end + private def build_conditions(relation, args) diff --git a/lib/rolify/dynamic.rb b/lib/rolify/dynamic.rb index 686c7a41..1c811510 100644 --- a/lib/rolify/dynamic.rb +++ b/lib/rolify/dynamic.rb @@ -3,7 +3,7 @@ module Rolify module Dynamic def define_dynamic_method(role_name, resource) - class_eval do + class_eval do define_method("is_#{role_name}?".to_sym) do has_role?("#{role_name}") end if !method_defined?("is_#{role_name}?".to_sym) && self.adapter.where_strict(self.role_class, name: role_name).exists? diff --git a/lib/rolify/resource.rb b/lib/rolify/resource.rb index 45159ec8..778cc207 100644 --- a/lib/rolify/resource.rb +++ b/lib/rolify/resource.rb @@ -20,7 +20,7 @@ def with_role(role_name, user = nil) user ? self.resource_adapter.in(resources, user, role_name) : resources end alias :with_roles :with_role - alias :find_as :with_role + alias :find_as :with_role alias :find_multiple_as :with_role @@ -28,8 +28,8 @@ def without_role(role_name, user = nil) self.resource_adapter.all_except(self, self.find_as(role_name, user)) end alias :without_roles :without_role - alias :except_as :without_role - alias :except_multiple_as :without_role + alias :except_as :without_role + alias :except_multiple_as :without_role @@ -38,7 +38,7 @@ def applied_roles(children = true) end - + end def applied_roles diff --git a/lib/rolify/role.rb b/lib/rolify/role.rb index 34f6f13a..6ced8ce8 100644 --- a/lib/rolify/role.rb +++ b/lib/rolify/role.rb @@ -11,7 +11,7 @@ def self.included(base) def add_role(role_name, resource = nil) role = self.class.adapter.find_or_create_by(role_name.to_s, - (resource.is_a?(Class) ? resource.to_s : resource.class.name if resource), + (self.class.adapter.resource_base_class(resource) if resource), (resource.id if resource && !resource.is_a?(Class))) if !roles.include?(role)