2018-08-07 21:19:24 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-07-31 19:40:27 +08:00
|
|
|
module Api
|
|
|
|
module V1
|
|
|
|
class BaseController < ApiController
|
2018-10-23 23:52:48 +08:00
|
|
|
class TypeError < StandardError; end
|
2021-10-28 00:17:38 +08:00
|
|
|
|
2018-10-23 23:52:48 +08:00
|
|
|
class IDMismatchError < StandardError; end
|
2021-10-28 00:17:38 +08:00
|
|
|
|
2020-07-02 23:03:29 +08:00
|
|
|
class IncludeNotSupportedError < StandardError; end
|
2021-10-28 00:17:38 +08:00
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
class PermissionError < StandardError
|
2021-08-18 16:00:01 +08:00
|
|
|
attr_reader :klass, :mode
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def initialize(klass, mode)
|
|
|
|
@klass = klass
|
|
|
|
@mode = mode
|
|
|
|
end
|
|
|
|
end
|
2018-10-23 23:52:48 +08:00
|
|
|
|
|
|
|
rescue_from StandardError do |e|
|
2018-07-31 19:40:27 +08:00
|
|
|
logger.error e.message
|
2018-10-23 23:52:48 +08:00
|
|
|
logger.error e.backtrace.join("\n")
|
|
|
|
render_error(I18n.t('api.core.errors.general.title'),
|
|
|
|
I18n.t('api.core.errors.general.detail'),
|
|
|
|
:bad_request)
|
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
rescue_from PermissionError do |e|
|
|
|
|
model = e.klass.name.underscore
|
|
|
|
render_error(
|
|
|
|
I18n.t("api.core.errors.#{e.mode}_permission.title"),
|
|
|
|
I18n.t("api.core.errors.#{e.mode}_permission.detail", model: model),
|
|
|
|
:forbidden
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2018-10-23 23:52:48 +08:00
|
|
|
rescue_from TypeError do
|
|
|
|
render_error(I18n.t('api.core.errors.type.title'),
|
|
|
|
I18n.t('api.core.errors.type.detail'),
|
|
|
|
:bad_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
rescue_from IDMismatchError do
|
|
|
|
render_error(I18n.t('api.core.errors.id_mismatch.title'),
|
|
|
|
I18n.t('api.core.errors.id_mismatch.detail'),
|
|
|
|
:bad_request)
|
|
|
|
end
|
|
|
|
|
2020-07-02 23:03:29 +08:00
|
|
|
rescue_from NotImplementedError do
|
|
|
|
render_error(I18n.t('api.core.errors.not_implemented.title'),
|
|
|
|
I18n.t('api.core.errors.not_implemented.detail'),
|
|
|
|
:bad_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
rescue_from IncludeNotSupportedError do
|
|
|
|
render_error(I18n.t('api.core.errors.include_not_supported.title'),
|
|
|
|
I18n.t('api.core.errors.include_not_supported.detail'),
|
|
|
|
:bad_request)
|
|
|
|
end
|
|
|
|
|
2018-10-23 23:52:48 +08:00
|
|
|
rescue_from ActionController::ParameterMissing do |e|
|
|
|
|
render_error(
|
|
|
|
I18n.t('api.core.errors.parameter.title'), e.message, :bad_request
|
|
|
|
)
|
2018-07-31 19:40:27 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
rescue_from ActiveRecord::RecordNotFound do |e|
|
2018-10-23 23:52:48 +08:00
|
|
|
render_error(
|
|
|
|
I18n.t('api.core.errors.record_not_found.title'),
|
|
|
|
I18n.t('api.core.errors.record_not_found.detail',
|
|
|
|
model: e.model,
|
|
|
|
id: e.id),
|
|
|
|
:not_found
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
rescue_from ActiveRecord::RecordInvalid do |e|
|
|
|
|
render_error(
|
|
|
|
I18n.t('api.core.errors.validation.title'), e.message, :bad_request
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2018-11-28 21:14:45 +08:00
|
|
|
rescue_from JWT::DecodeError,
|
|
|
|
JWT::InvalidPayload,
|
|
|
|
JWT::VerificationError,
|
|
|
|
JWT::ExpiredSignature do |e|
|
|
|
|
render_error(
|
|
|
|
I18n.t('api.core.invalid_token'), e.message, :unauthorized
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2020-07-02 23:03:29 +08:00
|
|
|
before_action :check_include_param, only: %i(index show)
|
|
|
|
|
|
|
|
def index
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def show
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def create
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def update
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def destroy
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
2018-10-23 23:52:48 +08:00
|
|
|
private
|
|
|
|
|
|
|
|
def render_error(title, message, status)
|
|
|
|
logger.error message
|
|
|
|
render json: {
|
|
|
|
errors: [
|
|
|
|
{
|
|
|
|
id: request.uuid,
|
|
|
|
status: Rack::Utils.status_code(status),
|
|
|
|
title: title,
|
|
|
|
detail: message
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}, status: status
|
|
|
|
end
|
|
|
|
|
2020-07-02 23:03:29 +08:00
|
|
|
def check_include_param
|
|
|
|
return if params[:include].blank?
|
|
|
|
|
|
|
|
include_params
|
|
|
|
end
|
|
|
|
|
|
|
|
# redefine it in the specific controller if includes are used there
|
|
|
|
def permitted_includes
|
|
|
|
[]
|
|
|
|
end
|
|
|
|
|
|
|
|
def include_params
|
|
|
|
return nil if params[:include].blank?
|
|
|
|
|
|
|
|
provided_includes = params[:include].split(',')
|
|
|
|
raise IncludeNotSupportedError if (provided_includes - permitted_includes).any?
|
|
|
|
|
|
|
|
provided_includes
|
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_team(key = :team_id)
|
|
|
|
@team = Team.find(params.require(key))
|
2023-04-06 21:26:39 +08:00
|
|
|
current_user.permission_team = @team
|
2018-11-07 22:43:44 +08:00
|
|
|
raise PermissionError.new(Team, :read) unless can_read_team?(@team)
|
2018-10-23 23:52:48 +08:00
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_inventory(key = :inventory_id)
|
|
|
|
@inventory = @team.repositories.find(params.require(key))
|
2020-11-20 18:59:15 +08:00
|
|
|
raise PermissionError.new(Repository, :read) unless can_read_repository?(@inventory)
|
2018-10-23 23:52:48 +08:00
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_inventory_column(key = :column_id)
|
2020-11-20 18:59:15 +08:00
|
|
|
@inventory_column = @inventory.repository_columns.find(params.require(key))
|
2018-10-23 23:52:48 +08:00
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_inventory_item(key = :item_id)
|
2020-11-20 18:59:15 +08:00
|
|
|
@inventory_item = @inventory.repository_rows.find(params[key])
|
2018-10-23 23:52:48 +08:00
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_project(key = :project_id)
|
|
|
|
@project = @team.projects.find(params.require(key))
|
2019-09-17 19:02:38 +08:00
|
|
|
raise PermissionError.new(Project, :read) unless can_read_project?(@project)
|
2018-10-23 23:52:48 +08:00
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_experiment(key = :experiment_id)
|
|
|
|
@experiment = @project.experiments.find(params.require(key))
|
2019-09-17 19:02:38 +08:00
|
|
|
raise PermissionError.new(Experiment, :read) unless can_read_experiment?(@experiment)
|
2018-10-23 23:52:48 +08:00
|
|
|
end
|
|
|
|
|
2018-11-07 22:43:44 +08:00
|
|
|
def load_task(key = :task_id)
|
|
|
|
@task = @experiment.my_modules.find(params.require(key))
|
2021-10-28 20:48:28 +08:00
|
|
|
raise PermissionError.new(MyModule, :read) unless can_read_my_module?(@task)
|
2018-07-31 19:40:27 +08:00
|
|
|
end
|
2019-09-17 19:02:38 +08:00
|
|
|
|
|
|
|
def load_protocol(key = :protocol_id)
|
|
|
|
@protocol = @task.protocols.find(params.require(key))
|
|
|
|
raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_module?(@protocol)
|
|
|
|
end
|
|
|
|
|
|
|
|
def load_step(key = :step_id)
|
|
|
|
@step = @protocol.steps.find(params.require(key))
|
|
|
|
raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_module?(@step.protocol)
|
|
|
|
end
|
2020-07-02 23:03:29 +08:00
|
|
|
|
|
|
|
def load_table(key = :table_id)
|
|
|
|
@table = @step.tables.find(params.require(key))
|
|
|
|
raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_module?(@step.protocol)
|
|
|
|
end
|
|
|
|
|
|
|
|
def load_checklist(key = :checklist_id)
|
|
|
|
@checklist = @step.checklists.find(params.require(key))
|
|
|
|
raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_module?(@step.protocol)
|
|
|
|
end
|
|
|
|
|
2022-06-27 18:30:45 +08:00
|
|
|
def load_step_text(key = :step_text_id)
|
|
|
|
@step_text = @step.step_texts.find(params.require(key))
|
|
|
|
raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_module?(@step.protocol)
|
|
|
|
end
|
|
|
|
|
2020-07-02 23:03:29 +08:00
|
|
|
def load_checklist_item(key = :checklist_item_id)
|
|
|
|
@checklist_item = @checklist.checklist_items.find(params.require(key))
|
|
|
|
raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_module?(@step.protocol)
|
|
|
|
end
|
2020-08-20 21:49:48 +08:00
|
|
|
|
|
|
|
def load_workflow(key = :workflow_id)
|
|
|
|
@workflow = MyModuleStatusFlow.find(params.require(key))
|
|
|
|
end
|
2018-07-31 19:40:27 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|