module ErpTechSvcs::Extensions::ActiveRecord::ProtectedByCapabilities::ClassMethods
Public Instance Methods
protected_with_capabilities(options = {})
click to toggle source
# File lib/erp_tech_svcs/extensions/active_record/protected_with_capabilities.rb, line 12 def protected_with_capabilities(options = {}) extend ProtectedByCapabilities::SingletonMethods include ProtectedByCapabilities::InstanceMethods has_many :capabilities, :as => :capability_resource # protect all instance of this class by default class_attribute :protect_all_instances self.protect_all_instances = (options[:protect_all_instances].nil? ? false : options[:protect_all_instances]) # Get records filtered via query scope capabilities # By default Compass AE treats query scopes as restrictions # A user will see all records unless the user has a capability accessor with a query scope # If you set :protect_all_instances => true it is honored via with_user_security & with_instance_security but NOT with_query_security # arguments: user, capability_type_iids # capability_type_iids is optional and can be a single string or an array of strings # Example: which files can this user download? FileAsset.with_query_security(user, 'download').all # Example: which website sections can this user either view or edit? WebsiteSection.with_query_security(user, ['view','edit']).all scope :with_query_security, lambda{|*args| raise ArgumentError if args.empty? || args.size > 2 user = args.first capability_type_iids = args.second || [] capability_type_iids = [capability_type_iids] if capability_type_iids.is_a?(String) scope_type = ScopeType.find_by_internal_identifier('query') granted_capabilities = user.all_capabilities.where(:scope_type_id => scope_type.id).where(:capability_resource_type => self.name) unless capability_type_iids.empty? capability_type_ids = capability_type_iids.collect{|type| convert_capability_type(type).id } granted_capabilities = granted_capabilities.where("capability_type_id IN (?)", capability_type_ids.join(',')) end query = nil granted_capabilities.each do |scope_capability| query = query.nil? ? where(scope_capability.scope_query) : query.where(scope_capability.scope_query) end query } # Get records for this model permitted via instance capabilities # If :protect_all_instances => true return only instances user has explicitly been granted access to # If :protect_all_instances => false return instances without capabilities or that user is granted access to (default) # arguments: user, capability_type_iids # capability_type_iids is optional and can be a single string or an array of strings # Example: which files can this user download? FileAsset.with_instance_security(user, 'download').all # Example: which website sections can this user either view or edit? WebsiteSection.with_instance_security(user, ['view','edit']).all scope :with_instance_security, lambda{|*args| raise ArgumentError if args.empty? || args.size > 2 user = args.first capability_type_iids = args.second || [] capability_type_iids = [capability_type_iids] if capability_type_iids.is_a?(String) scope_type = ScopeType.find_by_internal_identifier('instance') granted_capabilities = user.all_capabilities.where(:scope_type_id => scope_type.id).where(:capability_resource_type => self.name) unless capability_type_iids.empty? capability_type_ids = capability_type_iids.collect{|type| convert_capability_type(type).id } granted_capabilities = granted_capabilities.where("capability_type_id IN (#{capability_type_ids.join(',')})") end denied_capabilities = instance_capabilities.select('capabilities.id').where("capabilities.id NOT IN (#{granted_capabilities.select('capabilities.id').to_sql})") deny_count = denied_capabilities.count join_type = (self.protect_all_instances ? 'JOIN' : 'LEFT JOIN') query = joins("#{join_type} capabilities AS c ON c.capability_resource_id = #{self.table_name}.id AND c.capability_resource_type = '#{self.name}'"). group(columns.collect{|c| "#{self.table_name}.#{c.name}" }) query = (deny_count == 0 ? query.where("c.id NOT IN (SELECT id FROM capabilities) OR c.id = c.id") : query.where("c.id NOT IN (SELECT id FROM capabilities) OR c.id NOT IN (#{denied_capabilities.to_sql})")) query } # Get records for this model that the given user has access to # arguments: user, capability_type_iids # capability_type_iids is optional and can be a single string or an array of strings # Example: which files can this user download? FileAsset.with_user_security(user, 'download').all # Example: which website sections can this user either view or edit? WebsiteSection.with_user_security(user, ['view','edit']).all scope :with_user_security, lambda{|*args| raise ArgumentError if args.empty? || args.size > 2 with_instance_security(*args).with_query_security(*args) } end