diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index f1fdc5d96..457a67380 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -11,6 +11,15 @@ module Api class FilterParamError < StandardError; end + class MutuallyExclusiveParamsError < StandardError + attr_reader :first_param, :second_param + + def initialize(first_param, second_param) + @first_param = first_param + @second_param = second_param + end + end + class PermissionError < StandardError attr_reader :klass, :mode @@ -28,6 +37,14 @@ module Api :bad_request) end + rescue_from MutuallyExclusiveParamsError do |e| + render_error(I18n.t('api.core.errors.mutually_exclusive_params_error.title'), + I18n.t('api.core.errors.mutually_exclusive_params_error.detail', + first_param: e.first_param, + second_param: e.second_param), + :bad_request) + end + rescue_from FilterParamError do |e| logger.error e.message logger.error e.backtrace.join("\n") diff --git a/app/controllers/api/v2/inventory_item_relationships_controller.rb b/app/controllers/api/v2/inventory_item_relationships_controller.rb new file mode 100644 index 000000000..714147bf1 --- /dev/null +++ b/app/controllers/api/v2/inventory_item_relationships_controller.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +module Api + module V2 + class InventoryItemRelationshipsController < BaseController + before_action :load_team, :load_inventory, :load_inventory_item + before_action :check_manage_permission, only: %w(create destroy) + before_action :load_create_params, only: :create + + def create + parent = @relation == :parent ? @inventory_item : @inventory_item_to_link + child = @relation == :child ? @inventory_item : @inventory_item_to_link + + @connection = RepositoryRowConnection.create!( + parent_id: parent, + child_id: child, + created_by: current_user, + last_modified_by: current_user + ) + + render jsonapi: @connection, serializer: InventoryItemRelationshipSerializer, status: :created + end + + def destroy + @connection = @inventory_item.parent_connections + .or(@inventory_item.child_connections) + .find(params.require(:id)) + @connection.destroy! + render body: nil + end + + private + + def check_manage_permission + raise PermissionError.new(Repository, :manage) unless can_manage_repository?(@inventory) + end + + def load_create_params + if connection_params[:parent_id].present? && connection_params[:child_id].present? + raise MutuallyExclusiveParamsError.new(:parent_id, :child_id) + end + + if connection_params[:parent_id].present? + @relation = :parent + @inventory_item_to_link = RepositoryRow.find(connection_params[:parent_id]) + elsif connection_params[:child_id].present? + @relation = :child + @inventory_item_to_link = RepositoryRow.find(connection_params[:child_id]) + end + + raise ActiveRecord::RecordNotFound unless @inventory_item_to_link + end + + def connection_params + raise TypeError unless params.require(:data).require(:type) == 'inventory_item_relationships' + + params.require(:data).require(:attributes).permit(%i(parent_id child_id)) + end + + def permitted_includes + %w(parent child) + end + end + end +end diff --git a/app/serializers/api/v2/inventory_item_relationship_serializer.rb b/app/serializers/api/v2/inventory_item_relationship_serializer.rb new file mode 100644 index 000000000..f3ad0c591 --- /dev/null +++ b/app/serializers/api/v2/inventory_item_relationship_serializer.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Api + module V2 + class InventoryItemRelationshipSerializer < ActiveModel::Serializer + type :inventory_item_relationships + + belongs_to :parent, serializer: InventoryItemSerializer + belongs_to :child, serializer: InventoryItemSerializer + belongs_to :created_by, serializer: UserSerializer + belongs_to :last_modified_by, serializer: UserSerializer + end + end +end diff --git a/config/locales/en.yml b/config/locales/en.yml index d6de24273..6c537e9cf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3907,6 +3907,9 @@ en: read_users_permission: title: "Permission denied" detail: "You don't have permission to read users on %{model}" + mutually_exclusive_params_error: + title: "Mutually Exclusive Parameters" + detail: "Parameters %{first_param} and %{second_param} should not be specified at the same time." update_stock_consumption_permission: title: "Permission denied" detail: "You don't have permisson to update stock consumption on this task item." diff --git a/config/routes/api_v2.rb b/config/routes/api_v2.rb new file mode 100644 index 000000000..3f74b3a6f --- /dev/null +++ b/config/routes/api_v2.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +# rubocop:disable Metrics/BlockLength + +namespace :v2, module: 'v1' do + resources :teams, only: %i(index show) do + resources :inventories, only: %i(index create show update destroy) do + resources :inventory_columns, + only: %i(index create show update destroy), + path: 'columns', + as: :columns do + resources :inventory_list_items, + only: %i(index create show update destroy), + path: 'list_items', + as: :list_items + resources :inventory_checklist_items, + only: %i(index create show update destroy), + path: 'checklist_items', + as: :checklist_items + resources :inventory_status_items, + only: %i(index create show update destroy), + path: 'status_items', + as: :status_items + resources :inventory_stock_unit_items, + only: %i(index create show update destroy), + path: 'stock_unit_items', + as: :stock_unit_items + end + resources :inventory_items, + only: %i(index create show update destroy), + path: 'items', + as: :items do + resources :inventory_cells, + only: %i(index create show update destroy), + path: 'cells', + as: :cells + resources :inventory_item_relationships, only: %i(create destroy) + end + end + resources :projects, only: %i(index show create update) do + resources :user_assignments, + only: %i(index show create update destroy), + controller: :project_user_assignments, + path: 'users', + as: :users + resources :project_comments, only: %i(index show), path: 'comments', as: :comments + get 'activities', to: 'projects#activities' + resources :reports, only: %i(index show), path: 'reports', as: :reports + resources :experiments, only: %i(index show create update) do + resources :user_assignments, + only: %i(index show update), + controller: :experiment_user_assignments + resources :task_groups, only: %i(index show) + resources :connections, only: %i(index show create destroy) + resources :tasks, only: %i(index show create update) do + resources :user_assignments, + only: %i(index show update), + controller: :task_user_assignments + resources :task_inventory_items, only: %i(index show update), + path: 'items', + as: :items + resources :task_users, only: %i(index show), + path: 'users', + as: :users + resources :task_tags, only: %i(index show), + path: 'tags', + as: :tags + resources :task_assignments, only: %i(index create destroy), + path: 'task_assignments', + as: :task_assignments + resources :protocols, only: %i(index show) do + resources :steps, only: %i(index show create update destroy) do + resources :assets, only: %i(index show create), path: 'attachments' + resources :checklists, only: %i(index show create update destroy), path: 'checklists' do + resources :checklist_items, + only: %i(index show create update destroy), + as: :items, + path: 'items' + end + resources :tables, only: %i(index show create update destroy), path: 'tables' + resources :step_texts, only: %i(index show create update destroy), path: 'step_texts' + end + end + get 'activities', to: 'tasks#activities' + end + end + end + resources :project_folders, only: %i(index show create update) + resources :users, only: %i(index) + resources :protocol_templates, only: %i(index show) + end + resources :users, only: %i(show) do + resources :user_identities, + only: %i(index create show update destroy), + path: 'identities', + as: :identities + end + + resources :user_roles, only: :index + resources :workflows, only: %i(index show) do + resources :workflow_statuses, path: :statuses, only: %i(index) + end +end + +namespace :v2 do + resources :teams do + resources :projects do + resources :experiments do + resources :tasks do + resources :results, only: %i(index create show update destroy) do + resources :result_assets, only: %i(index show create update destroy), path: 'assets' + resources :result_tables, only: %i(index show create update destroy), path: 'tables' + resources :result_texts, only: %i(index show create update destroy) + end + end + end + end + end +end + +# rubocop:enable Metrics/BlockLength