lib/acl9/model_extensions/subject.rb in be9-acl9-0.10.0 vs lib/acl9/model_extensions/subject.rb in be9-acl9-0.11.0
- old
+ new
@@ -1,59 +1,127 @@
module Acl9
module ModelExtensions
module Subject
+ ##
+ # Role check.
+ #
+ # There is a global option, +Acl9.config[:protect_global_roles]+, which governs
+ # this method behavior.
+ #
+ # If protect_global_roles is +false+, an object role is automatically counted
+ # as global role. E.g.
+ #
+ # Acl9.config[:protect_global_roles] = false
+ # user.has_role!(:manager, @foo)
+ # user.has_role?(:manager, @foo) # => true
+ # user.has_role?(:manager) # => true
+ #
+ # In this case manager is anyone who "manages" at least one object.
+ #
+ # However, if protect_global_roles option set to +true+, you'll need to
+ # explicitly grant global role with same name.
+ #
+ # Acl9.config[:protect_global_roles] = true
+ # user.has_role!(:manager, @foo)
+ # user.has_role?(:manager) # => false
+ # user.has_role!(:manager)
+ # user.has_role?(:manager) # => true
+ #
+ # protect_global_roles option is +false+ by default as for now, but this
+ # may change in future!
+ #
+ # @return [Boolean] Whether +self+ has a role +role_name+ on +object+.
+ # @param [Symbol,String] role_name Role name
+ # @param [Object] object Object to query a role on
+ #
+ # @see Acl9::ModelExtensions::Object#accepts_role?
def has_role?(role_name, object = nil)
- !! if object.nil?
- self.roles.find_by_name(role_name.to_s) ||
- self.roles.member?(get_role(role_name, nil))
+ !! if object.nil? && !::Acl9.config[:protect_global_roles]
+ self.role_objects.find_by_name(role_name.to_s) ||
+ self.role_objects.member?(get_role(role_name, nil))
else
role = get_role(role_name, object)
- role && self.roles.exists?(role.id)
+ role && self.role_objects.exists?(role.id)
end
end
+ ##
+ # Add specified role on +object+ to +self+.
+ #
+ # @param [Symbol,String] role_name Role name
+ # @param [Object] object Object to add a role for
+ # @see Acl9::ModelExtensions::Object#accepts_role!
def has_role!(role_name, object = nil)
role = get_role(role_name, object)
if role.nil?
role_attrs = case object
when Class then { :authorizable_type => object.to_s }
when nil then {}
else { :authorizable => object }
end.merge( { :name => role_name.to_s })
- role = self._auth_role_class.create(role_attrs)
+ role = self._auth_role_class.create(role_attrs)
end
- self.roles << role if role && !self.roles.exists?( role.id )
+ self.role_objects << role if role && !self.role_objects.exists?(role.id)
end
+ ##
+ # Free +self+ from a specified role on +object+.
+ #
+ # @param [Symbol,String] role_name Role name
+ # @param [Object] object Object to remove a role on
+ # @see Acl9::ModelExtensions::Object#accepts_no_role!
def has_no_role!(role_name, object = nil)
delete_role(get_role(role_name, object))
end
+ ##
+ # Are there any roles for +self+ on +object+?
+ #
+ # @param [Object] object Object to query roles
+ # @return [Boolean] Returns true if +self+ has any roles on +object+.
+ # @see Acl9::ModelExtensions::Object#accepts_roles_by?
def has_roles_for?(object)
- !!self.roles.detect(&role_selecting_lambda(object))
+ !!self.role_objects.detect(&role_selecting_lambda(object))
end
alias :has_role_for? :has_roles_for?
+ ##
+ # Which roles does +self+ have on +object+?
+ #
+ # @return [Array<Role>] Role instances, associated both with +self+ and +object+
+ # @param [Object] object Object to query roles
+ # @see Acl9::ModelExtensions::Object#accepted_roles_by
+ # @example
+ # user = User.find(...)
+ # product = Product.find(...)
+ #
+ # user.roles_for(product).map(&:name).sort #=> role names in alphabetical order
def roles_for(object)
- self.roles.select(&role_selecting_lambda(object))
+ self.role_objects.select(&role_selecting_lambda(object))
end
+ ##
+ # Unassign any roles on +object+ from +self+.
+ #
+ # @param [Object,nil] object Object to unassign roles for. +nil+ means unassign global roles.
def has_no_roles_for!(object = nil)
roles_for(object).each { |role| delete_role(role) }
end
+ ##
+ # Unassign all roles from +self+.
def has_no_roles!
- # for some reason simple
+ # for some reason simple
#
# self.roles.each { |role| delete_role(role) }
#
# doesn't work. seems like a bug in ActiveRecord
- self.roles.map(&:id).each do |role_id|
+ self.role_objects.map(&:id).each do |role_id|
delete_role self._auth_role_class.find(role_id)
end
end
private
@@ -63,12 +131,12 @@
when Class
lambda { |role| role.authorizable_type == object.to_s }
when nil
lambda { |role| role.authorizable.nil? }
else
- lambda do |role|
- role.authorizable_type == object.class.base_class.to_s && role.authorizable == object
+ lambda do |role|
+ role.authorizable_type == object.class.base_class.to_s && role.authorizable == object
end
end
end
def get_role(role_name, object)
@@ -78,23 +146,23 @@
when Class
[ 'name = ? and authorizable_type = ? and authorizable_id IS NULL', role_name, object.to_s ]
when nil
[ 'name = ? and authorizable_type IS NULL and authorizable_id IS NULL', role_name ]
else
- [
+ [
'name = ? and authorizable_type = ? and authorizable_id = ?',
- role_name, object.class.base_class.to_s, object.id
+ role_name, object.class.base_class.to_s, object.id
]
end
self._auth_role_class.first :conditions => cond
end
- def delete_role(role)
+ def delete_role(role)
if role
- self.roles.delete role
+ self.role_objects.delete role
- role.destroy if role.send(self.class.to_s.tableize).empty?
+ role.destroy if role.send(self.class.to_s.demodulize.tableize).empty?
end
end
protected