forked from AkkomaGang/akkoma
Use info.fields instead of source_data for remote users
This commit is contained in:
parent
2c35d4b0b0
commit
f7bbf99caa
10 changed files with 91 additions and 39 deletions
|
@ -280,3 +280,31 @@ def scrub({tag, attributes, children}), do: {tag, attributes, children}
|
||||||
def scrub({_tag, children}), do: children
|
def scrub({_tag, children}), do: children
|
||||||
def scrub(text), do: text
|
def scrub(text), do: text
|
||||||
end
|
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
|
||||||
|
|
|
@ -50,6 +50,7 @@ defmodule Pleroma.User.Info do
|
||||||
field(:emoji, {:array, :map}, default: [])
|
field(:emoji, {:array, :map}, default: [])
|
||||||
field(:pleroma_settings_store, :map, default: %{})
|
field(:pleroma_settings_store, :map, default: %{})
|
||||||
field(:fields, {:array, :map}, default: [])
|
field(:fields, {:array, :map}, default: [])
|
||||||
|
field(:raw_fields, {:array, :map}, default: [])
|
||||||
|
|
||||||
field(:notification_settings, :map,
|
field(:notification_settings, :map,
|
||||||
default: %{
|
default: %{
|
||||||
|
@ -270,8 +271,10 @@ def user_upgrade(info, params) do
|
||||||
:follower_count,
|
:follower_count,
|
||||||
:following_count,
|
:following_count,
|
||||||
:hide_follows,
|
:hide_follows,
|
||||||
|
:fields,
|
||||||
:hide_followers
|
:hide_followers
|
||||||
])
|
])
|
||||||
|
|> validate_fields()
|
||||||
end
|
end
|
||||||
|
|
||||||
def profile_update(info, params) do
|
def profile_update(info, params) do
|
||||||
|
@ -288,6 +291,7 @@ def profile_update(info, params) do
|
||||||
:show_role,
|
:show_role,
|
||||||
:skip_thread_containment,
|
:skip_thread_containment,
|
||||||
:fields,
|
:fields,
|
||||||
|
:raw_fields,
|
||||||
:pleroma_settings_store
|
:pleroma_settings_store
|
||||||
])
|
])
|
||||||
|> validate_fields()
|
|> validate_fields()
|
||||||
|
@ -415,7 +419,7 @@ def remove_reblog_mute(info, ap_id) do
|
||||||
|
|
||||||
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
|
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
|
||||||
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
|
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
|
||||||
def fields(%{source_data: %{"attachment" => attachment}}) do
|
def fields(%{fields: [], source_data: %{"attachment" => attachment}}) do
|
||||||
attachment
|
attachment
|
||||||
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|
||||||
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
|
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
|
||||||
|
|
|
@ -598,13 +598,17 @@ def handle_incoming(
|
||||||
|
|
||||||
banner = new_user_data[:info][:banner]
|
banner = new_user_data[:info][:banner]
|
||||||
locked = new_user_data[:info][:locked] || false
|
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 =
|
update_data =
|
||||||
new_user_data
|
new_user_data
|
||||||
|> Map.take([:name, :bio, :avatar])
|
|> Map.take([:name, :bio, :avatar])
|
||||||
|> Map.put(:info, %{banner: banner, locked: locked})
|
|> Map.put(:info, %{banner: banner, locked: locked, fields: fields})
|
||||||
|> Map.put(:info, %{"banner" => banner, "locked" => locked, "source_data" => source_data})
|
|
||||||
|
|
||||||
actor
|
actor
|
||||||
|> User.upgrade_changeset(update_data)
|
|> User.upgrade_changeset(update_data)
|
||||||
|
|
|
@ -83,8 +83,13 @@ def render("user.json", %{user: user}) do
|
||||||
fields =
|
fields =
|
||||||
user.info
|
user.info
|
||||||
|> User.Info.fields()
|
|> 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(&Map.put(&1, "type", "PropertyValue"))
|
||||||
|> Enum.map(fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
"id" => user.ap_id,
|
"id" => user.ap_id,
|
||||||
|
|
|
@ -137,7 +137,9 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
|
||||||
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
|
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
|
||||||
|
|
||||||
user_info_emojis =
|
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()
|
|> Enum.dedup()
|
||||||
|
|
||||||
info_params =
|
info_params =
|
||||||
|
@ -157,16 +159,11 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do
|
||||||
end)
|
end)
|
||||||
|> add_if_present(params, "default_scope", :default_scope)
|
|> add_if_present(params, "default_scope", :default_scope)
|
||||||
|> add_if_present(params, "fields", :fields, fn fields ->
|
|> add_if_present(params, "fields", :fields, fn fields ->
|
||||||
fields =
|
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
||||||
Enum.map(fields, fn field ->
|
|
||||||
%{
|
|
||||||
"name" => Formatter.html_escape(field["name"], "text/plain"),
|
|
||||||
"value" => Formatter.html_escape(field["value"], "text/plain")
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
|
|
||||||
{:ok, fields}
|
{:ok, fields}
|
||||||
end)
|
end)
|
||||||
|
|> add_if_present(params, "fields", :raw_fields)
|
||||||
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
||||||
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -93,11 +93,19 @@ defp do_render("account.json", %{user: user} = opts) do
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
fields = User.Info.fields(user.info)
|
fields =
|
||||||
fields_html = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
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)
|
||||||
|
|
||||||
|
raw_fields = Map.get(user.info, :raw_fields, [])
|
||||||
|
|
||||||
bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
|
bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
|
||||||
|
|
||||||
relationship = render("relationship.json", %{user: opts[:for], target: user})
|
relationship = render("relationship.json", %{user: opts[:for], target: user})
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -117,12 +125,12 @@ defp do_render("account.json", %{user: user} = opts) do
|
||||||
header: header,
|
header: header,
|
||||||
header_static: header,
|
header_static: header,
|
||||||
emojis: emojis,
|
emojis: emojis,
|
||||||
fields: fields_html,
|
fields: fields,
|
||||||
bot: bot,
|
bot: bot,
|
||||||
source: %{
|
source: %{
|
||||||
note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
fields: fields,
|
fields: raw_fields,
|
||||||
pleroma: %{}
|
pleroma: %{}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,15 @@ defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
|> HTML.filter_tags(User.html_filter_policy(for_user))
|
|> HTML.filter_tags(User.html_filter_policy(for_user))
|
||||||
|> Formatter.emojify(emoji)
|
|> 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 =
|
data =
|
||||||
%{
|
%{
|
||||||
|
|
|
@ -518,9 +518,9 @@ test "it works with custom profile fields" do
|
||||||
|
|
||||||
user = User.get_cached_by_ap_id(activity.actor)
|
user = User.get_cached_by_ap_id(activity.actor)
|
||||||
|
|
||||||
assert user.info.source_data["attachment"] == [
|
assert User.Info.fields(user.info) == [
|
||||||
%{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
|
%{"name" => "foo", "value" => "bar"},
|
||||||
%{"name" => "foo1", "type" => "PropertyValue", "value" => "bar1"}
|
%{"name" => "foo1", "value" => "bar1"}
|
||||||
]
|
]
|
||||||
|
|
||||||
update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
|
update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
|
||||||
|
@ -539,9 +539,9 @@ test "it works with custom profile fields" do
|
||||||
|
|
||||||
user = User.get_cached_by_ap_id(user.ap_id)
|
user = User.get_cached_by_ap_id(user.ap_id)
|
||||||
|
|
||||||
assert user.info.source_data["attachment"] == [
|
assert User.Info.fields(user.info) == [
|
||||||
%{"name" => "foo", "type" => "PropertyValue", "value" => "updated"},
|
%{"name" => "foo", "value" => "updated"},
|
||||||
%{"name" => "foo1", "type" => "PropertyValue", "value" => "updated"}
|
%{"name" => "foo1", "value" => "updated"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -24,21 +24,16 @@ test "Renders a user, including the public key" do
|
||||||
|
|
||||||
test "Renders profile fields" do
|
test "Renders profile fields" do
|
||||||
fields = [
|
fields = [
|
||||||
%{"name" => "foo", "value" => "bar"},
|
%{"name" => "foo", "value" => "bar"}
|
||||||
%{"name" => "website", "value" => "cofe.my"}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
user = insert(:user, info: %{fields: fields})
|
{:ok, user} =
|
||||||
|
insert(:user)
|
||||||
|
|> User.upgrade_changeset(%{info: %{fields: fields}})
|
||||||
|
|> User.update_and_set_cache()
|
||||||
|
|
||||||
assert %{
|
assert %{
|
||||||
"attachment" => [
|
"attachment" => [%{"name" => "foo", "type" => "PropertyValue", "value" => "bar"}]
|
||||||
%{"name" => "foo", "type" => "PropertyValue", "value" => "bar"},
|
|
||||||
%{
|
|
||||||
"name" => "website",
|
|
||||||
"type" => "PropertyValue",
|
|
||||||
"value" => "<a href=\"http://cofe.my\">cofe.my</a>"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} = UserView.render("user.json", %{user: user})
|
} = UserView.render("user.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,7 @@ test "update fields", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
fields = [
|
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"}
|
%{"name" => "link", "value" => "cofe.io"}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -316,12 +316,15 @@ test "update fields", %{conn: conn} do
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert account["fields"] == [
|
assert account["fields"] == [
|
||||||
%{"name" => "<b>foo<b>", "value" => "<i>bar</i>"},
|
%{"name" => "foo", "value" => "bar"},
|
||||||
%{"name" => "link", "value" => "<a href=\"http://cofe.io\">cofe.io</a>"}
|
%{"name" => "link", "value" => "<a href=\"http://cofe.io\">cofe.io</a>"}
|
||||||
]
|
]
|
||||||
|
|
||||||
assert account["source"]["fields"] == [
|
assert account["source"]["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"}
|
%{"name" => "link", "value" => "cofe.io"}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue