Use info.fields instead of source_data for remote users
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 6 Aug 2019 11:21:25 +0000 (18:21 +0700)
committerEgor Kislitsyn <egor@kislitsyn.com>
Wed, 14 Aug 2019 07:52:54 +0000 (14:52 +0700)
lib/pleroma/html.ex
lib/pleroma/user/info.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/activity_pub/views/user_view.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/account_view.ex
lib/pleroma/web/twitter_api/views/user_view.ex
test/web/activity_pub/transmogrifier_test.exs
test/web/activity_pub/views/user_view_test.exs
test/web/mastodon_api/mastodon_api_controller/update_credentials_test.exs

index 2fae7281c46c30134ec89edf4adc10267539cd9f..bf2000d904a3515a76b424fa51c0eb54dfa33bb9 100644 (file)
@@ -280,3 +280,31 @@ defmodule Pleroma.HTML.Transform.MediaProxy do
   def scrub({_tag, children}), do: children
   def scrub(text), do: text
 end
+
+defmodule Pleroma.HTML.Scrubber.LinksOnly do
+  @moduledoc """
+  An HTML scrubbing policy which limits to links only.
+  """
+
+  @valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
+
+  require HtmlSanitizeEx.Scrubber.Meta
+  alias HtmlSanitizeEx.Scrubber.Meta
+
+  Meta.remove_cdata_sections_before_scrub()
+  Meta.strip_comments()
+
+  # links
+  Meta.allow_tag_with_uri_attributes("a", ["href"], @valid_schemes)
+
+  Meta.allow_tag_with_this_attribute_values("a", "rel", [
+    "tag",
+    "nofollow",
+    "noopener",
+    "noreferrer",
+    "me"
+  ])
+
+  Meta.allow_tag_with_these_attributes("a", ["name", "title"])
+  Meta.strip_everything_not_covered()
+end
index e54243f06fc91b9525accd78da764778d825d2a7..ada9fb6897317adb85603cf8efeb13db66552e50 100644 (file)
@@ -50,6 +50,7 @@ defmodule Pleroma.User.Info do
     field(:emoji, {:array, :map}, default: [])
     field(:pleroma_settings_store, :map, default: %{})
     field(:fields, {:array, :map}, default: [])
+    field(:raw_fields, {:array, :map}, default: [])
 
     field(:notification_settings, :map,
       default: %{
@@ -270,8 +271,10 @@ defmodule Pleroma.User.Info do
       :follower_count,
       :following_count,
       :hide_follows,
+      :fields,
       :hide_followers
     ])
+    |> validate_fields()
   end
 
   def profile_update(info, params) do
@@ -288,6 +291,7 @@ defmodule Pleroma.User.Info do
       :show_role,
       :skip_thread_containment,
       :fields,
+      :raw_fields,
       :pleroma_settings_store
     ])
     |> validate_fields()
@@ -415,7 +419,7 @@ defmodule Pleroma.User.Info do
 
   # ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
   # For example: [{"name": "Pronoun", "value": "she/her"}, …]
-  def fields(%{source_data: %{"attachment" => attachment}}) do
+  def fields(%{fields: [], source_data: %{"attachment" => attachment}}) do
     attachment
     |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
     |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
index 225c34875841a20ecc9303a855c245839bcbc6f9..2be2e3294682438edf4cdd605440d301b6be4205 100644 (file)
@@ -598,13 +598,17 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
       banner = new_user_data[:info][:banner]
       locked = new_user_data[:info][:locked] || false
-      attachment = get_in(new_user_data, [:info, "source_data", "attachment"])
+      attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || []
+
+      fields =
+        attachment
+        |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
+        |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
 
       update_data =
         new_user_data
         |> Map.take([:name, :bio, :avatar])
-        |> Map.put(:info, %{banner: banner, locked: locked})
-        |> Map.put(:info, %{"banner" => banner, "locked" => locked, "source_data" => source_data})
+        |> Map.put(:info, %{banner: banner, locked: locked, fields: fields})
 
       actor
       |> User.upgrade_changeset(update_data)
index b2a22478d882b6696fe06d89d0c120845965088d..7be734b2604a73e917814a81364c43259e19b4f9 100644 (file)
@@ -83,8 +83,13 @@ defmodule Pleroma.Web.ActivityPub.UserView do
     fields =
       user.info
       |> User.Info.fields()
+      |> Enum.map(fn %{"name" => name, "value" => value} ->
+        %{
+          "name" => Pleroma.HTML.strip_tags(name),
+          "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
+        }
+      end)
       |> Enum.map(&Map.put(&1, "type", "PropertyValue"))
-      |> Enum.map(fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
 
     %{
       "id" => user.ap_id,
index e79a02caa6caff223c11be9a492a5a6b61163584..e8fac88808a680ac4859b56f71c92869046d71c8 100644 (file)
@@ -137,7 +137,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
 
     user_info_emojis =
-      ((user.info.emoji || []) ++ Formatter.get_emoji_map(emojis_text))
+      user.info
+      |> Map.get(:emoji, [])
+      |> Enum.concat(Formatter.get_emoji_map(emojis_text))
       |> Enum.dedup()
 
     info_params =
@@ -157,16 +159,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       end)
       |> add_if_present(params, "default_scope", :default_scope)
       |> add_if_present(params, "fields", :fields, fn fields ->
-        fields =
-          Enum.map(fields, fn field ->
-            %{
-              "name" => Formatter.html_escape(field["name"], "text/plain"),
-              "value" => Formatter.html_escape(field["value"], "text/plain")
-            }
-          end)
+        fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
 
         {:ok, fields}
       end)
+      |> add_if_present(params, "fields", :raw_fields)
       |> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
         {:ok, Map.merge(user.info.pleroma_settings_store, value)}
       end)
index d2f3986ff0476b4ec8f711dffe810c669f1d8817..a2297a8e84b363f95ee740a4ec194e186af734a4 100644 (file)
@@ -93,11 +93,19 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
         }
       end)
 
-    fields = User.Info.fields(user.info)
-    fields_html = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
+    fields =
+      user.info
+      |> User.Info.fields()
+      |> Enum.map(fn %{"name" => name, "value" => value} ->
+        %{
+          "name" => Pleroma.HTML.strip_tags(name),
+          "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
+        }
+      end)
 
-    bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
+    raw_fields = Map.get(user.info, :raw_fields, [])
 
+    bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
     relationship = render("relationship.json", %{user: opts[:for], target: user})
 
     %{
@@ -117,12 +125,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
       header: header,
       header_static: header,
       emojis: emojis,
-      fields: fields_html,
+      fields: fields,
       bot: bot,
       source: %{
         note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
         sensitive: false,
-        fields: fields,
+        fields: raw_fields,
         pleroma: %{}
       },
 
index 3681773bef83e32d0b272acd40f8a8c0f7abdb64..8a7d2fc72832b5a61a8394b8e8f6aac0071dd055 100644 (file)
@@ -74,7 +74,15 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
       |> HTML.filter_tags(User.html_filter_policy(for_user))
       |> Formatter.emojify(emoji)
 
-    fields = User.Info.fields(user.info)
+    fields =
+      user.info
+      |> User.Info.fields()
+      |> Enum.map(fn %{"name" => name, "value" => value} ->
+        %{
+          "name" => Pleroma.HTML.strip_tags(name),
+          "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
+        }
+      end)
 
     data =
       %{
index 05ec09ec12d4a9c6aac65d2233b11e7ec300bd11..7e2c8769d2132e47d54f495a92eea84f3a0882d8 100644 (file)
@@ -518,9 +518,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
 
       user = User.get_cached_by_ap_id(activity.actor)
 
-      assert user.info.source_data["attachment"] == [
-               %{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
-               %{"name" => "foo1", "type" => "PropertyValue", "value" => "bar1"}
+      assert User.Info.fields(user.info) == [
+               %{"name" => "foo", "value" => "bar"},
+               %{"name" => "foo1", "value" => "bar1"}
              ]
 
       update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
@@ -539,9 +539,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
 
       user = User.get_cached_by_ap_id(user.ap_id)
 
-      assert user.info.source_data["attachment"] == [
-               %{"name" => "foo", "type" => "PropertyValue", "value" => "updated"},
-               %{"name" => "foo1", "type" => "PropertyValue", "value" => "updated"}
+      assert User.Info.fields(user.info) == [
+               %{"name" => "foo", "value" => "updated"},
+               %{"name" => "foo1", "value" => "updated"}
              ]
     end
 
index a2aa5238126ba2bc519092d000be941f23aa52c0..fb7fd9e79f6bbf4fd0ff87a5c5b4c06ffe4fa136 100644 (file)
@@ -24,21 +24,16 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
 
   test "Renders profile fields" do
     fields = [
-      %{"name" => "foo", "value" => "bar"},
-      %{"name" => "website", "value" => "cofe.my"}
+      %{"name" => "foo", "value" => "bar"}
     ]
 
-    user = insert(:user, info: %{fields: fields})
+    {:ok, user} =
+      insert(:user)
+      |> User.upgrade_changeset(%{info: %{fields: fields}})
+      |> User.update_and_set_cache()
 
     assert %{
-             "attachment" => [
-               %{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
-               %{
-                 "name" => "website",
-                 "type" => "PropertyValue",
-                 "value" => "<a href=\"http://cofe.my\">cofe.my</a>"
-               }
-             ]
+             "attachment" => [%{"name" => "foo", "type" => "PropertyValue", "value" => "bar"}]
            } = UserView.render("user.json", %{user: user})
   end
 
index e75f25d51f2b2d4d2132ef5a9878d4c8765750d5..dd443495be2c68e1b26eee46e6c2d3cc87bb32bb 100644 (file)
@@ -305,7 +305,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
       user = insert(:user)
 
       fields = [
-        %{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
+        %{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
         %{"name" => "link", "value" => "cofe.io"}
       ]
 
@@ -316,12 +316,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
         |> json_response(200)
 
       assert account["fields"] == [
-               %{"name" => "&lt;b&gt;foo&lt;b&gt;", "value" => "&lt;i&gt;bar&lt;/i&gt;"},
+               %{"name" => "foo", "value" => "bar"},
                %{"name" => "link", "value" => "<a href=\"http://cofe.io\">cofe.io</a>"}
              ]
 
       assert account["source"]["fields"] == [
-               %{"name" => "&lt;b&gt;foo&lt;b&gt;", "value" => "&lt;i&gt;bar&lt;/i&gt;"},
+               %{
+                 "name" => "<a href=\"http://google.com\">foo</a>",
+                 "value" => "<script>bar</script>"
+               },
                %{"name" => "link", "value" => "cofe.io"}
              ]