diff --git a/test/pleroma/html_test.exs b/test/pleroma/html_test.exs index fe1a1ed57..beb482317 100644 --- a/test/pleroma/html_test.exs +++ b/test/pleroma/html_test.exs @@ -176,7 +176,7 @@ defmodule Pleroma.HTMLTest do }) object = Object.normalize(activity, fetch: false) - {:ok, url} = HTML.extract_first_external_url_from_object(object) + url = HTML.extract_first_external_url_from_object(object) assert url == "https://github.com/komeiji-satori/Dress" end @@ -191,7 +191,7 @@ defmodule Pleroma.HTMLTest do }) object = Object.normalize(activity, fetch: false) - {:ok, url} = HTML.extract_first_external_url_from_object(object) + url = HTML.extract_first_external_url_from_object(object) assert url == "https://github.com/syuilo/misskey/blob/develop/docs/setup.en.md" @@ -207,7 +207,7 @@ defmodule Pleroma.HTMLTest do }) object = Object.normalize(activity, fetch: false) - {:ok, url} = HTML.extract_first_external_url_from_object(object) + url = HTML.extract_first_external_url_from_object(object) assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140" end @@ -223,7 +223,7 @@ defmodule Pleroma.HTMLTest do }) object = Object.normalize(activity, fetch: false) - {:ok, url} = HTML.extract_first_external_url_from_object(object) + url = HTML.extract_first_external_url_from_object(object) assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140" end @@ -235,7 +235,7 @@ defmodule Pleroma.HTMLTest do object = Object.normalize(activity, fetch: false) - assert {:ok, nil} = HTML.extract_first_external_url_from_object(object) + assert nil == HTML.extract_first_external_url_from_object(object) end test "skips attachment links" do @@ -249,7 +249,7 @@ defmodule Pleroma.HTMLTest do object = Object.normalize(activity, fetch: false) - assert {:ok, nil} = HTML.extract_first_external_url_from_object(object) + assert nil == HTML.extract_first_external_url_from_object(object) end end end diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs index 22f65a0d1..ce251a7ba 100644 --- a/test/pleroma/web/mastodon_api/views/status_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/status_view_test.exs @@ -16,6 +16,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.StatusView + alias Pleroma.Web.RichMedia.Card import Pleroma.Factory import Tesla.Mock @@ -677,56 +678,88 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do describe "rich media cards" do test "a rich media card without a site name renders correctly" do - page_url = "http://example.com" + page_url = "https://example.com" - card = %{ - url: page_url, - image: page_url <> "/example.jpg", - title: "Example website" - } + {:ok, card} = + Card.create(page_url, %{image: page_url <> "/example.jpg", title: "Example website"}) - %{provider_name: "example.com"} = - StatusView.render("card.json", %{page_url: page_url, rich_media: card}) + %{provider_name: "example.com"} = StatusView.render("card.json", card) end test "a rich media card without a site name or image renders correctly" do - page_url = "http://example.com" + page_url = "https://example.com" - card = %{ - url: page_url, - title: "Example website" + fields = %{ + "url" => page_url, + "title" => "Example website" } - %{provider_name: "example.com"} = - StatusView.render("card.json", %{page_url: page_url, rich_media: card}) + {:ok, card} = Card.create(page_url, fields) + + %{provider_name: "example.com"} = StatusView.render("card.json", card) end test "a rich media card without an image renders correctly" do - page_url = "http://example.com" + page_url = "https://example.com" - card = %{ - url: page_url, - site_name: "Example site name", - title: "Example website" + fields = %{ + "url" => page_url, + "site_name" => "Example site name", + "title" => "Example website" } - %{provider_name: "example.com"} = - StatusView.render("card.json", %{page_url: page_url, rich_media: card}) + {:ok, card} = Card.create(page_url, fields) + + %{provider_name: "example.com"} = StatusView.render("card.json", card) end test "a rich media card with all relevant data renders correctly" do - page_url = "http://example.com" + page_url = "https://example.com" - card = %{ - url: page_url, - site_name: "Example site name", - title: "Example website", - image: page_url <> "/example.jpg", - description: "Example description" + fields = %{ + "url" => page_url, + "site_name" => "Example site name", + "title" => "Example website", + "image" => page_url <> "/example.jpg", + "description" => "Example description" } - %{provider_name: "example.com"} = - StatusView.render("card.json", %{page_url: page_url, rich_media: card}) + {:ok, card} = Card.create(page_url, fields) + + %{provider_name: "example.com"} = StatusView.render("card.json", card) + end + + test "a rich media card has all media proxied" do + clear_config([:media_proxy, :enabled], true) + clear_config([:media_preview_proxy, :enabled]) + + ConfigMock + |> stub_with(Pleroma.Test.StaticConfig) + + page_url = "https://example.com" + + fields = %{ + "url" => page_url, + "site_name" => "Example site name", + "title" => "Example website", + "image" => page_url <> "/example.jpg", + "audio" => page_url <> "/example.ogg", + "video" => page_url <> "/example.mp4", + "description" => "Example description" + } + + {:ok, card} = Card.create(page_url, fields) + + %{ + provider_name: "example.com", + image: image, + pleroma: %{opengraph: og} + } = StatusView.render("card.json", card) + + assert String.match?(image, ~r/\/proxy\//) + assert String.match?(og["image"], ~r/\/proxy\//) + assert String.match?(og["audio"], ~r/\/proxy\//) + assert String.match?(og["video"], ~r/\/proxy\//) end end diff --git a/test/pleroma/web/rich_media/card_test.exs b/test/pleroma/web/rich_media/card_test.exs new file mode 100644 index 000000000..6ad312748 --- /dev/null +++ b/test/pleroma/web/rich_media/card_test.exs @@ -0,0 +1,71 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2024 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.RichMedia.CardTest do + use Pleroma.DataCase, async: true + + alias Pleroma.UnstubbedConfigMock, as: ConfigMock + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.RichMedia.Card + + import Mox + import Pleroma.Factory + import Tesla.Mock + + setup do + mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + ConfigMock + |> stub_with(Pleroma.Test.StaticConfig) + + :ok + end + + setup do: clear_config([:rich_media, :enabled], true) + + test "crawls URL in activity" do + user = insert(:user) + + url = "https://example.com/ogp" + url_hash = Card.url_to_hash(url) + + {:ok, activity} = + CommonAPI.post(user, %{ + status: "[test](#{url})", + content_type: "text/markdown" + }) + + assert %Card{url_hash: ^url_hash, fields: _} = Card.get_by_activity(activity) + end + + test "recrawls URLs on updates" do + original_url = "https://google.com/" + original_url_hash = Card.url_to_hash(original_url) + updated_url = "https://yahoo.com/" + updated_url_hash = Card.url_to_hash(updated_url) + + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "I like this site #{original_url}"}) + + # Force a backfill + Card.get_by_activity(activity) + + assert match?( + %Card{url_hash: ^original_url_hash, fields: _}, + Card.get_by_activity(activity) + ) + + {:ok, _} = CommonAPI.update(user, activity, %{status: "I like this site #{updated_url}"}) + + activity = Pleroma.Activity.get_by_id(activity.id) + + # Force a backfill + Card.get_by_activity(activity) + + assert match?( + %Card{url_hash: ^updated_url_hash, fields: _}, + Card.get_by_activity(activity) + ) + end +end diff --git a/test/pleroma/web/rich_media/helpers_test.exs b/test/pleroma/web/rich_media/helpers_test.exs deleted file mode 100644 index 4d8a04788..000000000 --- a/test/pleroma/web/rich_media/helpers_test.exs +++ /dev/null @@ -1,91 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.RichMedia.HelpersTest do - use Pleroma.DataCase - - alias Pleroma.Web.CommonAPI - alias Pleroma.Web.RichMedia.Helpers - - import Pleroma.Factory - import Tesla.Mock - - setup do - mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) - - :ok - end - - setup do: clear_config([:rich_media, :enabled]) - - test "refuses to crawl incomplete URLs" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "[test](example.com/ogp)", - content_type: "text/markdown" - }) - - clear_config([:rich_media, :enabled], true) - - assert %{} == Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) - end - - test "refuses to crawl malformed URLs" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "[test](example.com[]/ogp)", - content_type: "text/markdown" - }) - - clear_config([:rich_media, :enabled], true) - - assert %{} == Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) - end - - test "crawls valid, complete URLs" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "[test](https://example.com/ogp)", - content_type: "text/markdown" - }) - - clear_config([:rich_media, :enabled], true) - - assert %{page_url: "https://example.com/ogp", rich_media: _} = - Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) - end - - test "refuses to crawl URLs of private network from posts" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{status: "http://127.0.0.1:4000/notice/9kCP7VNyPJXFOXDrgO"}) - - {:ok, activity2} = CommonAPI.post(user, %{status: "https://10.111.10.1/notice/9kCP7V"}) - {:ok, activity3} = CommonAPI.post(user, %{status: "https://172.16.32.40/notice/9kCP7V"}) - {:ok, activity4} = CommonAPI.post(user, %{status: "https://192.168.10.40/notice/9kCP7V"}) - {:ok, activity5} = CommonAPI.post(user, %{status: "https://pleroma.local/notice/9kCP7V"}) - - clear_config([:rich_media, :enabled], true) - - assert %{} = Helpers.fetch_data_for_activity(activity) - assert %{} = Helpers.fetch_data_for_activity(activity2) - assert %{} = Helpers.fetch_data_for_activity(activity3) - assert %{} = Helpers.fetch_data_for_activity(activity4) - assert %{} = Helpers.fetch_data_for_activity(activity5) - end - - test "catches errors in fetching" do - Tesla.Mock.mock(fn _ -> raise ArgumentError end) - - assert {:error, :fetch_error} == - Helpers.rich_media_get("wp-json/oembed/1.0/embed?url=http:%252F%252F") - end -end diff --git a/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs b/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs index 0c8203417..9acfe11c8 100644 --- a/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs +++ b/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs @@ -3,8 +3,22 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrlTest do - # Relies on Cachex, needs to be synchronous - use Pleroma.DataCase + use Pleroma.DataCase, async: false + use Oban.Testing, repo: Pleroma.Repo + + import Mox + + alias Pleroma.UnstubbedConfigMock, as: ConfigMock + alias Pleroma.Web.RichMedia.Card + + setup do + ConfigMock + |> stub_with(Pleroma.Test.StaticConfig) + + clear_config([:rich_media, :enabled], true) + + :ok + end test "s3 signed url is parsed correct for expiration time" do url = "https://pleroma.social/amz" @@ -43,26 +57,29 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrlTest do - + """ Tesla.Mock.mock(fn %{ method: :get, - url: "https://pleroma.social/amz" + url: ^url } -> %Tesla.Env{status: 200, body: body} + + %{method: :head} -> + %Tesla.Env{status: 200} end) - Cachex.put(:rich_media_cache, url, metadata) + Card.get_or_backfill_by_url(url) - Pleroma.Web.RichMedia.Parser.set_ttl_based_on_image(metadata, url) + assert_enqueued(worker: Pleroma.Workers.RichMediaExpirationWorker, args: %{"url" => url}) - {:ok, cache_ttl} = Cachex.ttl(:rich_media_cache, url) + [%Oban.Job{scheduled_at: scheduled_at}] = all_enqueued() - # as there is delay in setting and pulling the data from cache we ignore 1 second - # make it 2 seconds for flakyness - assert_in_delta(valid_till * 1000, cache_ttl, 2000) + timestamp_dt = Timex.parse!(timestamp, "{ISO:Basic:Z}") + + assert DateTime.diff(scheduled_at, timestamp_dt) == valid_till end defp construct_s3_url(timestamp, valid_till) do @@ -71,11 +88,11 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrlTest do defp construct_metadata(timestamp, valid_till, url) do %{ - image: construct_s3_url(timestamp, valid_till), - site: "Pleroma", - title: "Pleroma", - description: "Pleroma", - url: url + "image" => construct_s3_url(timestamp, valid_till), + "site" => "Pleroma", + "title" => "Pleroma", + "description" => "Pleroma", + "url" => url } end end diff --git a/test/pleroma/web/rich_media/parser_test.exs b/test/pleroma/web/rich_media/parser_test.exs index 426cc72e6..40d00a170 100644 --- a/test/pleroma/web/rich_media/parser_test.exs +++ b/test/pleroma/web/rich_media/parser_test.exs @@ -3,8 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.RichMedia.ParserTest do - use ExUnit.Case - + use Pleroma.DataCase alias Pleroma.Web.RichMedia.Parser setup do @@ -173,4 +172,27 @@ defmodule Pleroma.Web.RichMedia.ParserTest do test "does a HEAD request to check if the body is html" do assert {:error, {:content_type, _}} = Parser.parse("http://example.com/pdf-file") end + + test "refuses to crawl incomplete URLs" do + url = "example.com/ogp" + assert :error == Parser.parse(url) + end + + test "refuses to crawl malformed URLs" do + url = "example.com[]/ogp" + assert :error == Parser.parse(url) + end + + test "refuses to crawl URLs of private network from posts" do + [ + "http://127.0.0.1:4000/notice/9kCP7VNyPJXFOXDrgO", + "https://10.111.10.1/notice/9kCP7V", + "https://172.16.32.40/notice/9kCP7V", + "https://192.168.10.40/notice/9kCP7V", + "https://pleroma.local/notice/9kCP7V" + ] + |> Enum.each(fn url -> + assert :error == Parser.parse(url) + end) + end end