{{ user.display_name }}
\nPassword reset token was generated: {{ passwordResetToken }}
\nYou can also use this link to reset password:\n {{ passwordResetLink }}\n
\n#{lines.value}
", attrs, [], lnb) + end + + ######## + # Html # + ######## + defp render_block(%Block.Html{html: html}, context) do + {context, html} + end + + defp render_block(%Block.HtmlComment{lines: lines}, context) do + {context, lines} + end + + defp render_block(%Block.HtmlOneline{html: html}, context) do + {context, html} + end + + ######### + # Ruler # + ######### + defp render_block(%Block.Ruler{lnb: lnb, attrs: attrs}, context) do + add_attrs(context, "#{body}" + add_attrs(context1, html, attrs, [], lnb) + end + + ######### + # Table # + ######### + + defp render_block( + %Block.Table{lnb: lnb, header: header, rows: rows, alignments: aligns, attrs: attrs}, + context + ) do + {context1, html} = add_attrs(context, "
]
+ lines = options.render_code.(block)
+ html = ~s[#{tag}#{lines}
]
+ add_attrs(context, html, attrs, [], lnb)
+ end
+
+ #########
+ # Lists #
+ #########
+
+ defp render_block(
+ %Block.List{lnb: lnb, type: type, blocks: items, attrs: attrs, start: start},
+ context
+ ) do
+ {context1, content} = render(items, context)
+ html = "<#{type}#{start}>#{content}#{type}>"
+ add_attrs(context1, html, attrs, [], lnb)
+ end
+
+ # format a single paragraph list item, and remove the para tags
+ defp render_block(
+ %Block.ListItem{lnb: lnb, blocks: blocks, spaced: false, attrs: attrs},
+ context
+ )
+ when length(blocks) == 1 do
+ {context1, content} = render(blocks, context)
+ content = Regex.replace(~r{?p>}, content, "")
+ html = "{:#{verbatim}}
"} + end + + #################### + # IDDef is ignored # + #################### + + defp render_block(%Block.IdDef{}, context), do: {context, ""} + + ##################################### + # And here are the inline renderers # + ##################################### + + defdelegate br, to: HtmlRenderer + defdelegate codespan(text), to: HtmlRenderer + defdelegate em(text), to: HtmlRenderer + defdelegate strong(text), to: HtmlRenderer + defdelegate strikethrough(text), to: HtmlRenderer + + defdelegate link(url, text), to: HtmlRenderer + defdelegate link(url, text, title), to: HtmlRenderer + + defdelegate image(path, alt, title), to: HtmlRenderer + + defdelegate footnote_link(ref, backref, number), to: HtmlRenderer + + # Table rows + defp add_trs(context, rows, tag, aligns, lnb) do + numbered_rows = + rows + |> Enum.zip(Stream.iterate(lnb, &(&1 + 1))) + + numbered_rows + |> Enum.reduce(context, fn {row, lnb}, ctx -> + append(add_tds(append(ctx, "Password reset token was generated: {{ passwordResetToken }}
\nYou can also use this link to reset password:\n {{ passwordResetLink }}\n
\nPassword reset token was generated: {{ passwordResetToken }}
\nYou can also use this link to reset password:\n {{ passwordResetLink }}\n
\n{{ $t('emoji.selectLocalPack') }}
\n{{ $t('emoji.specifyShortcode') }}
\n{{ $t('emoji.specifyFilename') }}
\nor
\n\n {{ $t('emoji.thisWillDownload') }} \"{{ name }}\" {{ $t('emoji.downloadToCurrentInstance') }}\n \"{{ downloadSharedAs.trim() === '' ? name : downloadSharedAs }}\" ({{ $t('emoji.canBeChanged') }}).\n {{ $t('emoji.willBeUsable') }}.\n
\n{{ $t('emoji.selectLocalPack') }}
\n{{ $t('emoji.specifyShortcode') }}
\n{{ $t('emoji.specifyFilename') }}
\nor
\n\n {{ $t('emoji.thisWillDownload') }} \"{{ name }}\" {{ $t('emoji.downloadToCurrentInstance') }}\n \"{{ downloadSharedAs.trim() === '' ? name : downloadSharedAs }}\" ({{ $t('emoji.canBeChanged') }}).\n {{ $t('emoji.willBeUsable') }}.\n
\nPassword reset token was generated: {{ passwordResetToken }}
\nYou can also use this link to reset password:\n {{ passwordResetLink }}\n
\n{{ this.$t('invites.token') }}: {{ newToken.token }}
\n{{ this.$t('invites.maxUse') }}: {{ newToken.maxUse }}
\n{{ this.$t('invites.expiresAt') }}: {{ newToken.expiresAt }}
\n{{ $t('invites.inviteViaEmailAlert') }}
\n{{ this.$t('invites.token') }}: {{ newToken.token }}
\n{{ this.$t('invites.maxUse') }}: {{ newToken.maxUse }}
\n{{ this.$t('invites.expiresAt') }}: {{ newToken.expiresAt }}
\n{{ $t('invites.inviteViaEmailAlert') }}
\nPassword reset token was generated: {{ passwordResetToken }}
\nYou can also use this link to reset password:\n {{ passwordResetLink }}\n
\n{{ $t('userProfile.noStatuses') }}
\nHello
World!
" + end + + test "raw HTML" do + code = ~s[OwO] + result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer}) + assert result == "#{code}
" + end + + test "rulers" do + code = ~s[before\n\n-----\n\nafter] + result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer}) + assert result == "before
after
" + end + + test "headings" do + code = ~s[# h1\n## h2\n### h3\n] + result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer}) + assert result == ~s[" + end + + test "code" do + code = ~s[`mix`] + result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer}) + assert result == ~s[whoms’t are you quoting?
mix
mix
puts "Hello World"
]
+ end
+
+ test "lists" do
+ code = ~s[- one\n- two\n- three\n- four]
+ result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer})
+ assert result == "#{code}
" + + code = ~s[*aaaa~*] + result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer}) + assert result == ~s[aaaa~
] + + code = ~s[**aaaa~**] + result = Earmark.as_html!(code, %Earmark.Options{renderer: Pleroma.EarmarkRenderer}) + assert result == ~s[aaaa~
] + + # strikethrought + code = ~s[aaaa~
This is a test Audio for Pleroma.
", + "mediaType": "text/html", + "tag": [ + { + "type": "Hashtag", + "name": "#funkwhale" + }, + { + "type": "Hashtag", + "name": "#test" + }, + { + "type": "Hashtag", + "name": "#tests" + } + ], + "summary": "#funkwhale #test #tests", + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers" + } + ] +} diff --git a/test/fixtures/tesla_mock/funkwhale_channel.json b/test/fixtures/tesla_mock/funkwhale_channel.json new file mode 100644 index 000000000..cf9ee8151 --- /dev/null +++ b/test/fixtures/tesla_mock/funkwhale_channel.json @@ -0,0 +1,44 @@ +{ + "id": "https://channels.tests.funkwhale.audio/federation/actors/compositions", + "outbox": "https://channels.tests.funkwhale.audio/federation/actors/compositions/outbox", + "inbox": "https://channels.tests.funkwhale.audio/federation/actors/compositions/inbox", + "preferredUsername": "compositions", + "type": "Person", + "name": "Compositions", + "followers": "https://channels.tests.funkwhale.audio/federation/actors/compositions/followers", + "following": "https://channels.tests.funkwhale.audio/federation/actors/compositions/following", + "manuallyApprovesFollowers": false, + "url": [ + { + "type": "Link", + "href": "https://channels.tests.funkwhale.audio/channels/compositions", + "mediaType": "text/html" + }, + { + "type": "Link", + "href": "https://channels.tests.funkwhale.audio/api/v1/channels/compositions/rss", + "mediaType": "application/rss+xml" + } + ], + "icon": { + "type": "Image", + "url": "https://channels.tests.funkwhale.audio/media/attachments/75/b4/f1/nosmile.jpeg", + "mediaType": "image/jpeg" + }, + "summary": "I'm testing federation with the fediverse :)
", + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers" + } + ], + "publicKey": { + "owner": "https://channels.tests.funkwhale.audio/federation/actors/compositions", + "publicKeyPem": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAv25u57oZfVLV3KltS+HcsdSx9Op4MmzIes1J8Wu8s0KbdXf2zEwS\nsVqyHgs/XCbnzsR3FqyJTo46D2BVnvZcuU5srNcR2I2HMaqQ0oVdnATE4K6KdcgV\nN+98pMWo56B8LTgE1VpvqbsrXLi9jCTzjrkebVMOP+ZVu+64v1qdgddseblYMnBZ\nct0s7ONbHnqrWlTGf5wES1uIZTVdn5r4MduZG+Uenfi1opBS0lUUxfWdW9r0oF2b\nyneZUyaUCbEroeKbqsweXCWVgnMarUOsgqC42KM4cf95lySSwTSaUtZYIbTw7s9W\n2jveU/rVg8BYZu5JK5obgBoxtlUeUoSswwIDAQAB\n-----END RSA PUBLIC KEY-----\n", + "id": "https://channels.tests.funkwhale.audio/federation/actors/compositions#main-key" + }, + "endpoints": { + "sharedInbox": "https://channels.tests.funkwhale.audio/federation/shared/inbox" + } +} diff --git a/test/http/request_builder_test.exs b/test/http/request_builder_test.exs index 11a9314ae..bf3a15ebe 100644 --- a/test/http/request_builder_test.exs +++ b/test/http/request_builder_test.exs @@ -8,8 +8,8 @@ defmodule Pleroma.HTTP.RequestBuilderTest do alias Pleroma.HTTP.RequestBuilder describe "headers/2" do - clear_config([:http, :send_user_agent]) - clear_config([:http, :user_agent]) + setup do: clear_config([:http, :send_user_agent]) + setup do: clear_config([:http, :user_agent]) test "don't send pleroma user agent" do assert RequestBuilder.headers(%{}, []) == %{headers: []} diff --git a/test/notification_test.exs b/test/notification_test.exs index 56a581810..d87eca836 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -6,12 +6,14 @@ defmodule Pleroma.NotificationTest do use Pleroma.DataCase import Pleroma.Factory + import Mock alias Pleroma.Notification alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.CommonAPI + alias Pleroma.Web.Push alias Pleroma.Web.Streamer describe "create_notifications" do @@ -80,6 +82,80 @@ test "does not create a notification for subscribed users if status is a reply" end end + describe "CommonApi.post/2 notification-related functionality" do + test_with_mock "creates but does NOT send notification to blocker user", + Push, + [:passthrough], + [] do + user = insert(:user) + blocker = insert(:user) + {:ok, _user_relationship} = User.block(blocker, user) + + {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"}) + + blocker_id = blocker.id + assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification) + refute called(Push.send(:_)) + end + + test_with_mock "creates but does NOT send notification to notification-muter user", + Push, + [:passthrough], + [] do + user = insert(:user) + muter = insert(:user) + {:ok, _user_relationships} = User.mute(muter, user) + + {:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"}) + + muter_id = muter.id + assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification) + refute called(Push.send(:_)) + end + + test_with_mock "creates but does NOT send notification to thread-muter user", + Push, + [:passthrough], + [] do + user = insert(:user) + thread_muter = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"}) + + {:ok, _} = CommonAPI.add_mute(thread_muter, activity) + + {:ok, _same_context_activity} = + CommonAPI.post(user, %{ + "status" => "hey-hey-hey @#{thread_muter.nickname}!", + "in_reply_to_status_id" => activity.id + }) + + [pre_mute_notification, post_mute_notification] = + Repo.all(from(n in Notification, where: n.user_id == ^thread_muter.id, order_by: n.id)) + + pre_mute_notification_id = pre_mute_notification.id + post_mute_notification_id = post_mute_notification.id + + assert called( + Push.send( + :meck.is(fn + %Notification{id: ^pre_mute_notification_id} -> true + _ -> false + end) + ) + ) + + refute called( + Push.send( + :meck.is(fn + %Notification{id: ^post_mute_notification_id} -> true + _ -> false + end) + ) + ) + end + end + describe "create_notification" do @tag needs_streamer: true test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do @@ -382,7 +458,7 @@ test "Returns recent notifications" do end end - describe "notification target determination" do + describe "notification target determination / get_notified_from_activity/2" do test "it sends notifications to addressed users in new messages" do user = insert(:user) other_user = insert(:user) @@ -392,7 +468,9 @@ test "it sends notifications to addressed users in new messages" do "status" => "hey @#{other_user.nickname}!" }) - assert other_user in Notification.get_notified_from_activity(activity) + {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) + + assert other_user in enabled_receivers end test "it sends notifications to mentioned users in new messages" do @@ -420,7 +498,9 @@ test "it sends notifications to mentioned users in new messages" do {:ok, activity} = Transmogrifier.handle_incoming(create_activity) - assert other_user in Notification.get_notified_from_activity(activity) + {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) + + assert other_user in enabled_receivers end test "it does not send notifications to users who are only cc in new messages" do @@ -442,7 +522,9 @@ test "it does not send notifications to users who are only cc in new messages" d {:ok, activity} = Transmogrifier.handle_incoming(create_activity) - assert other_user not in Notification.get_notified_from_activity(activity) + {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) + + assert other_user not in enabled_receivers end test "it does not send notification to mentioned users in likes" do @@ -457,7 +539,10 @@ test "it does not send notification to mentioned users in likes" do {:ok, activity_two, _} = CommonAPI.favorite(activity_one.id, third_user) - assert other_user not in Notification.get_notified_from_activity(activity_two) + {enabled_receivers, _disabled_receivers} = + Notification.get_notified_from_activity(activity_two) + + assert other_user not in enabled_receivers end test "it does not send notification to mentioned users in announces" do @@ -472,7 +557,57 @@ test "it does not send notification to mentioned users in announces" do {:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user) - assert other_user not in Notification.get_notified_from_activity(activity_two) + {enabled_receivers, _disabled_receivers} = + Notification.get_notified_from_activity(activity_two) + + assert other_user not in enabled_receivers + end + + test "it returns blocking recipient in disabled recipients list" do + user = insert(:user) + other_user = insert(:user) + {:ok, _user_relationship} = User.block(other_user, user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"}) + + {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) + + assert [] == enabled_receivers + assert [other_user] == disabled_receivers + end + + test "it returns notification-muting recipient in disabled recipients list" do + user = insert(:user) + other_user = insert(:user) + {:ok, _user_relationships} = User.mute(other_user, user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"}) + + {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) + + assert [] == enabled_receivers + assert [other_user] == disabled_receivers + end + + test "it returns thread-muting recipient in disabled recipients list" do + user = insert(:user) + other_user = insert(:user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"}) + + {:ok, _} = CommonAPI.add_mute(other_user, activity) + + {:ok, same_context_activity} = + CommonAPI.post(user, %{ + "status" => "hey-hey-hey @#{other_user.nickname}!", + "in_reply_to_status_id" => activity.id + }) + + {enabled_receivers, disabled_receivers} = + Notification.get_notified_from_activity(same_context_activity) + + assert [other_user] == disabled_receivers + refute other_user in enabled_receivers end end @@ -667,7 +802,13 @@ test "move activity generates a notification" do Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user) ObanHelpers.perform_all() - assert [] = Notification.for_user(follower) + assert [ + %{ + activity: %{ + data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id} + } + } + ] = Notification.for_user(follower) assert [ %{ @@ -675,17 +816,7 @@ test "move activity generates a notification" do data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id} } } - ] = Notification.for_user(follower, %{with_move: true}) - - assert [] = Notification.for_user(other_follower) - - assert [ - %{ - activity: %{ - data: %{"type" => "Move", "actor" => ^old_ap_id, "target" => ^new_ap_id} - } - } - ] = Notification.for_user(other_follower, %{with_move: true}) + ] = Notification.for_user(other_follower) end end @@ -720,7 +851,7 @@ test "it doesn't return notifications for blocked user" do assert Notification.for_user(user) == [] end - test "it doesn't return notificatitons for blocked domain" do + test "it doesn't return notifications for blocked domain" do user = insert(:user) blocked = insert(:user, ap_id: "http://some-domain.com") {:ok, user} = User.block_domain(user, "some-domain.com") diff --git a/test/object/fetcher_test.exs b/test/object/fetcher_test.exs index 4775ee152..c06e91f12 100644 --- a/test/object/fetcher_test.exs +++ b/test/object/fetcher_test.exs @@ -28,8 +28,7 @@ defmodule Pleroma.Object.FetcherTest do describe "max thread distance restriction" do @ap_id "http://mastodon.example.org/@admin/99541947525187367" - - clear_config([:instance, :federation_incoming_replies_max_depth]) + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) test "it returns thread depth exceeded error if thread depth is exceeded" do Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0) @@ -160,7 +159,7 @@ test "it can refetch pruned objects" do end describe "signed fetches" do - clear_config([:activitypub, :sign_object_fetches]) + setup do: clear_config([:activitypub, :sign_object_fetches]) test_with_mock "it signs fetches when configured to do so", Pleroma.Signature, diff --git a/test/object_test.exs b/test/object_test.exs index 85b2a3f6d..fe583decd 100644 --- a/test/object_test.exs +++ b/test/object_test.exs @@ -74,8 +74,8 @@ test "ensures cache is cleared for the object" do end describe "delete attachments" do - clear_config([Pleroma.Upload]) - clear_config([:instance, :cleanup_attachments]) + setup do: clear_config([Pleroma.Upload]) + setup do: clear_config([:instance, :cleanup_attachments]) test "Disabled via config" do Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) diff --git a/test/plugs/admin_secret_authentication_plug_test.exs b/test/plugs/admin_secret_authentication_plug_test.exs index 2e300ac0c..100016c62 100644 --- a/test/plugs/admin_secret_authentication_plug_test.exs +++ b/test/plugs/admin_secret_authentication_plug_test.exs @@ -23,7 +23,7 @@ test "does nothing if a user is assigned", %{conn: conn} do end describe "when secret set it assigns an admin user" do - clear_config([:admin_token]) + setup do: clear_config([:admin_token]) test "with `admin_token` query parameter", %{conn: conn} do Pleroma.Config.put(:admin_token, "password123") diff --git a/test/plugs/cache_control_test.exs b/test/plugs/cache_control_test.exs index 005912ffb..6b567e81d 100644 --- a/test/plugs/cache_control_test.exs +++ b/test/plugs/cache_control_test.exs @@ -9,7 +9,7 @@ defmodule Pleroma.Web.CacheControlTest do test "Verify Cache-Control header on static assets", %{conn: conn} do conn = get(conn, "/index.html") - assert Conn.get_resp_header(conn, "cache-control") == ["public max-age=86400 must-revalidate"] + assert Conn.get_resp_header(conn, "cache-control") == ["public, no-cache"] end test "Verify Cache-Control header on the API", %{conn: conn} do diff --git a/test/plugs/ensure_authenticated_plug_test.exs b/test/plugs/ensure_authenticated_plug_test.exs index 18be5edd0..7f3559b83 100644 --- a/test/plugs/ensure_authenticated_plug_test.exs +++ b/test/plugs/ensure_authenticated_plug_test.exs @@ -8,24 +8,62 @@ defmodule Pleroma.Plugs.EnsureAuthenticatedPlugTest do alias Pleroma.Plugs.EnsureAuthenticatedPlug alias Pleroma.User - test "it halts if no user is assigned", %{conn: conn} do - conn = - conn - |> EnsureAuthenticatedPlug.call(%{}) + describe "without :if_func / :unless_func options" do + test "it halts if user is NOT assigned", %{conn: conn} do + conn = EnsureAuthenticatedPlug.call(conn, %{}) - assert conn.status == 403 - assert conn.halted == true + assert conn.status == 403 + assert conn.halted == true + end + + test "it continues if a user is assigned", %{conn: conn} do + conn = assign(conn, :user, %User{}) + ret_conn = EnsureAuthenticatedPlug.call(conn, %{}) + + assert ret_conn == conn + end end - test "it continues if a user is assigned", %{conn: conn} do - conn = - conn - |> assign(:user, %User{}) + describe "with :if_func / :unless_func options" do + setup do + %{ + true_fn: fn -> true end, + false_fn: fn -> false end + } + end - ret_conn = - conn - |> EnsureAuthenticatedPlug.call(%{}) + test "it continues if a user is assigned", %{conn: conn, true_fn: true_fn, false_fn: false_fn} do + conn = assign(conn, :user, %User{}) + assert EnsureAuthenticatedPlug.call(conn, if_func: true_fn) == conn + assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn + assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn + assert EnsureAuthenticatedPlug.call(conn, unless_func: false_fn) == conn + end - assert ret_conn == conn + test "it continues if a user is NOT assigned but :if_func evaluates to `false`", + %{conn: conn, false_fn: false_fn} do + assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn + end + + test "it continues if a user is NOT assigned but :unless_func evaluates to `true`", + %{conn: conn, true_fn: true_fn} do + assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn + end + + test "it halts if a user is NOT assigned and :if_func evaluates to `true`", + %{conn: conn, true_fn: true_fn} do + conn = EnsureAuthenticatedPlug.call(conn, if_func: true_fn) + + assert conn.status == 403 + assert conn.halted == true + end + + test "it halts if a user is NOT assigned and :unless_func evaluates to `false`", + %{conn: conn, false_fn: false_fn} do + conn = EnsureAuthenticatedPlug.call(conn, unless_func: false_fn) + + assert conn.status == 403 + assert conn.halted == true + end end end diff --git a/test/plugs/ensure_public_or_authenticated_plug_test.exs b/test/plugs/ensure_public_or_authenticated_plug_test.exs index 3fcb4d372..411252274 100644 --- a/test/plugs/ensure_public_or_authenticated_plug_test.exs +++ b/test/plugs/ensure_public_or_authenticated_plug_test.exs @@ -9,7 +9,7 @@ defmodule Pleroma.Plugs.EnsurePublicOrAuthenticatedPlugTest do alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.User - clear_config([:instance, :public]) + setup do: clear_config([:instance, :public]) test "it halts if not public and no user is assigned", %{conn: conn} do Config.put([:instance, :public], false) diff --git a/test/plugs/http_security_plug_test.exs b/test/plugs/http_security_plug_test.exs index 944a9a139..84e4c274f 100644 --- a/test/plugs/http_security_plug_test.exs +++ b/test/plugs/http_security_plug_test.exs @@ -7,9 +7,9 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do alias Pleroma.Config alias Plug.Conn - clear_config([:http_securiy, :enabled]) - clear_config([:http_security, :sts]) - clear_config([:http_security, :referrer_policy]) + setup do: clear_config([:http_securiy, :enabled]) + setup do: clear_config([:http_security, :sts]) + setup do: clear_config([:http_security, :referrer_policy]) describe "http security enabled" do setup do diff --git a/test/plugs/instance_static_test.exs b/test/plugs/instance_static_test.exs index 8cd9b5712..b8f070d6a 100644 --- a/test/plugs/instance_static_test.exs +++ b/test/plugs/instance_static_test.exs @@ -12,9 +12,7 @@ defmodule Pleroma.Web.RuntimeStaticPlugTest do on_exit(fn -> File.rm_rf(@dir) end) end - clear_config([:instance, :static_dir]) do - Pleroma.Config.put([:instance, :static_dir], @dir) - end + setup do: clear_config([:instance, :static_dir], @dir) test "overrides index" do bundled_index = get(build_conn(), "/") diff --git a/test/plugs/oauth_plug_test.exs b/test/plugs/oauth_plug_test.exs index 8534a5c13..f74c068cd 100644 --- a/test/plugs/oauth_plug_test.exs +++ b/test/plugs/oauth_plug_test.exs @@ -38,7 +38,7 @@ test "with valid token(downcase), it assigns the user", %{conn: conn} = opts do assert conn.assigns[:user] == opts[:user] end - test "with valid token(downcase) in url parameters, it assings the user", opts do + test "with valid token(downcase) in url parameters, it assigns the user", opts do conn = :get |> build_conn("/?access_token=#{opts[:token]}") diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs index 1b3aa85b6..e79ecf263 100644 --- a/test/plugs/oauth_scopes_plug_test.exs +++ b/test/plugs/oauth_scopes_plug_test.exs @@ -193,7 +193,7 @@ test "filters scopes which directly match or are ancestors of supported scopes" end describe "transform_scopes/2" do - clear_config([:auth, :enforce_oauth_admin_scope_usage]) + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage]) setup do {:ok, %{f: &OAuthScopesPlug.transform_scopes/2}} diff --git a/test/plugs/rate_limiter_test.exs b/test/plugs/rate_limiter_test.exs index 8023271e4..0ce9f3a0a 100644 --- a/test/plugs/rate_limiter_test.exs +++ b/test/plugs/rate_limiter_test.exs @@ -3,8 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Plugs.RateLimiterTest do - use ExUnit.Case, async: true - use Plug.Test + use Pleroma.Web.ConnCase alias Pleroma.Config alias Pleroma.Plugs.RateLimiter @@ -13,14 +12,12 @@ defmodule Pleroma.Plugs.RateLimiterTest do import Pleroma.Tests.Helpers, only: [clear_config: 1, clear_config: 2] # Note: each example must work with separate buckets in order to prevent concurrency issues - - clear_config([Pleroma.Web.Endpoint, :http, :ip]) - clear_config(:rate_limit) + setup do: clear_config([Pleroma.Web.Endpoint, :http, :ip]) + setup do: clear_config(:rate_limit) describe "config" do @limiter_name :test_init - - clear_config([Pleroma.Plugs.RemoteIp, :enabled]) + setup do: clear_config([Pleroma.Plugs.RemoteIp, :enabled]) test "config is required for plug to work" do Config.put([:rate_limit, @limiter_name], {1, 1}) @@ -36,63 +33,44 @@ test "config is required for plug to work" do |> RateLimiter.init() |> RateLimiter.action_settings() end + end - test "it is disabled for localhost" do - Config.put([:rate_limit, @limiter_name], {1, 1}) - Config.put([Pleroma.Web.Endpoint, :http, :ip], {127, 0, 0, 1}) - Config.put([Pleroma.Plugs.RemoteIp, :enabled], false) + test "it is disabled if it remote ip plug is enabled but no remote ip is found" do + Config.put([Pleroma.Web.Endpoint, :http, :ip], {127, 0, 0, 1}) + assert RateLimiter.disabled?(Plug.Conn.assign(build_conn(), :remote_ip_found, false)) + end - assert RateLimiter.disabled?() == true - end + test "it restricts based on config values" do + limiter_name = :test_plug_opts + scale = 80 + limit = 5 - test "it is disabled for socket" do - Config.put([:rate_limit, @limiter_name], {1, 1}) - Config.put([Pleroma.Web.Endpoint, :http, :ip], {:local, "/path/to/pleroma.sock"}) - Config.put([Pleroma.Plugs.RemoteIp, :enabled], false) + Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8}) + Config.put([:rate_limit, limiter_name], {scale, limit}) - assert RateLimiter.disabled?() == true - end - - test "it is enabled for socket when remote ip is enabled" do - Config.put([:rate_limit, @limiter_name], {1, 1}) - Config.put([Pleroma.Web.Endpoint, :http, :ip], {:local, "/path/to/pleroma.sock"}) - Config.put([Pleroma.Plugs.RemoteIp, :enabled], true) - - assert RateLimiter.disabled?() == false - end - - test "it restricts based on config values" do - limiter_name = :test_plug_opts - scale = 80 - limit = 5 - - Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8}) - Config.put([:rate_limit, limiter_name], {scale, limit}) - - plug_opts = RateLimiter.init(name: limiter_name) - conn = conn(:get, "/") - - for i <- 1..5 do - conn = RateLimiter.call(conn, plug_opts) - assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) - Process.sleep(10) - end + plug_opts = RateLimiter.init(name: limiter_name) + conn = build_conn(:get, "/") + for i <- 1..5 do conn = RateLimiter.call(conn, plug_opts) - assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) - assert conn.halted - - Process.sleep(50) - - conn = conn(:get, "/") - - conn = RateLimiter.call(conn, plug_opts) - assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) - - refute conn.status == Plug.Conn.Status.code(:too_many_requests) - refute conn.resp_body - refute conn.halted + assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) + Process.sleep(10) end + + conn = RateLimiter.call(conn, plug_opts) + assert %{"error" => "Throttled"} = Phoenix.ConnTest.json_response(conn, :too_many_requests) + assert conn.halted + + Process.sleep(50) + + conn = build_conn(:get, "/") + + conn = RateLimiter.call(conn, plug_opts) + assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) + + refute conn.status == Plug.Conn.Status.code(:too_many_requests) + refute conn.resp_body + refute conn.halted end describe "options" do @@ -105,7 +83,7 @@ test "`bucket_name` option overrides default bucket name" do base_bucket_name = "#{limiter_name}:group1" plug_opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name) - conn = conn(:get, "/") + conn = build_conn(:get, "/") RateLimiter.call(conn, plug_opts) assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, plug_opts) @@ -119,9 +97,9 @@ test "`params` option allows different queries to be tracked independently" do plug_opts = RateLimiter.init(name: limiter_name, params: ["id"]) - conn = conn(:get, "/?id=1") + conn = build_conn(:get, "/?id=1") conn = Plug.Conn.fetch_query_params(conn) - conn_2 = conn(:get, "/?id=2") + conn_2 = build_conn(:get, "/?id=2") RateLimiter.call(conn, plug_opts) assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts) @@ -140,9 +118,9 @@ test "it supports combination of options modifying bucket name" do id = "100" - conn = conn(:get, "/?id=#{id}") + conn = build_conn(:get, "/?id=#{id}") conn = Plug.Conn.fetch_query_params(conn) - conn_2 = conn(:get, "/?id=#{101}") + conn_2 = build_conn(:get, "/?id=#{101}") RateLimiter.call(conn, plug_opts) assert {1, 4} = RateLimiter.inspect_bucket(conn, base_bucket_name, plug_opts) @@ -158,8 +136,8 @@ test "are restricted based on remote IP" do plug_opts = RateLimiter.init(name: limiter_name) - conn = %{conn(:get, "/") | remote_ip: {127, 0, 0, 2}} - conn_2 = %{conn(:get, "/") | remote_ip: {127, 0, 0, 3}} + conn = %{build_conn(:get, "/") | remote_ip: {127, 0, 0, 2}} + conn_2 = %{build_conn(:get, "/") | remote_ip: {127, 0, 0, 3}} for i <- 1..5 do conn = RateLimiter.call(conn, plug_opts) @@ -199,7 +177,7 @@ test "can have limits separate from unauthenticated connections" do plug_opts = RateLimiter.init(name: limiter_name) user = insert(:user) - conn = conn(:get, "/") |> assign(:user, user) + conn = build_conn(:get, "/") |> assign(:user, user) for i <- 1..5 do conn = RateLimiter.call(conn, plug_opts) @@ -221,10 +199,10 @@ test "different users are counted independently" do plug_opts = RateLimiter.init(name: limiter_name) user = insert(:user) - conn = conn(:get, "/") |> assign(:user, user) + conn = build_conn(:get, "/") |> assign(:user, user) user_2 = insert(:user) - conn_2 = conn(:get, "/") |> assign(:user, user_2) + conn_2 = build_conn(:get, "/") |> assign(:user, user_2) for i <- 1..5 do conn = RateLimiter.call(conn, plug_opts) @@ -250,8 +228,8 @@ test "doesn't crash due to a race condition when multiple requests are made at t opts = RateLimiter.init(name: limiter_name) - conn = conn(:get, "/") - conn_2 = conn(:get, "/") + conn = build_conn(:get, "/") + conn_2 = build_conn(:get, "/") %Task{pid: pid1} = task1 = diff --git a/test/plugs/remote_ip_test.exs b/test/plugs/remote_ip_test.exs index 9c3737b0b..752ab32e7 100644 --- a/test/plugs/remote_ip_test.exs +++ b/test/plugs/remote_ip_test.exs @@ -9,8 +9,7 @@ defmodule Pleroma.Plugs.RemoteIpTest do alias Pleroma.Plugs.RemoteIp import Pleroma.Tests.Helpers, only: [clear_config: 1, clear_config: 2] - - clear_config(RemoteIp) + setup do: clear_config(RemoteIp) test "disabled" do Pleroma.Config.put(RemoteIp, enabled: false) diff --git a/test/plugs/user_enabled_plug_test.exs b/test/plugs/user_enabled_plug_test.exs index 931513d83..b219d8abf 100644 --- a/test/plugs/user_enabled_plug_test.exs +++ b/test/plugs/user_enabled_plug_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Plugs.UserEnabledPlugTest do alias Pleroma.Plugs.UserEnabledPlug import Pleroma.Factory - clear_config([:instance, :account_activation_required]) + setup do: clear_config([:instance, :account_activation_required]) test "doesn't do anything if the user isn't set", %{conn: conn} do ret_conn = diff --git a/test/plugs/user_is_admin_plug_test.exs b/test/plugs/user_is_admin_plug_test.exs index 015d51018..fd6a50e53 100644 --- a/test/plugs/user_is_admin_plug_test.exs +++ b/test/plugs/user_is_admin_plug_test.exs @@ -9,9 +9,7 @@ defmodule Pleroma.Plugs.UserIsAdminPlugTest do import Pleroma.Factory describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do - clear_config([:auth, :enforce_oauth_admin_scope_usage]) do - Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], false) - end + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) test "accepts a user that is an admin" do user = insert(:user, is_admin: true) @@ -42,9 +40,7 @@ test "denies when a user isn't set" do end describe "with [:auth, :enforce_oauth_admin_scope_usage]," do - clear_config([:auth, :enforce_oauth_admin_scope_usage]) do - Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], true) - end + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) setup do admin_user = insert(:user, is_admin: true) diff --git a/test/repo_test.exs b/test/repo_test.exs index 75e85f974..daffc6542 100644 --- a/test/repo_test.exs +++ b/test/repo_test.exs @@ -67,7 +67,7 @@ test "return error if has not assoc " do :ok end - clear_config([:i_am_aware_this_may_cause_data_loss, :disable_migration_check]) + setup do: clear_config([:i_am_aware_this_may_cause_data_loss, :disable_migration_check]) test "raises if it detects unapplied migrations" do assert_raise Pleroma.Repo.UnappliedMigrationsError, fn -> diff --git a/test/reverse_proxy_test.exs b/test/reverse_proxy_test.exs index 18d70862c..87c6aca4e 100644 --- a/test/reverse_proxy_test.exs +++ b/test/reverse_proxy_test.exs @@ -275,17 +275,6 @@ test "returns 400 on non GET, HEAD requests", %{conn: conn} do end describe "cache resp headers" do - test "returns headers", %{conn: conn} do - ClientMock - |> expect(:request, fn :get, "/cache/" <> ttl, _, _, _ -> - {:ok, 200, [{"cache-control", "public, max-age=" <> ttl}], %{}} - end) - |> expect(:stream_body, fn _ -> :done end) - - conn = ReverseProxy.call(conn, "/cache/10") - assert {"cache-control", "public, max-age=10"} in conn.resp_headers - end - test "add cache-control", %{conn: conn} do ClientMock |> expect(:request, fn :get, "/cache", _, _, _ -> @@ -294,7 +283,7 @@ test "add cache-control", %{conn: conn} do |> expect(:stream_body, fn _ -> :done end) conn = ReverseProxy.call(conn, "/cache") - assert {"cache-control", "public"} in conn.resp_headers + assert {"cache-control", "public, max-age=1209600"} in conn.resp_headers end end diff --git a/test/scheduled_activity_test.exs b/test/scheduled_activity_test.exs index 4369e7e8a..7faa5660d 100644 --- a/test/scheduled_activity_test.exs +++ b/test/scheduled_activity_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.ScheduledActivityTest do alias Pleroma.ScheduledActivity import Pleroma.Factory - clear_config([ScheduledActivity, :enabled]) + setup do: clear_config([ScheduledActivity, :enabled]) setup context do DataCase.ensure_local_uploader(context) diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 0f2e81f9e..064874201 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -26,6 +26,8 @@ defmodule Pleroma.Web.ConnCase do use Pleroma.Tests.Helpers import Pleroma.Web.Router.Helpers + alias Pleroma.Config + # The default endpoint for testing @endpoint Pleroma.Web.Endpoint @@ -48,6 +50,28 @@ defp oauth_access(scopes, opts \\ []) do %{user: user, token: token, conn: conn} end + + defp ensure_federating_or_authenticated(conn, url, user) do + initial_setting = Config.get([:instance, :federating]) + on_exit(fn -> Config.put([:instance, :federating], initial_setting) end) + + Config.put([:instance, :federating], false) + + conn + |> get(url) + |> response(403) + + conn + |> assign(:user, user) + |> get(url) + |> response(200) + + Config.put([:instance, :federating], true) + + conn + |> get(url) + |> response(200) + end end end diff --git a/test/support/helpers.ex b/test/support/helpers.ex index 6bf4b019e..e68e9bfd2 100644 --- a/test/support/helpers.ex +++ b/test/support/helpers.ex @@ -17,35 +17,17 @@ defmacro clear_config(config_path) do defmacro clear_config(config_path, do: yield) do quote do - setup do - initial_setting = Config.get(unquote(config_path)) - unquote(yield) - on_exit(fn -> Config.put(unquote(config_path), initial_setting) end) - :ok - end + initial_setting = Config.get(unquote(config_path)) + unquote(yield) + on_exit(fn -> Config.put(unquote(config_path), initial_setting) end) + :ok end end - @doc "Stores initial config value and restores it after *all* test examples are executed." - defmacro clear_config_all(config_path) do + defmacro clear_config(config_path, temp_setting) do quote do - clear_config_all(unquote(config_path)) do - end - end - end - - @doc """ - Stores initial config value and restores it after *all* test examples are executed. - Only use if *all* test examples should work with the same stubbed value - (*no* examples set a different value). - """ - defmacro clear_config_all(config_path, do: yield) do - quote do - setup_all do - initial_setting = Config.get(unquote(config_path)) - unquote(yield) - on_exit(fn -> Config.put(unquote(config_path), initial_setting) end) - :ok + clear_config(unquote(config_path)) do + Config.put(unquote(config_path), unquote(temp_setting)) end end end @@ -55,9 +37,7 @@ defmacro __using__(_opts) do import Pleroma.Tests.Helpers, only: [ clear_config: 1, - clear_config: 2, - clear_config_all: 1, - clear_config_all: 2 + clear_config: 2 ] def to_datetime(naive_datetime) do diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index d46887865..79ab129fd 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1273,10 +1273,29 @@ def get("https://patch.cx/users/rin", _, _, _) do {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}} end + def get( + "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871", + _, + _, + _ + ) do + {:ok, + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/funkwhale_audio.json")}} + end + + def get("https://channels.tests.funkwhale.audio/federation/actors/compositions", _, _, _) do + {:ok, + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json")}} + end + def get("http://example.com/rel_me/error", _, _, _) do {:ok, %Tesla.Env{status: 404, body: ""}} end + def get("https://relay.mastodon.host/actor", _, _, _) do + {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/relay/relay.json")}} + end + def get(url, query, body, headers) do {:error, "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{ @@ -1289,6 +1308,10 @@ def get(url, query, body, headers) do def post(url, query \\ [], body \\ [], headers \\ []) + def post("https://relay.mastodon.host/inbox", _, _, _) do + {:ok, %Tesla.Env{status: 200, body: ""}} + end + def post("http://example.org/needs_refresh", _, _, _) do {:ok, %Tesla.Env{ diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs index a6c0de351..3dee4f082 100644 --- a/test/tasks/config_test.exs +++ b/test/tasks/config_test.exs @@ -20,9 +20,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do :ok end - clear_config_all(:configurable_from_database) do - Pleroma.Config.put(:configurable_from_database, true) - end + setup_all do: clear_config(:configurable_from_database, true) test "error if file with custom settings doesn't exist" do Mix.Tasks.Pleroma.Config.migrate_to_db("config/not_existance_config_file.exs") diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs index 08855f245..d3d88467d 100644 --- a/test/tasks/relay_test.exs +++ b/test/tasks/relay_test.exs @@ -38,6 +38,9 @@ test "relay is followed" do assert activity.data["type"] == "Follow" assert activity.data["actor"] == local_user.ap_id assert activity.data["object"] == target_user.ap_id + + :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) + assert_receive {:mix_shell, :info, ["mastodon.example.org (no Accept received)"]} end end diff --git a/test/tasks/robots_txt_test.exs b/test/tasks/robots_txt_test.exs index e03c9c192..7040a0e4e 100644 --- a/test/tasks/robots_txt_test.exs +++ b/test/tasks/robots_txt_test.exs @@ -7,7 +7,7 @@ defmodule Mix.Tasks.Pleroma.RobotsTxtTest do use Pleroma.Tests.Helpers alias Mix.Tasks.Pleroma.RobotsTxt - clear_config([:instance, :static_dir]) + setup do: clear_config([:instance, :static_dir]) test "creates new dir" do path = "test/fixtures/new_dir/" diff --git a/test/upload/filter/anonymize_filename_test.exs b/test/upload/filter/anonymize_filename_test.exs index 330158580..2d5c580f1 100644 --- a/test/upload/filter/anonymize_filename_test.exs +++ b/test/upload/filter/anonymize_filename_test.exs @@ -18,7 +18,7 @@ defmodule Pleroma.Upload.Filter.AnonymizeFilenameTest do %{upload_file: upload_file} end - clear_config([Pleroma.Upload.Filter.AnonymizeFilename, :text]) + setup do: clear_config([Pleroma.Upload.Filter.AnonymizeFilename, :text]) test "it replaces filename on pre-defined text", %{upload_file: upload_file} do Config.put([Upload.Filter.AnonymizeFilename, :text], "custom-file.png") diff --git a/test/upload/filter/mogrify_test.exs b/test/upload/filter/mogrify_test.exs index 52483d80c..b6a463e8c 100644 --- a/test/upload/filter/mogrify_test.exs +++ b/test/upload/filter/mogrify_test.exs @@ -10,7 +10,7 @@ defmodule Pleroma.Upload.Filter.MogrifyTest do alias Pleroma.Upload alias Pleroma.Upload.Filter - clear_config([Filter.Mogrify, :args]) + setup do: clear_config([Filter.Mogrify, :args]) test "apply mogrify filter" do Config.put([Filter.Mogrify, :args], [{"tint", "40"}]) diff --git a/test/upload/filter_test.exs b/test/upload/filter_test.exs index 2ffc5247b..352b66402 100644 --- a/test/upload/filter_test.exs +++ b/test/upload/filter_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Upload.FilterTest do alias Pleroma.Config alias Pleroma.Upload.Filter - clear_config([Pleroma.Upload.Filter.AnonymizeFilename, :text]) + setup do: clear_config([Pleroma.Upload.Filter.AnonymizeFilename, :text]) test "applies filters" do Config.put([Pleroma.Upload.Filter.AnonymizeFilename, :text], "custom-file.png") diff --git a/test/upload_test.exs b/test/upload_test.exs index 6ce42b630..060a940bb 100644 --- a/test/upload_test.exs +++ b/test/upload_test.exs @@ -250,9 +250,7 @@ test "escapes reserved uri characters" do end describe "Setting a custom base_url for uploaded media" do - clear_config([Pleroma.Upload, :base_url]) do - Pleroma.Config.put([Pleroma.Upload, :base_url], "https://cache.pleroma.social") - end + setup do: clear_config([Pleroma.Upload, :base_url], "https://cache.pleroma.social") test "returns a media url with configured base_url" do base_url = Pleroma.Config.get([Pleroma.Upload, :base_url]) diff --git a/test/uploaders/s3_test.exs b/test/uploaders/s3_test.exs index fdc7eff41..6950ccb25 100644 --- a/test/uploaders/s3_test.exs +++ b/test/uploaders/s3_test.exs @@ -11,12 +11,11 @@ defmodule Pleroma.Uploaders.S3Test do import Mock import ExUnit.CaptureLog - clear_config([Pleroma.Uploaders.S3]) do - Config.put([Pleroma.Uploaders.S3], - bucket: "test_bucket", - public_endpoint: "https://s3.amazonaws.com" - ) - end + setup do: + clear_config(Pleroma.Uploaders.S3, + bucket: "test_bucket", + public_endpoint: "https://s3.amazonaws.com" + ) describe "get_file/1" do test "it returns path to local folder for files" do diff --git a/test/user_search_test.exs b/test/user_search_test.exs index 406cc8fb2..cb847b516 100644 --- a/test/user_search_test.exs +++ b/test/user_search_test.exs @@ -15,7 +15,7 @@ defmodule Pleroma.UserSearchTest do end describe "User.search" do - clear_config([:instance, :limit_to_local_content]) + setup do: clear_config([:instance, :limit_to_local_content]) test "excluded invisible users from results" do user = insert(:user, %{nickname: "john t1000"}) diff --git a/test/user_test.exs b/test/user_test.exs index 84d7f5727..8055ebd08 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -24,7 +24,7 @@ defmodule Pleroma.UserTest do :ok end - clear_config([:instance, :account_activation_required]) + setup do: clear_config([:instance, :account_activation_required]) describe "service actors" do test "returns updated invisible actor" do @@ -86,7 +86,7 @@ test "returns invisible actor" do {:ok, user: insert(:user)} end - test "outgoing_relations_ap_ids/1", %{user: user} do + test "outgoing_relationships_ap_ids/1", %{user: user} do rel_types = [:block, :mute, :notification_mute, :reblog_mute, :inverse_subscription] ap_ids_by_rel = @@ -124,10 +124,10 @@ test "outgoing_relations_ap_ids/1", %{user: user} do assert ap_ids_by_rel[:inverse_subscription] == Enum.sort(Enum.map(User.subscriber_users(user), & &1.ap_id)) - outgoing_relations_ap_ids = User.outgoing_relations_ap_ids(user, rel_types) + outgoing_relationships_ap_ids = User.outgoing_relationships_ap_ids(user, rel_types) assert ap_ids_by_rel == - Enum.into(outgoing_relations_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end) + Enum.into(outgoing_relationships_ap_ids, %{}, fn {k, v} -> {k, Enum.sort(v)} end) end end @@ -297,7 +297,7 @@ test "local users do not automatically follow local locked accounts" do end describe "unfollow/2" do - clear_config([:instance, :external_user_synchronization]) + setup do: clear_config([:instance, :external_user_synchronization]) test "unfollow with syncronizes external user" do Pleroma.Config.put([:instance, :external_user_synchronization], true) @@ -375,10 +375,9 @@ test "fetches correct profile for nickname beginning with number" do password_confirmation: "test", email: "email@example.com" } - - clear_config([:instance, :autofollowed_nicknames]) - clear_config([:instance, :welcome_message]) - clear_config([:instance, :welcome_user_nickname]) + setup do: clear_config([:instance, :autofollowed_nicknames]) + setup do: clear_config([:instance, :welcome_message]) + setup do: clear_config([:instance, :welcome_user_nickname]) test "it autofollows accounts that are set for it" do user = insert(:user) @@ -412,7 +411,11 @@ test "it sends a welcome message if it is set" do assert activity.actor == welcome_user.ap_id end - test "it requires an email, name, nickname and password, bio is optional" do + setup do: clear_config([:instance, :account_activation_required]) + + test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do + Pleroma.Config.put([:instance, :account_activation_required], true) + @full_user_data |> Map.keys() |> Enum.each(fn key -> @@ -423,6 +426,19 @@ test "it requires an email, name, nickname and password, bio is optional" do end) end + test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do + Pleroma.Config.put([:instance, :account_activation_required], false) + + @full_user_data + |> Map.keys() + |> Enum.each(fn key -> + params = Map.delete(@full_user_data, key) + changeset = User.register_changeset(%User{}, params) + + assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid? + end) + end + test "it restricts certain nicknames" do [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames]) @@ -458,10 +474,7 @@ test "it sets the password_hash and ap_id" do password_confirmation: "test", email: "email@example.com" } - - clear_config([:instance, :account_activation_required]) do - Pleroma.Config.put([:instance, :account_activation_required], true) - end + setup do: clear_config([:instance, :account_activation_required], true) test "it creates unconfirmed user" do changeset = User.register_changeset(%User{}, @full_user_data) @@ -604,9 +617,8 @@ test "returns an ap_followers link for a user" do ap_id: "http...", avatar: %{some: "avatar"} } - - clear_config([:instance, :user_bio_length]) - clear_config([:instance, :user_name_length]) + setup do: clear_config([:instance, :user_bio_length]) + setup do: clear_config([:instance, :user_name_length]) test "it confirms validity" do cs = User.remote_user_creation(@valid_remote) @@ -1099,7 +1111,7 @@ test "hide a user's statuses from timelines and notifications" do [user: user] end - clear_config([:instance, :federating]) + setup do: clear_config([:instance, :federating]) test ".delete_user_activities deletes all create activities", %{user: user} do {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"}) @@ -1280,7 +1292,7 @@ test "User.delete() plugs any possible zombie objects" do end describe "account_status/1" do - clear_config([:instance, :account_activation_required]) + setup do: clear_config([:instance, :account_activation_required]) test "return confirmation_pending for unconfirm user" do Pleroma.Config.put([:instance, :account_activation_required], true) @@ -1648,7 +1660,7 @@ test "performs update cache if user updated" do end describe "following/followers synchronization" do - clear_config([:instance, :external_user_synchronization]) + setup do: clear_config([:instance, :external_user_synchronization]) test "updates the counters normally on following/getting a follow when disabled" do Pleroma.Config.put([:instance, :external_user_synchronization], false) @@ -1753,7 +1765,7 @@ test "changes email", %{user: user} do [local_user: local_user, remote_user: remote_user] end - clear_config([:instance, :limit_to_local_content]) + setup do: clear_config([:instance, :limit_to_local_content]) test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{ remote_user: remote_user diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index 9151034da..573853afa 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do import Pleroma.Factory alias Pleroma.Activity + alias Pleroma.Config alias Pleroma.Delivery alias Pleroma.Instances alias Pleroma.Object @@ -25,12 +26,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do :ok end - clear_config_all([:instance, :federating], - do: Pleroma.Config.put([:instance, :federating], true) - ) + setup do: clear_config([:instance, :federating], true) describe "/relay" do - clear_config([:instance, :allow_relay]) + setup do: clear_config([:instance, :allow_relay]) test "with the relay active, it returns the relay user", %{conn: conn} do res = @@ -42,12 +41,21 @@ test "with the relay active, it returns the relay user", %{conn: conn} do end test "with the relay disabled, it returns 404", %{conn: conn} do - Pleroma.Config.put([:instance, :allow_relay], false) + Config.put([:instance, :allow_relay], false) conn |> get(activity_pub_path(conn, :relay)) |> json_response(404) - |> assert + end + + test "on non-federating instance, it returns 404", %{conn: conn} do + Config.put([:instance, :federating], false) + user = insert(:user) + + conn + |> assign(:user, user) + |> get(activity_pub_path(conn, :relay)) + |> json_response(404) end end @@ -60,6 +68,16 @@ test "it returns the internal fetch user", %{conn: conn} do assert res["id"] =~ "/fetch" end + + test "on non-federating instance, it returns 404", %{conn: conn} do + Config.put([:instance, :federating], false) + user = insert(:user) + + conn + |> assign(:user, user) + |> get(activity_pub_path(conn, :internal_fetch)) + |> json_response(404) + end end describe "/users/:nickname" do @@ -123,9 +141,34 @@ test "it returns 404 for remote users", %{ assert json_response(conn, 404) end + + test "it returns error when user is not found", %{conn: conn} do + response = + conn + |> put_req_header("accept", "application/json") + |> get("/users/jimm") + |> json_response(404) + + assert response == "Not found" + end + + test "it requires authentication if instance is NOT federating", %{ + conn: conn + } do + user = insert(:user) + + conn = + put_req_header( + conn, + "accept", + "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" + ) + + ensure_federating_or_authenticated(conn, "/users/#{user.nickname}.json", user) + end end - describe "/object/:uuid" do + describe "/objects/:uuid" do test "it returns a json representation of the object with accept application/json", %{ conn: conn } do @@ -236,6 +279,18 @@ test "cached purged after object deletion", %{conn: conn} do assert "Not found" == json_response(conn2, :not_found) end + + test "it requires authentication if instance is NOT federating", %{ + conn: conn + } do + user = insert(:user) + note = insert(:note) + uuid = String.split(note.data["id"], "/") |> List.last() + + conn = put_req_header(conn, "accept", "application/activity+json") + + ensure_federating_or_authenticated(conn, "/objects/#{uuid}", user) + end end describe "/activities/:uuid" do @@ -307,6 +362,18 @@ test "cached purged after activity deletion", %{conn: conn} do assert "Not found" == json_response(conn2, :not_found) end + + test "it requires authentication if instance is NOT federating", %{ + conn: conn + } do + user = insert(:user) + activity = insert(:note_activity) + uuid = String.split(activity.data["id"], "/") |> List.last() + + conn = put_req_header(conn, "accept", "application/activity+json") + + ensure_federating_or_authenticated(conn, "/activities/#{uuid}", user) + end end describe "/inbox" do @@ -341,6 +408,72 @@ test "it clears `unreachable` federation status of the sender", %{conn: conn} do assert "ok" == json_response(conn, 200) assert Instances.reachable?(sender_url) end + + test "accept follow activity", %{conn: conn} do + Pleroma.Config.put([:instance, :federating], true) + relay = Relay.get_actor() + + assert {:ok, %Activity{} = activity} = Relay.follow("https://relay.mastodon.host/actor") + + followed_relay = Pleroma.User.get_by_ap_id("https://relay.mastodon.host/actor") + relay = refresh_record(relay) + + accept = + File.read!("test/fixtures/relay/accept-follow.json") + |> String.replace("{{ap_id}}", relay.ap_id) + |> String.replace("{{activity_id}}", activity.data["id"]) + + assert "ok" == + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/inbox", accept) + |> json_response(200) + + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + + assert Pleroma.FollowingRelationship.following?( + relay, + followed_relay + ) + + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) + assert_receive {:mix_shell, :info, ["relay.mastodon.host"]} + end + + test "without valid signature, " <> + "it only accepts Create activities and requires enabled federation", + %{conn: conn} do + data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() + non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!() + + conn = put_req_header(conn, "content-type", "application/activity+json") + + Config.put([:instance, :federating], false) + + conn + |> post("/inbox", data) + |> json_response(403) + + conn + |> post("/inbox", non_create_data) + |> json_response(403) + + Config.put([:instance, :federating], true) + + ret_conn = post(conn, "/inbox", data) + assert "ok" == json_response(ret_conn, 200) + + conn + |> post("/inbox", non_create_data) + |> json_response(400) + end end describe "/users/:nickname/inbox" do @@ -479,22 +612,11 @@ test "it accepts messages from actors that are followed by the user", %{ test "it rejects reads from other users", %{conn: conn} do user = insert(:user) - otheruser = insert(:user) - - conn = - conn - |> assign(:user, otheruser) - |> put_req_header("accept", "application/activity+json") - |> get("/users/#{user.nickname}/inbox") - - assert json_response(conn, 403) - end - - test "it doesn't crash without an authenticated user", %{conn: conn} do - user = insert(:user) + other_user = insert(:user) conn = conn + |> assign(:user, other_user) |> put_req_header("accept", "application/activity+json") |> get("/users/#{user.nickname}/inbox") @@ -575,14 +697,30 @@ test "it removes all follower collections but actor's", %{conn: conn} do refute recipient.follower_address in activity.data["cc"] refute recipient.follower_address in activity.data["to"] end + + test "it requires authentication", %{conn: conn} do + user = insert(:user) + conn = put_req_header(conn, "accept", "application/activity+json") + + ret_conn = get(conn, "/users/#{user.nickname}/inbox") + assert json_response(ret_conn, 403) + + ret_conn = + conn + |> assign(:user, user) + |> get("/users/#{user.nickname}/inbox") + + assert json_response(ret_conn, 200) + end end - describe "/users/:nickname/outbox" do - test "it will not bomb when there is no activity", %{conn: conn} do + describe "GET /users/:nickname/outbox" do + test "it returns 200 even if there're no activities", %{conn: conn} do user = insert(:user) conn = conn + |> assign(:user, user) |> put_req_header("accept", "application/activity+json") |> get("/users/#{user.nickname}/outbox") @@ -597,6 +735,7 @@ test "it returns a note activity in a collection", %{conn: conn} do conn = conn + |> assign(:user, user) |> put_req_header("accept", "application/activity+json") |> get("/users/#{user.nickname}/outbox?page=true") @@ -609,24 +748,38 @@ test "it returns an announce activity in a collection", %{conn: conn} do conn = conn + |> assign(:user, user) |> put_req_header("accept", "application/activity+json") |> get("/users/#{user.nickname}/outbox?page=true") assert response(conn, 200) =~ announce_activity.data["object"] end - test "it rejects posts from other users", %{conn: conn} do + test "it requires authentication if instance is NOT federating", %{ + conn: conn + } do + user = insert(:user) + conn = put_req_header(conn, "accept", "application/activity+json") + + ensure_federating_or_authenticated(conn, "/users/#{user.nickname}/outbox", user) + end + end + + describe "POST /users/:nickname/outbox" do + test "it rejects posts from other users / unauuthenticated users", %{conn: conn} do data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!() user = insert(:user) - otheruser = insert(:user) + other_user = insert(:user) + conn = put_req_header(conn, "content-type", "application/activity+json") - conn = - conn - |> assign(:user, otheruser) - |> put_req_header("content-type", "application/activity+json") - |> post("/users/#{user.nickname}/outbox", data) + conn + |> post("/users/#{user.nickname}/outbox", data) + |> json_response(403) - assert json_response(conn, 403) + conn + |> assign(:user, other_user) + |> post("/users/#{user.nickname}/outbox", data) + |> json_response(403) end test "it inserts an incoming create activity into the database", %{conn: conn} do @@ -741,24 +894,42 @@ test "it returns relay followers", %{conn: conn} do result = conn - |> assign(:relay, true) |> get("/relay/followers") |> json_response(200) assert result["first"]["orderedItems"] == [user.ap_id] end + + test "on non-federating instance, it returns 404", %{conn: conn} do + Config.put([:instance, :federating], false) + user = insert(:user) + + conn + |> assign(:user, user) + |> get("/relay/followers") + |> json_response(404) + end end describe "/relay/following" do test "it returns relay following", %{conn: conn} do result = conn - |> assign(:relay, true) |> get("/relay/following") |> json_response(200) assert result["first"]["orderedItems"] == [] end + + test "on non-federating instance, it returns 404", %{conn: conn} do + Config.put([:instance, :federating], false) + user = insert(:user) + + conn + |> assign(:user, user) + |> get("/relay/following") + |> json_response(404) + end end describe "/users/:nickname/followers" do @@ -769,32 +940,36 @@ test "it returns the followers in a collection", %{conn: conn} do result = conn + |> assign(:user, user_two) |> get("/users/#{user_two.nickname}/followers") |> json_response(200) assert result["first"]["orderedItems"] == [user.ap_id] end - test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do + test "it returns a uri if the user has 'hide_followers' set", %{conn: conn} do user = insert(:user) user_two = insert(:user, hide_followers: true) User.follow(user, user_two) result = conn + |> assign(:user, user) |> get("/users/#{user_two.nickname}/followers") |> json_response(200) assert is_binary(result["first"]) end - test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated", + test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is from another user", %{conn: conn} do - user = insert(:user, hide_followers: true) + user = insert(:user) + other_user = insert(:user, hide_followers: true) result = conn - |> get("/users/#{user.nickname}/followers?page=1") + |> assign(:user, user) + |> get("/users/#{other_user.nickname}/followers?page=1") assert result.status == 403 assert result.resp_body == "" @@ -826,6 +1001,7 @@ test "it works for more than 10 users", %{conn: conn} do result = conn + |> assign(:user, user) |> get("/users/#{user.nickname}/followers") |> json_response(200) @@ -835,12 +1011,21 @@ test "it works for more than 10 users", %{conn: conn} do result = conn + |> assign(:user, user) |> get("/users/#{user.nickname}/followers?page=2") |> json_response(200) assert length(result["orderedItems"]) == 5 assert result["totalItems"] == 15 end + + test "returns 403 if requester is not logged in", %{conn: conn} do + user = insert(:user) + + conn + |> get("/users/#{user.nickname}/followers") + |> json_response(403) + end end describe "/users/:nickname/following" do @@ -851,6 +1036,7 @@ test "it returns the following in a collection", %{conn: conn} do result = conn + |> assign(:user, user) |> get("/users/#{user.nickname}/following") |> json_response(200) @@ -858,25 +1044,28 @@ test "it returns the following in a collection", %{conn: conn} do end test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do - user = insert(:user, hide_follows: true) - user_two = insert(:user) + user = insert(:user) + user_two = insert(:user, hide_follows: true) User.follow(user, user_two) result = conn - |> get("/users/#{user.nickname}/following") + |> assign(:user, user) + |> get("/users/#{user_two.nickname}/following") |> json_response(200) assert is_binary(result["first"]) end - test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated", + test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is from another user", %{conn: conn} do - user = insert(:user, hide_follows: true) + user = insert(:user) + user_two = insert(:user, hide_follows: true) result = conn - |> get("/users/#{user.nickname}/following?page=1") + |> assign(:user, user) + |> get("/users/#{user_two.nickname}/following?page=1") assert result.status == 403 assert result.resp_body == "" @@ -909,6 +1098,7 @@ test "it works for more than 10 users", %{conn: conn} do result = conn + |> assign(:user, user) |> get("/users/#{user.nickname}/following") |> json_response(200) @@ -918,12 +1108,21 @@ test "it works for more than 10 users", %{conn: conn} do result = conn + |> assign(:user, user) |> get("/users/#{user.nickname}/following?page=2") |> json_response(200) assert length(result["orderedItems"]) == 5 assert result["totalItems"] == 15 end + + test "returns 403 if requester is not logged in", %{conn: conn} do + user = insert(:user) + + conn + |> get("/users/#{user.nickname}/following") + |> json_response(403) + end end describe "delivery tracking" do @@ -1008,8 +1207,8 @@ test "it tracks a signed activity fetch when the json is cached", %{conn: conn} end end - describe "Additionnal ActivityPub C2S endpoints" do - test "/api/ap/whoami", %{conn: conn} do + describe "Additional ActivityPub C2S endpoints" do + test "GET /api/ap/whoami", %{conn: conn} do user = insert(:user) conn = @@ -1020,12 +1219,16 @@ test "/api/ap/whoami", %{conn: conn} do user = User.get_cached_by_id(user.id) assert UserView.render("user.json", %{user: user}) == json_response(conn, 200) + + conn + |> get("/api/ap/whoami") + |> json_response(403) end - clear_config([:media_proxy]) - clear_config([Pleroma.Upload]) + setup do: clear_config([:media_proxy]) + setup do: clear_config([Pleroma.Upload]) - test "uploadMedia", %{conn: conn} do + test "POST /api/ap/upload_media", %{conn: conn} do user = insert(:user) desc = "Description of the image" @@ -1045,6 +1248,10 @@ test "uploadMedia", %{conn: conn} do assert object["name"] == desc assert object["type"] == "Document" assert object["actor"] == user.ap_id + + conn + |> post("/api/ap/upload_media", %{"file" => image, "description" => desc}) + |> json_response(403) end end end diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 3dd3dd04d..049b14498 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -27,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do :ok end - clear_config([:instance, :federating]) + setup do: clear_config([:instance, :federating]) describe "streaming out participations" do test "it streams them out" do @@ -1396,7 +1396,7 @@ test "creates an undo activity for the last block" do end describe "deletion" do - clear_config([:instance, :rewrite_policy]) + setup do: clear_config([:instance, :rewrite_policy]) test "it reverts deletion on error" do note = insert(:note_activity) @@ -1425,6 +1425,12 @@ test "it creates a delete activity and deletes the original object" do assert Repo.get(Object, object.id).data["type"] == "Tombstone" end + test "it doesn't fail when an activity was already deleted" do + {:ok, delete} = insert(:note_activity) |> Object.normalize() |> ActivityPub.delete() + + assert {:ok, ^delete} = delete |> Object.normalize() |> ActivityPub.delete() + end + test "decrements user note count only for public activities" do user = insert(:user, note_count: 10) @@ -1580,7 +1586,7 @@ test "it filters broken threads" do end describe "update" do - clear_config([:instance, :max_pinned_statuses]) + setup do: clear_config([:instance, :max_pinned_statuses]) test "it creates an update activity with the new user data" do user = insert(:user) @@ -1955,11 +1961,9 @@ test "create" do activity = %Activity{activity | object: nil} - assert [%Notification{activity: ^activity}] = - Notification.for_user(follower, %{with_move: true}) + assert [%Notification{activity: ^activity}] = Notification.for_user(follower) - assert [%Notification{activity: ^activity}] = - Notification.for_user(follower_move_opted_out, %{with_move: true}) + assert [%Notification{activity: ^activity}] = Notification.for_user(follower_move_opted_out) end test "old user must be in the new user's `also_known_as` list" do diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs index 916b95692..95ef0b168 100644 --- a/test/web/activity_pub/mrf/hellthread_policy_test.exs +++ b/test/web/activity_pub/mrf/hellthread_policy_test.exs @@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do [user: user, message: message] end - clear_config(:mrf_hellthread) + setup do: clear_config(:mrf_hellthread) describe "reject" do test "rejects the message if the recipient count is above reject_threshold", %{ diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs index 18242a889..fd1f7aec8 100644 --- a/test/web/activity_pub/mrf/keyword_policy_test.exs +++ b/test/web/activity_pub/mrf/keyword_policy_test.exs @@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do alias Pleroma.Web.ActivityPub.MRF.KeywordPolicy - clear_config(:mrf_keyword) + setup do: clear_config(:mrf_keyword) setup do Pleroma.Config.put([:mrf_keyword], %{reject: [], federated_timeline_removal: [], replace: []}) diff --git a/test/web/activity_pub/mrf/mention_policy_test.exs b/test/web/activity_pub/mrf/mention_policy_test.exs index 08f7be542..aa003bef5 100644 --- a/test/web/activity_pub/mrf/mention_policy_test.exs +++ b/test/web/activity_pub/mrf/mention_policy_test.exs @@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do alias Pleroma.Web.ActivityPub.MRF.MentionPolicy - clear_config(:mrf_mention) + setup do: clear_config(:mrf_mention) test "pass filter if allow list is empty" do Pleroma.Config.delete([:mrf_mention]) diff --git a/test/web/activity_pub/mrf/mrf_test.exs b/test/web/activity_pub/mrf/mrf_test.exs index 04709df17..c941066f2 100644 --- a/test/web/activity_pub/mrf/mrf_test.exs +++ b/test/web/activity_pub/mrf/mrf_test.exs @@ -60,7 +60,7 @@ test "matches are case-insensitive" do end describe "describe/0" do - clear_config([:instance, :rewrite_policy]) + setup do: clear_config([:instance, :rewrite_policy]) test "it works as expected with noop policy" do expected = %{ diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs index 643609da4..0fbc5f57a 100644 --- a/test/web/activity_pub/mrf/object_age_policy_test.exs +++ b/test/web/activity_pub/mrf/object_age_policy_test.exs @@ -9,12 +9,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do alias Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy alias Pleroma.Web.ActivityPub.Visibility - clear_config([:mrf_object_age]) do - Config.put(:mrf_object_age, - threshold: 172_800, - actions: [:delist, :strip_followers] - ) - end + setup do: + clear_config(:mrf_object_age, + threshold: 172_800, + actions: [:delist, :strip_followers] + ) setup_all do Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs index fc1d190bb..abfd32df8 100644 --- a/test/web/activity_pub/mrf/reject_non_public_test.exs +++ b/test/web/activity_pub/mrf/reject_non_public_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic - clear_config([:mrf_rejectnonpublic]) + setup do: clear_config([:mrf_rejectnonpublic]) describe "public message" do test "it's allowed when address is public" do diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs index df0f223f8..5aebbc675 100644 --- a/test/web/activity_pub/mrf/simple_policy_test.exs +++ b/test/web/activity_pub/mrf/simple_policy_test.exs @@ -8,18 +8,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do alias Pleroma.Config alias Pleroma.Web.ActivityPub.MRF.SimplePolicy - clear_config([:mrf_simple]) do - Config.put(:mrf_simple, - media_removal: [], - media_nsfw: [], - federated_timeline_removal: [], - report_removal: [], - reject: [], - accept: [], - avatar_removal: [], - banner_removal: [] - ) - end + setup do: + clear_config(:mrf_simple, + media_removal: [], + media_nsfw: [], + federated_timeline_removal: [], + report_removal: [], + reject: [], + accept: [], + avatar_removal: [], + banner_removal: [] + ) describe "when :media_removal" do test "is empty" do diff --git a/test/web/activity_pub/mrf/subchain_policy_test.exs b/test/web/activity_pub/mrf/subchain_policy_test.exs index 221b8958e..fff66cb7e 100644 --- a/test/web/activity_pub/mrf/subchain_policy_test.exs +++ b/test/web/activity_pub/mrf/subchain_policy_test.exs @@ -13,8 +13,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicyTest do "type" => "Create", "object" => %{"content" => "hi"} } - - clear_config([:mrf_subchain, :match_actor]) + setup do: clear_config([:mrf_subchain, :match_actor]) test "it matches and processes subchains when the actor matches a configured target" do Pleroma.Config.put([:mrf_subchain, :match_actor], %{ diff --git a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs index 87c9e1b29..724bae058 100644 --- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs +++ b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs @@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy - clear_config([:mrf_user_allowlist, :localhost]) + setup do: clear_config([:mrf_user_allowlist, :localhost]) test "pass filter if allow list is empty" do actor = insert(:user) diff --git a/test/web/activity_pub/mrf/vocabulary_policy_test.exs b/test/web/activity_pub/mrf/vocabulary_policy_test.exs index d9207b095..69f22bb77 100644 --- a/test/web/activity_pub/mrf/vocabulary_policy_test.exs +++ b/test/web/activity_pub/mrf/vocabulary_policy_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do alias Pleroma.Web.ActivityPub.MRF.VocabularyPolicy describe "accept" do - clear_config([:mrf_vocabulary, :accept]) + setup do: clear_config([:mrf_vocabulary, :accept]) test "it accepts based on parent activity type" do Pleroma.Config.put([:mrf_vocabulary, :accept], ["Like"]) @@ -65,7 +65,7 @@ test "it does not accept disallowed parent types" do end describe "reject" do - clear_config([:mrf_vocabulary, :reject]) + setup do: clear_config([:mrf_vocabulary, :reject]) test "it rejects based on parent activity type" do Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"]) diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs index 3404848d4..801da03c1 100644 --- a/test/web/activity_pub/publisher_test.exs +++ b/test/web/activity_pub/publisher_test.exs @@ -23,6 +23,8 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do :ok end + setup_all do: clear_config([:instance, :federating], true) + describe "gather_webfinger_links/1" do test "it returns links" do user = insert(:user) diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs index e3115dcd8..040625e4d 100644 --- a/test/web/activity_pub/relay_test.exs +++ b/test/web/activity_pub/relay_test.exs @@ -68,7 +68,7 @@ test "returns activity" do end describe "publish/1" do - clear_config([:instance, :federating]) + setup do: clear_config([:instance, :federating]) test "returns error when activity not `Create` type" do activity = insert(:like_activity) diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index c3d3f9830..967389fae 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do end describe "handle_incoming" do - clear_config([:user, :deny_follow_blocked]) + setup do: clear_config([:user, :deny_follow_blocked]) test "it works for osada follow request" do user = insert(:user) diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index efbca82f6..b2cabbd30 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -25,7 +25,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do :ok end - clear_config([:instance, :max_remote_account_fields]) + setup do: clear_config([:instance, :max_remote_account_fields]) describe "handle_incoming" do test "it ignores an incoming notice if we already have it" do @@ -1351,11 +1351,8 @@ test "it accepts Move activities" do end describe "`handle_incoming/2`, Mastodon format `replies` handling" do - clear_config([:activitypub, :note_replies_output_limit]) do - Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5) - end - - clear_config([:instance, :federation_incoming_replies_max_depth]) + setup do: clear_config([:activitypub, :note_replies_output_limit], 5) + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) setup do data = @@ -1394,11 +1391,8 @@ test "does NOT schedule background fetching of `replies` beyond max thread depth end describe "`handle_incoming/2`, Pleroma format `replies` handling" do - clear_config([:activitypub, :note_replies_output_limit]) do - Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5) - end - - clear_config([:instance, :federation_incoming_replies_max_depth]) + setup do: clear_config([:activitypub, :note_replies_output_limit], 5) + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) setup do user = insert(:user) @@ -1882,7 +1876,7 @@ test "returns fixed object" do end describe "fix_in_reply_to/2" do - clear_config([:instance, :federation_incoming_replies_max_depth]) + setup do: clear_config([:instance, :federation_incoming_replies_max_depth]) setup do data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) @@ -2145,9 +2139,7 @@ test "returns object with emoji when object contains map tag" do end describe "set_replies/1" do - clear_config([:activitypub, :note_replies_output_limit]) do - Pleroma.Config.put([:activitypub, :note_replies_output_limit], 2) - end + setup do: clear_config([:activitypub, :note_replies_output_limit], 2) test "returns unmodified object if activity doesn't have self-replies" do data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json")) diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index e5ab54dd4..e913a5148 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -177,71 +177,6 @@ test "does not adress actor's follower address if the activity is not public", % end end - describe "fetch_ordered_collection" do - import Tesla.Mock - - test "fetches the first OrderedCollectionPage when an OrderedCollection is encountered" do - mock(fn - %{method: :get, url: "http://mastodon.com/outbox"} -> - json(%{"type" => "OrderedCollection", "first" => "http://mastodon.com/outbox?page=true"}) - - %{method: :get, url: "http://mastodon.com/outbox?page=true"} -> - json(%{"type" => "OrderedCollectionPage", "orderedItems" => ["ok"]}) - end) - - assert Utils.fetch_ordered_collection("http://mastodon.com/outbox", 1) == ["ok"] - end - - test "fetches several pages in the right order one after another, but only the specified amount" do - mock(fn - %{method: :get, url: "http://example.com/outbox"} -> - json(%{ - "type" => "OrderedCollectionPage", - "orderedItems" => [0], - "next" => "http://example.com/outbox?page=1" - }) - - %{method: :get, url: "http://example.com/outbox?page=1"} -> - json(%{ - "type" => "OrderedCollectionPage", - "orderedItems" => [1], - "next" => "http://example.com/outbox?page=2" - }) - - %{method: :get, url: "http://example.com/outbox?page=2"} -> - json(%{"type" => "OrderedCollectionPage", "orderedItems" => [2]}) - end) - - assert Utils.fetch_ordered_collection("http://example.com/outbox", 0) == [0] - assert Utils.fetch_ordered_collection("http://example.com/outbox", 1) == [0, 1] - end - - test "returns an error if the url doesn't have an OrderedCollection/Page" do - mock(fn - %{method: :get, url: "http://example.com/not-an-outbox"} -> - json(%{"type" => "NotAnOutbox"}) - end) - - assert {:error, _} = Utils.fetch_ordered_collection("http://example.com/not-an-outbox", 1) - end - - test "returns the what was collected if there are less pages than specified" do - mock(fn - %{method: :get, url: "http://example.com/outbox"} -> - json(%{ - "type" => "OrderedCollectionPage", - "orderedItems" => [0], - "next" => "http://example.com/outbox?page=1" - }) - - %{method: :get, url: "http://example.com/outbox?page=1"} -> - json(%{"type" => "OrderedCollectionPage", "orderedItems" => [1]}) - end) - - assert Utils.fetch_ordered_collection("http://example.com/outbox", 5) == [0, 1] - end - end - test "make_json_ld_header/0" do assert Utils.make_json_ld_header() == %{ "@context" => [ diff --git a/test/web/activity_pub/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs index 09866e99b..de5ffc5b3 100644 --- a/test/web/activity_pub/views/object_view_test.exs +++ b/test/web/activity_pub/views/object_view_test.exs @@ -37,9 +37,7 @@ test "renders a note activity" do end describe "note activity's `replies` collection rendering" do - clear_config([:activitypub, :note_replies_output_limit]) do - Pleroma.Config.put([:activitypub, :note_replies_output_limit], 5) - end + setup do: clear_config([:activitypub, :note_replies_output_limit], 5) test "renders `replies` collection for a note activity" do user = insert(:user) diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 8009d4386..c9e228cc8 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -43,9 +43,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "with [:auth, :enforce_oauth_admin_scope_usage]," do - clear_config([:auth, :enforce_oauth_admin_scope_usage]) do - Config.put([:auth, :enforce_oauth_admin_scope_usage], true) - end + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", %{admin: admin} do @@ -93,9 +91,7 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro end describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do - clear_config([:auth, :enforce_oauth_admin_scope_usage]) do - Config.put([:auth, :enforce_oauth_admin_scope_usage], false) - end + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) test "GET /api/pleroma/admin/users/:nickname requires " <> "read:accounts or admin:read:accounts or broader scope", @@ -581,13 +577,8 @@ test "/:right DELETE, can remove from a permission group (multiple)", %{ end describe "POST /api/pleroma/admin/email_invite, with valid config" do - clear_config([:instance, :registrations_open]) do - Config.put([:instance, :registrations_open], false) - end - - clear_config([:instance, :invites_enabled]) do - Config.put([:instance, :invites_enabled], true) - end + setup do: clear_config([:instance, :registrations_open], false) + setup do: clear_config([:instance, :invites_enabled], true) test "sends invitation and returns 204", %{admin: admin, conn: conn} do recipient_email = "foo@bar.com" @@ -638,8 +629,8 @@ test "it returns 403 if requested by a non-admin" do end describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do - clear_config([:instance, :registrations_open]) - clear_config([:instance, :invites_enabled]) + setup do: clear_config([:instance, :registrations_open]) + setup do: clear_config([:instance, :invites_enabled]) test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do Config.put([:instance, :registrations_open], false) @@ -1888,9 +1879,7 @@ test "returns 404 when the status does not exist", %{conn: conn} do end describe "GET /api/pleroma/admin/config" do - clear_config(:configurable_from_database) do - Config.put(:configurable_from_database, true) - end + setup do: clear_config(:configurable_from_database, true) test "when configuration from database is off", %{conn: conn} do Config.put(:configurable_from_database, false) @@ -2041,9 +2030,7 @@ test "POST /api/pleroma/admin/config error", %{conn: conn} do end) end - clear_config(:configurable_from_database) do - Config.put(:configurable_from_database, true) - end + setup do: clear_config(:configurable_from_database, true) @tag capture_log: true test "create new config setting in db", %{conn: conn} do @@ -3052,9 +3039,7 @@ test "proxy tuple ip", %{conn: conn} do end describe "GET /api/pleroma/admin/restart" do - clear_config(:configurable_from_database) do - Config.put(:configurable_from_database, true) - end + setup do: clear_config(:configurable_from_database, true) test "pleroma restarts", %{conn: conn} do capture_log(fn -> @@ -3066,7 +3051,7 @@ test "pleroma restarts", %{conn: conn} do end describe "GET /api/pleroma/admin/statuses" do - test "returns all public, unlisted, and direct statuses", %{conn: conn, admin: admin} do + test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do blocked = insert(:user) user = insert(:user) User.block(admin, blocked) @@ -3085,7 +3070,7 @@ test "returns all public, unlisted, and direct statuses", %{conn: conn, admin: a |> json_response(200) refute "private" in Enum.map(response, & &1["visibility"]) - assert length(response) == 4 + assert length(response) == 3 end test "returns only local statuses with local_only on", %{conn: conn} do @@ -3102,12 +3087,16 @@ test "returns only local statuses with local_only on", %{conn: conn} do assert length(response) == 1 end - test "returns private statuses with godmode on", %{conn: conn} do + test "returns private and direct statuses with godmode on", %{conn: conn, admin: admin} do user = insert(:user) + + {:ok, _} = + CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"}) + {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) conn = get(conn, "/api/pleroma/admin/statuses?godmode=true") - assert json_response(conn, 200) |> length() == 2 + assert json_response(conn, 200) |> length() == 3 end end @@ -3385,6 +3374,75 @@ test "returns log filtered by search", %{conn: conn, moderator: moderator} do end end + describe "GET /users/:nickname/credentials" do + test "gets the user credentials", %{conn: conn} do + user = insert(:user) + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials") + + response = assert json_response(conn, 200) + assert response["email"] == user.email + end + + test "returns 403 if requested by a non-admin" do + user = insert(:user) + + conn = + build_conn() + |> assign(:user, user) + |> get("/api/pleroma/admin/users/#{user.nickname}/credentials") + + assert json_response(conn, :forbidden) + end + end + + describe "PATCH /users/:nickname/credentials" do + test "changes password and email", %{conn: conn, admin: admin} do + user = insert(:user) + assert user.password_reset_pending == false + + conn = + patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{ + "password" => "new_password", + "email" => "new_email@example.com", + "name" => "new_name" + }) + + assert json_response(conn, 200) == %{"status" => "success"} + + ObanHelpers.perform_all() + + updated_user = User.get_by_id(user.id) + + assert updated_user.email == "new_email@example.com" + assert updated_user.name == "new_name" + assert updated_user.password_hash != user.password_hash + assert updated_user.password_reset_pending == true + + [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort() + + assert ModerationLog.get_log_entry_message(log_entry1) == + "@#{admin.nickname} updated users: @#{user.nickname}" + + assert ModerationLog.get_log_entry_message(log_entry2) == + "@#{admin.nickname} forced password reset for users: @#{user.nickname}" + end + + test "returns 403 if requested by a non-admin" do + user = insert(:user) + + conn = + build_conn() + |> assign(:user, user) + |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{ + "password" => "new_password", + "email" => "new_email@example.com", + "name" => "new_name" + }) + + assert json_response(conn, :forbidden) + end + end + describe "PATCH /users/:nickname/force_password_reset" do test "sets password_reset_pending to true", %{conn: conn} do user = insert(:user) diff --git a/test/web/chat_channel_test.exs b/test/web/chat_channel_test.exs index 68c24a9f9..f18f3a212 100644 --- a/test/web/chat_channel_test.exs +++ b/test/web/chat_channel_test.exs @@ -21,7 +21,7 @@ test "it broadcasts a message", %{socket: socket} do end describe "message lengths" do - clear_config([:instance, :chat_limit]) + setup do: clear_config([:instance, :chat_limit]) test "it ignores messages of length zero", %{socket: socket} do push(socket, "new_msg", %{"text" => ""}) diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 299d968db..0da0bd2e2 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -17,9 +17,9 @@ defmodule Pleroma.Web.CommonAPITest do require Pleroma.Constants - clear_config([:instance, :safe_dm_mentions]) - clear_config([:instance, :limit]) - clear_config([:instance, :max_pinned_statuses]) + setup do: clear_config([:instance, :safe_dm_mentions]) + setup do: clear_config([:instance, :limit]) + setup do: clear_config([:instance, :max_pinned_statuses]) test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do user = insert(:user) @@ -202,13 +202,15 @@ test "it returns error when status is empty and no attachments" do CommonAPI.post(user, %{"status" => ""}) end - test "it returns error when character limit is exceeded" do + test "it validates character limits are correctly enforced" do Pleroma.Config.put([:instance, :limit], 5) user = insert(:user) assert {:error, "The status is over the character limit"} = CommonAPI.post(user, %{"status" => "foobar"}) + + assert {:ok, activity} = CommonAPI.post(user, %{"status" => "12345"}) end test "it can handle activities that expire" do diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs index b380d10d8..45fc94522 100644 --- a/test/web/common_api/common_api_utils_test.exs +++ b/test/web/common_api/common_api_utils_test.exs @@ -89,8 +89,8 @@ test "works for bare text/html" do assert output == expected - text = "hello world!
\n\nsecond paragraph
" - expected = "hello world!
\n\nsecond paragraph
" + text = "hello world!
second paragraph
" + expected = "hello world!
second paragraph
" {output, [], []} = Utils.format_input(text, "text/html") @@ -99,14 +99,14 @@ test "works for bare text/html" do test "works for bare text/markdown" do text = "**hello world**" - expected = "hello world
\n" + expected = "hello world
" {output, [], []} = Utils.format_input(text, "text/markdown") assert output == expected text = "**hello world**\n\n*another paragraph*" - expected = "hello world
\nanother paragraph
\n" + expected = "hello world
another paragraph
" {output, [], []} = Utils.format_input(text, "text/markdown") @@ -118,7 +118,7 @@ test "works for bare text/markdown" do by someone """ - expected = "\ncool quote
\n
by someone
\n" + expected = "cool quote
by someone
" {output, [], []} = Utils.format_input(text, "text/markdown") @@ -134,7 +134,7 @@ test "works for bare text/bbcode" do assert output == expected text = "[b]hello world![/b]\n\nsecond paragraph!" - expected = "hello world!hello world
\nanother @user__test and @user__test google.com paragraph
\n) - {output, _, _} = Utils.format_input(text, "text/markdown") - assert output == expected + assert output == + ~s(hello world
another @user__test and @user__test google.com paragraph
) end end diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs index d2ee2267c..da844c24c 100644 --- a/test/web/federator_test.exs +++ b/test/web/federator_test.exs @@ -21,13 +21,10 @@ defmodule Pleroma.Web.FederatorTest do :ok end - clear_config_all([:instance, :federating]) do - Pleroma.Config.put([:instance, :federating], true) - end - - clear_config([:instance, :allow_relay]) - clear_config([:instance, :rewrite_policy]) - clear_config([:mrf_keyword]) + setup_all do: clear_config([:instance, :federating], true) + setup do: clear_config([:instance, :allow_relay]) + setup do: clear_config([:instance, :rewrite_policy]) + setup do: clear_config([:mrf_keyword]) describe "Publish an activity" do setup do diff --git a/test/web/feed/tag_controller_test.exs b/test/web/feed/tag_controller_test.exs index 5950605e8..e863df86b 100644 --- a/test/web/feed/tag_controller_test.exs +++ b/test/web/feed/tag_controller_test.exs @@ -8,9 +8,11 @@ defmodule Pleroma.Web.Feed.TagControllerTest do import Pleroma.Factory import SweetXml + alias Pleroma.Object + alias Pleroma.Web.CommonAPI alias Pleroma.Web.Feed.FeedView - clear_config([:feed]) + setup do: clear_config([:feed]) test "gets a feed (ATOM)", %{conn: conn} do Pleroma.Config.put( @@ -19,9 +21,9 @@ test "gets a feed (ATOM)", %{conn: conn} do ) user = insert(:user) - {:ok, activity1} = Pleroma.Web.CommonAPI.post(user, %{"status" => "yeah #PleromaArt"}) + {:ok, activity1} = CommonAPI.post(user, %{"status" => "yeah #PleromaArt"}) - object = Pleroma.Object.normalize(activity1) + object = Object.normalize(activity1) object_data = Map.put(object.data, "attachment", [ @@ -41,14 +43,13 @@ test "gets a feed (ATOM)", %{conn: conn} do |> Ecto.Changeset.change(data: object_data) |> Pleroma.Repo.update() - {:ok, _activity2} = - Pleroma.Web.CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"}) + {:ok, activity2} = CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"}) - {:ok, _activity3} = Pleroma.Web.CommonAPI.post(user, %{"status" => "This is :moominmamma"}) + {:ok, _activity3} = CommonAPI.post(user, %{"status" => "This is :moominmamma"}) response = conn - |> put_req_header("content-type", "application/atom+xml") + |> put_req_header("accept", "application/atom+xml") |> get(tag_feed_path(conn, :feed, "pleromaart.atom")) |> response(200) @@ -63,6 +64,21 @@ test "gets a feed (ATOM)", %{conn: conn} do assert xpath(xml, ~x"//feed/entry/author/name/text()"ls) == [user.nickname, user.nickname] assert xpath(xml, ~x"//feed/entry/author/id/text()"ls) == [user.ap_id, user.ap_id] + + conn = + conn + |> put_req_header("accept", "application/atom+xml") + |> get("/tags/pleromaart.atom", %{"max_id" => activity2.id}) + + assert get_resp_header(conn, "content-type") == ["application/atom+xml; charset=utf-8"] + resp = response(conn, 200) + xml = parse(resp) + + assert xpath(xml, ~x"//feed/title/text()") == '#pleromaart' + + assert xpath(xml, ~x"//feed/entry/title/text()"l) == [ + 'yeah #PleromaArt' + ] end test "gets a feed (RSS)", %{conn: conn} do @@ -72,9 +88,9 @@ test "gets a feed (RSS)", %{conn: conn} do ) user = insert(:user) - {:ok, activity1} = Pleroma.Web.CommonAPI.post(user, %{"status" => "yeah #PleromaArt"}) + {:ok, activity1} = CommonAPI.post(user, %{"status" => "yeah #PleromaArt"}) - object = Pleroma.Object.normalize(activity1) + object = Object.normalize(activity1) object_data = Map.put(object.data, "attachment", [ @@ -94,14 +110,13 @@ test "gets a feed (RSS)", %{conn: conn} do |> Ecto.Changeset.change(data: object_data) |> Pleroma.Repo.update() - {:ok, activity2} = - Pleroma.Web.CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"}) + {:ok, activity2} = CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"}) - {:ok, _activity3} = Pleroma.Web.CommonAPI.post(user, %{"status" => "This is :moominmamma"}) + {:ok, _activity3} = CommonAPI.post(user, %{"status" => "This is :moominmamma"}) response = conn - |> put_req_header("content-type", "application/rss+xml") + |> put_req_header("accept", "application/rss+xml") |> get(tag_feed_path(conn, :feed, "pleromaart.rss")) |> response(200) @@ -131,8 +146,8 @@ test "gets a feed (RSS)", %{conn: conn} do "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4" ] - obj1 = Pleroma.Object.normalize(activity1) - obj2 = Pleroma.Object.normalize(activity2) + obj1 = Object.normalize(activity1) + obj2 = Object.normalize(activity2) assert xpath(xml, ~x"//channel/item/description/text()"sl) == [ HtmlEntities.decode(FeedView.activity_content(obj2)), @@ -141,7 +156,7 @@ test "gets a feed (RSS)", %{conn: conn} do response = conn - |> put_req_header("content-type", "application/atom+xml") + |> put_req_header("accept", "application/rss+xml") |> get(tag_feed_path(conn, :feed, "pleromaart")) |> response(200) @@ -150,5 +165,20 @@ test "gets a feed (RSS)", %{conn: conn} do assert xpath(xml, ~x"//channel/description/text()"s) == "These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse." + + conn = + conn + |> put_req_header("accept", "application/rss+xml") + |> get("/tags/pleromaart.rss", %{"max_id" => activity2.id}) + + assert get_resp_header(conn, "content-type") == ["application/rss+xml; charset=utf-8"] + resp = response(conn, 200) + xml = parse(resp) + + assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart' + + assert xpath(xml, ~x"//channel/item/title/text()"l) == [ + 'yeah #PleromaArt' + ] end end diff --git a/test/web/feed/user_controller_test.exs b/test/web/feed/user_controller_test.exs index 19a019060..05ad427c2 100644 --- a/test/web/feed/user_controller_test.exs +++ b/test/web/feed/user_controller_test.exs @@ -8,222 +8,160 @@ defmodule Pleroma.Web.Feed.UserControllerTest do import Pleroma.Factory import SweetXml + alias Pleroma.Config alias Pleroma.Object alias Pleroma.User - clear_config([:feed]) + setup do: clear_config([:instance, :federating], true) - test "gets a feed", %{conn: conn} do - Pleroma.Config.put( - [:feed, :post_title], - %{max_length: 10, omission: "..."} - ) + describe "feed" do + setup do: clear_config([:feed]) - activity = insert(:note_activity) - - note = - insert(:note, - data: %{ - "content" => "This is :moominmamma: note ", - "attachment" => [ - %{ - "url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}] - } - ], - "inReplyTo" => activity.data["id"] - } + test "gets a feed", %{conn: conn} do + Config.put( + [:feed, :post_title], + %{max_length: 10, omission: "..."} ) - note_activity = insert(:note_activity, note: note) - user = User.get_cached_by_ap_id(note_activity.data["actor"]) + activity = insert(:note_activity) - note2 = - insert(:note, - user: user, - data: %{"content" => "42 This is :moominmamma: note ", "inReplyTo" => activity.data["id"]} + note = + insert(:note, + data: %{ + "content" => "This is :moominmamma: note ", + "attachment" => [ + %{ + "url" => [ + %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"} + ] + } + ], + "inReplyTo" => activity.data["id"] + } + ) + + note_activity = insert(:note_activity, note: note) + user = User.get_cached_by_ap_id(note_activity.data["actor"]) + + note2 = + insert(:note, + user: user, + data: %{ + "content" => "42 This is :moominmamma: note ", + "inReplyTo" => activity.data["id"] + } + ) + + note_activity2 = insert(:note_activity, note: note2) + object = Object.normalize(note_activity) + + resp = + conn + |> put_req_header("accept", "application/atom+xml") + |> get(user_feed_path(conn, :feed, user.nickname)) + |> response(200) + + activity_titles = + resp + |> SweetXml.parse() + |> SweetXml.xpath(~x"//entry/title/text()"l) + + assert activity_titles == ['42 This...', 'This is...'] + assert resp =~ object.data["content"] + + resp = + conn + |> put_req_header("accept", "application/atom+xml") + |> get("/users/#{user.nickname}/feed", %{"max_id" => note_activity2.id}) + |> response(200) + + activity_titles = + resp + |> SweetXml.parse() + |> SweetXml.xpath(~x"//entry/title/text()"l) + + assert activity_titles == ['This is...'] + end + + test "gets a rss feed", %{conn: conn} do + Pleroma.Config.put( + [:feed, :post_title], + %{max_length: 10, omission: "..."} ) - _note_activity2 = insert(:note_activity, note: note2) - object = Object.normalize(note_activity) + activity = insert(:note_activity) - resp = - conn - |> put_req_header("content-type", "application/atom+xml") - |> get(user_feed_path(conn, :feed, user.nickname)) - |> response(200) + note = + insert(:note, + data: %{ + "content" => "This is :moominmamma: note ", + "attachment" => [ + %{ + "url" => [ + %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"} + ] + } + ], + "inReplyTo" => activity.data["id"] + } + ) - activity_titles = - resp - |> SweetXml.parse() - |> SweetXml.xpath(~x"//entry/title/text()"l) + note_activity = insert(:note_activity, note: note) + user = User.get_cached_by_ap_id(note_activity.data["actor"]) - assert activity_titles == ['42 This...', 'This is...'] - assert resp =~ object.data["content"] - end - - test "returns 404 for a missing feed", %{conn: conn} do - conn = - conn - |> put_req_header("content-type", "application/atom+xml") - |> get(user_feed_path(conn, :feed, "nonexisting")) - - assert response(conn, 404) + note2 = + insert(:note, + user: user, + data: %{ + "content" => "42 This is :moominmamma: note ", + "inReplyTo" => activity.data["id"] + } + ) + + note_activity2 = insert(:note_activity, note: note2) + object = Object.normalize(note_activity) + + resp = + conn + |> put_req_header("accept", "application/rss+xml") + |> get("/users/#{user.nickname}/feed.rss") + |> response(200) + + activity_titles = + resp + |> SweetXml.parse() + |> SweetXml.xpath(~x"//item/title/text()"l) + + assert activity_titles == ['42 This...', 'This is...'] + assert resp =~ object.data["content"] + + resp = + conn + |> put_req_header("accept", "application/rss+xml") + |> get("/users/#{user.nickname}/feed.rss", %{"max_id" => note_activity2.id}) + |> response(200) + + activity_titles = + resp + |> SweetXml.parse() + |> SweetXml.xpath(~x"//item/title/text()"l) + + assert activity_titles == ['This is...'] + end + + test "returns 404 for a missing feed", %{conn: conn} do + conn = + conn + |> put_req_header("accept", "application/atom+xml") + |> get(user_feed_path(conn, :feed, "nonexisting")) + + assert response(conn, 404) + end end + # Note: see ActivityPubControllerTest for JSON format tests describe "feed_redirect" do - test "undefined format. it redirects to feed", %{conn: conn} do - note_activity = insert(:note_activity) - user = User.get_cached_by_ap_id(note_activity.data["actor"]) - - response = - conn - |> put_req_header("accept", "application/xml") - |> get("/users/#{user.nickname}") - |> response(302) - - assert response == - "You are being redirected." - end - - test "undefined format. it returns error when user not found", %{conn: conn} do - response = - conn - |> put_req_header("accept", "application/xml") - |> get(user_feed_path(conn, :feed, "jimm")) - |> response(404) - - assert response == ~S({"error":"Not found"}) - end - - test "activity+json format. it redirects on actual feed of user", %{conn: conn} do - note_activity = insert(:note_activity) - user = User.get_cached_by_ap_id(note_activity.data["actor"]) - - response = - conn - |> put_req_header("accept", "application/activity+json") - |> get("/users/#{user.nickname}") - |> json_response(200) - - assert response["endpoints"] == %{ - "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize", - "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps", - "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token", - "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox", - "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media" - } - - assert response["@context"] == [ - "https://www.w3.org/ns/activitystreams", - "http://localhost:4001/schemas/litepub-0.1.jsonld", - %{"@language" => "und"} - ] - - assert Map.take(response, [ - "followers", - "following", - "id", - "inbox", - "manuallyApprovesFollowers", - "name", - "outbox", - "preferredUsername", - "summary", - "tag", - "type", - "url" - ]) == %{ - "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers", - "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following", - "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}", - "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox", - "manuallyApprovesFollowers" => false, - "name" => user.name, - "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox", - "preferredUsername" => user.nickname, - "summary" => user.bio, - "tag" => [], - "type" => "Person", - "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}" - } - end - - test "activity+json format. it returns error whe use not found", %{conn: conn} do - response = - conn - |> put_req_header("accept", "application/activity+json") - |> get("/users/jimm") - |> json_response(404) - - assert response == "Not found" - end - - test "json format. it redirects on actual feed of user", %{conn: conn} do - note_activity = insert(:note_activity) - user = User.get_cached_by_ap_id(note_activity.data["actor"]) - - response = - conn - |> put_req_header("accept", "application/json") - |> get("/users/#{user.nickname}") - |> json_response(200) - - assert response["endpoints"] == %{ - "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize", - "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps", - "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token", - "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox", - "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media" - } - - assert response["@context"] == [ - "https://www.w3.org/ns/activitystreams", - "http://localhost:4001/schemas/litepub-0.1.jsonld", - %{"@language" => "und"} - ] - - assert Map.take(response, [ - "followers", - "following", - "id", - "inbox", - "manuallyApprovesFollowers", - "name", - "outbox", - "preferredUsername", - "summary", - "tag", - "type", - "url" - ]) == %{ - "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers", - "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following", - "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}", - "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox", - "manuallyApprovesFollowers" => false, - "name" => user.name, - "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox", - "preferredUsername" => user.nickname, - "summary" => user.bio, - "tag" => [], - "type" => "Person", - "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}" - } - end - - test "json format. it returns error whe use not found", %{conn: conn} do - response = - conn - |> put_req_header("accept", "application/json") - |> get("/users/jimm") - |> json_response(404) - - assert response == "Not found" - end - - test "html format. it redirects on actual feed of user", %{conn: conn} do + test "with html format, it redirects to user feed", %{conn: conn} do note_activity = insert(:note_activity) user = User.get_cached_by_ap_id(note_activity.data["actor"]) @@ -239,7 +177,7 @@ test "html format. it redirects on actual feed of user", %{conn: conn} do ).resp_body end - test "html format. it returns error when user not found", %{conn: conn} do + test "with html format, it returns error when user is not found", %{conn: conn} do response = conn |> get("/users/jimm") @@ -247,5 +185,30 @@ test "html format. it returns error when user not found", %{conn: conn} do assert response == %{"error" => "Not found"} end + + test "with non-html / non-json format, it redirects to user feed in atom format", %{ + conn: conn + } do + note_activity = insert(:note_activity) + user = User.get_cached_by_ap_id(note_activity.data["actor"]) + + conn = + conn + |> put_req_header("accept", "application/xml") + |> get("/users/#{user.nickname}") + + assert conn.status == 302 + assert redirected_to(conn) == "#{Pleroma.Web.base_url()}/users/#{user.nickname}/feed.atom" + end + + test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do + response = + conn + |> put_req_header("accept", "application/xml") + |> get(user_feed_path(conn, :feed, "jimm")) + |> response(404) + + assert response == ~S({"error":"Not found"}) + end end end diff --git a/test/web/instances/instance_test.exs b/test/web/instances/instance_test.exs index a3c93b986..e463200ca 100644 --- a/test/web/instances/instance_test.exs +++ b/test/web/instances/instance_test.exs @@ -10,9 +10,7 @@ defmodule Pleroma.Instances.InstanceTest do import Pleroma.Factory - clear_config_all([:instance, :federation_reachability_timeout_days]) do - Pleroma.Config.put([:instance, :federation_reachability_timeout_days], 1) - end + setup_all do: clear_config([:instance, :federation_reachability_timeout_days], 1) describe "set_reachable/1" do test "clears `unreachable_since` of existing matching Instance record having non-nil `unreachable_since`" do diff --git a/test/web/instances/instances_test.exs b/test/web/instances/instances_test.exs index c5d6abc9c..d2618025c 100644 --- a/test/web/instances/instances_test.exs +++ b/test/web/instances/instances_test.exs @@ -7,9 +7,7 @@ defmodule Pleroma.InstancesTest do use Pleroma.DataCase - clear_config_all([:instance, :federation_reachability_timeout_days]) do - Pleroma.Config.put([:instance, :federation_reachability_timeout_days], 1) - end + setup_all do: clear_config([:instance, :federation_reachability_timeout_days], 1) describe "reachable?/1" do test "returns `true` for host / url with unknown reachability status" do diff --git a/test/web/masto_fe_controller_test.exs b/test/web/masto_fe_controller_test.exs index 9a2d76e0b..1d107d56c 100644 --- a/test/web/masto_fe_controller_test.exs +++ b/test/web/masto_fe_controller_test.exs @@ -10,7 +10,7 @@ defmodule Pleroma.Web.MastodonAPI.MastoFEController do import Pleroma.Factory - clear_config([:instance, :public]) + setup do: clear_config([:instance, :public]) test "put settings", %{conn: conn} do user = insert(:user) diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index cba68859e..b693c1a47 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -9,7 +9,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do use Pleroma.Web.ConnCase import Pleroma.Factory - clear_config([:instance, :max_account_fields]) + + setup do: clear_config([:instance, :max_account_fields]) describe "updating credentials" do setup do: oauth_access(["write:accounts"]) @@ -75,7 +76,7 @@ test "updates the user's bio", %{conn: conn} do conn = patch(conn, "/api/v1/accounts/update_credentials", %{ - "note" => "I drink #cofe with @#{user2.nickname}" + "note" => "I drink #cofe with @#{user2.nickname}\n\nsuya.." }) assert user_data = json_response(conn, 200) @@ -83,7 +84,7 @@ test "updates the user's bio", %{conn: conn} do assert user_data["note"] == ~s(I drink #cofe with @#{user2.nickname}) + }" class="u-url mention" href="#{user2.ap_id}" rel="ugc">@#{user2.nickname}