aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/tests/auth_test_controller.ex12
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/announce_validator.ex27
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/common_fixes.ex20
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex31
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/like_validator.ex50
-rw-r--r--lib/pleroma/web/metadata/providers/open_graph.ex61
-rw-r--r--lib/pleroma/web/metadata/providers/twitter_card.ex42
-rw-r--r--lib/pleroma/web/metadata/utils.ex5
8 files changed, 161 insertions, 87 deletions
diff --git a/lib/pleroma/tests/auth_test_controller.ex b/lib/pleroma/tests/auth_test_controller.ex
index ddf3fea4f..76514948b 100644
--- a/lib/pleroma/tests/auth_test_controller.ex
+++ b/lib/pleroma/tests/auth_test_controller.ex
@@ -9,7 +9,6 @@ defmodule Pleroma.Tests.AuthTestController do
use Pleroma.Web, :controller
alias Pleroma.User
- alias Pleroma.Web.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Web.Plugs.OAuthScopesPlug
# Serves only with proper OAuth token (:api and :authenticated_api)
@@ -47,10 +46,7 @@ defmodule Pleroma.Tests.AuthTestController do
# Via :authenticated_api, serves if token is present and has requested scopes
#
# Suggested use: as :fallback_oauth_check but open with nil :user for :api on private instances
- plug(
- :skip_plug,
- EnsurePublicOrAuthenticatedPlug when action == :fallback_oauth_skip_publicity_check
- )
+ plug(:skip_public_check when action == :fallback_oauth_skip_publicity_check)
plug(
OAuthScopesPlug,
@@ -62,11 +58,7 @@ defmodule Pleroma.Tests.AuthTestController do
# Via :authenticated_api, serves if :user is set (regardless of token presence and its scopes)
#
# Suggested use: making an :api endpoint always accessible (e.g. email confirmation endpoint)
- plug(
- :skip_plug,
- [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug]
- when action == :skip_oauth_skip_publicity_check
- )
+ plug(:skip_auth when action == :skip_oauth_skip_publicity_check)
# Via :authenticated_api, always fails with 403 (endpoint is insecure)
# Via :api, drops :user if present and serves if public (private instance rejects on no user)
diff --git a/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex b/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex
index a2f752ac3..4db76f387 100644
--- a/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex
@@ -8,6 +8,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
@@ -23,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
field(:type, :string)
field(:object, ObjectValidators.ObjectID)
field(:actor, ObjectValidators.ObjectID)
- field(:context, :string, autogenerate: {Utils, :generate_context_id, []})
+ field(:context, :string)
field(:to, ObjectValidators.Recipients, default: [])
field(:cc, ObjectValidators.Recipients, default: [])
field(:published, ObjectValidators.DateTime)
@@ -36,6 +37,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
end
def cast_data(data) do
+ data =
+ data
+ |> fix()
+
%__MODULE__{}
|> changeset(data)
end
@@ -43,11 +48,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
- |> fix_after_cast()
end
- def fix_after_cast(cng) do
- cng
+ defp fix(data) do
+ data =
+ data
+ |> CommonFixes.fix_actor()
+ |> CommonFixes.fix_activity_addressing()
+
+ with %Object{} = object <- Object.normalize(data["object"]) do
+ data
+ |> CommonFixes.fix_activity_context(object)
+ |> CommonFixes.fix_object_action_recipients(object)
+ else
+ _ -> data
+ end
end
defp validate_data(data_cng) do
@@ -60,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
|> validate_announcable()
end
- def validate_announcable(cng) do
+ defp validate_announcable(cng) do
with actor when is_binary(actor) <- get_field(cng, :actor),
object when is_binary(object) <- get_field(cng, :object),
%User{} = actor <- User.get_cached_by_ap_id(actor),
@@ -91,7 +106,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
end
end
- def validate_existing_announce(cng) do
+ defp validate_existing_announce(cng) do
actor = get_field(cng, :actor)
object = get_field(cng, :object)
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
index c958fcc5d..9631013a7 100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
+ alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Transmogrifier
@@ -36,7 +37,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
|> Transmogrifier.fix_implicit_addressing(follower_collection)
end
- def fix_activity_addressing(activity, _meta) do
+ def fix_activity_addressing(activity) do
%User{follower_address: follower_collection} = User.get_cached_by_ap_id(activity["actor"])
activity
@@ -57,4 +58,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
|> Map.put("actor", actor)
|> Map.put("attributedTo", actor)
end
+
+ def fix_activity_context(data, %Object{data: %{"context" => object_context}}) do
+ data
+ |> Map.put("context", object_context)
+ end
+
+ def fix_object_action_recipients(%{"actor" => actor} = data, %Object{data: %{"actor" => actor}}) do
+ to = ((data["to"] || []) -- [actor]) |> Enum.uniq()
+
+ Map.put(data, "to", to)
+ end
+
+ def fix_object_action_recipients(data, %Object{data: %{"actor" => actor}}) do
+ to = ((data["to"] || []) ++ [actor]) |> Enum.uniq()
+
+ Map.put(data, "to", to)
+ end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex
index ec7566515..a18bd7540 100644
--- a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
import Ecto.Changeset
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
@@ -31,6 +32,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
end
def cast_data(data) do
+ data =
+ data
+ |> fix()
+
%__MODULE__{}
|> changeset(data)
end
@@ -38,28 +43,24 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
- |> fix_after_cast()
- end
-
- def fix_after_cast(cng) do
- cng
- |> fix_context()
end
- def fix_context(cng) do
- object = get_field(cng, :object)
+ defp fix(data) do
+ data =
+ data
+ |> CommonFixes.fix_actor()
+ |> CommonFixes.fix_activity_addressing()
- with nil <- get_field(cng, :context),
- %Object{data: %{"context" => context}} <- Object.get_cached_by_ap_id(object) do
- cng
- |> put_change(:context, context)
+ with %Object{} = object <- Object.normalize(data["object"]) do
+ data
+ |> CommonFixes.fix_activity_context(object)
+ |> CommonFixes.fix_object_action_recipients(object)
else
- _ ->
- cng
+ _ -> data
end
end
- def validate_emoji(cng) do
+ defp validate_emoji(cng) do
content = get_field(cng, :content)
if Pleroma.Emoji.is_unicode_emoji?(content) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex
index 509da507b..8b99c89b9 100644
--- a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.Utils
import Ecto.Changeset
@@ -31,6 +32,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
end
def cast_data(data) do
+ data =
+ data
+ |> fix()
+
%__MODULE__{}
|> changeset(data)
end
@@ -38,41 +43,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
- |> fix_after_cast()
- end
-
- def fix_after_cast(cng) do
- cng
- |> fix_recipients()
- |> fix_context()
- end
-
- def fix_context(cng) do
- object = get_field(cng, :object)
-
- with nil <- get_field(cng, :context),
- %Object{data: %{"context" => context}} <- Object.get_cached_by_ap_id(object) do
- cng
- |> put_change(:context, context)
- else
- _ ->
- cng
- end
end
- def fix_recipients(cng) do
- to = get_field(cng, :to)
- cc = get_field(cng, :cc)
- object = get_field(cng, :object)
+ defp fix(data) do
+ data =
+ data
+ |> CommonFixes.fix_actor()
+ |> CommonFixes.fix_activity_addressing()
- with {[], []} <- {to, cc},
- %Object{data: %{"actor" => actor}} <- Object.get_cached_by_ap_id(object),
- {:ok, actor} <- ObjectValidators.ObjectID.cast(actor) do
- cng
- |> put_change(:to, [actor])
+ with %Object{} = object <- Object.normalize(data["object"]) do
+ data
+ |> CommonFixes.fix_activity_context(object)
+ |> CommonFixes.fix_object_action_recipients(object)
else
- _ ->
- cng
+ _ -> data
end
end
@@ -85,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
|> validate_existing_like()
end
- def validate_existing_like(%{changes: %{actor: actor, object: object}} = cng) do
+ defp validate_existing_like(%{changes: %{actor: actor, object: object}} = cng) do
if Utils.get_existing_like(actor, %{data: %{"id" => object}}) do
cng
|> add_error(:actor, "already liked this object")
@@ -95,5 +79,5 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
end
end
- def validate_existing_like(cng), do: cng
+ defp validate_existing_like(cng), do: cng
end
diff --git a/lib/pleroma/web/metadata/providers/open_graph.ex b/lib/pleroma/web/metadata/providers/open_graph.ex
index 18ddde84b..df0cca74a 100644
--- a/lib/pleroma/web/metadata/providers/open_graph.ex
+++ b/lib/pleroma/web/metadata/providers/open_graph.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
alias Pleroma.User
+ alias Pleroma.Web.MediaProxy
alias Pleroma.Web.Metadata
alias Pleroma.Web.Metadata.Providers.Provider
alias Pleroma.Web.Metadata.Utils
@@ -32,11 +33,11 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
property: "og:description",
content: scrubbed_content
], []},
- {:meta, [property: "og:type", content: "website"], []}
+ {:meta, [property: "og:type", content: "article"], []}
] ++
if attachments == [] or Metadata.activity_nsfw?(object) do
[
- {:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))],
+ {:meta, [property: "og:image", content: MediaProxy.preview_url(User.avatar_url(user))],
[]},
{:meta, [property: "og:image:width", content: 150], []},
{:meta, [property: "og:image:height", content: 150], []}
@@ -57,8 +58,9 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
], []},
{:meta, [property: "og:url", content: user.uri || user.ap_id], []},
{:meta, [property: "og:description", content: truncated_bio], []},
- {:meta, [property: "og:type", content: "website"], []},
- {:meta, [property: "og:image", content: Utils.attachment_url(User.avatar_url(user))], []},
+ {:meta, [property: "og:type", content: "article"], []},
+ {:meta, [property: "og:image", content: MediaProxy.preview_url(User.avatar_url(user))],
+ []},
{:meta, [property: "og:image:width", content: 150], []},
{:meta, [property: "og:image:height", content: 150], []}
]
@@ -69,28 +71,35 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
Enum.reduce(attachments, [], fn attachment, acc ->
rendered_tags =
Enum.reduce(attachment["url"], [], fn url, acc ->
- # TODO: Add additional properties to objects when we have the data available.
- # Also, Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image
+ # TODO: Whatsapp only wants JPEG or PNGs. It seems that if we add a second og:image
# object when a Video or GIF is attached it will display that in Whatsapp Rich Preview.
case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" ->
[
- {:meta, [property: "og:audio", content: Utils.attachment_url(url["href"])], []}
+ {:meta, [property: "og:audio", content: MediaProxy.url(url["href"])], []}
| acc
]
+ # Not using preview_url for this. It saves bandwidth, but the image dimensions will
+ # be wrong. We generate it on the fly and have no way to capture or analyze the
+ # image to get the dimensions. This can be an issue for apps/FEs rendering images
+ # in timelines too, but you can get clever with the aspect ratio metadata as a
+ # workaround.
"image" ->
[
- {:meta, [property: "og:image", content: Utils.attachment_url(url["href"])], []},
+ {:meta, [property: "og:image", content: MediaProxy.url(url["href"])], []},
{:meta, [property: "og:image:alt", content: attachment["name"]], []}
| acc
]
+ |> maybe_add_dimensions(url)
"video" ->
[
- {:meta, [property: "og:video", content: Utils.attachment_url(url["href"])], []}
+ {:meta, [property: "og:video", content: MediaProxy.url(url["href"])], []}
| acc
]
+ |> maybe_add_dimensions(url)
+ |> maybe_add_video_thumbnail(url)
_ ->
acc
@@ -102,4 +111,38 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
end
defp build_attachments(_), do: []
+
+ # We can use url["mediaType"] to dynamically fill the metadata
+ defp maybe_add_dimensions(metadata, url) do
+ type = url["mediaType"] |> String.split("/") |> List.first()
+
+ cond do
+ !is_nil(url["height"]) && !is_nil(url["width"]) ->
+ metadata ++
+ [
+ {:meta, [property: "og:#{type}:width", content: "#{url["width"]}"], []},
+ {:meta, [property: "og:#{type}:height", content: "#{url["height"]}"], []}
+ ]
+
+ true ->
+ metadata
+ end
+ end
+
+ # Media Preview Proxy makes thumbnails of videos without resizing, so we can trust the
+ # width and height of the source video.
+ defp maybe_add_video_thumbnail(metadata, url) do
+ cond do
+ Pleroma.Config.get([:media_preview_proxy, :enabled], false) ->
+ metadata ++
+ [
+ {:meta, [property: "og:image:width", content: "#{url["width"]}"], []},
+ {:meta, [property: "og:image:height", content: "#{url["height"]}"], []},
+ {:meta, [property: "og:image", content: MediaProxy.preview_url(url["href"])], []}
+ ]
+
+ true ->
+ metadata
+ end
+ end
end
diff --git a/lib/pleroma/web/metadata/providers/twitter_card.ex b/lib/pleroma/web/metadata/providers/twitter_card.ex
index 12c372d77..79183df86 100644
--- a/lib/pleroma/web/metadata/providers/twitter_card.ex
+++ b/lib/pleroma/web/metadata/providers/twitter_card.ex
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
alias Pleroma.User
+ alias Pleroma.Web.MediaProxy
alias Pleroma.Web.Metadata
alias Pleroma.Web.Metadata.Providers.Provider
alias Pleroma.Web.Metadata.Utils
@@ -48,14 +49,14 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
end
def image_tag(user) do
- {:meta, [property: "twitter:image", content: Utils.attachment_url(User.avatar_url(user))], []}
+ {:meta, [property: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))],
+ []}
end
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
Enum.reduce(attachments, [], fn attachment, acc ->
rendered_tags =
Enum.reduce(attachment["url"], [], fn url, acc ->
- # TODO: Add additional properties to objects when we have the data available.
case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" ->
[
@@ -66,26 +67,35 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
| acc
]
+ # Not using preview_url for this. It saves bandwidth, but the image dimensions will
+ # be wrong. We generate it on the fly and have no way to capture or analyze the
+ # image to get the dimensions. This can be an issue for apps/FEs rendering images
+ # in timelines too, but you can get clever with the aspect ratio metadata as a
+ # workaround.
"image" ->
[
{:meta, [property: "twitter:card", content: "summary_large_image"], []},
{:meta,
[
property: "twitter:player",
- content: Utils.attachment_url(url["href"])
+ content: MediaProxy.url(url["href"])
], []}
| acc
]
+ |> maybe_add_dimensions(url)
- # TODO: Need the true width and height values here or Twitter renders an iFrame with
- # a bad aspect ratio
"video" ->
+ # fallback to old placeholder values
+ height = url["height"] || 480
+ width = url["width"] || 480
+
[
{:meta, [property: "twitter:card", content: "player"], []},
{:meta, [property: "twitter:player", content: player_url(id)], []},
- {:meta, [property: "twitter:player:width", content: "480"], []},
- {:meta, [property: "twitter:player:height", content: "480"], []},
- {:meta, [property: "twitter:player:stream", content: url["href"]], []},
+ {:meta, [property: "twitter:player:width", content: "#{width}"], []},
+ {:meta, [property: "twitter:player:height", content: "#{height}"], []},
+ {:meta, [property: "twitter:player:stream", content: MediaProxy.url(url["href"])],
+ []},
{:meta,
[property: "twitter:player:stream:content_type", content: url["mediaType"]], []}
| acc
@@ -105,4 +115,20 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
defp player_url(id) do
Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice_player, id)
end
+
+ # Videos have problems without dimensions, but we used to not provide WxH for images.
+ # A default (read: incorrect) fallback for images is likely to cause rendering bugs.
+ defp maybe_add_dimensions(metadata, url) do
+ cond do
+ !is_nil(url["height"]) && !is_nil(url["width"]) ->
+ metadata ++
+ [
+ {:meta, [property: "twitter:player:width", content: "#{url["width"]}"], []},
+ {:meta, [property: "twitter:player:height", content: "#{url["height"]}"], []}
+ ]
+
+ true ->
+ metadata
+ end
+ end
end
diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex
index bc31d66b9..caca42934 100644
--- a/lib/pleroma/web/metadata/utils.ex
+++ b/lib/pleroma/web/metadata/utils.ex
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.Metadata.Utils do
alias Pleroma.Emoji
alias Pleroma.Formatter
alias Pleroma.HTML
- alias Pleroma.Web.MediaProxy
def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do
content
@@ -38,10 +37,6 @@ defmodule Pleroma.Web.Metadata.Utils do
def scrub_html(content), do: content
- def attachment_url(url) do
- MediaProxy.preview_url(url)
- end
-
def user_name_string(user) do
"#{user.name} " <>
if user.local do