diff --git a/lib/rbac/filterer.rb b/lib/rbac/filterer.rb index f6a6600e0cb..4cfcbbe4112 100644 --- a/lib/rbac/filterer.rb +++ b/lib/rbac/filterer.rb @@ -332,7 +332,7 @@ def get_self_service_objects(user, miq_group, klass) klass.user_or_group_owned(user, miq_group).except(:order) end - def calc_filtered_ids(scope, user_filters, user, miq_group) + def calc_filtered_ids(scope, user_filters, user, miq_group, scope_tenant_filter) klass = scope.respond_to?(:klass) ? scope.klass : scope u_filtered_ids = pluck_ids(get_self_service_objects(user, miq_group, klass)) b_filtered_ids = get_belongsto_filter_object_ids(klass, user_filters['belongsto']) @@ -340,13 +340,11 @@ def calc_filtered_ids(scope, user_filters, user, miq_group) d_filtered_ids = pluck_ids(matches_via_descendants(rbac_class(klass), user_filters['match_via_descendants'], :user => user, :miq_group => miq_group)) - combine_filtered_ids(u_filtered_ids, b_filtered_ids, m_filtered_ids, d_filtered_ids) + combine_filtered_ids(u_filtered_ids, b_filtered_ids, m_filtered_ids, d_filtered_ids, scope_tenant_filter.try(:ids)) end - # # Algorithm: filter = u_filtered_ids UNION (b_filtered_ids INTERSECTION m_filtered_ids) - # filter = filter UNION d_filtered_ids if filter is not nil - # + # filter = (filter UNION d_filtered_ids if filter is not nil) UNION tenant_filter_ids # a nil as input for any field means it does not apply # a nil as output means there is not filter # @@ -354,9 +352,11 @@ def calc_filtered_ids(scope, user_filters, user, miq_group) # @param b_filtered_ids [nil|Array] objects that belong to parent # @param m_filtered_ids [nil|Array] managed filter object ids # @param d_filtered_ids [nil|Array] ids from descendants + # @param tenant_filter_ids [nil|Array] ids # @return nil if filters do not aply # @return [Array] target ids for filter - def combine_filtered_ids(u_filtered_ids, b_filtered_ids, m_filtered_ids, d_filtered_ids) + + def combine_filtered_ids(u_filtered_ids, b_filtered_ids, m_filtered_ids, d_filtered_ids, tenant_filter_ids) filtered_ids = if b_filtered_ids.nil? m_filtered_ids @@ -376,7 +376,11 @@ def combine_filtered_ids(u_filtered_ids, b_filtered_ids, m_filtered_ids, d_filte filtered_ids.uniq! end - filtered_ids + if filtered_ids.kind_of?(Array) + filtered_ids | tenant_filter_ids.to_a + elsif filtered_ids.nil? && tenant_filter_ids.kind_of?(Array) && tenant_filter_ids.present? + tenant_filter_ids + end end # @param parent_class [Class] Class of parent (e.g. Host) @@ -435,14 +439,18 @@ def scope_targets(klass, scope, rbac_filters, user, miq_group) end if apply_rbac_directly?(klass) - filtered_ids = calc_filtered_ids(scope, rbac_filters, user, miq_group) + filtered_ids = calc_filtered_ids(scope, rbac_filters, user, miq_group, nil) scope_by_ids(scope, filtered_ids) elsif apply_rbac_through_association?(klass) # if subclasses of MetricRollup or Metric, use the associated # model to derive permissions from associated_class = rbac_class(scope) - filtered_ids = calc_filtered_ids(associated_class, rbac_filters, user, miq_group) + if associated_class.try(:scope_by_tenant?) + scope_tenant_filter = scope_to_tenant(associated_class, user, miq_group) + end + + filtered_ids = calc_filtered_ids(associated_class, rbac_filters, user, miq_group, scope_tenant_filter) scope_by_parent_ids(associated_class, scope, filtered_ids) elsif klass == User && user.try!(:self_service?) # Self service users searching for users only see themselves diff --git a/spec/factories/vm_performance.rb b/spec/factories/vm_performance.rb new file mode 100644 index 00000000000..3453e2c6430 --- /dev/null +++ b/spec/factories/vm_performance.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :vm_performance do + timestamp { Time.now.utc } + end +end diff --git a/spec/lib/rbac/filterer_spec.rb b/spec/lib/rbac/filterer_spec.rb index 3e2f5e42d34..b7bc0e1e63c 100644 --- a/spec/lib/rbac/filterer_spec.rb +++ b/spec/lib/rbac/filterer_spec.rb @@ -156,6 +156,22 @@ let(:child_tenant) { FactoryGirl.create(:tenant, :divisible => false, :parent => owner_tenant) } let(:child_group) { FactoryGirl.create(:miq_group, :tenant => child_tenant) } + context 'with Vm as resource of VmPerformance model' do + let!(:root_tenant_vm) { FactoryGirl.create(:vm_vmware, :tenant => Tenant.root_tenant) } + let!(:vm_performance_root_tenant) { FactoryGirl.create(:vm_performance, :resource => root_tenant_vm) } + let!(:vm_performance_other_tenant) { FactoryGirl.create(:vm_performance, :resource => other_vm) } + + it 'list only other_user\'s VmPerformances' do + results = described_class.search(:class => VmPerformance, :user => other_user).first + expect(results).to match_array [vm_performance_other_tenant] + end + + it 'list all VmPerformances' do + results = described_class.search(:class => VmPerformance, :user => admin_user).first + expect(results).to match_array [vm_performance_other_tenant, vm_performance_root_tenant] + end + end + context "searching MiqTemplate" do it "can't see descendant tenant's templates" do owned_template.update_attributes!(:tenant_id => child_tenant.id, :miq_group_id => child_group.id)