Skip to content

Commit

Permalink
feat(APIv2): RHICOMPL-3890 implement ValueDefinitions controller
Browse files Browse the repository at this point in the history
  • Loading branch information
RoamingNoMaD authored and skateman committed Aug 29, 2023
1 parent 6288fcd commit d67e823
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 0 deletions.
34 changes: 34 additions & 0 deletions app/controllers/v2/value_definitions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

module V2
# API for Value Definitions under Security Guides
class ValueDefinitionsController < ApplicationController
def index
render_json value_definitions
end
permission_for_action :index, Rbac::COMPLIANCE_VIEWER

def show
render_json value_definition
end
permission_for_action :show, Rbac::COMPLIANCE_VIEWER

private

def value_definitions
@value_definitions ||= authorize(resolve_collection)
end

def value_definition
@value_definition ||= authorize(resource.find(permitted_params[:id]))
end

def resource
V2::ValueDefinition.where(security_guide_id: params[:security_guide_id])
end

def serializer
V2::ValueDefinitionSerializer
end
end
end
1 change: 1 addition & 0 deletions app/models/v2/security_guide.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class SecurityGuide < ApplicationRecord
)

has_many :profiles, class_name: 'V2::Profile', dependent: :destroy
has_many :value_definitions, class_name: 'V2::ValueDefinitions', dependent: :destroy

scoped_search on: :title, only_explicit: true, operators: %i[like unlike eq ne in notin]
scoped_search on: %i[version ref_id], only_explicit: true, operators: %i[eq ne in notin]
Expand Down
15 changes: 15 additions & 0 deletions app/models/v2/value_definition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

# Stores information about value definitions. This comes from SCAP.
module V2
# Model for Value Definitions
class ValueDefinition < ApplicationRecord
# FIXME: drop the foreign key and alias after remodel
alias_attribute :security_guide_id, :benchmark_id
belongs_to :security_guide, class_name: 'V2::SecurityGuide', foreign_key: 'benchmark_id', inverse_of: false

sortable_by :title

scoped_search on: :title, only_explicit: true, operators: %i[like unlike eq ne in notin]
end
end
21 changes: 21 additions & 0 deletions app/policies/v2/value_definition_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module V2
# Policies for accessing Value Definitions
class ValueDefinitionPolicy < ApplicationPolicy
def index?
true
end

def show?
true
end

# All users should see all value definitions currently
class Scope < ::ApplicationPolicy::Scope
def resolve
scope.all
end
end
end
end
8 changes: 8 additions & 0 deletions app/serializers/v2/value_definition_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

module V2
# JSON API serialization for an OpenSCAP Value
class ValueDefinitionSerializer < ApplicationSerializer
attributes :ref_id, :title, :description, :value_type, :default_value
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def draw_routes(prefix)
scope 'v2', module: 'v2', as: 'v2' do
resources :security_guides, only: [:index, :show] do
resources :profiles, only: [:index, :show], parents: [V2::SecurityGuide]
resources :value_definitions, only: [:index, :show], parents: [V2::SecurityGuide]
end
end
end
Expand Down
156 changes: 156 additions & 0 deletions spec/controllers/v2/value_definitions_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# frozen_string_literal: true

require 'rails_helper'

describe V2::ValueDefinitionsController do
let(:attributes) do
{
ref_id: :ref_id,
title: :title,
description: :description,
value_type: :value_type,
default_value: :default_value
}
end

let(:current_user) { FactoryBot.create(:v2_user) }

before do
request.headers['X-RH-IDENTITY'] = current_user.account.identity_header.raw
expect(controller).to receive(:rbac_allowed?).and_return(rbac_allowed?)
end

describe 'GET index' do
let(:item_count) { 2 }
let(:security_guide) { FactoryBot.create(:v2_security_guide) }
let(:items) do
FactoryBot.create_list(
:v2_value_definition,
item_count,
security_guide: security_guide
).sort_by(&:id)
end

context 'Authorized' do
let(:rbac_allowed?) { true }

it 'returns base fields for each result' do
collection = items.map do |vd|
hash_including(
'id' => vd.id,
'type' => 'value_definition',
'attributes' => attributes.each_with_object({}) do |(key, value), obj|
obj[key.to_s] = vd.send(value)
end
)
end

nested_route(V2::SecurityGuide) do |parents|
get :index, params: {
security_guide_id: security_guide.id,
parents: parents
}
end

expect(response).to have_http_status :ok
expect(response_body_data).to match_array(collection)

response_body_data.each do |vd|
expect(vd['attributes'].keys.count).to eq(attributes.keys.count)
end
end

include_examples 'with metadata', V2::SecurityGuide do
let(:extra_params) { { security_guide_id: security_guide.id } }
end

it_behaves_like 'paginable', V2::SecurityGuide do
let(:extra_params) { { security_guide_id: security_guide.id } }
end

it_behaves_like 'sortable', V2::SecurityGuide do
let(:extra_params) { { security_guide_id: security_guide.id } }
end

it_behaves_like 'searchable', V2::SecurityGuide do
let(:extra_params) { { security_guide_id: security_guide.id } }
end

context 'multiple security guides' do
let(:empty_security_guide) { FactoryBot.create(:v2_security_guide) }
let(:item) { FactoryBot.create(:v2_value_definition) }

it 'returns no data from empty security guide' do
nested_route(V2::SecurityGuide) do |parents|
get :index, params: {
security_guide_id: empty_security_guide.id,
parents: parents
}
end
expect(response_body_data).to be_empty
end
end
end

context 'Unathorized' do
let(:rbac_allowed?) { false }

it 'responds with unauthorized status' do
nested_route(V2::SecurityGuide) do |parents|
get :index, params: {
security_guide_id: security_guide.id,
parents: parents
}
end

expect(response).to have_http_status :forbidden
end
end
end

describe 'GET show' do
let(:value_definition) { FactoryBot.create(:v2_value_definition) }
let(:security_guide) { value_definition.security_guide }

context 'Authorized' do
let(:rbac_allowed?) { true }

it 'returns value_definition by id' do
item = hash_including('data' => {
'id' => value_definition.id,
'type' => 'value_definition',
'attributes' => attributes.each_with_object({}) do |(key, value), obj|
obj[key.to_s] = value_definition.send(value)
end
})

nested_route(V2::SecurityGuide) do |parents|
get :show, params: {
security_guide_id: security_guide.id,
id: value_definition.id,
parents: parents
}
end

expect(response.parsed_body).to match(item)
end

context 'under incorrect parent security guide' do
let(:item) { FactoryBot.create(:v2_value_definition) }
let(:security_guide) { FactoryBot.create(:v2_security_guide) }

it 'returns not_found' do
nested_route(V2::SecurityGuide) do |parents|
get :show, params: {
security_guide_id: security_guide.id,
id: item.id,
parents: parents
}

expect(response).to have_http_status :not_found
end
end
end
end
end
end
17 changes: 17 additions & 0 deletions spec/factories/value_definition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

FactoryBot.define do
factory :v2_value_definition, class: V2::ValueDefinition do
ref_id { "foo_value_#{SecureRandom.uuid}" }
title { Faker::Lorem.sentence }
description { Faker::Lorem.paragraph }
value_type { 'boolean' }
default_value { %w[true false].sample }

security_guide { association :v2_security_guide, os_major_version: os_major_version }

transient do
os_major_version { 7 }
end
end
end
68 changes: 68 additions & 0 deletions spec/fixtures/files/searchable/value_definitions_controller.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---

- :name: "equality search by title"
:entities:
:found:
- :factory: :v2_value_definition
:title: searched title
:security_guide_id: ${security_guide_id}
:not_found:
- :factory: :v2_value_definition
:title: not this title
:security_guide_id: ${security_guide_id}
:query: (title = "searched title")
- :name: "non-equality search by title"
:entities:
:found:
- :factory: :v2_value_definition
:title: not this title
:security_guide_id: ${security_guide_id}
:not_found:
- :factory: :v2_value_definition
:title: searched title
:security_guide_id: ${security_guide_id}
:query: (title != "searched title")
- :name: "in search by title"
:entities:
:found:
- :factory: :v2_value_definition
:title: searched title
:security_guide_id: ${security_guide_id}
:not_found:
- :factory: :v2_value_definition
:title: not this title
:security_guide_id: ${security_guide_id}
:query: (title ^ "searched title")
- :name: "not-in search by title"
:entities:
:found:
- :factory: :v2_value_definition
:title: not this title
:security_guide_id: ${security_guide_id}
:not_found:
- :factory: :v2_value_definition
:title: searched title
:security_guide_id: ${security_guide_id}
:query: (title !^ "searched title")
- :name: "like search by title"
:entities:
:found:
- :factory: :v2_value_definition
:title: searched title
:security_guide_id: ${security_guide_id}
:not_found:
- :factory: :v2_value_definition
:title: not this title
:security_guide_id: ${security_guide_id}
:query: (title ~ "searched title")
- :name: "unlike search by title"
:entities:
:found:
- :factory: :v2_value_definition
:title: not this title
:security_guide_id: ${security_guide_id}
:not_found:
- :factory: :v2_value_definition
:title: searched title
:security_guide_id: ${security_guide_id}
:query: (title !~ "searched title")
29 changes: 29 additions & 0 deletions spec/fixtures/files/sortable/value_definitions_controller.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
:entities:
- :factory: :v2_value_definition
:title: 'aba'
:security_guide_id: ${security_guide_id}
- :factory: :v2_value_definition
:title: 'bac'
:security_guide_id: ${security_guide_id}
- :factory: :v2_value_definition
:title: 'aab'
:security_guide_id: ${security_guide_id}
- :factory: :v2_value_definition
:title: 'aaa'
:security_guide_id: ${security_guide_id}
- :factory: :v2_value_definition
:title: 'caa'
:security_guide_id: ${security_guide_id}
- :factory: :v2_value_definition
:title: 'aaa'
:security_guide_id: ${security_guide_id}
:queries:
- :sort_by:
- 'title'
:result: [[3, 5], 2, 0, 1, 4]
- :sort_by:
- 'title:asc'
:result: [[3, 5], 2, 0, 1, 4]
- :sort_by:
- 'title:desc'
:result: [4, 1, 0, 2, [3, 5]]

0 comments on commit d67e823

Please sign in to comment.