From 56d4e3901217251b5fb19d3e688f376f5a8627c1 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 11 Feb 2019 22:27:02 +0100 Subject: [PATCH 1/8] Pleroma.User: Add rel=me to URLs where it linkbacks to the profile --- lib/pleroma/user.ex | 9 +++++++- lib/pleroma/web/rel_me.ex | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 lib/pleroma/web/rel_me.ex diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d58274508..b54613274 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -22,6 +22,7 @@ defmodule Pleroma.User do alias Pleroma.Web.OAuth alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.RelMe require Logger @@ -1202,8 +1203,14 @@ def parse_bio(bio, user) do {String.trim(name, ":"), url} end) + # TODO: get profile URLs other than user.ap_id + profile_urls = user[:ap_id] + bio - |> CommonUtils.format_input("text/plain", mentions_format: :full) + |> CommonUtils.format_input("text/plain", %{ + mentions_format: :full, + rel: &RelMe.maybe_put_rel_me(&1, profile_urls) + }) |> elem(0) |> Formatter.emojify(emoji) end diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex new file mode 100644 index 000000000..b23c49977 --- /dev/null +++ b/lib/pleroma/web/rel_me.ex @@ -0,0 +1,46 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.RelMe do + @hackney_options [ + pool: :media, + timeout: 2_000, + recv_timeout: 2_000, + max_body: 2_000_000 + ] + + def parse(nil), do: {:error, "No URL provided"} + + if Mix.env() == :test do + def parse(url), do: parse_url(url) + else + def parse(url) do + Cachex.fetch!(:rel_me_cache, url, fn _ -> + {:commit, parse_url(url)} + end) + rescue + e -> {:error, "Cachex error: #{inspect(e)}"} + end + end + + defp parse_url(url) do + {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options) + + Floki.attribute(html, "link[rel=me]", "href") ++ Floki.attribute(html, "a[rel=me]", "href") + rescue + e -> {:error, "Parsing error: #{inspect(e)}"} + end + + def maybe_put_rel_me("http" <> _ = target_page, urls) when not is_nil(urls) do + if Enum.any?(parse(target_page), fn x -> x in urls end) do + "rel=\"me\" " + else + "" + end + end + + def maybe_put_rel_me(_, _) do + "" + end +end From 25e588496adab62be79da65e8dc23426b8813159 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 06:13:04 +0100 Subject: [PATCH 2/8] Pleroma.Web.RelMeTest: Add test against Pleroma.Web.RelMe --- test/fixtures/rel_me_anchor.html | 14 +++++++++ test/fixtures/rel_me_link.html | 14 +++++++++ test/fixtures/rel_me_null.html | 13 ++++++++ test/web/rel_me_test.exs | 54 ++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 test/fixtures/rel_me_anchor.html create mode 100644 test/fixtures/rel_me_link.html create mode 100644 test/fixtures/rel_me_null.html create mode 100644 test/web/rel_me_test.exs diff --git a/test/fixtures/rel_me_anchor.html b/test/fixtures/rel_me_anchor.html new file mode 100644 index 000000000..5abcce129 --- /dev/null +++ b/test/fixtures/rel_me_anchor.html @@ -0,0 +1,14 @@ + + + + + Blog + + + + + diff --git a/test/fixtures/rel_me_link.html b/test/fixtures/rel_me_link.html new file mode 100644 index 000000000..b9ff18f6e --- /dev/null +++ b/test/fixtures/rel_me_link.html @@ -0,0 +1,14 @@ + + + + + Blog + + + +
+

Lorem ipsum

+

Lorem ipsum dolor sit ameph, …

+
+ + diff --git a/test/fixtures/rel_me_null.html b/test/fixtures/rel_me_null.html new file mode 100644 index 000000000..57d424b80 --- /dev/null +++ b/test/fixtures/rel_me_null.html @@ -0,0 +1,13 @@ + + + + + Blog + + +
+

Lorem ipsum

+

Lorem ipsum dolor sit ameph, …

+
+ + diff --git a/test/web/rel_me_test.exs b/test/web/rel_me_test.exs new file mode 100644 index 000000000..94cc01728 --- /dev/null +++ b/test/web/rel_me_test.exs @@ -0,0 +1,54 @@ +defmodule Pleroma.Web.RelMeTest do + use ExUnit.Case, async: true + + setup do + Tesla.Mock.mock(fn + %{ + method: :get, + url: "http://example.com/rel_me/anchor" + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_anchor.html")} + + %{ + method: :get, + url: "http://example.com/rel_me/link" + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_link.html")} + + %{ + method: :get, + url: "http://example.com/rel_me/null" + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_null.html")} + end) + + :ok + end + + test "parse/1" do + hrefs = ["https://social.example.org/users/lain"] + + assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/null") == {:ok, []} + assert {:error, _} = Pleroma.Web.RelMe.parse("http://example.com/rel_me/error") + + assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/link") == {:ok, hrefs} + assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/anchor") == {:ok, hrefs} + end + + test "maybe_put_rel_me/2" do + profile_urls = ["https://social.example.org/users/lain"] + attr = "rel=\"me\" " + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/null", profile_urls) == + "" + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/error", profile_urls) == + "" + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/anchor", profile_urls) == + attr + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/link", profile_urls) == + attr + end +end From 9b83236fb0292ae19a981b8f464183f8c6214a48 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 06:32:03 +0100 Subject: [PATCH 3/8] Pleroma.Web.RelMe: fixups --- lib/pleroma/web/rel_me.ex | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex index b23c49977..3f0ee9ac6 100644 --- a/lib/pleroma/web/rel_me.ex +++ b/lib/pleroma/web/rel_me.ex @@ -10,12 +10,10 @@ defmodule Pleroma.Web.RelMe do max_body: 2_000_000 ] - def parse(nil), do: {:error, "No URL provided"} - if Mix.env() == :test do - def parse(url), do: parse_url(url) + def parse(url) when is_binary(url), do: parse_url(url) else - def parse(url) do + def parse(url) when is_binary(url) do Cachex.fetch!(:rel_me_cache, url, fn _ -> {:commit, parse_url(url)} end) @@ -24,20 +22,27 @@ def parse(url) do end end + def parse(_), do: {:error, "No URL provided"} + defp parse_url(url) do {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options) - Floki.attribute(html, "link[rel=me]", "href") ++ Floki.attribute(html, "a[rel=me]", "href") + data = + Floki.attribute(html, "link[rel=me]", "href") ++ Floki.attribute(html, "a[rel=me]", "href") + + {:ok, data} rescue e -> {:error, "Parsing error: #{inspect(e)}"} end - def maybe_put_rel_me("http" <> _ = target_page, urls) when not is_nil(urls) do - if Enum.any?(parse(target_page), fn x -> x in urls end) do - "rel=\"me\" " - else - "" - end + def maybe_put_rel_me("http" <> _ = target_page, profile_urls) when is_list(profile_urls) do + {:ok, rel_me_hrefs} = parse(target_page) + + true = Enum.any?(rel_me_hrefs, fn x -> x in profile_urls end) + + "rel=\"me\" " + rescue + _ -> "" end def maybe_put_rel_me(_, _) do From 3d22642352b797c6963dba7c9116c27699d5c641 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 06:33:15 +0100 Subject: [PATCH 4/8] Pleroma.User: Pass an array to profile_urls --- lib/pleroma/user.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index b54613274..447beb25b 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1204,7 +1204,7 @@ def parse_bio(bio, user) do end) # TODO: get profile URLs other than user.ap_id - profile_urls = user[:ap_id] + profile_urls = [user[:ap_id]] bio |> CommonUtils.format_input("text/plain", %{ From 39a5bea9b73daa63203b0640d0a7906d6f1af143 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 06:57:28 +0100 Subject: [PATCH 5/8] Pleroma.User: Fix syntax and user.ap_id call --- lib/pleroma/user.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 447beb25b..a9592df6d 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1204,13 +1204,13 @@ def parse_bio(bio, user) do end) # TODO: get profile URLs other than user.ap_id - profile_urls = [user[:ap_id]] + profile_urls = [user.ap_id] bio - |> CommonUtils.format_input("text/plain", %{ + |> CommonUtils.format_input("text/plain", [ mentions_format: :full, rel: &RelMe.maybe_put_rel_me(&1, profile_urls) - }) + ]) |> elem(0) |> Formatter.emojify(emoji) end From 8e6f7fdb86bc7f90618c59ee4b13b30b94fda475 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 06:58:42 +0100 Subject: [PATCH 6/8] RelMe.maybe_put_rel_me/2: When true put "me" otherwise nil --- lib/pleroma/web/rel_me.ex | 6 +++--- test/web/rel_me_test.exs | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex index 3f0ee9ac6..a07db966f 100644 --- a/lib/pleroma/web/rel_me.ex +++ b/lib/pleroma/web/rel_me.ex @@ -40,12 +40,12 @@ def maybe_put_rel_me("http" <> _ = target_page, profile_urls) when is_list(profi true = Enum.any?(rel_me_hrefs, fn x -> x in profile_urls end) - "rel=\"me\" " + "me" rescue - _ -> "" + _ -> nil end def maybe_put_rel_me(_, _) do - "" + nil end end diff --git a/test/web/rel_me_test.exs b/test/web/rel_me_test.exs index 94cc01728..ba8038e69 100644 --- a/test/web/rel_me_test.exs +++ b/test/web/rel_me_test.exs @@ -37,13 +37,14 @@ test "parse/1" do test "maybe_put_rel_me/2" do profile_urls = ["https://social.example.org/users/lain"] - attr = "rel=\"me\" " + attr = "me" + fallback = nil assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/null", profile_urls) == - "" + fallback assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/error", profile_urls) == - "" + fallback assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/anchor", profile_urls) == attr From 7b9868f34344144bfb965cdd099f71b2617976c6 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 06:59:09 +0100 Subject: [PATCH 7/8] Pleroma.UserTest: Add tests for rel=me --- test/user_test.exs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/user_test.exs b/test/user_test.exs index cbe4693fc..e182a809f 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1039,6 +1039,22 @@ test "preserves hosts in user links text" do assert expected_text == User.parse_bio(bio, user) end + + test "Adds rel=me on linkbacked urls" do + user = insert(:user, ap_id: "http://social.example.org/users/lain") + + bio = "http://example.org/rel_me/null" + expected_text = "#{bio}" + assert expected_text == User.parse_bio(bio, user) + + bio = "http://example.org/rel_me/link" + expected_text = "#{bio}" + assert expected_text == User.parse_bio(bio, user) + + bio = "http://example.org/rel_me/anchor" + expected_text = "#{bio}" + assert expected_text == User.parse_bio(bio, user) + end end test "bookmarks" do From f2452d5700afc48284638ae2cd1bff4886571d8c Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Sat, 2 Mar 2019 07:04:49 +0100 Subject: [PATCH 8/8] Pleroma.User: mix format --- lib/pleroma/user.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index a9592df6d..6ec1033a5 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -1207,10 +1207,10 @@ def parse_bio(bio, user) do profile_urls = [user.ap_id] bio - |> CommonUtils.format_input("text/plain", [ + |> CommonUtils.format_input("text/plain", mentions_format: :full, rel: &RelMe.maybe_put_rel_me(&1, profile_urls) - ]) + ) |> elem(0) |> Formatter.emojify(emoji) end