Merge latest core-api branch [SCI-2765]

This commit is contained in:
Oleksii Kriuchykhin 2018-10-16 12:07:47 +02:00
commit f6b039d54e
54 changed files with 804 additions and 379 deletions

View file

@ -17,7 +17,7 @@ gem 'recaptcha', require: 'recaptcha/rails'
gem 'sanitize', '~> 4.4'
# Gems for OAuth2 subsystem
gem 'doorkeeper', '~> 4.4'
gem 'doorkeeper', '>= 4.6'
gem 'omniauth'
gem 'omniauth-linkedin-oauth2'

View file

@ -216,7 +216,7 @@ GEM
discard (1.0.0)
activerecord (>= 4.2, < 6)
docile (1.1.5)
doorkeeper (4.4.1)
doorkeeper (5.0.0)
railties (>= 4.2)
erubi (1.7.1)
execjs (2.7.0)
@ -308,7 +308,7 @@ GEM
rails (>= 3.2.0)
newrelic_rpm (4.7.1.340)
nio4r (2.3.1)
nokogiri (1.8.4)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0)
nokogiri
@ -357,7 +357,7 @@ GEM
public_suffix (3.0.2)
puma (3.11.2)
rack (2.0.5)
rack-test (1.0.0)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.1.6)
actioncable (= 5.1.6)
@ -565,7 +565,7 @@ DEPENDENCIES
devise_invitable
devise_security_extension!
discard (~> 1.0)
doorkeeper (~> 4.4)
doorkeeper (>= 4.6)
factory_bot_rails
faker
figaro

View file

@ -12,11 +12,16 @@ module Api
def index
@connections = @connections.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: @connections, each_serializer: ConnectionSerializer
incl = params[:include] == 'tasks' ? %i(input_task output_task) : nil
render jsonapi: @connections,
each_serializer: ConnectionSerializer,
include: incl
end
def show
render jsonapi: @connection, serializer: ConnectionSerializer
render jsonapi: @connection,
serializer: ConnectionSerializer,
include: %i(input_task output_task)
end
private

View file

@ -27,7 +27,9 @@ module Api
end
def show
render jsonapi: @inventory, serializer: InventorySerializer
render jsonapi: @inventory,
serializer: InventorySerializer,
include: :created_by
end
def update

View file

@ -14,8 +14,9 @@ module Api
.includes(:repository_list_items)
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: columns, each_serializer: InventoryColumnSerializer,
include: :inventory_list_items
render jsonapi: columns,
each_serializer: InventoryColumnSerializer,
hide_list_items: true
end
def create
@ -23,18 +24,22 @@ module Api
@inventory.repository_columns.create!(inventory_column_params)
render jsonapi: inventory_column,
serializer: InventoryColumnSerializer,
hide_list_items: true,
status: :created
end
def show
render jsonapi: @inventory_column, serializer: InventoryColumnSerializer
render jsonapi: @inventory_column,
serializer: InventoryColumnSerializer,
include: :inventory_list_items
end
def update
@inventory_column.attributes = update_inventory_column_params
if @inventory_column.changed? && @inventory_column.save!
render jsonapi: @inventory_column,
serializer: InventoryColumnSerializer
serializer: InventoryColumnSerializer,
hide_list_items: true
else
render body: nil
end
@ -89,6 +94,10 @@ module Api
raise ActionController::BadRequest,
'Object ID mismatch in URL and request body'
end
if params.require(:data).require(:attributes).include?(:data_type)
raise ActionController::BadRequest,
'Update of data_type attribute is not allowed'
end
inventory_column_params[:attributes]
end
end

View file

@ -16,9 +16,10 @@ module Api
repository_cells: Extends::REPOSITORY_SEARCH_INCLUDES
).page(params.dig(:page, :number))
.per(params.dig(:page, :size))
incl = params[:include] == 'inventory_cells' ? :inventory_cells : nil
render jsonapi: items,
each_serializer: InventoryItemSerializer,
include: :inventory_cells
include: incl
end
def create

View file

@ -1,59 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class MyModuleRepositoryRowsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task
before_action :load_task_repository_row, only: :show
def index
repo_rows = @my_module.my_module_repository_rows
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: repo_rows,
each_serializer: MyModuleRepositoryRowSerializer
end
def show
render jsonapi: @repo_row, serializer: MyModuleRepositoryRowSerializer
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_experiment
@experiment = @project.experiments.find(params.require(:experiment_id))
render jsonapi: {}, status: :forbidden unless can_read_experiment?(
@experiment
)
end
def load_task
@my_module = @experiment.my_modules.find(params.require(:task_id))
render jsonapi: {}, status: :not_found if @my_module.nil?
end
def load_task_repository_row
@repo_row = @my_module.my_module_repository_rows.find(
params.require(:id)
)
render jsonapi: {}, status: :not_found if @repo_row.nil?
end
end
end
end

View file

@ -1,59 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class MyModuleTagsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task
before_action :load_task_tag, only: :show
def index
task_tags = @my_module.my_module_tags
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: task_tags,
each_serializer: MyModuleTagSerializer
end
def show
render jsonapi: @task_tag, serializer: MyModuleTagSerializer
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_experiment
@experiment = @project.experiments.find(params.require(:experiment_id))
render jsonapi: {}, status: :forbidden unless can_read_experiment?(
@experiment
)
end
def load_task
@my_module = @experiment.my_modules.find(params.require(:task_id))
render jsonapi: {}, status: :not_found if @my_module.nil?
end
def load_task_tag
@task_tag = @my_module.my_module_tags.find(
params.require(:id)
)
render jsonapi: {}, status: :not_found if @task_tag.nil?
end
end
end
end

View file

@ -0,0 +1,47 @@
# frozen_string_literal: true
module Api
module V1
class ProjectCommentsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_project_comment, only: :show
def index
project_comments = @project.project_comments
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: project_comments,
each_serializer: CommentSerializer,
hide_project: true
end
def show
render jsonapi: @project_comment,
serializer: CommentSerializer,
hide_project: true,
include: :user
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_project_comment
@project_comment = @project.project_comments.find(params.require(:id))
render jsonapi: {}, status: :not_found if @project_comment.nil?
end
end
end
end

View file

@ -0,0 +1,52 @@
# frozen_string_literal: true
module Api
module V1
class ProjectsController < BaseController
before_action :load_team
before_action :load_project, only: :show
before_action :load_project_relative, only: :activities
def index
projects = @team.projects
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: projects, each_serializer: ProjectSerializer
end
def show
render jsonapi: @project, serializer: ProjectSerializer
end
def activities
activities = @project.activities
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: activities,
each_serializer: ActivitySerializer
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_project_relative
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
end
end
end

View file

@ -10,7 +10,7 @@ module Api
before_action :load_protocol, only: :show
def index
protocols = @my_module.protocols
protocols = @task.protocols
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
@ -44,11 +44,11 @@ module Api
end
def load_task
@my_module = @experiment.my_modules.find(params.require(:task_id))
@task = @experiment.my_modules.find(params.require(:task_id))
end
def load_protocol
@protocol = @my_module.protocols.find(
@protocol = @task.protocols.find(
params.require(:id)
)
end

View file

@ -0,0 +1,47 @@
# frozen_string_literal: true
module Api
module V1
class ReportsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_report, only: :show
def index
reports = @project.reports
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: reports,
each_serializer: ReportSerializer,
hide_project: true
end
def show
render jsonapi: @report,
serializer: ReportSerializer,
hide_project: true,
include: :user
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_report
@report = @project.reports.find(params.require(:id))
render jsonapi: {}, status: :not_found if @report.nil?
end
end
end
end

View file

@ -14,7 +14,7 @@ module Api
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: results, each_serializer: ResultSerializer,
include: %i(asset table text)
include: %i(text table file)
end
def create
@ -22,13 +22,13 @@ module Api
throw ActionController::ParameterMissing unless @result
render jsonapi: @result,
serializer: ResultSerializer,
include: %i(asset table text),
include: %i(text table file),
status: :created
end
def show
render jsonapi: @result, serializer: ResultSerializer,
include: %i(asset table text)
include: %i(text table file)
end
private

View file

@ -2,23 +2,26 @@
module Api
module V1
class MyModuleGroupsController < BaseController
class TaskGroupsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task_group, only: :show
def index
my_module_groups = @experiment.my_module_groups
task_groups = @experiment.my_module_groups
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: my_module_groups,
each_serializer: MyModuleGroupSerializer
incl = params[:include] == 'tasks' ? :tasks : nil
render jsonapi: task_groups,
each_serializer: TaskGroupSerializer,
include: incl
end
def show
render jsonapi: @my_module_group, serializer: MyModuleGroupSerializer
render jsonapi: @task_group,
serializer: TaskGroupSerializer,
include: :tasks
end
private
@ -43,7 +46,7 @@ module Api
end
def load_task_group
@my_module_group = @experiment.my_module_groups.find(
@task_group = @experiment.my_module_groups.find(
params.require(:id)
)
end

View file

@ -0,0 +1,67 @@
# frozen_string_literal: true
module Api
module V1
class TaskInventoryItemsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task
before_action :load_inventory_item, only: :show
def index
items =
@task.repository_rows
.includes(repository_cells: :repository_column)
.includes(repository_cells: Extends::REPOSITORY_SEARCH_INCLUDES)
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
incl = params[:include] == 'inventory_cells' ? :inventory_cells : nil
render jsonapi: items,
each_serializer: InventoryItemSerializer,
show_repository: true,
include: incl
end
def show
render jsonapi: @item,
serializer: InventoryItemSerializer,
show_repository: true,
include: %i(inventory_cells inventory)
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_experiment
@experiment = @project.experiments.find(params.require(:experiment_id))
render jsonapi: {}, status: :forbidden unless can_read_experiment?(
@experiment
)
end
def load_task
@task = @experiment.my_modules.find(params.require(:task_id))
render jsonapi: {}, status: :not_found if @task.nil?
end
def load_inventory_item
@item = @task.repository_rows.find(
params.require(:id)
)
render jsonapi: {}, status: :not_found if @item.nil?
end
end
end
end

View file

@ -2,24 +2,24 @@
module Api
module V1
class ActivitiesController < BaseController
class TaskTagsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task
before_action :load_activity, only: :show
before_action :load_tag, only: :show
def index
activities = @my_module.activities
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
tags = @task.tags
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: activities,
each_serializer: ActivitySerializer
render jsonapi: tags,
each_serializer: TagSerializer
end
def show
render jsonapi: @activity, serializer: ActivitySerializer
render jsonapi: @tag, serializer: TagSerializer
end
private
@ -44,15 +44,15 @@ module Api
end
def load_task
@my_module = @experiment.my_modules.find(params.require(:task_id))
render jsonapi: {}, status: :not_found if @my_module.nil?
@task = @experiment.my_modules.find(params.require(:task_id))
render jsonapi: {}, status: :not_found if @task.nil?
end
def load_activity
@activity = @my_module.activities.find(
def load_tag
@tag = @task.tags.find(
params.require(:id)
)
render jsonapi: {}, status: :not_found if @activity.nil?
render jsonapi: {}, status: :not_found if @tag.nil?
end
end
end

View file

@ -2,24 +2,24 @@
module Api
module V1
class UserMyModulesController < BaseController
class TaskUsersController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task
before_action :load_user_task, only: :show
before_action :load_user, only: :show
def index
user_tasks = @my_module.user_my_modules
users = @task.users
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: user_tasks,
each_serializer: UserMyModuleSerializer
render jsonapi: users,
each_serializer: UserSerializer
end
def show
render jsonapi: @user_task, serializer: UserMyModuleSerializer
render jsonapi: @user, serializer: UserSerializer
end
private
@ -44,11 +44,11 @@ module Api
end
def load_task
@my_module = @experiment.my_modules.find(params.require(:task_id))
@task = @experiment.my_modules.find(params.require(:task_id))
end
def load_user_task
@user_task = @my_module.user_my_modules.find(
def load_user
@user = @task.users.find(
params.require(:id)
)
end

View file

@ -2,47 +2,46 @@
module Api
module V1
class MyModulesController < BaseController
class TasksController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task, only: :show
before_action :load_task_relative, only: %i(outputs output inputs input)
before_action :load_task_relative, only: %i(inputs outputs activities)
def index
tasks = @experiment.my_modules
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: tasks, each_serializer: MyModuleSerializer
render jsonapi: tasks, each_serializer: TaskSerializer
end
def show
render jsonapi: @my_module, serializer: MyModuleSerializer
end
def outputs
outputs = @my_module.my_modules
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: outputs, each_serializer: MyModuleSerializer
end
def output
output = @my_module.my_modules.find(params.require(:id))
render jsonapi: output, serializer: MyModuleSerializer
render jsonapi: @task, serializer: TaskSerializer
end
def inputs
inputs = @my_module.my_module_antecessors
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: inputs, each_serializer: MyModuleSerializer
inputs = @task.my_module_antecessors
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: inputs, each_serializer: TaskSerializer
end
def input
input = @my_module.my_module_antecessors.find(params.require(:id))
render jsonapi: input, serializer: MyModuleSerializer
def outputs
outputs = @task.my_modules
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: outputs, each_serializer: TaskSerializer
end
def activities
activities = @task.activities
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: activities,
each_serializer: ActivitySerializer
end
private
@ -67,7 +66,7 @@ module Api
end
def load_task
@my_module = @experiment.my_modules.find(params.require(:id))
@task = @experiment.my_modules.find(params.require(:id))
end
# Made the method below because its more elegant than changing parameters
@ -75,7 +74,7 @@ module Api
# for a task, the "id" that used to be task id is now an id for the output
# or input.
def load_task_relative
@my_module = @experiment.my_modules.find(params.require(:task_id))
@task = @experiment.my_modules.find(params.require(:task_id))
end
end
end

View file

@ -13,7 +13,9 @@ module Api
end
def show
render jsonapi: @team, serializer: TeamSerializer
render jsonapi: @team,
serializer: TeamSerializer,
include: :created_by
end
private

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
module Api
module V1
class UserProjectsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_user_project, only: :show
def index
user_projects = @project.user_projects
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: user_projects,
each_serializer: UserProjectSerializer,
include: :user
end
def show
render jsonapi: @user_project,
serializer: UserProjectSerializer,
include: :user
end
private
def load_team
@team = Team.find(params.require(:team_id))
render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end
def load_project
@project = @team.projects.find(params.require(:project_id))
render jsonapi: {}, status: :forbidden unless can_read_project?(
@project
)
end
def load_user_project
@user_project = @project.user_projects.find(params.require(:id))
render jsonapi: {}, status: :not_found if @user_project.nil?
end
end
end
end

View file

@ -4,9 +4,15 @@ module Api
module V1
class ActivitySerializer < ActiveModel::Serializer
type :activities
attributes :id, :my_module_id, :user_id, :type_of, :message,
:project_id, :experiment_id
belongs_to :my_module, serializer: MyModuleSerializer
attributes :id, :type_of, :message
belongs_to :project, serializer: ProjectSerializer
belongs_to :experiment, serializer: TaskSerializer,
if: -> { object.experiment.present? }
belongs_to :my_module, key: :task,
serializer: TaskSerializer,
class_name: 'MyModule',
if: -> { object.my_module.present? }
belongs_to :user, serializer: UserSerializer
end
end
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
module Api
module V1
class CommentSerializer < ActiveModel::Serializer
type :comments
attributes :id, :message
belongs_to :user, serializer: UserSerializer
belongs_to :project,
serializer: ProjectSerializer,
if: -> { object.class == ProjectComment &&
!instance_options[:hide_project] }
# TODO
#belongs_to :my_module,
# serializer: TaskSerializer,
# key: :task,
# class_name: 'MyModule',
# if: -> { object.class == TaskComment &&
# !instance_options[:hide_task] }
#belongs_to :step,
# serializer: StepSerializer,
# if: -> { object.class == StepComment &&
# !instance_options[:hide_step] }
belongs_to :result,
serializer: ResultSerializer,
if: -> { object.class == ResultComment &&
!instance_options[:hide_result] }
end
end
end

View file

@ -4,16 +4,13 @@ module Api
module V1
class ConnectionSerializer < ActiveModel::Serializer
type :connections
attributes :id, :input_id, :output_id
has_one :input_task, serializer: MyModuleSerializer
has_one :output_task, serializer: MyModuleSerializer
def input_task
MyModule.find(object.input_id)
end
def output_task
MyModule.find(object.output_id)
end
attributes :id
belongs_to :from, key: :input_task,
serializer: TaskSerializer,
class_name: 'MyModule'
belongs_to :to, key: :output_task,
serializer: TaskSerializer,
class_name: 'MyModule'
end
end
end

View file

@ -7,12 +7,6 @@ module Api
attributes :id, :value_type, :value
attribute :repository_column_id, key: :column_id
def value_type
type_id = RepositoryColumn
.data_types[object.repository_column.data_type]
I18n.t("api.v1.inventory_data_types.t#{type_id}")
end
def value
value =
case object.value_type

View file

@ -5,15 +5,12 @@ module Api
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
has_many :repository_list_items,
key: :inventory_list_items,
serializer: InventoryListItemSerializer,
class_name: 'RepositoryListItem',
if: -> { object.data_type == 'RepositoryListValue' &&
!instance_options[:hide_list_items] }
end
end
end

View file

@ -7,7 +7,12 @@ module Api
attributes :name
has_many :repository_cells, key: :inventory_cells,
serializer: InventoryCellSerializer,
class_name: 'RepositoryCell'
class_name: 'RepositoryCell',
unless: -> { object.repository_cells.empty? }
belongs_to :repository, key: :inventory,
serializer: InventorySerializer,
class_name: 'Repository',
if: -> { instance_options[:show_repository] }
end
end
end

View file

@ -5,6 +5,7 @@ module Api
class InventorySerializer < ActiveModel::Serializer
type :inventories
attributes :id, :name
belongs_to :created_by, serializer: UserSerializer
end
end
end

View file

@ -1,11 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class MyModuleGroupSerializer < ActiveModel::Serializer
type :task_groups
attributes :id, :experiment_id
belongs_to :experiment, serializer: ExperimentSerializer
end
end
end

View file

@ -1,12 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class MyModuleRepositoryRowSerializer < ActiveModel::Serializer
type :task_inventory_rows
attribute :repository_row_id, key: :inventory_row_id
attribute :my_module_id, key: :task_id
belongs_to :my_module, serializer: MyModuleSerializer
end
end
end

View file

@ -1,12 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class MyModuleSerializer < ActiveModel::Serializer
type :tasks
attributes :id, :name, :due_date, :description, :state
attribute :my_module_group_id, key: :task_group_id
belongs_to :experiment, serializer: ExperimentSerializer
end
end
end

View file

@ -1,13 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class MyModuleTagSerializer < ActiveModel::Serializer
type :task_tags
attributes :id, :tag_id
attribute :my_module_id, key: :task_id
belongs_to :my_module, serializer: MyModuleSerializer
end
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
module Api
module V1
class ProjectSerializer < ActiveModel::Serializer
type :projects
attributes :id, :name, :visibility, :due_date,
:archived
end
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Api
module V1
class ProtocolKeywordSerializer < ActiveModel::Serializer
type :protocol_keywords
attributes :id, :name
end
end
end

View file

@ -4,12 +4,14 @@ module Api
module V1
class ProtocolSerializer < ActiveModel::Serializer
type :protocols
attributes :id, :name, :authors, :description,
:team_id, :protocol_type,
:nr_of_linked_children
attribute :my_module_id, key: :task_id
belongs_to :my_module, serializer: MyModuleSerializer
attributes :id, :name, :authors, :description, :protocol_type
has_many :protocol_keywords,
key: :keywords,
serializer: ProtocolKeywordSerializer,
class_name: 'ProtocolKeyword',
unless: -> { object.protocol_keywords.empty? }
belongs_to :parent, serializer: ProtocolSerializer,
if: -> { object.parent.present? }
end
end
end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
module Api
module V1
class ReportSerializer < ActiveModel::Serializer
type :reports
attributes :id, :name, :description
belongs_to :user, serializer: UserSerializer
belongs_to :project, serializer: ProjectSerializer,
unless: -> { instance_options[:hide_project] }
end
end
end

View file

@ -23,7 +23,6 @@ module Api
elsif object.asset&.file&.is_stored_on_s3?
object.asset.presigned_url(download: true)
else
# separate api endpoint for local files download is needed
object.asset.file.url
end
end

View file

@ -3,8 +3,32 @@
module Api
module V1
class ResultAssetSerializer < ActiveModel::Serializer
type :result_assets
attributes :asset_id
type :result_files
attributes :file_id, :file_name, :file_size, :url
def file_id
object.asset&.id
end
def file_name
object.asset&.file_file_name
end
def file_size
object.asset&.file_file_size
end
def url
if !object.asset&.file_present
nil
elsif object.asset&.file&.is_stored_on_s3?
object.asset.presigned_url(download: true)
else
# TODO
# separate api endpoint for local files download is needed
'url'#download_asset_path(object.asset.id)
end
end
end
end
end

View file

@ -4,22 +4,20 @@ module Api
module V1
class ResultSerializer < ActiveModel::Serializer
type :results
attributes :name, :user_id, :archived
attribute :my_module_id, key: :task_id
belongs_to :my_module, serializer: MyModuleSerializer
has_one :result_asset, key: :asset,
serializer: ResultAssetSerializer,
class_name: 'ResultAsset',
if: -> { object.is_asset }
has_one :result_table, key: :table,
serializer: ResultTableSerializer,
class_name: 'ResultTable',
if: -> { object.is_table }
attributes :name, :archived
belongs_to :user, serializer: UserSerializer
has_one :result_text, key: :text,
serializer: ResultTextSerializer,
class_name: 'ResultText',
if: -> { object.is_text }
has_one :result_table, key: :table,
serializer: ResultTableSerializer,
class_name: 'ResultTable',
if: -> { object.is_table }
has_one :result_asset, key: :file,
serializer: ResultAssetSerializer,
class_name: 'ResultAsset',
if: -> { object.is_asset }
end
end
end

View file

@ -4,7 +4,15 @@ module Api
module V1
class ResultTableSerializer < ActiveModel::Serializer
type :result_tables
attributes :table_id
attributes :table_id, :table_contents
def table_id
object.table&.id
end
def table_contents
object.table&.contents
end
end
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Api
module V1
class TagSerializer < ActiveModel::Serializer
type :tags
attributes :id, :name, :color
end
end
end

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
module Api
module V1
class TaskGroupSerializer < ActiveModel::Serializer
type :task_groups
attributes :id
has_many :my_modules, key: :tasks,
serializer: TaskSerializer,
class_name: 'MyModule',
unless: -> { object.my_modules.empty? }
end
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Api
module V1
class TaskSerializer < ActiveModel::Serializer
type :tasks
attributes :id, :name, :due_date, :description, :state, :archived
end
end
end

View file

@ -4,6 +4,7 @@ module Api
module V1
class TeamSerializer < ActiveModel::Serializer
attributes :id, :name, :description, :space_taken
belongs_to :created_by, serializer: UserSerializer
end
end
end

View file

@ -1,13 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class UserMyModuleSerializer < ActiveModel::Serializer
type :user_tasks
attributes :id, :user_id
attribute :my_module_id, key: :task_id
belongs_to :my_module, serializer: MyModuleSerializer
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
module Api
module V1
class UserProjectSerializer < ActiveModel::Serializer
type :user_projects
attributes :id, :role
belongs_to :user, serializer: UserSerializer
end
end
end

View file

@ -8,11 +8,9 @@ Doorkeeper.configure do
end
# If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
# admin_authenticator do
# # Put your admin authentication logic here.
# # Example implementation:
# Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
# end
admin_authenticator do
current_user || redirect_to(new_admin_session_url)
end
# Authorization Code expiration time (default 10 minutes).
authorization_code_expires_in 10.minutes

View file

@ -61,7 +61,7 @@ class Extends
repository_asset_value: :asset]
# List of implemented core API versions
API_VERSIONS = ['20170715']
API_VERSIONS = ['v1']
# Array used for injecting names of additional authentication methods for API
API_PLUGABLE_AUTH_METHODS = [:azure_jwt_auth]

View file

@ -1943,12 +1943,6 @@ en:
status_ok: "Ok"
expired_token: "Token is expired"
invalid_token: "Token is invalid"
v1:
inventory_data_types:
t0: "text"
t1: "date"
t2: "list"
t3: "file"
Add: "Add"
Asset: "File"

View file

@ -567,52 +567,40 @@ Rails.application.routes.draw do
end
end
resources :projects, only: %i(index show) do
resources :user_projects, only: %i(index show),
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) do
resources :my_module_groups,
only: %i(index show),
path: 'task_groups',
as: :task_groups
resources :connections,
only: %i(index show),
path: 'connections',
as: :connections
resources :my_modules,
only: %i(index show),
path: 'tasks',
as: :tasks do
resources :my_module_repository_rows, only: %i(index show),
path: 'task_inventory_rows',
as: :task_inventory_rows
resources :user_my_modules, only: %i(index show),
path: 'user_tasks',
as: :user_tasks
resources :my_module_tags, only: %i(index show),
path: 'task_tags',
as: :task_tags
resources :protocols, only: %i(index show),
path: 'protocols',
as: :protocols
resources :results, only: %i(index create show),
path: 'results',
as: :results
get 'inputs',
to: 'my_modules#inputs'
get 'inputs/:id',
to: 'my_modules#input'
get 'outputs',
to: 'my_modules#outputs'
get 'outputs/:id',
to: 'my_modules#output'
resources :activities, only: %i(index show),
path: 'activities',
as: :activities
resources :task_groups, only: %i(index show)
resources :connections, only: %i(index show)
resources :tasks, only: %i(index show) do
resources :task_inventory_items, only: %i(index show),
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 :protocols, only: %i(index show)
resources :results, only: %i(index create show)
get 'inputs', to: 'tasks#inputs'
get 'outputs', to: 'tasks#outputs'
get 'activities', to: 'tasks#activities'
end
end
end
end
resources :users, only: %i(show) do
resources :user_identities,
only: %i(index create show update destroy)
only: %i(index create show update destroy),
path: 'identities',
as: :identities
end
end
end

View file

@ -16,8 +16,8 @@ describe Api::ApiController, type: :controller do
expect { hash_body = json }.not_to raise_exception
expect(hash_body).to match(
'message' => I18n.t('api.core.status_ok'),
'versions' => [{ 'version' => '20170715',
'baseUrl' => '/api/20170715/' }]
'versions' => [{ 'version' => 'v1',
'baseUrl' => '/api/v1/' }]
)
end
end

View file

@ -41,16 +41,9 @@ RSpec.describe 'Api::V1::InventoryColumnsController', type: :request do
ActiveModelSerializers::SerializableResource
.new(@valid_inventory.repository_columns.limit(10),
each_serializer: Api::V1::InventoryColumnSerializer,
include: :inventory_columns)
hide_list_items: true)
.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
@ -87,6 +80,100 @@ RSpec.describe 'Api::V1::InventoryColumnsController', type: :request do
end
end
describe 'GET inventory_column, #show' do
it 'Valid text column response' do
text_column = @valid_inventory.repository_columns.first
hash_body = nil
get api_v1_team_inventory_column_path(
id: text_column.id,
team_id: @teams.first.id,
inventory_id: @valid_inventory.id
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(text_column,
serializer: Api::V1::InventoryColumnSerializer)
.as_json[:data]
)
expect(hash_body[:data]).not_to include('relationships')
end
it 'Valid list column response' do
list_column = @valid_inventory.repository_columns.second
hash_body = nil
get api_v1_team_inventory_column_path(
id: list_column.id,
team_id: @teams.first.id,
inventory_id: @valid_inventory.id
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(list_column,
serializer: Api::V1::InventoryColumnSerializer)
.as_json[:data]
)
expect(hash_body[:data]).to include('relationships')
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 'Valid file column response' do
file_column = @valid_inventory.repository_columns.third
hash_body = nil
get api_v1_team_inventory_column_path(
id: file_column.id,
team_id: @teams.first.id,
inventory_id: @valid_inventory.id
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(file_column,
serializer: Api::V1::InventoryColumnSerializer)
.as_json[:data]
)
expect(hash_body[:data]).not_to include('relationships')
end
it 'Invalid request, non existing inventory column' do
get api_v1_team_inventory_column_path(
id: 1001,
team_id: @teams.first.id,
inventory_id: @teams.first.repositories.first.id
), headers: @valid_headers
expect(response).to have_http_status(404)
end
it 'When invalid request, incorrect repository' do
id = @teams.first.repositories.first.repository_columns.last.id
get api_v1_team_inventory_column_path(
id: id,
team_id: @teams.first.id,
inventory_id: @teams.second.repositories.first.id
), headers: @valid_headers
expect(response).to have_http_status(404)
expect(RepositoryColumn.where(id: id)).to exist
end
it 'When invalid request, repository from another team' do
id = @teams.first.repositories.first.repository_columns.last.id
get api_v1_team_inventory_column_path(
id: id,
team_id: @teams.second.id,
inventory_id: @teams.first.repositories.first.id
), headers: @valid_headers
expect(response).to have_http_status(403)
expect(RepositoryColumn.where(id: id)).to exist
end
end
describe 'POST inventory_column, #create' do
before :all do
@valid_headers['Content-Type'] = 'application/json'
@ -259,4 +346,80 @@ RSpec.describe 'Api::V1::InventoryColumnsController', type: :request do
expect(RepositoryColumn.where(id: deleted_id)).to exist
end
end
describe 'PATCH inventory_column, #update' do
before :all do
@valid_headers['Content-Type'] = 'application/json'
@inventory_column = ActiveModelSerializers::SerializableResource.new(
RepositoryColumn.last,
serializer: Api::V1::InventoryColumnSerializer
)
end
it 'Response with correctly updated inventory column' do
hash_body = nil
updated_inventory_column = @inventory_column.as_json
updated_inventory_column[:data][:attributes][:name] =
Faker::Name.unique.name
returned_inventory_column = updated_inventory_column.deep_dup
updated_inventory_column[:data][:attributes].delete(:data_type)
patch api_v1_team_inventory_column_path(
id: RepositoryColumn.last.id,
team_id: @teams.first.id,
inventory_id: @teams.first.repositories.first.id
), params: updated_inventory_column.to_json,
headers: @valid_headers
expect(response).to have_http_status 200
expect { hash_body = json }.not_to raise_exception
expect(hash_body.to_json).to match(returned_inventory_column.to_json)
end
it 'Invalid request, wrong team' do
hash_body = nil
updated_inventory_column = @inventory_column.as_json
updated_inventory_column[:data][:attributes][:name] =
Faker::Name.unique.name
patch api_v1_team_inventory_column_path(
id: RepositoryColumn.last.id,
team_id: @teams.second.id,
inventory_id: @teams.first.repositories.first.id
), params: updated_inventory_column.to_json,
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 'Invalid request, wrong inventory' do
hash_body = nil
updated_inventory_column = @inventory_column.as_json
updated_inventory_column[:data][:attributes][:name] =
Faker::Name.unique.name
patch api_v1_team_inventory_column_path(
id: RepositoryColumn.last.id,
team_id: @teams.second.id,
inventory_id: @teams.second.repositories.first.id
), params: updated_inventory_column.to_json,
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 'Invalid request, non-existent inventory' do
hash_body = nil
updated_inventory_column = @inventory_column.as_json
updated_inventory_column[:data][:attributes][:name] =
Faker::Name.unique.name
patch api_v1_team_inventory_column_path(
id: RepositoryColumn.last.id,
team_id: @teams.first.id,
inventory_id: 123
), params: updated_inventory_column.to_json,
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

View file

@ -75,6 +75,24 @@ RSpec.describe 'Api::V1::InventoryItemsController', type: :request do
include: :inventory_cells)
.as_json[:data]
)
expect(hash_body).not_to include('included')
end
it 'Response with correct inventory items, included cells' do
hash_body = nil
get api_v1_team_inventory_items_path(
team_id: @teams.first.id,
inventory_id: @teams.first.repositories.first.id,
include: 'inventory_cells'
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(@valid_inventory.repository_rows.limit(10),
each_serializer: Api::V1::InventoryItemSerializer,
include: :inventory_cells)
.as_json[:data]
)
expect(hash_body[:included]).to match(
ActiveModelSerializers::SerializableResource
.new(@valid_inventory.repository_rows.limit(10),
@ -98,13 +116,7 @@ RSpec.describe 'Api::V1::InventoryItemsController', type: :request do
include: :inventory_cells)
.as_json[:data]
)
expect(hash_body[:included]).to match(
ActiveModelSerializers::SerializableResource
.new(@valid_inventory.repository_rows.limit(100),
each_serializer: Api::V1::InventoryItemSerializer,
include: :inventory_cells)
.as_json[:included]
)
expect(hash_body).not_to include('included')
end
it 'When invalid request, user in not member of the team' do
@ -245,4 +257,30 @@ RSpec.describe 'Api::V1::InventoryItemsController', type: :request do
expect(hash_body).to match({})
end
end
describe 'PATCH inventory_items, #update' do
before :all do
@valid_headers['Content-Type'] = 'application/json'
@inventory_item = ActiveModelSerializers::SerializableResource.new(
RepositoryRow.last,
serializer: Api::V1::InventoryItemSerializer,
include: :inventory_cells
)
end
it 'Response with correctly updated inventory item for name field' do
hash_body = nil
updated_inventory_item = @inventory_item.as_json[:data]
updated_inventory_item[:attributes][:name] = Faker::Name.unique.name
patch api_v1_team_inventory_item_path(
id: RepositoryRow.last.id,
team_id: @teams.first.id,
inventory_id: @valid_inventory.id
), params: { data: updated_inventory_item }.to_json,
headers: @valid_headers
expect(response).to have_http_status 200
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data].to_json).to match(updated_inventory_item.to_json)
end
end
end

View file

@ -15,7 +15,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
describe 'GET user_identities, #index' do
it 'When valid request, requested identities for current user' do
hash_body = nil
get api_v1_user_user_identities_path(user_id: @user1.id),
get api_v1_user_identities_path(user_id: @user1.id),
headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
@ -28,7 +28,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
it 'When invalid request, requested user is not signed in user' do
hash_body = nil
get api_v1_user_user_identities_path(user_id: @user2.id),
get api_v1_user_identities_path(user_id: @user2.id),
headers: @valid_headers
expect(response).to have_http_status(403)
expect(hash_body).to match(nil)
@ -36,7 +36,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
it 'When invalid request, non existing user' do
hash_body = nil
get api_v1_user_user_identities_path(user_id: 123),
get api_v1_user_identities_path(user_id: 123),
headers: @valid_headers
expect(response).to have_http_status(403)
expect(hash_body).to match(nil)
@ -46,7 +46,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
describe 'POST user_identities, #create' do
it 'When valid request, create new identity for current user' do
hash_body = nil
post api_v1_user_user_identities_path(user_id: @user1.id),
post api_v1_user_identities_path(user_id: @user1.id),
params: {
data: { type: 'user_identities',
attributes: { uid: Faker::Crypto.unique.sha1,
@ -66,7 +66,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
describe 'GET user_identity, #show' do
it 'When valid request, requested specific identity for current user' do
hash_body = nil
get api_v1_user_user_identity_path(
get api_v1_user_identity_path(
user_id: @user1.id, id: @user1.user_identities.order(:id).last
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
@ -82,7 +82,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
describe 'PUT user_identities, #update' do
it 'When valid request, update identity for current user' do
hash_body = nil
put api_v1_user_user_identity_path(user_id: @user1.id,
put api_v1_user_identity_path(user_id: @user1.id,
id: @user1.user_identities.order(:id).last),
params: {
data: { id: @user1.user_identities.order(:id).last.id,
@ -103,7 +103,7 @@ RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
describe 'DELETE user_identity, #destroy' do
it 'When valid request, destroy specified identity for current user' do
identity = @user1.user_identities.order(:id).last
delete api_v1_user_user_identity_path(user_id: @user1.id, id: identity),
delete api_v1_user_identity_path(user_id: @user1.id, id: identity),
headers: @valid_headers
expect(response).to have_http_status(200)
expect(response.body).to eq('')