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