diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 66e9403..46aba7d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,20 +1,25 @@ class ApplicationController < ActionController::API include ActionController::HttpAuthentication::Basic::ControllerMethods + include ApiAuthenticatable include Bolognese::DoiUtils include Bolognese::Utils - attr_accessor :username, :password + attr_accessor :username, :password, :bearer before_action :set_raven_context after_action :set_consumer_header - # check that username and password exist - # store them in instance variables used for calling MDS API - def authenticate_user_with_basic_auth! - @username, @password = ActionController::HttpAuthentication::Basic::user_name_and_password(request) + # check that Basic or Bearer credentials exist + # store them in instance variables used for calling DataCite API + def authenticate_request! + @bearer = bearer_token_from_request + return if @bearer.present? - request_http_basic_authentication(ENV["REALM"], "An Authentication object was not found in the SecurityContext") if @username.blank? || @password.blank? + @username, @password = basic_credentials_from_request + return if @username.present? && (@password.present? || self.class.api_key_username?(@username)) + + request_http_basic_authentication(ENV["REALM"], "An Authentication object was not found in the SecurityContext") end def set_consumer_header @@ -42,7 +47,7 @@ def route_not_found end if status == 401 - response.headers["WWW-Authenticate"] = "Basic realm=\"#{ENV['REALM']}\"" + response.headers["WWW-Authenticate"] = "Basic realm=\"#{ENV['REALM']}\", Bearer realm=\"#{ENV['REALM']}\"" response.headers.delete_if { |key| key == "X-Credential-Username" } message = "Bad credentials" elsif status == 403 @@ -82,4 +87,23 @@ def set_raven_context ) end end + + private + + def bearer_token_from_request + auth_header = request.authorization.to_s + return nil unless auth_header.match?(/\ABearer\s+/i) + + auth_header.sub(/\ABearer\s+/i, "").strip.presence + end + + def basic_credentials_from_request + auth_header = request.authorization.to_s + return ActionController::HttpAuthentication::Basic::user_name_and_password(request) unless auth_header.match?(/\ABasic\s+/i) + return ActionController::HttpAuthentication::Basic::user_name_and_password(request) if auth_header.start_with?("Basic ") + + raw_credentials = auth_header.sub(/\ABasic\s+/i, "").strip + decoded = Base64.decode64(raw_credentials) + decoded.split(":", 2) + end end diff --git a/app/controllers/concerns/api_authenticatable.rb b/app/controllers/concerns/api_authenticatable.rb new file mode 100644 index 0000000..215a34f --- /dev/null +++ b/app/controllers/concerns/api_authenticatable.rb @@ -0,0 +1,50 @@ +module ApiAuthenticatable + extend ActiveSupport::Concern + + class_methods do + def api_key_username?(username) + username.present? && username.length > 20 && username.match?(/\ADC\./i) + end + + def maremma_auth(options = {}) + return { bearer: options[:bearer] } if options[:bearer].present? + + username = options[:username] + password = options[:password] + if username.present? && (password.present? || api_key_username?(username)) + return { username: username, password: password.to_s } + end + + nil + end + + def missing_auth_response + OpenStruct.new(body: { "errors" => [{ "title" => "Authentication credentials missing" }] }) + end + + def with_maremma_auth(options = {}) + auth = maremma_auth(options) + return missing_auth_response if auth.blank? + + yield auth + end + + def client_relationship(auth) + return nil unless auth.key?(:username) + return nil if api_key_username?(auth[:username]) + + { + "client" => { + "data" => { + "type" => "clients", + "id" => auth[:username], + }, + }, + } + end + end + + def forward_auth_options + self.class.maremma_auth(bearer: bearer, username: username, password: password) + end +end \ No newline at end of file diff --git a/app/controllers/concerns/doiable.rb b/app/controllers/concerns/doiable.rb index 26db0c0..31265ed 100644 --- a/app/controllers/concerns/doiable.rb +++ b/app/controllers/concerns/doiable.rb @@ -1,5 +1,6 @@ module Doiable extend ActiveSupport::Concern + include ApiAuthenticatable included do def extract_url(doi: nil, data: nil) @@ -22,56 +23,51 @@ def extract_url(doi: nil, data: nil) end module ClassMethods - require "uri" def put_doi(doi, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - return OpenStruct.new(body: { "errors" => [{ "title" => "Not a valid HTTP(S) or FTP URL" }] }) unless /\A(http|https|ftp):\/\/[\S]+/.match(options[:url]) + with_maremma_auth(options) do |auth| + return OpenStruct.new(body: { "errors" => [{ "title" => "Not a valid HTTP(S) or FTP URL" }] }) unless /\A(http|https|ftp):\/\/[\S]+/.match(options[:url]) - data = { - "data" => { - "type" => "dois", - "attributes"=> { - "url" => options[:url], - "should_validate" => "true", - "source" => "mds", - "event" => "publish" - }, - "relationships"=> { - "client"=> { - "data"=> { - "type"=> "clients", - "id"=> options[:username] - } + data = { + "data" => { + "type" => "dois", + "attributes"=> { + "url" => options[:url], + "should_validate" => "true", + "source" => "mds", + "event" => "publish" } } } - } - url = "#{ENV['API_URL']}/dois/#{doi}" - Maremma.put(url, content_type: 'application/vnd.api+json', data: data.to_json, username: options[:username], password: options[:password]) + relationships = client_relationship(auth) + data["data"]["relationships"] = relationships if relationships + + url = "#{ENV['API_URL']}/dois/#{doi}" + Maremma.put(url, content_type: 'application/vnd.api+json', data: data.to_json, **auth) + end end def get_doi(doi, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/#{doi}/get-url" - Maremma.get(url, username: options[:username], password: options[:password]) + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/#{doi}/get-url" + Maremma.get(url, **auth) + end end def delete_doi(doi, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/#{doi}" - Maremma.delete(url, username: options[:username], password: options[:password]) + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/#{doi}" + Maremma.delete(url, **auth) + end end def get_dois(options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/get-dois" - Maremma.get(url, username: options[:username], password: options[:password]) + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/get-dois" + Maremma.get(url, **auth) + end end end end \ No newline at end of file diff --git a/app/controllers/concerns/mediable.rb b/app/controllers/concerns/mediable.rb index 167b1b0..8741595 100644 --- a/app/controllers/concerns/mediable.rb +++ b/app/controllers/concerns/mediable.rb @@ -1,57 +1,59 @@ module Mediable extend ActiveSupport::Concern + include ApiAuthenticatable module ClassMethods def create_media(doi, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - return OpenStruct.new(body: { "errors" => [{ "title" => "Media type and URL missing" }] }) unless options[:data].present? + with_maremma_auth(options) do |auth| + return OpenStruct.new(body: { "errors" => [{ "title" => "Media type and URL missing" }] }) unless options[:data].present? - media_type, url = options[:data].split("=") + media_type, url = options[:data].split("=") - data = { - "data" => { - "type" => "media", - "attributes"=> { + data = { + "data" => { + "type" => "media", + "attributes"=> { "mediaType" => media_type, - "url" => url + "url" => url + } } } - } - url = "#{ENV['API_URL']}/dois/#{doi}/media" - Maremma.post(url, content_type: 'application/vnd.api+json', data: data.to_json, username: options[:username], password: options[:password]) + url = "#{ENV['API_URL']}/dois/#{doi}/media" + Maremma.post(url, content_type: 'application/vnd.api+json', data: data.to_json, **auth) + end end def list_media(doi, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/#{doi}/media" - response = Maremma.get(url, content_type: 'application/vnd.api+json', username: options[:username], password: options[:password]) - return response unless response.body["data"].present? + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/#{doi}/media" + response = Maremma.get(url, content_type: 'application/vnd.api+json', **auth) + return response unless response.body["data"].present? - response.body["data"] = Array.wrap(response.body["data"]).map do |m| - "#{m.dig("attributes", "mediaType").to_s}=#{m.dig("attributes", "url").to_s}" - end.join("\n") - response + response.body["data"] = Array.wrap(response.body["data"]).map do |m| + "#{m.dig("attributes", "mediaType").to_s}=#{m.dig("attributes", "url").to_s}" + end.join("\n") + response + end end def get_media(doi, id, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/#{doi}/media/#{id}" - response = Maremma.get(url, content_type: 'application/vnd.api+json', username: options[:username], password: options[:password]) - return response unless response.body["data"].present? - - m = response.body["data"] - response.body["data"] = "#{m.dig("attributes", "mediaType").to_s}=#{m.dig("attributes", "url").to_s}" - response + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/#{doi}/media/#{id}" + response = Maremma.get(url, content_type: 'application/vnd.api+json', **auth) + return response unless response.body["data"].present? + + m = response.body["data"] + response.body["data"] = "#{m.dig("attributes", "mediaType").to_s}=#{m.dig("attributes", "url").to_s}" + response + end end def delete_media(doi, id, options={}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/#{doi}/media/#{id}" - response = Maremma.delete(url, content_type: 'application/vnd.api+json', username: options[:username], password: options[:password]) + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/#{doi}/media/#{id}" + Maremma.delete(url, content_type: 'application/vnd.api+json', **auth) + end end end end \ No newline at end of file diff --git a/app/controllers/concerns/metadatable.rb b/app/controllers/concerns/metadatable.rb index 2974ac7..9026c81 100644 --- a/app/controllers/concerns/metadatable.rb +++ b/app/controllers/concerns/metadatable.rb @@ -1,5 +1,6 @@ module Metadatable extend ActiveSupport::Concern + include ApiAuthenticatable require "bolognese" require "securerandom" @@ -98,70 +99,58 @@ module ClassMethods include Bolognese::DoiUtils def get_metadata(doi, options = {}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - url = "#{ENV['API_URL']}/dois/#{doi}" - Maremma.get(url, accept: "application/vnd.datacite.datacite+xml", username: options[:username], password: options[:password], raw: true) + with_maremma_auth(options) do |auth| + url = "#{ENV['API_URL']}/dois/#{doi}" + Maremma.get(url, accept: "application/vnd.datacite.datacite+xml", raw: true, **auth) + end end def create_metadata(doi, options = {}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - xml = options[:data].present? ? ::Base64.strict_encode64(options[:data]) : nil - - attributes = { - "doi" => doi, - "xml" => xml, - "should_validate" => "true", - "source" => "mds", - "event" => "show", - }.compact - - relationships = { - "client" => { + with_maremma_auth(options) do |auth| + xml = options[:data].present? ? ::Base64.strict_encode64(options[:data]) : nil + + attributes = { + "doi" => doi, + "xml" => xml, + "should_validate" => "true", + "source" => "mds", + "event" => "show", + }.compact + + data = { "data" => { - "type" => "clients", - "id" => options[:username], + "type" => "dois", + "attributes" => attributes, }, - }, - } - - data = { - "data" => { - "type" => "dois", - "attributes" => attributes, - "relationships" => relationships, - }, - } - - url = "#{ENV['API_URL']}/dois/#{doi}" - Maremma.put(url, content_type: "application/vnd.api+json", data: data.to_json, username: options[:username], password: options[:password]) + } + + relationships = client_relationship(auth) + data["data"]["relationships"] = relationships if relationships + + url = "#{ENV['API_URL']}/dois/#{doi}" + Maremma.put(url, content_type: "application/vnd.api+json", data: data.to_json, **auth) + end end def delete_metadata(doi, options = {}) - return OpenStruct.new(body: { "errors" => [{ "title" => "Username or password missing" }] }) unless options[:username].present? && options[:password].present? - - attributes = { - "event" => "hide", - } - - data = { - "data" => { - "type" => "dois", - "attributes" => attributes, - "relationships" => { - "client" => { - "data" => { - "type" => "clients", - "id" => options[:username], - }, - }, + with_maremma_auth(options) do |auth| + attributes = { + "event" => "hide", + } + + data = { + "data" => { + "type" => "dois", + "attributes" => attributes, }, - }, - } + } + + relationships = client_relationship(auth) + data["data"]["relationships"] = relationships if relationships - url = "#{ENV['API_URL']}/dois/#{doi}" - Maremma.patch(url, content_type: "application/vnd.api+json", data: data.to_json, username: options[:username], password: options[:password]) + url = "#{ENV['API_URL']}/dois/#{doi}" + Maremma.patch(url, content_type: "application/vnd.api+json", data: data.to_json, **auth) + end end end end diff --git a/app/controllers/dois_controller.rb b/app/controllers/dois_controller.rb index 5365433..bf6380b 100644 --- a/app/controllers/dois_controller.rb +++ b/app/controllers/dois_controller.rb @@ -1,12 +1,12 @@ class DoisController < ApplicationController include Doiable - prepend_before_action :authenticate_user_with_basic_auth! + prepend_before_action :authenticate_request! before_action :set_doi, only: %i(show destroy) before_action :set_raven_context, only: %i(update) def index - response = DoisController.get_dois(username: username, password: password) + response = DoisController.get_dois(**forward_auth_options) if response.status == 200 render plain: response.body.dig("data", "dois").join("\n"), status: :ok @@ -25,7 +25,7 @@ def index end def show - response = DoisController.get_doi(@doi, username: username, password: password) + response = DoisController.get_doi(@doi, **forward_auth_options) if response.status == 200 render plain: response.body.dig("data", "url"), status: :ok @@ -55,7 +55,7 @@ def update return head :bad_request end - response = DoisController.put_doi(doi, url: url, username: username, password: password) + response = DoisController.put_doi(doi, url: url, **forward_auth_options) if [200, 201].include?(response.status) render plain: "OK", status: :created elsif response.status == 401 @@ -73,7 +73,7 @@ def update end def destroy - response = DoisController.delete_doi(@doi, username: username, password: password) + response = DoisController.delete_doi(@doi, **forward_auth_options) if response.status == 204 render plain: "OK", status: :ok diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb index e34e228..e582c4e 100644 --- a/app/controllers/media_controller.rb +++ b/app/controllers/media_controller.rb @@ -1,12 +1,12 @@ class MediaController < ApplicationController include Mediable - prepend_before_action :authenticate_user_with_basic_auth! + prepend_before_action :authenticate_request! before_action :set_doi before_action :set_media, only: [:show, :destroy] def index - response = MediaController.list_media(@doi, username: username, password: password) + response = MediaController.list_media(@doi, **forward_auth_options) if response.status == 200 && response.body["data"].present? render plain: response.body["data"], status: :ok @@ -27,7 +27,7 @@ def index end def show - response = MediaController.get_media(@doi, @id, username: username, password: password) + response = MediaController.get_media(@doi, @id, **forward_auth_options) if response.status == 200 render plain: response.body["data"], status: :ok @@ -46,7 +46,7 @@ def show end def create - response = MediaController.create_media(@doi, data: safe_params[:data], username: username, password: password) + response = MediaController.create_media(@doi, data: safe_params[:data], **forward_auth_options) if [200, 201].include?(response.status) render plain: "OK", status: :ok @@ -65,7 +65,7 @@ def create end def destroy - response = MediaController.delete_media(@doi, @id, username: username, password: password) + response = MediaController.delete_media(@doi, @id, **forward_auth_options) if response.status == 204 render plain: "OK", status: :ok diff --git a/app/controllers/metadata_controller.rb b/app/controllers/metadata_controller.rb index d254d35..eb0ffd5 100644 --- a/app/controllers/metadata_controller.rb +++ b/app/controllers/metadata_controller.rb @@ -1,7 +1,7 @@ class MetadataController < ApplicationController include Metadatable - prepend_before_action :authenticate_user_with_basic_auth! + prepend_before_action :authenticate_request! before_action :set_doi, only: [:destroy] before_action :set_raven_context, only: [:create_metadata] @@ -9,7 +9,7 @@ def index @doi = validate_doi(params[:doi_id]) fail AbstractController::ActionNotFound unless @doi.present? - response = MetadataController.get_metadata(@doi, username: username, password: password) + response = MetadataController.get_metadata(@doi, **forward_auth_options) if response.status == 200 render xml: response.body["data"], status: :ok @@ -47,7 +47,7 @@ def create return end - response = MetadataController.create_metadata(@doi, data: safe_params[:data], username: username, password: password) + response = MetadataController.create_metadata(@doi, data: safe_params[:data], **forward_auth_options) if [200, 201].include?(response.status) render plain: "OK (" + response.body.dig("data", "id").upcase + ")", status: :created, location: ENV["MDS_URL"] + "/metadata/" + @doi @@ -64,7 +64,7 @@ def create end def destroy - response = MetadataController.delete_metadata(@doi, username: username, password: password) + response = MetadataController.delete_metadata(@doi, **forward_auth_options) if response.status == 200 render plain: "OK", status: :ok diff --git a/spec/concerns/doiable_spec.rb b/spec/concerns/doiable_spec.rb index 1f7785d..40e7f36 100644 --- a/spec/concerns/doiable_spec.rb +++ b/spec/concerns/doiable_spec.rb @@ -9,6 +9,35 @@ subject { DoisController } + context "api key auth" do + let(:api_key) { "DC.frSFkVLbXUY5hygoWay5R51cWvEMODw3" } + + it "forwards api key as basic username to API" do + basic = ::Base64.strict_encode64("#{api_key}:") + url = "#{ENV['API_URL']}/dois/#{doi}/get-url" + stub = stub_request(:get, url) + .with(headers: { "Authorization" => "Basic #{basic}" }) + .to_return(status: 404, body: { errors: [{ title: "Not found" }] }.to_json, headers: { "Content-Type" => "application/json" }) + + response = subject.get_doi(doi, username: api_key, password: nil) + expect(response.status).to eq(404) + expect(stub).to have_been_requested + end + end + + context "bearer auth" do + it "forwards bearer token to API" do + url = "#{ENV['API_URL']}/dois/#{doi}/get-url" + stub = stub_request(:get, url) + .with(headers: { "Authorization" => "Bearer test-api-key" }) + .to_return(status: 404, body: { errors: [{ title: "Not found" }] }.to_json, headers: { "Content-Type" => "application/json" }) + + response = subject.get_doi(doi, bearer: "test-api-key") + expect(response.status).to eq(404) + expect(stub).to have_been_requested + end + end + context "put_doi" do # it "should register" do # options = { url: url, username: username, password: password } @@ -26,7 +55,7 @@ it "no password" do options = { username: username, password: nil } - expect(subject.put_doi(doi, options).body.dig("errors")).to eq([{"title"=>"Username or password missing"}]) + expect(subject.put_doi(doi, options).body.dig("errors")).to eq([{"title"=>"Authentication credentials missing"}]) end end @@ -47,7 +76,7 @@ it "no password" do options = { username: username, password: nil } - expect(subject.get_dois(options).body.dig("errors")).to eq([{"title"=>"Username or password missing"}]) + expect(subject.get_dois(options).body.dig("errors")).to eq([{"title"=>"Authentication credentials missing"}]) end end @@ -76,7 +105,7 @@ it "no password" do options = { username: username, password: nil } - expect(subject.delete_doi(doi, options).body.dig("errors")).to eq([{"title"=>"Username or password missing"}]) + expect(subject.delete_doi(doi, options).body.dig("errors")).to eq([{"title"=>"Authentication credentials missing"}]) end end diff --git a/spec/concerns/mediable_spec.rb b/spec/concerns/mediable_spec.rb index 1c6a3e3..58d0036 100644 --- a/spec/concerns/mediable_spec.rb +++ b/spec/concerns/mediable_spec.rb @@ -10,6 +10,19 @@ subject { MediaController } + context "bearer auth" do + it "forwards bearer token to API" do + url = "#{ENV['API_URL']}/dois/#{doi}/media" + stub = stub_request(:get, url) + .with(headers: { "Authorization" => "Bearer test-api-key" }) + .to_return(status: 200, body: { data: [] }.to_json, headers: { "Content-Type" => "application/json" }) + + response = subject.list_media(doi, bearer: "test-api-key") + expect(response.status).to eq(200) + expect(stub).to have_been_requested + end + end + context "create_media" do it "should register" do options = { data: data, username: username, password: password } diff --git a/spec/concerns/metadatable_spec.rb b/spec/concerns/metadatable_spec.rb index 39634e6..cfb0c7f 100644 --- a/spec/concerns/metadatable_spec.rb +++ b/spec/concerns/metadatable_spec.rb @@ -14,6 +14,21 @@ let(:doiv3a) { "10.14454/0000-0003" } let(:doiv4a) { "10.14454/0000-0003" } + context "bearer auth" do + subject { MetadataController } + + it "forwards bearer token to API" do + url = "#{ENV['API_URL']}/dois/#{doi}" + stub = stub_request(:get, url) + .with(headers: { "Authorization" => "Bearer test-api-key" }) + .to_return(status: 404, body: { errors: [{ title: "Not found" }] }.to_json, headers: { "Content-Type" => "application/json" }) + + response = subject.get_metadata(doi, bearer: "test-api-key") + expect(response.status).to eq(404) + expect(stub).to have_been_requested + end + end + context "versions" do subject { MetadataController } diff --git a/spec/requests/doi_spec.rb b/spec/requests/doi_spec.rb index 8169dea..1573e20 100644 --- a/spec/requests/doi_spec.rb +++ b/spec/requests/doi_spec.rb @@ -3,6 +3,9 @@ describe "dois", type: :request, vcr: true do let(:credentials) { ::Base64.strict_encode64("#{ENV["MDS_USERNAME"]}:#{ENV["MDS_PASSWORD"]}") } let(:headers) { {"HTTP_AUTHORIZATION" => "Basic " + credentials } } + let(:bearer_headers) { { "HTTP_AUTHORIZATION" => "Bearer test-api-key" } } + let(:api_key) { "DC.frSFkVLbXUY5hygoWay5R51cWvEMODw3" } + let(:api_key_basic_headers) { { "HTTP_AUTHORIZATION" => "Basic " + ::Base64.strict_encode64("#{api_key}:") } } describe "authentication", type: :request do let(:doi) { "10.14454/05MB-Q396" } @@ -22,6 +25,20 @@ #expect(last_response.status).to eq(401) expect(last_response.body).to eq("Bad credentials") end + + it "accepts bearer token auth" do + get "/doi/xxx", nil, bearer_headers + + expect(last_response.status).to eq(404) + expect(last_response.body).to eq("DOI not found") + end + + it "accepts api key as basic username" do + get "/doi/xxx", nil, api_key_basic_headers + + expect(last_response.status).to eq(404) + expect(last_response.body).to eq("DOI not found") + end end describe "/doi", type: :request do diff --git a/spec/requests/media_spec.rb b/spec/requests/media_spec.rb index 191c3f8..4ae8dc4 100644 --- a/spec/requests/media_spec.rb +++ b/spec/requests/media_spec.rb @@ -2,6 +2,25 @@ describe "media", type: :request, vcr: true, order: :defined do let(:credentials) { ::Base64.strict_encode64("#{ENV["MDS_USERNAME"]}:#{ENV["MDS_PASSWORD"]}") } + let(:bearer_headers) { { "CONTENT_TYPE" => "text/plain;charset=UTF-8", "HTTP_AUTHORIZATION" => "Bearer test-api-key" } } + let(:api_key) { "DC.frSFkVLbXUY5hygoWay5R51cWvEMODw3" } + let(:api_key_basic_headers) { { "CONTENT_TYPE" => "text/plain;charset=UTF-8", "HTTP_AUTHORIZATION" => "Basic " + ::Base64.strict_encode64("#{api_key}:") } } + + describe "authentication", type: :request do + it "accepts bearer token auth" do + get "/media/xxx", nil, bearer_headers + + expect(last_response.status).to eq(404) + expect(last_response.body).to eq("DOI not found") + end + + it "accepts api key as basic username" do + get "/media/xxx", nil, api_key_basic_headers + + expect(last_response.status).to eq(404) + expect(last_response.body).to eq("DOI not found") + end + end describe "/media/10.0144/DUMMY.V0I1.45", type: :request do let(:doi_id) { "10.0144/DUMMY.V0I1.45" } diff --git a/spec/requests/metadata_spec.rb b/spec/requests/metadata_spec.rb index 23f4a9b..fdec47b 100644 --- a/spec/requests/metadata_spec.rb +++ b/spec/requests/metadata_spec.rb @@ -2,6 +2,25 @@ describe "metadata", type: :request, vcr: true, order: :defined do let(:credentials) { ::Base64.strict_encode64("#{ENV["MDS_USERNAME"]}:#{ENV["MDS_PASSWORD"]}") } + let(:bearer_headers) { { "ACCEPT" => "application/xml;charset=UTF-8", "HTTP_AUTHORIZATION" => "Bearer test-api-key" } } + let(:api_key) { "DC.frSFkVLbXUY5hygoWay5R51cWvEMODw3" } + let(:api_key_basic_headers) { { "ACCEPT" => "application/xml;charset=UTF-8", "HTTP_AUTHORIZATION" => "Basic " + ::Base64.strict_encode64("#{api_key}:") } } + + describe "authentication", type: :request do + it "accepts bearer token auth" do + get "/metadata/xxx", nil, bearer_headers + + expect(last_response.status).to eq(404) + expect(last_response.body).to eq("DOI not found") + end + + it "accepts api key as basic username" do + get "/metadata/xxx", nil, api_key_basic_headers + + expect(last_response.status).to eq(404) + expect(last_response.body).to eq("DOI not found") + end + end describe "/metadata/10.0144/DUMMY.V0I1.45", type: :request do let(:doi_id) { "10.0144/DUMMY.V0I1.45" }