diff --git a/app/models/switch.rb b/app/models/switch.rb index f3a48b87127..cff0418bd95 100644 --- a/app/models/switch.rb +++ b/app/models/switch.rb @@ -1,6 +1,7 @@ class Switch < ApplicationRecord include NewWithTypeStiMixin include CustomActionsMixin + extend TenancyCommonMixin belongs_to :host, :inverse_of => :host_virtual_switches has_one :ext_management_system, :through => :host @@ -15,5 +16,21 @@ class Switch < ApplicationRecord scope :shareable, -> { where(:shared => true) } scope :with_id, ->(id) { where(:id => id) } + has_one :tenant, :through => :ext_management_system + + def self.scope_by_tenant? + true + end + + def self.tenant_id_clause_format(tenant_ids) + {:ext_management_systems => {:tenant_id => tenant_ids}} + end + + # in a perfect world, all of this would be in tenant_clause + # and that would not return a hash but a scope + def self.tenant_join_clause + left_outer_joins(:tenant) + end + acts_as_miq_taggable end diff --git a/lib/rbac/filterer.rb b/lib/rbac/filterer.rb index b2ed47adf94..7f98250ee4f 100644 --- a/lib/rbac/filterer.rb +++ b/lib/rbac/filterer.rb @@ -155,6 +155,7 @@ class Filterer 'SecurityGroup' => :descendant_ids, 'SecurityPolicy' => :descendant_ids, 'SecurityPolicyRule' => :descendant_ids, + 'Switch' => :descendant_ids, 'Tenant' => :descendant_ids, 'User' => :descendant_ids, 'Vm' => :descendant_ids @@ -622,7 +623,9 @@ def scope_to_tenant(scope, user, miq_group) klass = scope.respond_to?(:klass) ? scope.klass : scope user_or_group = user || miq_group tenant_id_clause = klass.tenant_id_clause(user_or_group) - tenant_id_clause ? scope.where(tenant_id_clause) : scope + scope = scope.where(tenant_id_clause) if tenant_id_clause + scope = scope.tenant_join_clause if scope.respond_to?(:tenant_join_clause) + scope end def scope_to_cloud_tenant(scope, user, miq_group) diff --git a/spec/lib/rbac/filterer_spec.rb b/spec/lib/rbac/filterer_spec.rb index 83d2aa2cd1d..cf9b908103b 100644 --- a/spec/lib/rbac/filterer_spec.rb +++ b/spec/lib/rbac/filterer_spec.rb @@ -132,16 +132,19 @@ def combine_filtered_ids(user_filtered_ids, belongsto_filtered_ids, managed_filt let(:owner_tenant) { FactoryBot.create(:tenant) } let(:owner_group) { FactoryBot.create(:miq_group, :tenant => owner_tenant) } let(:owner_user) { FactoryBot.create(:user, :miq_groups => [owner_group]) } - let(:owned_vm) { FactoryBot.create(:vm_vmware, :tenant => owner_tenant) } + let(:owned_ems) { FactoryBot.create(:ems_vmware, :tenant => owner_tenant) } + let(:owned_vm) { FactoryBot.create(:vm_vmware, :ext_management_system => owned_ems, :tenant => owner_tenant) } let(:other_tenant) { FactoryBot.create(:tenant) } let(:other_group) { FactoryBot.create(:miq_group, :tenant => other_tenant) } let(:other_user) { FactoryBot.create(:user, :miq_groups => [other_group]) } - let(:other_vm) { FactoryBot.create(:vm_vmware, :tenant => other_tenant) } + let(:other_ems) { FactoryBot.create(:ems_vmware, :tenant => other_tenant) } + let(:other_vm) { FactoryBot.create(:vm_vmware, :ext_management_system => other_ems, :tenant => other_tenant) } let(:child_tenant) { FactoryBot.create(:tenant, :divisible => false, :parent => owner_tenant) } let(:child_group) { FactoryBot.create(:miq_group, :tenant => child_tenant) } let(:child_user) { FactoryBot.create(:user, :miq_groups => [child_group]) } + let(:child_ems) { FactoryBot.create(:ems_vmware, :tenant => child_tenant) } let(:child_openstack_vm) { FactoryBot.create(:vm_openstack, :tenant => child_tenant, :miq_group => child_group) } describe ".search" do @@ -834,16 +837,18 @@ def combine_filtered_ids(user_filtered_ids, belongsto_filtered_ids, managed_filt end context "with accessible_tenant_ids filtering (strategy = :ancestor_ids)" do - it "can see parent tenant's EMS" do - ems = FactoryBot.create(:ems_vmware, :tenant => owner_tenant) + it "can see parent and own tenant's EMS" do + owned_ems + child_ems results = described_class.search(:class => "ExtManagementSystem", :miq_group => child_group).first - expect(results).to match_array [ems] + expect(results).to match_array [owned_ems, child_ems] end it "can't see descendant tenant's EMS" do - _ems = FactoryBot.create(:ems_vmware, :tenant => child_tenant) + owned_ems + child_ems results = described_class.search(:class => "ExtManagementSystem", :miq_group => owner_group).first - expect(results).to match_array [] + expect(results).to match_array [owned_ems] end end @@ -1203,6 +1208,34 @@ def combine_filtered_ids(user_filtered_ids, belongsto_filtered_ids, managed_filt end.not_to raise_error end end + + context "for Switches" do + let(:owned_host) { FactoryBot.create(:host, :ext_management_system => owned_ems) } + let(:other_host) { FactoryBot.create(:host, :ext_management_system => other_ems) } + let(:child_host) { FactoryBot.create(:host, :ext_management_system => child_ems) } + + let(:owned_switch) { FactoryBot.create(:switch, :host => owned_host) } + let(:other_switch) { FactoryBot.create(:switch, :host => other_host) } + let(:child_switch) { FactoryBot.create(:switch, :host => child_host) } + + it "finds own switches and child switches" do + owned_switch + other_switch + child_switch + + results = described_class.filtered(Switch, :user => owner_user) + expect(results).to match_array([owned_switch, child_switch]) + end + + it "doesn't finds parent switches" do + owned_switch + other_switch + child_switch + + results = described_class.filtered(Switch, :user => child_user) + expect(results).to match_array([child_switch]) + end + end end context "common setup" do