diff --git a/app/models/concerns/helpable.rb b/app/models/concerns/helpable.rb index 2bf0a4b77..29c26af5f 100644 --- a/app/models/concerns/helpable.rb +++ b/app/models/concerns/helpable.rb @@ -23,6 +23,11 @@ def register_url return OpenStruct.new(body: { "errors" => [{ "title" => "Client ID missing." }] }) end + unless match_url_with_domains(url: url, domains: client.domains) + Rails.logger.error "[Handle] Error updating DOI " + doi + ": URL not allowed by client domains settings." + return OpenStruct.new(body: { "errors" => [{ "title" => "URL not allowed by client domains settings." }] }) + end + unless is_registered_or_findable? return OpenStruct.new(body: { "errors" => [{ "title" => "DOI is not registered or findable." }] }) end @@ -122,6 +127,23 @@ def https_to_http(url) uri.scheme = "http" uri.to_s end + + def match_url_with_domains(url: nil, domains: nil) + return false if url.blank? || domains.blank? + return true if domains == "*" + + uri = Addressable::URI.parse(url) + domain_list = domains.split(",") + domain_list.any? do |d| + # strip asterix for subdomain + if d.starts_with?("*.") + d = d[1..-1] + uri.host.ends_with?(d) + else + uri.host == d + end + end + end end module ClassMethods diff --git a/spec/concerns/helpable_spec.rb b/spec/concerns/helpable_spec.rb index 787c7328b..ec2d1cae2 100644 --- a/spec/concerns/helpable_spec.rb +++ b/spec/concerns/helpable_spec.rb @@ -81,6 +81,36 @@ end end + context "match_url_with_domains" do + it "url missing" do + domains = "*" + expect(subject.match_url_with_domains(domains: domains)).to be false + end + + it "domain missing" do + url = "https://blog.datacite.org/bla-bla" + expect(subject.match_url_with_domains(url: url)).to be false + end + + it "uses *" do + domains = "*" + url = "https://blog.datacite.org/bla-bla" + expect(subject.match_url_with_domains(domains: domains, url: url)).to be true + end + + it "specific host should be in list" do + domains = "blog.datacite.org,blog.example.com" + url = "https://blog.datacite.org/bla-bla" + expect(subject.match_url_with_domains(domains: domains, url: url)).to be true + end + + it "wildcard host should be in list" do + domains = "*.datacite.org,blog.example.com" + url = "https://blog.datacite.org/bla-bla" + expect(subject.match_url_with_domains(domains: domains, url: url)).to be true + end + end + context "register_doi", order: :defined do let(:provider) { create(:provider, symbol: "DATACITE") } let(:client) { create(:client, provider: provider, symbol: ENV['MDS_USERNAME']) } @@ -134,6 +164,24 @@ expect(response.body.dig("data", "values")).to eq([{"index"=>1, "type"=>"URL", "data"=>{"format"=>"string", "value"=>"https://blog.datacite.org/re3data-science-europe/"}, "ttl"=>86400, "timestamp"=>"2020-07-26T08:55:35Z"}]) end + it 'wrong domain' do + client = create(:client, provider: provider, symbol: ENV['MDS_USERNAME'], password: ENV['MDS_PASSWORD'], domains: "example.org") + subject = build(:doi, doi: "10.5438/mcnv-ga6n", url: "https://blog.datacite.org/", client: client, aasm_state: "findable") + expect(subject.register_url.body).to eq("errors"=>[{"title"=>"URL not allowed by client domains settings."}]) + end + + it 'wrong subdomain' do + client = create(:client, provider: provider, symbol: ENV['MDS_USERNAME'], password: ENV['MDS_PASSWORD'], domains: "datacite.org") + subject = build(:doi, doi: "10.5438/mcnv-ga6n", url: "https://blog.datacite.org/", client: client, aasm_state: "findable") + expect(subject.register_url.body).to eq("errors"=>[{"title"=>"URL not allowed by client domains settings."}]) + end + + it 'wildcard for subdomain but using naked domain' do + client = create(:client, provider: provider, symbol: ENV['MDS_USERNAME'], password: ENV['MDS_PASSWORD'], domains: "*.datacite.org") + subject = build(:doi, doi: "10.5438/mcnv-ga6n", url: "https://datacite.org/", client: client, aasm_state: "findable") + expect(subject.register_url.body).to eq("errors"=>[{"title"=>"URL not allowed by client domains settings."}]) + end + it 'draft doi' do subject = build(:doi, doi: "10.5438/mcnv-ga6n", url: "https://blog.datacite.org/", client: client, aasm_state: "draft") expect(subject.register_url.body).to eq("errors"=>[{"title"=>"DOI is not registered or findable."}])