diff options
Diffstat (limited to 'test')
45 files changed, 2761 insertions, 936 deletions
diff --git a/test/chat/message_reference_test.exs b/test/chat/message_reference_test.exs new file mode 100644 index 000000000..aaa7c1ad4 --- /dev/null +++ b/test/chat/message_reference_test.exs @@ -0,0 +1,29 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Chat.MessageReferenceTest do + use Pleroma.DataCase, async: true + + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + describe "messages" do + test "it returns the last message in a chat" do + user = insert(:user) + recipient = insert(:user) + + {:ok, _message_1} = CommonAPI.post_chat_message(user, recipient, "hey") + {:ok, _message_2} = CommonAPI.post_chat_message(recipient, user, "ho") + + {:ok, chat} = Chat.get_or_create(user.id, recipient.ap_id) + + message = MessageReference.last_message_for_chat(chat) + + assert message.object.data["content"] == "ho" + end + end +end diff --git a/test/chat_test.exs b/test/chat_test.exs new file mode 100644 index 000000000..332f2180a --- /dev/null +++ b/test/chat_test.exs @@ -0,0 +1,61 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.ChatTest do + use Pleroma.DataCase, async: true + + alias Pleroma.Chat + + import Pleroma.Factory + + describe "creation and getting" do + test "it only works if the recipient is a valid user (for now)" do + user = insert(:user) + + assert {:error, _chat} = Chat.bump_or_create(user.id, "http://some/nonexisting/account") + assert {:error, _chat} = Chat.get_or_create(user.id, "http://some/nonexisting/account") + end + + test "it creates a chat for a user and recipient" do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) + + assert chat.id + end + + test "it returns and bumps a chat for a user and recipient if it already exists" do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) + {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id) + + assert chat.id == chat_two.id + end + + test "it returns a chat for a user and recipient if it already exists" do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + {:ok, chat_two} = Chat.get_or_create(user.id, other_user.ap_id) + + assert chat.id == chat_two.id + end + + test "a returning chat will have an updated `update_at` field" do + user = insert(:user) + other_user = insert(:user) + + {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) + :timer.sleep(1500) + {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id) + + assert chat.id == chat_two.id + assert chat.updated_at != chat_two.updated_at + end + end +end diff --git a/test/config/config_db_test.exs b/test/config/config_db_test.exs index 336de7359..3895e2cda 100644 --- a/test/config/config_db_test.exs +++ b/test/config/config_db_test.exs @@ -7,40 +7,28 @@ defmodule Pleroma.ConfigDBTest do import Pleroma.Factory alias Pleroma.ConfigDB - test "get_by_key/1" do + test "get_by_params/1" do config = insert(:config) insert(:config) assert config == ConfigDB.get_by_params(%{group: config.group, key: config.key}) end - test "create/1" do - {:ok, config} = ConfigDB.create(%{group: ":pleroma", key: ":some_key", value: "some_value"}) - assert config == ConfigDB.get_by_params(%{group: ":pleroma", key: ":some_key"}) - end - - test "update/1" do - config = insert(:config) - {:ok, updated} = ConfigDB.update(config, %{value: "some_value"}) - loaded = ConfigDB.get_by_params(%{group: config.group, key: config.key}) - assert loaded == updated - end - test "get_all_as_keyword/0" do saved = insert(:config) - insert(:config, group: ":quack", key: ":level", value: ConfigDB.to_binary(:info)) - insert(:config, group: ":quack", key: ":meta", value: ConfigDB.to_binary([:none])) + insert(:config, group: ":quack", key: ":level", value: :info) + insert(:config, group: ":quack", key: ":meta", value: [:none]) insert(:config, group: ":quack", key: ":webhook_url", - value: ConfigDB.to_binary("https://hooks.slack.com/services/KEY/some_val") + value: "https://hooks.slack.com/services/KEY/some_val" ) config = ConfigDB.get_all_as_keyword() assert config[:pleroma] == [ - {ConfigDB.from_string(saved.key), ConfigDB.from_binary(saved.value)} + {saved.key, saved.value} ] assert config[:quack][:level] == :info @@ -51,11 +39,11 @@ defmodule Pleroma.ConfigDBTest do describe "update_or_create/1" do test "common" do config = insert(:config) - key2 = "another_key" + key2 = :another_key params = [ - %{group: "pleroma", key: key2, value: "another_value"}, - %{group: config.group, key: config.key, value: "new_value"} + %{group: :pleroma, key: key2, value: "another_value"}, + %{group: :pleroma, key: config.key, value: [a: 1, b: 2, c: "new_value"]} ] assert Repo.all(ConfigDB) |> length() == 1 @@ -65,16 +53,16 @@ defmodule Pleroma.ConfigDBTest do assert Repo.all(ConfigDB) |> length() == 2 config1 = ConfigDB.get_by_params(%{group: config.group, key: config.key}) - config2 = ConfigDB.get_by_params(%{group: "pleroma", key: key2}) + config2 = ConfigDB.get_by_params(%{group: :pleroma, key: key2}) - assert config1.value == ConfigDB.transform("new_value") - assert config2.value == ConfigDB.transform("another_value") + assert config1.value == [a: 1, b: 2, c: "new_value"] + assert config2.value == "another_value" end test "partial update" do - config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: :val2)) + config = insert(:config, value: [key1: "val1", key2: :val2]) - {:ok, _config} = + {:ok, config} = ConfigDB.update_or_create(%{ group: config.group, key: config.key, @@ -83,15 +71,14 @@ defmodule Pleroma.ConfigDBTest do updated = ConfigDB.get_by_params(%{group: config.group, key: config.key}) - value = ConfigDB.from_binary(updated.value) - assert length(value) == 3 - assert value[:key1] == :val1 - assert value[:key2] == :val2 - assert value[:key3] == :val3 + assert config.value == updated.value + assert updated.value[:key1] == :val1 + assert updated.value[:key2] == :val2 + assert updated.value[:key3] == :val3 end test "deep merge" do - config = insert(:config, value: ConfigDB.to_binary(key1: "val1", key2: [k1: :v1, k2: "v2"])) + config = insert(:config, value: [key1: "val1", key2: [k1: :v1, k2: "v2"]]) {:ok, config} = ConfigDB.update_or_create(%{ @@ -103,18 +90,15 @@ defmodule Pleroma.ConfigDBTest do updated = ConfigDB.get_by_params(%{group: config.group, key: config.key}) assert config.value == updated.value - - value = ConfigDB.from_binary(updated.value) - assert value[:key1] == :val1 - assert value[:key2] == [k1: :v1, k2: :v2, k3: :v3] - assert value[:key3] == :val3 + assert updated.value[:key1] == :val1 + assert updated.value[:key2] == [k1: :v1, k2: :v2, k3: :v3] + assert updated.value[:key3] == :val3 end test "only full update for some keys" do - config1 = insert(:config, key: ":ecto_repos", value: ConfigDB.to_binary(repo: Pleroma.Repo)) + config1 = insert(:config, key: :ecto_repos, value: [repo: Pleroma.Repo]) - config2 = - insert(:config, group: ":cors_plug", key: ":max_age", value: ConfigDB.to_binary(18)) + config2 = insert(:config, group: :cors_plug, key: :max_age, value: 18) {:ok, _config} = ConfigDB.update_or_create(%{ @@ -133,8 +117,8 @@ defmodule Pleroma.ConfigDBTest do updated1 = ConfigDB.get_by_params(%{group: config1.group, key: config1.key}) updated2 = ConfigDB.get_by_params(%{group: config2.group, key: config2.key}) - assert ConfigDB.from_binary(updated1.value) == [another_repo: [Pleroma.Repo]] - assert ConfigDB.from_binary(updated2.value) == 777 + assert updated1.value == [another_repo: [Pleroma.Repo]] + assert updated2.value == 777 end test "full update if value is not keyword" do @@ -142,7 +126,7 @@ defmodule Pleroma.ConfigDBTest do insert(:config, group: ":tesla", key: ":adapter", - value: ConfigDB.to_binary(Tesla.Adapter.Hackney) + value: Tesla.Adapter.Hackney ) {:ok, _config} = @@ -154,20 +138,20 @@ defmodule Pleroma.ConfigDBTest do updated = ConfigDB.get_by_params(%{group: config.group, key: config.key}) - assert ConfigDB.from_binary(updated.value) == Tesla.Adapter.Httpc + assert updated.value == Tesla.Adapter.Httpc end test "only full update for some subkeys" do config1 = insert(:config, key: ":emoji", - value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1]) + value: [groups: [a: 1, b: 2], key: [a: 1]] ) config2 = insert(:config, key: ":assets", - value: ConfigDB.to_binary(mascots: [a: 1, b: 2], key: [a: 1]) + value: [mascots: [a: 1, b: 2], key: [a: 1]] ) {:ok, _config} = @@ -187,8 +171,8 @@ defmodule Pleroma.ConfigDBTest do updated1 = ConfigDB.get_by_params(%{group: config1.group, key: config1.key}) updated2 = ConfigDB.get_by_params(%{group: config2.group, key: config2.key}) - assert ConfigDB.from_binary(updated1.value) == [groups: [c: 3, d: 4], key: [a: 1, b: 2]] - assert ConfigDB.from_binary(updated2.value) == [mascots: [c: 3, d: 4], key: [a: 1, b: 2]] + assert updated1.value == [groups: [c: 3, d: 4], key: [a: 1, b: 2]] + assert updated2.value == [mascots: [c: 3, d: 4], key: [a: 1, b: 2]] end end @@ -206,14 +190,14 @@ defmodule Pleroma.ConfigDBTest do end test "partial subkeys delete" do - config = insert(:config, value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1])) + config = insert(:config, value: [groups: [a: 1, b: 2], key: [a: 1]]) {:ok, deleted} = ConfigDB.delete(%{group: config.group, key: config.key, subkeys: [":groups"]}) assert Ecto.get_meta(deleted, :state) == :loaded - assert deleted.value == ConfigDB.to_binary(key: [a: 1]) + assert deleted.value == [key: [a: 1]] updated = ConfigDB.get_by_params(%{group: config.group, key: config.key}) @@ -221,7 +205,7 @@ defmodule Pleroma.ConfigDBTest do end test "full delete if remaining value after subkeys deletion is empty list" do - config = insert(:config, value: ConfigDB.to_binary(groups: [a: 1, b: 2])) + config = insert(:config, value: [groups: [a: 1, b: 2]]) {:ok, deleted} = ConfigDB.delete(%{group: config.group, key: config.key, subkeys: [":groups"]}) @@ -232,234 +216,159 @@ defmodule Pleroma.ConfigDBTest do end end - describe "transform/1" do + describe "to_elixir_types/1" do test "string" do - binary = ConfigDB.transform("value as string") - assert binary == :erlang.term_to_binary("value as string") - assert ConfigDB.from_binary(binary) == "value as string" + assert ConfigDB.to_elixir_types("value as string") == "value as string" end test "boolean" do - binary = ConfigDB.transform(false) - assert binary == :erlang.term_to_binary(false) - assert ConfigDB.from_binary(binary) == false + assert ConfigDB.to_elixir_types(false) == false end test "nil" do - binary = ConfigDB.transform(nil) - assert binary == :erlang.term_to_binary(nil) - assert ConfigDB.from_binary(binary) == nil + assert ConfigDB.to_elixir_types(nil) == nil end test "integer" do - binary = ConfigDB.transform(150) - assert binary == :erlang.term_to_binary(150) - assert ConfigDB.from_binary(binary) == 150 + assert ConfigDB.to_elixir_types(150) == 150 end test "atom" do - binary = ConfigDB.transform(":atom") - assert binary == :erlang.term_to_binary(:atom) - assert ConfigDB.from_binary(binary) == :atom + assert ConfigDB.to_elixir_types(":atom") == :atom end test "ssl options" do - binary = ConfigDB.transform([":tlsv1", ":tlsv1.1", ":tlsv1.2"]) - assert binary == :erlang.term_to_binary([:tlsv1, :"tlsv1.1", :"tlsv1.2"]) - assert ConfigDB.from_binary(binary) == [:tlsv1, :"tlsv1.1", :"tlsv1.2"] + assert ConfigDB.to_elixir_types([":tlsv1", ":tlsv1.1", ":tlsv1.2"]) == [ + :tlsv1, + :"tlsv1.1", + :"tlsv1.2" + ] end test "pleroma module" do - binary = ConfigDB.transform("Pleroma.Bookmark") - assert binary == :erlang.term_to_binary(Pleroma.Bookmark) - assert ConfigDB.from_binary(binary) == Pleroma.Bookmark + assert ConfigDB.to_elixir_types("Pleroma.Bookmark") == Pleroma.Bookmark end test "pleroma string" do - binary = ConfigDB.transform("Pleroma") - assert binary == :erlang.term_to_binary("Pleroma") - assert ConfigDB.from_binary(binary) == "Pleroma" + assert ConfigDB.to_elixir_types("Pleroma") == "Pleroma" end test "phoenix module" do - binary = ConfigDB.transform("Phoenix.Socket.V1.JSONSerializer") - assert binary == :erlang.term_to_binary(Phoenix.Socket.V1.JSONSerializer) - assert ConfigDB.from_binary(binary) == Phoenix.Socket.V1.JSONSerializer + assert ConfigDB.to_elixir_types("Phoenix.Socket.V1.JSONSerializer") == + Phoenix.Socket.V1.JSONSerializer end test "tesla module" do - binary = ConfigDB.transform("Tesla.Adapter.Hackney") - assert binary == :erlang.term_to_binary(Tesla.Adapter.Hackney) - assert ConfigDB.from_binary(binary) == Tesla.Adapter.Hackney + assert ConfigDB.to_elixir_types("Tesla.Adapter.Hackney") == Tesla.Adapter.Hackney end test "ExSyslogger module" do - binary = ConfigDB.transform("ExSyslogger") - assert binary == :erlang.term_to_binary(ExSyslogger) - assert ConfigDB.from_binary(binary) == ExSyslogger + assert ConfigDB.to_elixir_types("ExSyslogger") == ExSyslogger end test "Quack.Logger module" do - binary = ConfigDB.transform("Quack.Logger") - assert binary == :erlang.term_to_binary(Quack.Logger) - assert ConfigDB.from_binary(binary) == Quack.Logger + assert ConfigDB.to_elixir_types("Quack.Logger") == Quack.Logger end test "Swoosh.Adapters modules" do - binary = ConfigDB.transform("Swoosh.Adapters.SMTP") - assert binary == :erlang.term_to_binary(Swoosh.Adapters.SMTP) - assert ConfigDB.from_binary(binary) == Swoosh.Adapters.SMTP - binary = ConfigDB.transform("Swoosh.Adapters.AmazonSES") - assert binary == :erlang.term_to_binary(Swoosh.Adapters.AmazonSES) - assert ConfigDB.from_binary(binary) == Swoosh.Adapters.AmazonSES + assert ConfigDB.to_elixir_types("Swoosh.Adapters.SMTP") == Swoosh.Adapters.SMTP + assert ConfigDB.to_elixir_types("Swoosh.Adapters.AmazonSES") == Swoosh.Adapters.AmazonSES end test "sigil" do - binary = ConfigDB.transform("~r[comp[lL][aA][iI][nN]er]") - assert binary == :erlang.term_to_binary(~r/comp[lL][aA][iI][nN]er/) - assert ConfigDB.from_binary(binary) == ~r/comp[lL][aA][iI][nN]er/ + assert ConfigDB.to_elixir_types("~r[comp[lL][aA][iI][nN]er]") == ~r/comp[lL][aA][iI][nN]er/ end test "link sigil" do - binary = ConfigDB.transform("~r/https:\/\/example.com/") - assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/) - assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/ + assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/") == ~r/https:\/\/example.com/ end test "link sigil with um modifiers" do - binary = ConfigDB.transform("~r/https:\/\/example.com/um") - assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/um) - assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/um + assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/um") == + ~r/https:\/\/example.com/um end test "link sigil with i modifier" do - binary = ConfigDB.transform("~r/https:\/\/example.com/i") - assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/i) - assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/i + assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/i") == ~r/https:\/\/example.com/i end test "link sigil with s modifier" do - binary = ConfigDB.transform("~r/https:\/\/example.com/s") - assert binary == :erlang.term_to_binary(~r/https:\/\/example.com/s) - assert ConfigDB.from_binary(binary) == ~r/https:\/\/example.com/s + assert ConfigDB.to_elixir_types("~r/https:\/\/example.com/s") == ~r/https:\/\/example.com/s end test "raise if valid delimiter not found" do assert_raise ArgumentError, "valid delimiter for Regex expression not found", fn -> - ConfigDB.transform("~r/https://[]{}<>\"'()|example.com/s") + ConfigDB.to_elixir_types("~r/https://[]{}<>\"'()|example.com/s") end end test "2 child tuple" do - binary = ConfigDB.transform(%{"tuple" => ["v1", ":v2"]}) - assert binary == :erlang.term_to_binary({"v1", :v2}) - assert ConfigDB.from_binary(binary) == {"v1", :v2} + assert ConfigDB.to_elixir_types(%{"tuple" => ["v1", ":v2"]}) == {"v1", :v2} end test "proxy tuple with localhost" do - binary = - ConfigDB.transform(%{ - "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}] - }) - - assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, :localhost, 1234}}) - assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, :localhost, 1234}} + assert ConfigDB.to_elixir_types(%{ + "tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}] + }) == {:proxy_url, {:socks5, :localhost, 1234}} end test "proxy tuple with domain" do - binary = - ConfigDB.transform(%{ - "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}] - }) - - assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, 'domain.com', 1234}}) - assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, 'domain.com', 1234}} + assert ConfigDB.to_elixir_types(%{ + "tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}] + }) == {:proxy_url, {:socks5, 'domain.com', 1234}} end test "proxy tuple with ip" do - binary = - ConfigDB.transform(%{ - "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}] - }) - - assert binary == :erlang.term_to_binary({:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}}) - assert ConfigDB.from_binary(binary) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}} + assert ConfigDB.to_elixir_types(%{ + "tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}] + }) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}} end test "tuple with n childs" do - binary = - ConfigDB.transform(%{ - "tuple" => [ - "v1", - ":v2", - "Pleroma.Bookmark", - 150, - false, - "Phoenix.Socket.V1.JSONSerializer" - ] - }) - - assert binary == - :erlang.term_to_binary( - {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer} - ) - - assert ConfigDB.from_binary(binary) == - {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer} + assert ConfigDB.to_elixir_types(%{ + "tuple" => [ + "v1", + ":v2", + "Pleroma.Bookmark", + 150, + false, + "Phoenix.Socket.V1.JSONSerializer" + ] + }) == {"v1", :v2, Pleroma.Bookmark, 150, false, Phoenix.Socket.V1.JSONSerializer} end test "map with string key" do - binary = ConfigDB.transform(%{"key" => "value"}) - assert binary == :erlang.term_to_binary(%{"key" => "value"}) - assert ConfigDB.from_binary(binary) == %{"key" => "value"} + assert ConfigDB.to_elixir_types(%{"key" => "value"}) == %{"key" => "value"} end test "map with atom key" do - binary = ConfigDB.transform(%{":key" => "value"}) - assert binary == :erlang.term_to_binary(%{key: "value"}) - assert ConfigDB.from_binary(binary) == %{key: "value"} + assert ConfigDB.to_elixir_types(%{":key" => "value"}) == %{key: "value"} end test "list of strings" do - binary = ConfigDB.transform(["v1", "v2", "v3"]) - assert binary == :erlang.term_to_binary(["v1", "v2", "v3"]) - assert ConfigDB.from_binary(binary) == ["v1", "v2", "v3"] + assert ConfigDB.to_elixir_types(["v1", "v2", "v3"]) == ["v1", "v2", "v3"] end test "list of modules" do - binary = ConfigDB.transform(["Pleroma.Repo", "Pleroma.Activity"]) - assert binary == :erlang.term_to_binary([Pleroma.Repo, Pleroma.Activity]) - assert ConfigDB.from_binary(binary) == [Pleroma.Repo, Pleroma.Activity] + assert ConfigDB.to_elixir_types(["Pleroma.Repo", "Pleroma.Activity"]) == [ + Pleroma.Repo, + Pleroma.Activity + ] end test "list of atoms" do - binary = ConfigDB.transform([":v1", ":v2", ":v3"]) - assert binary == :erlang.term_to_binary([:v1, :v2, :v3]) - assert ConfigDB.from_binary(binary) == [:v1, :v2, :v3] + assert ConfigDB.to_elixir_types([":v1", ":v2", ":v3"]) == [:v1, :v2, :v3] end test "list of mixed values" do - binary = - ConfigDB.transform([ - "v1", - ":v2", - "Pleroma.Repo", - "Phoenix.Socket.V1.JSONSerializer", - 15, - false - ]) - - assert binary == - :erlang.term_to_binary([ - "v1", - :v2, - Pleroma.Repo, - Phoenix.Socket.V1.JSONSerializer, - 15, - false - ]) - - assert ConfigDB.from_binary(binary) == [ + assert ConfigDB.to_elixir_types([ + "v1", + ":v2", + "Pleroma.Repo", + "Phoenix.Socket.V1.JSONSerializer", + 15, + false + ]) == [ "v1", :v2, Pleroma.Repo, @@ -470,40 +379,17 @@ defmodule Pleroma.ConfigDBTest do end test "simple keyword" do - binary = ConfigDB.transform([%{"tuple" => [":key", "value"]}]) - assert binary == :erlang.term_to_binary([{:key, "value"}]) - assert ConfigDB.from_binary(binary) == [{:key, "value"}] - assert ConfigDB.from_binary(binary) == [key: "value"] - end - - test "keyword with partial_chain key" do - binary = - ConfigDB.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}]) - - assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1) - assert ConfigDB.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1] + assert ConfigDB.to_elixir_types([%{"tuple" => [":key", "value"]}]) == [key: "value"] end test "keyword" do - binary = - ConfigDB.transform([ - %{"tuple" => [":types", "Pleroma.PostgresTypes"]}, - %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]}, - %{"tuple" => [":migration_lock", nil]}, - %{"tuple" => [":key1", 150]}, - %{"tuple" => [":key2", "string"]} - ]) - - assert binary == - :erlang.term_to_binary( - types: Pleroma.PostgresTypes, - telemetry_event: [Pleroma.Repo.Instrumenter], - migration_lock: nil, - key1: 150, - key2: "string" - ) - - assert ConfigDB.from_binary(binary) == [ + assert ConfigDB.to_elixir_types([ + %{"tuple" => [":types", "Pleroma.PostgresTypes"]}, + %{"tuple" => [":telemetry_event", ["Pleroma.Repo.Instrumenter"]]}, + %{"tuple" => [":migration_lock", nil]}, + %{"tuple" => [":key1", 150]}, + %{"tuple" => [":key2", "string"]} + ]) == [ types: Pleroma.PostgresTypes, telemetry_event: [Pleroma.Repo.Instrumenter], migration_lock: nil, @@ -512,86 +398,60 @@ defmodule Pleroma.ConfigDBTest do ] end + test "trandformed keyword" do + assert ConfigDB.to_elixir_types(a: 1, b: 2, c: "string") == [a: 1, b: 2, c: "string"] + end + test "complex keyword with nested mixed childs" do - binary = - ConfigDB.transform([ - %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]}, - %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]}, - %{"tuple" => [":link_name", true]}, - %{"tuple" => [":proxy_remote", false]}, - %{"tuple" => [":common_map", %{":key" => "value"}]}, - %{ - "tuple" => [ - ":proxy_opts", - [ - %{"tuple" => [":redirect_on_failure", false]}, - %{"tuple" => [":max_body_length", 1_048_576]}, - %{ - "tuple" => [ - ":http", - [%{"tuple" => [":follow_redirect", true]}, %{"tuple" => [":pool", ":upload"]}] - ] - } - ] - ] - } - ]) - - assert binary == - :erlang.term_to_binary( - uploader: Pleroma.Uploaders.Local, - filters: [Pleroma.Upload.Filter.Dedupe], - link_name: true, - proxy_remote: false, - common_map: %{key: "value"}, - proxy_opts: [ - redirect_on_failure: false, - max_body_length: 1_048_576, - http: [ - follow_redirect: true, - pool: :upload + assert ConfigDB.to_elixir_types([ + %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]}, + %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]}, + %{"tuple" => [":link_name", true]}, + %{"tuple" => [":proxy_remote", false]}, + %{"tuple" => [":common_map", %{":key" => "value"}]}, + %{ + "tuple" => [ + ":proxy_opts", + [ + %{"tuple" => [":redirect_on_failure", false]}, + %{"tuple" => [":max_body_length", 1_048_576]}, + %{ + "tuple" => [ + ":http", + [ + %{"tuple" => [":follow_redirect", true]}, + %{"tuple" => [":pool", ":upload"]} + ] + ] + } ] ] - ) - - assert ConfigDB.from_binary(binary) == - [ - uploader: Pleroma.Uploaders.Local, - filters: [Pleroma.Upload.Filter.Dedupe], - link_name: true, - proxy_remote: false, - common_map: %{key: "value"}, - proxy_opts: [ - redirect_on_failure: false, - max_body_length: 1_048_576, - http: [ - follow_redirect: true, - pool: :upload - ] + } + ]) == [ + uploader: Pleroma.Uploaders.Local, + filters: [Pleroma.Upload.Filter.Dedupe], + link_name: true, + proxy_remote: false, + common_map: %{key: "value"}, + proxy_opts: [ + redirect_on_failure: false, + max_body_length: 1_048_576, + http: [ + follow_redirect: true, + pool: :upload ] ] + ] end test "common keyword" do - binary = - ConfigDB.transform([ - %{"tuple" => [":level", ":warn"]}, - %{"tuple" => [":meta", [":all"]]}, - %{"tuple" => [":path", ""]}, - %{"tuple" => [":val", nil]}, - %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]} - ]) - - assert binary == - :erlang.term_to_binary( - level: :warn, - meta: [:all], - path: "", - val: nil, - webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE" - ) - - assert ConfigDB.from_binary(binary) == [ + assert ConfigDB.to_elixir_types([ + %{"tuple" => [":level", ":warn"]}, + %{"tuple" => [":meta", [":all"]]}, + %{"tuple" => [":path", ""]}, + %{"tuple" => [":val", nil]}, + %{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]} + ]) == [ level: :warn, meta: [:all], path: "", @@ -601,98 +461,73 @@ defmodule Pleroma.ConfigDBTest do end test "complex keyword with sigil" do - binary = - ConfigDB.transform([ - %{"tuple" => [":federated_timeline_removal", []]}, - %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]}, - %{"tuple" => [":replace", []]} - ]) - - assert binary == - :erlang.term_to_binary( - federated_timeline_removal: [], - reject: [~r/comp[lL][aA][iI][nN]er/], - replace: [] - ) - - assert ConfigDB.from_binary(binary) == - [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []] + assert ConfigDB.to_elixir_types([ + %{"tuple" => [":federated_timeline_removal", []]}, + %{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]}, + %{"tuple" => [":replace", []]} + ]) == [ + federated_timeline_removal: [], + reject: [~r/comp[lL][aA][iI][nN]er/], + replace: [] + ] end test "complex keyword with tuples with more than 2 values" do - binary = - ConfigDB.transform([ - %{ - "tuple" => [ - ":http", - [ - %{ - "tuple" => [ - ":key1", - [ - %{ - "tuple" => [ - ":_", - [ - %{ - "tuple" => [ - "/api/v1/streaming", - "Pleroma.Web.MastodonAPI.WebsocketHandler", - [] - ] - }, - %{ - "tuple" => [ - "/websocket", - "Phoenix.Endpoint.CowboyWebSocket", - %{ - "tuple" => [ - "Phoenix.Transports.WebSocket", - %{ - "tuple" => [ - "Pleroma.Web.Endpoint", - "Pleroma.Web.UserSocket", - [] - ] - } - ] - } - ] - }, - %{ - "tuple" => [ - ":_", - "Phoenix.Endpoint.Cowboy2Handler", - %{"tuple" => ["Pleroma.Web.Endpoint", []]} - ] - } - ] - ] - } - ] - ] - } - ] - ] - } - ]) - - assert binary == - :erlang.term_to_binary( - http: [ - key1: [ - _: [ - {"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, - {"/websocket", Phoenix.Endpoint.CowboyWebSocket, - {Phoenix.Transports.WebSocket, - {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, []}}}, - {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}} - ] + assert ConfigDB.to_elixir_types([ + %{ + "tuple" => [ + ":http", + [ + %{ + "tuple" => [ + ":key1", + [ + %{ + "tuple" => [ + ":_", + [ + %{ + "tuple" => [ + "/api/v1/streaming", + "Pleroma.Web.MastodonAPI.WebsocketHandler", + [] + ] + }, + %{ + "tuple" => [ + "/websocket", + "Phoenix.Endpoint.CowboyWebSocket", + %{ + "tuple" => [ + "Phoenix.Transports.WebSocket", + %{ + "tuple" => [ + "Pleroma.Web.Endpoint", + "Pleroma.Web.UserSocket", + [] + ] + } + ] + } + ] + }, + %{ + "tuple" => [ + ":_", + "Phoenix.Endpoint.Cowboy2Handler", + %{"tuple" => ["Pleroma.Web.Endpoint", []]} + ] + } + ] + ] + } + ] + ] + } ] ] - ) - - assert ConfigDB.from_binary(binary) == [ + } + ]) == [ http: [ key1: [ {:_, diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs index 473899d1d..f53829e09 100644 --- a/test/config/transfer_task_test.exs +++ b/test/config/transfer_task_test.exs @@ -6,9 +6,9 @@ defmodule Pleroma.Config.TransferTaskTest do use Pleroma.DataCase import ExUnit.CaptureLog + import Pleroma.Factory alias Pleroma.Config.TransferTask - alias Pleroma.ConfigDB setup do: clear_config(:configurable_from_database, true) @@ -19,31 +19,11 @@ defmodule Pleroma.Config.TransferTaskTest do refute Application.get_env(:postgrex, :test_key) initial = Application.get_env(:logger, :level) - ConfigDB.create(%{ - group: ":pleroma", - key: ":test_key", - value: [live: 2, com: 3] - }) - - ConfigDB.create(%{ - group: ":idna", - key: ":test_key", - value: [live: 15, com: 35] - }) - - ConfigDB.create(%{ - group: ":quack", - key: ":test_key", - value: [:test_value1, :test_value2] - }) - - ConfigDB.create(%{ - group: ":postgrex", - key: ":test_key", - value: :value - }) - - ConfigDB.create(%{group: ":logger", key: ":level", value: :debug}) + insert(:config, key: :test_key, value: [live: 2, com: 3]) + insert(:config, group: :idna, key: :test_key, value: [live: 15, com: 35]) + insert(:config, group: :quack, key: :test_key, value: [:test_value1, :test_value2]) + insert(:config, group: :postgrex, key: :test_key, value: :value) + insert(:config, group: :logger, key: :level, value: :debug) TransferTask.start_link([]) @@ -66,17 +46,8 @@ defmodule Pleroma.Config.TransferTaskTest do level = Application.get_env(:quack, :level) meta = Application.get_env(:quack, :meta) - ConfigDB.create(%{ - group: ":quack", - key: ":level", - value: :info - }) - - ConfigDB.create(%{ - group: ":quack", - key: ":meta", - value: [:none] - }) + insert(:config, group: :quack, key: :level, value: :info) + insert(:config, group: :quack, key: :meta, value: [:none]) TransferTask.start_link([]) @@ -95,17 +66,8 @@ defmodule Pleroma.Config.TransferTaskTest do clear_config(:emoji) clear_config(:assets) - ConfigDB.create(%{ - group: ":pleroma", - key: ":emoji", - value: [groups: [a: 1, b: 2]] - }) - - ConfigDB.create(%{ - group: ":pleroma", - key: ":assets", - value: [mascots: [a: 1, b: 2]] - }) + insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]]) + insert(:config, key: :assets, value: [mascots: [a: 1, b: 2]]) TransferTask.start_link([]) @@ -122,12 +84,7 @@ defmodule Pleroma.Config.TransferTaskTest do test "don't restart if no reboot time settings were changed" do clear_config(:emoji) - - ConfigDB.create(%{ - group: ":pleroma", - key: ":emoji", - value: [groups: [a: 1, b: 2]] - }) + insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]]) refute String.contains?( capture_log(fn -> TransferTask.start_link([]) end), @@ -137,25 +94,13 @@ defmodule Pleroma.Config.TransferTaskTest do test "on reboot time key" do clear_config(:chat) - - ConfigDB.create(%{ - group: ":pleroma", - key: ":chat", - value: [enabled: false] - }) - + insert(:config, key: :chat, value: [enabled: false]) assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted" end test "on reboot time subkey" do clear_config(Pleroma.Captcha) - - ConfigDB.create(%{ - group: ":pleroma", - key: "Pleroma.Captcha", - value: [seconds_valid: 60] - }) - + insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60]) assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted" end @@ -163,17 +108,8 @@ defmodule Pleroma.Config.TransferTaskTest do clear_config(:chat) clear_config(Pleroma.Captcha) - ConfigDB.create(%{ - group: ":pleroma", - key: ":chat", - value: [enabled: false] - }) - - ConfigDB.create(%{ - group: ":pleroma", - key: "Pleroma.Captcha", - value: [seconds_valid: 60] - }) + insert(:config, key: :chat, value: [enabled: false]) + insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60]) refute String.contains?( capture_log(fn -> TransferTask.load_and_update_env([], false) end), diff --git a/test/fixtures/create-chat-message.json b/test/fixtures/create-chat-message.json new file mode 100644 index 000000000..9c23a1c9b --- /dev/null +++ b/test/fixtures/create-chat-message.json @@ -0,0 +1,31 @@ +{ + "actor": "http://2hu.gensokyo/users/raymoo", + "id": "http://2hu.gensokyo/objects/1", + "object": { + "attributedTo": "http://2hu.gensokyo/users/raymoo", + "content": "You expected a cute girl? Too bad. <script>alert('XSS')</script>", + "id": "http://2hu.gensokyo/objects/2", + "published": "2020-02-12T14:08:20Z", + "to": [ + "http://2hu.gensokyo/users/marisa" + ], + "tag": [ + { + "icon": { + "type": "Image", + "url": "http://2hu.gensokyo/emoji/Firefox.gif" + }, + "id": "http://2hu.gensokyo/emoji/Firefox.gif", + "name": ":firefox:", + "type": "Emoji", + "updated": "1970-01-01T00:00:00Z" + } + ], + "type": "ChatMessage" + }, + "published": "2018-02-12T14:08:20Z", + "to": [ + "http://2hu.gensokyo/users/marisa" + ], + "type": "Create" +} diff --git a/test/migration_helper/notification_backfill_test.exs b/test/migration_helper/notification_backfill_test.exs new file mode 100644 index 000000000..2a62a2b00 --- /dev/null +++ b/test/migration_helper/notification_backfill_test.exs @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.MigrationHelper.NotificationBackfillTest do + use Pleroma.DataCase + + alias Pleroma.Activity + alias Pleroma.MigrationHelper.NotificationBackfill + alias Pleroma.Notification + alias Pleroma.Repo + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + describe "fill_in_notification_types" do + test "it fills in missing notification types" do + user = insert(:user) + other_user = insert(:user) + + {:ok, post} = CommonAPI.post(user, %{status: "yeah, @#{other_user.nickname}"}) + {:ok, chat} = CommonAPI.post_chat_message(user, other_user, "yo") + {:ok, react} = CommonAPI.react_with_emoji(post.id, other_user, "☕") + {:ok, like} = CommonAPI.favorite(other_user, post.id) + {:ok, react_2} = CommonAPI.react_with_emoji(post.id, other_user, "☕") + + data = + react_2.data + |> Map.put("type", "EmojiReaction") + + {:ok, react_2} = + react_2 + |> Activity.change(%{data: data}) + |> Repo.update() + + assert {5, nil} = Repo.update_all(Notification, set: [type: nil]) + + NotificationBackfill.fill_in_notification_types() + + assert %{type: "mention"} = + Repo.get_by(Notification, user_id: other_user.id, activity_id: post.id) + + assert %{type: "favourite"} = + Repo.get_by(Notification, user_id: user.id, activity_id: like.id) + + assert %{type: "pleroma:emoji_reaction"} = + Repo.get_by(Notification, user_id: user.id, activity_id: react.id) + + assert %{type: "pleroma:emoji_reaction"} = + Repo.get_by(Notification, user_id: user.id, activity_id: react_2.id) + + assert %{type: "pleroma:chat_mention"} = + Repo.get_by(Notification, user_id: other_user.id, activity_id: chat.id) + end + end +end diff --git a/test/notification_test.exs b/test/notification_test.exs index 37c255fee..526f43fab 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -10,6 +10,7 @@ defmodule Pleroma.NotificationTest do alias Pleroma.FollowingRelationship alias Pleroma.Notification + alias Pleroma.Repo alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub @@ -31,6 +32,7 @@ defmodule Pleroma.NotificationTest do {:ok, [notification]} = Notification.create_notifications(activity) assert notification.user_id == user.id + assert notification.type == "pleroma:emoji_reaction" end test "notifies someone when they are directly addressed" do @@ -48,6 +50,7 @@ defmodule Pleroma.NotificationTest do notified_ids = Enum.sort([notification.user_id, other_notification.user_id]) assert notified_ids == [other_user.id, third_user.id] assert notification.activity_id == activity.id + assert notification.type == "mention" assert other_notification.activity_id == activity.id assert [%Pleroma.Marker{unread_count: 2}] = @@ -303,6 +306,14 @@ defmodule Pleroma.NotificationTest do assert {:ok, []} == Notification.create_notifications(status) end + + test "it disables notifications from people who are invisible" do + author = insert(:user, invisible: true) + user = insert(:user) + + {:ok, status} = CommonAPI.post(author, %{status: "hey @#{user.nickname}"}) + refute Notification.create_notification(status, user) + end end describe "follow / follow_request notifications" do @@ -335,9 +346,12 @@ defmodule Pleroma.NotificationTest do # After request is accepted, the same notification is rendered with type "follow": assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user) - notification_id = notification.id - assert [%{id: ^notification_id}] = Notification.for_user(followed_user) - assert %{type: "follow"} = NotificationView.render("show.json", render_opts) + notification = + Repo.get(Notification, notification.id) + |> Repo.preload(:activity) + + assert %{type: "follow"} = + NotificationView.render("show.json", notification: notification, for: followed_user) end test "it doesn't create a notification for follow-unfollow-follow chains" do diff --git a/test/pagination_test.exs b/test/pagination_test.exs index d5b1b782d..9165427ae 100644 --- a/test/pagination_test.exs +++ b/test/pagination_test.exs @@ -21,7 +21,7 @@ defmodule Pleroma.PaginationTest do id = Enum.at(notes, 2).id |> Integer.to_string() %{total: total, items: paginated} = - Pagination.fetch_paginated(Object, %{"min_id" => id, "total" => true}) + Pagination.fetch_paginated(Object, %{min_id: id, total: true}) assert length(paginated) == 2 assert total == 5 @@ -31,7 +31,7 @@ defmodule Pleroma.PaginationTest do id = Enum.at(notes, 2).id |> Integer.to_string() %{total: total, items: paginated} = - Pagination.fetch_paginated(Object, %{"since_id" => id, "total" => true}) + Pagination.fetch_paginated(Object, %{since_id: id, total: true}) assert length(paginated) == 2 assert total == 5 @@ -41,7 +41,7 @@ defmodule Pleroma.PaginationTest do id = Enum.at(notes, 1).id |> Integer.to_string() %{total: total, items: paginated} = - Pagination.fetch_paginated(Object, %{"max_id" => id, "total" => true}) + Pagination.fetch_paginated(Object, %{max_id: id, total: true}) assert length(paginated) == 1 assert total == 5 @@ -50,7 +50,7 @@ defmodule Pleroma.PaginationTest do test "paginates by min_id & limit", %{notes: notes} do id = Enum.at(notes, 2).id |> Integer.to_string() - paginated = Pagination.fetch_paginated(Object, %{"min_id" => id, "limit" => 1}) + paginated = Pagination.fetch_paginated(Object, %{min_id: id, limit: 1}) assert length(paginated) == 1 end @@ -64,13 +64,13 @@ defmodule Pleroma.PaginationTest do end test "paginates by limit" do - paginated = Pagination.fetch_paginated(Object, %{"limit" => 2}, :offset) + paginated = Pagination.fetch_paginated(Object, %{limit: 2}, :offset) assert length(paginated) == 2 end test "paginates by limit & offset" do - paginated = Pagination.fetch_paginated(Object, %{"limit" => 2, "offset" => 4}, :offset) + paginated = Pagination.fetch_paginated(Object, %{limit: 2, offset: 4}, :offset) assert length(paginated) == 1 end diff --git a/test/support/factory.ex b/test/support/factory.ex index 1a9b96180..6e22b66a4 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -397,24 +397,17 @@ defmodule Pleroma.Factory do } end - def config_factory do + def config_factory(attrs \\ %{}) do %Pleroma.ConfigDB{ - key: - sequence(:key, fn key -> - # Atom dynamic registration hack in tests - "some_key_#{key}" - |> String.to_atom() - |> inspect() - end), - group: ":pleroma", + key: sequence(:key, &String.to_atom("some_key_#{&1}")), + group: :pleroma, value: sequence( :value, - fn key -> - :erlang.term_to_binary(%{another_key: "#{key}somevalue", another: "#{key}somevalue"}) - end + &%{another_key: "#{&1}somevalue", another: "#{&1}somevalue"} ) } + |> merge_attributes(attrs) end def marker_factory do diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs index 04bc947a9..e1bddfebf 100644 --- a/test/tasks/config_test.exs +++ b/test/tasks/config_test.exs @@ -5,6 +5,8 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do use Pleroma.DataCase + import Pleroma.Factory + alias Pleroma.ConfigDB alias Pleroma.Repo @@ -49,24 +51,19 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do refute ConfigDB.get_by_params(%{group: ":pleroma", key: "Pleroma.Repo"}) refute ConfigDB.get_by_params(%{group: ":postgrex", key: ":json_library"}) - assert ConfigDB.from_binary(config1.value) == [key: "value", key2: [Repo]] - assert ConfigDB.from_binary(config2.value) == [key: "value2", key2: ["Activity"]] - assert ConfigDB.from_binary(config3.value) == :info + assert config1.value == [key: "value", key2: [Repo]] + assert config2.value == [key: "value2", key2: ["Activity"]] + assert config3.value == :info end test "config table is truncated before migration" do - ConfigDB.create(%{ - group: ":pleroma", - key: ":first_setting", - value: [key: "value", key2: ["Activity"]] - }) - + insert(:config, key: :first_setting, value: [key: "value", key2: ["Activity"]]) assert Repo.aggregate(ConfigDB, :count, :id) == 1 Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") config = ConfigDB.get_by_params(%{group: ":pleroma", key: ":first_setting"}) - assert ConfigDB.from_binary(config.value) == [key: "value", key2: [Repo]] + assert config.value == [key: "value", key2: [Repo]] end end @@ -82,19 +79,9 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do end test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do - ConfigDB.create(%{ - group: ":pleroma", - key: ":setting_first", - value: [key: "value", key2: ["Activity"]] - }) - - ConfigDB.create(%{ - group: ":pleroma", - key: ":setting_second", - value: [key: "value2", key2: [Repo]] - }) - - ConfigDB.create(%{group: ":quack", key: ":level", value: :info}) + insert(:config, key: :setting_first, value: [key: "value", key2: ["Activity"]]) + insert(:config, key: :setting_second, value: [key: "value2", key2: [Repo]]) + insert(:config, group: :quack, key: :level, value: :info) Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"]) @@ -107,9 +94,8 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do end test "load a settings with large values and pass to file", %{temp_file: temp_file} do - ConfigDB.create(%{ - group: ":pleroma", - key: ":instance", + insert(:config, + key: :instance, value: [ name: "Pleroma", email: "example@example.com", @@ -163,7 +149,6 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do extended_nickname_format: true, multi_factor_authentication: [ totp: [ - # digits 6 or 8 digits: 6, period: 30 ], @@ -173,7 +158,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do ] ] ] - }) + ) Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"]) diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs index 678288854..a8ba0658d 100644 --- a/test/tasks/relay_test.exs +++ b/test/tasks/relay_test.exs @@ -62,11 +62,11 @@ defmodule Mix.Tasks.Pleroma.RelayTest do [undo_activity] = ActivityPub.fetch_activities([], %{ - "type" => "Undo", - "actor_id" => follower_id, - "limit" => 1, - "skip_preload" => true, - "invisible_actors" => true + type: "Undo", + actor_id: follower_id, + limit: 1, + skip_preload: true, + invisible_actors: true }) assert undo_activity.data["type"] == "Undo" diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs index b55aa1cdb..9220d23fc 100644 --- a/test/tasks/user_test.exs +++ b/test/tasks/user_test.exs @@ -4,6 +4,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do alias Pleroma.Activity + alias Pleroma.MFA alias Pleroma.Object alias Pleroma.Repo alias Pleroma.Tests.ObanHelpers @@ -278,6 +279,35 @@ defmodule Mix.Tasks.Pleroma.UserTest do end end + describe "running reset_mfa" do + test "disables MFA" do + user = + insert(:user, + multi_factor_authentication_settings: %MFA.Settings{ + enabled: true, + totp: %MFA.Settings.TOTP{secret: "xx", confirmed: true} + } + ) + + Mix.Tasks.Pleroma.User.run(["reset_mfa", user.nickname]) + + assert_received {:mix_shell, :info, [message]} + assert message == "Multi-Factor Authentication disabled for #{user.nickname}" + + assert %{enabled: false, totp: false} == + user.nickname + |> User.get_cached_by_nickname() + |> MFA.mfa_settings() + end + + test "no user to reset MFA" do + Mix.Tasks.Pleroma.User.run(["reset_password", "nonexistent"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + describe "running invite" do test "invite token is generated" do assert capture_io(fn -> diff --git a/test/upload/filter/mogrify_test.exs b/test/upload/filter/mogrify_test.exs index b6a463e8c..62ca30487 100644 --- a/test/upload/filter/mogrify_test.exs +++ b/test/upload/filter/mogrify_test.exs @@ -6,21 +6,17 @@ defmodule Pleroma.Upload.Filter.MogrifyTest do use Pleroma.DataCase import Mock - alias Pleroma.Config - alias Pleroma.Upload alias Pleroma.Upload.Filter - setup do: clear_config([Filter.Mogrify, :args]) - test "apply mogrify filter" do - Config.put([Filter.Mogrify, :args], [{"tint", "40"}]) + clear_config(Filter.Mogrify, args: [{"tint", "40"}]) File.cp!( "test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg" ) - upload = %Upload{ + upload = %Pleroma.Upload{ name: "an… image.jpg", content_type: "image/jpg", path: Path.absname("test/fixtures/image_tmp.jpg"), diff --git a/test/upload_test.exs b/test/upload_test.exs index 060a940bb..2abf0edec 100644 --- a/test/upload_test.exs +++ b/test/upload_test.exs @@ -54,6 +54,7 @@ defmodule Pleroma.UploadTest do %{ "name" => "image.jpg", "type" => "Document", + "mediaType" => "image/jpeg", "url" => [ %{ "href" => "http://localhost:4001/media/post-process-file.jpg", diff --git a/test/user_test.exs b/test/user_test.exs index 6b344158d..98c79da4f 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1122,7 +1122,7 @@ defmodule Pleroma.UserTest do assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] == ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{ - "user" => user2 + user: user2 }) {:ok, _user} = User.deactivate(user) @@ -1132,7 +1132,7 @@ defmodule Pleroma.UserTest do assert [] == ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{ - "user" => user2 + user: user2 }) end end @@ -1159,6 +1159,9 @@ defmodule Pleroma.UserTest do follower = insert(:user) {:ok, follower} = User.follow(follower, user) + locked_user = insert(:user, name: "locked", locked: true) + {:ok, _} = User.follow(user, locked_user, :follow_pending) + object = insert(:note, user: user) activity = insert(:note_activity, user: user, note: object) @@ -1177,6 +1180,8 @@ defmodule Pleroma.UserTest do refute User.following?(follower, user) assert %{deactivated: true} = User.get_by_id(user.id) + assert [] == User.get_follow_requests(locked_user) + user_activities = user.ap_id |> Activity.Queries.by_actor() diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 3dcb62873..7693f6400 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -82,30 +82,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"}) - activities = - ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id}) + activities = ActivityPub.fetch_activities([], %{visibility: "direct", actor_id: user.ap_id}) assert activities == [direct_activity] activities = - ActivityPub.fetch_activities([], %{:visibility => "unlisted", "actor_id" => user.ap_id}) + ActivityPub.fetch_activities([], %{visibility: "unlisted", actor_id: user.ap_id}) assert activities == [unlisted_activity] activities = - ActivityPub.fetch_activities([], %{:visibility => "private", "actor_id" => user.ap_id}) + ActivityPub.fetch_activities([], %{visibility: "private", actor_id: user.ap_id}) assert activities == [private_activity] - activities = - ActivityPub.fetch_activities([], %{:visibility => "public", "actor_id" => user.ap_id}) + activities = ActivityPub.fetch_activities([], %{visibility: "public", actor_id: user.ap_id}) assert activities == [public_activity] activities = ActivityPub.fetch_activities([], %{ - :visibility => ~w[private public], - "actor_id" => user.ap_id + visibility: ~w[private public], + actor_id: user.ap_id }) assert activities == [public_activity, private_activity] @@ -126,8 +124,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activities = ActivityPub.fetch_activities([], %{ - "exclude_visibilities" => "direct", - "actor_id" => user.ap_id + exclude_visibilities: "direct", + actor_id: user.ap_id }) assert public_activity in activities @@ -137,8 +135,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activities = ActivityPub.fetch_activities([], %{ - "exclude_visibilities" => "unlisted", - "actor_id" => user.ap_id + exclude_visibilities: "unlisted", + actor_id: user.ap_id }) assert public_activity in activities @@ -148,8 +146,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activities = ActivityPub.fetch_activities([], %{ - "exclude_visibilities" => "private", - "actor_id" => user.ap_id + exclude_visibilities: "private", + actor_id: user.ap_id }) assert public_activity in activities @@ -159,8 +157,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activities = ActivityPub.fetch_activities([], %{ - "exclude_visibilities" => "public", - "actor_id" => user.ap_id + exclude_visibilities: "public", + actor_id: user.ap_id }) refute public_activity in activities @@ -193,23 +191,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"}) {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"}) - fetch_one = ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => "test"}) + fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"}) - fetch_two = - ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => ["test", "essais"]}) + fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]}) fetch_three = ActivityPub.fetch_activities([], %{ - "type" => "Create", - "tag" => ["test", "essais"], - "tag_reject" => ["reject"] + type: "Create", + tag: ["test", "essais"], + tag_reject: ["reject"] }) fetch_four = ActivityPub.fetch_activities([], %{ - "type" => "Create", - "tag" => ["test"], - "tag_all" => ["test", "reject"] + type: "Create", + tag: ["test"], + tag_all: ["test", "reject"] }) assert fetch_one == [status_one, status_three] @@ -375,7 +372,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do _listen_activity_2 = insert(:listen) _listen_activity_3 = insert(:listen) - timeline = ActivityPub.fetch_activities([], %{"type" => ["Listen"]}) + timeline = ActivityPub.fetch_activities([], %{type: ["Listen"]}) assert length(timeline) == 3 end @@ -507,7 +504,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _user_relationship} = User.block(user, %{ap_id: activity_five.data["actor"]}) - activities = ActivityPub.fetch_activities_for_context("2hu", %{"blocking_user" => user}) + activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user}) assert activities == [activity_two, activity] end end @@ -520,8 +517,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do booster = insert(:user) {:ok, _user_relationship} = User.block(user, %{ap_id: activity_one.data["actor"]}) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) assert Enum.member?(activities, activity_two) assert Enum.member?(activities, activity_three) @@ -529,8 +525,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _user_block} = User.unblock(user, %{ap_id: activity_one.data["actor"]}) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) assert Enum.member?(activities, activity_two) assert Enum.member?(activities, activity_three) @@ -541,16 +536,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id) activity_three = Activity.get_by_id(activity_three.id) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) assert Enum.member?(activities, activity_two) refute Enum.member?(activities, activity_three) refute Enum.member?(activities, boost_activity) assert Enum.member?(activities, activity_one) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => nil, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: nil, skip_preload: true}) assert Enum.member?(activities, activity_two) assert Enum.member?(activities, activity_three) @@ -573,7 +566,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, activity_four} = CommonAPI.post(blockee, %{status: "hey! @#{blocker.nickname}"}) - activities = ActivityPub.fetch_activities([], %{"blocking_user" => blocker}) + activities = ActivityPub.fetch_activities([], %{blocking_user: blocker}) assert Enum.member?(activities, activity_one) refute Enum.member?(activities, activity_two) @@ -581,7 +574,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do refute Enum.member?(activities, activity_four) end - test "doesn't return announce activities concerning blocked users" do + test "doesn't return announce activities with blocked users in 'to'" do blocker = insert(:user) blockee = insert(:user) friend = insert(:user) @@ -595,7 +588,40 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, activity_three} = CommonAPI.repeat(activity_two.id, friend) activities = - ActivityPub.fetch_activities([], %{"blocking_user" => blocker}) + ActivityPub.fetch_activities([], %{blocking_user: blocker}) + |> Enum.map(fn act -> act.id end) + + assert Enum.member?(activities, activity_one.id) + refute Enum.member?(activities, activity_two.id) + refute Enum.member?(activities, activity_three.id) + end + + test "doesn't return announce activities with blocked users in 'cc'" do + blocker = insert(:user) + blockee = insert(:user) + friend = insert(:user) + + {:ok, _user_relationship} = User.block(blocker, blockee) + + {:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"}) + + {:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"}) + + assert object = Pleroma.Object.normalize(activity_two) + + data = %{ + "actor" => friend.ap_id, + "object" => object.data["id"], + "context" => object.data["context"], + "type" => "Announce", + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "cc" => [blockee.ap_id] + } + + assert {:ok, activity_three} = ActivityPub.insert(data) + + activities = + ActivityPub.fetch_activities([], %{blocking_user: blocker}) |> Enum.map(fn act -> act.id end) assert Enum.member?(activities, activity_one.id) @@ -611,8 +637,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do user = insert(:user) {:ok, user} = User.block_domain(user, domain) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) refute activity in activities @@ -620,8 +645,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do ActivityPub.follow(user, followed_user) {:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) refute repeat_activity in activities end @@ -641,8 +665,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do note = insert(:note, %{data: %{"actor" => domain_user.ap_id}}) activity = insert(:note_activity, %{note: note}) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => blocker, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: blocker, skip_preload: true}) assert activity in activities @@ -653,8 +676,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do bad_activity = insert(:note_activity, %{note: bad_note}) {:ok, repeat_activity} = CommonAPI.repeat(bad_activity.id, domain_user) - activities = - ActivityPub.fetch_activities([], %{"blocking_user" => blocker, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{blocking_user: blocker, skip_preload: true}) refute repeat_activity in activities end @@ -669,8 +691,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activity_one_actor = User.get_by_ap_id(activity_one.data["actor"]) {:ok, _user_relationships} = User.mute(user, activity_one_actor) - activities = - ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true}) assert Enum.member?(activities, activity_two) assert Enum.member?(activities, activity_three) @@ -679,9 +700,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do # Calling with 'with_muted' will deliver muted activities, too. activities = ActivityPub.fetch_activities([], %{ - "muting_user" => user, - "with_muted" => true, - "skip_preload" => true + muting_user: user, + with_muted: true, + skip_preload: true }) assert Enum.member?(activities, activity_two) @@ -690,8 +711,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _user_mute} = User.unmute(user, activity_one_actor) - activities = - ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true}) assert Enum.member?(activities, activity_two) assert Enum.member?(activities, activity_three) @@ -703,15 +723,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do %Activity{} = boost_activity = Activity.get_create_by_object_ap_id(id) activity_three = Activity.get_by_id(activity_three.id) - activities = - ActivityPub.fetch_activities([], %{"muting_user" => user, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{muting_user: user, skip_preload: true}) assert Enum.member?(activities, activity_two) refute Enum.member?(activities, activity_three) refute Enum.member?(activities, boost_activity) assert Enum.member?(activities, activity_one) - activities = ActivityPub.fetch_activities([], %{"muting_user" => nil, "skip_preload" => true}) + activities = ActivityPub.fetch_activities([], %{muting_user: nil, skip_preload: true}) assert Enum.member?(activities, activity_two) assert Enum.member?(activities, activity_three) @@ -727,7 +746,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two) - assert [_activity_one] = ActivityPub.fetch_activities([], %{"muting_user" => user}) + assert [_activity_one] = ActivityPub.fetch_activities([], %{muting_user: user}) end test "returns thread muted activities when with_muted is set" do @@ -739,7 +758,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two) assert [_activity_two, _activity_one] = - ActivityPub.fetch_activities([], %{"muting_user" => user, "with_muted" => true}) + ActivityPub.fetch_activities([], %{muting_user: user, with_muted: true}) end test "does include announces on request" do @@ -761,7 +780,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, expected_activity} = ActivityBuilder.insert(%{"type" => "Create"}, %{:user => user}) {:ok, _} = ActivityBuilder.insert(%{"type" => "Announce"}, %{:user => user}) - [activity] = ActivityPub.fetch_user_activities(user, nil, %{"exclude_reblogs" => "true"}) + [activity] = ActivityPub.fetch_user_activities(user, nil, %{exclude_reblogs: true}) assert activity == expected_activity end @@ -804,7 +823,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do expected_activities = ActivityBuilder.insert_list(10) since_id = List.last(activities).id - activities = ActivityPub.fetch_public_activities(%{"since_id" => since_id}) + activities = ActivityPub.fetch_public_activities(%{since_id: since_id}) assert collect_ids(activities) == collect_ids(expected_activities) assert length(activities) == 10 @@ -819,7 +838,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do |> ActivityBuilder.insert_list() |> List.first() - activities = ActivityPub.fetch_public_activities(%{"max_id" => max_id}) + activities = ActivityPub.fetch_public_activities(%{max_id: max_id}) assert length(activities) == 20 assert collect_ids(activities) == collect_ids(expected_activities) @@ -831,8 +850,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do later_activities = ActivityBuilder.insert_list(10) - activities = - ActivityPub.fetch_public_activities(%{"page" => "2", "page_size" => "20"}, :offset) + activities = ActivityPub.fetch_public_activities(%{page: "2", page_size: "20"}, :offset) assert length(activities) == 20 @@ -848,7 +866,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, activity} = CommonAPI.repeat(activity.id, booster) - activities = ActivityPub.fetch_activities([], %{"muting_user" => user}) + activities = ActivityPub.fetch_activities([], %{muting_user: user}) refute Enum.any?(activities, fn %{id: id} -> id == activity.id end) end @@ -862,7 +880,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, activity} = CommonAPI.repeat(activity.id, booster) - activities = ActivityPub.fetch_activities([], %{"muting_user" => user}) + activities = ActivityPub.fetch_activities([], %{muting_user: user}) assert Enum.any?(activities, fn %{id: id} -> id == activity.id end) end @@ -1066,7 +1084,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert length(activities) == 3 activities = - ActivityPub.fetch_activities([user1.ap_id | User.following(user1)], %{"user" => user1}) + ActivityPub.fetch_activities([user1.ap_id | User.following(user1)], %{user: user1}) |> Enum.map(fn a -> a.id end) assert [public_activity.id, private_activity_1.id] == activities @@ -1115,7 +1133,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do CommonAPI.pin(activity_three.id, user) user = refresh_record(user) - activities = ActivityPub.fetch_user_activities(user, nil, %{"pinned" => "true"}) + activities = ActivityPub.fetch_user_activities(user, nil, %{pinned: true}) assert 3 = length(activities) end @@ -1226,7 +1244,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do activity = Repo.preload(activity, :bookmark) activity = %Activity{activity | thread_muted?: !!activity.thread_muted?} - assert ActivityPub.fetch_activities([], %{"user" => user}) == [activity] + assert ActivityPub.fetch_activities([], %{user: user}) == [activity] end def data_uri do @@ -1400,7 +1418,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id] - result = ActivityPub.fetch_favourites(user, %{"limit" => 2}) + result = ActivityPub.fetch_favourites(user, %{limit: 2}) assert Enum.map(result, & &1.id) == [a1.id, a5.id] end end @@ -1470,7 +1488,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _reply} = CommonAPI.post(user, %{status: "yeah", in_reply_to_status_id: activity.id}) - [result] = ActivityPub.fetch_public_activities(%{"exclude_replies" => "true"}) + [result] = ActivityPub.fetch_public_activities(%{exclude_replies: true}) assert result.id == activity.id @@ -1483,11 +1501,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "public timeline", %{users: %{u1: user}} do activities_ids = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", false) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:local_only, false) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_filtering_user, user) |> ActivityPub.fetch_public_activities() |> Enum.map(& &1.id) @@ -1504,12 +1522,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } do activities_ids = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", false) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("reply_visibility", "following") - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:local_only, false) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_visibility, "following") + |> Map.put(:reply_filtering_user, user) |> ActivityPub.fetch_public_activities() |> Enum.map(& &1.id) @@ -1531,12 +1549,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } do activities_ids = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", false) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("reply_visibility", "self") - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:local_only, false) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_visibility, "self") + |> Map.put(:reply_filtering_user, user) |> ActivityPub.fetch_public_activities() |> Enum.map(& &1.id) @@ -1555,11 +1573,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } do params = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) + |> Map.put(:reply_filtering_user, user) activities_ids = ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) @@ -1593,12 +1611,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } do params = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) - |> Map.put("reply_visibility", "following") - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) + |> Map.put(:reply_visibility, "following") + |> Map.put(:reply_filtering_user, user) activities_ids = ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) @@ -1632,12 +1650,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } do params = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) - |> Map.put("reply_visibility", "self") - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) + |> Map.put(:reply_visibility, "self") + |> Map.put(:reply_filtering_user, user) activities_ids = ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) @@ -1658,6 +1676,40 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert Enum.all?(visible_ids, &(&1 in activities_ids)) end + + test "filtering out announces where the user is the actor of the announced message" do + user = insert(:user) + other_user = insert(:user) + third_user = insert(:user) + User.follow(user, other_user) + + {:ok, post} = CommonAPI.post(user, %{status: "yo"}) + {:ok, other_post} = CommonAPI.post(third_user, %{status: "yo"}) + {:ok, _announce} = CommonAPI.repeat(post.id, other_user) + {:ok, _announce} = CommonAPI.repeat(post.id, third_user) + {:ok, announce} = CommonAPI.repeat(other_post.id, other_user) + + params = %{ + type: ["Announce"] + } + + results = + [user.ap_id | User.following(user)] + |> ActivityPub.fetch_activities(params) + + assert length(results) == 3 + + params = %{ + type: ["Announce"], + announce_filtering_user: user + } + + [result] = + [user.ap_id | User.following(user)] + |> ActivityPub.fetch_activities(params) + + assert result.id == announce.id + end end describe "replies filtering with private messages" do @@ -1666,11 +1718,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "public timeline", %{users: %{u1: user}} do activities_ids = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", false) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:local_only, false) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) |> ActivityPub.fetch_public_activities() |> Enum.map(& &1.id) @@ -1680,13 +1732,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "public timeline with default reply_visibility `following`", %{users: %{u1: user}} do activities_ids = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", false) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("reply_visibility", "following") - |> Map.put("reply_filtering_user", user) - |> Map.put("user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:local_only, false) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_visibility, "following") + |> Map.put(:reply_filtering_user, user) + |> Map.put(:user, user) |> ActivityPub.fetch_public_activities() |> Enum.map(& &1.id) @@ -1696,13 +1748,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "public timeline with default reply_visibility `self`", %{users: %{u1: user}} do activities_ids = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("local_only", false) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("reply_visibility", "self") - |> Map.put("reply_filtering_user", user) - |> Map.put("user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:local_only, false) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_visibility, "self") + |> Map.put(:reply_filtering_user, user) + |> Map.put(:user, user) |> ActivityPub.fetch_public_activities() |> Enum.map(& &1.id) @@ -1712,10 +1764,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "home timeline", %{users: %{u1: user}} do params = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) activities_ids = ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) @@ -1727,12 +1779,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "home timeline with default reply_visibility `following`", %{users: %{u1: user}} do params = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) - |> Map.put("reply_visibility", "following") - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) + |> Map.put(:reply_visibility, "following") + |> Map.put(:reply_filtering_user, user) activities_ids = ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) @@ -1751,12 +1803,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do } do params = %{} - |> Map.put("type", ["Create", "Announce"]) - |> Map.put("blocking_user", user) - |> Map.put("muting_user", user) - |> Map.put("user", user) - |> Map.put("reply_visibility", "self") - |> Map.put("reply_filtering_user", user) + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:user, user) + |> Map.put(:reply_visibility, "self") + |> Map.put(:reply_filtering_user, user) activities_ids = ActivityPub.fetch_activities([user.ap_id | User.following(user)], params) @@ -2001,4 +2053,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end) =~ "Follower/Following counter update for #{user.ap_id} failed" end end + + describe "global activity expiration" do + setup do: clear_config([:instance, :rewrite_policy]) + + test "creates an activity expiration for local Create activities" do + Pleroma.Config.put( + [:instance, :rewrite_policy], + Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy + ) + + {:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"}) + {:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"}) + + assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all() + end + end end diff --git a/test/web/activity_pub/mrf/activity_expiration_policy_test.exs b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs new file mode 100644 index 000000000..8babf49e7 --- /dev/null +++ b/test/web/activity_pub/mrf/activity_expiration_policy_test.exs @@ -0,0 +1,77 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do + use ExUnit.Case, async: true + alias Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy + + @id Pleroma.Web.Endpoint.url() <> "/activities/cofe" + + test "adds `expires_at` property" do + assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} = + ActivityExpirationPolicy.filter(%{ + "id" => @id, + "type" => "Create", + "object" => %{"type" => "Note"} + }) + + assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364 + end + + test "keeps existing `expires_at` if it less than the config setting" do + expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: 1) + + assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} = + ActivityExpirationPolicy.filter(%{ + "id" => @id, + "type" => "Create", + "expires_at" => expires_at, + "object" => %{"type" => "Note"} + }) + end + + test "overwrites existing `expires_at` if it greater than the config setting" do + too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2) + + assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} = + ActivityExpirationPolicy.filter(%{ + "id" => @id, + "type" => "Create", + "expires_at" => too_distant_future, + "object" => %{"type" => "Note"} + }) + + assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364 + end + + test "ignores remote activities" do + assert {:ok, activity} = + ActivityExpirationPolicy.filter(%{ + "id" => "https://example.com/123", + "type" => "Create", + "object" => %{"type" => "Note"} + }) + + refute Map.has_key?(activity, "expires_at") + end + + test "ignores non-Create/Note activities" do + assert {:ok, activity} = + ActivityExpirationPolicy.filter(%{ + "id" => "https://example.com/123", + "type" => "Follow" + }) + + refute Map.has_key?(activity, "expires_at") + + assert {:ok, activity} = + ActivityExpirationPolicy.filter(%{ + "id" => "https://example.com/123", + "type" => "Create", + "object" => %{"type" => "Cofe"} + }) + + refute Map.has_key?(activity, "expires_at") + end +end 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 724bae058..ba1b69658 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 - setup do: clear_config([:mrf_user_allowlist, :localhost]) + setup do: clear_config(:mrf_user_allowlist) test "pass filter if allow list is empty" do actor = insert(:user) @@ -17,14 +17,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do test "pass filter if allow list isn't empty and user in allow list" do actor = insert(:user) - Pleroma.Config.put([:mrf_user_allowlist, :localhost], [actor.ap_id, "test-ap-id"]) + Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => [actor.ap_id, "test-ap-id"]}) message = %{"actor" => actor.ap_id} assert UserAllowListPolicy.filter(message) == {:ok, message} end test "rejected if allow list isn't empty and user not in allow list" do actor = insert(:user) - Pleroma.Config.put([:mrf_user_allowlist, :localhost], ["test-ap-id"]) + Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]}) message = %{"actor" => actor.ap_id} assert UserAllowListPolicy.filter(message) == {:reject, nil} end diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index 7953eecf2..31224abe0 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -2,14 +2,264 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do use Pleroma.DataCase alias Pleroma.Object + alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.ObjectValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.CommonAPI import Pleroma.Factory + describe "attachments" do + test "works with honkerific attachments" do + attachment = %{ + "mediaType" => "", + "name" => "", + "summary" => "298p3RG7j27tfsZ9RQ.jpg", + "type" => "Document", + "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" + } + + assert {:ok, attachment} = + AttachmentValidator.cast_and_validate(attachment) + |> Ecto.Changeset.apply_action(:insert) + + assert attachment.mediaType == "application/octet-stream" + end + + test "it turns mastodon attachments into our attachments" do + attachment = %{ + "url" => + "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg", + "type" => "Document", + "name" => nil, + "mediaType" => "image/jpeg" + } + + {:ok, attachment} = + AttachmentValidator.cast_and_validate(attachment) + |> Ecto.Changeset.apply_action(:insert) + + assert [ + %{ + href: + "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg", + type: "Link", + mediaType: "image/jpeg" + } + ] = attachment.url + + assert attachment.mediaType == "image/jpeg" + end + + test "it handles our own uploads" do + user = insert(:user) + + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + + {:ok, attachment} = + attachment.data + |> AttachmentValidator.cast_and_validate() + |> Ecto.Changeset.apply_action(:insert) + + assert attachment.mediaType == "image/jpeg" + end + end + + describe "chat message create activities" do + test "it is invalid if the object already exists" do + user = insert(:user) + recipient = insert(:user) + {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey") + object = Object.normalize(activity, false) + + {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id]) + + {:error, cng} = ObjectValidator.validate(create_data, []) + + assert {:object, {"The object to create already exists", []}} in cng.errors + end + + test "it is invalid if the object data has a different `to` or `actor` field" do + user = insert(:user) + recipient = insert(:user) + {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey") + + {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id]) + + {:error, cng} = ObjectValidator.validate(create_data, []) + + assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors + assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors + end + end + + describe "chat messages" do + setup do + clear_config([:instance, :remote_limit]) + user = insert(:user) + recipient = insert(:user, local: false) + + {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:") + + %{user: user, recipient: recipient, valid_chat_message: valid_chat_message} + end + + test "let's through some basic html", %{user: user, recipient: recipient} do + {:ok, valid_chat_message, _} = + Builder.chat_message( + user, + recipient.ap_id, + "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>" + ) + + assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + + assert object["content"] == + "hey <a href=\"https://example.org\">example</a> alert('uguu')" + end + + test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do + assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + + assert Map.put(valid_chat_message, "attachment", nil) == object + end + + test "validates for a basic object with an attachment", %{ + valid_chat_message: valid_chat_message, + user: user + } do + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + + valid_chat_message = + valid_chat_message + |> Map.put("attachment", attachment.data) + + assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + + assert object["attachment"] + end + + test "validates for a basic object with an attachment in an array", %{ + valid_chat_message: valid_chat_message, + user: user + } do + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + + valid_chat_message = + valid_chat_message + |> Map.put("attachment", [attachment.data]) + + assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + + assert object["attachment"] + end + + test "validates for a basic object with an attachment but without content", %{ + valid_chat_message: valid_chat_message, + user: user + } do + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) + + valid_chat_message = + valid_chat_message + |> Map.put("attachment", attachment.data) + |> Map.delete("content") + + assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + + assert object["attachment"] + end + + test "does not validate if the message has no content", %{ + valid_chat_message: valid_chat_message + } do + contentless = + valid_chat_message + |> Map.delete("content") + + refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, [])) + end + + test "does not validate if the message is longer than the remote_limit", %{ + valid_chat_message: valid_chat_message + } do + Pleroma.Config.put([:instance, :remote_limit], 2) + refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) + end + + test "does not validate if the recipient is blocking the actor", %{ + valid_chat_message: valid_chat_message, + user: user, + recipient: recipient + } do + Pleroma.User.block(recipient, user) + refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) + end + + test "does not validate if the actor or the recipient is not in our system", %{ + valid_chat_message: valid_chat_message + } do + chat_message = + valid_chat_message + |> Map.put("actor", "https://raymoo.com/raymoo") + + {:error, _} = ObjectValidator.validate(chat_message, []) + + chat_message = + valid_chat_message + |> Map.put("to", ["https://raymoo.com/raymoo"]) + + {:error, _} = ObjectValidator.validate(chat_message, []) + end + + test "does not validate for a message with multiple recipients", %{ + valid_chat_message: valid_chat_message, + user: user, + recipient: recipient + } do + chat_message = + valid_chat_message + |> Map.put("to", [user.ap_id, recipient.ap_id]) + + assert {:error, _} = ObjectValidator.validate(chat_message, []) + end + + test "does not validate if it doesn't concern local users" do + user = insert(:user, local: false) + recipient = insert(:user, local: false) + + {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey") + assert {:error, _} = ObjectValidator.validate(valid_chat_message, []) + end + end + describe "EmojiReacts" do setup do user = insert(:user) diff --git a/test/web/activity_pub/object_validators/types/object_id_test.exs b/test/web/activity_pub/object_validators/types/object_id_test.exs index 834213182..c8911948e 100644 --- a/test/web/activity_pub/object_validators/types/object_id_test.exs +++ b/test/web/activity_pub/object_validators/types/object_id_test.exs @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.ObjectValidators.Types.ObjectIDTest do alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID use Pleroma.DataCase diff --git a/test/web/activity_pub/object_validators/types/safe_text_test.exs b/test/web/activity_pub/object_validators/types/safe_text_test.exs new file mode 100644 index 000000000..d4a574554 --- /dev/null +++ b/test/web/activity_pub/object_validators/types/safe_text_test.exs @@ -0,0 +1,30 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeTextTest do + use Pleroma.DataCase + + alias Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeText + + test "it lets normal text go through" do + text = "hey how are you" + assert {:ok, text} == SafeText.cast(text) + end + + test "it removes html tags from text" do + text = "hey look xss <script>alert('foo')</script>" + assert {:ok, "hey look xss alert('foo')"} == SafeText.cast(text) + end + + test "it keeps basic html tags" do + text = "hey <a href='http://gensokyo.2hu'>look</a> xss <script>alert('foo')</script>" + + assert {:ok, "hey <a href=\"http://gensokyo.2hu\">look</a> xss alert('foo')"} == + SafeText.cast(text) + end + + test "errors for non-text" do + assert :error == SafeText.cast(1) + end +end diff --git a/test/web/activity_pub/pipeline_test.exs b/test/web/activity_pub/pipeline_test.exs index 26557720b..8deb64501 100644 --- a/test/web/activity_pub/pipeline_test.exs +++ b/test/web/activity_pub/pipeline_test.exs @@ -33,7 +33,10 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do { Pleroma.Web.ActivityPub.SideEffects, [], - [handle: fn o, m -> {:ok, o, m} end] + [ + handle: fn o, m -> {:ok, o, m} end, + handle_after_transaction: fn m -> m end + ] }, { Pleroma.Web.Federator, @@ -71,7 +74,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do { Pleroma.Web.ActivityPub.SideEffects, [], - [handle: fn o, m -> {:ok, o, m} end] + [handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end] }, { Pleroma.Web.Federator, @@ -110,7 +113,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do { Pleroma.Web.ActivityPub.SideEffects, [], - [handle: fn o, m -> {:ok, o, m} end] + [handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end] }, { Pleroma.Web.Federator, diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index a80104ea7..6bbbaae87 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -7,6 +7,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do use Pleroma.DataCase alias Pleroma.Activity + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo @@ -20,6 +22,48 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do import Pleroma.Factory import Mock + describe "handle_after_transaction" do + test "it streams out notifications and streams" do + author = insert(:user, local: true) + recipient = insert(:user, local: true) + + {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + + {:ok, create_activity_data, _meta} = + Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, meta} = + SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + + assert [notification] = meta[:notifications] + + with_mocks([ + { + Pleroma.Web.Streamer, + [], + [ + stream: fn _, _ -> nil end + ] + }, + { + Pleroma.Web.Push, + [], + [ + send: fn _ -> nil end + ] + } + ]) do + SideEffects.handle_after_transaction(meta) + + assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification)) + assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_)) + assert called(Pleroma.Web.Push.send(notification)) + end + end + end + describe "delete objects" do setup do user = insert(:user) @@ -290,6 +334,147 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do end end + describe "creation of ChatMessages" do + test "notifies the recipient" do + author = insert(:user, local: false) + recipient = insert(:user, local: true) + + {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + + {:ok, create_activity_data, _meta} = + Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, _meta} = + SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + + assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id) + end + + test "it streams the created ChatMessage" do + author = insert(:user, local: true) + recipient = insert(:user, local: true) + + {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + + {:ok, create_activity_data, _meta} = + Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, meta} = + SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + + assert [_, _] = meta[:streamables] + end + + test "it creates a Chat and MessageReferences for the local users and bumps the unread count, except for the author" do + author = insert(:user, local: true) + recipient = insert(:user, local: true) + + {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + + {:ok, create_activity_data, _meta} = + Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + with_mocks([ + { + Pleroma.Web.Streamer, + [], + [ + stream: fn _, _ -> nil end + ] + }, + { + Pleroma.Web.Push, + [], + [ + send: fn _ -> nil end + ] + } + ]) do + {:ok, _create_activity, meta} = + SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + + # The notification gets created + assert [notification] = meta[:notifications] + assert notification.activity_id == create_activity.id + + # But it is not sent out + refute called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification)) + refute called(Pleroma.Web.Push.send(notification)) + + # Same for the user chat stream + assert [{topics, _}, _] = meta[:streamables] + assert topics == ["user", "user:pleroma_chat"] + refute called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_)) + + chat = Chat.get(author.id, recipient.ap_id) + + [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all() + + assert cm_ref.object.data["content"] == "hey" + assert cm_ref.unread == false + + chat = Chat.get(recipient.id, author.ap_id) + + [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all() + + assert cm_ref.object.data["content"] == "hey" + assert cm_ref.unread == true + end + end + + test "it creates a Chat for the local users and bumps the unread count" do + author = insert(:user, local: false) + recipient = insert(:user, local: true) + + {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + + {:ok, create_activity_data, _meta} = + Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, _meta} = + SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + + # An object is created + assert Object.get_by_ap_id(chat_message_data["id"]) + + # The remote user won't get a chat + chat = Chat.get(author.id, recipient.ap_id) + refute chat + + # The local user will get a chat + chat = Chat.get(recipient.id, author.ap_id) + assert chat + + author = insert(:user, local: true) + recipient = insert(:user, local: true) + + {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + + {:ok, create_activity_data, _meta} = + Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, _meta} = + SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + + # Both users are local and get the chat + chat = Chat.get(author.id, recipient.ap_id) + assert chat + + chat = Chat.get(recipient.id, author.ap_id) + assert chat + end + end + describe "announce objects" do setup do poster = insert(:user) diff --git a/test/web/activity_pub/transmogrifier/chat_message_test.exs b/test/web/activity_pub/transmogrifier/chat_message_test.exs new file mode 100644 index 000000000..d6736dc3e --- /dev/null +++ b/test/web/activity_pub/transmogrifier/chat_message_test.exs @@ -0,0 +1,153 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.Transmogrifier.ChatMessageTest do + use Pleroma.DataCase + + import Pleroma.Factory + + alias Pleroma.Activity + alias Pleroma.Chat + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.Transmogrifier + + describe "handle_incoming" do + test "handles chonks with attachment" do + data = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "actor" => "https://honk.tedunangst.com/u/tedu", + "id" => "https://honk.tedunangst.com/u/tedu/honk/x6gt8X8PcyGkQcXxzg1T", + "object" => %{ + "attachment" => [ + %{ + "mediaType" => "image/jpeg", + "name" => "298p3RG7j27tfsZ9RQ.jpg", + "summary" => "298p3RG7j27tfsZ9RQ.jpg", + "type" => "Document", + "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" + } + ], + "attributedTo" => "https://honk.tedunangst.com/u/tedu", + "content" => "", + "id" => "https://honk.tedunangst.com/u/tedu/chonk/26L4wl5yCbn4dr4y1b", + "published" => "2020-05-18T01:13:03Z", + "to" => [ + "https://dontbulling.me/users/lain" + ], + "type" => "ChatMessage" + }, + "published" => "2020-05-18T01:13:03Z", + "to" => [ + "https://dontbulling.me/users/lain" + ], + "type" => "Create" + } + + _user = insert(:user, ap_id: data["actor"]) + _user = insert(:user, ap_id: hd(data["to"])) + + assert {:ok, _activity} = Transmogrifier.handle_incoming(data) + end + + test "it rejects messages that don't contain content" do + data = + File.read!("test/fixtures/create-chat-message.json") + |> Poison.decode!() + + object = + data["object"] + |> Map.delete("content") + + data = + data + |> Map.put("object", object) + + _author = + insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) + + _recipient = + insert(:user, + ap_id: List.first(data["to"]), + local: true, + last_refreshed_at: DateTime.utc_now() + ) + + {:error, _} = Transmogrifier.handle_incoming(data) + end + + test "it rejects messages that don't concern local users" do + data = + File.read!("test/fixtures/create-chat-message.json") + |> Poison.decode!() + + _author = + insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) + + _recipient = + insert(:user, + ap_id: List.first(data["to"]), + local: false, + last_refreshed_at: DateTime.utc_now() + ) + + {:error, _} = Transmogrifier.handle_incoming(data) + end + + test "it rejects messages where the `to` field of activity and object don't match" do + data = + File.read!("test/fixtures/create-chat-message.json") + |> Poison.decode!() + + author = insert(:user, ap_id: data["actor"]) + _recipient = insert(:user, ap_id: List.first(data["to"])) + + data = + data + |> Map.put("to", author.ap_id) + + assert match?({:error, _}, Transmogrifier.handle_incoming(data)) + refute Object.get_by_ap_id(data["object"]["id"]) + end + + test "it fetches the actor if they aren't in our system" do + Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + + data = + File.read!("test/fixtures/create-chat-message.json") + |> Poison.decode!() + |> Map.put("actor", "http://mastodon.example.org/users/admin") + |> put_in(["object", "actor"], "http://mastodon.example.org/users/admin") + + _recipient = insert(:user, ap_id: List.first(data["to"]), local: true) + + {:ok, %Activity{} = _activity} = Transmogrifier.handle_incoming(data) + end + + test "it inserts it and creates a chat" do + data = + File.read!("test/fixtures/create-chat-message.json") + |> Poison.decode!() + + author = + insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) + + recipient = insert(:user, ap_id: List.first(data["to"]), local: true) + + {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(data) + assert activity.local == false + + assert activity.actor == author.ap_id + assert activity.recipients == [recipient.ap_id, author.ap_id] + + %Object{} = object = Object.get_by_ap_id(activity.data["object"]) + + assert object + assert object.data["content"] == "You expected a cute girl? Too bad. alert('XSS')" + assert match?(%{"firefox" => _}, object.data["emoji"]) + + refute Chat.get(author.id, recipient.ap_id) + assert Chat.get(recipient.id, author.ap_id) + end + end +end diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index 967389fae..06c39eed6 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -5,6 +5,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do use Pleroma.DataCase alias Pleroma.Activity + alias Pleroma.Notification alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.ActivityPub.Transmogrifier @@ -12,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do import Pleroma.Factory import Ecto.Query + import Mock setup_all do Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -57,9 +59,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do activity = Repo.get(Activity, activity.id) assert activity.data["state"] == "accept" assert User.following?(User.get_cached_by_ap_id(data["actor"]), user) + + [notification] = Notification.for_user(user) + assert notification.type == "follow" end - test "with locked accounts, it does not create a follow or an accept" do + test "with locked accounts, it does create a Follow, but not an Accept" do user = insert(:user, locked: true) data = @@ -81,6 +86,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do |> Repo.all() assert Enum.empty?(accepts) + + [notification] = Notification.for_user(user) + assert notification.type == "follow_request" end test "it works for follow requests when you are already followed, creating a new accept activity" do @@ -144,6 +152,23 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do assert activity.data["state"] == "reject" end + test "it rejects incoming follow requests if the following errors for some reason" do + user = insert(:user) + + data = + File.read!("test/fixtures/mastodon-follow-activity.json") + |> Poison.decode!() + |> Map.put("object", user.ap_id) + + with_mock Pleroma.User, [:passthrough], follow: fn _, _ -> {:error, :testing} end do + {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data) + + %Activity{} = activity = Activity.get_by_ap_id(id) + + assert activity.data["state"] == "reject" + end + end + test "it works for incoming follow requests from hubzilla" do user = insert(:user) diff --git a/test/web/admin_api/controllers/admin_api_controller_test.exs b/test/web/admin_api/controllers/admin_api_controller_test.exs index 2aaec510d..e3d3ccb8d 100644 --- a/test/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/web/admin_api/controllers/admin_api_controller_test.exs @@ -337,7 +337,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } assert expected == json_response(conn, 200) @@ -614,7 +615,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), "display_name" => HTML.strip_tags(admin.name || admin.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => admin.ap_id }, %{ "deactivated" => user.deactivated, @@ -625,7 +627,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => ["foo", "bar"], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] |> Enum.sort_by(& &1["nickname"]) @@ -697,7 +700,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -722,7 +726,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -747,7 +752,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -772,7 +778,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -797,7 +804,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -822,7 +830,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -842,7 +851,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user2) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user2.name || user2.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user2.ap_id } ] } @@ -874,7 +884,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -899,7 +910,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id }, %{ "deactivated" => admin.deactivated, @@ -910,7 +922,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), "display_name" => HTML.strip_tags(admin.name || admin.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => admin.ap_id }, %{ "deactivated" => false, @@ -921,7 +934,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(), "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => old_admin.ap_id } ] |> Enum.sort_by(& &1["nickname"]) @@ -951,7 +965,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), "display_name" => HTML.strip_tags(admin.name || admin.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => admin.ap_id }, %{ "deactivated" => false, @@ -962,7 +977,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(), "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => second_admin.ap_id } ] |> Enum.sort_by(& &1["nickname"]) @@ -994,7 +1010,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(moderator) |> MediaProxy.url(), "display_name" => HTML.strip_tags(moderator.name || moderator.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => moderator.ap_id } ] } @@ -1019,7 +1036,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => ["first"], "avatar" => User.avatar_url(user1) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user1.name || user1.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user1.ap_id }, %{ "deactivated" => false, @@ -1030,7 +1048,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => ["second"], "avatar" => User.avatar_url(user2) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user2.name || user2.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user2.ap_id } ] |> Enum.sort_by(& &1["nickname"]) @@ -1069,7 +1088,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } ] } @@ -1093,7 +1113,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), "display_name" => HTML.strip_tags(admin.name || admin.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => admin.ap_id } ] } @@ -1155,7 +1176,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false + "confirmation_pending" => false, + "url" => user.ap_id } log_entry = Repo.one(ModerationLog) @@ -1604,57 +1626,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end end - describe "relays" do - test "POST /relay", %{conn: conn, admin: admin} do - conn = - post(conn, "/api/pleroma/admin/relay", %{ - relay_url: "http://mastodon.example.org/users/admin" - }) - - assert json_response(conn, 200) == "http://mastodon.example.org/users/admin" - - log_entry = Repo.one(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" - end - - test "GET /relay", %{conn: conn} do - relay_user = Pleroma.Web.ActivityPub.Relay.get_actor() - - ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"] - |> Enum.each(fn ap_id -> - {:ok, user} = User.get_or_fetch_by_ap_id(ap_id) - User.follow(relay_user, user) - end) - - conn = get(conn, "/api/pleroma/admin/relay") - - assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == [] - end - - test "DELETE /relay", %{conn: conn, admin: admin} do - post(conn, "/api/pleroma/admin/relay", %{ - relay_url: "http://mastodon.example.org/users/admin" - }) - - conn = - delete(conn, "/api/pleroma/admin/relay", %{ - relay_url: "http://mastodon.example.org/users/admin" - }) - - assert json_response(conn, 200) == "http://mastodon.example.org/users/admin" - - [log_entry_one, log_entry_two] = Repo.all(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry_one) == - "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" - - assert ModerationLog.get_log_entry_message(log_entry_two) == - "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin" - end - end - describe "instances" do test "GET /instances/:instance/statuses", %{conn: conn} do user = insert(:user, local: false, nickname: "archaeme@archae.me") diff --git a/test/web/admin_api/controllers/config_controller_test.exs b/test/web/admin_api/controllers/config_controller_test.exs index 780de8d18..064ef9bc7 100644 --- a/test/web/admin_api/controllers/config_controller_test.exs +++ b/test/web/admin_api/controllers/config_controller_test.exs @@ -57,12 +57,12 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ] } = json_response_and_validate_schema(conn, 200) - assert key1 == config1.key - assert key2 == config2.key + assert key1 == inspect(config1.key) + assert key2 == inspect(config2.key) end test "db is added to settings that are in db", %{conn: conn} do - _config = insert(:config, key: ":instance", value: ConfigDB.to_binary(name: "Some name")) + _config = insert(:config, key: ":instance", value: [name: "Some name"]) %{"configs" => configs} = conn @@ -83,7 +83,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do config3 = insert(:config, - value: ConfigDB.to_binary(k1: :v1, k2: :v2) + value: [k1: :v1, k2: :v2] ) %{"configs" => configs} = @@ -93,42 +93,45 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do assert length(configs) > 3 + saved_configs = [config1, config2, config3] + keys = Enum.map(saved_configs, &inspect(&1.key)) + received_configs = Enum.filter(configs, fn %{"group" => group, "key" => key} -> - group == ":pleroma" and key in [config1.key, config2.key, config3.key] + group == ":pleroma" and key in keys end) assert length(received_configs) == 3 db_keys = config3.value - |> ConfigDB.from_binary() |> Keyword.keys() - |> ConfigDB.convert() + |> ConfigDB.to_json_types() + + keys = Enum.map(saved_configs -- [config3], &inspect(&1.key)) + + values = Enum.map(saved_configs, &ConfigDB.to_json_types(&1.value)) + + mapset_keys = MapSet.new(keys ++ db_keys) Enum.each(received_configs, fn %{"value" => value, "db" => db} -> - assert db in [[config1.key], [config2.key], db_keys] + db = MapSet.new(db) + assert MapSet.subset?(db, mapset_keys) - assert value in [ - ConfigDB.from_binary_with_convert(config1.value), - ConfigDB.from_binary_with_convert(config2.value), - ConfigDB.from_binary_with_convert(config3.value) - ] + assert value in values end) end test "subkeys with full update right merge", %{conn: conn} do - config1 = - insert(:config, - key: ":emoji", - value: ConfigDB.to_binary(groups: [a: 1, b: 2], key: [a: 1]) - ) + insert(:config, + key: ":emoji", + value: [groups: [a: 1, b: 2], key: [a: 1]] + ) - config2 = - insert(:config, - key: ":assets", - value: ConfigDB.to_binary(mascots: [a: 1, b: 2], key: [a: 1]) - ) + insert(:config, + key: ":assets", + value: [mascots: [a: 1, b: 2], key: [a: 1]] + ) %{"configs" => configs} = conn @@ -137,14 +140,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do vals = Enum.filter(configs, fn %{"group" => group, "key" => key} -> - group == ":pleroma" and key in [config1.key, config2.key] + group == ":pleroma" and key in [":emoji", ":assets"] end) emoji = Enum.find(vals, fn %{"key" => key} -> key == ":emoji" end) assets = Enum.find(vals, fn %{"key" => key} -> key == ":assets" end) - emoji_val = ConfigDB.transform_with_out_binary(emoji["value"]) - assets_val = ConfigDB.transform_with_out_binary(assets["value"]) + emoji_val = ConfigDB.to_elixir_types(emoji["value"]) + assets_val = ConfigDB.to_elixir_types(assets["value"]) assert emoji_val[:groups] == [a: 1, b: 2] assert assets_val[:mascots] == [a: 1, b: 2] @@ -277,7 +280,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}, "db" => [":key5"] } - ] + ], + "need_reboot" => false } assert Application.get_env(:pleroma, :key1) == "value1" @@ -357,7 +361,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do "value" => "https://hooks.slack.com/services/KEY", "db" => [":webhook_url"] } - ] + ], + "need_reboot" => false } assert Application.get_env(:quack, :level) == :info @@ -366,14 +371,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do end test "saving config with partial update", %{conn: conn} do - config = insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2)) + insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: 2)) conn = conn |> put_req_header("content-type", "application/json") |> post("/api/pleroma/admin/config", %{ configs: [ - %{group: config.group, key: config.key, value: [%{"tuple" => [":key3", 3]}]} + %{group: ":pleroma", key: ":key1", value: [%{"tuple" => [":key3", 3]}]} ] }) @@ -389,7 +394,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ], "db" => [":key1", ":key2", ":key3"] } - ] + ], + "need_reboot" => false } end @@ -500,8 +506,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do end test "saving config with nested merge", %{conn: conn} do - config = - insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2])) + insert(:config, key: :key1, value: [key1: 1, key2: [k1: 1, k2: 2]]) conn = conn @@ -509,8 +514,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do |> post("/api/pleroma/admin/config", %{ configs: [ %{ - group: config.group, - key: config.key, + group: ":pleroma", + key: ":key1", value: [ %{"tuple" => [":key3", 3]}, %{ @@ -548,7 +553,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ], "db" => [":key1", ":key3", ":key2"] } - ] + ], + "need_reboot" => false } end @@ -588,7 +594,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ], "db" => [":ssl_options"] } - ] + ], + "need_reboot" => false } assert Application.get_env(:pleroma, :key1) == [ @@ -600,12 +607,11 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do backends = Application.get_env(:logger, :backends) on_exit(fn -> Application.put_env(:logger, :backends, backends) end) - config = - insert(:config, - group: ":logger", - key: ":backends", - value: :erlang.term_to_binary([]) - ) + insert(:config, + group: :logger, + key: :backends, + value: [] + ) Pleroma.Config.TransferTask.load_and_update_env([], false) @@ -617,8 +623,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do |> post("/api/pleroma/admin/config", %{ configs: [ %{ - group: config.group, - key: config.key, + group: ":logger", + key: ":backends", value: [":console"] } ] @@ -634,7 +640,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ], "db" => [":backends"] } - ] + ], + "need_reboot" => false } assert Application.get_env(:logger, :backends) == [ @@ -643,19 +650,18 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do end test "saving full setting if value is not keyword", %{conn: conn} do - config = - insert(:config, - group: ":tesla", - key: ":adapter", - value: :erlang.term_to_binary(Tesla.Adapter.Hackey) - ) + insert(:config, + group: :tesla, + key: :adapter, + value: Tesla.Adapter.Hackey + ) conn = conn |> put_req_header("content-type", "application/json") |> post("/api/pleroma/admin/config", %{ configs: [ - %{group: config.group, key: config.key, value: "Tesla.Adapter.Httpc"} + %{group: ":tesla", key: ":adapter", value: "Tesla.Adapter.Httpc"} ] }) @@ -667,7 +673,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do "value" => "Tesla.Adapter.Httpc", "db" => [":adapter"] } - ] + ], + "need_reboot" => false } end @@ -677,13 +684,13 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do token: token } do ueberauth = Application.get_env(:ueberauth, Ueberauth) - config1 = insert(:config, key: ":keyaa1") - config2 = insert(:config, key: ":keyaa2") + insert(:config, key: :keyaa1) + insert(:config, key: :keyaa2) config3 = insert(:config, - group: ":ueberauth", - key: "Ueberauth" + group: :ueberauth, + key: Ueberauth ) conn = @@ -691,8 +698,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do |> put_req_header("content-type", "application/json") |> post("/api/pleroma/admin/config", %{ configs: [ - %{group: config1.group, key: config1.key, value: "another_value"}, - %{group: config2.group, key: config2.key, value: "another_value"} + %{group: ":pleroma", key: ":keyaa1", value: "another_value"}, + %{group: ":pleroma", key: ":keyaa2", value: "another_value"} ] }) @@ -700,22 +707,23 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do "configs" => [ %{ "group" => ":pleroma", - "key" => config1.key, + "key" => ":keyaa1", "value" => "another_value", "db" => [":keyaa1"] }, %{ "group" => ":pleroma", - "key" => config2.key, + "key" => ":keyaa2", "value" => "another_value", "db" => [":keyaa2"] } - ] + ], + "need_reboot" => false } assert Application.get_env(:pleroma, :keyaa1) == "another_value" assert Application.get_env(:pleroma, :keyaa2) == "another_value" - assert Application.get_env(:ueberauth, Ueberauth) == ConfigDB.from_binary(config3.value) + assert Application.get_env(:ueberauth, Ueberauth) == config3.value conn = build_conn() @@ -724,7 +732,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do |> put_req_header("content-type", "application/json") |> post("/api/pleroma/admin/config", %{ configs: [ - %{group: config2.group, key: config2.key, delete: true}, + %{group: ":pleroma", key: ":keyaa2", delete: true}, %{ group: ":ueberauth", key: "Ueberauth", @@ -734,7 +742,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do }) assert json_response_and_validate_schema(conn, 200) == %{ - "configs" => [] + "configs" => [], + "need_reboot" => false } assert Application.get_env(:ueberauth, Ueberauth) == ueberauth @@ -801,7 +810,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ":name" ] } - ] + ], + "need_reboot" => false } end @@ -935,7 +945,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ], "db" => [":http"] } - ] + ], + "need_reboot" => false } end @@ -1000,7 +1011,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ], "db" => [":key2", ":key3"] } - ] + ], + "need_reboot" => false } end @@ -1027,7 +1039,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do "value" => %{"key" => "some_val"}, "db" => [":key1"] } - ] + ], + "need_reboot" => false } end @@ -1077,16 +1090,16 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do ":background" ] } - ] + ], + "need_reboot" => false } end test "delete part of settings by atom subkeys", %{conn: conn} do - config = - insert(:config, - key: ":keyaa1", - value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3") - ) + insert(:config, + key: :keyaa1, + value: [subkey1: "val1", subkey2: "val2", subkey3: "val3"] + ) conn = conn @@ -1094,8 +1107,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do |> post("/api/pleroma/admin/config", %{ configs: [ %{ - group: config.group, - key: config.key, + group: ":pleroma", + key: ":keyaa1", subkeys: [":subkey1", ":subkey3"], delete: true } @@ -1110,7 +1123,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do "value" => [%{"tuple" => [":subkey2", "val2"]}], "db" => [":subkey2"] } - ] + ], + "need_reboot" => false } end @@ -1236,6 +1250,90 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do assert Application.get_env(:pleroma, Pleroma.Captcha.NotReal) == "value5" assert Application.get_env(:not_real, :anything) == "value6" end + + test "args for Pleroma.Upload.Filter.Mogrify with custom tuples", %{conn: conn} do + clear_config(Pleroma.Upload.Filter.Mogrify) + + assert conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/config", %{ + configs: [ + %{ + group: ":pleroma", + key: "Pleroma.Upload.Filter.Mogrify", + value: [ + %{"tuple" => [":args", ["auto-orient", "strip"]]} + ] + } + ] + }) + |> json_response_and_validate_schema(200) == %{ + "configs" => [ + %{ + "group" => ":pleroma", + "key" => "Pleroma.Upload.Filter.Mogrify", + "value" => [ + %{"tuple" => [":args", ["auto-orient", "strip"]]} + ], + "db" => [":args"] + } + ], + "need_reboot" => false + } + + assert Config.get(Pleroma.Upload.Filter.Mogrify) == [args: ["auto-orient", "strip"]] + + assert conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/config", %{ + configs: [ + %{ + group: ":pleroma", + key: "Pleroma.Upload.Filter.Mogrify", + value: [ + %{ + "tuple" => [ + ":args", + [ + "auto-orient", + "strip", + "{\"implode\", \"1\"}", + "{\"resize\", \"3840x1080>\"}" + ] + ] + } + ] + } + ] + }) + |> json_response(200) == %{ + "configs" => [ + %{ + "group" => ":pleroma", + "key" => "Pleroma.Upload.Filter.Mogrify", + "value" => [ + %{ + "tuple" => [ + ":args", + [ + "auto-orient", + "strip", + "{\"implode\", \"1\"}", + "{\"resize\", \"3840x1080>\"}" + ] + ] + } + ], + "db" => [":args"] + } + ], + "need_reboot" => false + } + + assert Config.get(Pleroma.Upload.Filter.Mogrify) == [ + args: ["auto-orient", "strip", {"implode", "1"}, {"resize", "3840x1080>"}] + ] + end end describe "GET /api/pleroma/admin/config/descriptions" do diff --git a/test/web/admin_api/controllers/relay_controller_test.exs b/test/web/admin_api/controllers/relay_controller_test.exs new file mode 100644 index 000000000..64086adc5 --- /dev/null +++ b/test/web/admin_api/controllers/relay_controller_test.exs @@ -0,0 +1,92 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.RelayControllerTest do + use Pleroma.Web.ConnCase + + import Pleroma.Factory + + alias Pleroma.Config + alias Pleroma.ModerationLog + alias Pleroma.Repo + alias Pleroma.User + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + :ok + end + + setup do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "relays" do + test "POST /relay", %{conn: conn, admin: admin} do + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/relay", %{ + relay_url: "http://mastodon.example.org/users/admin" + }) + + assert json_response_and_validate_schema(conn, 200) == + "http://mastodon.example.org/users/admin" + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" + end + + test "GET /relay", %{conn: conn} do + relay_user = Pleroma.Web.ActivityPub.Relay.get_actor() + + ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"] + |> Enum.each(fn ap_id -> + {:ok, user} = User.get_or_fetch_by_ap_id(ap_id) + User.follow(relay_user, user) + end) + + conn = get(conn, "/api/pleroma/admin/relay") + + assert json_response_and_validate_schema(conn, 200)["relays"] -- + ["mastodon.example.org", "mstdn.io"] == [] + end + + test "DELETE /relay", %{conn: conn, admin: admin} do + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/admin/relay", %{ + relay_url: "http://mastodon.example.org/users/admin" + }) + + conn = + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/pleroma/admin/relay", %{ + relay_url: "http://mastodon.example.org/users/admin" + }) + + assert json_response_and_validate_schema(conn, 200) == + "http://mastodon.example.org/users/admin" + + [log_entry_one, log_entry_two] = Repo.all(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry_one) == + "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" + + assert ModerationLog.get_log_entry_message(log_entry_two) == + "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin" + end + end +end diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 2291f76dd..6bd26050e 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -5,7 +5,9 @@ defmodule Pleroma.Web.CommonAPITest do use Pleroma.DataCase alias Pleroma.Activity + alias Pleroma.Chat alias Pleroma.Conversation.Participation + alias Pleroma.Notification alias Pleroma.Object alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub @@ -23,6 +25,150 @@ defmodule Pleroma.Web.CommonAPITest do setup do: clear_config([:instance, :limit]) setup do: clear_config([:instance, :max_pinned_statuses]) + describe "posting chat messages" do + setup do: clear_config([:instance, :chat_limit]) + + test "it posts a chat message without content but with an attachment" do + author = insert(:user) + recipient = insert(:user) + + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, upload} = ActivityPub.upload(file, actor: author.ap_id) + + with_mocks([ + { + Pleroma.Web.Streamer, + [], + [ + stream: fn _, _ -> + nil + end + ] + }, + { + Pleroma.Web.Push, + [], + [ + send: fn _ -> nil end + ] + } + ]) do + {:ok, activity} = + CommonAPI.post_chat_message( + author, + recipient, + nil, + media_id: upload.id + ) + + notification = + Notification.for_user_and_activity(recipient, activity) + |> Repo.preload(:activity) + + assert called(Pleroma.Web.Push.send(notification)) + assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification)) + assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_)) + + assert activity + end + end + + test "it adds html newlines" do + author = insert(:user) + recipient = insert(:user) + + other_user = insert(:user) + + {:ok, activity} = + CommonAPI.post_chat_message( + author, + recipient, + "uguu\nuguuu" + ) + + assert other_user.ap_id not in activity.recipients + + object = Object.normalize(activity, false) + + assert object.data["content"] == "uguu<br/>uguuu" + end + + test "it linkifies" do + author = insert(:user) + recipient = insert(:user) + + other_user = insert(:user) + + {:ok, activity} = + CommonAPI.post_chat_message( + author, + recipient, + "https://example.org is the site of @#{other_user.nickname} #2hu" + ) + + assert other_user.ap_id not in activity.recipients + + object = Object.normalize(activity, false) + + assert object.data["content"] == + "<a href=\"https://example.org\" rel=\"ugc\">https://example.org</a> is the site of <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{ + other_user.id + }\" href=\"#{other_user.ap_id}\" rel=\"ugc\">@<span>#{other_user.nickname}</span></a></span> <a class=\"hashtag\" data-tag=\"2hu\" href=\"http://localhost:4001/tag/2hu\">#2hu</a>" + end + + test "it posts a chat message" do + author = insert(:user) + recipient = insert(:user) + + {:ok, activity} = + CommonAPI.post_chat_message( + author, + recipient, + "a test message <script>alert('uuu')</script> :firefox:" + ) + + assert activity.data["type"] == "Create" + assert activity.local + object = Object.normalize(activity) + + assert object.data["type"] == "ChatMessage" + assert object.data["to"] == [recipient.ap_id] + + assert object.data["content"] == + "a test message <script>alert('uuu')</script> :firefox:" + + assert object.data["emoji"] == %{ + "firefox" => "http://localhost:4001/emoji/Firefox.gif" + } + + assert Chat.get(author.id, recipient.ap_id) + assert Chat.get(recipient.id, author.ap_id) + + assert :ok == Pleroma.Web.Federator.perform(:publish, activity) + end + + test "it reject messages over the local limit" do + Pleroma.Config.put([:instance, :chat_limit], 2) + + author = insert(:user) + recipient = insert(:user) + + {:error, message} = + CommonAPI.post_chat_message( + author, + recipient, + "123" + ) + + assert message == :content_too_long + end + end + describe "unblocking" do test "it works even without an existing block activity" do blocked = insert(:user) diff --git a/test/web/mastodon_api/controllers/notification_controller_test.exs b/test/web/mastodon_api/controllers/notification_controller_test.exs index e278d61f5..70ef0e8b5 100644 --- a/test/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/web/mastodon_api/controllers/notification_controller_test.exs @@ -54,6 +54,27 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do assert response == expected_response end + test "by default, does not contain pleroma:chat_mention" do + %{user: user, conn: conn} = oauth_access(["read:notifications"]) + other_user = insert(:user) + + {:ok, _activity} = CommonAPI.post_chat_message(other_user, user, "hey") + + result = + conn + |> get("/api/v1/notifications") + |> json_response_and_validate_schema(200) + + assert [] == result + + result = + conn + |> get("/api/v1/notifications?include_types[]=pleroma:chat_mention") + |> json_response_and_validate_schema(200) + + assert [_] = result + end + test "getting a single notification" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) @@ -292,6 +313,33 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do assert public_activity.id in activity_ids refute unlisted_activity.id in activity_ids end + + test "doesn't return less than the requested amount of records when the user's reply is liked" do + user = insert(:user) + %{user: other_user, conn: conn} = oauth_access(["read:notifications"]) + + {:ok, mention} = + CommonAPI.post(user, %{status: "@#{other_user.nickname}", visibility: "public"}) + + {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "public"}) + + {:ok, reply} = + CommonAPI.post(other_user, %{ + status: ".", + visibility: "public", + in_reply_to_status_id: activity.id + }) + + {:ok, _favorite} = CommonAPI.favorite(user, reply.id) + + activity_ids = + conn + |> get("/api/v1/notifications?exclude_visibilities[]=direct&limit=2") + |> json_response_and_validate_schema(200) + |> Enum.map(& &1["status"]["id"]) + + assert [reply.id, mention.id] == activity_ids + end end test "filters notifications using exclude_types" do diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs index 84d46895e..c605957b1 100644 --- a/test/web/mastodon_api/controllers/search_controller_test.exs +++ b/test/web/mastodon_api/controllers/search_controller_test.exs @@ -111,6 +111,44 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do %{"name" => "prone", "url" => "#{Web.base_url()}/tag/prone"}, %{"name" => "AccidentProne", "url" => "#{Web.base_url()}/tag/AccidentProne"} ] + + results = + conn + |> get("/api/v2/search?#{URI.encode_query(%{q: "https://shpposter.club/users/shpuld"})}") + |> json_response_and_validate_schema(200) + + assert results["hashtags"] == [ + %{"name" => "shpuld", "url" => "#{Web.base_url()}/tag/shpuld"} + ] + + results = + conn + |> get( + "/api/v2/search?#{ + URI.encode_query(%{ + q: + "https://www.washingtonpost.com/sports/2020/06/10/" <> + "nascar-ban-display-confederate-flag-all-events-properties/" + }) + }" + ) + |> json_response_and_validate_schema(200) + + assert results["hashtags"] == [ + %{"name" => "nascar", "url" => "#{Web.base_url()}/tag/nascar"}, + %{"name" => "ban", "url" => "#{Web.base_url()}/tag/ban"}, + %{"name" => "display", "url" => "#{Web.base_url()}/tag/display"}, + %{"name" => "confederate", "url" => "#{Web.base_url()}/tag/confederate"}, + %{"name" => "flag", "url" => "#{Web.base_url()}/tag/flag"}, + %{"name" => "all", "url" => "#{Web.base_url()}/tag/all"}, + %{"name" => "events", "url" => "#{Web.base_url()}/tag/events"}, + %{"name" => "properties", "url" => "#{Web.base_url()}/tag/properties"}, + %{ + "name" => "NascarBanDisplayConfederateFlagAllEventsProperties", + "url" => + "#{Web.base_url()}/tag/NascarBanDisplayConfederateFlagAllEventsProperties" + } + ] end test "excludes a blocked users from search results", %{conn: conn} do diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index 700c82e4f..648e6f2ce 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -1541,14 +1541,49 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do } = response end + test "favorites paginate correctly" do + %{user: user, conn: conn} = oauth_access(["read:favourites"]) + other_user = insert(:user) + {:ok, first_post} = CommonAPI.post(other_user, %{status: "bla"}) + {:ok, second_post} = CommonAPI.post(other_user, %{status: "bla"}) + {:ok, third_post} = CommonAPI.post(other_user, %{status: "bla"}) + + {:ok, _first_favorite} = CommonAPI.favorite(user, third_post.id) + {:ok, _second_favorite} = CommonAPI.favorite(user, first_post.id) + {:ok, third_favorite} = CommonAPI.favorite(user, second_post.id) + + result = + conn + |> get("/api/v1/favourites?limit=1") + + assert [%{"id" => post_id}] = json_response_and_validate_schema(result, 200) + assert post_id == second_post.id + + # Using the header for pagination works correctly + [next, _] = get_resp_header(result, "link") |> hd() |> String.split(", ") + [_, max_id] = Regex.run(~r/max_id=(.*)>;/, next) + + assert max_id == third_favorite.id + + result = + conn + |> get("/api/v1/favourites?max_id=#{max_id}") + + assert [%{"id" => first_post_id}, %{"id" => third_post_id}] = + json_response_and_validate_schema(result, 200) + + assert first_post_id == first_post.id + assert third_post_id == third_post.id + end + test "returns the favorites of a user" do %{user: user, conn: conn} = oauth_access(["read:favourites"]) other_user = insert(:user) {:ok, _} = CommonAPI.post(other_user, %{status: "bla"}) - {:ok, activity} = CommonAPI.post(other_user, %{status: "traps are happy"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "trees are happy"}) - {:ok, _} = CommonAPI.favorite(user, activity.id) + {:ok, last_like} = CommonAPI.favorite(user, activity.id) first_conn = get(conn, "/api/v1/favourites") @@ -1566,9 +1601,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do {:ok, _} = CommonAPI.favorite(user, second_activity.id) - last_like = status["id"] - - second_conn = get(conn, "/api/v1/favourites?since_id=#{last_like}") + second_conn = get(conn, "/api/v1/favourites?since_id=#{last_like.id}") assert [second_status] = json_response_and_validate_schema(second_conn, 200) assert second_status["id"] == to_string(second_activity.id) diff --git a/test/web/mastodon_api/controllers/subscription_controller_test.exs b/test/web/mastodon_api/controllers/subscription_controller_test.exs index 4aa260663..d36bb1ae8 100644 --- a/test/web/mastodon_api/controllers/subscription_controller_test.exs +++ b/test/web/mastodon_api/controllers/subscription_controller_test.exs @@ -58,7 +58,9 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do result = conn |> post("/api/v1/push/subscription", %{ - "data" => %{"alerts" => %{"mention" => true, "test" => true}}, + "data" => %{ + "alerts" => %{"mention" => true, "test" => true, "pleroma:chat_mention" => true} + }, "subscription" => @sub }) |> json_response_and_validate_schema(200) @@ -66,7 +68,7 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do [subscription] = Pleroma.Repo.all(Subscription) assert %{ - "alerts" => %{"mention" => true}, + "alerts" => %{"mention" => true, "pleroma:chat_mention" => true}, "endpoint" => subscription.endpoint, "id" => to_string(subscription.id), "server_key" => @server_key diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 7ac70dc58..80b1f734c 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -73,6 +73,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do fields: [] }, pleroma: %{ + ap_id: user.ap_id, background_image: "https://example.com/images/asuka_hospital.png", confirmation_pending: false, tags: [], @@ -149,6 +150,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do fields: [] }, pleroma: %{ + ap_id: user.ap_id, background_image: nil, confirmation_pending: false, tags: [], diff --git a/test/web/mastodon_api/views/conversation_view_test.exs b/test/web/mastodon_api/views/conversation_view_test.exs index 6f84366f8..2e8203c9b 100644 --- a/test/web/mastodon_api/views/conversation_view_test.exs +++ b/test/web/mastodon_api/views/conversation_view_test.exs @@ -15,8 +15,17 @@ defmodule Pleroma.Web.MastodonAPI.ConversationViewTest do user = insert(:user) other_user = insert(:user) + {:ok, parent} = CommonAPI.post(user, %{status: "parent"}) + {:ok, activity} = - CommonAPI.post(user, %{status: "hey @#{other_user.nickname}", visibility: "direct"}) + CommonAPI.post(user, %{ + status: "hey @#{other_user.nickname}", + visibility: "direct", + in_reply_to_id: parent.id + }) + + {:ok, _reply_activity} = + CommonAPI.post(user, %{status: "hu", visibility: "public", in_reply_to_id: parent.id}) [participation] = Participation.for_user_with_last_activity_id(user) diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index f15be1df1..9c399b2df 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -6,7 +6,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do use Pleroma.DataCase alias Pleroma.Activity + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference alias Pleroma.Notification + alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.CommonAPI @@ -14,6 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.NotificationView alias Pleroma.Web.MastodonAPI.StatusView + alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView import Pleroma.Factory defp test_notifications_rendering(notifications, user, expected_result) do @@ -31,6 +35,30 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do assert expected_result == result end + test "ChatMessage notification" do + user = insert(:user) + recipient = insert(:user) + {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "what's up my dude") + + {:ok, [notification]} = Notification.create_notifications(activity) + + object = Object.normalize(activity) + chat = Chat.get(recipient.id, user.ap_id) + + cm_ref = MessageReference.for_chat_and_object(chat, object) + + expected = %{ + id: to_string(notification.id), + pleroma: %{is_seen: false}, + type: "pleroma:chat_mention", + account: AccountView.render("show.json", %{user: user, for: recipient}), + chat_message: MessageReferenceView.render("show.json", %{chat_message_reference: cm_ref}), + created_at: Utils.to_masto_date(notification.inserted_at) + } + + test_notifications_rendering([notification], recipient, [expected]) + end + test "Mention notification" do user = insert(:user) mentioned_user = insert(:user) @@ -111,9 +139,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do test_notifications_rendering([notification], followed, [expected]) User.perform(:delete, follower) - notification = Notification |> Repo.one() |> Repo.preload(:activity) - - test_notifications_rendering([notification], followed, []) + refute Repo.one(Notification) end @tag capture_log: true diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs index 9bcc07b37..00925caad 100644 --- a/test/web/node_info_test.exs +++ b/test/web/node_info_test.exs @@ -145,7 +145,8 @@ defmodule Pleroma.Web.NodeInfoTest do "shareable_emoji_packs", "multifetch", "pleroma_emoji_reactions", - "pleroma:api/v1/notifications:include_types_filter" + "pleroma:api/v1/notifications:include_types_filter", + "pleroma_chat_messages" ] assert MapSet.subset?( diff --git a/test/web/pleroma_api/controllers/chat_controller_test.exs b/test/web/pleroma_api/controllers/chat_controller_test.exs new file mode 100644 index 000000000..82e16741d --- /dev/null +++ b/test/web/pleroma_api/controllers/chat_controller_test.exs @@ -0,0 +1,336 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only +defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do + use Pleroma.Web.ConnCase, async: true + + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference + alias Pleroma.Object + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + describe "POST /api/v1/pleroma/chats/:id/messages/:message_id/read" do + setup do: oauth_access(["write:chats"]) + + test "it marks one message as read", %{conn: conn, user: user} do + other_user = insert(:user) + + {:ok, create} = CommonAPI.post_chat_message(other_user, user, "sup") + {:ok, _create} = CommonAPI.post_chat_message(other_user, user, "sup part 2") + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + object = Object.normalize(create, false) + cm_ref = MessageReference.for_chat_and_object(chat, object) + + assert cm_ref.unread == true + + result = + conn + |> post("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}/read") + |> json_response_and_validate_schema(200) + + assert result["unread"] == false + + cm_ref = MessageReference.for_chat_and_object(chat, object) + + assert cm_ref.unread == false + end + end + + describe "POST /api/v1/pleroma/chats/:id/read" do + setup do: oauth_access(["write:chats"]) + + test "given a `last_read_id`, it marks everything until then as read", %{ + conn: conn, + user: user + } do + other_user = insert(:user) + + {:ok, create} = CommonAPI.post_chat_message(other_user, user, "sup") + {:ok, _create} = CommonAPI.post_chat_message(other_user, user, "sup part 2") + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + object = Object.normalize(create, false) + cm_ref = MessageReference.for_chat_and_object(chat, object) + + assert cm_ref.unread == true + + result = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/chats/#{chat.id}/read", %{"last_read_id" => cm_ref.id}) + |> json_response_and_validate_schema(200) + + assert result["unread"] == 1 + + cm_ref = MessageReference.for_chat_and_object(chat, object) + + assert cm_ref.unread == false + end + end + + describe "POST /api/v1/pleroma/chats/:id/messages" do + setup do: oauth_access(["write:chats"]) + + test "it posts a message to the chat", %{conn: conn, user: user} do + other_user = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + + result = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "Hallo!!"}) + |> json_response_and_validate_schema(200) + + assert result["content"] == "Hallo!!" + assert result["chat_id"] == chat.id |> to_string() + end + + test "it fails if there is no content", %{conn: conn, user: user} do + other_user = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + + result = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/chats/#{chat.id}/messages") + |> json_response_and_validate_schema(400) + + assert result + end + + test "it works with an attachment", %{conn: conn, user: user} do + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) + + other_user = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + + result = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{ + "media_id" => to_string(upload.id) + }) + |> json_response_and_validate_schema(200) + + assert result["attachment"] + end + end + + describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do + setup do: oauth_access(["write:chats"]) + + test "it deletes a message from the chat", %{conn: conn, user: user} do + recipient = insert(:user) + + {:ok, message} = + CommonAPI.post_chat_message(user, recipient, "Hello darkness my old friend") + + {:ok, other_message} = CommonAPI.post_chat_message(recipient, user, "nico nico ni") + + object = Object.normalize(message, false) + + chat = Chat.get(user.id, recipient.ap_id) + + cm_ref = MessageReference.for_chat_and_object(chat, object) + + # Deleting your own message removes the message and the reference + result = + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}") + |> json_response_and_validate_schema(200) + + assert result["id"] == cm_ref.id + refute MessageReference.get_by_id(cm_ref.id) + assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id) + + # Deleting other people's messages just removes the reference + object = Object.normalize(other_message, false) + cm_ref = MessageReference.for_chat_and_object(chat, object) + + result = + conn + |> put_req_header("content-type", "application/json") + |> delete("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}") + |> json_response_and_validate_schema(200) + + assert result["id"] == cm_ref.id + refute MessageReference.get_by_id(cm_ref.id) + assert Object.get_by_id(object.id) + end + end + + describe "GET /api/v1/pleroma/chats/:id/messages" do + setup do: oauth_access(["read:chats"]) + + test "it paginates", %{conn: conn, user: user} do + recipient = insert(:user) + + Enum.each(1..30, fn _ -> + {:ok, _} = CommonAPI.post_chat_message(user, recipient, "hey") + end) + + chat = Chat.get(user.id, recipient.ap_id) + + result = + conn + |> get("/api/v1/pleroma/chats/#{chat.id}/messages") + |> json_response_and_validate_schema(200) + + assert length(result) == 20 + + result = + conn + |> get("/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") + |> json_response_and_validate_schema(200) + + assert length(result) == 10 + end + + test "it returns the messages for a given chat", %{conn: conn, user: user} do + other_user = insert(:user) + third_user = insert(:user) + + {:ok, _} = CommonAPI.post_chat_message(user, other_user, "hey") + {:ok, _} = CommonAPI.post_chat_message(user, third_user, "hey") + {:ok, _} = CommonAPI.post_chat_message(user, other_user, "how are you?") + {:ok, _} = CommonAPI.post_chat_message(other_user, user, "fine, how about you?") + + chat = Chat.get(user.id, other_user.ap_id) + + result = + conn + |> get("/api/v1/pleroma/chats/#{chat.id}/messages") + |> json_response_and_validate_schema(200) + + result + |> Enum.each(fn message -> + assert message["chat_id"] == chat.id |> to_string() + end) + + assert length(result) == 3 + + # Trying to get the chat of a different user + result = + conn + |> assign(:user, other_user) + |> get("/api/v1/pleroma/chats/#{chat.id}/messages") + + assert result |> json_response(404) + end + end + + describe "POST /api/v1/pleroma/chats/by-account-id/:id" do + setup do: oauth_access(["write:chats"]) + + test "it creates or returns a chat", %{conn: conn} do + other_user = insert(:user) + + result = + conn + |> post("/api/v1/pleroma/chats/by-account-id/#{other_user.id}") + |> json_response_and_validate_schema(200) + + assert result["id"] + end + end + + describe "GET /api/v1/pleroma/chats/:id" do + setup do: oauth_access(["read:chats"]) + + test "it returns a chat", %{conn: conn, user: user} do + other_user = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) + + result = + conn + |> get("/api/v1/pleroma/chats/#{chat.id}") + |> json_response_and_validate_schema(200) + + assert result["id"] == to_string(chat.id) + end + end + + describe "GET /api/v1/pleroma/chats" do + setup do: oauth_access(["read:chats"]) + + test "it does not return chats with users you blocked", %{conn: conn, user: user} do + recipient = insert(:user) + + {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id) + + result = + conn + |> get("/api/v1/pleroma/chats") + |> json_response_and_validate_schema(200) + + assert length(result) == 1 + + User.block(user, recipient) + + result = + conn + |> get("/api/v1/pleroma/chats") + |> json_response_and_validate_schema(200) + + assert length(result) == 0 + end + + test "it returns all chats", %{conn: conn, user: user} do + Enum.each(1..30, fn _ -> + recipient = insert(:user) + {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id) + end) + + result = + conn + |> get("/api/v1/pleroma/chats") + |> json_response_and_validate_schema(200) + + assert length(result) == 30 + end + + test "it return a list of chats the current user is participating in, in descending order of updates", + %{conn: conn, user: user} do + har = insert(:user) + jafnhar = insert(:user) + tridi = insert(:user) + + {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id) + :timer.sleep(1000) + {:ok, _chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id) + :timer.sleep(1000) + {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id) + :timer.sleep(1000) + + # bump the second one + {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id) + + result = + conn + |> get("/api/v1/pleroma/chats") + |> json_response_and_validate_schema(200) + + ids = Enum.map(result, & &1["id"]) + + assert ids == [ + chat_2.id |> to_string(), + chat_3.id |> to_string(), + chat_1.id |> to_string() + ] + end + end +end diff --git a/test/web/pleroma_api/views/chat/message_reference_view_test.exs b/test/web/pleroma_api/views/chat/message_reference_view_test.exs new file mode 100644 index 000000000..e5b165255 --- /dev/null +++ b/test/web/pleroma_api/views/chat/message_reference_view_test.exs @@ -0,0 +1,61 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceViewTest do + use Pleroma.DataCase + + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference + alias Pleroma.Object + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView + + import Pleroma.Factory + + test "it displays a chat message" do + user = insert(:user) + recipient = insert(:user) + + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) + {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "kippis :firefox:") + + chat = Chat.get(user.id, recipient.ap_id) + + object = Object.normalize(activity) + + cm_ref = MessageReference.for_chat_and_object(chat, object) + + chat_message = MessageReferenceView.render("show.json", chat_message_reference: cm_ref) + + assert chat_message[:id] == cm_ref.id + assert chat_message[:content] == "kippis :firefox:" + assert chat_message[:account_id] == user.id + assert chat_message[:chat_id] + assert chat_message[:created_at] + assert chat_message[:unread] == false + assert match?([%{shortcode: "firefox"}], chat_message[:emojis]) + + {:ok, activity} = CommonAPI.post_chat_message(recipient, user, "gkgkgk", media_id: upload.id) + + object = Object.normalize(activity) + + cm_ref = MessageReference.for_chat_and_object(chat, object) + + chat_message_two = MessageReferenceView.render("show.json", chat_message_reference: cm_ref) + + assert chat_message_two[:id] == cm_ref.id + assert chat_message_two[:content] == "gkgkgk" + assert chat_message_two[:account_id] == recipient.id + assert chat_message_two[:chat_id] == chat_message[:chat_id] + assert chat_message_two[:attachment] + assert chat_message_two[:unread] == true + end +end diff --git a/test/web/pleroma_api/views/chat_view_test.exs b/test/web/pleroma_api/views/chat_view_test.exs new file mode 100644 index 000000000..14eecb1bd --- /dev/null +++ b/test/web/pleroma_api/views/chat_view_test.exs @@ -0,0 +1,48 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.ChatViewTest do + use Pleroma.DataCase + + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference + alias Pleroma.Object + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.CommonAPI.Utils + alias Pleroma.Web.MastodonAPI.AccountView + alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView + alias Pleroma.Web.PleromaAPI.ChatView + + import Pleroma.Factory + + test "it represents a chat" do + user = insert(:user) + recipient = insert(:user) + + {:ok, chat} = Chat.get_or_create(user.id, recipient.ap_id) + + represented_chat = ChatView.render("show.json", chat: chat) + + assert represented_chat == %{ + id: "#{chat.id}", + account: AccountView.render("show.json", user: recipient), + unread: 0, + last_message: nil, + updated_at: Utils.to_masto_date(chat.updated_at) + } + + {:ok, chat_message_creation} = CommonAPI.post_chat_message(user, recipient, "hello") + + chat_message = Object.normalize(chat_message_creation, false) + + {:ok, chat} = Chat.get_or_create(user.id, recipient.ap_id) + + represented_chat = ChatView.render("show.json", chat: chat) + + cm_ref = MessageReference.for_chat_and_object(chat, chat_message) + + assert represented_chat[:last_message] == + MessageReferenceView.render("show.json", chat_message_reference: cm_ref) + end +end diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index a826b24c9..b48952b29 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -5,8 +5,10 @@ defmodule Pleroma.Web.Push.ImplTest do use Pleroma.DataCase + alias Pleroma.Notification alias Pleroma.Object alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.CommonAPI alias Pleroma.Web.Push.Impl alias Pleroma.Web.Push.Subscription @@ -60,7 +62,8 @@ defmodule Pleroma.Web.Push.ImplTest do notif = insert(:notification, user: user, - activity: activity + activity: activity, + type: "mention" ) assert Impl.perform(notif) == {:ok, [:ok, :ok]} @@ -126,7 +129,7 @@ defmodule Pleroma.Web.Push.ImplTest do ) == "@Bob: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..." - assert Impl.format_title(%{activity: activity}) == + assert Impl.format_title(%{activity: activity, type: "mention"}) == "New Mention" end @@ -136,9 +139,10 @@ defmodule Pleroma.Web.Push.ImplTest do {:ok, _, _, activity} = CommonAPI.follow(user, other_user) object = Object.normalize(activity, false) - assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has followed you" + assert Impl.format_body(%{activity: activity, type: "follow"}, user, object) == + "@Bob has followed you" - assert Impl.format_title(%{activity: activity}) == + assert Impl.format_title(%{activity: activity, type: "follow"}) == "New Follower" end @@ -157,7 +161,7 @@ defmodule Pleroma.Web.Push.ImplTest do assert Impl.format_body(%{activity: announce_activity}, user, object) == "@#{user.nickname} repeated: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..." - assert Impl.format_title(%{activity: announce_activity}) == + assert Impl.format_title(%{activity: announce_activity, type: "reblog"}) == "New Repeat" end @@ -173,9 +177,10 @@ defmodule Pleroma.Web.Push.ImplTest do {:ok, activity} = CommonAPI.favorite(user, activity.id) object = Object.normalize(activity) - assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post" + assert Impl.format_body(%{activity: activity, type: "favourite"}, user, object) == + "@Bob has favorited your post" - assert Impl.format_title(%{activity: activity}) == + assert Impl.format_title(%{activity: activity, type: "favourite"}) == "New Favorite" end @@ -193,6 +198,46 @@ defmodule Pleroma.Web.Push.ImplTest do end describe "build_content/3" do + test "builds content for chat messages" do + user = insert(:user) + recipient = insert(:user) + + {:ok, chat} = CommonAPI.post_chat_message(user, recipient, "hey") + object = Object.normalize(chat, false) + [notification] = Notification.for_user(recipient) + + res = Impl.build_content(notification, user, object) + + assert res == %{ + body: "@#{user.nickname}: hey", + title: "New Chat Message" + } + end + + test "builds content for chat messages with no content" do + user = insert(:user) + recipient = insert(:user) + + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) + + {:ok, chat} = CommonAPI.post_chat_message(user, recipient, nil, media_id: upload.id) + object = Object.normalize(chat, false) + [notification] = Notification.for_user(recipient) + + res = Impl.build_content(notification, user, object) + + assert res == %{ + body: "@#{user.nickname}: (Attachment)", + title: "New Chat Message" + } + end + test "hides details for notifications when privacy option enabled" do user = insert(:user, nickname: "Bob") user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: true}) @@ -218,7 +263,7 @@ defmodule Pleroma.Web.Push.ImplTest do status: "<Lorem ipsum dolor sit amet." }) - notif = insert(:notification, user: user2, activity: activity) + notif = insert(:notification, user: user2, activity: activity, type: "mention") actor = User.get_cached_by_ap_id(notif.activity.data["actor"]) object = Object.normalize(activity) @@ -229,7 +274,7 @@ defmodule Pleroma.Web.Push.ImplTest do {:ok, activity} = CommonAPI.favorite(user, activity.id) - notif = insert(:notification, user: user2, activity: activity) + notif = insert(:notification, user: user2, activity: activity, type: "favourite") actor = User.get_cached_by_ap_id(notif.activity.data["actor"]) object = Object.normalize(activity) @@ -268,7 +313,7 @@ defmodule Pleroma.Web.Push.ImplTest do "<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis." }) - notif = insert(:notification, user: user2, activity: activity) + notif = insert(:notification, user: user2, activity: activity, type: "mention") actor = User.get_cached_by_ap_id(notif.activity.data["actor"]) object = Object.normalize(activity) @@ -281,7 +326,7 @@ defmodule Pleroma.Web.Push.ImplTest do {:ok, activity} = CommonAPI.favorite(user, activity.id) - notif = insert(:notification, user: user2, activity: activity) + notif = insert(:notification, user: user2, activity: activity, type: "favourite") actor = User.get_cached_by_ap_id(notif.activity.data["actor"]) object = Object.normalize(activity) diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs index e54a13bc8..420a612c6 100644 --- a/test/web/rich_media/parser_test.exs +++ b/test/web/rich_media/parser_test.exs @@ -60,19 +60,19 @@ defmodule Pleroma.Web.RichMedia.ParserTest do test "doesn't just add a title" do assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/non-ogp") == {:error, - "Found metadata was invalid or incomplete: %{url: \"http://example.com/non-ogp\"}"} + "Found metadata was invalid or incomplete: %{\"url\" => \"http://example.com/non-ogp\"}"} end test "parses ogp" do assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp") == {:ok, %{ - image: "http://ia.media-imdb.com/images/rock.jpg", - title: "The Rock", - description: + "image" => "http://ia.media-imdb.com/images/rock.jpg", + "title" => "The Rock", + "description" => "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", - type: "video.movie", - url: "http://example.com/ogp" + "type" => "video.movie", + "url" => "http://example.com/ogp" }} end @@ -80,12 +80,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/ogp-missing-title") == {:ok, %{ - image: "http://ia.media-imdb.com/images/rock.jpg", - title: "The Rock (1996)", - description: + "image" => "http://ia.media-imdb.com/images/rock.jpg", + "title" => "The Rock (1996)", + "description" => "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.", - type: "video.movie", - url: "http://example.com/ogp-missing-title" + "type" => "video.movie", + "url" => "http://example.com/ogp-missing-title" }} end @@ -93,12 +93,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/twitter-card") == {:ok, %{ - card: "summary", - site: "@flickr", - image: "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg", - title: "Small Island Developing States Photo Submission", - description: "View the album on Flickr.", - url: "http://example.com/twitter-card" + "card" => "summary", + "site" => "@flickr", + "image" => "https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg", + "title" => "Small Island Developing States Photo Submission", + "description" => "View the album on Flickr.", + "url" => "http://example.com/twitter-card" }} end @@ -106,27 +106,28 @@ defmodule Pleroma.Web.RichMedia.ParserTest do assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/oembed") == {:ok, %{ - author_name: "bees", - author_url: "https://www.flickr.com/photos/bees/", - cache_age: 3600, - flickr_type: "photo", - height: "768", - html: + "author_name" => "bees", + "author_url" => "https://www.flickr.com/photos/bees/", + "cache_age" => 3600, + "flickr_type" => "photo", + "height" => "768", + "html" => "<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by bees, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"></a><script async src=\"https://embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>", - license: "All Rights Reserved", - license_id: 0, - provider_name: "Flickr", - provider_url: "https://www.flickr.com/", - thumbnail_height: 150, - thumbnail_url: "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg", - thumbnail_width: 150, - title: "Bacon Lollys", - type: "photo", - url: "http://example.com/oembed", - version: "1.0", - web_page: "https://www.flickr.com/photos/bees/2362225867/", - web_page_short_url: "https://flic.kr/p/4AK2sc", - width: "1024" + "license" => "All Rights Reserved", + "license_id" => 0, + "provider_name" => "Flickr", + "provider_url" => "https://www.flickr.com/", + "thumbnail_height" => 150, + "thumbnail_url" => + "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg", + "thumbnail_width" => 150, + "title" => "Bacon Lollys", + "type" => "photo", + "url" => "http://example.com/oembed", + "version" => "1.0", + "web_page" => "https://www.flickr.com/photos/bees/2362225867/", + "web_page_short_url" => "https://flic.kr/p/4AK2sc", + "width" => "1024" }} end diff --git a/test/web/rich_media/parsers/twitter_card_test.exs b/test/web/rich_media/parsers/twitter_card_test.exs index 87c767c15..219f005a2 100644 --- a/test/web/rich_media/parsers/twitter_card_test.exs +++ b/test/web/rich_media/parsers/twitter_card_test.exs @@ -7,8 +7,7 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do alias Pleroma.Web.RichMedia.Parsers.TwitterCard test "returns error when html not contains twitter card" do - assert TwitterCard.parse([{"html", [], [{"head", [], []}, {"body", [], []}]}], %{}) == - {:error, "No twitter card metadata found"} + assert TwitterCard.parse([{"html", [], [{"head", [], []}, {"body", [], []}]}], %{}) == %{} end test "parses twitter card with only name attributes" do @@ -17,15 +16,21 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do |> Floki.parse_document!() assert TwitterCard.parse(html, %{}) == - {:ok, - %{ - "app:id:googleplay": "com.nytimes.android", - "app:name:googleplay": "NYTimes", - "app:url:googleplay": "nytimes://reader/id/100000006583622", - site: nil, - title: - "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times" - }} + %{ + "app:id:googleplay" => "com.nytimes.android", + "app:name:googleplay" => "NYTimes", + "app:url:googleplay" => "nytimes://reader/id/100000006583622", + "site" => nil, + "description" => + "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.", + "image" => + "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-facebookJumbo.jpg", + "type" => "article", + "url" => + "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html", + "title" => + "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database." + } end test "parses twitter card with only property attributes" do @@ -34,19 +39,19 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do |> Floki.parse_document!() assert TwitterCard.parse(html, %{}) == - {:ok, - %{ - card: "summary_large_image", - description: - "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.", - image: - "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg", - "image:alt": "", - title: - "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.", - url: - "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html" - }} + %{ + "card" => "summary_large_image", + "description" => + "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.", + "image" => + "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg", + "image:alt" => "", + "title" => + "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.", + "url" => + "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html", + "type" => "article" + } end test "parses twitter card with name & property attributes" do @@ -55,23 +60,23 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do |> Floki.parse_document!() assert TwitterCard.parse(html, %{}) == - {:ok, - %{ - "app:id:googleplay": "com.nytimes.android", - "app:name:googleplay": "NYTimes", - "app:url:googleplay": "nytimes://reader/id/100000006583622", - card: "summary_large_image", - description: - "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.", - image: - "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg", - "image:alt": "", - site: nil, - title: - "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.", - url: - "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html" - }} + %{ + "app:id:googleplay" => "com.nytimes.android", + "app:name:googleplay" => "NYTimes", + "app:url:googleplay" => "nytimes://reader/id/100000006583622", + "card" => "summary_large_image", + "description" => + "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.", + "image" => + "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-videoSixteenByNineJumbo1600.jpg", + "image:alt" => "", + "site" => nil, + "title" => + "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.", + "url" => + "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html", + "type" => "article" + } end test "respect only first title tag on the page" do @@ -84,14 +89,17 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do File.read!("test/fixtures/margaret-corbin-grave-west-point.html") |> Floki.parse_document!() assert TwitterCard.parse(html, %{}) == - {:ok, - %{ - site: "@atlasobscura", - title: - "The Missing Grave of Margaret Corbin, Revolutionary War Veteran - Atlas Obscura", - card: "summary_large_image", - image: image_path - }} + %{ + "site" => "@atlasobscura", + "title" => "The Missing Grave of Margaret Corbin, Revolutionary War Veteran", + "card" => "summary_large_image", + "image" => image_path, + "description" => + "She's the only woman veteran honored with a monument at West Point. But where was she buried?", + "site_name" => "Atlas Obscura", + "type" => "article", + "url" => "http://www.atlasobscura.com/articles/margaret-corbin-grave-west-point" + } end test "takes first founded title in html head if there is html markup error" do @@ -100,14 +108,20 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do |> Floki.parse_document!() assert TwitterCard.parse(html, %{}) == - {:ok, - %{ - site: nil, - title: - "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times", - "app:id:googleplay": "com.nytimes.android", - "app:name:googleplay": "NYTimes", - "app:url:googleplay": "nytimes://reader/id/100000006583622" - }} + %{ + "site" => nil, + "title" => + "She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database.", + "app:id:googleplay" => "com.nytimes.android", + "app:name:googleplay" => "NYTimes", + "app:url:googleplay" => "nytimes://reader/id/100000006583622", + "description" => + "With little oversight, the N.Y.P.D. has been using powerful surveillance technology on photos of children and teenagers.", + "image" => + "https://static01.nyt.com/images/2019/08/01/nyregion/01nypd-juveniles-promo/01nypd-juveniles-promo-facebookJumbo.jpg", + "type" => "article", + "url" => + "https://www.nytimes.com/2019/08/01/nyregion/nypd-facial-recognition-children-teenagers.html" + } end end diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index 3f012259a..245f6e63f 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -7,11 +7,15 @@ defmodule Pleroma.Web.StreamerTest do import Pleroma.Factory + alias Pleroma.Chat + alias Pleroma.Chat.MessageReference alias Pleroma.Conversation.Participation alias Pleroma.List + alias Pleroma.Object alias Pleroma.User alias Pleroma.Web.CommonAPI alias Pleroma.Web.Streamer + alias Pleroma.Web.StreamerView @moduletag needs_streamer: true, capture_log: true @@ -145,6 +149,57 @@ defmodule Pleroma.Web.StreamerTest do refute Streamer.filtered_by_user?(user, notify) end + test "it sends chat messages to the 'user:pleroma_chat' stream", %{user: user} do + other_user = insert(:user) + + {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") + object = Object.normalize(create_activity, false) + chat = Chat.get(user.id, other_user.ap_id) + cm_ref = MessageReference.for_chat_and_object(chat, object) + cm_ref = %{cm_ref | chat: chat, object: object} + + Streamer.get_topic_and_add_socket("user:pleroma_chat", user) + Streamer.stream("user:pleroma_chat", {user, cm_ref}) + + text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) + + assert text =~ "hey cirno" + assert_receive {:text, ^text} + end + + test "it sends chat messages to the 'user' stream", %{user: user} do + other_user = insert(:user) + + {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") + object = Object.normalize(create_activity, false) + chat = Chat.get(user.id, other_user.ap_id) + cm_ref = MessageReference.for_chat_and_object(chat, object) + cm_ref = %{cm_ref | chat: chat, object: object} + + Streamer.get_topic_and_add_socket("user", user) + Streamer.stream("user", {user, cm_ref}) + + text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}) + + assert text =~ "hey cirno" + assert_receive {:text, ^text} + end + + test "it sends chat message notifications to the 'user:notification' stream", %{user: user} do + other_user = insert(:user) + + {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey") + + notify = + Repo.get_by(Pleroma.Notification, user_id: user.id, activity_id: create_activity.id) + |> Repo.preload(:activity) + + Streamer.get_topic_and_add_socket("user:notification", user) + Streamer.stream("user:notification", notify) + assert_receive {:render_with_user, _, _, ^notify} + refute Streamer.filtered_by_user?(user, notify) + end + test "it doesn't send notify to the 'user:notification' stream when a user is blocked", %{ user: user } do diff --git a/test/workers/cron/purge_expired_activities_worker_test.exs b/test/workers/cron/purge_expired_activities_worker_test.exs index 5864f9e5f..6d2991a60 100644 --- a/test/workers/cron/purge_expired_activities_worker_test.exs +++ b/test/workers/cron/purge_expired_activities_worker_test.exs @@ -11,7 +11,10 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do import Pleroma.Factory import ExUnit.CaptureLog - setup do: clear_config([ActivityExpiration, :enabled]) + setup do + clear_config([ActivityExpiration, :enabled]) + clear_config([:instance, :rewrite_policy]) + end test "deletes an expiration activity" do Pleroma.Config.put([ActivityExpiration, :enabled], true) @@ -36,6 +39,35 @@ defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) end + test "works with ActivityExpirationPolicy" do + Pleroma.Config.put([ActivityExpiration, :enabled], true) + + Pleroma.Config.put( + [:instance, :rewrite_policy], + Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy + ) + + user = insert(:user) + + days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365) + + {:ok, %{id: id} = activity} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"}) + + past_date = + NaiveDateTime.utc_now() |> Timex.shift(days: -days) |> NaiveDateTime.truncate(:second) + + activity + |> Repo.preload(:expiration) + |> Map.get(:expiration) + |> Ecto.Changeset.change(%{scheduled_at: past_date}) + |> Repo.update!() + + Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid) + + assert [%{data: %{"type" => "Delete", "deleted_activity_id" => ^id}}] = + Pleroma.Repo.all(Pleroma.Activity) + end + describe "delete_activity/1" do test "adds log message if activity isn't find" do assert capture_log([level: :error], fn -> |