From a288708368e18bf59d7cea8a113628d0a5cb8bb3 Mon Sep 17 00:00:00 2001 From: ajugo Date: Wed, 3 May 2023 15:55:36 +0200 Subject: [PATCH] Add API endpoint for protocol templates [SCI-7456] (#5321) * Add API endpoint for protocol templates [SCI-7456] * Create protocol template api serializer [SCI-7456] --- .../api/v1/protocol_templates_controller.rb | 39 +++++++ app/models/user.rb | 2 +- .../api/v1/protocol_template_serializer.rb | 11 ++ spec/factories/protocols.rb | 18 +++ .../v1/protocol_templates_controller_spec.rb | 104 ++++++++++++++++++ 5 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 app/controllers/api/v1/protocol_templates_controller.rb create mode 100644 app/serializers/api/v1/protocol_template_serializer.rb create mode 100644 spec/requests/api/v1/protocol_templates_controller_spec.rb diff --git a/app/controllers/api/v1/protocol_templates_controller.rb b/app/controllers/api/v1/protocol_templates_controller.rb new file mode 100644 index 000000000..84cd32c4d --- /dev/null +++ b/app/controllers/api/v1/protocol_templates_controller.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Api + module V1 + class ProtocolTemplatesController < BaseController + include Api::V1::ExtraParams + + before_action :load_team + before_action only: :show do + load_protocol_template(:id) + end + + def index + protocol_templates = Protocol.latest_available_versions(@team) + .with_granted_permissions(current_user, ProtocolPermissions::READ) + .page(params.dig(:page, :number)) + .per(params.dig(:page, :size)) + + render jsonapi: protocol_templates, + each_serializer: ProtocolTemplateSerializer, rte_rendering: render_rte?, team: @team + end + + def show + render jsonapi: @protocol, + serializer: ProtocolTemplateSerializer, + include: include_params, + rte_rendering: render_rte?, + team: @team + end + + private + + def load_protocol_template(key = :protocol_id) + @protocol = @team.protocols.find(params.require(key)) + raise PermissionError.new(Protocol, :read) unless can_read_protocol_in_repository?(@protocol) + end + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 7a91cbd77..6529ecb19 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -383,7 +383,7 @@ class User < ApplicationRecord end def permission_team=(team) - @permission_team = teams.find(team.id) + @permission_team = teams.find_by(id: team.id) end def permission_team diff --git a/app/serializers/api/v1/protocol_template_serializer.rb b/app/serializers/api/v1/protocol_template_serializer.rb new file mode 100644 index 000000000..b8ee12250 --- /dev/null +++ b/app/serializers/api/v1/protocol_template_serializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Api + module V1 + class ProtocolTemplateSerializer < ProtocolSerializer + type :protocol_templates + attributes :version_number, :version_comment, :published_on, :archived + belongs_to :published_by, serializer: UserSerializer + end + end +end diff --git a/spec/factories/protocols.rb b/spec/factories/protocols.rb index eef9af1af..04fa32d74 100644 --- a/spec/factories/protocols.rb +++ b/spec/factories/protocols.rb @@ -16,5 +16,23 @@ FactoryBot.define do parent { create :protocol } added_by { create :user } end + + trait :in_repository_draft do + my_module { nil } + protocol_type { :in_repository_draft } + end + + trait :in_repository_published_original do + my_module { nil } + protocol_type { :in_repository_published_original } + version_number { 1 } + published_on { Time.now } + end + + trait :in_repository_published_version do + my_module { nil } + protocol_type { :in_repository_published_version } + published_on { Time.now } + end end end diff --git a/spec/requests/api/v1/protocol_templates_controller_spec.rb b/spec/requests/api/v1/protocol_templates_controller_spec.rb new file mode 100644 index 000000000..798c4f2fe --- /dev/null +++ b/spec/requests/api/v1/protocol_templates_controller_spec.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Api::V1::ProtocolTemplateController', type: :request do + before :all do + @user = create(:user) + @another_user = create(:user) + @team = create(:team, created_by: @user) + @team2 = create(:team, created_by: @another_user) + + @protocol_draft = create(:protocol, :in_repository_draft, team: @team, added_by: @user) + @protocol_published_original = create(:protocol, :in_repository_published_original, team: @team, added_by: @user) + @protocol_published = create(:protocol, :in_repository_published_version, team: @team, added_by: @user, parent: @protocol_published_original, version_number: 2) + @protocol_published_draft = create(:protocol, :in_repository_draft, team: @team, added_by: @user, + parent: @protocol_published_original, version_number: 3, name: @protocol_published_original.name) + + @protocol_draft_second_team = create(:protocol, :in_repository_draft, team: @team2, added_by: @another_user) + + @valid_headers = { 'Authorization': 'Bearer ' + generate_token(@user.id) } + end + + describe 'GET protocol template, #index' do + it 'Response with correct protocol templates' do + hash_body = nil + get api_v1_team_protocol_templates_path( + team_id: @team.id + ), headers: @valid_headers + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + JSON.parse( + ActiveModelSerializers::SerializableResource + .new(Protocol.latest_available_versions(@team), each_serializer: Api::V1::ProtocolTemplateSerializer) + .to_json + )['data'] + ) + end + + it 'When invalid request, user in not member of the team' do + hash_body = nil + get api_v1_team_protocol_templates_path( + team_id: @team2.id + ), headers: @valid_headers + + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing team' do + hash_body = nil + get api_v1_team_protocol_templates_path(team_id: -1), headers: @valid_headers + + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end + + describe 'GET protocol templates, #show' do + it 'When valid request, user can read protocol template' do + hash_body = nil + get api_v1_team_protocol_template_path(id: @protocol_published_original.id, team_id: @team.id), headers: @valid_headers + + expect { hash_body = json }.not_to raise_exception + expect(hash_body[:data]).to match( + JSON.parse( + ActiveModelSerializers::SerializableResource + .new(@protocol_published_original, serializer: Api::V1::ProtocolTemplateSerializer) + .to_json + )['data'] + ) + end + + it 'When invalid request, user in not member of the team' do + hash_body = nil + get api_v1_team_protocol_template_path(team_id: @team2.id, + id: @protocol_published.id), + headers: @valid_headers + expect(response).to have_http_status(403) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 403) + end + + it 'When invalid request, non existing protocol template' do + hash_body = nil + get api_v1_team_protocol_template_path(team_id: @team.id, id: -1), + headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + + it 'When invalid request, protocol template from another team' do + hash_body = nil + get api_v1_team_protocol_template_path(team_id: @team.id, + id: @protocol_draft_second_team.id), + headers: @valid_headers + expect(response).to have_http_status(404) + expect { hash_body = json }.not_to raise_exception + expect(hash_body['errors'][0]).to include('status': 404) + end + end +end