diff --git a/app/models/v2/profile_rule.rb b/app/models/v2/profile_rule.rb new file mode 100644 index 000000000..add697332 --- /dev/null +++ b/app/models/v2/profile_rule.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module V2 + # Model for ProfileRules + class ProfileRule < ApplicationRecord + self.table_name = :profile_rules + + belongs_to :profile, class_name: 'V2::Profile' + belongs_to :rule, class_name: 'V2::Rule' + end +end diff --git a/app/models/v2/rule.rb b/app/models/v2/rule.rb index 28bedf0a0..b72a90897 100644 --- a/app/models/v2/rule.rb +++ b/app/models/v2/rule.rb @@ -19,6 +19,8 @@ class Rule < ApplicationRecord ) belongs_to :security_guide + has_many :profile_rules, dependent: :delete_all + has_many :profiles, through: :profile_rules, source: :profile, class_name: 'V2::Profile' sortable_by :title sortable_by :severity, SORTED_SEVERITIES diff --git a/config/routes.rb b/config/routes.rb index 4b5c24318..ba65f52a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,9 +25,11 @@ def draw_routes(prefix) if !Rails.env.production? || ENV.fetch('ENABLE_API_V2', false) scope 'v2', module: 'v2', as: 'v2' do resources :security_guides, only: [:index, :show] do - resources :profiles, only: [:index, :show], parents: [:security_guide] resources :value_definitions, only: [:index, :show], parents: [:security_guide] resources :rules, only: [:index, :show], parents: [:security_guide] + resources :profiles, only: [:index, :show], parents: [:security_guide] do + resources :rules, only: [:index, :show], parents: [:security_guide, :profiles] + end end end end diff --git a/spec/controllers/v2/concerns/collection_spec.rb b/spec/controllers/v2/concerns/collection_spec.rb index 9dd75d87d..3e37ecdf7 100644 --- a/spec/controllers/v2/concerns/collection_spec.rb +++ b/spec/controllers/v2/concerns/collection_spec.rb @@ -41,8 +41,6 @@ end context 'under incorrect parent', if: parents.present? do - let(:parent) { FactoryBot.create(:"v2_#{parents.first}") } - it 'returns not_found' do get :index, params: extra_params.merge(parents: parents) diff --git a/spec/controllers/v2/rules_controller_spec.rb b/spec/controllers/v2/rules_controller_spec.rb index 66e8d56bd..de3d0f841 100644 --- a/spec/controllers/v2/rules_controller_spec.rb +++ b/spec/controllers/v2/rules_controller_spec.rb @@ -23,31 +23,66 @@ allow(controller).to receive(:rbac_allowed?).and_return(rbac_allowed?) end - describe 'GET index' do - let(:parent) { FactoryBot.create(:v2_security_guide) } - let(:extra_params) { { security_guide_id: parent.id } } - let(:item_count) { 2 } - let(:items) do - FactoryBot.create_list( - :v2_rule, - item_count, - security_guide: parent - ).sort_by(&:id) + context '/security_guides/:id/rules' do + describe 'GET index' do + let(:parent) { FactoryBot.create(:v2_security_guide) } + let(:extra_params) { { security_guide_id: parent.id } } + let(:item_count) { 2 } + let(:items) do + FactoryBot.create_list( + :v2_rule, + item_count, + security_guide: parent + ).sort_by(&:id) + end + + it_behaves_like 'collection', :security_guide + include_examples 'with metadata', :security_guide + it_behaves_like 'paginable', :security_guide + it_behaves_like 'sortable', :security_guide + it_behaves_like 'searchable', :security_guide end - it_behaves_like 'collection', :security_guide - include_examples 'with metadata', :security_guide - it_behaves_like 'paginable', :security_guide - it_behaves_like 'sortable', :security_guide - it_behaves_like 'searchable', :security_guide + describe 'GET show' do + let(:item) { FactoryBot.create(:v2_rule) } + let(:parent) { item.security_guide } + let(:extra_params) { { security_guide_id: parent.id, id: item.id } } + let(:notfound_params) { extra_params.merge(security_guide_id: FactoryBot.create(:v2_security_guide).id) } + + it_behaves_like 'resource', :security_guide + end end - describe 'GET show' do - let(:item) { FactoryBot.create(:v2_rule) } - let(:parent) { item.security_guide } - let(:extra_params) { { security_guide_id: parent.id, id: item.id } } - let(:notfound_params) { extra_params.merge(security_guide_id: FactoryBot.create(:v2_security_guide).id) } + context '/security_guides/:id/profiles/:id/rules' do + describe 'GET index' do + let(:parent) { FactoryBot.create(:v2_profile) } + let(:extra_params) { { security_guide_id: parent.security_guide.id, profile_id: parent.id } } + let(:item_count) { 2 } + let(:items) do + FactoryBot.create_list( + :v2_rule, + item_count, + security_guide: parent.security_guide, + profile_id: parent.id + ).sort_by(&:id) + end - it_behaves_like 'resource', :security_guide + it_behaves_like 'collection', :security_guide, :profiles + include_examples 'with metadata', :security_guide, :profiles + it_behaves_like 'paginable', :security_guide, :profiles + it_behaves_like 'sortable', :security_guide, :profiles + it_behaves_like 'searchable', :security_guide, :profiles + end + + describe 'GET show' do + let(:parent) { FactoryBot.create(:v2_profile) } + let(:extra_params) { { security_guide_id: parent.security_guide.id, profile_id: parent.id, id: item.id } } + let(:notfound_params) { extra_params.merge(security_guide_id: FactoryBot.create(:v2_security_guide).id) } + let(:item) do + FactoryBot.create(:v2_rule, security_guide: parent.security_guide, profile_id: parent.id) + end + + it_behaves_like 'resource', :security_guide, :profiles + end end end diff --git a/spec/factories/profile_rule.rb b/spec/factories/profile_rule.rb new file mode 100644 index 000000000..e7b2423f5 --- /dev/null +++ b/spec/factories/profile_rule.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :v2_profile_rule, class: 'V2::ProfileRule' do + end +end diff --git a/spec/factories/rule.rb b/spec/factories/rule.rb index ac57c0fb2..8ea898bbc 100644 --- a/spec/factories/rule.rb +++ b/spec/factories/rule.rb @@ -13,6 +13,13 @@ transient do os_major_version { 7 } + profile_id { nil } + end + + after(:create) do |rule, ev| + next if ev.profile_id.nil? + + rule.profile_rules << FactoryBot.create(:v2_profile_rule, rule_id: rule.id, profile_id: ev.profile_id) end end end diff --git a/spec/fixtures/files/searchable/rules_controller.yaml b/spec/fixtures/files/searchable/rules_controller.yaml index 0a047e921..c17385127 100644 --- a/spec/fixtures/files/searchable/rules_controller.yaml +++ b/spec/fixtures/files/searchable/rules_controller.yaml @@ -6,10 +6,12 @@ - :factory: :v2_rule :title: searched title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: not this title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (title = "searched title") - :name: "non-equality search by title" :entities: @@ -17,10 +19,12 @@ - :factory: :v2_rule :title: not this title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: searched title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (title != "searched title") - :name: "in search by title" :entities: @@ -28,10 +32,12 @@ - :factory: :v2_rule :title: searched title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: not this title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (title ^ "searched title") - :name: "not-in search by title" :entities: @@ -39,10 +45,12 @@ - :factory: :v2_rule :title: not this title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: searched title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (title !^ "searched title") - :name: "like search by title" :entities: @@ -50,10 +58,12 @@ - :factory: :v2_rule :title: searched title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: not this title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (title ~ "searched title") - :name: "unlike search by title" :entities: @@ -61,10 +71,12 @@ - :factory: :v2_rule :title: not this title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: searched title :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (title !~ "searched title") - :name: "equality search by severity" @@ -74,11 +86,13 @@ :title: searched title :severity: searched severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: not this title :severity: not this severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (severity = "searched severity") - :name: "non-equality search by severity" :entities: @@ -87,11 +101,13 @@ :title: not this title :severity: not this severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: searched title :severity: searched severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (severity != "searched severity") - :name: "in search by severity" :entities: @@ -100,11 +116,13 @@ :title: searched title :severity: searched severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: not this title :severity: not this severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (severity ^ "searched severity") - :name: "not-in search by severity" :entities: @@ -113,9 +131,11 @@ :title: not this title :severity: not this severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :not_found: - :factory: :v2_rule :title: searched title :severity: searched severity :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :query: (severity !^ "searched severity") diff --git a/spec/fixtures/files/sortable/rules_controller.yaml b/spec/fixtures/files/sortable/rules_controller.yaml index 6d4bcaa59..85401fcf2 100644 --- a/spec/fixtures/files/sortable/rules_controller.yaml +++ b/spec/fixtures/files/sortable/rules_controller.yaml @@ -4,60 +4,70 @@ :severity: 'high' :precedence: 1234 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'abda' :severity: 'medium' :precedence: 567 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'aaaa' :severity: 'low' :precedence: 8765 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'adac' :severity: 'high' :precedence: 987 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'bbbb' :severity: 'medium' :precedence: 4562 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'cccd' :severity: 'low' :precedence: 2341 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'aaaa' :severity: 'high' :precedence: 954 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'bacc' :severity: 'medium' :precedence: 1854 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'zzab' :severity: 'low' :precedence: 5321 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} - :factory: :v2_rule :title: 'edfa' :severity: 'high' :precedence: 954 :security_guide_id: ${security_guide_id} + :profile_id: ${profile_id} :queries: - :sort_by: