diff --git a/app/controllers/api/v1/inventory_columns_controller.rb b/app/controllers/api/v1/inventory_columns_controller.rb new file mode 100644 index 000000000..13d34a82b --- /dev/null +++ b/app/controllers/api/v1/inventory_columns_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Api + module V1 + class InventoryColumnsController < BaseController + before_action :load_team + before_action :load_inventory + + def index + columns = @inventory.repository_columns + .includes(:repository_list_items) + .page(params[:page]) + .per(params[:page_size]) + render json: columns, each_serializer: InventoryColumnSerializer, + include: :inventory_list_items + end + + private + + def load_team + @team = Team.find(params.require(:team_id)) + return render json: {}, status: :forbidden unless can_read_team?(@team) + end + + def load_inventory + @inventory = @team.repositories.find(params.require(:inventory_id)) + end + end + end +end diff --git a/app/serializers/api/v1/inventory_column_serializer.rb b/app/serializers/api/v1/inventory_column_serializer.rb new file mode 100644 index 000000000..1d0f65b7a --- /dev/null +++ b/app/serializers/api/v1/inventory_column_serializer.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Api + module V1 + class InventoryColumnSerializer < ActiveModel::Serializer + type :inventory_columns + attributes :name, :data_type + has_many :repository_list_items, key: :inventory_list_items, + serializer: InventoryListItemSerializer, + class_name: 'RepositoryListItem' + + def data_type + type_id = RepositoryColumn + .data_types[object.data_type] + I18n.t("api.v1.inventory_data_types.t#{type_id}") + end + end + end +end diff --git a/app/serializers/api/v1/inventory_list_item_serializer.rb b/app/serializers/api/v1/inventory_list_item_serializer.rb new file mode 100644 index 000000000..6220983f4 --- /dev/null +++ b/app/serializers/api/v1/inventory_list_item_serializer.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Api + module V1 + class InventoryListItemSerializer < ActiveModel::Serializer + type :inventory_list_items + attribute :data + end + end +end diff --git a/config/routes.rb b/config/routes.rb index bc95e9011..a0c7a8ebd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -543,6 +543,7 @@ Rails.application.routes.draw do namespace :v1 do resources :teams, only: %i(index show) do resources :inventories, only: %i(index show) do + get 'columns', to: 'inventory_columns#index' get 'items', to: 'inventory_items#index' end end diff --git a/spec/requests/api/v1/inventory_columns_controller_spec.rb b/spec/requests/api/v1/inventory_columns_controller_spec.rb new file mode 100644 index 000000000..9d7b0d9c3 --- /dev/null +++ b/spec/requests/api/v1/inventory_columns_controller_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Api::V1::InventoryColumnsController', type: :request do + before :all do + @user = create(:user) + @teams = create_list(:team, 2, created_by: @user) + create(:user_team, user: @user, team: @teams.first, role: 2) + + # valid_inventory + @valid_inventory = create(:repository, name: Faker::Name.unique.name, + created_by: @user, team: @teams.first) + + # unaccessable_inventory + create(:repository, name: Faker::Name.unique.name, + created_by: @user, team: @teams.second) + + create(:repository_column, name: Faker::Name.unique.name, + repository: @valid_inventory, data_type: :RepositoryTextValue) + list_column = create(:repository_column, name: Faker::Name.unique.name, + repository: @valid_inventory, data_type: :RepositoryListValue) + create(:repository_list_item, repository: @valid_inventory, + repository_column: list_column, data: Faker::Name.unique.name) + create(:repository_column, name: Faker::Name.unique.name, + repository: @valid_inventory, data_type: :RepositoryAssetValue) + + @valid_headers = + { 'Authorization': 'Bearer ' + generate_token(@user.id) } + end + + describe 'GET inventory_columns, #index' do + it 'Response with correct inventory items, default per page' do + hash_body = nil + get api_v1_team_inventory_columns_path( + team_id: @teams.first.id, + inventory_id: @teams.first.repositories.first.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_inventory.repository_columns.limit(10), + each_serializer: Api::V1::InventoryColumnSerializer, + include: :inventory_columns) + .as_json[:data] + ) + expect(hash_body[:included]).to match( + ActiveModelSerializers::SerializableResource + .new(@valid_inventory.repository_columns.limit(10), + each_serializer: Api::V1::InventoryColumnSerializer, + include: :inventory_list_items) + .as_json[:included] + ) + end + + it 'When invalid request, user in not member of the team' do + hash_body = nil + get api_v1_team_inventory_columns_path( + team_id: @teams.second.id, + inventory_id: @teams.second.repositories.first.id + ), headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body).to match({}) + end + + it 'When invalid request, non existing inventory' do + hash_body = nil + get api_v1_team_inventory_columns_path( + team_id: @teams.first.id, + inventory_id: 123 + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body).to match({}) + end + + it 'When invalid request, repository from another team' do + hash_body = nil + get api_v1_team_inventory_columns_path( + team_id: @teams.first.id, + inventory_id: @teams.second.repositories.first.id + ), headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body).to match({}) + end + end +end