diff --git a/Changelog.md b/Changelog.md index 9336f4075..8d530638a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,6 +21,7 @@ ## Features * Add a manifest.json file as a first step to make diaspora* a Progressive Web App [#7998](https://github.com/diaspora/diaspora/pull/7998) +* Allow `web+diaspora://` links to link to a profile with only the diaspora ID [#8000](https://github.com/diaspora/diaspora/pull/8000) # 0.7.10.0 diff --git a/app/services/diaspora_link_service.rb b/app/services/diaspora_link_service.rb index 1923aa01d..ca8ffea76 100644 --- a/app/services/diaspora_link_service.rb +++ b/app/services/diaspora_link_service.rb @@ -10,7 +10,11 @@ class DiasporaLinkService end def find_or_fetch_entity - entity_finder.find || fetch_entity + if type && guid + entity_finder.find || fetch_entity + elsif author + find_or_fetch_person + end end private @@ -28,6 +32,12 @@ class DiasporaLinkService @entity_finder ||= Diaspora::EntityFinder.new(type, guid) end + def find_or_fetch_person + Person.find_or_fetch_by_identifier(author) + rescue DiasporaFederation::Discovery::DiscoveryError + nil + end + def normalize link.gsub!(%r{^web\+diaspora://}, "diaspora://") || link.gsub!(%r{^//}, "diaspora://") || @@ -38,8 +48,10 @@ class DiasporaLinkService def parse normalize match = DiasporaFederation::Federation::DiasporaUrlParser::DIASPORA_URL_REGEX.match(link) - @author = match[1] - @type = match[2] - @guid = match[3] + if match + @author, @type, @guid = match.captures + else + @author = %r{^diaspora://(#{Validation::Rule::DiasporaId::DIASPORA_ID_REGEX})$}u.match(link)&.captures&.first + end end end diff --git a/spec/services/diaspora_link_service_spec.rb b/spec/services/diaspora_link_service_spec.rb index bde411a27..c65004e31 100644 --- a/spec/services/diaspora_link_service_spec.rb +++ b/spec/services/diaspora_link_service_spec.rb @@ -40,5 +40,33 @@ describe DiasporaLinkService do expect(service.find_or_fetch_entity).to be_nil end end + + context "with invalid links" do + it "returns nil when the link is invalid" do + service = described_class.new("web+diaspora://something_invalid") + expect(service.find_or_fetch_entity).to be_nil + end + + it "returns nil when the author is valid, but rest of the link is invalid" do + service = described_class.new("web+diaspora://#{alice.diaspora_handle}/foo/bar") + expect(service.find_or_fetch_entity).to be_nil + end + end + + context "with only a diaspora ID" do + let(:person) { FactoryGirl.create(:person) } + let(:link) { "diaspora://#{person.diaspora_handle}" } + + it "returns the person" do + expect(service.find_or_fetch_entity).to eq(person) + end + + it "returns nil when person is non fetchable" do + expect(Person).to receive(:find_or_fetch_by_identifier) + .with(person.diaspora_handle).and_raise(DiasporaFederation::Discovery::DiscoveryError) + + expect(service.find_or_fetch_entity).to be_nil + end + end end end