Merge remote-tracking branch 'upstream/develop' into neckbeard

This commit is contained in:
Your New SJW Waifu 2024-03-10 07:58:37 -05:00
commit 965ce9ae57
7 changed files with 146 additions and 25 deletions

View File

@ -0,0 +1 @@
Video framegrabs were not working correctly after the change to use Exile to execute ffmpeg

View File

@ -0,0 +1 @@
Verify profile link ownership with rel="me"

View File

@ -40,12 +40,14 @@ defmodule Pleroma.Helpers.MediaHelper do
end end
# Note: video thumbnail is intentionally not resized (always has original dimensions) # Note: video thumbnail is intentionally not resized (always has original dimensions)
@spec video_framegrab(String.t()) :: {:ok, binary()} | {:error, any()}
def video_framegrab(url) do def video_framegrab(url) do
with executable when is_binary(executable) <- System.find_executable("ffmpeg"), with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
{:ok, env} <- HTTP.get(url, [], pool: :media), {:ok, env} <- HTTP.get(url, [], pool: :media),
{:ok, pid} <- StringIO.open(env.body) do {:ok, pid} <- StringIO.open(env.body) do
body_stream = IO.binstream(pid, 1) body_stream = IO.binstream(pid, 1)
result =
Exile.stream!( Exile.stream!(
[ [
executable, executable,
@ -62,6 +64,8 @@ defmodule Pleroma.Helpers.MediaHelper do
stderr: :disable stderr: :disable
) )
|> Enum.into(<<>>) |> Enum.into(<<>>)
{:ok, result}
else else
nil -> {:error, {:ffmpeg, :command_not_found}} nil -> {:error, {:ffmpeg, :command_not_found}}
{:error, _} = error -> error {:error, _} = error -> error

View File

@ -8,6 +8,7 @@ defmodule Pleroma.User do
import Ecto.Changeset import Ecto.Changeset
import Ecto.Query import Ecto.Query
import Ecto, only: [assoc: 2] import Ecto, only: [assoc: 2]
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
alias Ecto.Multi alias Ecto.Multi
alias Pleroma.Activity alias Pleroma.Activity
@ -596,9 +597,23 @@ defmodule Pleroma.User do
defp put_fields(changeset) do defp put_fields(changeset) do
if raw_fields = get_change(changeset, :raw_fields) do if raw_fields = get_change(changeset, :raw_fields) do
old_fields = changeset.data.raw_fields
raw_fields = raw_fields =
raw_fields raw_fields
|> Enum.filter(fn %{"name" => n} -> n != "" end) |> Enum.filter(fn %{"name" => n} -> n != "" end)
|> Enum.map(fn field ->
previous =
old_fields
|> Enum.find(fn %{"value" => value} -> field["value"] == value end)
if previous && Map.has_key?(previous, "verified_at") do
field
|> Map.put("verified_at", previous["verified_at"])
else
field
end
end)
fields = fields =
raw_fields raw_fields
@ -1200,6 +1215,10 @@ defmodule Pleroma.User do
def update_and_set_cache(changeset) do def update_and_set_cache(changeset) do
with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
if get_change(changeset, :raw_fields) do
BackgroundWorker.enqueue("verify_fields_links", %{"user_id" => user.id})
end
set_cache(user) set_cache(user)
end end
end end
@ -1975,8 +1994,45 @@ defmodule Pleroma.User do
maybe_delete_from_db(user) maybe_delete_from_db(user)
end end
def perform(:verify_fields_links, user) do
profile_urls = [user.ap_id]
fields =
user.raw_fields
|> Enum.map(&verify_field_link(&1, profile_urls))
changeset =
user
|> update_changeset(%{raw_fields: fields})
with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
set_cache(user)
end
end
def perform(:set_activation_async, user, status), do: set_activation(user, status) def perform(:set_activation_async, user, status), do: set_activation(user, status)
defp verify_field_link(field, profile_urls) do
verified_at =
with %{"value" => value} <- field,
{:verified_at, nil} <- {:verified_at, Map.get(field, "verified_at")},
%{scheme: scheme, userinfo: nil, host: host}
when not_empty_string(host) and scheme in ["http", "https"] <-
URI.parse(value),
{:not_idn, true} <- {:not_idn, to_string(:idna.encode(host)) == host},
"me" <- Pleroma.Web.RelMe.maybe_put_rel_me(value, profile_urls) do
CommonUtils.to_masto_date(NaiveDateTime.utc_now())
else
{:verified_at, value} when not_empty_string(value) ->
value
_ ->
nil
end
Map.put(field, "verified_at", verified_at)
end
@spec external_users_query() :: Ecto.Query.t() @spec external_users_query() :: Ecto.Query.t()
def external_users_query do def external_users_query do
User.Query.build(%{ User.Query.build(%{
@ -2664,10 +2720,11 @@ defmodule Pleroma.User do
# - display name # - display name
def sanitize_html(%User{} = user, filter) do def sanitize_html(%User{} = user, filter) do
fields = fields =
Enum.map(user.fields, fn %{"name" => name, "value" => value} -> Enum.map(user.fields, fn %{"name" => name, "value" => value} = fields ->
%{ %{
"name" => name, "name" => name,
"value" => HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly) "value" => HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly),
"verified_at" => Map.get(fields, "verified_at")
} }
end) end)

View File

@ -40,6 +40,11 @@ defmodule Pleroma.Workers.BackgroundWorker do
Pleroma.FollowingRelationship.move_following(origin, target) Pleroma.FollowingRelationship.move_following(origin, target)
end end
def perform(%Job{args: %{"op" => "verify_fields_links", "user_id" => user_id}}) do
user = User.get_by_id(user_id)
User.perform(:verify_fields_links, user)
end
def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do
Instance.perform(:delete_instance, host) Instance.perform(:delete_instance, host)
end end

View File

@ -2928,4 +2928,51 @@ defmodule Pleroma.UserTest do
refute User.endorses?(user, pinned_user) refute User.endorses?(user, pinned_user)
end end
end end
test "it checks fields links for a backlink" do
user = insert(:user, ap_id: "https://social.example.org/users/lain")
fields = [
%{"name" => "Link", "value" => "http://example.com/rel_me/null"},
%{"name" => "Verified link", "value" => "http://example.com/rel_me/link"},
%{"name" => "Not a link", "value" => "i'm not a link"}
]
user
|> User.update_and_set_cache(%{raw_fields: fields})
ObanHelpers.perform_all()
user = User.get_cached_by_id(user.id)
assert [
%{"verified_at" => nil},
%{"verified_at" => verified_at},
%{"verified_at" => nil}
] = user.fields
assert is_binary(verified_at)
end
test "updating fields does not invalidate previously validated links" do
user = insert(:user, ap_id: "https://social.example.org/users/lain")
user
|> User.update_and_set_cache(%{
raw_fields: [%{"name" => "verified link", "value" => "http://example.com/rel_me/link"}]
})
ObanHelpers.perform_all()
%User{fields: [%{"verified_at" => verified_at}]} = user = User.get_cached_by_id(user.id)
user
|> User.update_and_set_cache(%{
raw_fields: [%{"name" => "Verified link", "value" => "http://example.com/rel_me/link"}]
})
user = User.get_cached_by_id(user.id)
assert [%{"verified_at" => ^verified_at}] = user.fields
end
end end

View File

@ -511,10 +511,15 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert account_data["fields"] == [ assert account_data["fields"] == [
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"}, %{
"name" => "<a href=\"http://google.com\">foo</a>",
"value" => "bar",
"verified_at" => nil
},
%{ %{
"name" => "link.io", "name" => "link.io",
"value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>) "value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>),
"verified_at" => nil
} }
] ]
@ -573,8 +578,8 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert account_data["fields"] == [ assert account_data["fields"] == [
%{"name" => ":firefox:", "value" => "is best 2hu"}, %{"name" => ":firefox:", "value" => "is best 2hu", "verified_at" => nil},
%{"name" => "they wins", "value" => ":blank:"} %{"name" => "they wins", "value" => ":blank:", "verified_at" => nil}
] ]
assert account_data["source"]["fields"] == [ assert account_data["source"]["fields"] == [
@ -602,10 +607,11 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert account["fields"] == [ assert account["fields"] == [
%{"name" => "foo", "value" => "bar"}, %{"name" => "foo", "value" => "bar", "verified_at" => nil},
%{ %{
"name" => "link", "name" => "link",
"value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>) "value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>),
"verified_at" => nil
} }
] ]
@ -627,7 +633,7 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert account["fields"] == [ assert account["fields"] == [
%{"name" => "foo", "value" => ""} %{"name" => "foo", "value" => "", "verified_at" => nil}
] ]
end end