tests consistency
This commit is contained in:
parent
6bf85440b3
commit
7dffaef479
258 changed files with 38 additions and 37 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,84 +0,0 @@
|
|||
# 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"
|
||||
@local_actor Pleroma.Web.Endpoint.url() <> "/users/cofe"
|
||||
|
||||
test "adds `expires_at` property" do
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => @id,
|
||||
"actor" => @local_actor,
|
||||
"type" => "Create",
|
||||
"object" => %{"type" => "Note"}
|
||||
})
|
||||
|
||||
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
|
||||
end
|
||||
|
||||
test "keeps existing `expires_at` if it less than the config setting" do
|
||||
expires_at = DateTime.utc_now() |> Timex.shift(days: 1)
|
||||
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => @id,
|
||||
"actor" => @local_actor,
|
||||
"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 = DateTime.utc_now() |> Timex.shift(years: 2)
|
||||
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => @id,
|
||||
"actor" => @local_actor,
|
||||
"type" => "Create",
|
||||
"expires_at" => too_distant_future,
|
||||
"object" => %{"type" => "Note"}
|
||||
})
|
||||
|
||||
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
|
||||
end
|
||||
|
||||
test "ignores remote activities" do
|
||||
assert {:ok, activity} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => "https://example.com/123",
|
||||
"actor" => "https://example.com/users/cofe",
|
||||
"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",
|
||||
"actor" => "https://example.com/users/cofe",
|
||||
"type" => "Follow"
|
||||
})
|
||||
|
||||
refute Map.has_key?(activity, "expires_at")
|
||||
|
||||
assert {:ok, activity} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
"id" => "https://example.com/123",
|
||||
"actor" => "https://example.com/users/cofe",
|
||||
"type" => "Create",
|
||||
"object" => %{"type" => "Cofe"}
|
||||
})
|
||||
|
||||
refute Map.has_key?(activity, "expires_at")
|
||||
end
|
||||
end
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
# 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.AntiFollowbotPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy
|
||||
|
||||
describe "blocking based on attributes" do
|
||||
test "matches followbots by nickname" do
|
||||
actor = insert(:user, %{nickname: "followbot@example.com"})
|
||||
target = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Follow",
|
||||
"actor" => actor.ap_id,
|
||||
"object" => target.ap_id,
|
||||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "matches followbots by display name" do
|
||||
actor = insert(:user, %{name: "Federation Bot"})
|
||||
target = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Follow",
|
||||
"actor" => actor.ap_id,
|
||||
"object" => target.ap_id,
|
||||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
test "it allows non-followbots" do
|
||||
actor = insert(:user)
|
||||
target = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Follow",
|
||||
"actor" => actor.ap_id,
|
||||
"object" => target.ap_id,
|
||||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it gracefully handles nil display names" do
|
||||
actor = insert(:user, %{name: nil})
|
||||
target = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Follow",
|
||||
"actor" => actor.ap_id,
|
||||
"object" => target.ap_id,
|
||||
"id" => "https://example.com/activities/1234"
|
||||
}
|
||||
|
||||
{:ok, _} = AntiFollowbotPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
# 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.AntiLinkSpamPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy
|
||||
|
||||
@linkless_message %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "hi world!"
|
||||
}
|
||||
}
|
||||
|
||||
@linkful_message %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "<a href='https://example.com'>hi world!</a>"
|
||||
}
|
||||
}
|
||||
|
||||
@response_message %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"name" => "yes",
|
||||
"type" => "Answer"
|
||||
}
|
||||
}
|
||||
|
||||
describe "with new user" do
|
||||
test "it allows posts without links" do
|
||||
user = insert(:user, local: false)
|
||||
|
||||
assert user.note_count == 0
|
||||
|
||||
message =
|
||||
@linkless_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it disallows posts with links" do
|
||||
user = insert(:user, local: false)
|
||||
|
||||
assert user.note_count == 0
|
||||
|
||||
message =
|
||||
@linkful_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:reject, _} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it allows posts with links for local users" do
|
||||
user = insert(:user)
|
||||
|
||||
assert user.note_count == 0
|
||||
|
||||
message =
|
||||
@linkful_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with old user" do
|
||||
test "it allows posts without links" do
|
||||
user = insert(:user, note_count: 1)
|
||||
|
||||
assert user.note_count == 1
|
||||
|
||||
message =
|
||||
@linkless_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it allows posts with links" do
|
||||
user = insert(:user, note_count: 1)
|
||||
|
||||
assert user.note_count == 1
|
||||
|
||||
message =
|
||||
@linkful_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with followed new user" do
|
||||
test "it allows posts without links" do
|
||||
user = insert(:user, follower_count: 1)
|
||||
|
||||
assert user.follower_count == 1
|
||||
|
||||
message =
|
||||
@linkless_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it allows posts with links" do
|
||||
user = insert(:user, follower_count: 1)
|
||||
|
||||
assert user.follower_count == 1
|
||||
|
||||
message =
|
||||
@linkful_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with unknown actors" do
|
||||
setup do
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get, url: "http://invalid.actor"} ->
|
||||
%Tesla.Env{status: 500, body: ""}
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it rejects posts without links" do
|
||||
message =
|
||||
@linkless_message
|
||||
|> Map.put("actor", "http://invalid.actor")
|
||||
|
||||
assert capture_log(fn ->
|
||||
{:reject, _} = AntiLinkSpamPolicy.filter(message)
|
||||
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
|
||||
end
|
||||
|
||||
test "it rejects posts with links" do
|
||||
message =
|
||||
@linkful_message
|
||||
|> Map.put("actor", "http://invalid.actor")
|
||||
|
||||
assert capture_log(fn ->
|
||||
{:reject, _} = AntiLinkSpamPolicy.filter(message)
|
||||
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
|
||||
end
|
||||
end
|
||||
|
||||
describe "with contentless-objects" do
|
||||
test "it does not reject them or error out" do
|
||||
user = insert(:user, note_count: 1)
|
||||
|
||||
message =
|
||||
@response_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
# 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.EnsureRePrependedTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
|
||||
|
||||
describe "rewrites summary" do
|
||||
test "it adds `re:` to summary object when child summary and parent summary equal" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res["object"]["summary"] == "re: object-summary"
|
||||
end
|
||||
|
||||
test "it adds `re:` to summary object when child summary containts re-subject of parent summary " do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "re: object-summary"}}}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res["object"]["summary"] == "re: object-summary"
|
||||
end
|
||||
end
|
||||
|
||||
describe "skip filter" do
|
||||
test "it skip if type isn't 'Create'" do
|
||||
message = %{
|
||||
"type" => "Annotation",
|
||||
"object" => %{"summary" => "object-summary"}
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
|
||||
test "it skip if summary is empty" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
|
||||
test "it skip if inReplyTo is empty" do
|
||||
message = %{"type" => "Create", "object" => %{"summary" => "summary"}}
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
|
||||
test "it skip if parent and child summary isn't equal" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
|
||||
test "it skips if the object is only a reference" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => "somereference"
|
||||
}
|
||||
|
||||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
# 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.ForceBotUnlistedPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy
|
||||
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
defp generate_messages(actor) do
|
||||
{%{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{},
|
||||
"to" => [@public, "f"],
|
||||
"cc" => [actor.follower_address, "d"]
|
||||
},
|
||||
%{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
|
||||
"to" => ["f", actor.follower_address],
|
||||
"cc" => ["d", @public]
|
||||
}}
|
||||
end
|
||||
|
||||
test "removes from the federated timeline by nickname heuristics 1" do
|
||||
actor = insert(:user, %{nickname: "annoying_ebooks@example.com"})
|
||||
|
||||
{message, except_message} = generate_messages(actor)
|
||||
|
||||
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
|
||||
test "removes from the federated timeline by nickname heuristics 2" do
|
||||
actor = insert(:user, %{nickname: "cirnonewsnetworkbot@meow.cat"})
|
||||
|
||||
{message, except_message} = generate_messages(actor)
|
||||
|
||||
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
|
||||
test "removes from the federated timeline by actor type Application" do
|
||||
actor = insert(:user, %{actor_type: "Application"})
|
||||
|
||||
{message, except_message} = generate_messages(actor)
|
||||
|
||||
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
|
||||
test "removes from the federated timeline by actor type Service" do
|
||||
actor = insert(:user, %{actor_type: "Service"})
|
||||
|
||||
{message, except_message} = generate_messages(actor)
|
||||
|
||||
assert ForceBotUnlistedPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
# 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.HellthreadPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
import Pleroma.Web.ActivityPub.MRF.HellthreadPolicy
|
||||
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"actor" => user.ap_id,
|
||||
"cc" => [user.follower_address],
|
||||
"type" => "Create",
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"https://instance.tld/users/user1",
|
||||
"https://instance.tld/users/user2",
|
||||
"https://instance.tld/users/user3"
|
||||
],
|
||||
"object" => %{
|
||||
"type" => "Note"
|
||||
}
|
||||
}
|
||||
|
||||
[user: user, message: message]
|
||||
end
|
||||
|
||||
setup do: clear_config(:mrf_hellthread)
|
||||
|
||||
test "doesn't die on chat messages" do
|
||||
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
|
||||
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post_chat_message(user, other_user, "moin")
|
||||
|
||||
assert {:ok, _} = filter(activity.data)
|
||||
end
|
||||
|
||||
describe "reject" do
|
||||
test "rejects the message if the recipient count is above reject_threshold", %{
|
||||
message: message
|
||||
} do
|
||||
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2})
|
||||
|
||||
assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} ==
|
||||
filter(message)
|
||||
end
|
||||
|
||||
test "does not reject the message if the recipient count is below reject_threshold", %{
|
||||
message: message
|
||||
} do
|
||||
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
|
||||
|
||||
assert {:ok, ^message} = filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "delist" do
|
||||
test "delists the message if the recipient count is above delist_threshold", %{
|
||||
user: user,
|
||||
message: message
|
||||
} do
|
||||
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
|
||||
|
||||
{:ok, message} = filter(message)
|
||||
assert user.follower_address in message["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in message["cc"]
|
||||
end
|
||||
|
||||
test "does not delist the message if the recipient count is below delist_threshold", %{
|
||||
message: message
|
||||
} do
|
||||
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 4, reject_threshold: 0})
|
||||
|
||||
assert {:ok, ^message} = filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
test "excludes follower collection and public URI from threshold count", %{message: message} do
|
||||
Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
|
||||
|
||||
assert {:ok, ^message} = filter(message)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
# 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.KeywordPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.KeywordPolicy
|
||||
|
||||
setup do: clear_config(:mrf_keyword)
|
||||
|
||||
setup do
|
||||
Pleroma.Config.put([:mrf_keyword], %{reject: [], federated_timeline_removal: [], replace: []})
|
||||
end
|
||||
|
||||
describe "rejecting based on keywords" do
|
||||
test "rejects if string matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that compLAINer is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
|
||||
KeywordPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "rejects if string matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that compLAINer is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
|
||||
KeywordPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "rejects if regex matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that #{content} is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
|
||||
KeywordPolicy.filter(message)
|
||||
end)
|
||||
end
|
||||
|
||||
test "rejects if regex matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that #{content} is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
|
||||
KeywordPolicy.filter(message)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "delisting from ftl based on keywords" do
|
||||
test "delists if string matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
|
||||
|
||||
message = %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that compLAINer is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"]
|
||||
refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
|
||||
end
|
||||
|
||||
test "delists if string matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
|
||||
|
||||
message = %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that compLAINer is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"]
|
||||
refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
|
||||
end
|
||||
|
||||
test "delists if regex matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that #{content} is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
|
||||
["https://www.w3.org/ns/activitystreams#Public"] == result["cc"] and
|
||||
not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
|
||||
end)
|
||||
end
|
||||
|
||||
test "delists if regex matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that #{content} is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
|
||||
["https://www.w3.org/ns/activitystreams#Public"] == result["cc"] and
|
||||
not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "replacing keywords" do
|
||||
test "replaces keyword if string matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"content" => "ZFS is opensource", "summary" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
|
||||
assert result == "ZFS is free software"
|
||||
end
|
||||
|
||||
test "replaces keyword if string matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"summary" => "ZFS is opensource", "content" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
|
||||
assert result == "ZFS is free software"
|
||||
end
|
||||
|
||||
test "replaces keyword if regex matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [
|
||||
{~r/open(-|\s)?source\s?(software)?/, "free software"}
|
||||
])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["opensource", "open-source", "open source"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"content" => "ZFS is #{content}", "summary" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
|
||||
result == "ZFS is free software"
|
||||
end)
|
||||
end
|
||||
|
||||
test "replaces keyword if regex matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [
|
||||
{~r/open(-|\s)?source\s?(software)?/, "free software"}
|
||||
])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["opensource", "open-source", "open source"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"summary" => "ZFS is #{content}", "content" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
|
||||
result == "ZFS is free software"
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
# 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.MediaProxyWarmingPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy
|
||||
|
||||
import Mock
|
||||
|
||||
@message %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "content",
|
||||
"attachment" => [
|
||||
%{"url" => [%{"href" => "http://example.com/image.jpg"}]}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
setup do: clear_config([:media_proxy, :enabled], true)
|
||||
|
||||
test "it prefetches media proxy URIs" do
|
||||
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
|
||||
MediaProxyWarmingPolicy.filter(@message)
|
||||
|
||||
ObanHelpers.perform_all()
|
||||
# Performing jobs which has been just enqueued
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert called(HTTP.get(:_, :_, :_))
|
||||
end
|
||||
end
|
||||
|
||||
test "it does nothing when no attachments are present" do
|
||||
object =
|
||||
@message["object"]
|
||||
|> Map.delete("attachment")
|
||||
|
||||
message =
|
||||
@message
|
||||
|> Map.put("object", object)
|
||||
|
||||
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
|
||||
MediaProxyWarmingPolicy.filter(message)
|
||||
refute called(HTTP.get(:_, :_, :_))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
# 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.MentionPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.MentionPolicy
|
||||
|
||||
setup do: clear_config(:mrf_mention)
|
||||
|
||||
test "pass filter if allow list is empty" do
|
||||
Pleroma.Config.delete([:mrf_mention])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://example.com/ok"],
|
||||
"cc" => ["https://example.com/blocked"]
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
describe "allow" do
|
||||
test "empty" do
|
||||
Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
|
||||
|
||||
message = %{
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
test "to" do
|
||||
Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://example.com/ok"]
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
test "cc" do
|
||||
Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"cc" => ["https://example.com/ok"]
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
test "both" do
|
||||
Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://example.com/ok"],
|
||||
"cc" => ["https://example.com/ok2"]
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "deny" do
|
||||
test "to" do
|
||||
Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://example.com/blocked"]
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) ==
|
||||
{:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
|
||||
end
|
||||
|
||||
test "cc" do
|
||||
Pleroma.Config.put([:mrf_mention], %{actors: ["https://example.com/blocked"]})
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://example.com/ok"],
|
||||
"cc" => ["https://example.com/blocked"]
|
||||
}
|
||||
|
||||
assert MentionPolicy.filter(message) ==
|
||||
{:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
# 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.MRFTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Pleroma.Tests.Helpers
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
test "subdomains_regex/1" do
|
||||
assert MRF.subdomains_regex(["unsafe.tld", "*.unsafe.tld"]) == [
|
||||
~r/^unsafe.tld$/i,
|
||||
~r/^(.*\.)*unsafe.tld$/i
|
||||
]
|
||||
end
|
||||
|
||||
describe "subdomain_match/2" do
|
||||
test "common domains" do
|
||||
regexes = MRF.subdomains_regex(["unsafe.tld", "unsafe2.tld"])
|
||||
|
||||
assert regexes == [~r/^unsafe.tld$/i, ~r/^unsafe2.tld$/i]
|
||||
|
||||
assert MRF.subdomain_match?(regexes, "unsafe.tld")
|
||||
assert MRF.subdomain_match?(regexes, "unsafe2.tld")
|
||||
|
||||
refute MRF.subdomain_match?(regexes, "example.com")
|
||||
end
|
||||
|
||||
test "wildcard domains with one subdomain" do
|
||||
regexes = MRF.subdomains_regex(["*.unsafe.tld"])
|
||||
|
||||
assert regexes == [~r/^(.*\.)*unsafe.tld$/i]
|
||||
|
||||
assert MRF.subdomain_match?(regexes, "unsafe.tld")
|
||||
assert MRF.subdomain_match?(regexes, "sub.unsafe.tld")
|
||||
refute MRF.subdomain_match?(regexes, "anotherunsafe.tld")
|
||||
refute MRF.subdomain_match?(regexes, "unsafe.tldanother")
|
||||
end
|
||||
|
||||
test "wildcard domains with two subdomains" do
|
||||
regexes = MRF.subdomains_regex(["*.unsafe.tld"])
|
||||
|
||||
assert regexes == [~r/^(.*\.)*unsafe.tld$/i]
|
||||
|
||||
assert MRF.subdomain_match?(regexes, "unsafe.tld")
|
||||
assert MRF.subdomain_match?(regexes, "sub.sub.unsafe.tld")
|
||||
refute MRF.subdomain_match?(regexes, "sub.anotherunsafe.tld")
|
||||
refute MRF.subdomain_match?(regexes, "sub.unsafe.tldanother")
|
||||
end
|
||||
|
||||
test "matches are case-insensitive" do
|
||||
regexes = MRF.subdomains_regex(["UnSafe.TLD", "UnSAFE2.Tld"])
|
||||
|
||||
assert regexes == [~r/^UnSafe.TLD$/i, ~r/^UnSAFE2.Tld$/i]
|
||||
|
||||
assert MRF.subdomain_match?(regexes, "UNSAFE.TLD")
|
||||
assert MRF.subdomain_match?(regexes, "UNSAFE2.TLD")
|
||||
assert MRF.subdomain_match?(regexes, "unsafe.tld")
|
||||
assert MRF.subdomain_match?(regexes, "unsafe2.tld")
|
||||
|
||||
refute MRF.subdomain_match?(regexes, "EXAMPLE.COM")
|
||||
refute MRF.subdomain_match?(regexes, "example.com")
|
||||
end
|
||||
end
|
||||
|
||||
describe "describe/0" do
|
||||
test "it works as expected with noop policy" do
|
||||
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.NoOpPolicy])
|
||||
|
||||
expected = %{
|
||||
mrf_policies: ["NoOpPolicy"],
|
||||
exclusions: false
|
||||
}
|
||||
|
||||
{:ok, ^expected} = MRF.describe()
|
||||
end
|
||||
|
||||
test "it works as expected with mock policy" do
|
||||
clear_config([:mrf, :policies], [MRFModuleMock])
|
||||
|
||||
expected = %{
|
||||
mrf_policies: ["MRFModuleMock"],
|
||||
mrf_module_mock: "some config data",
|
||||
exclusions: false
|
||||
}
|
||||
|
||||
{:ok, ^expected} = MRF.describe()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# 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.NoPlaceholderTextPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
|
||||
|
||||
test "it clears content object" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{"content" => ".", "attachment" => "image"}
|
||||
}
|
||||
|
||||
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
|
||||
assert res["object"]["content"] == ""
|
||||
|
||||
message = put_in(message, ["object", "content"], "<p>.</p>")
|
||||
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
|
||||
assert res["object"]["content"] == ""
|
||||
end
|
||||
|
||||
@messages [
|
||||
%{
|
||||
"type" => "Create",
|
||||
"object" => %{"content" => "test", "attachment" => "image"}
|
||||
},
|
||||
%{"type" => "Create", "object" => %{"content" => "."}},
|
||||
%{"type" => "Create", "object" => %{"content" => "<p>.</p>"}}
|
||||
]
|
||||
test "it skips filter" do
|
||||
Enum.each(@messages, fn message ->
|
||||
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
|
||||
assert res == message
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# 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.NormalizeMarkupTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
|
||||
|
||||
@html_sample """
|
||||
<b>this is in bold</b>
|
||||
<p>this is a paragraph</p>
|
||||
this is a linebreak<br />
|
||||
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||
this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a>
|
||||
this is an image: <img src="http://example.com/image.jpg"><br />
|
||||
<script>alert('hacked')</script>
|
||||
"""
|
||||
|
||||
test "it filter html tags" do
|
||||
expected = """
|
||||
<b>this is in bold</b>
|
||||
<p>this is a paragraph</p>
|
||||
this is a linebreak<br/>
|
||||
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
||||
this is an image: <img src="http://example.com/image.jpg"/><br/>
|
||||
alert('hacked')
|
||||
"""
|
||||
|
||||
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
|
||||
|
||||
assert {:ok, res} = NormalizeMarkup.filter(message)
|
||||
assert res["object"]["content"] == expected
|
||||
end
|
||||
|
||||
test "it skips filter if type isn't `Create`" do
|
||||
message = %{"type" => "Note", "object" => %{}}
|
||||
|
||||
assert {:ok, res} = NormalizeMarkup.filter(message)
|
||||
assert res == message
|
||||
end
|
||||
end
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
# 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.ObjectAgePolicyTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
|
||||
setup do:
|
||||
clear_config(:mrf_object_age,
|
||||
threshold: 172_800,
|
||||
actions: [:delist, :strip_followers]
|
||||
)
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
defp get_old_message do
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
end
|
||||
|
||||
defp get_new_message do
|
||||
old_message = get_old_message()
|
||||
|
||||
new_object =
|
||||
old_message
|
||||
|> Map.get("object")
|
||||
|> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
|
||||
|
||||
old_message
|
||||
|> Map.put("object", new_object)
|
||||
end
|
||||
|
||||
describe "with reject action" do
|
||||
test "works with objects with empty to or cc fields" do
|
||||
Config.put([:mrf_object_age, :actions], [:reject])
|
||||
|
||||
data =
|
||||
get_old_message()
|
||||
|> Map.put("cc", nil)
|
||||
|> Map.put("to", nil)
|
||||
|
||||
assert match?({:reject, _}, ObjectAgePolicy.filter(data))
|
||||
end
|
||||
|
||||
test "it rejects an old post" do
|
||||
Config.put([:mrf_object_age, :actions], [:reject])
|
||||
|
||||
data = get_old_message()
|
||||
|
||||
assert match?({:reject, _}, ObjectAgePolicy.filter(data))
|
||||
end
|
||||
|
||||
test "it allows a new post" do
|
||||
Config.put([:mrf_object_age, :actions], [:reject])
|
||||
|
||||
data = get_new_message()
|
||||
|
||||
assert match?({:ok, _}, ObjectAgePolicy.filter(data))
|
||||
end
|
||||
end
|
||||
|
||||
describe "with delist action" do
|
||||
test "works with objects with empty to or cc fields" do
|
||||
Config.put([:mrf_object_age, :actions], [:delist])
|
||||
|
||||
data =
|
||||
get_old_message()
|
||||
|> Map.put("cc", nil)
|
||||
|> Map.put("to", nil)
|
||||
|
||||
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
|
||||
|
||||
{:ok, data} = ObjectAgePolicy.filter(data)
|
||||
|
||||
assert Visibility.get_visibility(%{data: data}) == "unlisted"
|
||||
end
|
||||
|
||||
test "it delists an old post" do
|
||||
Config.put([:mrf_object_age, :actions], [:delist])
|
||||
|
||||
data = get_old_message()
|
||||
|
||||
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
|
||||
|
||||
{:ok, data} = ObjectAgePolicy.filter(data)
|
||||
|
||||
assert Visibility.get_visibility(%{data: data}) == "unlisted"
|
||||
end
|
||||
|
||||
test "it allows a new post" do
|
||||
Config.put([:mrf_object_age, :actions], [:delist])
|
||||
|
||||
data = get_new_message()
|
||||
|
||||
{:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
|
||||
|
||||
assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
|
||||
end
|
||||
end
|
||||
|
||||
describe "with strip_followers action" do
|
||||
test "works with objects with empty to or cc fields" do
|
||||
Config.put([:mrf_object_age, :actions], [:strip_followers])
|
||||
|
||||
data =
|
||||
get_old_message()
|
||||
|> Map.put("cc", nil)
|
||||
|> Map.put("to", nil)
|
||||
|
||||
{:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
|
||||
|
||||
{:ok, data} = ObjectAgePolicy.filter(data)
|
||||
|
||||
refute user.follower_address in data["to"]
|
||||
refute user.follower_address in data["cc"]
|
||||
end
|
||||
|
||||
test "it strips followers collections from an old post" do
|
||||
Config.put([:mrf_object_age, :actions], [:strip_followers])
|
||||
|
||||
data = get_old_message()
|
||||
|
||||
{:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
|
||||
|
||||
{:ok, data} = ObjectAgePolicy.filter(data)
|
||||
|
||||
refute user.follower_address in data["to"]
|
||||
refute user.follower_address in data["cc"]
|
||||
end
|
||||
|
||||
test "it allows a new post" do
|
||||
Config.put([:mrf_object_age, :actions], [:strip_followers])
|
||||
|
||||
data = get_new_message()
|
||||
|
||||
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
|
||||
|
||||
assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# 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.RejectNonPublicTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic
|
||||
|
||||
setup do: clear_config([:mrf_rejectnonpublic])
|
||||
|
||||
describe "public message" do
|
||||
test "it's allowed when address is public" do
|
||||
actor = insert(:user, follower_address: "test-address")
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||
end
|
||||
|
||||
test "it's allowed when cc address contain public address" do
|
||||
actor = insert(:user, follower_address: "test-address")
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "followers message" do
|
||||
test "it's allowed when addrer of message in the follower addresses of user and it enabled in config" do
|
||||
actor = insert(:user, follower_address: "test-address")
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["test-address"],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], true)
|
||||
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||
end
|
||||
|
||||
test "it's rejected when addrer of message in the follower addresses of user and it disabled in config" do
|
||||
actor = insert(:user, follower_address: "test-address")
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["test-address"],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false)
|
||||
assert {:reject, _} = RejectNonPublic.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "direct message" do
|
||||
test "it's allows when direct messages are allow" do
|
||||
actor = insert(:user)
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], true)
|
||||
assert {:ok, message} = RejectNonPublic.filter(message)
|
||||
end
|
||||
|
||||
test "it's reject when direct messages aren't allow" do
|
||||
actor = insert(:user)
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Publid~~~"],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false)
|
||||
assert {:reject, _} = RejectNonPublic.filter(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,539 +0,0 @@
|
|||
# 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.SimplePolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
setup do:
|
||||
clear_config(:mrf_simple,
|
||||
media_removal: [],
|
||||
media_nsfw: [],
|
||||
federated_timeline_removal: [],
|
||||
report_removal: [],
|
||||
reject: [],
|
||||
followers_only: [],
|
||||
accept: [],
|
||||
avatar_removal: [],
|
||||
banner_removal: [],
|
||||
reject_deletes: []
|
||||
)
|
||||
|
||||
describe "when :media_removal" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :media_removal], [])
|
||||
media_message = build_media_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(media_message) == {:ok, media_message}
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
Config.put([:mrf_simple, :media_removal], ["remote.instance"])
|
||||
media_message = build_media_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(media_message) ==
|
||||
{:ok,
|
||||
media_message
|
||||
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "match with wildcard domain" do
|
||||
Config.put([:mrf_simple, :media_removal], ["*.remote.instance"])
|
||||
media_message = build_media_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(media_message) ==
|
||||
{:ok,
|
||||
media_message
|
||||
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :media_nsfw" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :media_nsfw], [])
|
||||
media_message = build_media_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(media_message) == {:ok, media_message}
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
Config.put([:mrf_simple, :media_nsfw], ["remote.instance"])
|
||||
media_message = build_media_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(media_message) ==
|
||||
{:ok,
|
||||
media_message
|
||||
|> put_in(["object", "tag"], ["foo", "nsfw"])
|
||||
|> put_in(["object", "sensitive"], true)}
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "match with wildcard domain" do
|
||||
Config.put([:mrf_simple, :media_nsfw], ["*.remote.instance"])
|
||||
media_message = build_media_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(media_message) ==
|
||||
{:ok,
|
||||
media_message
|
||||
|> put_in(["object", "tag"], ["foo", "nsfw"])
|
||||
|> put_in(["object", "sensitive"], true)}
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
end
|
||||
|
||||
defp build_media_message do
|
||||
%{
|
||||
"actor" => "https://remote.instance/users/bob",
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"attachment" => [%{}],
|
||||
"tag" => ["foo"],
|
||||
"sensitive" => false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
describe "when :report_removal" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :report_removal], [])
|
||||
report_message = build_report_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(report_message) == {:ok, report_message}
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
Config.put([:mrf_simple, :report_removal], ["remote.instance"])
|
||||
report_message = build_report_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(report_message)
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "match with wildcard domain" do
|
||||
Config.put([:mrf_simple, :report_removal], ["*.remote.instance"])
|
||||
report_message = build_report_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(report_message)
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
end
|
||||
|
||||
defp build_report_message do
|
||||
%{
|
||||
"actor" => "https://remote.instance/users/bob",
|
||||
"type" => "Flag"
|
||||
}
|
||||
end
|
||||
|
||||
describe "when :federated_timeline_removal" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :federated_timeline_removal], [])
|
||||
{_, ftl_message} = build_ftl_actor_and_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
{actor, ftl_message} = build_ftl_actor_and_message()
|
||||
|
||||
ftl_message_actor_host =
|
||||
ftl_message
|
||||
|> Map.fetch!("actor")
|
||||
|> URI.parse()
|
||||
|> Map.fetch!(:host)
|
||||
|
||||
Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
|
||||
local_message = build_local_message()
|
||||
|
||||
assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
|
||||
assert actor.follower_address in ftl_message["to"]
|
||||
refute actor.follower_address in ftl_message["cc"]
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "match with wildcard domain" do
|
||||
{actor, ftl_message} = build_ftl_actor_and_message()
|
||||
|
||||
ftl_message_actor_host =
|
||||
ftl_message
|
||||
|> Map.fetch!("actor")
|
||||
|> URI.parse()
|
||||
|> Map.fetch!(:host)
|
||||
|
||||
Config.put([:mrf_simple, :federated_timeline_removal], ["*." <> ftl_message_actor_host])
|
||||
local_message = build_local_message()
|
||||
|
||||
assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
|
||||
assert actor.follower_address in ftl_message["to"]
|
||||
refute actor.follower_address in ftl_message["cc"]
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "has a matching host but only as:Public in to" do
|
||||
{_actor, ftl_message} = build_ftl_actor_and_message()
|
||||
|
||||
ftl_message_actor_host =
|
||||
ftl_message
|
||||
|> Map.fetch!("actor")
|
||||
|> URI.parse()
|
||||
|> Map.fetch!(:host)
|
||||
|
||||
ftl_message = Map.put(ftl_message, "cc", [])
|
||||
|
||||
Config.put([:mrf_simple, :federated_timeline_removal], [ftl_message_actor_host])
|
||||
|
||||
assert {:ok, ftl_message} = SimplePolicy.filter(ftl_message)
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in ftl_message["to"]
|
||||
assert "https://www.w3.org/ns/activitystreams#Public" in ftl_message["cc"]
|
||||
end
|
||||
end
|
||||
|
||||
defp build_ftl_actor_and_message do
|
||||
actor = insert(:user)
|
||||
|
||||
{actor,
|
||||
%{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public", "http://foo.bar/baz"],
|
||||
"cc" => [actor.follower_address, "http://foo.bar/qux"]
|
||||
}}
|
||||
end
|
||||
|
||||
describe "when :reject" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :reject], [])
|
||||
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
end
|
||||
|
||||
test "activity has a matching host" do
|
||||
Config.put([:mrf_simple, :reject], ["remote.instance"])
|
||||
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
end
|
||||
|
||||
test "activity matches with wildcard domain" do
|
||||
Config.put([:mrf_simple, :reject], ["*.remote.instance"])
|
||||
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
end
|
||||
|
||||
test "actor has a matching host" do
|
||||
Config.put([:mrf_simple, :reject], ["remote.instance"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :followers_only" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :followers_only], [])
|
||||
{_, ftl_message} = build_ftl_actor_and_message()
|
||||
local_message = build_local_message()
|
||||
|
||||
assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
actor = insert(:user)
|
||||
following_user = insert(:user)
|
||||
non_following_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(following_user, actor)
|
||||
|
||||
activity = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
following_user.ap_id,
|
||||
non_following_user.ap_id
|
||||
],
|
||||
"cc" => [actor.follower_address, "http://foo.bar/qux"]
|
||||
}
|
||||
|
||||
dm_activity = %{
|
||||
"actor" => actor.ap_id,
|
||||
"to" => [
|
||||
following_user.ap_id,
|
||||
non_following_user.ap_id
|
||||
],
|
||||
"cc" => []
|
||||
}
|
||||
|
||||
actor_domain =
|
||||
activity
|
||||
|> Map.fetch!("actor")
|
||||
|> URI.parse()
|
||||
|> Map.fetch!(:host)
|
||||
|
||||
Config.put([:mrf_simple, :followers_only], [actor_domain])
|
||||
|
||||
assert {:ok, new_activity} = SimplePolicy.filter(activity)
|
||||
assert actor.follower_address in new_activity["cc"]
|
||||
assert following_user.ap_id in new_activity["to"]
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
|
||||
refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
|
||||
refute non_following_user.ap_id in new_activity["to"]
|
||||
refute non_following_user.ap_id in new_activity["cc"]
|
||||
|
||||
assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
|
||||
assert new_dm_activity["to"] == [following_user.ap_id]
|
||||
assert new_dm_activity["cc"] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :accept" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :accept], [])
|
||||
|
||||
local_message = build_local_message()
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
end
|
||||
|
||||
test "is not empty but activity doesn't have a matching host" do
|
||||
Config.put([:mrf_simple, :accept], ["non.matching.remote"])
|
||||
|
||||
local_message = build_local_message()
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
end
|
||||
|
||||
test "activity has a matching host" do
|
||||
Config.put([:mrf_simple, :accept], ["remote.instance"])
|
||||
|
||||
local_message = build_local_message()
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
end
|
||||
|
||||
test "activity matches with wildcard domain" do
|
||||
Config.put([:mrf_simple, :accept], ["*.remote.instance"])
|
||||
|
||||
local_message = build_local_message()
|
||||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
end
|
||||
|
||||
test "actor has a matching host" do
|
||||
Config.put([:mrf_simple, :accept], ["remote.instance"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :avatar_removal" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :avatar_removal], [])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
end
|
||||
|
||||
test "is not empty but it doesn't have a matching host" do
|
||||
Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
{:ok, filtered} = SimplePolicy.filter(remote_user)
|
||||
|
||||
refute filtered["icon"]
|
||||
end
|
||||
|
||||
test "match with wildcard domain" do
|
||||
Config.put([:mrf_simple, :avatar_removal], ["*.remote.instance"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
{:ok, filtered} = SimplePolicy.filter(remote_user)
|
||||
|
||||
refute filtered["icon"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :banner_removal" do
|
||||
test "is empty" do
|
||||
Config.put([:mrf_simple, :banner_removal], [])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
end
|
||||
|
||||
test "is not empty but it doesn't have a matching host" do
|
||||
Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
end
|
||||
|
||||
test "has a matching host" do
|
||||
Config.put([:mrf_simple, :banner_removal], ["remote.instance"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
{:ok, filtered} = SimplePolicy.filter(remote_user)
|
||||
|
||||
refute filtered["image"]
|
||||
end
|
||||
|
||||
test "match with wildcard domain" do
|
||||
Config.put([:mrf_simple, :banner_removal], ["*.remote.instance"])
|
||||
|
||||
remote_user = build_remote_user()
|
||||
{:ok, filtered} = SimplePolicy.filter(remote_user)
|
||||
|
||||
refute filtered["image"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :reject_deletes is empty" do
|
||||
setup do: Config.put([:mrf_simple, :reject_deletes], [])
|
||||
|
||||
test "it accepts deletions even from rejected servers" do
|
||||
Config.put([:mrf_simple, :reject], ["remote.instance"])
|
||||
|
||||
deletion_message = build_remote_deletion_message()
|
||||
|
||||
assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
|
||||
end
|
||||
|
||||
test "it accepts deletions even from non-whitelisted servers" do
|
||||
Config.put([:mrf_simple, :accept], ["non.matching.remote"])
|
||||
|
||||
deletion_message = build_remote_deletion_message()
|
||||
|
||||
assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :reject_deletes is not empty but it doesn't have a matching host" do
|
||||
setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
|
||||
|
||||
test "it accepts deletions even from rejected servers" do
|
||||
Config.put([:mrf_simple, :reject], ["remote.instance"])
|
||||
|
||||
deletion_message = build_remote_deletion_message()
|
||||
|
||||
assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
|
||||
end
|
||||
|
||||
test "it accepts deletions even from non-whitelisted servers" do
|
||||
Config.put([:mrf_simple, :accept], ["non.matching.remote"])
|
||||
|
||||
deletion_message = build_remote_deletion_message()
|
||||
|
||||
assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :reject_deletes has a matching host" do
|
||||
setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
|
||||
|
||||
test "it rejects the deletion" do
|
||||
deletion_message = build_remote_deletion_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(deletion_message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :reject_deletes match with wildcard domain" do
|
||||
setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
|
||||
|
||||
test "it rejects the deletion" do
|
||||
deletion_message = build_remote_deletion_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(deletion_message)
|
||||
end
|
||||
end
|
||||
|
||||
defp build_local_message do
|
||||
%{
|
||||
"actor" => "#{Pleroma.Web.base_url()}/users/alice",
|
||||
"to" => [],
|
||||
"cc" => []
|
||||
}
|
||||
end
|
||||
|
||||
defp build_remote_message do
|
||||
%{"actor" => "https://remote.instance/users/bob"}
|
||||
end
|
||||
|
||||
defp build_remote_user do
|
||||
%{
|
||||
"id" => "https://remote.instance/users/bob",
|
||||
"icon" => %{
|
||||
"url" => "http://example.com/image.jpg",
|
||||
"type" => "Image"
|
||||
},
|
||||
"image" => %{
|
||||
"url" => "http://example.com/image.jpg",
|
||||
"type" => "Image"
|
||||
},
|
||||
"type" => "Person"
|
||||
}
|
||||
end
|
||||
|
||||
defp build_remote_deletion_message do
|
||||
%{
|
||||
"type" => "Delete",
|
||||
"actor" => "https://remote.instance/users/bob"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
# 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.StealEmojiPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
setup do
|
||||
emoji_path = Path.join(Config.get([:instance, :static_dir]), "emoji/stolen")
|
||||
File.rm_rf!(emoji_path)
|
||||
File.mkdir!(emoji_path)
|
||||
|
||||
Pleroma.Emoji.reload()
|
||||
|
||||
on_exit(fn ->
|
||||
File.rm_rf!(emoji_path)
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "does nothing by default" do
|
||||
installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
|
||||
refute "firedfox" in installed_emoji
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
|
||||
"actor" => "https://example.org/users/admin"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, message} == StealEmojiPolicy.filter(message)
|
||||
|
||||
installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
|
||||
refute "firedfox" in installed_emoji
|
||||
end
|
||||
|
||||
test "Steals emoji on unknown shortcode from allowed remote host" do
|
||||
installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
|
||||
refute "firedfox" in installed_emoji
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"emoji" => [{"firedfox", "https://example.org/emoji/firedfox.png"}],
|
||||
"actor" => "https://example.org/users/admin"
|
||||
}
|
||||
}
|
||||
|
||||
clear_config([:mrf_steal_emoji, :hosts], ["example.org"])
|
||||
clear_config([:mrf_steal_emoji, :size_limit], 284_468)
|
||||
|
||||
assert {:ok, message} == StealEmojiPolicy.filter(message)
|
||||
|
||||
installed_emoji = Pleroma.Emoji.get_all() |> Enum.map(fn {k, _} -> k end)
|
||||
assert "firedfox" in installed_emoji
|
||||
end
|
||||
end
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# 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.SubchainPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.DropPolicy
|
||||
alias Pleroma.Web.ActivityPub.MRF.SubchainPolicy
|
||||
|
||||
@message %{
|
||||
"actor" => "https://banned.com",
|
||||
"type" => "Create",
|
||||
"object" => %{"content" => "hi"}
|
||||
}
|
||||
setup do: clear_config([:mrf_subchain, :match_actor])
|
||||
|
||||
test "it matches and processes subchains when the actor matches a configured target" do
|
||||
Pleroma.Config.put([:mrf_subchain, :match_actor], %{
|
||||
~r/^https:\/\/banned.com/s => [DropPolicy]
|
||||
})
|
||||
|
||||
{:reject, _} = SubchainPolicy.filter(@message)
|
||||
end
|
||||
|
||||
test "it doesn't match and process subchains when the actor doesn't match a configured target" do
|
||||
Pleroma.Config.put([:mrf_subchain, :match_actor], %{
|
||||
~r/^https:\/\/borked.com/s => [DropPolicy]
|
||||
})
|
||||
|
||||
{:ok, _message} = SubchainPolicy.filter(@message)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
# 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.TagPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.TagPolicy
|
||||
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
describe "mrf_tag:disable-any-subscription" do
|
||||
test "rejects message" do
|
||||
actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"])
|
||||
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => actor.ap_id}
|
||||
assert {:reject, _} = TagPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mrf_tag:disable-remote-subscription" do
|
||||
test "rejects non-local follow requests" do
|
||||
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
|
||||
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)
|
||||
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
|
||||
assert {:reject, _} = TagPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "allows non-local follow requests" do
|
||||
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
|
||||
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: true)
|
||||
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
|
||||
assert {:ok, message} = TagPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mrf_tag:sandbox" do
|
||||
test "removes from public timelines" do
|
||||
actor = insert(:user, tags: ["mrf_tag:sandbox"])
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{},
|
||||
"to" => [@public, "f"],
|
||||
"cc" => [@public, "d"]
|
||||
}
|
||||
|
||||
except_message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d"]},
|
||||
"to" => ["f", actor.follower_address],
|
||||
"cc" => ["d"]
|
||||
}
|
||||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "mrf_tag:force-unlisted" do
|
||||
test "removes from the federated timeline" do
|
||||
actor = insert(:user, tags: ["mrf_tag:force-unlisted"])
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{},
|
||||
"to" => [@public, "f"],
|
||||
"cc" => [actor.follower_address, "d"]
|
||||
}
|
||||
|
||||
except_message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
|
||||
"to" => ["f", actor.follower_address],
|
||||
"cc" => ["d", @public]
|
||||
}
|
||||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "mrf_tag:media-strip" do
|
||||
test "removes attachments" do
|
||||
actor = insert(:user, tags: ["mrf_tag:media-strip"])
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{"attachment" => ["file1"]}
|
||||
}
|
||||
|
||||
except_message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{}
|
||||
}
|
||||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "mrf_tag:media-force-nsfw" do
|
||||
test "Mark as sensitive on presence of attachments" do
|
||||
actor = insert(:user, tags: ["mrf_tag:media-force-nsfw"])
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{"tag" => ["test"], "attachment" => ["file1"]}
|
||||
}
|
||||
|
||||
except_message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Create",
|
||||
"object" => %{"tag" => ["test", "nsfw"], "attachment" => ["file1"], "sensitive" => true}
|
||||
}
|
||||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# 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.UserAllowListPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
|
||||
|
||||
setup do: clear_config(:mrf_user_allowlist)
|
||||
|
||||
test "pass filter if allow list is empty" do
|
||||
actor = insert(:user)
|
||||
message = %{"actor" => actor.ap_id}
|
||||
assert UserAllowListPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
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"]})
|
||||
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"]})
|
||||
message = %{"actor" => actor.ap_id}
|
||||
assert {:reject, _} = UserAllowListPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
# 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.VocabularyPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.VocabularyPolicy
|
||||
|
||||
describe "accept" do
|
||||
setup do: clear_config([:mrf_vocabulary, :accept])
|
||||
|
||||
test "it accepts based on parent activity type" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Like"])
|
||||
|
||||
message = %{
|
||||
"type" => "Like",
|
||||
"object" => "whatever"
|
||||
}
|
||||
|
||||
{:ok, ^message} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it accepts based on child object type" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Create", "Note"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "whatever"
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, ^message} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it does not accept disallowed child objects" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Create", "Note"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Article",
|
||||
"content" => "whatever"
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, _} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it does not accept disallowed parent types" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :accept], ["Announce", "Note"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "whatever"
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, _} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "reject" do
|
||||
setup do: clear_config([:mrf_vocabulary, :reject])
|
||||
|
||||
test "it rejects based on parent activity type" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"])
|
||||
|
||||
message = %{
|
||||
"type" => "Like",
|
||||
"object" => "whatever"
|
||||
}
|
||||
|
||||
{:reject, _} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it rejects based on child object type" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], ["Note"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "whatever"
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, _} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it passes through objects that aren't disallowed" do
|
||||
Pleroma.Config.put([:mrf_vocabulary, :reject], ["Like"])
|
||||
|
||||
message = %{
|
||||
"type" => "Announce",
|
||||
"object" => "whatever"
|
||||
}
|
||||
|
||||
{:ok, ^message} = VocabularyPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
# 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.DateTimeTest do
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime
|
||||
use Pleroma.DataCase
|
||||
|
||||
test "it validates an xsd:Datetime" do
|
||||
valid_strings = [
|
||||
"2004-04-12T13:20:00",
|
||||
"2004-04-12T13:20:15.5",
|
||||
"2004-04-12T13:20:00-05:00",
|
||||
"2004-04-12T13:20:00Z"
|
||||
]
|
||||
|
||||
invalid_strings = [
|
||||
"2004-04-12T13:00",
|
||||
"2004-04-1213:20:00",
|
||||
"99-04-12T13:00",
|
||||
"2004-04-12"
|
||||
]
|
||||
|
||||
assert {:ok, "2004-04-01T12:00:00Z"} == DateTime.cast("2004-04-01T12:00:00Z")
|
||||
|
||||
Enum.each(valid_strings, fn date_time ->
|
||||
result = DateTime.cast(date_time)
|
||||
assert {:ok, _} = result
|
||||
end)
|
||||
|
||||
Enum.each(invalid_strings, fn date_time ->
|
||||
result = DateTime.cast(date_time)
|
||||
assert :error == result
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# 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.EctoType.ActivityPub.ObjectValidators.ObjectID
|
||||
use Pleroma.DataCase
|
||||
|
||||
@uris [
|
||||
"http://lain.com/users/lain",
|
||||
"http://lain.com",
|
||||
"https://lain.com/object/1"
|
||||
]
|
||||
|
||||
@non_uris [
|
||||
"https://",
|
||||
"rin",
|
||||
1,
|
||||
:x,
|
||||
%{"1" => 2}
|
||||
]
|
||||
|
||||
test "it accepts http uris" do
|
||||
Enum.each(@uris, fn uri ->
|
||||
assert {:ok, uri} == ObjectID.cast(uri)
|
||||
end)
|
||||
end
|
||||
|
||||
test "it accepts an object with a nested uri id" do
|
||||
Enum.each(@uris, fn uri ->
|
||||
assert {:ok, uri} == ObjectID.cast(%{"id" => uri})
|
||||
end)
|
||||
end
|
||||
|
||||
test "it rejects non-uri strings" do
|
||||
Enum.each(@non_uris, fn non_uri ->
|
||||
assert :error == ObjectID.cast(non_uri)
|
||||
assert :error == ObjectID.cast(%{"id" => non_uri})
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# 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.RecipientsTest do
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients
|
||||
use Pleroma.DataCase
|
||||
|
||||
test "it asserts that all elements of the list are object ids" do
|
||||
list = ["https://lain.com/users/lain", "invalid"]
|
||||
|
||||
assert :error == Recipients.cast(list)
|
||||
end
|
||||
|
||||
test "it works with a list" do
|
||||
list = ["https://lain.com/users/lain"]
|
||||
assert {:ok, list} == Recipients.cast(list)
|
||||
end
|
||||
|
||||
test "it works with a list with whole objects" do
|
||||
list = ["https://lain.com/users/lain", %{"id" => "https://gensokyo.2hu/users/raymoo"}]
|
||||
resulting_list = ["https://gensokyo.2hu/users/raymoo", "https://lain.com/users/lain"]
|
||||
assert {:ok, resulting_list} == Recipients.cast(list)
|
||||
end
|
||||
|
||||
test "it turns a single string into a list" do
|
||||
recipient = "https://lain.com/users/lain"
|
||||
|
||||
assert {:ok, [recipient]} == Recipients.cast(recipient)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
# 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.EctoType.ActivityPub.ObjectValidators.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
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
# 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.PipelineTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "common_pipeline/2" do
|
||||
setup do
|
||||
clear_config([:instance, :federating], true)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "when given an `object_data` in meta, Federation will receive a the original activity with the `object` field set to this embedded object" do
|
||||
activity = insert(:note_activity)
|
||||
object = %{"id" => "1", "type" => "Love"}
|
||||
meta = [local: true, object_data: object]
|
||||
|
||||
activity_with_object = %{activity | data: Map.put(activity.data, "object", object)}
|
||||
|
||||
with_mocks([
|
||||
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.MRF,
|
||||
[],
|
||||
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.ActivityPub,
|
||||
[],
|
||||
[persist: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.SideEffects,
|
||||
[],
|
||||
[
|
||||
handle: fn o, m -> {:ok, o, m} end,
|
||||
handle_after_transaction: fn m -> m end
|
||||
]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.Federator,
|
||||
[],
|
||||
[publish: fn _o -> :ok end]
|
||||
}
|
||||
]) do
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
|
||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
assert_called(Pleroma.Web.Federator.publish(activity_with_object))
|
||||
end
|
||||
end
|
||||
|
||||
test "it goes through validation, filtering, persisting, side effects and federation for local activities" do
|
||||
activity = insert(:note_activity)
|
||||
meta = [local: true]
|
||||
|
||||
with_mocks([
|
||||
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.MRF,
|
||||
[],
|
||||
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.ActivityPub,
|
||||
[],
|
||||
[persist: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.SideEffects,
|
||||
[],
|
||||
[
|
||||
handle: fn o, m -> {:ok, o, m} end,
|
||||
handle_after_transaction: fn m -> m end
|
||||
]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.Federator,
|
||||
[],
|
||||
[publish: fn _o -> :ok end]
|
||||
}
|
||||
]) do
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
|
||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||
assert_called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do
|
||||
activity = insert(:note_activity)
|
||||
meta = [local: false]
|
||||
|
||||
with_mocks([
|
||||
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.MRF,
|
||||
[],
|
||||
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.ActivityPub,
|
||||
[],
|
||||
[persist: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.SideEffects,
|
||||
[],
|
||||
[handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.Federator,
|
||||
[],
|
||||
[]
|
||||
}
|
||||
]) do
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
|
||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||
end
|
||||
end
|
||||
|
||||
test "it goes through validation, filtering, persisting, side effects without federation for local activities if federation is deactivated" do
|
||||
clear_config([:instance, :federating], false)
|
||||
|
||||
activity = insert(:note_activity)
|
||||
meta = [local: true]
|
||||
|
||||
with_mocks([
|
||||
{Pleroma.Web.ActivityPub.ObjectValidator, [], [validate: fn o, m -> {:ok, o, m} end]},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.MRF,
|
||||
[],
|
||||
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.ActivityPub,
|
||||
[],
|
||||
[persist: fn o, m -> {:ok, o, m} end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.ActivityPub.SideEffects,
|
||||
[],
|
||||
[handle: fn o, m -> {:ok, o, m} end, handle_after_transaction: fn m -> m end]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.Federator,
|
||||
[],
|
||||
[]
|
||||
}
|
||||
]) do
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
|
||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
# 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.PublisherTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
import Mock
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Publisher
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
@as_public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
setup_all do: clear_config([:instance, :federating], true)
|
||||
|
||||
describe "gather_webfinger_links/1" do
|
||||
test "it returns links" do
|
||||
user = insert(:user)
|
||||
|
||||
expected_links = [
|
||||
%{"href" => user.ap_id, "rel" => "self", "type" => "application/activity+json"},
|
||||
%{
|
||||
"href" => user.ap_id,
|
||||
"rel" => "self",
|
||||
"type" => "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||
},
|
||||
%{
|
||||
"rel" => "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template" => "#{Pleroma.Web.base_url()}/ostatus_subscribe?acct={uri}"
|
||||
}
|
||||
]
|
||||
|
||||
assert expected_links == Publisher.gather_webfinger_links(user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "determine_inbox/2" do
|
||||
test "it returns sharedInbox for messages involving as:Public in to" do
|
||||
user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
|
||||
|
||||
activity = %Activity{
|
||||
data: %{"to" => [@as_public], "cc" => [user.follower_address]}
|
||||
}
|
||||
|
||||
assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
|
||||
end
|
||||
|
||||
test "it returns sharedInbox for messages involving as:Public in cc" do
|
||||
user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
|
||||
|
||||
activity = %Activity{
|
||||
data: %{"cc" => [@as_public], "to" => [user.follower_address]}
|
||||
}
|
||||
|
||||
assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
|
||||
end
|
||||
|
||||
test "it returns sharedInbox for messages involving multiple recipients in to" do
|
||||
user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
|
||||
user_two = insert(:user)
|
||||
user_three = insert(:user)
|
||||
|
||||
activity = %Activity{
|
||||
data: %{"cc" => [], "to" => [user.ap_id, user_two.ap_id, user_three.ap_id]}
|
||||
}
|
||||
|
||||
assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
|
||||
end
|
||||
|
||||
test "it returns sharedInbox for messages involving multiple recipients in cc" do
|
||||
user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
|
||||
user_two = insert(:user)
|
||||
user_three = insert(:user)
|
||||
|
||||
activity = %Activity{
|
||||
data: %{"to" => [], "cc" => [user.ap_id, user_two.ap_id, user_three.ap_id]}
|
||||
}
|
||||
|
||||
assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
|
||||
end
|
||||
|
||||
test "it returns sharedInbox for messages involving multiple recipients in total" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
shared_inbox: "http://example.com/inbox",
|
||||
inbox: "http://example.com/personal-inbox"
|
||||
})
|
||||
|
||||
user_two = insert(:user)
|
||||
|
||||
activity = %Activity{
|
||||
data: %{"to" => [user_two.ap_id], "cc" => [user.ap_id]}
|
||||
}
|
||||
|
||||
assert Publisher.determine_inbox(activity, user) == "http://example.com/inbox"
|
||||
end
|
||||
|
||||
test "it returns inbox for messages involving single recipients in total" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
shared_inbox: "http://example.com/inbox",
|
||||
inbox: "http://example.com/personal-inbox"
|
||||
})
|
||||
|
||||
activity = %Activity{
|
||||
data: %{"to" => [user.ap_id], "cc" => []}
|
||||
}
|
||||
|
||||
assert Publisher.determine_inbox(activity, user) == "http://example.com/personal-inbox"
|
||||
end
|
||||
end
|
||||
|
||||
describe "publish_one/1" do
|
||||
test "publish to url with with different ports" do
|
||||
inbox80 = "http://42.site/users/nick1/inbox"
|
||||
inbox42 = "http://42.site:42/users/nick1/inbox"
|
||||
|
||||
mock(fn
|
||||
%{method: :post, url: "http://42.site:42/users/nick1/inbox"} ->
|
||||
{:ok, %Tesla.Env{status: 200, body: "port 42"}}
|
||||
|
||||
%{method: :post, url: "http://42.site/users/nick1/inbox"} ->
|
||||
{:ok, %Tesla.Env{status: 200, body: "port 80"}}
|
||||
end)
|
||||
|
||||
actor = insert(:user)
|
||||
|
||||
assert {:ok, %{body: "port 42"}} =
|
||||
Publisher.publish_one(%{
|
||||
inbox: inbox42,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: true
|
||||
})
|
||||
|
||||
assert {:ok, %{body: "port 80"}} =
|
||||
Publisher.publish_one(%{
|
||||
inbox: inbox80,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: true
|
||||
})
|
||||
end
|
||||
|
||||
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
|
||||
assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
assert called(Instances.set_reachable(inbox))
|
||||
end
|
||||
|
||||
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is set",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
|
||||
assert {:ok, _} =
|
||||
Publisher.publish_one(%{
|
||||
inbox: inbox,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: NaiveDateTime.utc_now()
|
||||
})
|
||||
|
||||
assert called(Instances.set_reachable(inbox))
|
||||
end
|
||||
|
||||
test_with_mock "does NOT call `Instances.set_reachable` on successful federation if `unreachable_since` is nil",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
|
||||
assert {:ok, _} =
|
||||
Publisher.publish_one(%{
|
||||
inbox: inbox,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: nil
|
||||
})
|
||||
|
||||
refute called(Instances.set_reachable(inbox))
|
||||
end
|
||||
|
||||
test_with_mock "calls `Instances.set_unreachable` on target inbox on non-2xx HTTP response code",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://404.site/users/nick1/inbox"
|
||||
|
||||
assert {:error, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
|
||||
assert called(Instances.set_unreachable(inbox))
|
||||
end
|
||||
|
||||
test_with_mock "it calls `Instances.set_unreachable` on target inbox on request error of any kind",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://connrefused.site/users/nick1/inbox"
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, _} =
|
||||
Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
end) =~ "connrefused"
|
||||
|
||||
assert called(Instances.set_unreachable(inbox))
|
||||
end
|
||||
|
||||
test_with_mock "does NOT call `Instances.set_unreachable` if target is reachable",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
|
||||
assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
|
||||
refute called(Instances.set_unreachable(inbox))
|
||||
end
|
||||
|
||||
test_with_mock "does NOT call `Instances.set_unreachable` if target instance has non-nil `unreachable_since`",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://connrefused.site/users/nick1/inbox"
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, _} =
|
||||
Publisher.publish_one(%{
|
||||
inbox: inbox,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: NaiveDateTime.utc_now()
|
||||
})
|
||||
end) =~ "connrefused"
|
||||
|
||||
refute called(Instances.set_unreachable(inbox))
|
||||
end
|
||||
end
|
||||
|
||||
describe "publish/2" do
|
||||
test_with_mock "publishes an activity with BCC to all relevant peers.",
|
||||
Pleroma.Web.Federator.Publisher,
|
||||
[:passthrough],
|
||||
[] do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, _follower_one} = Pleroma.User.follow(follower, actor)
|
||||
actor = refresh_record(actor)
|
||||
|
||||
note_activity =
|
||||
insert(:note_activity,
|
||||
recipients: [follower.ap_id],
|
||||
data_attrs: %{"bcc" => [user.ap_id]}
|
||||
)
|
||||
|
||||
res = Publisher.publish(actor, note_activity)
|
||||
assert res == :ok
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
})
|
||||
)
|
||||
end
|
||||
|
||||
test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.",
|
||||
Pleroma.Web.Federator.Publisher,
|
||||
[:passthrough],
|
||||
[] do
|
||||
fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
)
|
||||
|
||||
another_fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
)
|
||||
|
||||
actor = insert(:user)
|
||||
|
||||
note_activity = insert(:note_activity, user: actor)
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
activity_path = String.trim_leading(note_activity.data["id"], Pleroma.Web.Endpoint.url())
|
||||
object_path = String.trim_leading(object.data["id"], Pleroma.Web.Endpoint.url())
|
||||
|
||||
build_conn()
|
||||
|> put_req_header("accept", "application/activity+json")
|
||||
|> assign(:user, fetcher)
|
||||
|> get(object_path)
|
||||
|> json_response(200)
|
||||
|
||||
build_conn()
|
||||
|> put_req_header("accept", "application/activity+json")
|
||||
|> assign(:user, another_fetcher)
|
||||
|> get(activity_path)
|
||||
|> json_response(200)
|
||||
|
||||
{:ok, delete} = CommonAPI.delete(note_activity.id, actor)
|
||||
|
||||
res = Publisher.publish(actor, delete)
|
||||
assert res == :ok
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
})
|
||||
)
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
})
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
# 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.RelayTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
test "gets an actor for the relay" do
|
||||
user = Relay.get_actor()
|
||||
assert user.ap_id == "#{Pleroma.Web.Endpoint.url()}/relay"
|
||||
end
|
||||
|
||||
test "relay actor is invisible" do
|
||||
user = Relay.get_actor()
|
||||
assert User.invisible?(user)
|
||||
end
|
||||
|
||||
describe "follow/1" do
|
||||
test "returns errors when user not found" do
|
||||
assert capture_log(fn ->
|
||||
{:error, _} = Relay.follow("test-ap-id")
|
||||
end) =~ "Could not decode user at fetch"
|
||||
end
|
||||
|
||||
test "returns activity" do
|
||||
user = insert(:user)
|
||||
service_actor = Relay.get_actor()
|
||||
assert {:ok, %Activity{} = activity} = Relay.follow(user.ap_id)
|
||||
assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
|
||||
assert user.ap_id in activity.recipients
|
||||
assert activity.data["type"] == "Follow"
|
||||
assert activity.data["actor"] == service_actor.ap_id
|
||||
assert activity.data["object"] == user.ap_id
|
||||
end
|
||||
end
|
||||
|
||||
describe "unfollow/1" do
|
||||
test "returns errors when user not found" do
|
||||
assert capture_log(fn ->
|
||||
{:error, _} = Relay.unfollow("test-ap-id")
|
||||
end) =~ "Could not decode user at fetch"
|
||||
end
|
||||
|
||||
test "returns activity" do
|
||||
user = insert(:user)
|
||||
service_actor = Relay.get_actor()
|
||||
CommonAPI.follow(service_actor, user)
|
||||
assert "#{user.ap_id}/followers" in User.following(service_actor)
|
||||
assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)
|
||||
assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
|
||||
assert user.ap_id in activity.recipients
|
||||
assert activity.data["type"] == "Undo"
|
||||
assert activity.data["actor"] == service_actor.ap_id
|
||||
assert activity.data["to"] == [user.ap_id]
|
||||
refute "#{user.ap_id}/followers" in User.following(service_actor)
|
||||
end
|
||||
|
||||
test "force unfollow when target service is dead" do
|
||||
user = insert(:user)
|
||||
user_ap_id = user.ap_id
|
||||
user_id = user.id
|
||||
|
||||
Tesla.Mock.mock(fn %{method: :get, url: ^user_ap_id} ->
|
||||
%Tesla.Env{status: 404}
|
||||
end)
|
||||
|
||||
service_actor = Relay.get_actor()
|
||||
CommonAPI.follow(service_actor, user)
|
||||
assert "#{user.ap_id}/followers" in User.following(service_actor)
|
||||
|
||||
assert Pleroma.Repo.get_by(
|
||||
Pleroma.FollowingRelationship,
|
||||
follower_id: service_actor.id,
|
||||
following_id: user_id
|
||||
)
|
||||
|
||||
Pleroma.Repo.delete(user)
|
||||
Cachex.clear(:user_cache)
|
||||
|
||||
assert {:ok, %Activity{} = activity} = Relay.unfollow(user_ap_id, %{force: true})
|
||||
|
||||
assert refresh_record(service_actor).following_count == 0
|
||||
|
||||
refute Pleroma.Repo.get_by(
|
||||
Pleroma.FollowingRelationship,
|
||||
follower_id: service_actor.id,
|
||||
following_id: user_id
|
||||
)
|
||||
|
||||
assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
|
||||
assert user.ap_id in activity.recipients
|
||||
assert activity.data["type"] == "Undo"
|
||||
assert activity.data["actor"] == service_actor.ap_id
|
||||
assert activity.data["to"] == [user_ap_id]
|
||||
refute "#{user.ap_id}/followers" in User.following(service_actor)
|
||||
end
|
||||
end
|
||||
|
||||
describe "publish/1" do
|
||||
setup do: clear_config([:instance, :federating])
|
||||
|
||||
test "returns error when activity not `Create` type" do
|
||||
activity = insert(:like_activity)
|
||||
assert Relay.publish(activity) == {:error, "Not implemented"}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns error when activity not public" do
|
||||
activity = insert(:direct_note_activity)
|
||||
assert Relay.publish(activity) == {:error, false}
|
||||
end
|
||||
|
||||
test "returns error when object is unknown" do
|
||||
activity =
|
||||
insert(:note_activity,
|
||||
data: %{
|
||||
"type" => "Create",
|
||||
"object" => "http://mastodon.example.org/eee/99541947525187367"
|
||||
}
|
||||
)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get, url: "http://mastodon.example.org/eee/99541947525187367"} ->
|
||||
%Tesla.Env{status: 500, body: ""}
|
||||
end)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert Relay.publish(activity) == {:error, false}
|
||||
end) =~ "[error] error: false"
|
||||
end
|
||||
|
||||
test_with_mock "returns announce activity and publish to federate",
|
||||
Pleroma.Web.Federator,
|
||||
[:passthrough],
|
||||
[] do
|
||||
clear_config([:instance, :federating], true)
|
||||
service_actor = Relay.get_actor()
|
||||
note = insert(:note_activity)
|
||||
assert {:ok, %Activity{} = activity} = Relay.publish(note)
|
||||
assert activity.data["type"] == "Announce"
|
||||
assert activity.data["actor"] == service_actor.ap_id
|
||||
assert activity.data["to"] == [service_actor.follower_address]
|
||||
assert called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
|
||||
test_with_mock "returns announce activity and not publish to federate",
|
||||
Pleroma.Web.Federator,
|
||||
[:passthrough],
|
||||
[] do
|
||||
clear_config([:instance, :federating], false)
|
||||
service_actor = Relay.get_actor()
|
||||
note = insert(:note_activity)
|
||||
assert {:ok, %Activity{} = activity} = Relay.publish(note)
|
||||
assert activity.data["type"] == "Announce"
|
||||
assert activity.data["actor"] == service_actor.ap_id
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,639 +0,0 @@
|
|||
# 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.SideEffectsTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Chat
|
||||
alias Pleroma.Chat.MessageReference
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.SideEffects
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
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 "blocking users" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
blocked = insert(:user)
|
||||
User.follow(blocked, user)
|
||||
User.follow(user, blocked)
|
||||
|
||||
{:ok, block_data, []} = Builder.block(user, blocked)
|
||||
{:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
|
||||
|
||||
%{user: user, blocked: blocked, block: block}
|
||||
end
|
||||
|
||||
test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
|
||||
assert User.following?(user, blocked)
|
||||
assert User.following?(blocked, user)
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(block)
|
||||
|
||||
refute User.following?(user, blocked)
|
||||
refute User.following?(blocked, user)
|
||||
assert User.blocks?(user, blocked)
|
||||
end
|
||||
|
||||
test "it blocks but does not unfollow if the relevant setting is set", %{
|
||||
user: user,
|
||||
blocked: blocked,
|
||||
block: block
|
||||
} do
|
||||
clear_config([:activitypub, :unfollow_blocked], false)
|
||||
assert User.following?(user, blocked)
|
||||
assert User.following?(blocked, user)
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(block)
|
||||
|
||||
refute User.following?(user, blocked)
|
||||
assert User.following?(blocked, user)
|
||||
assert User.blocks?(user, blocked)
|
||||
end
|
||||
end
|
||||
|
||||
describe "update users" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, update_data, []} = Builder.update(user, %{"id" => user.ap_id, "name" => "new name!"})
|
||||
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
|
||||
|
||||
%{user: user, update_data: update_data, update: update}
|
||||
end
|
||||
|
||||
test "it updates the user", %{user: user, update: update} do
|
||||
{:ok, _, _} = SideEffects.handle(update)
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.name == "new name!"
|
||||
end
|
||||
|
||||
test "it uses a given changeset to update", %{user: user, update: update} do
|
||||
changeset = Ecto.Changeset.change(user, %{default_scope: "direct"})
|
||||
|
||||
assert user.default_scope == "public"
|
||||
{:ok, _, _} = SideEffects.handle(update, user_update_changeset: changeset)
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.default_scope == "direct"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete objects" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
|
||||
{:ok, favorite} = CommonAPI.favorite(user, post.id)
|
||||
object = Object.normalize(post)
|
||||
{:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
|
||||
{:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
|
||||
{:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
|
||||
{:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
|
||||
|
||||
%{
|
||||
user: user,
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
delete_user: delete_user,
|
||||
op: op,
|
||||
favorite: favorite
|
||||
}
|
||||
end
|
||||
|
||||
test "it handles object deletions", %{
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
user: user,
|
||||
op: op,
|
||||
favorite: favorite
|
||||
} do
|
||||
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
|
||||
stream_out: fn _ -> nil end,
|
||||
stream_out_participations: fn _, _ -> nil end do
|
||||
{:ok, delete, _} = SideEffects.handle(delete)
|
||||
user = User.get_cached_by_ap_id(object.data["actor"])
|
||||
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
|
||||
end
|
||||
|
||||
object = Object.get_by_id(object.id)
|
||||
assert object.data["type"] == "Tombstone"
|
||||
refute Activity.get_by_id(post.id)
|
||||
refute Activity.get_by_id(favorite.id)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.note_count == 0
|
||||
|
||||
object = Object.normalize(op.data["object"], false)
|
||||
|
||||
assert object.data["repliesCount"] == 0
|
||||
end
|
||||
|
||||
test "it handles object deletions when the object itself has been pruned", %{
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
user: user,
|
||||
op: op
|
||||
} do
|
||||
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
|
||||
stream_out: fn _ -> nil end,
|
||||
stream_out_participations: fn _, _ -> nil end do
|
||||
{:ok, delete, _} = SideEffects.handle(delete)
|
||||
user = User.get_cached_by_ap_id(object.data["actor"])
|
||||
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
|
||||
end
|
||||
|
||||
object = Object.get_by_id(object.id)
|
||||
assert object.data["type"] == "Tombstone"
|
||||
refute Activity.get_by_id(post.id)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.note_count == 0
|
||||
|
||||
object = Object.normalize(op.data["object"], false)
|
||||
|
||||
assert object.data["repliesCount"] == 0
|
||||
end
|
||||
|
||||
test "it handles user deletions", %{delete_user: delete, user: user} do
|
||||
{:ok, _delete, _} = SideEffects.handle(delete)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert User.get_cached_by_ap_id(user.ap_id).deactivated
|
||||
end
|
||||
|
||||
test "it logs issues with objects deletion", %{
|
||||
delete: delete,
|
||||
object: object
|
||||
} do
|
||||
{:ok, object} =
|
||||
object
|
||||
|> Object.change(%{data: Map.delete(object.data, "actor")})
|
||||
|> Repo.update()
|
||||
|
||||
Object.invalid_object_cache(object)
|
||||
|
||||
assert capture_log(fn ->
|
||||
{:error, :no_object_actor} = SideEffects.handle(delete)
|
||||
end) =~ "object doesn't have an actor"
|
||||
end
|
||||
end
|
||||
|
||||
describe "EmojiReact objects" do
|
||||
setup do
|
||||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
|
||||
{:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
|
||||
{:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
|
||||
|
||||
%{emoji_react: emoji_react, user: user, poster: poster}
|
||||
end
|
||||
|
||||
test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
|
||||
{:ok, emoji_react, _} = SideEffects.handle(emoji_react)
|
||||
object = Object.get_by_ap_id(emoji_react.data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
assert ["👌", [user.ap_id]] in object.data["reactions"]
|
||||
end
|
||||
|
||||
test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
|
||||
{:ok, emoji_react, _} = SideEffects.handle(emoji_react)
|
||||
assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete users with confirmation pending" do
|
||||
setup do
|
||||
user = insert(:user, confirmation_pending: true)
|
||||
{:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
|
||||
{:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
|
||||
{:ok, delete: delete_user, user: user}
|
||||
end
|
||||
|
||||
test "when activation is not required", %{delete: delete, user: user} do
|
||||
clear_config([:instance, :account_activation_required], false)
|
||||
{:ok, _, _} = SideEffects.handle(delete)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert User.get_cached_by_id(user.id).deactivated
|
||||
end
|
||||
|
||||
test "when activation is required", %{delete: delete, user: user} do
|
||||
clear_config([:instance, :account_activation_required], true)
|
||||
{:ok, _, _} = SideEffects.handle(delete)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
refute User.get_cached_by_id(user.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Undo objects" do
|
||||
setup do
|
||||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
{:ok, like} = CommonAPI.favorite(user, post.id)
|
||||
{:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
|
||||
{:ok, announce} = CommonAPI.repeat(post.id, user)
|
||||
{:ok, block} = CommonAPI.block(user, poster)
|
||||
|
||||
{:ok, undo_data, _meta} = Builder.undo(user, like)
|
||||
{:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
||||
|
||||
{:ok, undo_data, _meta} = Builder.undo(user, reaction)
|
||||
{:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
||||
|
||||
{:ok, undo_data, _meta} = Builder.undo(user, announce)
|
||||
{:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
||||
|
||||
{:ok, undo_data, _meta} = Builder.undo(user, block)
|
||||
{:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
||||
|
||||
%{
|
||||
like_undo: like_undo,
|
||||
post: post,
|
||||
like: like,
|
||||
reaction_undo: reaction_undo,
|
||||
reaction: reaction,
|
||||
announce_undo: announce_undo,
|
||||
announce: announce,
|
||||
block_undo: block_undo,
|
||||
block: block,
|
||||
poster: poster,
|
||||
user: user
|
||||
}
|
||||
end
|
||||
|
||||
test "deletes the original block", %{
|
||||
block_undo: block_undo,
|
||||
block: block
|
||||
} do
|
||||
{:ok, _block_undo, _meta} = SideEffects.handle(block_undo)
|
||||
|
||||
refute Activity.get_by_id(block.id)
|
||||
end
|
||||
|
||||
test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
|
||||
blocker = User.get_by_ap_id(block.data["actor"])
|
||||
blocked = User.get_by_ap_id(block.data["object"])
|
||||
|
||||
{:ok, _block_undo, _} = SideEffects.handle(block_undo)
|
||||
refute User.blocks?(blocker, blocked)
|
||||
end
|
||||
|
||||
test "an announce undo removes the announce from the object", %{
|
||||
announce_undo: announce_undo,
|
||||
post: post
|
||||
} do
|
||||
{:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
|
||||
|
||||
object = Object.get_by_ap_id(post.data["object"])
|
||||
|
||||
assert object.data["announcement_count"] == 0
|
||||
assert object.data["announcements"] == []
|
||||
end
|
||||
|
||||
test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
|
||||
{:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
|
||||
refute Activity.get_by_id(announce.id)
|
||||
end
|
||||
|
||||
test "a reaction undo removes the reaction from the object", %{
|
||||
reaction_undo: reaction_undo,
|
||||
post: post
|
||||
} do
|
||||
{:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
|
||||
|
||||
object = Object.get_by_ap_id(post.data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 0
|
||||
assert object.data["reactions"] == []
|
||||
end
|
||||
|
||||
test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
|
||||
{:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
|
||||
refute Activity.get_by_id(reaction.id)
|
||||
end
|
||||
|
||||
test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
|
||||
{:ok, _like_undo, _} = SideEffects.handle(like_undo)
|
||||
|
||||
object = Object.get_by_ap_id(post.data["object"])
|
||||
|
||||
assert object.data["like_count"] == 0
|
||||
assert object.data["likes"] == []
|
||||
end
|
||||
|
||||
test "deletes the original like", %{like_undo: like_undo, like: like} do
|
||||
{:ok, _like_undo, _} = SideEffects.handle(like_undo)
|
||||
refute Activity.get_by_id(like.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "like objects" do
|
||||
setup do
|
||||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
|
||||
{:ok, like_data, _meta} = Builder.like(user, post.object)
|
||||
{:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
|
||||
|
||||
%{like: like, user: user, poster: poster}
|
||||
end
|
||||
|
||||
test "add the like to the original object", %{like: like, user: user} do
|
||||
{:ok, like, _} = SideEffects.handle(like)
|
||||
object = Object.get_by_ap_id(like.data["object"])
|
||||
assert object.data["like_count"] == 1
|
||||
assert user.ap_id in object.data["likes"]
|
||||
end
|
||||
|
||||
test "creates a notification", %{like: like, poster: poster} do
|
||||
{:ok, like, _} = SideEffects.handle(like)
|
||||
assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
|
||||
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)
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
{:ok, private_post} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
|
||||
|
||||
{:ok, announce_data, _meta} = Builder.announce(user, post.object, public: true)
|
||||
|
||||
{:ok, private_announce_data, _meta} =
|
||||
Builder.announce(user, private_post.object, public: false)
|
||||
|
||||
{:ok, relay_announce_data, _meta} =
|
||||
Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object, public: true)
|
||||
|
||||
{:ok, announce, _meta} = ActivityPub.persist(announce_data, local: true)
|
||||
{:ok, private_announce, _meta} = ActivityPub.persist(private_announce_data, local: true)
|
||||
{:ok, relay_announce, _meta} = ActivityPub.persist(relay_announce_data, local: true)
|
||||
|
||||
%{
|
||||
announce: announce,
|
||||
user: user,
|
||||
poster: poster,
|
||||
private_announce: private_announce,
|
||||
relay_announce: relay_announce
|
||||
}
|
||||
end
|
||||
|
||||
test "adds the announce to the original object", %{announce: announce, user: user} do
|
||||
{:ok, announce, _} = SideEffects.handle(announce)
|
||||
object = Object.get_by_ap_id(announce.data["object"])
|
||||
assert object.data["announcement_count"] == 1
|
||||
assert user.ap_id in object.data["announcements"]
|
||||
end
|
||||
|
||||
test "does not add the announce to the original object if the actor is a service actor", %{
|
||||
relay_announce: announce
|
||||
} do
|
||||
{:ok, announce, _} = SideEffects.handle(announce)
|
||||
object = Object.get_by_ap_id(announce.data["object"])
|
||||
assert object.data["announcement_count"] == nil
|
||||
end
|
||||
|
||||
test "creates a notification", %{announce: announce, poster: poster} do
|
||||
{:ok, announce, _} = SideEffects.handle(announce)
|
||||
assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id)
|
||||
end
|
||||
|
||||
test "it streams out the announce", %{announce: announce} do
|
||||
with_mocks([
|
||||
{
|
||||
Pleroma.Web.Streamer,
|
||||
[],
|
||||
[
|
||||
stream: fn _, _ -> nil end
|
||||
]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.Push,
|
||||
[],
|
||||
[
|
||||
send: fn _ -> nil end
|
||||
]
|
||||
}
|
||||
]) do
|
||||
{:ok, announce, _} = SideEffects.handle(announce)
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce)
|
||||
)
|
||||
|
||||
assert called(Pleroma.Web.Push.send(:_))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
# 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.AnnounceHandlingTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "it works for incoming honk announces" do
|
||||
user = insert(:user, ap_id: "https://honktest/u/test", local: false)
|
||||
other_user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"})
|
||||
|
||||
announce = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"actor" => "https://honktest/u/test",
|
||||
"id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx",
|
||||
"object" => post.data["object"],
|
||||
"published" => "2019-06-25T19:33:58Z",
|
||||
"to" => "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type" => "Announce"
|
||||
}
|
||||
|
||||
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(announce)
|
||||
|
||||
object = Object.get_by_ap_id(post.data["object"])
|
||||
|
||||
assert length(object.data["announcements"]) == 1
|
||||
assert user.ap_id in object.data["announcements"]
|
||||
end
|
||||
|
||||
test "it works for incoming announces with actor being inlined (kroeg)" do
|
||||
data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!()
|
||||
|
||||
_user = insert(:user, local: false, ap_id: data["actor"]["id"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, post} = CommonAPI.post(other_user, %{status: "kroegeroeg"})
|
||||
|
||||
data =
|
||||
data
|
||||
|> put_in(["object", "id"], post.data["object"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "https://puckipedia.com/"
|
||||
end
|
||||
|
||||
test "it works for incoming announces, fetching the announced object" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", "http://mastodon.example.org/users/admin/statuses/99541947525187367")
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get} ->
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/mastodon-note-object.json")}
|
||||
end)
|
||||
|
||||
_user = insert(:user, local: false, ap_id: data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Announce"
|
||||
|
||||
assert data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
|
||||
|
||||
assert data["object"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99541947525187367"
|
||||
|
||||
assert(Activity.get_create_by_object_ap_id(data["object"]))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming announces with an existing activity" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
_user = insert(:user, local: false, ap_id: data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Announce"
|
||||
|
||||
assert data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
|
||||
|
||||
assert data["object"] == activity.data["object"]
|
||||
|
||||
assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id
|
||||
end
|
||||
|
||||
# Ignore inlined activities for now
|
||||
@tag skip: true
|
||||
test "it works for incoming announces with an inlined activity" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce-private.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
_user =
|
||||
insert(:user,
|
||||
local: false,
|
||||
ap_id: data["actor"],
|
||||
follower_address: data["actor"] <> "/followers"
|
||||
)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Announce"
|
||||
|
||||
assert data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
|
||||
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368"
|
||||
assert object.data["content"] == "this is a private toot"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it rejects incoming announces with an inlined activity from another origin" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get} -> %Tesla.Env{status: 404, body: ""}
|
||||
end)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/bogus-mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
_user = insert(:user, local: false, ap_id: data["actor"])
|
||||
|
||||
assert {:error, e} = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it does not clobber the addressing on announce activities" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", Object.normalize(activity).data["id"])
|
||||
|> Map.put("to", ["http://mastodon.example.org/users/admin/followers"])
|
||||
|> Map.put("cc", [])
|
||||
|
||||
_user =
|
||||
insert(:user,
|
||||
local: false,
|
||||
ap_id: data["actor"],
|
||||
follower_address: "http://mastodon.example.org/users/admin/followers"
|
||||
)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["to"] == ["http://mastodon.example.org/users/admin/followers"]
|
||||
end
|
||||
end
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
# 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 doesn't work for deactivated 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(),
|
||||
deactivated: true
|
||||
)
|
||||
|
||||
_recipient = insert(:user, ap_id: List.first(data["to"]), local: true)
|
||||
|
||||
assert {:error, _} = 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
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
# 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.DeleteHandlingTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it works for incoming deletes" do
|
||||
activity = insert(:note_activity)
|
||||
deleting_user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", deleting_user.ap_id)
|
||||
|> put_in(["object", "id"], activity.data["object"])
|
||||
|
||||
{:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert id == data["id"]
|
||||
|
||||
# We delete the Create activity because we base our timelines on it.
|
||||
# This should be changed after we unify objects and activities
|
||||
refute Activity.get_by_id(activity.id)
|
||||
assert actor == deleting_user.ap_id
|
||||
|
||||
# Objects are replaced by a tombstone object.
|
||||
object = Object.normalize(activity.data["object"])
|
||||
assert object.data["type"] == "Tombstone"
|
||||
end
|
||||
|
||||
test "it works for incoming when the object has been pruned" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
{:ok, object} =
|
||||
Object.normalize(activity.data["object"])
|
||||
|> Repo.delete()
|
||||
|
||||
Cachex.del(:object_cache, "object:#{object.data["id"]}")
|
||||
|
||||
deleting_user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", deleting_user.ap_id)
|
||||
|> put_in(["object", "id"], activity.data["object"])
|
||||
|
||||
{:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert id == data["id"]
|
||||
|
||||
# We delete the Create activity because we base our timelines on it.
|
||||
# This should be changed after we unify objects and activities
|
||||
refute Activity.get_by_id(activity.id)
|
||||
assert actor == deleting_user.ap_id
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
activity = insert(:note_activity)
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", ap_id)
|
||||
|> put_in(["object", "id"], activity.data["object"])
|
||||
|
||||
assert match?({:error, _}, Transmogrifier.handle_incoming(data))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming user deletes" do
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
{:ok, _} = Transmogrifier.handle_incoming(data)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert User.get_cached_by_ap_id(ap_id).deactivated
|
||||
end
|
||||
|
||||
test "it fails for incoming user deletes with spoofed origin" do
|
||||
%{ap_id: ap_id} = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", ap_id)
|
||||
|
||||
assert match?({:error, _}, Transmogrifier.handle_incoming(data))
|
||||
|
||||
assert User.get_cached_by_ap_id(ap_id)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# 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.EmojiReactHandlingTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "it works for incoming emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == other_user.ap_id
|
||||
assert data["type"] == "EmojiReact"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
|
||||
assert data["object"] == activity.data["object"]
|
||||
assert data["content"] == "👌"
|
||||
|
||||
object = Object.get_by_ap_id(data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
assert match?([["👌", _]], object.data["reactions"])
|
||||
end
|
||||
|
||||
test "it reject invalid emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction-too-long.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|
||||
assert {:error, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction-no-emoji.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|
||||
assert {:error, _} = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
# 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.FollowHandlingTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
||||
import Pleroma.Factory
|
||||
import Ecto.Query
|
||||
import Mock
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "handle_incoming" do
|
||||
setup do: clear_config([:user, :deny_follow_blocked])
|
||||
|
||||
test "it works for osada follow request" do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/osada-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "https://apfed.club/channel/indio"
|
||||
assert data["type"] == "Follow"
|
||||
assert data["id"] == "https://apfed.club/follow/9"
|
||||
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
assert activity.data["state"] == "accept"
|
||||
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it works for incoming follow requests" do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Follow"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
|
||||
|
||||
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 create a Follow, but not an Accept" do
|
||||
user = insert(:user, locked: true)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["state"] == "pending"
|
||||
|
||||
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
|
||||
accepts =
|
||||
from(
|
||||
a in Activity,
|
||||
where: fragment("?->>'type' = ?", a.data, "Accept")
|
||||
)
|
||||
|> 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
|
||||
# This is important because the remote might have the wrong idea about the
|
||||
# current follow status. This can lead to instance A thinking that x@A is
|
||||
# followed by y@B, but B thinks they are not. In this case, the follow can
|
||||
# never go through again because it will never get an Accept.
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
accepts =
|
||||
from(
|
||||
a in Activity,
|
||||
where: fragment("?->>'type' = ?", a.data, "Accept")
|
||||
)
|
||||
|> Repo.all()
|
||||
|
||||
assert length(accepts) == 1
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("id", String.replace(data["id"], "2", "3"))
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
accepts =
|
||||
from(
|
||||
a in Activity,
|
||||
where: fragment("?->>'type' = ?", a.data, "Accept")
|
||||
)
|
||||
|> Repo.all()
|
||||
|
||||
assert length(accepts) == 2
|
||||
end
|
||||
|
||||
test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
|
||||
Pleroma.Config.put([:user, :deny_follow_blocked], true)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
|
||||
|
||||
{:ok, _user_relationship} = User.block(user, target)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
%Activity{} = activity = Activity.get_by_ap_id(id)
|
||||
|
||||
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)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/hubzilla-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|> Utils.normalize_params()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
|
||||
assert data["type"] == "Follow"
|
||||
assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
|
||||
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it works for incoming follows to locked account" do
|
||||
pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
||||
user = insert(:user, locked: true)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Follow"
|
||||
assert data["object"] == user.ap_id
|
||||
assert data["state"] == "pending"
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
assert [^pending_follower] = User.get_follow_requests(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
# 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.LikeHandlingTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "it works for incoming likes" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
_actor = insert(:user, ap_id: data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute Enum.empty?(activity.recipients)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Like"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
assert data["object"] == activity.data["object"]
|
||||
end
|
||||
|
||||
test "it works for incoming misskey likes, turning them into EmojiReacts" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/misskey-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
_actor = insert(:user, ap_id: data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert activity_data["actor"] == data["actor"]
|
||||
assert activity_data["type"] == "EmojiReact"
|
||||
assert activity_data["id"] == data["id"]
|
||||
assert activity_data["object"] == activity.data["object"]
|
||||
assert activity_data["content"] == "🍮"
|
||||
end
|
||||
|
||||
test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/misskey-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("_misskey_reaction", "⭐")
|
||||
|
||||
_actor = insert(:user, ap_id: data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert activity_data["actor"] == data["actor"]
|
||||
assert activity_data["type"] == "EmojiReact"
|
||||
assert activity_data["id"] == data["id"]
|
||||
assert activity_data["object"] == activity.data["object"]
|
||||
assert activity_data["content"] == "⭐"
|
||||
end
|
||||
end
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
# 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.UndoHandlingTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "it works for incoming emoji reaction undos" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
{:ok, reaction_activity} = CommonAPI.react_with_emoji(activity.id, user, "👌")
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", reaction_activity.data["id"])
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert activity.actor == user.ap_id
|
||||
assert activity.data["id"] == data["id"]
|
||||
assert activity.data["type"] == "Undo"
|
||||
end
|
||||
|
||||
test "it returns an error for incoming unlikes wihout a like activity" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
assert Transmogrifier.handle_incoming(data) == :error
|
||||
end
|
||||
|
||||
test "it works for incoming unlikes with an existing like activity" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
|
||||
|
||||
like_data =
|
||||
File.read!("test/fixtures/mastodon-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
_liker = insert(:user, ap_id: like_data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", like_data)
|
||||
|> Map.put("actor", like_data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Undo"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
|
||||
assert data["object"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
|
||||
note = Object.get_by_ap_id(like_data["object"])
|
||||
assert note.data["like_count"] == 0
|
||||
assert note.data["likes"] == []
|
||||
end
|
||||
|
||||
test "it works for incoming unlikes with an existing like activity and a compact object" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"})
|
||||
|
||||
like_data =
|
||||
File.read!("test/fixtures/mastodon-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
_liker = insert(:user, ap_id: like_data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", like_data["id"])
|
||||
|> Map.put("actor", like_data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert data["type"] == "Undo"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
|
||||
assert data["object"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
end
|
||||
|
||||
test "it works for incoming unannounces with an existing notice" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
|
||||
announce_data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
_announcer = insert(:user, ap_id: announce_data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: announce_data, local: false}} =
|
||||
Transmogrifier.handle_incoming(announce_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-announce.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", announce_data)
|
||||
|> Map.put("actor", announce_data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Undo"
|
||||
|
||||
assert data["object"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
|
||||
end
|
||||
|
||||
test "it works for incoming unfollows with an existing follow" do
|
||||
user = insert(:user)
|
||||
|
||||
follow_data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
_follower = insert(:user, ap_id: follow_data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-unfollow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", follow_data)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"]["type"] == "Follow"
|
||||
assert data["object"]["object"] == user.ap_id
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it works for incoming unblocks with an existing block" do
|
||||
user = insert(:user)
|
||||
|
||||
block_data =
|
||||
File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
_blocker = insert(:user, ap_id: block_data["actor"], local: false)
|
||||
|
||||
{:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-unblock-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", block_data)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"] == block_data["id"]
|
||||
|
||||
blocker = User.get_cached_by_ap_id(data["actor"])
|
||||
|
||||
refute User.blocks?(blocker, user)
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,548 +0,0 @@
|
|||
# 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.UtilsTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
describe "fetch the latest Follow" do
|
||||
test "fetches the latest Follow activity" do
|
||||
%Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
|
||||
follower = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
followed = User.get_cached_by_ap_id(activity.data["object"])
|
||||
|
||||
assert activity == Utils.fetch_latest_follow(follower, followed)
|
||||
end
|
||||
end
|
||||
|
||||
describe "determine_explicit_mentions()" do
|
||||
test "works with an object that has mentions" do
|
||||
object = %{
|
||||
"tag" => [
|
||||
%{
|
||||
"type" => "Mention",
|
||||
"href" => "https://example.com/~alyssa",
|
||||
"name" => "Alyssa P. Hacker"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
|
||||
end
|
||||
|
||||
test "works with an object that does not have mentions" do
|
||||
object = %{
|
||||
"tag" => [
|
||||
%{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
|
||||
]
|
||||
}
|
||||
|
||||
assert Utils.determine_explicit_mentions(object) == []
|
||||
end
|
||||
|
||||
test "works with an object that has mentions and other tags" do
|
||||
object = %{
|
||||
"tag" => [
|
||||
%{
|
||||
"type" => "Mention",
|
||||
"href" => "https://example.com/~alyssa",
|
||||
"name" => "Alyssa P. Hacker"
|
||||
},
|
||||
%{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
|
||||
]
|
||||
}
|
||||
|
||||
assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
|
||||
end
|
||||
|
||||
test "works with an object that has no tags" do
|
||||
object = %{}
|
||||
|
||||
assert Utils.determine_explicit_mentions(object) == []
|
||||
end
|
||||
|
||||
test "works with an object that has only IR tags" do
|
||||
object = %{"tag" => ["2hu"]}
|
||||
|
||||
assert Utils.determine_explicit_mentions(object) == []
|
||||
end
|
||||
|
||||
test "works with an object has tags as map" do
|
||||
object = %{
|
||||
"tag" => %{
|
||||
"type" => "Mention",
|
||||
"href" => "https://example.com/~alyssa",
|
||||
"name" => "Alyssa P. Hacker"
|
||||
}
|
||||
}
|
||||
|
||||
assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "make_like_data" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
[user: user, other_user: other_user, third_user: third_user]
|
||||
end
|
||||
|
||||
test "addresses actor's follower address if the activity is public", %{
|
||||
user: user,
|
||||
other_user: other_user,
|
||||
third_user: third_user
|
||||
} do
|
||||
expected_to = Enum.sort([user.ap_id, other_user.follower_address])
|
||||
expected_cc = Enum.sort(["https://www.w3.org/ns/activitystreams#Public", third_user.ap_id])
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status:
|
||||
"hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?"
|
||||
})
|
||||
|
||||
%{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
|
||||
assert Enum.sort(to) == expected_to
|
||||
assert Enum.sort(cc) == expected_cc
|
||||
end
|
||||
|
||||
test "does not adress actor's follower address if the activity is not public", %{
|
||||
user: user,
|
||||
other_user: other_user,
|
||||
third_user: third_user
|
||||
} do
|
||||
expected_to = Enum.sort([user.ap_id])
|
||||
expected_cc = [third_user.ap_id]
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
%{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
|
||||
assert Enum.sort(to) == expected_to
|
||||
assert Enum.sort(cc) == expected_cc
|
||||
end
|
||||
end
|
||||
|
||||
test "make_json_ld_header/0" do
|
||||
assert Utils.make_json_ld_header() == %{
|
||||
"@context" => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"http://localhost:4001/schemas/litepub-0.1.jsonld",
|
||||
%{
|
||||
"@language" => "und"
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
describe "get_existing_votes" do
|
||||
test "fetches existing votes" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "How do I pronounce LaTeX?",
|
||||
poll: %{
|
||||
options: ["laytekh", "lahtekh", "latex"],
|
||||
expires_in: 20,
|
||||
multiple: true
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
{:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
|
||||
assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
|
||||
end
|
||||
|
||||
test "fetches only Create activities" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "Are we living in a society?",
|
||||
poll: %{
|
||||
options: ["yes", "no"],
|
||||
expires_in: 20
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
{:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
|
||||
{:ok, _activity} = CommonAPI.favorite(user, activity.id)
|
||||
[fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
|
||||
assert fetched_vote.id == vote.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_follow_state_for_all/2" do
|
||||
test "updates the state of all Follow activities with the same actor and object" do
|
||||
user = insert(:user, locked: true)
|
||||
follower = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
|
||||
data =
|
||||
follow_activity_two.data
|
||||
|> Map.put("state", "accept")
|
||||
|
||||
cng = Ecto.Changeset.change(follow_activity_two, data: data)
|
||||
|
||||
{:ok, follow_activity_two} = Repo.update(cng)
|
||||
|
||||
{:ok, follow_activity_two} =
|
||||
Utils.update_follow_state_for_all(follow_activity_two, "accept")
|
||||
|
||||
assert refresh_record(follow_activity).data["state"] == "accept"
|
||||
assert refresh_record(follow_activity_two).data["state"] == "accept"
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_follow_state/2" do
|
||||
test "updates the state of the given follow activity" do
|
||||
user = insert(:user, locked: true)
|
||||
follower = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
|
||||
data =
|
||||
follow_activity_two.data
|
||||
|> Map.put("state", "accept")
|
||||
|
||||
cng = Ecto.Changeset.change(follow_activity_two, data: data)
|
||||
|
||||
{:ok, follow_activity_two} = Repo.update(cng)
|
||||
|
||||
{:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
|
||||
|
||||
assert refresh_record(follow_activity).data["state"] == "pending"
|
||||
assert refresh_record(follow_activity_two).data["state"] == "reject"
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_element_in_object/3" do
|
||||
test "updates likes" do
|
||||
user = insert(:user)
|
||||
activity = insert(:note_activity)
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert {:ok, updated_object} =
|
||||
Utils.update_element_in_object(
|
||||
"like",
|
||||
[user.ap_id],
|
||||
object
|
||||
)
|
||||
|
||||
assert updated_object.data["likes"] == [user.ap_id]
|
||||
assert updated_object.data["like_count"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "add_like_to_object/2" do
|
||||
test "add actor to likes" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
object = insert(:note)
|
||||
|
||||
assert {:ok, updated_object} =
|
||||
Utils.add_like_to_object(
|
||||
%Activity{data: %{"actor" => user.ap_id}},
|
||||
object
|
||||
)
|
||||
|
||||
assert updated_object.data["likes"] == [user.ap_id]
|
||||
assert updated_object.data["like_count"] == 1
|
||||
|
||||
assert {:ok, updated_object2} =
|
||||
Utils.add_like_to_object(
|
||||
%Activity{data: %{"actor" => user2.ap_id}},
|
||||
updated_object
|
||||
)
|
||||
|
||||
assert updated_object2.data["likes"] == [user2.ap_id, user.ap_id]
|
||||
assert updated_object2.data["like_count"] == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "remove_like_from_object/2" do
|
||||
test "removes ap_id from likes" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
object = insert(:note, data: %{"likes" => [user.ap_id, user2.ap_id], "like_count" => 2})
|
||||
|
||||
assert {:ok, updated_object} =
|
||||
Utils.remove_like_from_object(
|
||||
%Activity{data: %{"actor" => user.ap_id}},
|
||||
object
|
||||
)
|
||||
|
||||
assert updated_object.data["likes"] == [user2.ap_id]
|
||||
assert updated_object.data["like_count"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_existing_like/2" do
|
||||
test "fetches existing like" do
|
||||
note_activity = insert(:note_activity)
|
||||
assert object = Object.normalize(note_activity)
|
||||
|
||||
user = insert(:user)
|
||||
refute Utils.get_existing_like(user.ap_id, object)
|
||||
{:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
|
||||
|
||||
assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_get_existing_announce/2" do
|
||||
test "returns nil if announce not found" do
|
||||
actor = insert(:user)
|
||||
refute Utils.get_existing_announce(actor.ap_id, %{data: %{"id" => "test"}})
|
||||
end
|
||||
|
||||
test "fetches existing announce" do
|
||||
note_activity = insert(:note_activity)
|
||||
assert object = Object.normalize(note_activity)
|
||||
actor = insert(:user)
|
||||
|
||||
{:ok, announce} = CommonAPI.repeat(note_activity.id, actor)
|
||||
assert Utils.get_existing_announce(actor.ap_id, object) == announce
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_latest_block/2" do
|
||||
test "fetches last block activities" do
|
||||
user1 = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
|
||||
assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
|
||||
assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
|
||||
|
||||
assert Utils.fetch_latest_block(user1, user2) == activity
|
||||
end
|
||||
end
|
||||
|
||||
describe "recipient_in_message/3" do
|
||||
test "returns true when recipient in `to`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"to" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"to" => [recipient.ap_id], "cc" => ""}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when recipient in `cc`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"cc" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"cc" => [recipient.ap_id], "to" => ""}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when recipient in `bto`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"bto" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"bcc" => "", "bto" => [recipient.ap_id]}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when recipient in `bcc`" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"bcc" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"bto" => "", "bcc" => [recipient.ap_id]}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns true when message without addresses fields" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
assert Utils.recipient_in_message(recipient, actor, %{"bccc" => recipient.ap_id})
|
||||
|
||||
assert Utils.recipient_in_message(
|
||||
recipient,
|
||||
actor,
|
||||
%{"btod" => "", "bccc" => [recipient.ap_id]}
|
||||
)
|
||||
end
|
||||
|
||||
test "returns false" do
|
||||
recipient = insert(:user)
|
||||
actor = insert(:user)
|
||||
refute Utils.recipient_in_message(recipient, actor, %{"to" => "ap_id"})
|
||||
end
|
||||
end
|
||||
|
||||
describe "lazy_put_activity_defaults/2" do
|
||||
test "returns map with id and published data" do
|
||||
note_activity = insert(:note_activity)
|
||||
object = Object.normalize(note_activity)
|
||||
res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]})
|
||||
assert res["context"] == object.data["id"]
|
||||
assert res["context_id"] == object.id
|
||||
assert res["id"]
|
||||
assert res["published"]
|
||||
end
|
||||
|
||||
test "returns map with fake id and published data" do
|
||||
assert %{
|
||||
"context" => "pleroma:fakecontext",
|
||||
"context_id" => -1,
|
||||
"id" => "pleroma:fakeid",
|
||||
"published" => _
|
||||
} = Utils.lazy_put_activity_defaults(%{}, true)
|
||||
end
|
||||
|
||||
test "returns activity data with object" do
|
||||
note_activity = insert(:note_activity)
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
res =
|
||||
Utils.lazy_put_activity_defaults(%{
|
||||
"context" => object.data["id"],
|
||||
"object" => %{}
|
||||
})
|
||||
|
||||
assert res["context"] == object.data["id"]
|
||||
assert res["context_id"] == object.id
|
||||
assert res["id"]
|
||||
assert res["published"]
|
||||
assert res["object"]["id"]
|
||||
assert res["object"]["published"]
|
||||
assert res["object"]["context"] == object.data["id"]
|
||||
assert res["object"]["context_id"] == object.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "make_flag_data" do
|
||||
test "returns empty map when params is invalid" do
|
||||
assert Utils.make_flag_data(%{}, %{}) == %{}
|
||||
end
|
||||
|
||||
test "returns map with Flag object" do
|
||||
reporter = insert(:user)
|
||||
target_account = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"})
|
||||
context = Utils.generate_context_id()
|
||||
content = "foobar"
|
||||
|
||||
target_ap_id = target_account.ap_id
|
||||
activity_ap_id = activity.data["id"]
|
||||
|
||||
res =
|
||||
Utils.make_flag_data(
|
||||
%{
|
||||
actor: reporter,
|
||||
context: context,
|
||||
account: target_account,
|
||||
statuses: [%{"id" => activity.data["id"]}],
|
||||
content: content
|
||||
},
|
||||
%{}
|
||||
)
|
||||
|
||||
note_obj = %{
|
||||
"type" => "Note",
|
||||
"id" => activity_ap_id,
|
||||
"content" => content,
|
||||
"published" => activity.object.data["published"],
|
||||
"actor" =>
|
||||
AccountView.render("show.json", %{user: target_account, skip_visibility_check: true})
|
||||
}
|
||||
|
||||
assert %{
|
||||
"type" => "Flag",
|
||||
"content" => ^content,
|
||||
"context" => ^context,
|
||||
"object" => [^target_ap_id, ^note_obj],
|
||||
"state" => "open"
|
||||
} = res
|
||||
end
|
||||
end
|
||||
|
||||
describe "add_announce_to_object/2" do
|
||||
test "adds actor to announcement" do
|
||||
user = insert(:user)
|
||||
object = insert(:note)
|
||||
|
||||
activity =
|
||||
insert(:note_activity,
|
||||
data: %{
|
||||
"actor" => user.ap_id,
|
||||
"cc" => [Pleroma.Constants.as_public()]
|
||||
}
|
||||
)
|
||||
|
||||
assert {:ok, updated_object} = Utils.add_announce_to_object(activity, object)
|
||||
assert updated_object.data["announcements"] == [user.ap_id]
|
||||
assert updated_object.data["announcement_count"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "remove_announce_from_object/2" do
|
||||
test "removes actor from announcements" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
object =
|
||||
insert(:note,
|
||||
data: %{"announcements" => [user.ap_id, user2.ap_id], "announcement_count" => 2}
|
||||
)
|
||||
|
||||
activity = insert(:note_activity, data: %{"actor" => user.ap_id})
|
||||
|
||||
assert {:ok, updated_object} = Utils.remove_announce_from_object(activity, object)
|
||||
assert updated_object.data["announcements"] == [user2.ap_id]
|
||||
assert updated_object.data["announcement_count"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_cached_emoji_reactions/1" do
|
||||
test "returns the data or an emtpy list" do
|
||||
object = insert(:note)
|
||||
assert Utils.get_cached_emoji_reactions(object) == []
|
||||
|
||||
object = insert(:note, data: %{"reactions" => [["x", ["lain"]]]})
|
||||
assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"]]]
|
||||
|
||||
object = insert(:note, data: %{"reactions" => %{}})
|
||||
assert Utils.get_cached_emoji_reactions(object) == []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
# 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.ObjectViewTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "renders a note object" do
|
||||
note = insert(:note)
|
||||
|
||||
result = ObjectView.render("object.json", %{object: note})
|
||||
|
||||
assert result["id"] == note.data["id"]
|
||||
assert result["to"] == note.data["to"]
|
||||
assert result["content"] == note.data["content"]
|
||||
assert result["type"] == "Note"
|
||||
assert result["@context"]
|
||||
end
|
||||
|
||||
test "renders a note activity" do
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
|
||||
result = ObjectView.render("object.json", %{object: note})
|
||||
|
||||
assert result["id"] == note.data["id"]
|
||||
assert result["to"] == note.data["to"]
|
||||
assert result["object"]["type"] == "Note"
|
||||
assert result["object"]["content"] == object.data["content"]
|
||||
assert result["type"] == "Create"
|
||||
assert result["@context"]
|
||||
end
|
||||
|
||||
describe "note activity's `replies` collection rendering" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
|
||||
|
||||
test "renders `replies` collection for a note activity" do
|
||||
user = insert(:user)
|
||||
activity = insert(:note_activity, user: user)
|
||||
|
||||
{:ok, self_reply1} =
|
||||
CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: activity.id})
|
||||
|
||||
replies_uris = [self_reply1.object.data["id"]]
|
||||
result = ObjectView.render("object.json", %{object: refresh_record(activity)})
|
||||
|
||||
assert %{"type" => "Collection", "items" => ^replies_uris} =
|
||||
get_in(result, ["object", "replies"])
|
||||
end
|
||||
end
|
||||
|
||||
test "renders a like activity" do
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, like_activity} = CommonAPI.favorite(user, note.id)
|
||||
|
||||
result = ObjectView.render("object.json", %{object: like_activity})
|
||||
|
||||
assert result["id"] == like_activity.data["id"]
|
||||
assert result["object"] == object.data["id"]
|
||||
assert result["type"] == "Like"
|
||||
end
|
||||
|
||||
test "renders an announce activity" do
|
||||
note = insert(:note_activity)
|
||||
object = Object.normalize(note)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, announce_activity} = CommonAPI.repeat(note.id, user)
|
||||
|
||||
result = ObjectView.render("object.json", %{object: announce_activity})
|
||||
|
||||
assert result["id"] == announce_activity.data["id"]
|
||||
assert result["object"] == object.data["id"]
|
||||
assert result["type"] == "Announce"
|
||||
end
|
||||
end
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
# 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.UserViewTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.UserView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "Renders a user, including the public key" do
|
||||
user = insert(:user)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
assert result["id"] == user.ap_id
|
||||
assert result["preferredUsername"] == user.nickname
|
||||
|
||||
assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN PUBLIC KEY")
|
||||
end
|
||||
|
||||
test "Renders profile fields" do
|
||||
fields = [
|
||||
%{"name" => "foo", "value" => "bar"}
|
||||
]
|
||||
|
||||
{:ok, user} =
|
||||
insert(:user)
|
||||
|> User.update_changeset(%{fields: fields})
|
||||
|> User.update_and_set_cache()
|
||||
|
||||
assert %{
|
||||
"attachment" => [%{"name" => "foo", "type" => "PropertyValue", "value" => "bar"}]
|
||||
} = UserView.render("user.json", %{user: user})
|
||||
end
|
||||
|
||||
test "Renders with emoji tags" do
|
||||
user = insert(:user, emoji: %{"bib" => "/test"})
|
||||
|
||||
assert %{
|
||||
"tag" => [
|
||||
%{
|
||||
"icon" => %{"type" => "Image", "url" => "/test"},
|
||||
"id" => "/test",
|
||||
"name" => ":bib:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
} = UserView.render("user.json", %{user: user})
|
||||
end
|
||||
|
||||
test "Does not add an avatar image if the user hasn't set one" do
|
||||
user = insert(:user)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
refute result["icon"]
|
||||
refute result["image"]
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
avatar: %{"url" => [%{"href" => "https://someurl"}]},
|
||||
banner: %{"url" => [%{"href" => "https://somebanner"}]}
|
||||
)
|
||||
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
assert result["icon"]["url"] == "https://someurl"
|
||||
assert result["image"]["url"] == "https://somebanner"
|
||||
end
|
||||
|
||||
test "renders an invisible user with the invisible property set to true" do
|
||||
user = insert(:user, invisible: true)
|
||||
|
||||
assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
|
||||
end
|
||||
|
||||
describe "endpoints" do
|
||||
test "local users have a usable endpoints structure" do
|
||||
user = insert(:user)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
assert result["id"] == user.ap_id
|
||||
|
||||
%{
|
||||
"sharedInbox" => _,
|
||||
"oauthAuthorizationEndpoint" => _,
|
||||
"oauthRegistrationEndpoint" => _,
|
||||
"oauthTokenEndpoint" => _
|
||||
} = result["endpoints"]
|
||||
end
|
||||
|
||||
test "remote users have an empty endpoints structure" do
|
||||
user = insert(:user, local: false)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
assert result["id"] == user.ap_id
|
||||
assert result["endpoints"] == %{}
|
||||
end
|
||||
|
||||
test "instance users do not expose oAuth endpoints" do
|
||||
user = insert(:user, nickname: nil, local: true)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
refute result["endpoints"]["oauthAuthorizationEndpoint"]
|
||||
refute result["endpoints"]["oauthRegistrationEndpoint"]
|
||||
refute result["endpoints"]["oauthTokenEndpoint"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "followers" do
|
||||
test "sets totalItems to zero when followers are hidden" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_followers_count: true, hide_followers: true})
|
||||
refute UserView.render("followers.json", %{user: user}) |> Map.has_key?("totalItems")
|
||||
end
|
||||
|
||||
test "sets correct totalItems when followers are hidden but the follower counter is not" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_followers_count: false, hide_followers: true})
|
||||
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
|
||||
end
|
||||
end
|
||||
|
||||
describe "following" do
|
||||
test "sets totalItems to zero when follows are hidden" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_follows_count: true, hide_follows: true})
|
||||
assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user})
|
||||
end
|
||||
|
||||
test "sets correct totalItems when follows are hidden but the follow counter is not" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_follows_count: false, hide_follows: true})
|
||||
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
|
||||
end
|
||||
end
|
||||
|
||||
describe "acceptsChatMessages" do
|
||||
test "it returns this value if it is set" do
|
||||
true_user = insert(:user, accepts_chat_messages: true)
|
||||
false_user = insert(:user, accepts_chat_messages: false)
|
||||
nil_user = insert(:user, accepts_chat_messages: nil)
|
||||
|
||||
assert %{"capabilities" => %{"acceptsChatMessages" => true}} =
|
||||
UserView.render("user.json", user: true_user)
|
||||
|
||||
assert %{"capabilities" => %{"acceptsChatMessages" => false}} =
|
||||
UserView.render("user.json", user: false_user)
|
||||
|
||||
refute Map.has_key?(
|
||||
UserView.render("user.json", user: nil_user)["capabilities"],
|
||||
"acceptsChatMessages"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
# 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.VisibilityTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.CommonAPI
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
mentioned = insert(:user)
|
||||
following = insert(:user)
|
||||
unrelated = insert(:user)
|
||||
{:ok, following} = Pleroma.User.follow(following, user)
|
||||
{:ok, list} = Pleroma.List.create("foo", user)
|
||||
|
||||
Pleroma.List.follow(list, unrelated)
|
||||
|
||||
{:ok, public} =
|
||||
CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "public"})
|
||||
|
||||
{:ok, private} =
|
||||
CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "private"})
|
||||
|
||||
{:ok, direct} =
|
||||
CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, unlisted} =
|
||||
CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "unlisted"})
|
||||
|
||||
{:ok, list} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "@#{mentioned.nickname}",
|
||||
visibility: "list:#{list.id}"
|
||||
})
|
||||
|
||||
%{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
user: user,
|
||||
mentioned: mentioned,
|
||||
following: following,
|
||||
unrelated: unrelated,
|
||||
list: list
|
||||
}
|
||||
end
|
||||
|
||||
test "is_direct?", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
list: list
|
||||
} do
|
||||
assert Visibility.is_direct?(direct)
|
||||
refute Visibility.is_direct?(public)
|
||||
refute Visibility.is_direct?(private)
|
||||
refute Visibility.is_direct?(unlisted)
|
||||
assert Visibility.is_direct?(list)
|
||||
end
|
||||
|
||||
test "is_public?", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
list: list
|
||||
} do
|
||||
refute Visibility.is_public?(direct)
|
||||
assert Visibility.is_public?(public)
|
||||
refute Visibility.is_public?(private)
|
||||
assert Visibility.is_public?(unlisted)
|
||||
refute Visibility.is_public?(list)
|
||||
end
|
||||
|
||||
test "is_private?", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
list: list
|
||||
} do
|
||||
refute Visibility.is_private?(direct)
|
||||
refute Visibility.is_private?(public)
|
||||
assert Visibility.is_private?(private)
|
||||
refute Visibility.is_private?(unlisted)
|
||||
refute Visibility.is_private?(list)
|
||||
end
|
||||
|
||||
test "is_list?", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
list: list
|
||||
} do
|
||||
refute Visibility.is_list?(direct)
|
||||
refute Visibility.is_list?(public)
|
||||
refute Visibility.is_list?(private)
|
||||
refute Visibility.is_list?(unlisted)
|
||||
assert Visibility.is_list?(list)
|
||||
end
|
||||
|
||||
test "visible_for_user?", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
user: user,
|
||||
mentioned: mentioned,
|
||||
following: following,
|
||||
unrelated: unrelated,
|
||||
list: list
|
||||
} do
|
||||
# All visible to author
|
||||
|
||||
assert Visibility.visible_for_user?(public, user)
|
||||
assert Visibility.visible_for_user?(private, user)
|
||||
assert Visibility.visible_for_user?(unlisted, user)
|
||||
assert Visibility.visible_for_user?(direct, user)
|
||||
assert Visibility.visible_for_user?(list, user)
|
||||
|
||||
# All visible to a mentioned user
|
||||
|
||||
assert Visibility.visible_for_user?(public, mentioned)
|
||||
assert Visibility.visible_for_user?(private, mentioned)
|
||||
assert Visibility.visible_for_user?(unlisted, mentioned)
|
||||
assert Visibility.visible_for_user?(direct, mentioned)
|
||||
assert Visibility.visible_for_user?(list, mentioned)
|
||||
|
||||
# DM not visible for just follower
|
||||
|
||||
assert Visibility.visible_for_user?(public, following)
|
||||
assert Visibility.visible_for_user?(private, following)
|
||||
assert Visibility.visible_for_user?(unlisted, following)
|
||||
refute Visibility.visible_for_user?(direct, following)
|
||||
refute Visibility.visible_for_user?(list, following)
|
||||
|
||||
# Public and unlisted visible for unrelated user
|
||||
|
||||
assert Visibility.visible_for_user?(public, unrelated)
|
||||
assert Visibility.visible_for_user?(unlisted, unrelated)
|
||||
refute Visibility.visible_for_user?(private, unrelated)
|
||||
refute Visibility.visible_for_user?(direct, unrelated)
|
||||
|
||||
# Visible for a list member
|
||||
assert Visibility.visible_for_user?(list, unrelated)
|
||||
end
|
||||
|
||||
test "doesn't die when the user doesn't exist",
|
||||
%{
|
||||
direct: direct,
|
||||
user: user
|
||||
} do
|
||||
Repo.delete(user)
|
||||
Cachex.clear(:user_cache)
|
||||
refute Visibility.is_private?(direct)
|
||||
end
|
||||
|
||||
test "get_visibility", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
list: list
|
||||
} do
|
||||
assert Visibility.get_visibility(public) == "public"
|
||||
assert Visibility.get_visibility(private) == "private"
|
||||
assert Visibility.get_visibility(direct) == "direct"
|
||||
assert Visibility.get_visibility(unlisted) == "unlisted"
|
||||
assert Visibility.get_visibility(list) == "list"
|
||||
end
|
||||
|
||||
test "get_visibility with directMessage flag" do
|
||||
assert Visibility.get_visibility(%{data: %{"directMessage" => true}}) == "direct"
|
||||
end
|
||||
|
||||
test "get_visibility with listMessage flag" do
|
||||
assert Visibility.get_visibility(%{data: %{"listMessage" => ""}}) == "list"
|
||||
end
|
||||
|
||||
describe "entire_thread_visible_for_user?/2" do
|
||||
test "returns false if not found activity", %{user: user} do
|
||||
refute Visibility.entire_thread_visible_for_user?(%Activity{}, user)
|
||||
end
|
||||
|
||||
test "returns true if activity hasn't 'Create' type", %{user: user} do
|
||||
activity = insert(:like_activity)
|
||||
assert Visibility.entire_thread_visible_for_user?(activity, user)
|
||||
end
|
||||
|
||||
test "returns false when invalid recipients", %{user: user} do
|
||||
author = insert(:user)
|
||||
|
||||
activity =
|
||||
insert(:note_activity,
|
||||
note:
|
||||
insert(:note,
|
||||
user: author,
|
||||
data: %{"to" => ["test-user"]}
|
||||
)
|
||||
)
|
||||
|
||||
refute Visibility.entire_thread_visible_for_user?(activity, user)
|
||||
end
|
||||
|
||||
test "returns true if user following to author" do
|
||||
author = insert(:user)
|
||||
user = insert(:user)
|
||||
Pleroma.User.follow(user, author)
|
||||
|
||||
activity =
|
||||
insert(:note_activity,
|
||||
note:
|
||||
insert(:note,
|
||||
user: author,
|
||||
data: %{"to" => [user.ap_id]}
|
||||
)
|
||||
)
|
||||
|
||||
assert Visibility.entire_thread_visible_for_user?(activity, user)
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,281 +0,0 @@
|
|||
# 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.InviteControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.UserInviteToken
|
||||
|
||||
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 "POST /api/pleroma/admin/users/email_invite, with valid config" do
|
||||
setup do: clear_config([:instance, :registrations_open], false)
|
||||
setup do: clear_config([:instance, :invites_enabled], true)
|
||||
|
||||
test "sends invitation and returns 204", %{admin: admin, conn: conn} do
|
||||
recipient_email = "foo@bar.com"
|
||||
recipient_name = "J. D."
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json;charset=utf-8")
|
||||
|> post("/api/pleroma/admin/users/email_invite", %{
|
||||
email: recipient_email,
|
||||
name: recipient_name
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(conn, :no_content)
|
||||
|
||||
token_record = List.last(Repo.all(Pleroma.UserInviteToken))
|
||||
assert token_record
|
||||
refute token_record.used
|
||||
|
||||
notify_email = Config.get([:instance, :notify_email])
|
||||
instance_name = Config.get([:instance, :name])
|
||||
|
||||
email =
|
||||
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||
admin,
|
||||
token_record,
|
||||
recipient_email,
|
||||
recipient_name
|
||||
)
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {recipient_name, recipient_email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
test "it returns 403 if requested by a non-admin" do
|
||||
non_admin_user = insert(:user)
|
||||
token = insert(:oauth_token, user: non_admin_user)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, non_admin_user)
|
||||
|> assign(:token, token)
|
||||
|> put_req_header("content-type", "application/json;charset=utf-8")
|
||||
|> post("/api/pleroma/admin/users/email_invite", %{
|
||||
email: "foo@bar.com",
|
||||
name: "JD"
|
||||
})
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "email with +", %{conn: conn, admin: admin} do
|
||||
recipient_email = "foo+bar@baz.com"
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json;charset=utf-8")
|
||||
|> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email})
|
||||
|> json_response_and_validate_schema(:no_content)
|
||||
|
||||
token_record =
|
||||
Pleroma.UserInviteToken
|
||||
|> Repo.all()
|
||||
|> List.last()
|
||||
|
||||
assert token_record
|
||||
refute token_record.used
|
||||
|
||||
notify_email = Config.get([:instance, :notify_email])
|
||||
instance_name = Config.get([:instance, :name])
|
||||
|
||||
email =
|
||||
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||
admin,
|
||||
token_record,
|
||||
recipient_email
|
||||
)
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: recipient_email,
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
|
||||
setup do: clear_config([:instance, :registrations_open])
|
||||
setup do: clear_config([:instance, :invites_enabled])
|
||||
|
||||
test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do
|
||||
Config.put([:instance, :registrations_open], false)
|
||||
Config.put([:instance, :invites_enabled], false)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/email_invite", %{
|
||||
email: "foo@bar.com",
|
||||
name: "JD"
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(conn, :bad_request) ==
|
||||
%{
|
||||
"error" =>
|
||||
"To send invites you need to set the `invites_enabled` option to true."
|
||||
}
|
||||
end
|
||||
|
||||
test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do
|
||||
Config.put([:instance, :registrations_open], true)
|
||||
Config.put([:instance, :invites_enabled], true)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/email_invite", %{
|
||||
email: "foo@bar.com",
|
||||
name: "JD"
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(conn, :bad_request) ==
|
||||
%{
|
||||
"error" =>
|
||||
"To send invites you need to set the `registrations_open` option to false."
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/users/invite_token" do
|
||||
test "without options", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/invite_token")
|
||||
|
||||
invite_json = json_response_and_validate_schema(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(invite_json["token"])
|
||||
refute invite.used
|
||||
refute invite.expires_at
|
||||
refute invite.max_use
|
||||
assert invite.invite_type == "one_time"
|
||||
end
|
||||
|
||||
test "with expires_at", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/invite_token", %{
|
||||
"expires_at" => Date.to_string(Date.utc_today())
|
||||
})
|
||||
|
||||
invite_json = json_response_and_validate_schema(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(invite_json["token"])
|
||||
|
||||
refute invite.used
|
||||
assert invite.expires_at == Date.utc_today()
|
||||
refute invite.max_use
|
||||
assert invite.invite_type == "date_limited"
|
||||
end
|
||||
|
||||
test "with max_use", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
|
||||
|
||||
invite_json = json_response_and_validate_schema(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(invite_json["token"])
|
||||
refute invite.used
|
||||
refute invite.expires_at
|
||||
assert invite.max_use == 150
|
||||
assert invite.invite_type == "reusable"
|
||||
end
|
||||
|
||||
test "with max use and expires_at", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/invite_token", %{
|
||||
"max_use" => 150,
|
||||
"expires_at" => Date.to_string(Date.utc_today())
|
||||
})
|
||||
|
||||
invite_json = json_response_and_validate_schema(conn, 200)
|
||||
invite = UserInviteToken.find_by_token!(invite_json["token"])
|
||||
refute invite.used
|
||||
assert invite.expires_at == Date.utc_today()
|
||||
assert invite.max_use == 150
|
||||
assert invite.invite_type == "reusable_date_limited"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/users/invites" do
|
||||
test "no invites", %{conn: conn} do
|
||||
conn = get(conn, "/api/pleroma/admin/users/invites")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) == %{"invites" => []}
|
||||
end
|
||||
|
||||
test "with invite", %{conn: conn} do
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users/invites")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) == %{
|
||||
"invites" => [
|
||||
%{
|
||||
"expires_at" => nil,
|
||||
"id" => invite.id,
|
||||
"invite_type" => "one_time",
|
||||
"max_use" => nil,
|
||||
"token" => invite.token,
|
||||
"used" => false,
|
||||
"uses" => 0
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/users/revoke_invite" do
|
||||
test "with token", %{conn: conn} do
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) == %{
|
||||
"expires_at" => nil,
|
||||
"id" => invite.id,
|
||||
"invite_type" => "one_time",
|
||||
"max_use" => nil,
|
||||
"token" => invite.token,
|
||||
"used" => true,
|
||||
"uses" => 0
|
||||
}
|
||||
end
|
||||
|
||||
test "with invalid token", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
|
||||
|
||||
assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
# 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.MediaProxyCacheControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
setup do: clear_config([:media_proxy])
|
||||
|
||||
setup do
|
||||
on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
|
||||
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)
|
||||
|
||||
Config.put([:media_proxy, :enabled], true)
|
||||
Config.put([:media_proxy, :invalidation, :enabled], true)
|
||||
Config.put([:media_proxy, :invalidation, :provider], MediaProxy.Invalidation.Script)
|
||||
|
||||
{:ok, %{admin: admin, token: token, conn: conn}}
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/media_proxy_caches" do
|
||||
test "shows banned MediaProxy URLs", %{conn: conn} do
|
||||
MediaProxy.put_in_banned_urls([
|
||||
"http://localhost:4001/media/a688346.jpg",
|
||||
"http://localhost:4001/media/fb1f4d.jpg"
|
||||
])
|
||||
|
||||
MediaProxy.put_in_banned_urls("http://localhost:4001/media/gb1f44.jpg")
|
||||
MediaProxy.put_in_banned_urls("http://localhost:4001/media/tb13f47.jpg")
|
||||
MediaProxy.put_in_banned_urls("http://localhost:4001/media/wb1f46.jpg")
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/media_proxy_caches?page_size=2")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["page_size"] == 2
|
||||
assert response["count"] == 5
|
||||
|
||||
assert response["urls"] == [
|
||||
"http://localhost:4001/media/fb1f4d.jpg",
|
||||
"http://localhost:4001/media/a688346.jpg"
|
||||
]
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=2")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["urls"] == [
|
||||
"http://localhost:4001/media/gb1f44.jpg",
|
||||
"http://localhost:4001/media/tb13f47.jpg"
|
||||
]
|
||||
|
||||
assert response["page_size"] == 2
|
||||
assert response["count"] == 5
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=3")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["urls"] == ["http://localhost:4001/media/wb1f46.jpg"]
|
||||
end
|
||||
|
||||
test "search banned MediaProxy URLs", %{conn: conn} do
|
||||
MediaProxy.put_in_banned_urls([
|
||||
"http://localhost:4001/media/a688346.jpg",
|
||||
"http://localhost:4001/media/ff44b1f4d.jpg"
|
||||
])
|
||||
|
||||
MediaProxy.put_in_banned_urls("http://localhost:4001/media/gb1f44.jpg")
|
||||
MediaProxy.put_in_banned_urls("http://localhost:4001/media/tb13f47.jpg")
|
||||
MediaProxy.put_in_banned_urls("http://localhost:4001/media/wb1f46.jpg")
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/media_proxy_caches?page_size=2&query=F44")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["urls"] == [
|
||||
"http://localhost:4001/media/gb1f44.jpg",
|
||||
"http://localhost:4001/media/ff44b1f4d.jpg"
|
||||
]
|
||||
|
||||
assert response["page_size"] == 2
|
||||
assert response["count"] == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/media_proxy_caches/delete" do
|
||||
test "deleted MediaProxy URLs from banned", %{conn: conn} do
|
||||
MediaProxy.put_in_banned_urls([
|
||||
"http://localhost:4001/media/a688346.jpg",
|
||||
"http://localhost:4001/media/fb1f4d.jpg"
|
||||
])
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/media_proxy_caches/delete", %{
|
||||
urls: ["http://localhost:4001/media/a688346.jpg"]
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute MediaProxy.in_banned_urls("http://localhost:4001/media/a688346.jpg")
|
||||
assert MediaProxy.in_banned_urls("http://localhost:4001/media/fb1f4d.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/media_proxy_caches/purge" do
|
||||
test "perform invalidates cache of MediaProxy", %{conn: conn} do
|
||||
urls = [
|
||||
"http://example.com/media/a688346.jpg",
|
||||
"http://example.com/media/fb1f4d.jpg"
|
||||
]
|
||||
|
||||
with_mocks [
|
||||
{MediaProxy.Invalidation.Script, [],
|
||||
[
|
||||
purge: fn _, _ -> {"ok", 0} end
|
||||
]}
|
||||
] do
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: false})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg")
|
||||
refute MediaProxy.in_banned_urls("http://example.com/media/fb1f4d.jpg")
|
||||
end
|
||||
end
|
||||
|
||||
test "perform invalidates cache of MediaProxy and adds url to banned", %{conn: conn} do
|
||||
urls = [
|
||||
"http://example.com/media/a688346.jpg",
|
||||
"http://example.com/media/fb1f4d.jpg"
|
||||
]
|
||||
|
||||
with_mocks [{MediaProxy.Invalidation.Script, [], [purge: fn _, _ -> {"ok", 0} end]}] do
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post(
|
||||
"/api/pleroma/admin/media_proxy_caches/purge",
|
||||
%{urls: urls, ban: true}
|
||||
)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg")
|
||||
assert MediaProxy.in_banned_urls("http://example.com/media/fb1f4d.jpg")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
# 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.OAuthAppControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web
|
||||
|
||||
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 "POST /api/pleroma/admin/oauth_app" do
|
||||
test "errors", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/oauth_app", %{})
|
||||
|> json_response_and_validate_schema(400)
|
||||
|
||||
assert %{
|
||||
"error" => "Missing field: name. Missing field: redirect_uris."
|
||||
} = response
|
||||
end
|
||||
|
||||
test "success", %{conn: conn} do
|
||||
base_url = Web.base_url()
|
||||
app_name = "Trusted app"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/oauth_app", %{
|
||||
name: app_name,
|
||||
redirect_uris: base_url
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"client_id" => _,
|
||||
"client_secret" => _,
|
||||
"name" => ^app_name,
|
||||
"redirect_uri" => ^base_url,
|
||||
"trusted" => false
|
||||
} = response
|
||||
end
|
||||
|
||||
test "with trusted", %{conn: conn} do
|
||||
base_url = Web.base_url()
|
||||
app_name = "Trusted app"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/oauth_app", %{
|
||||
name: app_name,
|
||||
redirect_uris: base_url,
|
||||
trusted: true
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"client_id" => _,
|
||||
"client_secret" => _,
|
||||
"name" => ^app_name,
|
||||
"redirect_uri" => ^base_url,
|
||||
"trusted" => true
|
||||
} = response
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/oauth_app" do
|
||||
setup do
|
||||
app = insert(:oauth_app)
|
||||
{:ok, app: app}
|
||||
end
|
||||
|
||||
test "list", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/oauth_app")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"apps" => apps, "count" => count, "page_size" => _} = response
|
||||
|
||||
assert length(apps) == count
|
||||
end
|
||||
|
||||
test "with page size", %{conn: conn} do
|
||||
insert(:oauth_app)
|
||||
page_size = 1
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/oauth_app?page_size=#{page_size}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
|
||||
|
||||
assert length(apps) == page_size
|
||||
end
|
||||
|
||||
test "search by client name", %{conn: conn, app: app} do
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/oauth_app?name=#{app.client_name}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
|
||||
|
||||
assert returned["client_id"] == app.client_id
|
||||
assert returned["name"] == app.client_name
|
||||
end
|
||||
|
||||
test "search by client id", %{conn: conn, app: app} do
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/oauth_app?client_id=#{app.client_id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
|
||||
|
||||
assert returned["client_id"] == app.client_id
|
||||
assert returned["name"] == app.client_name
|
||||
end
|
||||
|
||||
test "only trusted", %{conn: conn} do
|
||||
app = insert(:oauth_app, trusted: true)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/oauth_app?trusted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
|
||||
|
||||
assert returned["client_id"] == app.client_id
|
||||
assert returned["name"] == app.client_name
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/pleroma/admin/oauth_app/:id" do
|
||||
test "with id", %{conn: conn} do
|
||||
app = insert(:oauth_app)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
|
||||
|> json_response_and_validate_schema(:no_content)
|
||||
|
||||
assert response == ""
|
||||
end
|
||||
|
||||
test "with non existance id", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> delete("/api/pleroma/admin/oauth_app/0")
|
||||
|> json_response_and_validate_schema(:bad_request)
|
||||
|
||||
assert response == ""
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/pleroma/admin/oauth_app/:id" do
|
||||
test "with id", %{conn: conn} do
|
||||
app = insert(:oauth_app)
|
||||
|
||||
name = "another name"
|
||||
url = "https://example.com"
|
||||
scopes = ["admin"]
|
||||
id = app.id
|
||||
website = "http://website.com"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/oauth_app/#{id}", %{
|
||||
name: name,
|
||||
trusted: true,
|
||||
redirect_uris: url,
|
||||
scopes: scopes,
|
||||
website: website
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"client_id" => _,
|
||||
"client_secret" => _,
|
||||
"id" => ^id,
|
||||
"name" => ^name,
|
||||
"redirect_uri" => ^url,
|
||||
"trusted" => true,
|
||||
"website" => ^website
|
||||
} = response
|
||||
end
|
||||
|
||||
test "without id", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/oauth_app/0")
|
||||
|> json_response_and_validate_schema(:bad_request)
|
||||
|
||||
assert response == ""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
# 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) == %{
|
||||
"actor" => "http://mastodon.example.org/users/admin",
|
||||
"followed_back" => false
|
||||
}
|
||||
|
||||
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"] == [
|
||||
%{
|
||||
"actor" => "http://mastodon.example.org/users/admin",
|
||||
"followed_back" => true
|
||||
},
|
||||
%{"actor" => "https://mstdn.io/users/mayuutann", "followed_back" => true}
|
||||
]
|
||||
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
|
||||
|
|
@ -1,372 +0,0 @@
|
|||
# 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.ReportControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.ModerationLog
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.ReportNote
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
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 "GET /api/pleroma/admin/reports/:id" do
|
||||
test "returns report by its id", %{conn: conn} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
{:ok, %{id: report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/reports/#{report_id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["id"] == report_id
|
||||
end
|
||||
|
||||
test "returns 404 when report id is invalid", %{conn: conn} do
|
||||
conn = get(conn, "/api/pleroma/admin/reports/test")
|
||||
|
||||
assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/pleroma/admin/reports" do
|
||||
setup do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
{:ok, %{id: report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
{:ok, %{id: second_report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel very offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
%{
|
||||
id: report_id,
|
||||
second_report_id: second_report_id
|
||||
}
|
||||
end
|
||||
|
||||
test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do
|
||||
read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"])
|
||||
write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:token, read_token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [%{"state" => "resolved", "id" => id}]
|
||||
})
|
||||
|> json_response_and_validate_schema(403)
|
||||
|
||||
assert response == %{
|
||||
"error" => "Insufficient permissions: admin:write:reports."
|
||||
}
|
||||
|
||||
conn
|
||||
|> assign(:token, write_token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [%{"state" => "resolved", "id" => id}]
|
||||
})
|
||||
|> json_response_and_validate_schema(:no_content)
|
||||
end
|
||||
|
||||
test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [
|
||||
%{"state" => "resolved", "id" => id}
|
||||
]
|
||||
})
|
||||
|> json_response_and_validate_schema(:no_content)
|
||||
|
||||
activity = Activity.get_by_id(id)
|
||||
assert activity.data["state"] == "resolved"
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} updated report ##{id} with 'resolved' state"
|
||||
end
|
||||
|
||||
test "closes report", %{conn: conn, id: id, admin: admin} do
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [
|
||||
%{"state" => "closed", "id" => id}
|
||||
]
|
||||
})
|
||||
|> json_response_and_validate_schema(:no_content)
|
||||
|
||||
activity = Activity.get_by_id(id)
|
||||
assert activity.data["state"] == "closed"
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} updated report ##{id} with 'closed' state"
|
||||
end
|
||||
|
||||
test "returns 400 when state is unknown", %{conn: conn, id: id} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [
|
||||
%{"state" => "test", "id" => id}
|
||||
]
|
||||
})
|
||||
|
||||
assert "Unsupported state" =
|
||||
hd(json_response_and_validate_schema(conn, :bad_request))["error"]
|
||||
end
|
||||
|
||||
test "returns 404 when report is not exist", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [
|
||||
%{"state" => "closed", "id" => "test"}
|
||||
]
|
||||
})
|
||||
|
||||
assert hd(json_response_and_validate_schema(conn, :bad_request))["error"] == "not_found"
|
||||
end
|
||||
|
||||
test "updates state of multiple reports", %{
|
||||
conn: conn,
|
||||
id: id,
|
||||
admin: admin,
|
||||
second_report_id: second_report_id
|
||||
} do
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [
|
||||
%{"state" => "resolved", "id" => id},
|
||||
%{"state" => "closed", "id" => second_report_id}
|
||||
]
|
||||
})
|
||||
|> json_response_and_validate_schema(:no_content)
|
||||
|
||||
activity = Activity.get_by_id(id)
|
||||
second_activity = Activity.get_by_id(second_report_id)
|
||||
assert activity.data["state"] == "resolved"
|
||||
assert second_activity.data["state"] == "closed"
|
||||
|
||||
[first_log_entry, second_log_entry] = Repo.all(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(first_log_entry) ==
|
||||
"@#{admin.nickname} updated report ##{id} with 'resolved' state"
|
||||
|
||||
assert ModerationLog.get_log_entry_message(second_log_entry) ==
|
||||
"@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/reports" do
|
||||
test "returns empty response when no reports created", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> get(report_path(conn, :index))
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert Enum.empty?(response["reports"])
|
||||
assert response["total"] == 0
|
||||
end
|
||||
|
||||
test "returns reports", %{conn: conn} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
{:ok, %{id: report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get(report_path(conn, :index))
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
[report] = response["reports"]
|
||||
|
||||
assert length(response["reports"]) == 1
|
||||
assert report["id"] == report_id
|
||||
|
||||
assert response["total"] == 1
|
||||
end
|
||||
|
||||
test "returns reports with specified state", %{conn: conn} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
{:ok, %{id: first_report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
{:ok, %{id: second_report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I don't like this user"
|
||||
})
|
||||
|
||||
CommonAPI.update_report_state(second_report_id, "closed")
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get(report_path(conn, :index, %{state: "open"}))
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [open_report] = response["reports"]
|
||||
|
||||
assert length(response["reports"]) == 1
|
||||
assert open_report["id"] == first_report_id
|
||||
|
||||
assert response["total"] == 1
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get(report_path(conn, :index, %{state: "closed"}))
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [closed_report] = response["reports"]
|
||||
|
||||
assert length(response["reports"]) == 1
|
||||
assert closed_report["id"] == second_report_id
|
||||
|
||||
assert response["total"] == 1
|
||||
|
||||
assert %{"total" => 0, "reports" => []} ==
|
||||
conn
|
||||
|> get(report_path(conn, :index, %{state: "resolved"}))
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "returns 403 when requested by a non-admin" do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> get("/api/pleroma/admin/reports")
|
||||
|
||||
assert json_response(conn, :forbidden) ==
|
||||
%{"error" => "User is not an admin."}
|
||||
end
|
||||
|
||||
test "returns 403 when requested by anonymous" do
|
||||
conn = get(build_conn(), "/api/pleroma/admin/reports")
|
||||
|
||||
assert json_response(conn, :forbidden) == %{
|
||||
"error" => "Invalid credentials."
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/reports/:id/notes" do
|
||||
setup %{conn: conn, admin: admin} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
{:ok, %{id: report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
|
||||
content: "this is disgusting!"
|
||||
})
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
|
||||
content: "this is disgusting2!"
|
||||
})
|
||||
|
||||
%{
|
||||
admin_id: admin.id,
|
||||
report_id: report_id
|
||||
}
|
||||
end
|
||||
|
||||
test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
|
||||
assert [note, _] = Repo.all(ReportNote)
|
||||
|
||||
assert %{
|
||||
activity_id: ^report_id,
|
||||
content: "this is disgusting!",
|
||||
user_id: ^admin_id
|
||||
} = note
|
||||
end
|
||||
|
||||
test "it returns reports with notes", %{conn: conn, admin: admin} do
|
||||
conn = get(conn, "/api/pleroma/admin/reports")
|
||||
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
notes = hd(response["reports"])["notes"]
|
||||
[note, _] = notes
|
||||
|
||||
assert note["user"]["nickname"] == admin.nickname
|
||||
assert note["content"] == "this is disgusting!"
|
||||
assert note["created_at"]
|
||||
assert response["total"] == 1
|
||||
end
|
||||
|
||||
test "it deletes the note", %{conn: conn, report_id: report_id} do
|
||||
assert ReportNote |> Repo.all() |> length() == 2
|
||||
assert [note, _] = Repo.all(ReportNote)
|
||||
|
||||
delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
|
||||
|
||||
assert ReportNote |> Repo.all() |> length() == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
# 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.StatusControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.ModerationLog
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
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 "GET /api/pleroma/admin/statuses/:id" do
|
||||
test "not found", %{conn: conn} do
|
||||
assert conn
|
||||
|> get("/api/pleroma/admin/statuses/not_found")
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
end
|
||||
|
||||
test "shows activity", %{conn: conn} do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/statuses/#{activity.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["id"] == activity.id
|
||||
|
||||
account = response["account"]
|
||||
actor = User.get_by_ap_id(activity.actor)
|
||||
|
||||
assert account["id"] == actor.id
|
||||
assert account["nickname"] == actor.nickname
|
||||
assert account["deactivated"] == actor.deactivated
|
||||
assert account["confirmation_pending"] == actor.confirmation_pending
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /api/pleroma/admin/statuses/:id" do
|
||||
setup do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
%{id: activity.id}
|
||||
end
|
||||
|
||||
test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["sensitive"]
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
refute response["sensitive"]
|
||||
end
|
||||
|
||||
test "change visibility flag", %{conn: conn, id: id, admin: admin} do
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "public"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["visibility"] == "public"
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "private"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["visibility"] == "private"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "unlisted"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["visibility"] == "unlisted"
|
||||
end
|
||||
|
||||
test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "test"})
|
||||
|
||||
assert %{"error" => "test - Invalid value for enum."} =
|
||||
json_response_and_validate_schema(conn, :bad_request)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/pleroma/admin/statuses/:id" do
|
||||
setup do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
%{id: activity.id}
|
||||
end
|
||||
|
||||
test "deletes status", %{conn: conn, id: id, admin: admin} do
|
||||
conn
|
||||
|> delete("/api/pleroma/admin/statuses/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
refute Activity.get_by_id(id)
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deleted status ##{id}"
|
||||
end
|
||||
|
||||
test "returns 404 when the status does not exist", %{conn: conn} do
|
||||
conn = delete(conn, "/api/pleroma/admin/statuses/test")
|
||||
|
||||
assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/statuses" do
|
||||
test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do
|
||||
blocked = insert(:user)
|
||||
user = insert(:user)
|
||||
User.block(admin, blocked)
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "@#{admin.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
{:ok, _} = CommonAPI.post(blocked, %{status: ".", visibility: "public"})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/statuses")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute "private" in Enum.map(response, & &1["visibility"])
|
||||
assert length(response) == 3
|
||||
end
|
||||
|
||||
test "returns only local statuses with local_only on", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
remote_user = insert(:user, local: false, nickname: "archaeme@archae.me")
|
||||
insert(:note_activity, user: user, local: true)
|
||||
insert(:note_activity, user: remote_user, local: false)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/statuses?local_only=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert length(response) == 1
|
||||
end
|
||||
|
||||
test "returns private and direct statuses with godmode on", %{conn: conn, admin: admin} do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "@#{admin.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
conn = get(conn, "/api/pleroma/admin/statuses?godmode=true")
|
||||
assert json_response_and_validate_schema(conn, 200) |> length() == 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
# 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.SearchTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.AdminAPI.Search
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "search for admin" do
|
||||
test "it ignores case" do
|
||||
insert(:user, nickname: "papercoach")
|
||||
insert(:user, nickname: "CanadaPaperCoach")
|
||||
|
||||
{:ok, _results, count} =
|
||||
Search.user(%{
|
||||
query: "paper",
|
||||
local: false,
|
||||
page: 1,
|
||||
page_size: 50
|
||||
})
|
||||
|
||||
assert count == 2
|
||||
end
|
||||
|
||||
test "it returns local/external users" do
|
||||
insert(:user, local: true)
|
||||
insert(:user, local: false)
|
||||
insert(:user, local: false)
|
||||
|
||||
{:ok, _results, local_count} =
|
||||
Search.user(%{
|
||||
query: "",
|
||||
local: true
|
||||
})
|
||||
|
||||
{:ok, _results, external_count} =
|
||||
Search.user(%{
|
||||
query: "",
|
||||
external: true
|
||||
})
|
||||
|
||||
assert local_count == 1
|
||||
assert external_count == 2
|
||||
end
|
||||
|
||||
test "it returns active/deactivated users" do
|
||||
insert(:user, deactivated: true)
|
||||
insert(:user, deactivated: true)
|
||||
insert(:user, deactivated: false)
|
||||
|
||||
{:ok, _results, active_count} =
|
||||
Search.user(%{
|
||||
query: "",
|
||||
active: true
|
||||
})
|
||||
|
||||
{:ok, _results, deactivated_count} =
|
||||
Search.user(%{
|
||||
query: "",
|
||||
deactivated: true
|
||||
})
|
||||
|
||||
assert active_count == 1
|
||||
assert deactivated_count == 2
|
||||
end
|
||||
|
||||
test "it returns specific user" do
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
user = insert(:user, nickname: "bob", local: true, deactivated: false)
|
||||
|
||||
{:ok, _results, total_count} = Search.user(%{query: ""})
|
||||
|
||||
{:ok, [^user], count} =
|
||||
Search.user(%{
|
||||
query: "Bo",
|
||||
active: true,
|
||||
local: true
|
||||
})
|
||||
|
||||
assert total_count == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns user by domain" do
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
user = insert(:user, nickname: "some@domain.com")
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^user], count} = Search.user(%{query: "domain.com"})
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it return user by full nickname" do
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
user = insert(:user, nickname: "some@domain.com")
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^user], count} = Search.user(%{query: "some@domain.com"})
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns admin user" do
|
||||
admin = insert(:user, is_admin: true)
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^admin], count} = Search.user(%{is_admin: true})
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns moderator user" do
|
||||
moderator = insert(:user, is_moderator: true)
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^moderator], count} = Search.user(%{is_moderator: true})
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns users with tags" do
|
||||
user1 = insert(:user, tags: ["first"])
|
||||
user2 = insert(:user, tags: ["second"])
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, users, count} = Search.user(%{tags: ["first", "second"]})
|
||||
assert total == 4
|
||||
assert count == 2
|
||||
assert user1 in users
|
||||
assert user2 in users
|
||||
end
|
||||
|
||||
test "it returns user by display name" do
|
||||
user = insert(:user, name: "Display name")
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^user], count} = Search.user(%{name: "display"})
|
||||
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns user by email" do
|
||||
user = insert(:user, email: "some@example.com")
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^user], count} = Search.user(%{email: "some@example.com"})
|
||||
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns unapproved user" do
|
||||
unapproved = insert(:user, approval_pending: true)
|
||||
insert(:user)
|
||||
insert(:user)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
{:ok, [^unapproved], count} = Search.user(%{need_approval: true})
|
||||
assert total == 3
|
||||
assert count == 1
|
||||
end
|
||||
|
||||
test "it returns non-discoverable users" do
|
||||
insert(:user)
|
||||
insert(:user, discoverable: false)
|
||||
|
||||
{:ok, _results, total} = Search.user()
|
||||
|
||||
assert total == 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
# 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.ReportViewTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.AdminAPI
|
||||
alias Pleroma.Web.AdminAPI.Report
|
||||
alias Pleroma.Web.AdminAPI.ReportView
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
test "renders a report" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
|
||||
|
||||
expected = %{
|
||||
content: nil,
|
||||
actor:
|
||||
Map.merge(
|
||||
MastodonAPI.AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
|
||||
AdminAPI.AccountView.render("show.json", %{user: user})
|
||||
),
|
||||
account:
|
||||
Map.merge(
|
||||
MastodonAPI.AccountView.render("show.json", %{
|
||||
user: other_user,
|
||||
skip_visibility_check: true
|
||||
}),
|
||||
AdminAPI.AccountView.render("show.json", %{user: other_user})
|
||||
),
|
||||
statuses: [],
|
||||
notes: [],
|
||||
state: "open",
|
||||
id: activity.id
|
||||
}
|
||||
|
||||
result =
|
||||
ReportView.render("show.json", Report.extract_report_info(activity))
|
||||
|> Map.delete(:created_at)
|
||||
|
||||
assert result == expected
|
||||
end
|
||||
|
||||
test "includes reported statuses" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "toot"})
|
||||
|
||||
{:ok, report_activity} =
|
||||
CommonAPI.report(user, %{account_id: other_user.id, status_ids: [activity.id]})
|
||||
|
||||
other_user = Pleroma.User.get_by_id(other_user.id)
|
||||
|
||||
expected = %{
|
||||
content: nil,
|
||||
actor:
|
||||
Map.merge(
|
||||
MastodonAPI.AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
|
||||
AdminAPI.AccountView.render("show.json", %{user: user})
|
||||
),
|
||||
account:
|
||||
Map.merge(
|
||||
MastodonAPI.AccountView.render("show.json", %{
|
||||
user: other_user,
|
||||
skip_visibility_check: true
|
||||
}),
|
||||
AdminAPI.AccountView.render("show.json", %{user: other_user})
|
||||
),
|
||||
statuses: [StatusView.render("show.json", %{activity: activity})],
|
||||
state: "open",
|
||||
notes: [],
|
||||
id: report_activity.id
|
||||
}
|
||||
|
||||
result =
|
||||
ReportView.render("show.json", Report.extract_report_info(report_activity))
|
||||
|> Map.delete(:created_at)
|
||||
|
||||
assert result == expected
|
||||
end
|
||||
|
||||
test "renders report's state" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.report(user, %{account_id: other_user.id})
|
||||
{:ok, activity} = CommonAPI.update_report_state(activity.id, "closed")
|
||||
|
||||
assert %{state: "closed"} =
|
||||
ReportView.render("show.json", Report.extract_report_info(activity))
|
||||
end
|
||||
|
||||
test "renders report description" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.report(user, %{
|
||||
account_id: other_user.id,
|
||||
comment: "posts are too good for this instance"
|
||||
})
|
||||
|
||||
assert %{content: "posts are too good for this instance"} =
|
||||
ReportView.render("show.json", Report.extract_report_info(activity))
|
||||
end
|
||||
|
||||
test "sanitizes report description" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.report(user, %{
|
||||
account_id: other_user.id,
|
||||
comment: ""
|
||||
})
|
||||
|
||||
data = Map.put(activity.data, "content", "<script> alert('hecked :D:D:D:D:D:D:D') </script>")
|
||||
activity = Map.put(activity, :data, data)
|
||||
|
||||
refute "<script> alert('hecked :D:D:D:D:D:D:D') </script>" ==
|
||||
ReportView.render("show.json", Report.extract_report_info(activity))[:content]
|
||||
end
|
||||
|
||||
test "doesn't error out when the user doesn't exists" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.report(user, %{
|
||||
account_id: other_user.id,
|
||||
comment: ""
|
||||
})
|
||||
|
||||
Pleroma.User.delete(other_user)
|
||||
Pleroma.User.invalidate_cache(other_user)
|
||||
|
||||
assert %{} = ReportView.render("show.json", Report.extract_report_info(activity))
|
||||
end
|
||||
end
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.SchemaExamplesTest do
|
||||
use ExUnit.Case, async: true
|
||||
import Pleroma.Tests.ApiSpecHelpers
|
||||
|
||||
@content_type "application/json"
|
||||
|
||||
for operation <- api_operations() do
|
||||
describe operation.operationId <> " Request Body" do
|
||||
if operation.requestBody do
|
||||
@media_type operation.requestBody.content[@content_type]
|
||||
@schema resolve_schema(@media_type.schema)
|
||||
|
||||
if @media_type.example do
|
||||
test "request body media type example matches schema" do
|
||||
assert_schema(@media_type.example, @schema)
|
||||
end
|
||||
end
|
||||
|
||||
if @schema.example do
|
||||
test "request body schema example matches schema" do
|
||||
assert_schema(@schema.example, @schema)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for {status, response} <- operation.responses, is_map(response.content[@content_type]) do
|
||||
describe "#{operation.operationId} - #{status} Response" do
|
||||
@schema resolve_schema(response.content[@content_type].schema)
|
||||
|
||||
if @schema.example do
|
||||
test "example matches schema" do
|
||||
assert_schema(@schema.example, @schema)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Tests.AuthTestControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "do_oauth_check" do
|
||||
test "serves with proper OAuth token (fulfilling requested scopes)" do
|
||||
%{conn: good_token_conn, user: user} = oauth_access(["read"])
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
good_token_conn
|
||||
|> get("/test/authenticated_api/do_oauth_check")
|
||||
|> json_response(200)
|
||||
|
||||
# Unintended usage (:api) — use with :authenticated_api instead
|
||||
assert %{"user_id" => user.id} ==
|
||||
good_token_conn
|
||||
|> get("/test/api/do_oauth_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "fails on no token / missing scope(s)" do
|
||||
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||
|
||||
bad_token_conn
|
||||
|> get("/test/authenticated_api/do_oauth_check")
|
||||
|> json_response(403)
|
||||
|
||||
bad_token_conn
|
||||
|> assign(:token, nil)
|
||||
|> get("/test/api/do_oauth_check")
|
||||
|> json_response(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fallback_oauth_check" do
|
||||
test "serves with proper OAuth token (fulfilling requested scopes)" do
|
||||
%{conn: good_token_conn, user: user} = oauth_access(["read"])
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
good_token_conn
|
||||
|> get("/test/api/fallback_oauth_check")
|
||||
|> json_response(200)
|
||||
|
||||
# Unintended usage (:authenticated_api) — use with :api instead
|
||||
assert %{"user_id" => user.id} ==
|
||||
good_token_conn
|
||||
|> get("/test/authenticated_api/fallback_oauth_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "for :api on public instance, drops :user and renders on no token / missing scope(s)" do
|
||||
clear_config([:instance, :public], true)
|
||||
|
||||
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
bad_token_conn
|
||||
|> get("/test/api/fallback_oauth_check")
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
bad_token_conn
|
||||
|> assign(:token, nil)
|
||||
|> get("/test/api/fallback_oauth_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "for :api on private instance, fails on no token / missing scope(s)" do
|
||||
clear_config([:instance, :public], false)
|
||||
|
||||
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||
|
||||
bad_token_conn
|
||||
|> get("/test/api/fallback_oauth_check")
|
||||
|> json_response(403)
|
||||
|
||||
bad_token_conn
|
||||
|> assign(:token, nil)
|
||||
|> get("/test/api/fallback_oauth_check")
|
||||
|> json_response(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe "skip_oauth_check" do
|
||||
test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
|
||||
user = insert(:user)
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|> get("/test/authenticated_api/skip_oauth_check")
|
||||
|> json_response(200)
|
||||
|
||||
%{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
bad_token_conn
|
||||
|> get("/test/authenticated_api/skip_oauth_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "serves via :api on public instance if :user is not set" do
|
||||
clear_config([:instance, :public], true)
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
build_conn()
|
||||
|> get("/test/api/skip_oauth_check")
|
||||
|> json_response(200)
|
||||
|
||||
build_conn()
|
||||
|> get("/test/authenticated_api/skip_oauth_check")
|
||||
|> json_response(403)
|
||||
end
|
||||
|
||||
test "fails on private instance if :user is not set" do
|
||||
clear_config([:instance, :public], false)
|
||||
|
||||
build_conn()
|
||||
|> get("/test/api/skip_oauth_check")
|
||||
|> json_response(403)
|
||||
|
||||
build_conn()
|
||||
|> get("/test/authenticated_api/skip_oauth_check")
|
||||
|> json_response(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fallback_oauth_skip_publicity_check" do
|
||||
test "serves with proper OAuth token (fulfilling requested scopes)" do
|
||||
%{conn: good_token_conn, user: user} = oauth_access(["read"])
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
good_token_conn
|
||||
|> get("/test/api/fallback_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
|
||||
# Unintended usage (:authenticated_api)
|
||||
assert %{"user_id" => user.id} ==
|
||||
good_token_conn
|
||||
|> get("/test/authenticated_api/fallback_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "for :api on private / public instance, drops :user and renders on token issue" do
|
||||
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||
|
||||
for is_public <- [true, false] do
|
||||
clear_config([:instance, :public], is_public)
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
bad_token_conn
|
||||
|> get("/test/api/fallback_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
bad_token_conn
|
||||
|> assign(:token, nil)
|
||||
|> get("/test/api/fallback_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "skip_oauth_skip_publicity_check" do
|
||||
test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
|
||||
user = insert(:user)
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
|
||||
%{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
bad_token_conn
|
||||
|> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "for :api, serves on private and public instances regardless of whether :user is set" do
|
||||
user = insert(:user)
|
||||
|
||||
for is_public <- [true, false] do
|
||||
clear_config([:instance, :public], is_public)
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
build_conn()
|
||||
|> get("/test/api/skip_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"user_id" => user.id} ==
|
||||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|> get("/test/api/skip_oauth_skip_publicity_check")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "missing_oauth_check_definition" do
|
||||
def test_missing_oauth_check_definition_failure(endpoint, expected_error) do
|
||||
%{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
|
||||
|
||||
assert %{"error" => expected_error} ==
|
||||
conn
|
||||
|> get(endpoint)
|
||||
|> json_response(403)
|
||||
end
|
||||
|
||||
test "fails if served via :authenticated_api" do
|
||||
test_missing_oauth_check_definition_failure(
|
||||
"/test/authenticated_api/missing_oauth_check_definition",
|
||||
"Security violation: OAuth scopes check was neither handled nor explicitly skipped."
|
||||
)
|
||||
end
|
||||
|
||||
test "fails if served via :api and the instance is private" do
|
||||
clear_config([:instance, :public], false)
|
||||
|
||||
test_missing_oauth_check_definition_failure(
|
||||
"/test/api/missing_oauth_check_definition",
|
||||
"This resource requires authentication."
|
||||
)
|
||||
end
|
||||
|
||||
test "succeeds with dropped :user if served via :api on public instance" do
|
||||
%{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
|
||||
|
||||
assert %{"user_id" => nil} ==
|
||||
conn
|
||||
|> get("/test/api/missing_oauth_check_definition")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.AuthenticatorTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.Auth.Authenticator
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "fetch_user/1" do
|
||||
test "returns user by name" do
|
||||
user = insert(:user)
|
||||
assert Authenticator.fetch_user(user.nickname) == user
|
||||
end
|
||||
|
||||
test "returns user by email" do
|
||||
user = insert(:user)
|
||||
assert Authenticator.fetch_user(user.email) == user
|
||||
end
|
||||
|
||||
test "returns nil" do
|
||||
assert Authenticator.fetch_user("email") == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_credentials/1" do
|
||||
test "returns name and password from authorization params" do
|
||||
params = %{"authorization" => %{"name" => "test", "password" => "test-pass"}}
|
||||
assert Authenticator.fetch_credentials(params) == {:ok, {"test", "test-pass"}}
|
||||
end
|
||||
|
||||
test "returns name and password with grant_type 'password'" do
|
||||
params = %{"grant_type" => "password", "username" => "test", "password" => "test-pass"}
|
||||
assert Authenticator.fetch_credentials(params) == {:ok, {"test", "test-pass"}}
|
||||
end
|
||||
|
||||
test "returns error" do
|
||||
assert Authenticator.fetch_credentials(%{}) == {:error, :invalid_credentials}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.BasicAuthTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "with HTTP Basic Auth used, grants access to OAuth scope-restricted endpoints", %{
|
||||
conn: conn
|
||||
} do
|
||||
user = insert(:user)
|
||||
assert Pbkdf2.verify_pass("test", user.password_hash)
|
||||
|
||||
basic_auth_contents =
|
||||
(URI.encode_www_form(user.nickname) <> ":" <> URI.encode_www_form("test"))
|
||||
|> Base.encode64()
|
||||
|
||||
# Succeeds with HTTP Basic Auth
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("authorization", "Basic " <> basic_auth_contents)
|
||||
|> get("/api/v1/accounts/verify_credentials")
|
||||
|> json_response(200)
|
||||
|
||||
user_nickname = user.nickname
|
||||
assert %{"username" => ^user_nickname} = response
|
||||
|
||||
# Succeeds with a properly scoped OAuth token
|
||||
valid_token = insert(:oauth_token, scopes: ["read:accounts"])
|
||||
|
||||
conn
|
||||
|> put_req_header("authorization", "Bearer #{valid_token.token}")
|
||||
|> get("/api/v1/accounts/verify_credentials")
|
||||
|> json_response(200)
|
||||
|
||||
# Fails with a wrong-scoped OAuth token (proof of restriction)
|
||||
invalid_token = insert(:oauth_token, scopes: ["read:something"])
|
||||
|
||||
conn
|
||||
|> put_req_header("authorization", "Bearer #{invalid_token.token}")
|
||||
|> get("/api/v1/accounts/verify_credentials")
|
||||
|> json_response(403)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.PleromaAuthenticatorTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.Auth.PleromaAuthenticator
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
password = "testpassword"
|
||||
name = "AgentSmith"
|
||||
user = insert(:user, nickname: name, password_hash: Pbkdf2.hash_pwd_salt(password))
|
||||
{:ok, [user: user, name: name, password: password]}
|
||||
end
|
||||
|
||||
test "get_user/authorization", %{name: name, password: password} do
|
||||
name = name <> "1"
|
||||
user = insert(:user, nickname: name, password_hash: Bcrypt.hash_pwd_salt(password))
|
||||
|
||||
params = %{"authorization" => %{"name" => name, "password" => password}}
|
||||
res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
|
||||
|
||||
assert {:ok, returned_user} = res
|
||||
assert returned_user.id == user.id
|
||||
assert "$pbkdf2" <> _ = returned_user.password_hash
|
||||
end
|
||||
|
||||
test "get_user/authorization with invalid password", %{name: name} do
|
||||
params = %{"authorization" => %{"name" => name, "password" => "password"}}
|
||||
res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
|
||||
|
||||
assert {:error, {:checkpw, false}} == res
|
||||
end
|
||||
|
||||
test "get_user/grant_type_password", %{user: user, name: name, password: password} do
|
||||
params = %{"grant_type" => "password", "username" => name, "password" => password}
|
||||
res = PleromaAuthenticator.get_user(%Plug.Conn{params: params})
|
||||
|
||||
assert {:ok, user} == res
|
||||
end
|
||||
|
||||
test "error credintails" do
|
||||
res = PleromaAuthenticator.get_user(%Plug.Conn{params: %{}})
|
||||
assert {:error, :invalid_credentials} == res
|
||||
end
|
||||
end
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.TOTPAuthenticatorTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.MFA
|
||||
alias Pleroma.MFA.BackupCodes
|
||||
alias Pleroma.MFA.TOTP
|
||||
alias Pleroma.Web.Auth.TOTPAuthenticator
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "verify token" do
|
||||
otp_secret = TOTP.generate_secret()
|
||||
otp_token = TOTP.generate_token(otp_secret)
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
multi_factor_authentication_settings: %MFA.Settings{
|
||||
enabled: true,
|
||||
totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true}
|
||||
}
|
||||
)
|
||||
|
||||
assert TOTPAuthenticator.verify(otp_token, user) == {:ok, :pass}
|
||||
assert TOTPAuthenticator.verify(nil, user) == {:error, :invalid_token}
|
||||
assert TOTPAuthenticator.verify("", user) == {:error, :invalid_token}
|
||||
end
|
||||
|
||||
test "checks backup codes" do
|
||||
[code | _] = backup_codes = BackupCodes.generate()
|
||||
|
||||
hashed_codes =
|
||||
backup_codes
|
||||
|> Enum.map(&Pbkdf2.hash_pwd_salt(&1))
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
multi_factor_authentication_settings: %MFA.Settings{
|
||||
enabled: true,
|
||||
backup_codes: hashed_codes,
|
||||
totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
|
||||
}
|
||||
)
|
||||
|
||||
assert TOTPAuthenticator.verify_recovery_code(user, code) == {:ok, :pass}
|
||||
refute TOTPAuthenticator.verify_recovery_code(code, refresh_record(user)) == {:ok, :pass}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ChatChannelTest do
|
||||
use Pleroma.Web.ChannelCase
|
||||
alias Pleroma.Web.ChatChannel
|
||||
alias Pleroma.Web.UserSocket
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, _, socket} =
|
||||
socket(UserSocket, "", %{user_name: user.nickname})
|
||||
|> subscribe_and_join(ChatChannel, "chat:public")
|
||||
|
||||
{:ok, socket: socket}
|
||||
end
|
||||
|
||||
test "it broadcasts a message", %{socket: socket} do
|
||||
push(socket, "new_msg", %{"text" => "why is tenshi eating a corndog so cute?"})
|
||||
assert_broadcast("new_msg", %{text: "why is tenshi eating a corndog so cute?"})
|
||||
end
|
||||
|
||||
describe "message lengths" do
|
||||
setup do: clear_config([:instance, :chat_limit])
|
||||
|
||||
test "it ignores messages of length zero", %{socket: socket} do
|
||||
push(socket, "new_msg", %{"text" => ""})
|
||||
refute_broadcast("new_msg", %{text: ""})
|
||||
end
|
||||
|
||||
test "it ignores messages above a certain length", %{socket: socket} do
|
||||
Pleroma.Config.put([:instance, :chat_limit], 2)
|
||||
push(socket, "new_msg", %{"text" => "123"})
|
||||
refute_broadcast("new_msg", %{text: "123"})
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,593 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
||||
alias Pleroma.Builders.UserBuilder
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
use Pleroma.DataCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
|
||||
@public_address "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
describe "add_attachments/2" do
|
||||
setup do
|
||||
name =
|
||||
"Sakura Mana – Turned on by a Senior OL with a Temptating Tight Skirt-s Full Hipline and Panty Shot- Beautiful Thick Thighs- and Erotic Ass- -2015- -- Oppaitime 8-28-2017 6-50-33 PM.png"
|
||||
|
||||
attachment = %{
|
||||
"url" => [%{"href" => URI.encode(name)}]
|
||||
}
|
||||
|
||||
%{name: name, attachment: attachment}
|
||||
end
|
||||
|
||||
test "it adds attachment links to a given text and attachment set", %{
|
||||
name: name,
|
||||
attachment: attachment
|
||||
} do
|
||||
len = 10
|
||||
clear_config([Pleroma.Upload, :filename_display_max_length], len)
|
||||
|
||||
expected =
|
||||
"<br><a href=\"#{URI.encode(name)}\" class='attachment'>#{String.slice(name, 0..len)}…</a>"
|
||||
|
||||
assert Utils.add_attachments("", [attachment]) == expected
|
||||
end
|
||||
|
||||
test "doesn't truncate file name if config for truncate is set to 0", %{
|
||||
name: name,
|
||||
attachment: attachment
|
||||
} do
|
||||
clear_config([Pleroma.Upload, :filename_display_max_length], 0)
|
||||
|
||||
expected = "<br><a href=\"#{URI.encode(name)}\" class='attachment'>#{name}</a>"
|
||||
|
||||
assert Utils.add_attachments("", [attachment]) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "it confirms the password given is the current users password" do
|
||||
test "incorrect password given" do
|
||||
{:ok, user} = UserBuilder.insert()
|
||||
|
||||
assert Utils.confirm_current_password(user, "") == {:error, "Invalid password."}
|
||||
end
|
||||
|
||||
test "correct password given" do
|
||||
{:ok, user} = UserBuilder.insert()
|
||||
assert Utils.confirm_current_password(user, "test") == {:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
describe "format_input/3" do
|
||||
test "works for bare text/plain" do
|
||||
text = "hello world!"
|
||||
expected = "hello world!"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/plain")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "hello world!\n\nsecond paragraph!"
|
||||
expected = "hello world!<br><br>second paragraph!"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/plain")
|
||||
|
||||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for bare text/html" do
|
||||
text = "<p>hello world!</p>"
|
||||
expected = "<p>hello world!</p>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/html")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "<p>hello world!</p><br/>\n<p>second paragraph</p>"
|
||||
expected = "<p>hello world!</p><br/>\n<p>second paragraph</p>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/html")
|
||||
|
||||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for bare text/markdown" do
|
||||
text = "**hello world**"
|
||||
expected = "<p><strong>hello world</strong></p>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/markdown")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "**hello world**\n\n*another paragraph*"
|
||||
expected = "<p><strong>hello world</strong></p><p><em>another paragraph</em></p>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/markdown")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = """
|
||||
> cool quote
|
||||
|
||||
by someone
|
||||
"""
|
||||
|
||||
expected = "<blockquote><p>cool quote</p></blockquote><p>by someone</p>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/markdown")
|
||||
|
||||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for bare text/bbcode" do
|
||||
text = "[b]hello world[/b]"
|
||||
expected = "<strong>hello world</strong>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "[b]hello world![/b]\n\nsecond paragraph!"
|
||||
expected = "<strong>hello world!</strong><br><br>second paragraph!"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "[b]hello world![/b]\n\n<strong>second paragraph!</strong>"
|
||||
|
||||
expected =
|
||||
"<strong>hello world!</strong><br><br><strong>second paragraph!</strong>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for text/markdown with mentions" do
|
||||
{:ok, user} =
|
||||
UserBuilder.insert(%{nickname: "user__test", ap_id: "http://foo.com/user__test"})
|
||||
|
||||
text = "**hello world**\n\n*another @user__test and @user__test google.com paragraph*"
|
||||
|
||||
{output, _, _} = Utils.format_input(text, "text/markdown")
|
||||
|
||||
assert output ==
|
||||
~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{
|
||||
user.id
|
||||
}" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{
|
||||
user.id
|
||||
}" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>)
|
||||
end
|
||||
end
|
||||
|
||||
describe "context_to_conversation_id" do
|
||||
test "creates a mapping object" do
|
||||
conversation_id = Utils.context_to_conversation_id("random context")
|
||||
object = Object.get_by_ap_id("random context")
|
||||
|
||||
assert conversation_id == object.id
|
||||
end
|
||||
|
||||
test "returns an existing mapping for an existing object" do
|
||||
{:ok, object} = Object.context_mapping("random context") |> Repo.insert()
|
||||
conversation_id = Utils.context_to_conversation_id("random context")
|
||||
|
||||
assert conversation_id == object.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "formats date to asctime" do
|
||||
test "when date is in ISO 8601 format" do
|
||||
date = DateTime.utc_now() |> DateTime.to_iso8601()
|
||||
|
||||
expected =
|
||||
date
|
||||
|> DateTime.from_iso8601()
|
||||
|> elem(1)
|
||||
|> Calendar.Strftime.strftime!("%a %b %d %H:%M:%S %z %Y")
|
||||
|
||||
assert Utils.date_to_asctime(date) == expected
|
||||
end
|
||||
|
||||
test "when date is a binary in wrong format" do
|
||||
date = DateTime.utc_now()
|
||||
|
||||
expected = ""
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert Utils.date_to_asctime(date) == expected
|
||||
end) =~ "[warn] Date #{date} in wrong format, must be ISO 8601"
|
||||
end
|
||||
|
||||
test "when date is a Unix timestamp" do
|
||||
date = DateTime.utc_now() |> DateTime.to_unix()
|
||||
|
||||
expected = ""
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert Utils.date_to_asctime(date) == expected
|
||||
end) =~ "[warn] Date #{date} in wrong format, must be ISO 8601"
|
||||
end
|
||||
|
||||
test "when date is nil" do
|
||||
expected = ""
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert Utils.date_to_asctime(nil) == expected
|
||||
end) =~ "[warn] Date in wrong format, must be ISO 8601"
|
||||
end
|
||||
|
||||
test "when date is a random string" do
|
||||
assert capture_log(fn ->
|
||||
assert Utils.date_to_asctime("foo") == ""
|
||||
end) =~ "[warn] Date foo in wrong format, must be ISO 8601"
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_to_and_cc" do
|
||||
test "for public posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 1
|
||||
|
||||
assert @public_address in to
|
||||
assert mentioned_user.ap_id in to
|
||||
assert user.follower_address in cc
|
||||
end
|
||||
|
||||
test "for public posts, a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 1
|
||||
|
||||
assert @public_address in to
|
||||
assert mentioned_user.ap_id in to
|
||||
assert third_user.ap_id in to
|
||||
assert user.follower_address in cc
|
||||
end
|
||||
|
||||
test "for unlisted posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 1
|
||||
|
||||
assert @public_address in cc
|
||||
assert mentioned_user.ap_id in to
|
||||
assert user.follower_address in to
|
||||
end
|
||||
|
||||
test "for unlisted posts, a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 1
|
||||
|
||||
assert @public_address in cc
|
||||
assert mentioned_user.ap_id in to
|
||||
assert third_user.ap_id in to
|
||||
assert user.follower_address in to
|
||||
end
|
||||
|
||||
test "for private posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private", nil)
|
||||
assert length(to) == 2
|
||||
assert Enum.empty?(cc)
|
||||
|
||||
assert mentioned_user.ap_id in to
|
||||
assert user.follower_address in to
|
||||
end
|
||||
|
||||
test "for private posts, a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert Enum.empty?(cc)
|
||||
|
||||
assert mentioned_user.ap_id in to
|
||||
assert user.follower_address in to
|
||||
end
|
||||
|
||||
test "for direct posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct", nil)
|
||||
|
||||
assert length(to) == 1
|
||||
assert Enum.empty?(cc)
|
||||
|
||||
assert mentioned_user.ap_id in to
|
||||
end
|
||||
|
||||
test "for direct posts, a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil)
|
||||
|
||||
assert length(to) == 1
|
||||
assert Enum.empty?(cc)
|
||||
|
||||
assert mentioned_user.ap_id in to
|
||||
|
||||
{:ok, direct_activity} = CommonAPI.post(third_user, %{status: "uguu", visibility: "direct"})
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, direct_activity, "direct", nil)
|
||||
|
||||
assert length(to) == 2
|
||||
assert Enum.empty?(cc)
|
||||
|
||||
assert mentioned_user.ap_id in to
|
||||
assert third_user.ap_id in to
|
||||
end
|
||||
end
|
||||
|
||||
describe "to_master_date/1" do
|
||||
test "removes microseconds from date (NaiveDateTime)" do
|
||||
assert Utils.to_masto_date(~N[2015-01-23 23:50:07.123]) == "2015-01-23T23:50:07.000Z"
|
||||
end
|
||||
|
||||
test "removes microseconds from date (String)" do
|
||||
assert Utils.to_masto_date("2015-01-23T23:50:07.123Z") == "2015-01-23T23:50:07.000Z"
|
||||
end
|
||||
|
||||
test "returns empty string when date invalid" do
|
||||
assert Utils.to_masto_date("2015-01?23T23:50:07.123Z") == ""
|
||||
end
|
||||
end
|
||||
|
||||
describe "conversation_id_to_context/1" do
|
||||
test "returns id" do
|
||||
object = insert(:note)
|
||||
assert Utils.conversation_id_to_context(object.id) == object.data["id"]
|
||||
end
|
||||
|
||||
test "returns error if object not found" do
|
||||
assert Utils.conversation_id_to_context("123") == {:error, "No such conversation"}
|
||||
end
|
||||
end
|
||||
|
||||
describe "maybe_notify_mentioned_recipients/2" do
|
||||
test "returns recipients when activity is not `Create`" do
|
||||
activity = insert(:like_activity)
|
||||
assert Utils.maybe_notify_mentioned_recipients(["test"], activity) == ["test"]
|
||||
end
|
||||
|
||||
test "returns recipients from tag" do
|
||||
user = insert(:user)
|
||||
|
||||
object =
|
||||
insert(:note,
|
||||
user: user,
|
||||
data: %{
|
||||
"tag" => [
|
||||
%{"type" => "Hashtag"},
|
||||
"",
|
||||
%{"type" => "Mention", "href" => "https://testing.pleroma.lol/users/lain"},
|
||||
%{"type" => "Mention", "href" => "https://shitposter.club/user/5381"},
|
||||
%{"type" => "Mention", "href" => "https://shitposter.club/user/5381"}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
activity = insert(:note_activity, user: user, note: object)
|
||||
|
||||
assert Utils.maybe_notify_mentioned_recipients(["test"], activity) == [
|
||||
"test",
|
||||
"https://testing.pleroma.lol/users/lain",
|
||||
"https://shitposter.club/user/5381"
|
||||
]
|
||||
end
|
||||
|
||||
test "returns recipients when object is map" do
|
||||
user = insert(:user)
|
||||
object = insert(:note, user: user)
|
||||
|
||||
activity =
|
||||
insert(:note_activity,
|
||||
user: user,
|
||||
note: object,
|
||||
data_attrs: %{
|
||||
"object" => %{
|
||||
"tag" => [
|
||||
%{"type" => "Hashtag"},
|
||||
"",
|
||||
%{"type" => "Mention", "href" => "https://testing.pleroma.lol/users/lain"},
|
||||
%{"type" => "Mention", "href" => "https://shitposter.club/user/5381"},
|
||||
%{"type" => "Mention", "href" => "https://shitposter.club/user/5381"}
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Pleroma.Repo.delete(object)
|
||||
|
||||
assert Utils.maybe_notify_mentioned_recipients(["test"], activity) == [
|
||||
"test",
|
||||
"https://testing.pleroma.lol/users/lain",
|
||||
"https://shitposter.club/user/5381"
|
||||
]
|
||||
end
|
||||
|
||||
test "returns recipients when object not found" do
|
||||
user = insert(:user)
|
||||
object = insert(:note, user: user)
|
||||
|
||||
activity = insert(:note_activity, user: user, note: object)
|
||||
Pleroma.Repo.delete(object)
|
||||
|
||||
obj_url = activity.data["object"]
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get, url: ^obj_url} ->
|
||||
%Tesla.Env{status: 404, body: ""}
|
||||
end)
|
||||
|
||||
assert Utils.maybe_notify_mentioned_recipients(["test-test"], activity) == [
|
||||
"test-test"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "attachments_from_ids_descs/2" do
|
||||
test "returns [] when attachment ids is empty" do
|
||||
assert Utils.attachments_from_ids_descs([], "{}") == []
|
||||
end
|
||||
|
||||
test "returns list attachments with desc" do
|
||||
object = insert(:note)
|
||||
desc = Jason.encode!(%{object.id => "test-desc"})
|
||||
|
||||
assert Utils.attachments_from_ids_descs(["#{object.id}", "34"], desc) == [
|
||||
Map.merge(object.data, %{"name" => "test-desc"})
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "attachments_from_ids/1" do
|
||||
test "returns attachments with descs" do
|
||||
object = insert(:note)
|
||||
desc = Jason.encode!(%{object.id => "test-desc"})
|
||||
|
||||
assert Utils.attachments_from_ids(%{
|
||||
media_ids: ["#{object.id}"],
|
||||
descriptions: desc
|
||||
}) == [
|
||||
Map.merge(object.data, %{"name" => "test-desc"})
|
||||
]
|
||||
end
|
||||
|
||||
test "returns attachments without descs" do
|
||||
object = insert(:note)
|
||||
assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}) == [object.data]
|
||||
end
|
||||
|
||||
test "returns [] when not pass media_ids" do
|
||||
assert Utils.attachments_from_ids(%{}) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "maybe_add_list_data/3" do
|
||||
test "adds list params when found user list" do
|
||||
user = insert(:user)
|
||||
{:ok, %Pleroma.List{} = list} = Pleroma.List.create("title", user)
|
||||
|
||||
assert Utils.maybe_add_list_data(%{additional: %{}, object: %{}}, user, {:list, list.id}) ==
|
||||
%{
|
||||
additional: %{"bcc" => [list.ap_id], "listMessage" => list.ap_id},
|
||||
object: %{"listMessage" => list.ap_id}
|
||||
}
|
||||
end
|
||||
|
||||
test "returns original params when list not found" do
|
||||
user = insert(:user)
|
||||
{:ok, %Pleroma.List{} = list} = Pleroma.List.create("title", insert(:user))
|
||||
|
||||
assert Utils.maybe_add_list_data(%{additional: %{}, object: %{}}, user, {:list, list.id}) ==
|
||||
%{additional: %{}, object: %{}}
|
||||
end
|
||||
end
|
||||
|
||||
describe "make_note_data/11" do
|
||||
test "returns note data" do
|
||||
user = insert(:user)
|
||||
note = insert(:note)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
|
||||
assert Utils.make_note_data(
|
||||
user.ap_id,
|
||||
[user2.ap_id],
|
||||
"2hu",
|
||||
"<h1>This is :moominmamma: note</h1>",
|
||||
[],
|
||||
note.id,
|
||||
[name: "jimm"],
|
||||
"test summary",
|
||||
[user3.ap_id],
|
||||
false,
|
||||
%{"custom_tag" => "test"}
|
||||
) == %{
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [],
|
||||
"cc" => [user3.ap_id],
|
||||
"content" => "<h1>This is :moominmamma: note</h1>",
|
||||
"context" => "2hu",
|
||||
"sensitive" => false,
|
||||
"summary" => "test summary",
|
||||
"tag" => ["jimm"],
|
||||
"to" => [user2.ap_id],
|
||||
"type" => "Note",
|
||||
"custom_tag" => "test"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "maybe_add_attachments/3" do
|
||||
test "returns parsed results when attachment_links is false" do
|
||||
assert Utils.maybe_add_attachments(
|
||||
{"test", [], ["tags"]},
|
||||
[],
|
||||
false
|
||||
) == {"test", [], ["tags"]}
|
||||
end
|
||||
|
||||
test "adds attachments to parsed results" do
|
||||
attachment = %{"url" => [%{"href" => "SakuraPM.png"}]}
|
||||
|
||||
assert Utils.maybe_add_attachments(
|
||||
{"test", [], ["tags"]},
|
||||
[attachment],
|
||||
true
|
||||
) == {
|
||||
"test<br><a href=\"SakuraPM.png\" class='attachment'>SakuraPM.png</a>",
|
||||
[],
|
||||
["tags"]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.FallbackTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "neither preloaded data nor metadata attached to" do
|
||||
test "GET /registration/:token", %{conn: conn} do
|
||||
response = get(conn, "/registration/foo")
|
||||
|
||||
assert html_response(response, 200) =~ "<!--server-generated-meta-->"
|
||||
end
|
||||
|
||||
test "GET /*path", %{conn: conn} do
|
||||
assert conn
|
||||
|> get("/foo")
|
||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
||||
end
|
||||
end
|
||||
|
||||
describe "preloaded data and metadata attached to" do
|
||||
test "GET /:maybe_nickname_or_id", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
user_missing = get(conn, "/foo")
|
||||
user_present = get(conn, "/#{user.nickname}")
|
||||
|
||||
assert(html_response(user_missing, 200) =~ "<!--server-generated-meta-->")
|
||||
refute html_response(user_present, 200) =~ "<!--server-generated-meta-->"
|
||||
assert html_response(user_present, 200) =~ "initial-results"
|
||||
end
|
||||
|
||||
test "GET /*path", %{conn: conn} do
|
||||
assert conn
|
||||
|> get("/foo")
|
||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
||||
|
||||
refute conn
|
||||
|> get("/foo/bar")
|
||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
||||
end
|
||||
end
|
||||
|
||||
describe "preloaded data is attached to" do
|
||||
test "GET /main/public", %{conn: conn} do
|
||||
public_page = get(conn, "/main/public")
|
||||
|
||||
refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
|
||||
assert html_response(public_page, 200) =~ "initial-results"
|
||||
end
|
||||
|
||||
test "GET /main/all", %{conn: conn} do
|
||||
public_page = get(conn, "/main/all")
|
||||
|
||||
refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
|
||||
assert html_response(public_page, 200) =~ "initial-results"
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /api*path", %{conn: conn} do
|
||||
assert conn
|
||||
|> get("/api/foo")
|
||||
|> json_response(404) == %{"error" => "Not implemented"}
|
||||
end
|
||||
|
||||
test "GET /pleroma/admin -> /pleroma/admin/", %{conn: conn} do
|
||||
assert redirected_to(get(conn, "/pleroma/admin")) =~ "/pleroma/admin/"
|
||||
end
|
||||
|
||||
test "OPTIONS /*path", %{conn: conn} do
|
||||
assert conn
|
||||
|> options("/foo")
|
||||
|> response(204) == ""
|
||||
|
||||
assert conn
|
||||
|> options("/foo/bar")
|
||||
|> response(204) == ""
|
||||
end
|
||||
end
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.FederatorTest do
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Workers.PublisherWorker
|
||||
|
||||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
setup_all do: clear_config([:instance, :federating], true)
|
||||
setup do: clear_config([:instance, :allow_relay])
|
||||
setup do: clear_config([:mrf, :policies])
|
||||
setup do: clear_config([:mrf_keyword])
|
||||
|
||||
describe "Publish an activity" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "HI"})
|
||||
|
||||
relay_mock = {
|
||||
Pleroma.Web.ActivityPub.Relay,
|
||||
[],
|
||||
[publish: fn _activity -> send(self(), :relay_publish) end]
|
||||
}
|
||||
|
||||
%{activity: activity, relay_mock: relay_mock}
|
||||
end
|
||||
|
||||
test "with relays active, it publishes to the relay", %{
|
||||
activity: activity,
|
||||
relay_mock: relay_mock
|
||||
} do
|
||||
with_mocks([relay_mock]) do
|
||||
Federator.publish(activity)
|
||||
ObanHelpers.perform(all_enqueued(worker: PublisherWorker))
|
||||
end
|
||||
|
||||
assert_received :relay_publish
|
||||
end
|
||||
|
||||
test "with relays deactivated, it does not publish to the relay", %{
|
||||
activity: activity,
|
||||
relay_mock: relay_mock
|
||||
} do
|
||||
Pleroma.Config.put([:instance, :allow_relay], false)
|
||||
|
||||
with_mocks([relay_mock]) do
|
||||
Federator.publish(activity)
|
||||
ObanHelpers.perform(all_enqueued(worker: PublisherWorker))
|
||||
end
|
||||
|
||||
refute_received :relay_publish
|
||||
end
|
||||
end
|
||||
|
||||
describe "Targets reachability filtering in `publish`" do
|
||||
test "it federates only to reachable instances via AP" do
|
||||
user = insert(:user)
|
||||
|
||||
{inbox1, inbox2} =
|
||||
{"https://domain.com/users/nick1/inbox", "https://domain2.com/users/nick2/inbox"}
|
||||
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "nick1@domain.com",
|
||||
ap_id: "https://domain.com/users/nick1",
|
||||
inbox: inbox1,
|
||||
ap_enabled: true
|
||||
})
|
||||
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "nick2@domain2.com",
|
||||
ap_id: "https://domain2.com/users/nick2",
|
||||
inbox: inbox2,
|
||||
ap_enabled: true
|
||||
})
|
||||
|
||||
dt = NaiveDateTime.utc_now()
|
||||
Instances.set_unreachable(inbox1, dt)
|
||||
|
||||
Instances.set_consistently_unreachable(URI.parse(inbox2).host)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{status: "HI @nick1@domain.com, @nick2@domain2.com!"})
|
||||
|
||||
expected_dt = NaiveDateTime.to_iso8601(dt)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: PublisherWorker))
|
||||
|
||||
assert ObanHelpers.member?(
|
||||
%{
|
||||
"op" => "publish_one",
|
||||
"params" => %{"inbox" => inbox1, "unreachable_since" => expected_dt}
|
||||
},
|
||||
all_enqueued(worker: PublisherWorker)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Receive an activity" do
|
||||
test "successfully processes incoming AP docs with correct origin" do
|
||||
params = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"actor" => "http://mastodon.example.org/users/admin",
|
||||
"type" => "Create",
|
||||
"id" => "http://mastodon.example.org/users/admin/activities/1",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "hi world!",
|
||||
"id" => "http://mastodon.example.org/users/admin/objects/1",
|
||||
"attributedTo" => "http://mastodon.example.org/users/admin"
|
||||
},
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
|
||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||
assert {:ok, _activity} = ObanHelpers.perform(job)
|
||||
|
||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||
assert {:error, :already_present} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
test "rejects incoming AP docs with incorrect origin" do
|
||||
params = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"actor" => "https://niu.moe/users/rye",
|
||||
"type" => "Create",
|
||||
"id" => "http://mastodon.example.org/users/admin/activities/1",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "hi world!",
|
||||
"id" => "http://mastodon.example.org/users/admin/objects/1",
|
||||
"attributedTo" => "http://mastodon.example.org/users/admin"
|
||||
},
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
|
||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||
assert {:error, :origin_containment_failed} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
test "it does not crash if MRF rejects the post" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["lain"])
|
||||
|
||||
Pleroma.Config.put(
|
||||
[:mrf, :policies],
|
||||
Pleroma.Web.ActivityPub.MRF.KeywordPolicy
|
||||
)
|
||||
|
||||
params =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||
assert {:error, _} = ObanHelpers.perform(job)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Feed.TagControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
import SweetXml
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.Feed.FeedView
|
||||
|
||||
setup do: clear_config([:feed])
|
||||
|
||||
test "gets a feed (ATOM)", %{conn: conn} do
|
||||
Pleroma.Config.put(
|
||||
[:feed, :post_title],
|
||||
%{max_length: 25, omission: "..."}
|
||||
)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"})
|
||||
|
||||
object = Object.normalize(activity1)
|
||||
|
||||
object_data =
|
||||
Map.put(object.data, "attachment", [
|
||||
%{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
object
|
||||
|> Ecto.Changeset.change(data: object_data)
|
||||
|> Pleroma.Repo.update()
|
||||
|
||||
{:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"})
|
||||
|
||||
{:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(tag_feed_path(conn, :feed, "pleromaart.atom"))
|
||||
|> response(200)
|
||||
|
||||
xml = parse(response)
|
||||
|
||||
assert xpath(xml, ~x"//feed/title/text()") == '#pleromaart'
|
||||
|
||||
assert xpath(xml, ~x"//feed/entry/title/text()"l) == [
|
||||
'42 This is :moominmamm...',
|
||||
'yeah #PleromaArt'
|
||||
]
|
||||
|
||||
assert xpath(xml, ~x"//feed/entry/author/name/text()"ls) == [user.nickname, user.nickname]
|
||||
assert xpath(xml, ~x"//feed/entry/author/id/text()"ls) == [user.ap_id, user.ap_id]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get("/tags/pleromaart.atom", %{"max_id" => activity2.id})
|
||||
|
||||
assert get_resp_header(conn, "content-type") == ["application/atom+xml; charset=utf-8"]
|
||||
resp = response(conn, 200)
|
||||
xml = parse(resp)
|
||||
|
||||
assert xpath(xml, ~x"//feed/title/text()") == '#pleromaart'
|
||||
|
||||
assert xpath(xml, ~x"//feed/entry/title/text()"l) == [
|
||||
'yeah #PleromaArt'
|
||||
]
|
||||
end
|
||||
|
||||
test "gets a feed (RSS)", %{conn: conn} do
|
||||
Pleroma.Config.put(
|
||||
[:feed, :post_title],
|
||||
%{max_length: 25, omission: "..."}
|
||||
)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"})
|
||||
|
||||
object = Object.normalize(activity1)
|
||||
|
||||
object_data =
|
||||
Map.put(object.data, "attachment", [
|
||||
%{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
object
|
||||
|> Ecto.Changeset.change(data: object_data)
|
||||
|> Pleroma.Repo.update()
|
||||
|
||||
{:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"})
|
||||
|
||||
{:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|
||||
|> response(200)
|
||||
|
||||
xml = parse(response)
|
||||
assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart'
|
||||
|
||||
assert xpath(xml, ~x"//channel/description/text()"s) ==
|
||||
"These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse."
|
||||
|
||||
assert xpath(xml, ~x"//channel/link/text()") ==
|
||||
'#{Pleroma.Web.base_url()}/tags/pleromaart.rss'
|
||||
|
||||
assert xpath(xml, ~x"//channel/webfeeds:logo/text()") ==
|
||||
'#{Pleroma.Web.base_url()}/static/logo.png'
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
|
||||
'42 This is :moominmamm...',
|
||||
'yeah #PleromaArt'
|
||||
]
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/pubDate/text()"sl) == [
|
||||
FeedView.pub_date(activity2.data["published"]),
|
||||
FeedView.pub_date(activity1.data["published"])
|
||||
]
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/enclosure/@url"sl) == [
|
||||
"https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4"
|
||||
]
|
||||
|
||||
obj1 = Object.normalize(activity1)
|
||||
obj2 = Object.normalize(activity2)
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/description/text()"sl) == [
|
||||
HtmlEntities.decode(FeedView.activity_content(obj2.data)),
|
||||
HtmlEntities.decode(FeedView.activity_content(obj1.data))
|
||||
]
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get(tag_feed_path(conn, :feed, "pleromaart"))
|
||||
|> response(200)
|
||||
|
||||
xml = parse(response)
|
||||
assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart'
|
||||
|
||||
assert xpath(xml, ~x"//channel/description/text()"s) ==
|
||||
"These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse."
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get("/tags/pleromaart.rss", %{"max_id" => activity2.id})
|
||||
|
||||
assert get_resp_header(conn, "content-type") == ["application/rss+xml; charset=utf-8"]
|
||||
resp = response(conn, 200)
|
||||
xml = parse(resp)
|
||||
|
||||
assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart'
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
|
||||
'yeah #PleromaArt'
|
||||
]
|
||||
end
|
||||
|
||||
describe "private instance" do
|
||||
setup do: clear_config([:instance, :public])
|
||||
|
||||
test "returns 404 for tags feed", %{conn: conn} do
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get(tag_feed_path(conn, :feed, "pleromaart"))
|
||||
|> response(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,265 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Feed.UserControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
import SweetXml
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
setup do: clear_config([:instance, :federating], true)
|
||||
|
||||
describe "feed" do
|
||||
setup do: clear_config([:feed])
|
||||
|
||||
test "gets an atom feed", %{conn: conn} do
|
||||
Config.put(
|
||||
[:feed, :post_title],
|
||||
%{max_length: 10, omission: "..."}
|
||||
)
|
||||
|
||||
activity = insert(:note_activity)
|
||||
|
||||
note =
|
||||
insert(:note,
|
||||
data: %{
|
||||
"content" => "This is :moominmamma: note ",
|
||||
"attachment" => [
|
||||
%{
|
||||
"url" => [
|
||||
%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inReplyTo" => activity.data["id"]
|
||||
}
|
||||
)
|
||||
|
||||
note_activity = insert(:note_activity, note: note)
|
||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
note2 =
|
||||
insert(:note,
|
||||
user: user,
|
||||
data: %{
|
||||
"content" => "42 This is :moominmamma: note ",
|
||||
"inReplyTo" => activity.data["id"]
|
||||
}
|
||||
)
|
||||
|
||||
note_activity2 = insert(:note_activity, note: note2)
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||
|> response(200)
|
||||
|
||||
activity_titles =
|
||||
resp
|
||||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|
||||
assert activity_titles == ['42 This...', 'This is...']
|
||||
assert resp =~ object.data["content"]
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get("/users/#{user.nickname}/feed", %{"max_id" => note_activity2.id})
|
||||
|> response(200)
|
||||
|
||||
activity_titles =
|
||||
resp
|
||||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|
||||
assert activity_titles == ['This is...']
|
||||
end
|
||||
|
||||
test "gets a rss feed", %{conn: conn} do
|
||||
Pleroma.Config.put(
|
||||
[:feed, :post_title],
|
||||
%{max_length: 10, omission: "..."}
|
||||
)
|
||||
|
||||
activity = insert(:note_activity)
|
||||
|
||||
note =
|
||||
insert(:note,
|
||||
data: %{
|
||||
"content" => "This is :moominmamma: note ",
|
||||
"attachment" => [
|
||||
%{
|
||||
"url" => [
|
||||
%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"inReplyTo" => activity.data["id"]
|
||||
}
|
||||
)
|
||||
|
||||
note_activity = insert(:note_activity, note: note)
|
||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
note2 =
|
||||
insert(:note,
|
||||
user: user,
|
||||
data: %{
|
||||
"content" => "42 This is :moominmamma: note ",
|
||||
"inReplyTo" => activity.data["id"]
|
||||
}
|
||||
)
|
||||
|
||||
note_activity2 = insert(:note_activity, note: note2)
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get("/users/#{user.nickname}/feed.rss")
|
||||
|> response(200)
|
||||
|
||||
activity_titles =
|
||||
resp
|
||||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//item/title/text()"l)
|
||||
|
||||
assert activity_titles == ['42 This...', 'This is...']
|
||||
assert resp =~ object.data["content"]
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get("/users/#{user.nickname}/feed.rss", %{"max_id" => note_activity2.id})
|
||||
|> response(200)
|
||||
|
||||
activity_titles =
|
||||
resp
|
||||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//item/title/text()"l)
|
||||
|
||||
assert activity_titles == ['This is...']
|
||||
end
|
||||
|
||||
test "returns 404 for a missing feed", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(user_feed_path(conn, :feed, "nonexisting"))
|
||||
|
||||
assert response(conn, 404)
|
||||
end
|
||||
|
||||
test "returns feed with public and unlisted activities", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "public", visibility: "public"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "direct", visibility: "direct"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "unlisted", visibility: "unlisted"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "private", visibility: "private"})
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||
|> response(200)
|
||||
|
||||
activity_titles =
|
||||
resp
|
||||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|> Enum.sort()
|
||||
|
||||
assert activity_titles == ['public', 'unlisted']
|
||||
end
|
||||
|
||||
test "returns 404 when the user is remote", %{conn: conn} do
|
||||
user = insert(:user, local: false)
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "test"})
|
||||
|
||||
assert conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||
|> response(404)
|
||||
end
|
||||
end
|
||||
|
||||
# Note: see ActivityPubControllerTest for JSON format tests
|
||||
describe "feed_redirect" do
|
||||
test "with html format, it redirects to user feed", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/users/#{user.nickname}")
|
||||
|> response(200)
|
||||
|
||||
assert response ==
|
||||
Fallback.RedirectController.redirector_with_meta(
|
||||
conn,
|
||||
%{user: user}
|
||||
).resp_body
|
||||
end
|
||||
|
||||
test "with html format, it returns error when user is not found", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> get("/users/jimm")
|
||||
|> json_response(404)
|
||||
|
||||
assert response == %{"error" => "Not found"}
|
||||
end
|
||||
|
||||
test "with non-html / non-json format, it redirects to user feed in atom format", %{
|
||||
conn: conn
|
||||
} do
|
||||
note_activity = insert(:note_activity)
|
||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/xml")
|
||||
|> get("/users/#{user.nickname}")
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == "#{Pleroma.Web.base_url()}/users/#{user.nickname}/feed.atom"
|
||||
end
|
||||
|
||||
test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/xml")
|
||||
|> get(user_feed_path(conn, :feed, "jimm"))
|
||||
|> response(404)
|
||||
|
||||
assert response == ~S({"error":"Not found"})
|
||||
end
|
||||
end
|
||||
|
||||
describe "private instance" do
|
||||
setup do: clear_config([:instance, :public])
|
||||
|
||||
test "returns 404 for user feed", %{conn: conn} do
|
||||
Config.put([:instance, :public], false)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "test"})
|
||||
|
||||
assert conn
|
||||
|> put_req_header("accept", "application/atom+xml")
|
||||
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||
|> response(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Instances.InstanceTest do
|
||||
alias Pleroma.Instances.Instance
|
||||
alias Pleroma.Repo
|
||||
|
||||
use Pleroma.DataCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do: clear_config([:instance, :federation_reachability_timeout_days], 1)
|
||||
|
||||
describe "set_reachable/1" do
|
||||
test "clears `unreachable_since` of existing matching Instance record having non-nil `unreachable_since`" do
|
||||
unreachable_since = NaiveDateTime.to_iso8601(NaiveDateTime.utc_now())
|
||||
instance = insert(:instance, unreachable_since: unreachable_since)
|
||||
|
||||
assert {:ok, instance} = Instance.set_reachable(instance.host)
|
||||
refute instance.unreachable_since
|
||||
end
|
||||
|
||||
test "keeps nil `unreachable_since` of existing matching Instance record having nil `unreachable_since`" do
|
||||
instance = insert(:instance, unreachable_since: nil)
|
||||
|
||||
assert {:ok, instance} = Instance.set_reachable(instance.host)
|
||||
refute instance.unreachable_since
|
||||
end
|
||||
|
||||
test "does NOT create an Instance record in case of no existing matching record" do
|
||||
host = "domain.org"
|
||||
assert nil == Instance.set_reachable(host)
|
||||
|
||||
assert [] = Repo.all(Ecto.Query.from(i in Instance))
|
||||
assert Instance.reachable?(host)
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_unreachable/1" do
|
||||
test "creates new record having `unreachable_since` to current time if record does not exist" do
|
||||
assert {:ok, instance} = Instance.set_unreachable("https://domain.com/path")
|
||||
|
||||
instance = Repo.get(Instance, instance.id)
|
||||
assert instance.unreachable_since
|
||||
assert "domain.com" == instance.host
|
||||
end
|
||||
|
||||
test "sets `unreachable_since` of existing record having nil `unreachable_since`" do
|
||||
instance = insert(:instance, unreachable_since: nil)
|
||||
refute instance.unreachable_since
|
||||
|
||||
assert {:ok, _} = Instance.set_unreachable(instance.host)
|
||||
|
||||
instance = Repo.get(Instance, instance.id)
|
||||
assert instance.unreachable_since
|
||||
end
|
||||
|
||||
test "does NOT modify `unreachable_since` value of existing record in case it's present" do
|
||||
instance =
|
||||
insert(:instance, unreachable_since: NaiveDateTime.add(NaiveDateTime.utc_now(), -10))
|
||||
|
||||
assert instance.unreachable_since
|
||||
initial_value = instance.unreachable_since
|
||||
|
||||
assert {:ok, _} = Instance.set_unreachable(instance.host)
|
||||
|
||||
instance = Repo.get(Instance, instance.id)
|
||||
assert initial_value == instance.unreachable_since
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_unreachable/2" do
|
||||
test "sets `unreachable_since` value of existing record in case it's newer than supplied value" do
|
||||
instance =
|
||||
insert(:instance, unreachable_since: NaiveDateTime.add(NaiveDateTime.utc_now(), -10))
|
||||
|
||||
assert instance.unreachable_since
|
||||
|
||||
past_value = NaiveDateTime.add(NaiveDateTime.utc_now(), -100)
|
||||
assert {:ok, _} = Instance.set_unreachable(instance.host, past_value)
|
||||
|
||||
instance = Repo.get(Instance, instance.id)
|
||||
assert past_value == instance.unreachable_since
|
||||
end
|
||||
|
||||
test "does NOT modify `unreachable_since` value of existing record in case it's equal to or older than supplied value" do
|
||||
instance =
|
||||
insert(:instance, unreachable_since: NaiveDateTime.add(NaiveDateTime.utc_now(), -10))
|
||||
|
||||
assert instance.unreachable_since
|
||||
initial_value = instance.unreachable_since
|
||||
|
||||
assert {:ok, _} = Instance.set_unreachable(instance.host, NaiveDateTime.utc_now())
|
||||
|
||||
instance = Repo.get(Instance, instance.id)
|
||||
assert initial_value == instance.unreachable_since
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_or_update_favicon/1" do
|
||||
test "Scrapes favicon URLs" do
|
||||
Tesla.Mock.mock(fn %{url: "https://favicon.example.org/"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: ~s[<html><head><link rel="icon" href="/favicon.png"></head></html>]
|
||||
}
|
||||
end)
|
||||
|
||||
assert "https://favicon.example.org/favicon.png" ==
|
||||
Instance.get_or_update_favicon(URI.parse("https://favicon.example.org/"))
|
||||
end
|
||||
|
||||
test "Returns nil on too long favicon URLs" do
|
||||
long_favicon_url =
|
||||
"https://Lorem.ipsum.dolor.sit.amet/consecteturadipiscingelit/Praesentpharetrapurusutaliquamtempus/Mauriseulaoreetarcu/atfacilisisorci/Nullamporttitor/nequesedfeugiatmollis/dolormagnaefficiturlorem/nonpretiumsapienorcieurisus/Nullamveleratsem/Maecenassedaccumsanexnam/favicon.png"
|
||||
|
||||
Tesla.Mock.mock(fn %{url: "https://long-favicon.example.org/"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
~s[<html><head><link rel="icon" href="] <> long_favicon_url <> ~s["></head></html>]
|
||||
}
|
||||
end)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert nil ==
|
||||
Instance.get_or_update_favicon(
|
||||
URI.parse("https://long-favicon.example.org/")
|
||||
)
|
||||
end) =~
|
||||
"Instance.get_or_update_favicon(\"long-favicon.example.org\") error: %Postgrex.Error{"
|
||||
end
|
||||
|
||||
test "Handles not getting a favicon URL properly" do
|
||||
Tesla.Mock.mock(fn %{url: "https://no-favicon.example.org/"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: ~s[<html><head><h1>I wil look down and whisper "GNO.."</h1></head></html>]
|
||||
}
|
||||
end)
|
||||
|
||||
refute capture_log(fn ->
|
||||
assert nil ==
|
||||
Instance.get_or_update_favicon(
|
||||
URI.parse("https://no-favicon.example.org/")
|
||||
)
|
||||
end) =~ "Instance.scrape_favicon(\"https://no-favicon.example.org/\") error: "
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.InstancesTest do
|
||||
alias Pleroma.Instances
|
||||
|
||||
use Pleroma.DataCase
|
||||
|
||||
setup_all do: clear_config([:instance, :federation_reachability_timeout_days], 1)
|
||||
|
||||
describe "reachable?/1" do
|
||||
test "returns `true` for host / url with unknown reachability status" do
|
||||
assert Instances.reachable?("unknown.site")
|
||||
assert Instances.reachable?("http://unknown.site")
|
||||
end
|
||||
|
||||
test "returns `false` for host / url marked unreachable for at least `reachability_datetime_threshold()`" do
|
||||
host = "consistently-unreachable.name"
|
||||
Instances.set_consistently_unreachable(host)
|
||||
|
||||
refute Instances.reachable?(host)
|
||||
refute Instances.reachable?("http://#{host}/path")
|
||||
end
|
||||
|
||||
test "returns `true` for host / url marked unreachable for less than `reachability_datetime_threshold()`" do
|
||||
url = "http://eventually-unreachable.name/path"
|
||||
|
||||
Instances.set_unreachable(url)
|
||||
|
||||
assert Instances.reachable?(url)
|
||||
assert Instances.reachable?(URI.parse(url).host)
|
||||
end
|
||||
|
||||
test "returns true on non-binary input" do
|
||||
assert Instances.reachable?(nil)
|
||||
assert Instances.reachable?(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "filter_reachable/1" do
|
||||
setup do
|
||||
host = "consistently-unreachable.name"
|
||||
url1 = "http://eventually-unreachable.com/path"
|
||||
url2 = "http://domain.com/path"
|
||||
|
||||
Instances.set_consistently_unreachable(host)
|
||||
Instances.set_unreachable(url1)
|
||||
|
||||
result = Instances.filter_reachable([host, url1, url2, nil])
|
||||
%{result: result, url1: url1, url2: url2}
|
||||
end
|
||||
|
||||
test "returns a map with keys containing 'not marked consistently unreachable' elements of supplied list",
|
||||
%{result: result, url1: url1, url2: url2} do
|
||||
assert is_map(result)
|
||||
assert Enum.sort([url1, url2]) == result |> Map.keys() |> Enum.sort()
|
||||
end
|
||||
|
||||
test "returns a map with `unreachable_since` values for keys",
|
||||
%{result: result, url1: url1, url2: url2} do
|
||||
assert is_map(result)
|
||||
assert %NaiveDateTime{} = result[url1]
|
||||
assert is_nil(result[url2])
|
||||
end
|
||||
|
||||
test "returns an empty map for empty list or list containing no hosts / url" do
|
||||
assert %{} == Instances.filter_reachable([])
|
||||
assert %{} == Instances.filter_reachable([nil])
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_reachable/1" do
|
||||
test "sets unreachable url or host reachable" do
|
||||
host = "domain.com"
|
||||
Instances.set_consistently_unreachable(host)
|
||||
refute Instances.reachable?(host)
|
||||
|
||||
Instances.set_reachable(host)
|
||||
assert Instances.reachable?(host)
|
||||
end
|
||||
|
||||
test "keeps reachable url or host reachable" do
|
||||
url = "https://site.name?q="
|
||||
assert Instances.reachable?(url)
|
||||
|
||||
Instances.set_reachable(url)
|
||||
assert Instances.reachable?(url)
|
||||
end
|
||||
|
||||
test "returns error status on non-binary input" do
|
||||
assert {:error, _} = Instances.set_reachable(nil)
|
||||
assert {:error, _} = Instances.set_reachable(1)
|
||||
end
|
||||
end
|
||||
|
||||
# Note: implementation-specific (e.g. Instance) details of set_unreachable/1
|
||||
# should be tested in implementation-specific tests
|
||||
describe "set_unreachable/1" do
|
||||
test "returns error status on non-binary input" do
|
||||
assert {:error, _} = Instances.set_unreachable(nil)
|
||||
assert {:error, _} = Instances.set_unreachable(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_consistently_unreachable/1" do
|
||||
test "sets reachable url or host unreachable" do
|
||||
url = "http://domain.com?q="
|
||||
assert Instances.reachable?(url)
|
||||
|
||||
Instances.set_consistently_unreachable(url)
|
||||
refute Instances.reachable?(url)
|
||||
end
|
||||
|
||||
test "keeps unreachable url or host unreachable" do
|
||||
host = "site.name"
|
||||
Instances.set_consistently_unreachable(host)
|
||||
refute Instances.reachable?(host)
|
||||
|
||||
Instances.set_consistently_unreachable(host)
|
||||
refute Instances.reachable?(host)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MastoFEController do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.User
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: clear_config([:instance, :public])
|
||||
|
||||
test "put settings", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, insert(:oauth_token, user: user, scopes: ["write:accounts"]))
|
||||
|> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
|
||||
|
||||
assert _result = json_response(conn, 200)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
assert user.mastofe_settings == %{"programming" => "socks"}
|
||||
end
|
||||
|
||||
describe "index/2 redirections" do
|
||||
setup %{conn: conn} do
|
||||
session_opts = [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(session_opts))
|
||||
|> fetch_session()
|
||||
|
||||
test_path = "/web/statuses/test"
|
||||
%{conn: conn, path: test_path}
|
||||
end
|
||||
|
||||
test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
|
||||
conn = get(conn, path)
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == "/web/login"
|
||||
end
|
||||
|
||||
test "redirects not logged-in users to the login page on private instances", %{
|
||||
conn: conn,
|
||||
path: path
|
||||
} do
|
||||
Config.put([:instance, :public], false)
|
||||
|
||||
conn = get(conn, path)
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == "/web/login"
|
||||
end
|
||||
|
||||
test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
|
||||
token = insert(:oauth_token, scopes: ["read"])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, token.user)
|
||||
|> assign(:token, token)
|
||||
|> get(path)
|
||||
|
||||
assert conn.status == 200
|
||||
end
|
||||
|
||||
test "saves referer path to session", %{conn: conn, path: path} do
|
||||
conn = get(conn, path)
|
||||
return_to = Plug.Conn.get_session(conn, :return_to)
|
||||
|
||||
assert return_to == path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,529 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: clear_config([:instance, :max_account_fields])
|
||||
|
||||
describe "updating credentials" do
|
||||
setup do: oauth_access(["write:accounts"])
|
||||
setup :request_content_type
|
||||
|
||||
test "sets user settings in a generic way", %{conn: conn} do
|
||||
res_conn =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_settings_store" => %{
|
||||
pleroma_fe: %{
|
||||
theme: "bla"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(res_conn, 200)
|
||||
assert user_data["pleroma"]["settings_store"] == %{"pleroma_fe" => %{"theme" => "bla"}}
|
||||
|
||||
user = Repo.get(User, user_data["id"])
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_settings_store" => %{
|
||||
masto_fe: %{
|
||||
theme: "bla"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(res_conn, 200)
|
||||
|
||||
assert user_data["pleroma"]["settings_store"] ==
|
||||
%{
|
||||
"pleroma_fe" => %{"theme" => "bla"},
|
||||
"masto_fe" => %{"theme" => "bla"}
|
||||
}
|
||||
|
||||
user = Repo.get(User, user_data["id"])
|
||||
|
||||
clear_config([:instance, :federating], true)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _activity -> :ok end do
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_settings_store" => %{
|
||||
masto_fe: %{
|
||||
theme: "blub"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(res_conn, 200)
|
||||
|
||||
assert user_data["pleroma"]["settings_store"] ==
|
||||
%{
|
||||
"pleroma_fe" => %{"theme" => "bla"},
|
||||
"masto_fe" => %{"theme" => "blub"}
|
||||
}
|
||||
|
||||
assert_called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
end
|
||||
|
||||
test "updates the user's bio", %{conn: conn} do
|
||||
user2 = insert(:user)
|
||||
|
||||
raw_bio = "I drink #cofe with @#{user2.nickname}\n\nsuya.."
|
||||
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{"note" => raw_bio})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
assert user_data["note"] ==
|
||||
~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{
|
||||
user2.id
|
||||
}" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..)
|
||||
|
||||
assert user_data["source"]["note"] == raw_bio
|
||||
|
||||
user = Repo.get(User, user_data["id"])
|
||||
|
||||
assert user.raw_bio == raw_bio
|
||||
end
|
||||
|
||||
test "updates the user's locking status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{locked: "true"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["locked"] == true
|
||||
end
|
||||
|
||||
test "updates the user's chat acceptance status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{accepts_chat_messages: "false"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["pleroma"]["accepts_chat_messages"] == false
|
||||
end
|
||||
|
||||
test "updates the user's allow_following_move", %{user: user, conn: conn} do
|
||||
assert user.allow_following_move == true
|
||||
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{allow_following_move: "false"})
|
||||
|
||||
assert refresh_record(user).allow_following_move == false
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["pleroma"]["allow_following_move"] == false
|
||||
end
|
||||
|
||||
test "updates the user's default scope", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{default_scope: "unlisted"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["source"]["privacy"] == "unlisted"
|
||||
end
|
||||
|
||||
test "updates the user's privacy", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{source: %{privacy: "unlisted"}})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["source"]["privacy"] == "unlisted"
|
||||
end
|
||||
|
||||
test "updates the user's hide_followers status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_followers: "true"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["pleroma"]["hide_followers"] == true
|
||||
end
|
||||
|
||||
test "updates the user's discoverable status", %{conn: conn} do
|
||||
assert %{"source" => %{"pleroma" => %{"discoverable" => true}}} =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{discoverable: "true"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"source" => %{"pleroma" => %{"discoverable" => false}}} =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{discoverable: "false"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "updates the user's hide_followers_count and hide_follows_count", %{conn: conn} do
|
||||
conn =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
hide_followers_count: "true",
|
||||
hide_follows_count: "true"
|
||||
})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["pleroma"]["hide_followers_count"] == true
|
||||
assert user_data["pleroma"]["hide_follows_count"] == true
|
||||
end
|
||||
|
||||
test "updates the user's skip_thread_containment option", %{user: user, conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{skip_thread_containment: "true"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["pleroma"]["skip_thread_containment"] == true
|
||||
assert refresh_record(user).skip_thread_containment
|
||||
end
|
||||
|
||||
test "updates the user's hide_follows status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_follows: "true"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["pleroma"]["hide_follows"] == true
|
||||
end
|
||||
|
||||
test "updates the user's hide_favorites status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_favorites: "true"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["pleroma"]["hide_favorites"] == true
|
||||
end
|
||||
|
||||
test "updates the user's show_role status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{show_role: "false"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["source"]["pleroma"]["show_role"] == false
|
||||
end
|
||||
|
||||
test "updates the user's no_rich_text status", %{conn: conn} do
|
||||
conn = patch(conn, "/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["source"]["pleroma"]["no_rich_text"] == true
|
||||
end
|
||||
|
||||
test "updates the user's name", %{conn: conn} do
|
||||
conn =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
assert user_data["display_name"] == "markorepairs"
|
||||
|
||||
update_activity = Repo.one(Pleroma.Activity)
|
||||
assert update_activity.data["type"] == "Update"
|
||||
assert update_activity.data["object"]["name"] == "markorepairs"
|
||||
end
|
||||
|
||||
test "updates the user's avatar", %{user: user, conn: conn} do
|
||||
new_avatar = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.avatar == %{}
|
||||
|
||||
res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
|
||||
|
||||
assert user_response = json_response_and_validate_schema(res, 200)
|
||||
assert user_response["avatar"] != User.avatar_url(user)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
refute user.avatar == %{}
|
||||
|
||||
# Also resets it
|
||||
_res = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => ""})
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.avatar == nil
|
||||
end
|
||||
|
||||
test "updates the user's banner", %{user: user, conn: conn} do
|
||||
new_header = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
|
||||
|
||||
assert user_response = json_response_and_validate_schema(res, 200)
|
||||
assert user_response["header"] != User.banner_url(user)
|
||||
|
||||
# Also resets it
|
||||
_res = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => ""})
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.banner == nil
|
||||
end
|
||||
|
||||
test "updates the user's background", %{conn: conn, user: user} do
|
||||
new_header = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
res =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
"pleroma_background_image" => new_header
|
||||
})
|
||||
|
||||
assert user_response = json_response_and_validate_schema(res, 200)
|
||||
assert user_response["pleroma"]["background_image"]
|
||||
#
|
||||
# Also resets it
|
||||
_res =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{"pleroma_background_image" => ""})
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.background == nil
|
||||
end
|
||||
|
||||
test "requires 'write:accounts' permission" do
|
||||
token1 = insert(:oauth_token, scopes: ["read"])
|
||||
token2 = insert(:oauth_token, scopes: ["write", "follow"])
|
||||
|
||||
for token <- [token1, token2] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> put_req_header("authorization", "Bearer #{token.token}")
|
||||
|> patch("/api/v1/accounts/update_credentials", %{})
|
||||
|
||||
if token == token1 do
|
||||
assert %{"error" => "Insufficient permissions: write:accounts."} ==
|
||||
json_response_and_validate_schema(conn, 403)
|
||||
else
|
||||
assert json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "updates profile emojos", %{user: user, conn: conn} do
|
||||
note = "*sips :blank:*"
|
||||
name = "I am :firefox:"
|
||||
|
||||
ret_conn =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
"note" => note,
|
||||
"display_name" => name
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(ret_conn, 200)
|
||||
|
||||
conn = get(conn, "/api/v1/accounts/#{user.id}")
|
||||
|
||||
assert user_data = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
assert user_data["note"] == note
|
||||
assert user_data["display_name"] == name
|
||||
assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = user_data["emojis"]
|
||||
end
|
||||
|
||||
test "update fields", %{conn: conn} do
|
||||
fields = [
|
||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "<script>bar</script>"},
|
||||
%{"name" => "link.io", "value" => "cofe.io"}
|
||||
]
|
||||
|
||||
account_data =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert account_data["fields"] == [
|
||||
%{"name" => "<a href=\"http://google.com\">foo</a>", "value" => "bar"},
|
||||
%{
|
||||
"name" => "link.io",
|
||||
"value" => ~S(<a href="http://cofe.io" rel="ugc">cofe.io</a>)
|
||||
}
|
||||
]
|
||||
|
||||
assert account_data["source"]["fields"] == [
|
||||
%{
|
||||
"name" => "<a href=\"http://google.com\">foo</a>",
|
||||
"value" => "<script>bar</script>"
|
||||
},
|
||||
%{"name" => "link.io", "value" => "cofe.io"}
|
||||
]
|
||||
end
|
||||
|
||||
test "emojis in fields labels", %{conn: conn} do
|
||||
fields = [
|
||||
%{"name" => ":firefox:", "value" => "is best 2hu"},
|
||||
%{"name" => "they wins", "value" => ":blank:"}
|
||||
]
|
||||
|
||||
account_data =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert account_data["fields"] == [
|
||||
%{"name" => ":firefox:", "value" => "is best 2hu"},
|
||||
%{"name" => "they wins", "value" => ":blank:"}
|
||||
]
|
||||
|
||||
assert account_data["source"]["fields"] == [
|
||||
%{"name" => ":firefox:", "value" => "is best 2hu"},
|
||||
%{"name" => "they wins", "value" => ":blank:"}
|
||||
]
|
||||
|
||||
assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = account_data["emojis"]
|
||||
end
|
||||
|
||||
test "update fields via x-www-form-urlencoded", %{conn: conn} do
|
||||
fields =
|
||||
[
|
||||
"fields_attributes[1][name]=link",
|
||||
"fields_attributes[1][value]=http://cofe.io",
|
||||
"fields_attributes[0][name]=foo",
|
||||
"fields_attributes[0][value]=bar"
|
||||
]
|
||||
|> Enum.join("&")
|
||||
|
||||
account =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/x-www-form-urlencoded")
|
||||
|> patch("/api/v1/accounts/update_credentials", fields)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert account["fields"] == [
|
||||
%{"name" => "foo", "value" => "bar"},
|
||||
%{
|
||||
"name" => "link",
|
||||
"value" => ~S(<a href="http://cofe.io" rel="ugc">http://cofe.io</a>)
|
||||
}
|
||||
]
|
||||
|
||||
assert account["source"]["fields"] == [
|
||||
%{"name" => "foo", "value" => "bar"},
|
||||
%{"name" => "link", "value" => "http://cofe.io"}
|
||||
]
|
||||
end
|
||||
|
||||
test "update fields with empty name", %{conn: conn} do
|
||||
fields = [
|
||||
%{"name" => "foo", "value" => ""},
|
||||
%{"name" => "", "value" => "bar"}
|
||||
]
|
||||
|
||||
account =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert account["fields"] == [
|
||||
%{"name" => "foo", "value" => ""}
|
||||
]
|
||||
end
|
||||
|
||||
test "update fields when invalid request", %{conn: conn} do
|
||||
name_limit = Pleroma.Config.get([:instance, :account_field_name_length])
|
||||
value_limit = Pleroma.Config.get([:instance, :account_field_value_length])
|
||||
|
||||
long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join()
|
||||
long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join()
|
||||
|
||||
fields = [%{"name" => "foo", "value" => long_value}]
|
||||
|
||||
assert %{"error" => "Invalid request"} ==
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||
|> json_response_and_validate_schema(403)
|
||||
|
||||
fields = [%{"name" => long_name, "value" => "bar"}]
|
||||
|
||||
assert %{"error" => "Invalid request"} ==
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||
|> json_response_and_validate_schema(403)
|
||||
|
||||
Pleroma.Config.put([:instance, :max_account_fields], 1)
|
||||
|
||||
fields = [
|
||||
%{"name" => "foo", "value" => "bar"},
|
||||
%{"name" => "link", "value" => "cofe.io"}
|
||||
]
|
||||
|
||||
assert %{"error" => "Invalid request"} ==
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Mark account as bot" do
|
||||
setup do: oauth_access(["write:accounts"])
|
||||
setup :request_content_type
|
||||
|
||||
test "changing actor_type to Service makes account a bot", %{conn: conn} do
|
||||
account =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{actor_type: "Service"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert account["bot"]
|
||||
assert account["source"]["pleroma"]["actor_type"] == "Service"
|
||||
end
|
||||
|
||||
test "changing actor_type to Person makes account a human", %{conn: conn} do
|
||||
account =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{actor_type: "Person"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute account["bot"]
|
||||
assert account["source"]["pleroma"]["actor_type"] == "Person"
|
||||
end
|
||||
|
||||
test "changing actor_type to Application causes error", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{actor_type: "Application"})
|
||||
|> json_response_and_validate_schema(403)
|
||||
|
||||
assert %{"error" => "Invalid request"} == response
|
||||
end
|
||||
|
||||
test "changing bot field to true changes actor_type to Service", %{conn: conn} do
|
||||
account =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{bot: "true"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert account["bot"]
|
||||
assert account["source"]["pleroma"]["actor_type"] == "Service"
|
||||
end
|
||||
|
||||
test "changing bot field to false changes actor_type to Person", %{conn: conn} do
|
||||
account =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{bot: "false"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute account["bot"]
|
||||
assert account["source"]["pleroma"]["actor_type"] == "Person"
|
||||
end
|
||||
|
||||
test "actor_type field has a higher priority than bot", %{conn: conn} do
|
||||
account =
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
actor_type: "Person",
|
||||
bot: "true"
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute account["bot"]
|
||||
assert account["source"]["pleroma"]["actor_type"] == "Person"
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,60 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.AppControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.Push
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "apps/verify_credentials", %{conn: conn} do
|
||||
token = insert(:oauth_token)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("authorization", "Bearer #{token.token}")
|
||||
|> get("/api/v1/apps/verify_credentials")
|
||||
|
||||
app = Repo.preload(token, :app).app
|
||||
|
||||
expected = %{
|
||||
"name" => app.client_name,
|
||||
"website" => app.website,
|
||||
"vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
|
||||
}
|
||||
|
||||
assert expected == json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
test "creates an oauth app", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
app_attrs = build(:oauth_app)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> assign(:user, user)
|
||||
|> post("/api/v1/apps", %{
|
||||
client_name: app_attrs.client_name,
|
||||
redirect_uris: app_attrs.redirect_uris
|
||||
})
|
||||
|
||||
[app] = Repo.all(App)
|
||||
|
||||
expected = %{
|
||||
"name" => app.client_name,
|
||||
"website" => app.website,
|
||||
"client_id" => app.client_id,
|
||||
"client_secret" => app.client_secret,
|
||||
"id" => app.id |> to_string(),
|
||||
"redirect_uri" => app.redirect_uris,
|
||||
"vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
|
||||
}
|
||||
|
||||
assert expected == json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
|
||||
import Pleroma.Factory
|
||||
import Swoosh.TestAssertions
|
||||
|
||||
describe "GET /web/login" do
|
||||
setup %{conn: conn} do
|
||||
session_opts = [
|
||||
store: :cookie,
|
||||
key: "_test",
|
||||
signing_salt: "cooldude"
|
||||
]
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(session_opts))
|
||||
|> fetch_session()
|
||||
|
||||
test_path = "/web/statuses/test"
|
||||
%{conn: conn, path: test_path}
|
||||
end
|
||||
|
||||
test "redirects to the saved path after log in", %{conn: conn, path: path} do
|
||||
app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
|
||||
auth = insert(:oauth_authorization, app: app)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_session(:return_to, path)
|
||||
|> get("/web/login", %{code: auth.token})
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == path
|
||||
end
|
||||
|
||||
test "redirects to the getting-started page when referer is not present", %{conn: conn} do
|
||||
app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
|
||||
auth = insert(:oauth_authorization, app: app)
|
||||
|
||||
conn = get(conn, "/web/login", %{code: auth.token})
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == "/web/getting-started"
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /auth/password, with valid parameters" do
|
||||
setup %{conn: conn} do
|
||||
user = insert(:user)
|
||||
conn = post(conn, "/auth/password?email=#{user.email}")
|
||||
%{conn: conn, user: user}
|
||||
end
|
||||
|
||||
test "it returns 204", %{conn: conn} do
|
||||
assert empty_json_response(conn)
|
||||
end
|
||||
|
||||
test "it creates a PasswordResetToken record for user", %{user: user} do
|
||||
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
|
||||
assert token_record
|
||||
end
|
||||
|
||||
test "it sends an email to user", %{user: user} do
|
||||
ObanHelpers.perform_all()
|
||||
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
|
||||
|
||||
email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
|
||||
notify_email = Config.get([:instance, :notify_email])
|
||||
instance_name = Config.get([:instance, :name])
|
||||
|
||||
assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /auth/password, with nickname" do
|
||||
test "it returns 204", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
assert conn
|
||||
|> post("/auth/password?nickname=#{user.nickname}")
|
||||
|> empty_json_response()
|
||||
|
||||
ObanHelpers.perform_all()
|
||||
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
|
||||
|
||||
email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
|
||||
notify_email = Config.get([:instance, :notify_email])
|
||||
instance_name = Config.get([:instance, :name])
|
||||
|
||||
assert_email_sent(
|
||||
from: {instance_name, notify_email},
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
test "it doesn't fail when a user has no email", %{conn: conn} do
|
||||
user = insert(:user, %{email: nil})
|
||||
|
||||
assert conn
|
||||
|> post("/auth/password?nickname=#{user.nickname}")
|
||||
|> empty_json_response()
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /auth/password, with invalid parameters" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, user: user}
|
||||
end
|
||||
|
||||
test "it returns 204 when user is not found", %{conn: conn, user: user} do
|
||||
conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
|
||||
|
||||
assert empty_json_response(conn)
|
||||
end
|
||||
|
||||
test "it returns 204 when user is not local", %{conn: conn, user: user} do
|
||||
{:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false))
|
||||
conn = post(conn, "/auth/password?email=#{user.email}")
|
||||
|
||||
assert empty_json_response(conn)
|
||||
end
|
||||
|
||||
test "it returns 204 when user is deactivated", %{conn: conn, user: user} do
|
||||
{:ok, user} = Repo.update(Ecto.Changeset.change(user, deactivated: true, local: true))
|
||||
conn = post(conn, "/auth/password?email=#{user.email}")
|
||||
|
||||
assert empty_json_response(conn)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /auth/sign_out" do
|
||||
test "redirect to root page", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> delete("/auth/sign_out")
|
||||
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == "/"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,209 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: oauth_access(["read:statuses"])
|
||||
|
||||
describe "returns a list of conversations" do
|
||||
setup(%{user: user_one, conn: conn}) do
|
||||
user_two = insert(:user)
|
||||
user_three = insert(:user)
|
||||
|
||||
{:ok, user_two} = User.follow(user_two, user_one)
|
||||
|
||||
{:ok, %{user: user_one, user_two: user_two, user_three: user_three, conn: conn}}
|
||||
end
|
||||
|
||||
test "returns correct conversations", %{
|
||||
user: user_one,
|
||||
user_two: user_two,
|
||||
user_three: user_three,
|
||||
conn: conn
|
||||
} do
|
||||
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
|
||||
{:ok, direct} = create_direct_message(user_one, [user_two, user_three])
|
||||
|
||||
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
|
||||
|
||||
{:ok, _follower_only} =
|
||||
CommonAPI.post(user_one, %{
|
||||
status: "Hi @#{user_two.nickname}!",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
res_conn = get(conn, "/api/v1/conversations")
|
||||
|
||||
assert response = json_response_and_validate_schema(res_conn, 200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"id" => res_id,
|
||||
"accounts" => res_accounts,
|
||||
"last_status" => res_last_status,
|
||||
"unread" => unread
|
||||
}
|
||||
] = response
|
||||
|
||||
account_ids = Enum.map(res_accounts, & &1["id"])
|
||||
assert length(res_accounts) == 2
|
||||
assert user_two.id in account_ids
|
||||
assert user_three.id in account_ids
|
||||
assert is_binary(res_id)
|
||||
assert unread == false
|
||||
assert res_last_status["id"] == direct.id
|
||||
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
|
||||
end
|
||||
|
||||
test "observes limit params", %{
|
||||
user: user_one,
|
||||
user_two: user_two,
|
||||
user_three: user_three,
|
||||
conn: conn
|
||||
} do
|
||||
{:ok, _} = create_direct_message(user_one, [user_two, user_three])
|
||||
{:ok, _} = create_direct_message(user_two, [user_one, user_three])
|
||||
{:ok, _} = create_direct_message(user_three, [user_two, user_one])
|
||||
|
||||
res_conn = get(conn, "/api/v1/conversations?limit=1")
|
||||
|
||||
assert response = json_response_and_validate_schema(res_conn, 200)
|
||||
|
||||
assert Enum.count(response) == 1
|
||||
|
||||
res_conn = get(conn, "/api/v1/conversations?limit=2")
|
||||
|
||||
assert response = json_response_and_validate_schema(res_conn, 200)
|
||||
|
||||
assert Enum.count(response) == 2
|
||||
end
|
||||
end
|
||||
|
||||
test "filters conversations by recipients", %{user: user_one, conn: conn} do
|
||||
user_two = insert(:user)
|
||||
user_three = insert(:user)
|
||||
{:ok, direct1} = create_direct_message(user_one, [user_two])
|
||||
{:ok, _direct2} = create_direct_message(user_one, [user_three])
|
||||
{:ok, direct3} = create_direct_message(user_one, [user_two, user_three])
|
||||
{:ok, _direct4} = create_direct_message(user_two, [user_three])
|
||||
{:ok, direct5} = create_direct_message(user_two, [user_one])
|
||||
|
||||
assert [conversation1, conversation2] =
|
||||
conn
|
||||
|> get("/api/v1/conversations?recipients[]=#{user_two.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert conversation1["last_status"]["id"] == direct5.id
|
||||
assert conversation2["last_status"]["id"] == direct1.id
|
||||
|
||||
[conversation1] =
|
||||
conn
|
||||
|> get("/api/v1/conversations?recipients[]=#{user_two.id}&recipients[]=#{user_three.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert conversation1["last_status"]["id"] == direct3.id
|
||||
end
|
||||
|
||||
test "updates the last_status on reply", %{user: user_one, conn: conn} do
|
||||
user_two = insert(:user)
|
||||
{:ok, direct} = create_direct_message(user_one, [user_two])
|
||||
|
||||
{:ok, direct_reply} =
|
||||
CommonAPI.post(user_two, %{
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: direct.id
|
||||
})
|
||||
|
||||
[%{"last_status" => res_last_status}] =
|
||||
conn
|
||||
|> get("/api/v1/conversations")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert res_last_status["id"] == direct_reply.id
|
||||
end
|
||||
|
||||
test "the user marks a conversation as read", %{user: user_one, conn: conn} do
|
||||
user_two = insert(:user)
|
||||
{:ok, direct} = create_direct_message(user_one, [user_two])
|
||||
|
||||
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
|
||||
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1
|
||||
|
||||
user_two_conn =
|
||||
build_conn()
|
||||
|> assign(:user, user_two)
|
||||
|> assign(
|
||||
:token,
|
||||
insert(:oauth_token, user: user_two, scopes: ["read:statuses", "write:conversations"])
|
||||
)
|
||||
|
||||
[%{"id" => direct_conversation_id, "unread" => true}] =
|
||||
user_two_conn
|
||||
|> get("/api/v1/conversations")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
%{"unread" => false} =
|
||||
user_two_conn
|
||||
|> post("/api/v1/conversations/#{direct_conversation_id}/read")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0
|
||||
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
|
||||
|
||||
# The conversation is marked as unread on reply
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user_two, %{
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: direct.id
|
||||
})
|
||||
|
||||
[%{"unread" => true}] =
|
||||
conn
|
||||
|> get("/api/v1/conversations")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
|
||||
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
|
||||
|
||||
# A reply doesn't increment the user's unread_conversation_count if the conversation is unread
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user_two, %{
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: direct.id
|
||||
})
|
||||
|
||||
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
|
||||
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
|
||||
end
|
||||
|
||||
test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do
|
||||
user_two = insert(:user)
|
||||
{:ok, direct} = create_direct_message(user_one, [user_two])
|
||||
|
||||
res_conn = get(conn, "/api/v1/statuses/#{direct.id}/context")
|
||||
|
||||
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
|
||||
end
|
||||
|
||||
defp create_direct_message(sender, recips) do
|
||||
hellos =
|
||||
recips
|
||||
|> Enum.map(fn s -> "@#{s.nickname}" end)
|
||||
|> Enum.join(", ")
|
||||
|
||||
CommonAPI.post(sender, %{
|
||||
status: "Hi #{hellos}!",
|
||||
visibility: "direct"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
test "with tags", %{conn: conn} do
|
||||
assert resp =
|
||||
conn
|
||||
|> get("/api/v1/custom_emojis")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [emoji | _body] = resp
|
||||
assert Map.has_key?(emoji, "shortcode")
|
||||
assert Map.has_key?(emoji, "static_url")
|
||||
assert Map.has_key?(emoji, "tags")
|
||||
assert is_list(emoji["tags"])
|
||||
assert Map.has_key?(emoji, "category")
|
||||
assert Map.has_key?(emoji, "url")
|
||||
assert Map.has_key?(emoji, "visible_in_picker")
|
||||
end
|
||||
end
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.User
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "blocking / unblocking a domain" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:blocks"])
|
||||
other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
|
||||
|
||||
assert %{} == json_response_and_validate_schema(ret_conn, 200)
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
assert User.blocks?(user, other_user)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
|
||||
|
||||
assert %{} == json_response_and_validate_schema(ret_conn, 200)
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
refute User.blocks?(user, other_user)
|
||||
end
|
||||
|
||||
test "blocking a domain via query params" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:blocks"])
|
||||
other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/domain_blocks?domain=dogwhistle.zone")
|
||||
|
||||
assert %{} == json_response_and_validate_schema(ret_conn, 200)
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
assert User.blocks?(user, other_user)
|
||||
end
|
||||
|
||||
test "unblocking a domain via query params" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:blocks"])
|
||||
other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
|
||||
|
||||
User.block_domain(user, "dogwhistle.zone")
|
||||
user = refresh_record(user)
|
||||
assert User.blocks?(user, other_user)
|
||||
|
||||
ret_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> delete("/api/v1/domain_blocks?domain=dogwhistle.zone")
|
||||
|
||||
assert %{} == json_response_and_validate_schema(ret_conn, 200)
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
refute User.blocks?(user, other_user)
|
||||
end
|
||||
|
||||
test "getting a list of domain blocks" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:blocks"])
|
||||
|
||||
{:ok, user} = User.block_domain(user, "bad.site")
|
||||
{:ok, user} = User.block_domain(user, "even.worse.site")
|
||||
|
||||
assert ["even.worse.site", "bad.site"] ==
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/domain_blocks")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.MastodonAPI.FilterView
|
||||
|
||||
test "creating a filter" do
|
||||
%{conn: conn} = oauth_access(["write:filters"])
|
||||
|
||||
filter = %Pleroma.Filter{
|
||||
phrase: "knights",
|
||||
context: ["home"]
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
|
||||
|
||||
assert response = json_response_and_validate_schema(conn, 200)
|
||||
assert response["phrase"] == filter.phrase
|
||||
assert response["context"] == filter.context
|
||||
assert response["irreversible"] == false
|
||||
assert response["id"] != nil
|
||||
assert response["id"] != ""
|
||||
end
|
||||
|
||||
test "fetching a list of filters" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:filters"])
|
||||
|
||||
query_one = %Pleroma.Filter{
|
||||
user_id: user.id,
|
||||
filter_id: 1,
|
||||
phrase: "knights",
|
||||
context: ["home"]
|
||||
}
|
||||
|
||||
query_two = %Pleroma.Filter{
|
||||
user_id: user.id,
|
||||
filter_id: 2,
|
||||
phrase: "who",
|
||||
context: ["home"]
|
||||
}
|
||||
|
||||
{:ok, filter_one} = Pleroma.Filter.create(query_one)
|
||||
{:ok, filter_two} = Pleroma.Filter.create(query_two)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/filters")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response ==
|
||||
render_json(
|
||||
FilterView,
|
||||
"index.json",
|
||||
filters: [filter_two, filter_one]
|
||||
)
|
||||
end
|
||||
|
||||
test "get a filter" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:filters"])
|
||||
|
||||
# check whole_word false
|
||||
query = %Pleroma.Filter{
|
||||
user_id: user.id,
|
||||
filter_id: 2,
|
||||
phrase: "knight",
|
||||
context: ["home"],
|
||||
whole_word: false
|
||||
}
|
||||
|
||||
{:ok, filter} = Pleroma.Filter.create(query)
|
||||
|
||||
conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
|
||||
|
||||
assert response = json_response_and_validate_schema(conn, 200)
|
||||
assert response["whole_word"] == false
|
||||
|
||||
# check whole_word true
|
||||
%{user: user, conn: conn} = oauth_access(["read:filters"])
|
||||
|
||||
query = %Pleroma.Filter{
|
||||
user_id: user.id,
|
||||
filter_id: 3,
|
||||
phrase: "knight",
|
||||
context: ["home"],
|
||||
whole_word: true
|
||||
}
|
||||
|
||||
{:ok, filter} = Pleroma.Filter.create(query)
|
||||
|
||||
conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
|
||||
|
||||
assert response = json_response_and_validate_schema(conn, 200)
|
||||
assert response["whole_word"] == true
|
||||
end
|
||||
|
||||
test "update a filter" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:filters"])
|
||||
|
||||
query = %Pleroma.Filter{
|
||||
user_id: user.id,
|
||||
filter_id: 2,
|
||||
phrase: "knight",
|
||||
context: ["home"],
|
||||
hide: true,
|
||||
whole_word: true
|
||||
}
|
||||
|
||||
{:ok, _filter} = Pleroma.Filter.create(query)
|
||||
|
||||
new = %Pleroma.Filter{
|
||||
phrase: "nii",
|
||||
context: ["home"]
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/filters/#{query.filter_id}", %{
|
||||
phrase: new.phrase,
|
||||
context: new.context
|
||||
})
|
||||
|
||||
assert response = json_response_and_validate_schema(conn, 200)
|
||||
assert response["phrase"] == new.phrase
|
||||
assert response["context"] == new.context
|
||||
assert response["irreversible"] == true
|
||||
assert response["whole_word"] == true
|
||||
end
|
||||
|
||||
test "delete a filter" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:filters"])
|
||||
|
||||
query = %Pleroma.Filter{
|
||||
user_id: user.id,
|
||||
filter_id: 2,
|
||||
phrase: "knight",
|
||||
context: ["home"]
|
||||
}
|
||||
|
||||
{:ok, filter} = Pleroma.Filter.create(query)
|
||||
|
||||
conn = delete(conn, "/api/v1/filters/#{filter.filter_id}")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) == %{}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "locked accounts" do
|
||||
setup do
|
||||
user = insert(:user, locked: true)
|
||||
%{conn: conn} = oauth_access(["follow"], user: user)
|
||||
%{user: user, conn: conn}
|
||||
end
|
||||
|
||||
test "/api/v1/follow_requests works", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, other_user} = User.follow(other_user, user, :follow_pending)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
|
||||
conn = get(conn, "/api/v1/follow_requests")
|
||||
|
||||
assert [relationship] = json_response_and_validate_schema(conn, 200)
|
||||
assert to_string(other_user.id) == relationship["id"]
|
||||
end
|
||||
|
||||
test "/api/v1/follow_requests/:id/authorize works", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, other_user} = User.follow(other_user, user, :follow_pending)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
|
||||
conn = post(conn, "/api/v1/follow_requests/#{other_user.id}/authorize")
|
||||
|
||||
assert relationship = json_response_and_validate_schema(conn, 200)
|
||||
assert to_string(other_user.id) == relationship["id"]
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
assert User.following?(other_user, user) == true
|
||||
end
|
||||
|
||||
test "/api/v1/follow_requests/:id/reject works", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
conn = post(conn, "/api/v1/follow_requests/#{other_user.id}/reject")
|
||||
|
||||
assert relationship = json_response_and_validate_schema(conn, 200)
|
||||
assert to_string(other_user.id) == relationship["id"]
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.User
|
||||
import Pleroma.Factory
|
||||
|
||||
test "get instance information", %{conn: conn} do
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
assert result = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
email = Pleroma.Config.get([:instance, :email])
|
||||
# Note: not checking for "max_toot_chars" since it's optional
|
||||
assert %{
|
||||
"uri" => _,
|
||||
"title" => _,
|
||||
"description" => _,
|
||||
"version" => _,
|
||||
"email" => from_config_email,
|
||||
"urls" => %{
|
||||
"streaming_api" => _
|
||||
},
|
||||
"stats" => _,
|
||||
"thumbnail" => _,
|
||||
"languages" => _,
|
||||
"registrations" => _,
|
||||
"approval_required" => _,
|
||||
"poll_limits" => _,
|
||||
"upload_limit" => _,
|
||||
"avatar_upload_limit" => _,
|
||||
"background_upload_limit" => _,
|
||||
"banner_upload_limit" => _,
|
||||
"background_image" => _,
|
||||
"chat_limit" => _,
|
||||
"description_limit" => _
|
||||
} = result
|
||||
|
||||
assert result["pleroma"]["metadata"]["account_activation_required"] != nil
|
||||
assert result["pleroma"]["metadata"]["features"]
|
||||
assert result["pleroma"]["metadata"]["federation"]
|
||||
assert result["pleroma"]["metadata"]["fields_limits"]
|
||||
assert result["pleroma"]["vapid_public_key"]
|
||||
|
||||
assert email == from_config_email
|
||||
end
|
||||
|
||||
test "get instance stats", %{conn: conn} do
|
||||
user = insert(:user, %{local: true})
|
||||
|
||||
user2 = insert(:user, %{local: true})
|
||||
{:ok, _user2} = User.deactivate(user2, !user2.deactivated)
|
||||
|
||||
insert(:user, %{local: false, nickname: "u@peer1.com"})
|
||||
insert(:user, %{local: false, nickname: "u@peer2.com"})
|
||||
|
||||
{:ok, _} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
|
||||
|
||||
Pleroma.Stats.force_update()
|
||||
|
||||
conn = get(conn, "/api/v1/instance")
|
||||
|
||||
assert result = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
stats = result["stats"]
|
||||
|
||||
assert stats
|
||||
assert stats["user_count"] == 1
|
||||
assert stats["status_count"] == 1
|
||||
assert stats["domain_count"] == 2
|
||||
end
|
||||
|
||||
test "get peers", %{conn: conn} do
|
||||
insert(:user, %{local: false, nickname: "u@peer1.com"})
|
||||
insert(:user, %{local: false, nickname: "u@peer2.com"})
|
||||
|
||||
Pleroma.Stats.force_update()
|
||||
|
||||
conn = get(conn, "/api/v1/instance/peers")
|
||||
|
||||
assert result = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
assert ["peer1.com", "peer2.com"] == Enum.sort(result)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "creating a list" do
|
||||
%{conn: conn} = oauth_access(["write:lists"])
|
||||
|
||||
assert %{"title" => "cuties"} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/lists", %{"title" => "cuties"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "renders error for invalid params" do
|
||||
%{conn: conn} = oauth_access(["write:lists"])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/lists", %{"title" => nil})
|
||||
|
||||
assert %{"error" => "title - null value where string expected."} =
|
||||
json_response_and_validate_schema(conn, 400)
|
||||
end
|
||||
|
||||
test "listing a user's lists" do
|
||||
%{conn: conn} = oauth_access(["read:lists", "write:lists"])
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/lists", %{"title" => "cuties"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/lists", %{"title" => "cofe"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
conn = get(conn, "/api/v1/lists")
|
||||
|
||||
assert [
|
||||
%{"id" => _, "title" => "cofe"},
|
||||
%{"id" => _, "title" => "cuties"}
|
||||
] = json_response_and_validate_schema(conn, :ok)
|
||||
end
|
||||
|
||||
test "adding users to a list" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||
other_user = insert(:user)
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
|
||||
assert %{} ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
%Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
|
||||
assert following == [other_user.follower_address]
|
||||
end
|
||||
|
||||
test "removing users from a list, body params" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
{:ok, list} = Pleroma.List.follow(list, third_user)
|
||||
|
||||
assert %{} ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
%Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
|
||||
assert following == [third_user.follower_address]
|
||||
end
|
||||
|
||||
test "removing users from a list, query params" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
{:ok, list} = Pleroma.List.follow(list, third_user)
|
||||
|
||||
assert %{} ==
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> delete("/api/v1/lists/#{list.id}/accounts?account_ids[]=#{other_user.id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
%Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
|
||||
assert following == [third_user.follower_address]
|
||||
end
|
||||
|
||||
test "listing users in a list" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:lists"])
|
||||
other_user = insert(:user)
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
|
||||
|
||||
assert [%{"id" => id}] = json_response_and_validate_schema(conn, 200)
|
||||
assert id == to_string(other_user.id)
|
||||
end
|
||||
|
||||
test "retrieving a list" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:lists"])
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/lists/#{list.id}")
|
||||
|
||||
assert %{"id" => id} = json_response_and_validate_schema(conn, 200)
|
||||
assert id == to_string(list.id)
|
||||
end
|
||||
|
||||
test "renders 404 if list is not found" do
|
||||
%{conn: conn} = oauth_access(["read:lists"])
|
||||
|
||||
conn = get(conn, "/api/v1/lists/666")
|
||||
|
||||
assert %{"error" => "List not found"} = json_response_and_validate_schema(conn, :not_found)
|
||||
end
|
||||
|
||||
test "renaming a list" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
|
||||
assert %{"title" => "newname"} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "validates title when renaming a list" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/lists/#{list.id}", %{"title" => " "})
|
||||
|
||||
assert %{"error" => "can't be blank"} ==
|
||||
json_response_and_validate_schema(conn, :unprocessable_entity)
|
||||
end
|
||||
|
||||
test "deleting a list" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
|
||||
conn = delete(conn, "/api/v1/lists/#{list.id}")
|
||||
|
||||
assert %{} = json_response_and_validate_schema(conn, 200)
|
||||
assert is_nil(Repo.get(Pleroma.List, list.id))
|
||||
end
|
||||
end
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "GET /api/v1/markers" do
|
||||
test "gets markers with correct scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||
insert_list(7, :notification, user: user, activity: insert(:note_activity))
|
||||
|
||||
{:ok, %{"notifications" => marker}} =
|
||||
Pleroma.Marker.upsert(
|
||||
user,
|
||||
%{"notifications" => %{"last_read_id" => "69420"}}
|
||||
)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> get("/api/v1/markers?timeline[]=notifications")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response == %{
|
||||
"notifications" => %{
|
||||
"last_read_id" => "69420",
|
||||
"updated_at" => NaiveDateTime.to_iso8601(marker.updated_at),
|
||||
"version" => 0,
|
||||
"pleroma" => %{"unread_count" => 7}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
test "gets markers with missed scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: [])
|
||||
|
||||
Pleroma.Marker.upsert(user, %{"notifications" => %{"last_read_id" => "69420"}})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> get("/api/v1/markers", %{timeline: ["notifications"]})
|
||||
|> json_response_and_validate_schema(403)
|
||||
|
||||
assert response == %{"error" => "Insufficient permissions: read:statuses."}
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/markers" do
|
||||
test "creates a marker with correct scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: ["write:statuses"])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/markers", %{
|
||||
home: %{last_read_id: "777"},
|
||||
notifications: %{"last_read_id" => "69420"}
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"notifications" => %{
|
||||
"last_read_id" => "69420",
|
||||
"updated_at" => _,
|
||||
"version" => 0,
|
||||
"pleroma" => %{"unread_count" => 0}
|
||||
}
|
||||
} = response
|
||||
end
|
||||
|
||||
test "updates exist marker", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: ["write:statuses"])
|
||||
|
||||
{:ok, %{"notifications" => marker}} =
|
||||
Pleroma.Marker.upsert(
|
||||
user,
|
||||
%{"notifications" => %{"last_read_id" => "69477"}}
|
||||
)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/markers", %{
|
||||
home: %{last_read_id: "777"},
|
||||
notifications: %{"last_read_id" => "69888"}
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response == %{
|
||||
"notifications" => %{
|
||||
"last_read_id" => "69888",
|
||||
"updated_at" => NaiveDateTime.to_iso8601(marker.updated_at),
|
||||
"version" => 0,
|
||||
"pleroma" => %{"unread_count" => 0}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
test "creates a marker with missed scopes", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/markers", %{
|
||||
home: %{last_read_id: "777"},
|
||||
notifications: %{"last_read_id" => "69420"}
|
||||
})
|
||||
|> json_response_and_validate_schema(403)
|
||||
|
||||
assert response == %{"error" => "Insufficient permissions: write:statuses."}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
||||
describe "Upload media" do
|
||||
setup do: oauth_access(["write:media"])
|
||||
|
||||
setup do
|
||||
image = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
[image: image]
|
||||
end
|
||||
|
||||
setup do: clear_config([:media_proxy])
|
||||
setup do: clear_config([Pleroma.Upload])
|
||||
|
||||
test "/api/v1/media", %{conn: conn, image: image} do
|
||||
desc = "Description of the image"
|
||||
|
||||
media =
|
||||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> post("/api/v1/media", %{"file" => image, "description" => desc})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert media["type"] == "image"
|
||||
assert media["description"] == desc
|
||||
assert media["id"]
|
||||
|
||||
object = Object.get_by_id(media["id"])
|
||||
assert object.data["actor"] == User.ap_id(conn.assigns[:user])
|
||||
end
|
||||
|
||||
test "/api/v2/media", %{conn: conn, user: user, image: image} do
|
||||
desc = "Description of the image"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|
||||
|> json_response_and_validate_schema(202)
|
||||
|
||||
assert media_id = response["id"]
|
||||
|
||||
%{conn: conn} = oauth_access(["read:media"], user: user)
|
||||
|
||||
media =
|
||||
conn
|
||||
|> get("/api/v1/media/#{media_id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert media["type"] == "image"
|
||||
assert media["description"] == desc
|
||||
assert media["id"]
|
||||
|
||||
object = Object.get_by_id(media["id"])
|
||||
assert object.data["actor"] == user.ap_id
|
||||
end
|
||||
end
|
||||
|
||||
describe "Update media description" do
|
||||
setup do: oauth_access(["write:media"])
|
||||
|
||||
setup %{user: actor} do
|
||||
file = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
{:ok, %Object{} = object} =
|
||||
ActivityPub.upload(
|
||||
file,
|
||||
actor: User.ap_id(actor),
|
||||
description: "test-m"
|
||||
)
|
||||
|
||||
[object: object]
|
||||
end
|
||||
|
||||
test "/api/v1/media/:id good request", %{conn: conn, object: object} do
|
||||
media =
|
||||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert media["description"] == "test-media"
|
||||
assert refresh_record(object).data["name"] == "test-media"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Get media by id (/api/v1/media/:id)" do
|
||||
setup do: oauth_access(["read:media"])
|
||||
|
||||
setup %{user: actor} do
|
||||
file = %Plug.Upload{
|
||||
content_type: "image/jpg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
{:ok, %Object{} = object} =
|
||||
ActivityPub.upload(
|
||||
file,
|
||||
actor: User.ap_id(actor),
|
||||
description: "test-media"
|
||||
)
|
||||
|
||||
[object: object]
|
||||
end
|
||||
|
||||
test "it returns media object when requested by owner", %{conn: conn, object: object} do
|
||||
media =
|
||||
conn
|
||||
|> get("/api/v1/media/#{object.id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert media["description"] == "test-media"
|
||||
assert media["type"] == "image"
|
||||
assert media["id"]
|
||||
end
|
||||
|
||||
test "it returns 403 if media object requested by non-owner", %{object: object, user: user} do
|
||||
%{conn: conn, user: other_user} = oauth_access(["read:media"])
|
||||
|
||||
assert object.data["actor"] == user.ap_id
|
||||
refute user.id == other_user.id
|
||||
|
||||
conn
|
||||
|> get("/api/v1/media/#{object.id}")
|
||||
|> json_response(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,626 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "does NOT render account/pleroma/relationship by default" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, [_notification]} = Notification.create_notifications(activity)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert Enum.all?(response, fn n ->
|
||||
get_in(n, ["account", "pleroma", "relationship"]) == %{}
|
||||
end)
|
||||
end
|
||||
|
||||
test "list of notifications" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
{:ok, [_notification]} = Notification.create_notifications(activity)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications")
|
||||
|
||||
expected_response =
|
||||
"hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{
|
||||
user.ap_id
|
||||
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
||||
|
||||
assert [%{"status" => %{"content" => response}} | _rest] =
|
||||
json_response_and_validate_schema(conn, 200)
|
||||
|
||||
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)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
||||
conn = get(conn, "/api/v1/notifications/#{notification.id}")
|
||||
|
||||
expected_response =
|
||||
"hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{
|
||||
user.ap_id
|
||||
}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>"
|
||||
|
||||
assert %{"status" => %{"content" => response}} = json_response_and_validate_schema(conn, 200)
|
||||
assert response == expected_response
|
||||
end
|
||||
|
||||
test "dismissing a single notification (deprecated endpoint)" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/notifications/dismiss", %{"id" => to_string(notification.id)})
|
||||
|
||||
assert %{} = json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
test "dismissing a single notification" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> post("/api/v1/notifications/#{notification.id}/dismiss")
|
||||
|
||||
assert %{} = json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
test "clearing all notifications" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:notifications", "read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
{:ok, [_notification]} = Notification.create_notifications(activity)
|
||||
|
||||
ret_conn = post(conn, "/api/v1/notifications/clear")
|
||||
|
||||
assert %{} = json_response_and_validate_schema(ret_conn, 200)
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert all = json_response_and_validate_schema(ret_conn, 200)
|
||||
assert all == []
|
||||
end
|
||||
|
||||
test "paginates notifications using min_id, since_id, max_id, and limit" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity1} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, activity2} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, activity3} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, activity4} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
notification1_id = get_notification_id_by_activity(activity1)
|
||||
notification2_id = get_notification_id_by_activity(activity2)
|
||||
notification3_id = get_notification_id_by_activity(activity3)
|
||||
notification4_id = get_notification_id_by_activity(activity4)
|
||||
|
||||
conn = assign(conn, :user, user)
|
||||
|
||||
# min_id
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
|
||||
|
||||
# since_id
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
||||
|
||||
# max_id
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
|
||||
end
|
||||
|
||||
describe "exclude_visibilities" do
|
||||
test "filters notifications for mentions" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, public_activity} =
|
||||
CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "public"})
|
||||
|
||||
{:ok, direct_activity} =
|
||||
CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, unlisted_activity} =
|
||||
CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "unlisted"})
|
||||
|
||||
{:ok, private_activity} =
|
||||
CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "private"})
|
||||
|
||||
query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "private"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||
assert id == direct_activity.id
|
||||
|
||||
query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "direct"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||
assert id == private_activity.id
|
||||
|
||||
query = params_to_query(%{exclude_visibilities: ["public", "private", "direct"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||
assert id == unlisted_activity.id
|
||||
|
||||
query = params_to_query(%{exclude_visibilities: ["unlisted", "private", "direct"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"status" => %{"id" => id}}] = json_response_and_validate_schema(conn_res, 200)
|
||||
assert id == public_activity.id
|
||||
end
|
||||
|
||||
test "filters notifications for Like activities" do
|
||||
user = insert(:user)
|
||||
%{user: other_user, conn: conn} = oauth_access(["read:notifications"])
|
||||
|
||||
{:ok, public_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "public"})
|
||||
|
||||
{:ok, direct_activity} =
|
||||
CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, unlisted_activity} =
|
||||
CommonAPI.post(other_user, %{status: ".", visibility: "unlisted"})
|
||||
|
||||
{:ok, private_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "private"})
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(user, public_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, direct_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, unlisted_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, private_activity.id)
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|> get("/api/v1/notifications?exclude_visibilities[]=direct")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|> Enum.map(& &1["status"]["id"])
|
||||
|
||||
assert public_activity.id in activity_ids
|
||||
assert unlisted_activity.id in activity_ids
|
||||
assert private_activity.id in activity_ids
|
||||
refute direct_activity.id in activity_ids
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|> Enum.map(& &1["status"]["id"])
|
||||
|
||||
assert public_activity.id in activity_ids
|
||||
refute unlisted_activity.id in activity_ids
|
||||
assert private_activity.id in activity_ids
|
||||
assert direct_activity.id in activity_ids
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|> get("/api/v1/notifications?exclude_visibilities[]=private")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|> Enum.map(& &1["status"]["id"])
|
||||
|
||||
assert public_activity.id in activity_ids
|
||||
assert unlisted_activity.id in activity_ids
|
||||
refute private_activity.id in activity_ids
|
||||
assert direct_activity.id in activity_ids
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|> get("/api/v1/notifications?exclude_visibilities[]=public")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|> Enum.map(& &1["status"]["id"])
|
||||
|
||||
refute public_activity.id in activity_ids
|
||||
assert unlisted_activity.id in activity_ids
|
||||
assert private_activity.id in activity_ids
|
||||
assert direct_activity.id in activity_ids
|
||||
end
|
||||
|
||||
test "filters notifications for Announce activities" do
|
||||
user = insert(:user)
|
||||
%{user: other_user, conn: conn} = oauth_access(["read:notifications"])
|
||||
|
||||
{:ok, public_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "public"})
|
||||
|
||||
{:ok, unlisted_activity} =
|
||||
CommonAPI.post(other_user, %{status: ".", visibility: "unlisted"})
|
||||
|
||||
{:ok, _} = CommonAPI.repeat(public_activity.id, user)
|
||||
{:ok, _} = CommonAPI.repeat(unlisted_activity.id, user)
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|> get("/api/v1/notifications?exclude_visibilities[]=unlisted")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|> Enum.map(& &1["status"]["id"])
|
||||
|
||||
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
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
mention_notification_id = get_notification_id_by_activity(mention_activity)
|
||||
favorite_notification_id = get_notification_id_by_activity(favorite_activity)
|
||||
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
query = params_to_query(%{exclude_types: ["mention", "favourite", "reblog"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
query = params_to_query(%{exclude_types: ["favourite", "reblog", "follow"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"id" => ^mention_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
query = params_to_query(%{exclude_types: ["reblog", "follow", "mention"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"id" => ^favorite_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
query = params_to_query(%{exclude_types: ["follow", "mention", "favourite"]})
|
||||
conn_res = get(conn, "/api/v1/notifications?" <> query)
|
||||
|
||||
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
end
|
||||
|
||||
test "filters notifications using include_types" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
mention_notification_id = get_notification_id_by_activity(mention_activity)
|
||||
favorite_notification_id = get_notification_id_by_activity(favorite_activity)
|
||||
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=follow")
|
||||
|
||||
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=mention")
|
||||
|
||||
assert [%{"id" => ^mention_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=favourite")
|
||||
|
||||
assert [%{"id" => ^favorite_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=reblog")
|
||||
|
||||
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
result = conn |> get("/api/v1/notifications") |> json_response_and_validate_schema(200)
|
||||
|
||||
assert length(result) == 4
|
||||
|
||||
query = params_to_query(%{include_types: ["follow", "mention", "favourite", "reblog"]})
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/notifications?" <> query)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert length(result) == 4
|
||||
end
|
||||
|
||||
test "destroy multiple" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications", "write:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity1} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, activity2} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, activity3} = CommonAPI.post(user, %{status: "hi @#{other_user.nickname}"})
|
||||
{:ok, activity4} = CommonAPI.post(user, %{status: "hi @#{other_user.nickname}"})
|
||||
|
||||
notification1_id = get_notification_id_by_activity(activity1)
|
||||
notification2_id = get_notification_id_by_activity(activity2)
|
||||
notification3_id = get_notification_id_by_activity(activity3)
|
||||
notification4_id = get_notification_id_by_activity(activity4)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/notifications")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
|
||||
|
||||
conn2 =
|
||||
conn
|
||||
|> assign(:user, other_user)
|
||||
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:notifications"]))
|
||||
|
||||
result =
|
||||
conn2
|
||||
|> get("/api/v1/notifications")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
||||
|
||||
query = params_to_query(%{ids: [notification1_id, notification2_id]})
|
||||
conn_destroy = delete(conn, "/api/v1/notifications/destroy_multiple?" <> query)
|
||||
|
||||
assert json_response_and_validate_schema(conn_destroy, 200) == %{}
|
||||
|
||||
result =
|
||||
conn2
|
||||
|> get("/api/v1/notifications")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
|
||||
end
|
||||
|
||||
test "doesn't see notifications after muting user with notifications" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, user2)
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, user2)
|
||||
|
||||
conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) == []
|
||||
end
|
||||
|
||||
test "see notifications after muting user without notifications" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, user2)
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, user2, false)
|
||||
|
||||
conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert length(json_response_and_validate_schema(conn, 200)) == 1
|
||||
end
|
||||
|
||||
test "see notifications after muting user with notifications and with_muted parameter" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, user2)
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert length(json_response_and_validate_schema(ret_conn, 200)) == 1
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, user2)
|
||||
|
||||
conn = get(conn, "/api/v1/notifications?with_muted=true")
|
||||
|
||||
assert length(json_response_and_validate_schema(conn, 200)) == 1
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "see move notifications" do
|
||||
old_user = insert(:user)
|
||||
new_user = insert(:user, also_known_as: [old_user.ap_id])
|
||||
%{user: follower, conn: conn} = oauth_access(["read:notifications"])
|
||||
|
||||
old_user_url = old_user.ap_id
|
||||
|
||||
body =
|
||||
File.read!("test/fixtures/users_mock/localhost.json")
|
||||
|> String.replace("{{nickname}}", old_user.nickname)
|
||||
|> Jason.encode!()
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get, url: ^old_user_url} ->
|
||||
%Tesla.Env{status: 200, body: body}
|
||||
end)
|
||||
|
||||
User.follow(follower, old_user)
|
||||
Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
|
||||
Pleroma.Tests.ObanHelpers.perform_all()
|
||||
|
||||
conn = get(conn, "/api/v1/notifications")
|
||||
|
||||
assert length(json_response_and_validate_schema(conn, 200)) == 1
|
||||
end
|
||||
|
||||
describe "link headers" do
|
||||
test "preserves parameters in link headers" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity1} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "hi @#{user.nickname}",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
{:ok, activity2} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "hi @#{user.nickname}",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
notification1 = Repo.get_by(Notification, activity_id: activity1.id)
|
||||
notification2 = Repo.get_by(Notification, activity_id: activity2.id)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications?limit=5")
|
||||
|
||||
assert [link_header] = get_resp_header(conn, "link")
|
||||
assert link_header =~ ~r/limit=5/
|
||||
assert link_header =~ ~r/min_id=#{notification2.id}/
|
||||
assert link_header =~ ~r/max_id=#{notification1.id}/
|
||||
end
|
||||
end
|
||||
|
||||
describe "from specified user" do
|
||||
test "account_id" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
|
||||
%{id: account_id} = other_user1 = insert(:user)
|
||||
other_user2 = insert(:user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(other_user1, %{status: "hi @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(other_user2, %{status: "bye @#{user.nickname}"})
|
||||
|
||||
assert [%{"account" => %{"id" => ^account_id}}] =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications?account_id=#{account_id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"error" => "Account is not found"} =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/notifications?account_id=cofe")
|
||||
|> json_response_and_validate_schema(404)
|
||||
end
|
||||
end
|
||||
|
||||
defp get_notification_id_by_activity(%{id: id}) do
|
||||
Notification
|
||||
|> Repo.get_by(activity_id: id)
|
||||
|> Map.get(:id)
|
||||
|> to_string()
|
||||
end
|
||||
|
||||
defp params_to_query(%{} = params) do
|
||||
Enum.map_join(params, "&", fn
|
||||
{k, v} when is_list(v) -> Enum.map_join(v, "&", &"#{k}[]=#{&1}")
|
||||
{k, v} -> k <> "=" <> v
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "GET /api/v1/polls/:id" do
|
||||
setup do: oauth_access(["read:statuses"])
|
||||
|
||||
test "returns poll entity for object id", %{user: user, conn: conn} do
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "Pleroma does",
|
||||
poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
conn = get(conn, "/api/v1/polls/#{object.id}")
|
||||
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
id = to_string(object.id)
|
||||
assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
|
||||
end
|
||||
|
||||
test "does not expose polls for private statuses", %{conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Pleroma does",
|
||||
poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20},
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
conn = get(conn, "/api/v1/polls/#{object.id}")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 404)
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/polls/:id/votes" do
|
||||
setup do: oauth_access(["write:statuses"])
|
||||
|
||||
test "votes are added to the poll", %{conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "A very delicious sandwich",
|
||||
poll: %{
|
||||
options: ["Lettuce", "Grilled Bacon", "Tomato"],
|
||||
expires_in: 20,
|
||||
multiple: true
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200)
|
||||
object = Object.get_by_id(object.id)
|
||||
|
||||
assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
|
||||
total_items == 1
|
||||
end)
|
||||
end
|
||||
|
||||
test "author can't vote", %{user: user, conn: conn} do
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "Am I cute?",
|
||||
poll: %{options: ["Yes", "No"], expires_in: 20}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
|
||||
|> json_response_and_validate_schema(422) == %{"error" => "Poll's author can't vote"}
|
||||
|
||||
object = Object.get_by_id(object.id)
|
||||
|
||||
refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
|
||||
end
|
||||
|
||||
test "does not allow multiple choices on a single-choice question", %{conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "The glass is",
|
||||
poll: %{options: ["half empty", "half full"], expires_in: 20}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
|
||||
|> json_response_and_validate_schema(422) == %{"error" => "Too many choices"}
|
||||
|
||||
object = Object.get_by_id(object.id)
|
||||
|
||||
refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
|
||||
total_items == 1
|
||||
end)
|
||||
end
|
||||
|
||||
test "does not allow choice index to be greater than options count", %{conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Am I cute?",
|
||||
poll: %{options: ["Yes", "No"], expires_in: 20}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 422) == %{"error" => "Invalid indices"}
|
||||
end
|
||||
|
||||
test "returns 404 error when object is not exist", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/polls/1/votes", %{"choices" => [0]})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
|
||||
end
|
||||
|
||||
test "returns 404 when poll is private and not available for user", %{conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Am I cute?",
|
||||
poll: %{options: ["Yes", "No"], expires_in: 20},
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: oauth_access(["write:reports"])
|
||||
|
||||
setup do
|
||||
target_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"})
|
||||
|
||||
[target_user: target_user, activity: activity]
|
||||
end
|
||||
|
||||
test "submit a basic report", %{conn: conn, target_user: target_user} do
|
||||
assert %{"action_taken" => false, "id" => _} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "submit a report with statuses and comment", %{
|
||||
conn: conn,
|
||||
target_user: target_user,
|
||||
activity: activity
|
||||
} do
|
||||
assert %{"action_taken" => false, "id" => _} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/reports", %{
|
||||
"account_id" => target_user.id,
|
||||
"status_ids" => [activity.id],
|
||||
"comment" => "bad status!",
|
||||
"forward" => "false"
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "account_id is required", %{
|
||||
conn: conn,
|
||||
activity: activity
|
||||
} do
|
||||
assert %{"error" => "Missing field: account_id."} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
|
||||
|> json_response_and_validate_schema(400)
|
||||
end
|
||||
|
||||
test "comment must be up to the size specified in the config", %{
|
||||
conn: conn,
|
||||
target_user: target_user
|
||||
} do
|
||||
max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
|
||||
comment = String.pad_trailing("a", max_size + 1, "a")
|
||||
|
||||
error = %{"error" => "Comment must be up to #{max_size} characters"}
|
||||
|
||||
assert ^error =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
|
||||
|> json_response_and_validate_schema(400)
|
||||
end
|
||||
|
||||
test "returns error when account is not exist", %{
|
||||
conn: conn,
|
||||
activity: activity
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 400) == %{"error" => "Account not found"}
|
||||
end
|
||||
|
||||
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do
|
||||
insert(:user, %{is_admin: true, email: nil})
|
||||
|
||||
assert %{"action_taken" => false, "id" => _} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.ScheduledActivity
|
||||
|
||||
import Pleroma.Factory
|
||||
import Ecto.Query
|
||||
|
||||
setup do: clear_config([ScheduledActivity, :enabled])
|
||||
|
||||
test "shows scheduled activities" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||
scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||
scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||
scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||
|
||||
# min_id
|
||||
conn_res = get(conn, "/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
|
||||
|
||||
result = json_response_and_validate_schema(conn_res, 200)
|
||||
assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
|
||||
|
||||
# since_id
|
||||
conn_res = get(conn, "/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
|
||||
|
||||
result = json_response_and_validate_schema(conn_res, 200)
|
||||
assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
|
||||
|
||||
# max_id
|
||||
conn_res = get(conn, "/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
|
||||
|
||||
result = json_response_and_validate_schema(conn_res, 200)
|
||||
assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
|
||||
end
|
||||
|
||||
test "shows a scheduled activity" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:statuses"])
|
||||
scheduled_activity = insert(:scheduled_activity, user: user)
|
||||
|
||||
res_conn = get(conn, "/api/v1/scheduled_statuses/#{scheduled_activity.id}")
|
||||
|
||||
assert %{"id" => scheduled_activity_id} = json_response_and_validate_schema(res_conn, 200)
|
||||
assert scheduled_activity_id == scheduled_activity.id |> to_string()
|
||||
|
||||
res_conn = get(conn, "/api/v1/scheduled_statuses/404")
|
||||
|
||||
assert %{"error" => "Record not found"} = json_response_and_validate_schema(res_conn, 404)
|
||||
end
|
||||
|
||||
test "updates a scheduled activity" do
|
||||
Pleroma.Config.put([ScheduledActivity, :enabled], true)
|
||||
%{user: user, conn: conn} = oauth_access(["write:statuses"])
|
||||
|
||||
scheduled_at = Timex.shift(NaiveDateTime.utc_now(), minutes: 60)
|
||||
|
||||
{:ok, scheduled_activity} =
|
||||
ScheduledActivity.create(
|
||||
user,
|
||||
%{
|
||||
scheduled_at: scheduled_at,
|
||||
params: build(:note).data
|
||||
}
|
||||
)
|
||||
|
||||
job = Repo.one(from(j in Oban.Job, where: j.queue == "scheduled_activities"))
|
||||
|
||||
assert job.args == %{"activity_id" => scheduled_activity.id}
|
||||
assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(scheduled_at)
|
||||
|
||||
new_scheduled_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> Timex.shift(minutes: 120)
|
||||
|> Timex.format!("%Y-%m-%dT%H:%M:%S.%fZ", :strftime)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
|
||||
scheduled_at: new_scheduled_at
|
||||
})
|
||||
|
||||
assert %{"scheduled_at" => expected_scheduled_at} =
|
||||
json_response_and_validate_schema(res_conn, 200)
|
||||
|
||||
assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
|
||||
job = refresh_record(job)
|
||||
|
||||
assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(new_scheduled_at)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
|
||||
|
||||
assert %{"error" => "Record not found"} = json_response_and_validate_schema(res_conn, 404)
|
||||
end
|
||||
|
||||
test "deletes a scheduled activity" do
|
||||
Pleroma.Config.put([ScheduledActivity, :enabled], true)
|
||||
%{user: user, conn: conn} = oauth_access(["write:statuses"])
|
||||
scheduled_at = Timex.shift(NaiveDateTime.utc_now(), minutes: 60)
|
||||
|
||||
{:ok, scheduled_activity} =
|
||||
ScheduledActivity.create(
|
||||
user,
|
||||
%{
|
||||
scheduled_at: scheduled_at,
|
||||
params: build(:note).data
|
||||
}
|
||||
)
|
||||
|
||||
job = Repo.one(from(j in Oban.Job, where: j.queue == "scheduled_activities"))
|
||||
|
||||
assert job.args == %{"activity_id" => scheduled_activity.id}
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
|
||||
|
||||
assert %{} = json_response_and_validate_schema(res_conn, 200)
|
||||
refute Repo.get(ScheduledActivity, scheduled_activity.id)
|
||||
refute Repo.get(Oban.Job, job.id)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
|
||||
|
||||
assert %{"error" => "Record not found"} = json_response_and_validate_schema(res_conn, 404)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,413 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.CommonAPI
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
import Tesla.Mock
|
||||
import Mock
|
||||
|
||||
setup_all do
|
||||
mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe ".search2" do
|
||||
test "it returns empty result if user or status search return undefined error", %{conn: conn} do
|
||||
with_mocks [
|
||||
{Pleroma.User, [], [search: fn _q, _o -> raise "Oops" end]},
|
||||
{Pleroma.Activity, [], [search: fn _u, _q, _o -> raise "Oops" end]}
|
||||
] do
|
||||
capture_log(fn ->
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v2/search?q=2hu")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["accounts"] == []
|
||||
assert results["statuses"] == []
|
||||
end) =~
|
||||
"[error] Elixir.Pleroma.Web.MastodonAPI.SearchController search error: %RuntimeError{message: \"Oops\"}"
|
||||
end
|
||||
end
|
||||
|
||||
test "search", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "This is about 2hu private 天子"})
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "This is about 2hu, but private",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, _} = CommonAPI.post(user_two, %{status: "This isn't"})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v2/search?#{URI.encode_query(%{q: "2hu #private"})}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[account | _] = results["accounts"]
|
||||
assert account["id"] == to_string(user_three.id)
|
||||
|
||||
assert results["hashtags"] == [
|
||||
%{"name" => "private", "url" => "#{Web.base_url()}/tag/private"}
|
||||
]
|
||||
|
||||
[status] = results["statuses"]
|
||||
assert status["id"] == to_string(activity.id)
|
||||
|
||||
results =
|
||||
get(conn, "/api/v2/search?q=天子")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["hashtags"] == [
|
||||
%{"name" => "天子", "url" => "#{Web.base_url()}/tag/天子"}
|
||||
]
|
||||
|
||||
[status] = results["statuses"]
|
||||
assert status["id"] == to_string(activity.id)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "constructs hashtags from search query", %{conn: conn} do
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v2/search?#{URI.encode_query(%{q: "some text with #explicit #hashtags"})}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["hashtags"] == [
|
||||
%{"name" => "explicit", "url" => "#{Web.base_url()}/tag/explicit"},
|
||||
%{"name" => "hashtags", "url" => "#{Web.base_url()}/tag/hashtags"}
|
||||
]
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v2/search?#{URI.encode_query(%{q: "john doe JOHN DOE"})}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["hashtags"] == [
|
||||
%{"name" => "john", "url" => "#{Web.base_url()}/tag/john"},
|
||||
%{"name" => "doe", "url" => "#{Web.base_url()}/tag/doe"},
|
||||
%{"name" => "JohnDoe", "url" => "#{Web.base_url()}/tag/JohnDoe"}
|
||||
]
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v2/search?#{URI.encode_query(%{q: "accident-prone"})}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["hashtags"] == [
|
||||
%{"name" => "accident", "url" => "#{Web.base_url()}/tag/accident"},
|
||||
%{"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 "supports pagination of hashtags search results", %{conn: conn} do
|
||||
results =
|
||||
conn
|
||||
|> get(
|
||||
"/api/v2/search?#{
|
||||
URI.encode_query(%{q: "#some #text #with #hashtags", limit: 2, offset: 1})
|
||||
}"
|
||||
)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["hashtags"] == [
|
||||
%{"name" => "text", "url" => "#{Web.base_url()}/tag/text"},
|
||||
%{"name" => "with", "url" => "#{Web.base_url()}/tag/with"}
|
||||
]
|
||||
end
|
||||
|
||||
test "excludes a blocked users from search results", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
user_smith = insert(:user, %{nickname: "Agent", name: "I love 2hu"})
|
||||
user_neo = insert(:user, %{nickname: "Agent Neo", name: "Agent"})
|
||||
|
||||
{:ok, act1} = CommonAPI.post(user, %{status: "This is about 2hu private 天子"})
|
||||
{:ok, act2} = CommonAPI.post(user_smith, %{status: "Agent Smith"})
|
||||
{:ok, act3} = CommonAPI.post(user_neo, %{status: "Agent Smith"})
|
||||
Pleroma.User.block(user, user_smith)
|
||||
|
||||
results =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
||||
|> get("/api/v2/search?q=Agent")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
status_ids = Enum.map(results["statuses"], fn g -> g["id"] end)
|
||||
|
||||
assert act3.id in status_ids
|
||||
refute act2.id in status_ids
|
||||
refute act1.id in status_ids
|
||||
end
|
||||
end
|
||||
|
||||
describe ".account_search" do
|
||||
test "account search", %{conn: conn} do
|
||||
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/accounts/search?q=shp")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
result_ids = for result <- results, do: result["acct"]
|
||||
|
||||
assert user_two.nickname in result_ids
|
||||
assert user_three.nickname in result_ids
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/accounts/search?q=2hu")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
result_ids = for result <- results, do: result["acct"]
|
||||
|
||||
assert user_three.nickname in result_ids
|
||||
end
|
||||
|
||||
test "returns account if query contains a space", %{conn: conn} do
|
||||
insert(:user, %{nickname: "shp@shitposter.club"})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/accounts/search?q=shp@shitposter.club xxx")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert length(results) == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe ".search" do
|
||||
test "it returns empty result if user or status search return undefined error", %{conn: conn} do
|
||||
with_mocks [
|
||||
{Pleroma.User, [], [search: fn _q, _o -> raise "Oops" end]},
|
||||
{Pleroma.Activity, [], [search: fn _u, _q, _o -> raise "Oops" end]}
|
||||
] do
|
||||
capture_log(fn ->
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert results["accounts"] == []
|
||||
assert results["statuses"] == []
|
||||
end) =~
|
||||
"[error] Elixir.Pleroma.Web.MastodonAPI.SearchController search error: %RuntimeError{message: \"Oops\"}"
|
||||
end
|
||||
end
|
||||
|
||||
test "search", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "This is about 2hu"})
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "This is about 2hu, but private",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, _} = CommonAPI.post(user_two, %{status: "This isn't"})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[account | _] = results["accounts"]
|
||||
assert account["id"] == to_string(user_three.id)
|
||||
|
||||
assert results["hashtags"] == ["2hu"]
|
||||
|
||||
[status] = results["statuses"]
|
||||
assert status["id"] == to_string(activity.id)
|
||||
end
|
||||
|
||||
test "search fetches remote statuses and prefers them over other results", %{conn: conn} do
|
||||
capture_log(fn ->
|
||||
{:ok, %{id: activity_id}} =
|
||||
CommonAPI.post(insert(:user), %{
|
||||
status: "check out http://mastodon.example.org/@admin/99541947525187367"
|
||||
})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=http://mastodon.example.org/@admin/99541947525187367")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{"url" => "http://mastodon.example.org/@admin/99541947525187367"},
|
||||
%{"id" => ^activity_id}
|
||||
] = results["statuses"]
|
||||
end)
|
||||
end
|
||||
|
||||
test "search doesn't show statuses that it shouldn't", %{conn: conn} do
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(insert(:user), %{
|
||||
status: "This is about 2hu, but private",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
capture_log(fn ->
|
||||
q = Object.normalize(activity).data["id"]
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=#{q}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[] = results["statuses"]
|
||||
end)
|
||||
end
|
||||
|
||||
test "search fetches remote accounts", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
query = URI.encode_query(%{q: " mike@osada.macgirvin.com ", resolve: true})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
||||
|> get("/api/v1/search?#{query}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[account] = results["accounts"]
|
||||
assert account["acct"] == "mike@osada.macgirvin.com"
|
||||
end
|
||||
|
||||
test "search doesn't fetch remote accounts if resolve is false", %{conn: conn} do
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=false")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [] == results["accounts"]
|
||||
end
|
||||
|
||||
test "search with limit and offset", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
_user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||
_user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||
|
||||
{:ok, _activity1} = CommonAPI.post(user, %{status: "This is about 2hu"})
|
||||
{:ok, _activity2} = CommonAPI.post(user, %{status: "This is also about 2hu"})
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu&limit=1")
|
||||
|
||||
assert results = json_response_and_validate_schema(result, 200)
|
||||
assert [%{"id" => activity_id1}] = results["statuses"]
|
||||
assert [_] = results["accounts"]
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu&limit=1&offset=1")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => activity_id2}] = results["statuses"]
|
||||
assert [] = results["accounts"]
|
||||
|
||||
assert activity_id1 != activity_id2
|
||||
end
|
||||
|
||||
test "search returns results only for the given type", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
_user_two = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "This is about 2hu"})
|
||||
|
||||
assert %{"statuses" => [_activity], "accounts" => [], "hashtags" => []} =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu&type=statuses")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{"statuses" => [], "accounts" => [_user_two], "hashtags" => []} =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu&type=accounts")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "search uses account_id to filter statuses by the author", %{conn: conn} do
|
||||
user = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||
user_two = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||
|
||||
{:ok, activity1} = CommonAPI.post(user, %{status: "This is about 2hu"})
|
||||
{:ok, activity2} = CommonAPI.post(user_two, %{status: "This is also about 2hu"})
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu&account_id=#{user.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => activity_id1}] = results["statuses"]
|
||||
assert activity_id1 == activity1.id
|
||||
assert [_] = results["accounts"]
|
||||
|
||||
results =
|
||||
conn
|
||||
|> get("/api/v1/search?q=2hu&account_id=#{user_two.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => activity_id2}] = results["statuses"]
|
||||
assert activity_id2 == activity2.id
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,199 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.Push
|
||||
alias Pleroma.Web.Push.Subscription
|
||||
|
||||
@sub %{
|
||||
"endpoint" => "https://example.com/example/1234",
|
||||
"keys" => %{
|
||||
"auth" => "8eDyX_uCN0XRhSbY5hs7Hg==",
|
||||
"p256dh" =>
|
||||
"BCIWgsnyXDv1VkhqL2P7YRBvdeuDnlwAPT2guNhdIoW3IP7GmHh1SMKPLxRf7x8vJy6ZFK3ol2ohgn_-0yP7QQA="
|
||||
}
|
||||
}
|
||||
@server_key Keyword.get(Push.vapid_config(), :public_key)
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: ["push"])
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|
||||
%{conn: conn, user: user, token: token}
|
||||
end
|
||||
|
||||
defmacro assert_error_when_disable_push(do: yield) do
|
||||
quote do
|
||||
vapid_details = Application.get_env(:web_push_encryption, :vapid_details, [])
|
||||
Application.put_env(:web_push_encryption, :vapid_details, [])
|
||||
|
||||
assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} ==
|
||||
unquote(yield)
|
||||
|
||||
Application.put_env(:web_push_encryption, :vapid_details, vapid_details)
|
||||
end
|
||||
end
|
||||
|
||||
describe "creates push subscription" do
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> post("/api/v1/push/subscription", %{subscription: @sub})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "successful creation", %{conn: conn} do
|
||||
result =
|
||||
conn
|
||||
|> post("/api/v1/push/subscription", %{
|
||||
"data" => %{
|
||||
"alerts" => %{"mention" => true, "test" => true, "pleroma:chat_mention" => true}
|
||||
},
|
||||
"subscription" => @sub
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[subscription] = Pleroma.Repo.all(Subscription)
|
||||
|
||||
assert %{
|
||||
"alerts" => %{"mention" => true, "pleroma:chat_mention" => true},
|
||||
"endpoint" => subscription.endpoint,
|
||||
"id" => to_string(subscription.id),
|
||||
"server_key" => @server_key
|
||||
} == result
|
||||
end
|
||||
end
|
||||
|
||||
describe "gets a user subscription" do
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> get("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error when user hasn't subscription", %{conn: conn} do
|
||||
res =
|
||||
conn
|
||||
|> get("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(404)
|
||||
|
||||
assert %{"error" => "Record not found"} == res
|
||||
end
|
||||
|
||||
test "returns a user subsciption", %{conn: conn, user: user, token: token} do
|
||||
subscription =
|
||||
insert(:push_subscription,
|
||||
user: user,
|
||||
token: token,
|
||||
data: %{"alerts" => %{"mention" => true}}
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> get("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
expect = %{
|
||||
"alerts" => %{"mention" => true},
|
||||
"endpoint" => "https://example.com/example/1234",
|
||||
"id" => to_string(subscription.id),
|
||||
"server_key" => @server_key
|
||||
}
|
||||
|
||||
assert expect == res
|
||||
end
|
||||
end
|
||||
|
||||
describe "updates a user subsciption" do
|
||||
setup %{conn: conn, user: user, token: token} do
|
||||
subscription =
|
||||
insert(:push_subscription,
|
||||
user: user,
|
||||
token: token,
|
||||
data: %{"alerts" => %{"mention" => true}}
|
||||
)
|
||||
|
||||
%{conn: conn, user: user, token: token, subscription: subscription}
|
||||
end
|
||||
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns updated subsciption", %{conn: conn, subscription: subscription} do
|
||||
res =
|
||||
conn
|
||||
|> put("/api/v1/push/subscription", %{
|
||||
data: %{"alerts" => %{"mention" => false, "follow" => true}}
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
expect = %{
|
||||
"alerts" => %{"follow" => true, "mention" => false},
|
||||
"endpoint" => "https://example.com/example/1234",
|
||||
"id" => to_string(subscription.id),
|
||||
"server_key" => @server_key
|
||||
}
|
||||
|
||||
assert expect == res
|
||||
end
|
||||
end
|
||||
|
||||
describe "deletes the user subscription" do
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> delete("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error when user hasn't subscription", %{conn: conn} do
|
||||
res =
|
||||
conn
|
||||
|> delete("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(404)
|
||||
|
||||
assert %{"error" => "Record not found"} == res
|
||||
end
|
||||
|
||||
test "returns empty result and delete user subsciption", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
token: token
|
||||
} do
|
||||
subscription =
|
||||
insert(:push_subscription,
|
||||
user: user,
|
||||
token: token,
|
||||
data: %{"alerts" => %{"mention" => true}}
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> delete("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{} == res
|
||||
refute Pleroma.Repo.get(Subscription, subscription.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
setup do: oauth_access(["read"])
|
||||
|
||||
test "returns empty result", %{conn: conn} do
|
||||
res =
|
||||
conn
|
||||
|> get("/api/v1/suggestions")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert res == []
|
||||
end
|
||||
end
|
||||
|
|
@ -1,560 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "home" do
|
||||
setup do: oauth_access(["read:statuses"])
|
||||
|
||||
test "does NOT embed account/pleroma/relationship in statuses", %{
|
||||
user: user,
|
||||
conn: conn
|
||||
} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/timelines/home")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert Enum.all?(response, fn n ->
|
||||
get_in(n, ["account", "pleroma", "relationship"]) == %{}
|
||||
end)
|
||||
end
|
||||
|
||||
test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do
|
||||
{:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
{:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
|
||||
{:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
|
||||
|
||||
{:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
|
||||
conn = get(conn, "/api/v1/timelines/home?exclude_visibilities[]=direct")
|
||||
|
||||
assert status_ids = json_response_and_validate_schema(conn, :ok) |> Enum.map(& &1["id"])
|
||||
assert public_activity.id in status_ids
|
||||
assert unlisted_activity.id in status_ids
|
||||
assert private_activity.id in status_ids
|
||||
refute direct_activity.id in status_ids
|
||||
end
|
||||
end
|
||||
|
||||
describe "public" do
|
||||
@tag capture_log: true
|
||||
test "the public timeline", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
|
||||
_activity = insert(:note_activity, local: false)
|
||||
|
||||
conn = get(conn, "/api/v1/timelines/public?local=False")
|
||||
|
||||
assert length(json_response_and_validate_schema(conn, :ok)) == 2
|
||||
|
||||
conn = get(build_conn(), "/api/v1/timelines/public?local=True")
|
||||
|
||||
assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok)
|
||||
|
||||
conn = get(build_conn(), "/api/v1/timelines/public?local=1")
|
||||
|
||||
assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok)
|
||||
|
||||
# does not contain repeats
|
||||
{:ok, _} = CommonAPI.repeat(activity.id, user)
|
||||
|
||||
conn = get(build_conn(), "/api/v1/timelines/public?local=true")
|
||||
|
||||
assert [_] = json_response_and_validate_schema(conn, :ok)
|
||||
end
|
||||
|
||||
test "the public timeline includes only public statuses for an authenticated user" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "private"})
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "unlisted"})
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "direct"})
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
|
||||
end
|
||||
|
||||
test "doesn't return replies if follower is posting with blocked user" do
|
||||
%{conn: conn, user: blocker} = oauth_access(["read:statuses"])
|
||||
[blockee, friend] = insert_list(2, :user)
|
||||
{:ok, blocker} = User.follow(blocker, friend)
|
||||
{:ok, _} = User.block(blocker, blockee)
|
||||
|
||||
conn = assign(conn, :user, blocker)
|
||||
|
||||
{:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"})
|
||||
|
||||
{:ok, reply_from_blockee} =
|
||||
CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity})
|
||||
|
||||
{:ok, _reply_from_friend} =
|
||||
CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee})
|
||||
|
||||
# Still shows replies from yourself
|
||||
{:ok, %{id: reply_from_me}} =
|
||||
CommonAPI.post(blocker, %{status: "status", in_reply_to_status_id: reply_from_blockee})
|
||||
|
||||
response =
|
||||
get(conn, "/api/v1/timelines/public")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert length(response) == 2
|
||||
[%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response
|
||||
end
|
||||
|
||||
test "doesn't return replies if follow is posting with users from blocked domain" do
|
||||
%{conn: conn, user: blocker} = oauth_access(["read:statuses"])
|
||||
friend = insert(:user)
|
||||
blockee = insert(:user, ap_id: "https://example.com/users/blocked")
|
||||
{:ok, blocker} = User.follow(blocker, friend)
|
||||
{:ok, blocker} = User.block_domain(blocker, "example.com")
|
||||
|
||||
conn = assign(conn, :user, blocker)
|
||||
|
||||
{:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"})
|
||||
|
||||
{:ok, reply_from_blockee} =
|
||||
CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity})
|
||||
|
||||
{:ok, _reply_from_friend} =
|
||||
CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee})
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public")
|
||||
|
||||
activities = json_response_and_validate_schema(res_conn, 200)
|
||||
[%{"id" => ^activity_id}] = activities
|
||||
end
|
||||
end
|
||||
|
||||
defp local_and_remote_activities do
|
||||
insert(:note_activity)
|
||||
insert(:note_activity, local: false)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "public with restrict unauthenticated timeline for local and federated timelines" do
|
||||
setup do: local_and_remote_activities()
|
||||
|
||||
setup do: clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
|
||||
setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
test "if user is unauthenticated", %{conn: conn} do
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=true")
|
||||
|
||||
assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
|
||||
"error" => "authorization required for timeline view"
|
||||
}
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=false")
|
||||
|
||||
assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
|
||||
"error" => "authorization required for timeline view"
|
||||
}
|
||||
end
|
||||
|
||||
test "if user is authenticated" do
|
||||
%{conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=true")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=false")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "public with restrict unauthenticated timeline for local" do
|
||||
setup do: local_and_remote_activities()
|
||||
|
||||
setup do: clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
|
||||
test "if user is unauthenticated", %{conn: conn} do
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=true")
|
||||
|
||||
assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
|
||||
"error" => "authorization required for timeline view"
|
||||
}
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=false")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
|
||||
test "if user is authenticated", %{conn: _conn} do
|
||||
%{conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=true")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=false")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "public with restrict unauthenticated timeline for remote" do
|
||||
setup do: local_and_remote_activities()
|
||||
|
||||
setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
test "if user is unauthenticated", %{conn: conn} do
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=true")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=false")
|
||||
|
||||
assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
|
||||
"error" => "authorization required for timeline view"
|
||||
}
|
||||
end
|
||||
|
||||
test "if user is authenticated", %{conn: _conn} do
|
||||
%{conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=true")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 1
|
||||
|
||||
res_conn = get(conn, "/api/v1/timelines/public?local=false")
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "direct" do
|
||||
test "direct timeline", %{conn: conn} do
|
||||
user_one = insert(:user)
|
||||
user_two = insert(:user)
|
||||
|
||||
{:ok, user_two} = User.follow(user_two, user_one)
|
||||
|
||||
{:ok, direct} =
|
||||
CommonAPI.post(user_one, %{
|
||||
status: "Hi @#{user_two.nickname}!",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, _follower_only} =
|
||||
CommonAPI.post(user_one, %{
|
||||
status: "Hi @#{user_two.nickname}!",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
conn_user_two =
|
||||
conn
|
||||
|> assign(:user, user_two)
|
||||
|> assign(:token, insert(:oauth_token, user: user_two, scopes: ["read:statuses"]))
|
||||
|
||||
# Only direct should be visible here
|
||||
res_conn = get(conn_user_two, "api/v1/timelines/direct")
|
||||
|
||||
assert [status] = json_response_and_validate_schema(res_conn, :ok)
|
||||
|
||||
assert %{"visibility" => "direct"} = status
|
||||
assert status["url"] != direct.data["id"]
|
||||
|
||||
# User should be able to see their own direct message
|
||||
res_conn =
|
||||
build_conn()
|
||||
|> assign(:user, user_one)
|
||||
|> assign(:token, insert(:oauth_token, user: user_one, scopes: ["read:statuses"]))
|
||||
|> get("api/v1/timelines/direct")
|
||||
|
||||
[status] = json_response_and_validate_schema(res_conn, :ok)
|
||||
|
||||
assert %{"visibility" => "direct"} = status
|
||||
|
||||
# Both should be visible here
|
||||
res_conn = get(conn_user_two, "api/v1/timelines/home")
|
||||
|
||||
[_s1, _s2] = json_response_and_validate_schema(res_conn, :ok)
|
||||
|
||||
# Test pagination
|
||||
Enum.each(1..20, fn _ ->
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user_one, %{
|
||||
status: "Hi @#{user_two.nickname}!",
|
||||
visibility: "direct"
|
||||
})
|
||||
end)
|
||||
|
||||
res_conn = get(conn_user_two, "api/v1/timelines/direct")
|
||||
|
||||
statuses = json_response_and_validate_schema(res_conn, :ok)
|
||||
assert length(statuses) == 20
|
||||
|
||||
max_id = List.last(statuses)["id"]
|
||||
|
||||
res_conn = get(conn_user_two, "api/v1/timelines/direct?max_id=#{max_id}")
|
||||
|
||||
assert [status] = json_response_and_validate_schema(res_conn, :ok)
|
||||
|
||||
assert status["url"] != direct.data["id"]
|
||||
end
|
||||
|
||||
test "doesn't include DMs from blocked users" do
|
||||
%{user: blocker, conn: conn} = oauth_access(["read:statuses"])
|
||||
blocked = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(blocker, blocked)
|
||||
|
||||
{:ok, _blocked_direct} =
|
||||
CommonAPI.post(blocked, %{
|
||||
status: "Hi @#{blocker.nickname}!",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, direct} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Hi @#{blocker.nickname}!",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
res_conn = get(conn, "api/v1/timelines/direct")
|
||||
|
||||
[status] = json_response_and_validate_schema(res_conn, :ok)
|
||||
assert status["id"] == direct.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "list" do
|
||||
setup do: oauth_access(["read:lists"])
|
||||
|
||||
test "does not contain retoots", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."})
|
||||
{:ok, activity_two} = CommonAPI.post(other_user, %{status: "Marisa is stupid."})
|
||||
{:ok, _} = CommonAPI.repeat(activity_one.id, other_user)
|
||||
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
|
||||
conn = get(conn, "/api/v1/timelines/list/#{list.id}")
|
||||
|
||||
assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok)
|
||||
|
||||
assert id == to_string(activity_two.id)
|
||||
end
|
||||
|
||||
test "works with pagination", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
|
||||
Enum.each(1..30, fn i ->
|
||||
CommonAPI.post(other_user, %{status: "post number #{i}"})
|
||||
end)
|
||||
|
||||
res =
|
||||
get(conn, "/api/v1/timelines/list/#{list.id}?limit=1")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert length(res) == 1
|
||||
|
||||
[first] = res
|
||||
|
||||
res =
|
||||
get(conn, "/api/v1/timelines/list/#{list.id}?max_id=#{first["id"]}&limit=30")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert length(res) == 29
|
||||
end
|
||||
|
||||
test "list timeline", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
{:ok, _activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."})
|
||||
{:ok, activity_two} = CommonAPI.post(other_user, %{status: "Marisa is cute."})
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
|
||||
conn = get(conn, "/api/v1/timelines/list/#{list.id}")
|
||||
|
||||
assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok)
|
||||
|
||||
assert id == to_string(activity_two.id)
|
||||
end
|
||||
|
||||
test "list timeline does not leak non-public statuses for unfollowed users", %{
|
||||
user: user,
|
||||
conn: conn
|
||||
} do
|
||||
other_user = insert(:user)
|
||||
{:ok, activity_one} = CommonAPI.post(other_user, %{status: "Marisa is cute."})
|
||||
|
||||
{:ok, _activity_two} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Marisa is cute.",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||
|
||||
conn = get(conn, "/api/v1/timelines/list/#{list.id}")
|
||||
|
||||
assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok)
|
||||
|
||||
assert id == to_string(activity_one.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "hashtag" do
|
||||
setup do: oauth_access(["n/a"])
|
||||
|
||||
@tag capture_log: true
|
||||
test "hashtag timeline", %{conn: conn} do
|
||||
following = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(following, %{status: "test #2hu"})
|
||||
|
||||
nconn = get(conn, "/api/v1/timelines/tag/2hu")
|
||||
|
||||
assert [%{"id" => id}] = json_response_and_validate_schema(nconn, :ok)
|
||||
|
||||
assert id == to_string(activity.id)
|
||||
|
||||
# works for different capitalization too
|
||||
nconn = get(conn, "/api/v1/timelines/tag/2HU")
|
||||
|
||||
assert [%{"id" => id}] = json_response_and_validate_schema(nconn, :ok)
|
||||
|
||||
assert id == to_string(activity.id)
|
||||
end
|
||||
|
||||
test "multi-hashtag timeline", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity_test} = CommonAPI.post(user, %{status: "#test"})
|
||||
{:ok, activity_test1} = CommonAPI.post(user, %{status: "#test #test1"})
|
||||
{:ok, activity_none} = CommonAPI.post(user, %{status: "#test #none"})
|
||||
|
||||
any_test = get(conn, "/api/v1/timelines/tag/test?any[]=test1")
|
||||
|
||||
[status_none, status_test1, status_test] = json_response_and_validate_schema(any_test, :ok)
|
||||
|
||||
assert to_string(activity_test.id) == status_test["id"]
|
||||
assert to_string(activity_test1.id) == status_test1["id"]
|
||||
assert to_string(activity_none.id) == status_none["id"]
|
||||
|
||||
restricted_test = get(conn, "/api/v1/timelines/tag/test?all[]=test1&none[]=none")
|
||||
|
||||
assert [status_test1] == json_response_and_validate_schema(restricted_test, :ok)
|
||||
|
||||
all_test = get(conn, "/api/v1/timelines/tag/test?all[]=none")
|
||||
|
||||
assert [status_none] == json_response_and_validate_schema(all_test, :ok)
|
||||
end
|
||||
end
|
||||
|
||||
describe "hashtag timeline handling of :restrict_unauthenticated setting" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"})
|
||||
{:ok, _activity2} = CommonAPI.post(user, %{status: "test #tag1"})
|
||||
|
||||
activity1
|
||||
|> Ecto.Changeset.change(%{local: false})
|
||||
|> Pleroma.Repo.update()
|
||||
|
||||
base_uri = "/api/v1/timelines/tag/tag1"
|
||||
error_response = %{"error" => "authorization required for timeline view"}
|
||||
|
||||
%{base_uri: base_uri, error_response: error_response}
|
||||
end
|
||||
|
||||
defp ensure_authenticated_access(base_uri) do
|
||||
%{conn: auth_conn} = oauth_access(["read:statuses"])
|
||||
|
||||
res_conn = get(auth_conn, "#{base_uri}?local=true")
|
||||
assert length(json_response(res_conn, 200)) == 1
|
||||
|
||||
res_conn = get(auth_conn, "#{base_uri}?local=false")
|
||||
assert length(json_response(res_conn, 200)) == 2
|
||||
end
|
||||
|
||||
test "with default settings on private instances, returns 403 for unauthenticated users", %{
|
||||
conn: conn,
|
||||
base_uri: base_uri,
|
||||
error_response: error_response
|
||||
} do
|
||||
clear_config([:instance, :public], false)
|
||||
clear_config([:restrict_unauthenticated, :timelines])
|
||||
|
||||
for local <- [true, false] do
|
||||
res_conn = get(conn, "#{base_uri}?local=#{local}")
|
||||
|
||||
assert json_response(res_conn, :unauthorized) == error_response
|
||||
end
|
||||
|
||||
ensure_authenticated_access(base_uri)
|
||||
end
|
||||
|
||||
test "with `%{local: true, federated: true}`, returns 403 for unauthenticated users", %{
|
||||
conn: conn,
|
||||
base_uri: base_uri,
|
||||
error_response: error_response
|
||||
} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
for local <- [true, false] do
|
||||
res_conn = get(conn, "#{base_uri}?local=#{local}")
|
||||
|
||||
assert json_response(res_conn, :unauthorized) == error_response
|
||||
end
|
||||
|
||||
ensure_authenticated_access(base_uri)
|
||||
end
|
||||
|
||||
test "with `%{local: false, federated: true}`, forbids unauthenticated access to federated timeline",
|
||||
%{conn: conn, base_uri: base_uri, error_response: error_response} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], false)
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
res_conn = get(conn, "#{base_uri}?local=true")
|
||||
assert length(json_response(res_conn, 200)) == 1
|
||||
|
||||
res_conn = get(conn, "#{base_uri}?local=false")
|
||||
assert json_response(res_conn, :unauthorized) == error_response
|
||||
|
||||
ensure_authenticated_access(base_uri)
|
||||
end
|
||||
|
||||
test "with `%{local: true, federated: false}`, forbids unauthenticated access to public timeline" <>
|
||||
"(but not to local public activities which are delivered as part of federated timeline)",
|
||||
%{conn: conn, base_uri: base_uri, error_response: error_response} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], false)
|
||||
|
||||
res_conn = get(conn, "#{base_uri}?local=true")
|
||||
assert json_response(res_conn, :unauthorized) == error_response
|
||||
|
||||
# Note: local activities get delivered as part of federated timeline
|
||||
res_conn = get(conn, "#{base_uri}?local=false")
|
||||
assert length(json_response(res_conn, 200)) == 2
|
||||
|
||||
ensure_authenticated_access(base_uri)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
describe "empty_array/2 (stubs)" do
|
||||
test "GET /api/v1/accounts/:id/identity_proofs" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:accounts"])
|
||||
|
||||
assert [] ==
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/identity_proofs")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "GET /api/v1/endorsements" do
|
||||
%{conn: conn} = oauth_access(["read:accounts"])
|
||||
|
||||
assert [] ==
|
||||
conn
|
||||
|> get("/api/v1/endorsements")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "GET /api/v1/trends", %{conn: conn} do
|
||||
assert [] ==
|
||||
conn
|
||||
|> get("/api/v1/trends")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.ScheduledActivity
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "follow/3" do
|
||||
test "returns error when followed user is deactivated" do
|
||||
follower = insert(:user)
|
||||
user = insert(:user, local: true, deactivated: true)
|
||||
assert {:error, _error} = MastodonAPI.follow(follower, user)
|
||||
end
|
||||
|
||||
test "following for user" do
|
||||
follower = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, follower} = MastodonAPI.follow(follower, user)
|
||||
assert User.following?(follower, user)
|
||||
end
|
||||
|
||||
test "returns ok if user already followed" do
|
||||
follower = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, follower} = User.follow(follower, user)
|
||||
{:ok, follower} = MastodonAPI.follow(follower, refresh_record(user))
|
||||
assert User.following?(follower, user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_followers/2" do
|
||||
test "returns user followers" do
|
||||
follower1_user = insert(:user)
|
||||
follower2_user = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, _follower1_user} = User.follow(follower1_user, user)
|
||||
{:ok, follower2_user} = User.follow(follower2_user, user)
|
||||
|
||||
assert MastodonAPI.get_followers(user, %{"limit" => 1}) == [follower2_user]
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_friends/2" do
|
||||
test "returns user friends" do
|
||||
user = insert(:user)
|
||||
followed_one = insert(:user)
|
||||
followed_two = insert(:user)
|
||||
followed_three = insert(:user)
|
||||
|
||||
{:ok, user} = User.follow(user, followed_one)
|
||||
{:ok, user} = User.follow(user, followed_two)
|
||||
{:ok, user} = User.follow(user, followed_three)
|
||||
res = MastodonAPI.get_friends(user)
|
||||
|
||||
assert length(res) == 3
|
||||
assert Enum.member?(res, refresh_record(followed_three))
|
||||
assert Enum.member?(res, refresh_record(followed_two))
|
||||
assert Enum.member?(res, refresh_record(followed_one))
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_notifications/2" do
|
||||
test "returns notifications for user" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
|
||||
|
||||
{:ok, status1} = CommonAPI.post(user, %{status: "Magi"})
|
||||
{:ok, [notification]} = Notification.create_notifications(status)
|
||||
{:ok, [notification1]} = Notification.create_notifications(status1)
|
||||
res = MastodonAPI.get_notifications(subscriber)
|
||||
|
||||
assert Enum.member?(Enum.map(res, & &1.id), notification.id)
|
||||
assert Enum.member?(Enum.map(res, & &1.id), notification1.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_scheduled_activities/2" do
|
||||
test "returns user scheduled activities" do
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(6), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
attrs = %{params: %{}, scheduled_at: today}
|
||||
{:ok, schedule} = ScheduledActivity.create(user, attrs)
|
||||
assert MastodonAPI.get_scheduled_activities(user) == [schedule]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,575 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserRelationship
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "Represent a user account" do
|
||||
background_image = %{
|
||||
"url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]
|
||||
}
|
||||
|
||||
user =
|
||||
insert(:user, %{
|
||||
follower_count: 3,
|
||||
note_count: 5,
|
||||
background: background_image,
|
||||
nickname: "shp@shitposter.club",
|
||||
name: ":karjalanpiirakka: shp",
|
||||
bio:
|
||||
"<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
|
||||
inserted_at: ~N[2017-08-15 15:47:06.597036],
|
||||
emoji: %{"karjalanpiirakka" => "/file.png"},
|
||||
raw_bio: "valid html. a\nb\nc\nd\nf '&<>\""
|
||||
})
|
||||
|
||||
expected = %{
|
||||
id: to_string(user.id),
|
||||
username: "shp",
|
||||
acct: user.nickname,
|
||||
display_name: user.name,
|
||||
locked: false,
|
||||
created_at: "2017-08-15T15:47:06.000Z",
|
||||
followers_count: 3,
|
||||
following_count: 0,
|
||||
statuses_count: 5,
|
||||
note: "<span>valid html</span>. a<br/>b<br/>c<br/>d<br/>f '&<>"",
|
||||
url: user.ap_id,
|
||||
avatar: "http://localhost:4001/images/avi.png",
|
||||
avatar_static: "http://localhost:4001/images/avi.png",
|
||||
header: "http://localhost:4001/images/banner.png",
|
||||
header_static: "http://localhost:4001/images/banner.png",
|
||||
emojis: [
|
||||
%{
|
||||
static_url: "/file.png",
|
||||
url: "/file.png",
|
||||
shortcode: "karjalanpiirakka",
|
||||
visible_in_picker: false
|
||||
}
|
||||
],
|
||||
fields: [],
|
||||
bot: false,
|
||||
source: %{
|
||||
note: "valid html. a\nb\nc\nd\nf '&<>\"",
|
||||
sensitive: false,
|
||||
pleroma: %{
|
||||
actor_type: "Person",
|
||||
discoverable: true
|
||||
},
|
||||
fields: []
|
||||
},
|
||||
pleroma: %{
|
||||
ap_id: user.ap_id,
|
||||
background_image: "https://example.com/images/asuka_hospital.png",
|
||||
favicon: nil,
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
hide_followers_count: false,
|
||||
hide_follows_count: false,
|
||||
relationship: %{},
|
||||
skip_thread_containment: false,
|
||||
accepts_chat_messages: nil
|
||||
}
|
||||
}
|
||||
|
||||
assert expected == AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
end
|
||||
|
||||
describe "favicon" do
|
||||
setup do
|
||||
[user: insert(:user)]
|
||||
end
|
||||
|
||||
test "is parsed when :instance_favicons is enabled", %{user: user} do
|
||||
clear_config([:instances_favicons, :enabled], true)
|
||||
|
||||
assert %{
|
||||
pleroma: %{
|
||||
favicon:
|
||||
"https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png"
|
||||
}
|
||||
} = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
end
|
||||
|
||||
test "is nil when :instances_favicons is disabled", %{user: user} do
|
||||
assert %{pleroma: %{favicon: nil}} =
|
||||
AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
end
|
||||
end
|
||||
|
||||
test "Represent the user account for the account owner" do
|
||||
user = insert(:user)
|
||||
|
||||
notification_settings = %{
|
||||
block_from_strangers: false,
|
||||
hide_notification_contents: false
|
||||
}
|
||||
|
||||
privacy = user.default_scope
|
||||
|
||||
assert %{
|
||||
pleroma: %{notification_settings: ^notification_settings, allow_following_move: true},
|
||||
source: %{privacy: ^privacy}
|
||||
} = AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "Represent a Service(bot) account" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
follower_count: 3,
|
||||
note_count: 5,
|
||||
actor_type: "Service",
|
||||
nickname: "shp@shitposter.club",
|
||||
inserted_at: ~N[2017-08-15 15:47:06.597036]
|
||||
})
|
||||
|
||||
expected = %{
|
||||
id: to_string(user.id),
|
||||
username: "shp",
|
||||
acct: user.nickname,
|
||||
display_name: user.name,
|
||||
locked: false,
|
||||
created_at: "2017-08-15T15:47:06.000Z",
|
||||
followers_count: 3,
|
||||
following_count: 0,
|
||||
statuses_count: 5,
|
||||
note: user.bio,
|
||||
url: user.ap_id,
|
||||
avatar: "http://localhost:4001/images/avi.png",
|
||||
avatar_static: "http://localhost:4001/images/avi.png",
|
||||
header: "http://localhost:4001/images/banner.png",
|
||||
header_static: "http://localhost:4001/images/banner.png",
|
||||
emojis: [],
|
||||
fields: [],
|
||||
bot: true,
|
||||
source: %{
|
||||
note: user.bio,
|
||||
sensitive: false,
|
||||
pleroma: %{
|
||||
actor_type: "Service",
|
||||
discoverable: true
|
||||
},
|
||||
fields: []
|
||||
},
|
||||
pleroma: %{
|
||||
ap_id: user.ap_id,
|
||||
background_image: nil,
|
||||
favicon: nil,
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
hide_followers_count: false,
|
||||
hide_follows_count: false,
|
||||
relationship: %{},
|
||||
skip_thread_containment: false,
|
||||
accepts_chat_messages: nil
|
||||
}
|
||||
}
|
||||
|
||||
assert expected == AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
end
|
||||
|
||||
test "Represent a Funkwhale channel" do
|
||||
{:ok, user} =
|
||||
User.get_or_fetch_by_ap_id(
|
||||
"https://channels.tests.funkwhale.audio/federation/actors/compositions"
|
||||
)
|
||||
|
||||
assert represented =
|
||||
AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
|
||||
assert represented.acct == "compositions@channels.tests.funkwhale.audio"
|
||||
assert represented.url == "https://channels.tests.funkwhale.audio/channels/compositions"
|
||||
end
|
||||
|
||||
test "Represent a deactivated user for an admin" do
|
||||
admin = insert(:user, is_admin: true)
|
||||
deactivated_user = insert(:user, deactivated: true)
|
||||
represented = AccountView.render("show.json", %{user: deactivated_user, for: admin})
|
||||
assert represented[:pleroma][:deactivated] == true
|
||||
end
|
||||
|
||||
test "Represent a smaller mention" do
|
||||
user = insert(:user)
|
||||
|
||||
expected = %{
|
||||
id: to_string(user.id),
|
||||
acct: user.nickname,
|
||||
username: user.nickname,
|
||||
url: user.ap_id
|
||||
}
|
||||
|
||||
assert expected == AccountView.render("mention.json", %{user: user})
|
||||
end
|
||||
|
||||
test "demands :for or :skip_visibility_check option for account rendering" do
|
||||
clear_config([:restrict_unauthenticated, :profiles, :local], false)
|
||||
|
||||
user = insert(:user)
|
||||
user_id = user.id
|
||||
|
||||
assert %{id: ^user_id} = AccountView.render("show.json", %{user: user, for: nil})
|
||||
assert %{id: ^user_id} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
assert %{id: ^user_id} =
|
||||
AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
|
||||
assert_raise RuntimeError, ~r/:skip_visibility_check or :for option is required/, fn ->
|
||||
AccountView.render("show.json", %{user: user})
|
||||
end
|
||||
end
|
||||
|
||||
describe "relationship" do
|
||||
defp test_relationship_rendering(user, other_user, expected_result) do
|
||||
opts = %{user: user, target: other_user, relationships: nil}
|
||||
assert expected_result == AccountView.render("relationship.json", opts)
|
||||
|
||||
relationships_opt = UserRelationship.view_relationships_option(user, [other_user])
|
||||
opts = Map.put(opts, :relationships, relationships_opt)
|
||||
assert expected_result == AccountView.render("relationship.json", opts)
|
||||
|
||||
assert [expected_result] ==
|
||||
AccountView.render("relationships.json", %{user: user, targets: [other_user]})
|
||||
end
|
||||
|
||||
@blank_response %{
|
||||
following: false,
|
||||
followed_by: false,
|
||||
blocking: false,
|
||||
blocked_by: false,
|
||||
muting: false,
|
||||
muting_notifications: false,
|
||||
subscribing: false,
|
||||
requested: false,
|
||||
domain_blocking: false,
|
||||
showing_reblogs: true,
|
||||
endorsed: false
|
||||
}
|
||||
|
||||
test "represent a relationship for the following and followed user" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, user} = User.follow(user, other_user)
|
||||
{:ok, other_user} = User.follow(other_user, user)
|
||||
{:ok, _subscription} = User.subscribe(user, other_user)
|
||||
{:ok, _user_relationships} = User.mute(user, other_user, true)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, other_user)
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{
|
||||
following: true,
|
||||
followed_by: true,
|
||||
muting: true,
|
||||
muting_notifications: true,
|
||||
subscribing: true,
|
||||
showing_reblogs: false,
|
||||
id: to_string(other_user.id)
|
||||
}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "represent a relationship for the blocking and blocked user" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, user} = User.follow(user, other_user)
|
||||
{:ok, _subscription} = User.subscribe(user, other_user)
|
||||
{:ok, _user_relationship} = User.block(user, other_user)
|
||||
{:ok, _user_relationship} = User.block(other_user, user)
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{following: false, blocking: true, blocked_by: true, id: to_string(other_user.id)}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "represent a relationship for the user blocking a domain" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, ap_id: "https://bad.site/users/other_user")
|
||||
|
||||
{:ok, user} = User.block_domain(user, "bad.site")
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{domain_blocking: true, blocking: false, id: to_string(other_user.id)}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "represent a relationship for the user with a pending follow request" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, locked: true)
|
||||
|
||||
{:ok, user, other_user, _} = CommonAPI.follow(user, other_user)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{requested: true, following: false, id: to_string(other_user.id)}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
|
||||
user = insert(:user, pleroma_settings_store: %{fe: "test"})
|
||||
|
||||
result =
|
||||
AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
|
||||
|
||||
assert result.pleroma.settings_store == %{:fe => "test"}
|
||||
|
||||
result = AccountView.render("show.json", %{user: user, for: nil, with_pleroma_settings: true})
|
||||
assert result.pleroma[:settings_store] == nil
|
||||
|
||||
result = AccountView.render("show.json", %{user: user, for: user})
|
||||
assert result.pleroma[:settings_store] == nil
|
||||
end
|
||||
|
||||
test "doesn't sanitize display names" do
|
||||
user = insert(:user, name: "<marquee> username </marquee>")
|
||||
result = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
assert result.display_name == "<marquee> username </marquee>"
|
||||
end
|
||||
|
||||
test "never display nil user follow counts" do
|
||||
user = insert(:user, following_count: 0, follower_count: 0)
|
||||
result = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
|
||||
assert result.following_count == 0
|
||||
assert result.followers_count == 0
|
||||
end
|
||||
|
||||
describe "hiding follows/following" do
|
||||
test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
hide_followers: true,
|
||||
hide_followers_count: true,
|
||||
hide_follows: true,
|
||||
hide_follows_count: true
|
||||
})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{
|
||||
followers_count: 0,
|
||||
following_count: 0,
|
||||
pleroma: %{hide_follows_count: true, hide_followers_count: true}
|
||||
} = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
end
|
||||
|
||||
test "shows when follows/followers are hidden" do
|
||||
user = insert(:user, hide_followers: true, hide_follows: true)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{
|
||||
followers_count: 1,
|
||||
following_count: 1,
|
||||
pleroma: %{hide_follows: true, hide_followers: true}
|
||||
} = AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
end
|
||||
|
||||
test "shows actual follower/following count to the account owner" do
|
||||
user = insert(:user, hide_followers: true, hide_follows: true)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert User.following?(user, other_user)
|
||||
assert Pleroma.FollowingRelationship.follower_count(other_user) == 1
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{
|
||||
followers_count: 1,
|
||||
following_count: 1
|
||||
} = AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "shows unread_conversation_count only to the account owner" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Hey @#{user.nickname}.",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert AccountView.render("show.json", %{user: user, for: other_user})[:pleroma][
|
||||
:unread_conversation_count
|
||||
] == nil
|
||||
|
||||
assert AccountView.render("show.json", %{user: user, for: user})[:pleroma][
|
||||
:unread_conversation_count
|
||||
] == 1
|
||||
end
|
||||
|
||||
test "shows unread_count only to the account owner" do
|
||||
user = insert(:user)
|
||||
insert_list(7, :notification, user: user, activity: insert(:note_activity))
|
||||
other_user = insert(:user)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert AccountView.render(
|
||||
"show.json",
|
||||
%{user: user, for: other_user}
|
||||
)[:pleroma][:unread_notifications_count] == nil
|
||||
|
||||
assert AccountView.render(
|
||||
"show.json",
|
||||
%{user: user, for: user}
|
||||
)[:pleroma][:unread_notifications_count] == 7
|
||||
end
|
||||
end
|
||||
|
||||
describe "follow requests counter" do
|
||||
test "shows zero when no follow requests are pending" do
|
||||
user = insert(:user)
|
||||
|
||||
assert %{follow_requests_count: 0} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{follow_requests_count: 0} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "shows non-zero when follow requests are pending" do
|
||||
user = insert(:user, locked: true)
|
||||
|
||||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "decreases when accepting a follow request" do
|
||||
user = insert(:user, locked: true)
|
||||
|
||||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
{:ok, _other_user} = CommonAPI.accept_follow_request(other_user, user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 0} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "decreases when rejecting a follow request" do
|
||||
user = insert(:user, locked: true)
|
||||
|
||||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
{:ok, _other_user} = CommonAPI.reject_follow_request(other_user, user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 0} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "shows non-zero when historical unapproved requests are present" do
|
||||
user = insert(:user, locked: true)
|
||||
|
||||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
{:ok, user} = User.update_and_set_cache(user, %{locked: false})
|
||||
|
||||
assert %{locked: false, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
end
|
||||
|
||||
test "uses mediaproxy urls when it's enabled (regardless of media preview proxy state)" do
|
||||
clear_config([:media_proxy, :enabled], true)
|
||||
clear_config([:media_preview_proxy, :enabled])
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
avatar: %{"url" => [%{"href" => "https://evil.website/avatar.png"}]},
|
||||
banner: %{"url" => [%{"href" => "https://evil.website/banner.png"}]},
|
||||
emoji: %{"joker_smile" => "https://evil.website/society.png"}
|
||||
)
|
||||
|
||||
with media_preview_enabled <- [false, true] do
|
||||
Config.put([:media_preview_proxy, :enabled], media_preview_enabled)
|
||||
|
||||
AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
|> Enum.all?(fn
|
||||
{key, url} when key in [:avatar, :avatar_static, :header, :header_static] ->
|
||||
String.starts_with?(url, Pleroma.Web.base_url())
|
||||
|
||||
{:emojis, emojis} ->
|
||||
Enum.all?(emojis, fn %{url: url, static_url: static_url} ->
|
||||
String.starts_with?(url, Pleroma.Web.base_url()) &&
|
||||
String.starts_with?(static_url, Pleroma.Web.base_url())
|
||||
end)
|
||||
|
||||
_ ->
|
||||
true
|
||||
end)
|
||||
|> assert()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ConversationViewTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.ConversationView
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "represents a Mastodon Conversation entity" 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",
|
||||
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)
|
||||
|
||||
assert participation
|
||||
|
||||
conversation =
|
||||
ConversationView.render("participation.json", %{participation: participation, for: user})
|
||||
|
||||
assert conversation.id == participation.id |> to_string()
|
||||
assert conversation.last_status.id == activity.id
|
||||
|
||||
assert [account] = conversation.accounts
|
||||
assert account.id == other_user.id
|
||||
assert conversation.last_status.pleroma.direct_conversation_id == participation.id
|
||||
end
|
||||
end
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ListViewTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Web.MastodonAPI.ListView
|
||||
|
||||
test "show" do
|
||||
user = insert(:user)
|
||||
title = "mortal enemies"
|
||||
{:ok, list} = Pleroma.List.create(title, user)
|
||||
|
||||
expected = %{
|
||||
id: to_string(list.id),
|
||||
title: title
|
||||
}
|
||||
|
||||
assert expected == ListView.render("show.json", %{list: list})
|
||||
end
|
||||
|
||||
test "index" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, list} = Pleroma.List.create("my list", user)
|
||||
{:ok, list2} = Pleroma.List.create("cofe", user)
|
||||
|
||||
assert [%{id: _, title: "my list"}, %{id: _, title: "cofe"}] =
|
||||
ListView.render("index.json", lists: [list, list2])
|
||||
end
|
||||
end
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MarkerViewTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Web.MastodonAPI.MarkerView
|
||||
import Pleroma.Factory
|
||||
|
||||
test "returns markers" do
|
||||
marker1 = insert(:marker, timeline: "notifications", last_read_id: "17", unread_count: 5)
|
||||
marker2 = insert(:marker, timeline: "home", last_read_id: "42")
|
||||
|
||||
assert MarkerView.render("markers.json", %{markers: [marker1, marker2]}) == %{
|
||||
"home" => %{
|
||||
last_read_id: "42",
|
||||
updated_at: NaiveDateTime.to_iso8601(marker2.updated_at),
|
||||
version: 0,
|
||||
pleroma: %{unread_count: 0}
|
||||
},
|
||||
"notifications" => %{
|
||||
last_read_id: "17",
|
||||
updated_at: NaiveDateTime.to_iso8601(marker1.updated_at),
|
||||
version: 0,
|
||||
pleroma: %{unread_count: 5}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
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
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
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
|
||||
result = NotificationView.render("index.json", %{notifications: notifications, for: user})
|
||||
|
||||
assert expected_result == result
|
||||
|
||||
result =
|
||||
NotificationView.render("index.json", %{
|
||||
notifications: notifications,
|
||||
for: user,
|
||||
relationships: nil
|
||||
})
|
||||
|
||||
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, is_muted: 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)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{mentioned_user.nickname}"})
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "mention",
|
||||
account:
|
||||
AccountView.render("show.json", %{
|
||||
user: user,
|
||||
for: mentioned_user
|
||||
}),
|
||||
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], mentioned_user, [expected])
|
||||
end
|
||||
|
||||
test "Favourite notification" do
|
||||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
|
||||
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
||||
create_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "favourite",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
status: StatusView.render("show.json", %{activity: create_activity, for: user}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], user, [expected])
|
||||
end
|
||||
|
||||
test "Reblog notification" do
|
||||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, another_user)
|
||||
{:ok, [notification]} = Notification.create_notifications(reblog_activity)
|
||||
reblog_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "reblog",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
status: StatusView.render("show.json", %{activity: reblog_activity, for: user}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], user, [expected])
|
||||
end
|
||||
|
||||
test "Follow notification" do
|
||||
follower = insert(:user)
|
||||
followed = insert(:user)
|
||||
{:ok, follower, followed, _activity} = CommonAPI.follow(follower, followed)
|
||||
notification = Notification |> Repo.one() |> Repo.preload(:activity)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "follow",
|
||||
account: AccountView.render("show.json", %{user: follower, for: followed}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], followed, [expected])
|
||||
|
||||
User.perform(:delete, follower)
|
||||
refute Repo.one(Notification)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "Move notification" do
|
||||
old_user = insert(:user)
|
||||
new_user = insert(:user, also_known_as: [old_user.ap_id])
|
||||
follower = insert(:user)
|
||||
|
||||
old_user_url = old_user.ap_id
|
||||
|
||||
body =
|
||||
File.read!("test/fixtures/users_mock/localhost.json")
|
||||
|> String.replace("{{nickname}}", old_user.nickname)
|
||||
|> Jason.encode!()
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get, url: ^old_user_url} ->
|
||||
%Tesla.Env{status: 200, body: body}
|
||||
end)
|
||||
|
||||
User.follow(follower, old_user)
|
||||
Pleroma.Web.ActivityPub.ActivityPub.move(old_user, new_user)
|
||||
Pleroma.Tests.ObanHelpers.perform_all()
|
||||
|
||||
old_user = refresh_record(old_user)
|
||||
new_user = refresh_record(new_user)
|
||||
|
||||
[notification] = Notification.for_user(follower)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "move",
|
||||
account: AccountView.render("show.json", %{user: old_user, for: follower}),
|
||||
target: AccountView.render("show.json", %{user: new_user, for: follower}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], follower, [expected])
|
||||
end
|
||||
|
||||
test "EmojiReact notification" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
|
||||
{:ok, _activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
|
||||
[notification] = Notification.for_user(user)
|
||||
|
||||
assert notification
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:emoji_reaction",
|
||||
emoji: "☕",
|
||||
account: AccountView.render("show.json", %{user: other_user, for: user}),
|
||||
status: StatusView.render("show.json", %{activity: activity, for: user}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], user, [expected])
|
||||
end
|
||||
|
||||
test "muted notification" do
|
||||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, _} = Pleroma.UserRelationship.create_mute(user, another_user)
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
|
||||
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
||||
create_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: true, is_muted: true},
|
||||
type: "favourite",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
status: StatusView.render("show.json", %{activity: create_activity, for: user}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], user, [expected])
|
||||
end
|
||||
end
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.PollViewTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.PollView
|
||||
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "renders a poll" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "Is Tenshi eating a corndog cute?",
|
||||
poll: %{
|
||||
options: ["absolutely!", "sure", "yes", "why are you even asking?"],
|
||||
expires_in: 20
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
expected = %{
|
||||
emojis: [],
|
||||
expired: false,
|
||||
id: to_string(object.id),
|
||||
multiple: false,
|
||||
options: [
|
||||
%{title: "absolutely!", votes_count: 0},
|
||||
%{title: "sure", votes_count: 0},
|
||||
%{title: "yes", votes_count: 0},
|
||||
%{title: "why are you even asking?", votes_count: 0}
|
||||
],
|
||||
voted: false,
|
||||
votes_count: 0,
|
||||
voters_count: nil
|
||||
}
|
||||
|
||||
result = PollView.render("show.json", %{object: object})
|
||||
expires_at = result.expires_at
|
||||
result = Map.delete(result, :expires_at)
|
||||
|
||||
assert result == expected
|
||||
|
||||
expires_at = NaiveDateTime.from_iso8601!(expires_at)
|
||||
assert NaiveDateTime.diff(expires_at, NaiveDateTime.utc_now()) in 15..20
|
||||
end
|
||||
|
||||
test "detects if it is multiple choice" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "Which Mastodon developer is your favourite?",
|
||||
poll: %{
|
||||
options: ["Gargron", "Eugen"],
|
||||
expires_in: 20,
|
||||
multiple: true
|
||||
}
|
||||
})
|
||||
|
||||
voter = insert(:user)
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
{:ok, _votes, object} = CommonAPI.vote(voter, object, [0, 1])
|
||||
|
||||
assert match?(
|
||||
%{
|
||||
multiple: true,
|
||||
voters_count: 1,
|
||||
votes_count: 2
|
||||
},
|
||||
PollView.render("show.json", %{object: object})
|
||||
)
|
||||
end
|
||||
|
||||
test "detects emoji" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "What's with the smug face?",
|
||||
poll: %{
|
||||
options: [":blank: sip", ":blank::blank: sip", ":blank::blank::blank: sip"],
|
||||
expires_in: 20
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert %{emojis: [%{shortcode: "blank"}]} = PollView.render("show.json", %{object: object})
|
||||
end
|
||||
|
||||
test "detects vote status" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "Which input devices do you use?",
|
||||
poll: %{
|
||||
options: ["mouse", "trackball", "trackpoint"],
|
||||
multiple: true,
|
||||
expires_in: 20
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
{:ok, _, object} = CommonAPI.vote(other_user, object, [1, 2])
|
||||
|
||||
result = PollView.render("show.json", %{object: object, for: other_user})
|
||||
|
||||
assert result[:voted] == true
|
||||
assert Enum.at(result[:options], 1)[:votes_count] == 1
|
||||
assert Enum.at(result[:options], 2)[:votes_count] == 1
|
||||
end
|
||||
|
||||
test "does not crash on polls with no end date" do
|
||||
object = Object.normalize("https://skippers-bin.com/notes/7x9tmrp97i")
|
||||
result = PollView.render("show.json", %{object: object})
|
||||
|
||||
assert result[:expires_at] == nil
|
||||
assert result[:expired] == false
|
||||
end
|
||||
|
||||
test "doesn't strips HTML tags" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "What's with the smug face?",
|
||||
poll: %{
|
||||
options: [
|
||||
"<input type=\"date\">",
|
||||
"<input type=\"date\" >",
|
||||
"<input type=\"date\"/>",
|
||||
"<input type=\"date\"></input>"
|
||||
],
|
||||
expires_in: 20
|
||||
}
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert %{
|
||||
options: [
|
||||
%{title: "<input type=\"date\">", votes_count: 0},
|
||||
%{title: "<input type=\"date\" >", votes_count: 0},
|
||||
%{title: "<input type=\"date\"/>", votes_count: 0},
|
||||
%{title: "<input type=\"date\"></input>", votes_count: 0}
|
||||
]
|
||||
} = PollView.render("show.json", %{object: object})
|
||||
end
|
||||
end
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ScheduledActivityViewTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.ScheduledActivity
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
import Pleroma.Factory
|
||||
|
||||
test "A scheduled activity with a media attachment" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hi"})
|
||||
|
||||
scheduled_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(10), :millisecond)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
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)
|
||||
|
||||
attrs = %{
|
||||
params: %{
|
||||
"media_ids" => [upload.id],
|
||||
"status" => "hi",
|
||||
"sensitive" => true,
|
||||
"spoiler_text" => "spoiler",
|
||||
"visibility" => "unlisted",
|
||||
"in_reply_to_id" => to_string(activity.id)
|
||||
},
|
||||
scheduled_at: scheduled_at
|
||||
}
|
||||
|
||||
{:ok, scheduled_activity} = ScheduledActivity.create(user, attrs)
|
||||
result = ScheduledActivityView.render("show.json", %{scheduled_activity: scheduled_activity})
|
||||
|
||||
expected = %{
|
||||
id: to_string(scheduled_activity.id),
|
||||
media_attachments:
|
||||
%{media_ids: [upload.id]}
|
||||
|> Utils.attachments_from_ids()
|
||||
|> Enum.map(&StatusView.render("attachment.json", %{attachment: &1})),
|
||||
params: %{
|
||||
in_reply_to_id: to_string(activity.id),
|
||||
media_ids: [upload.id],
|
||||
poll: nil,
|
||||
scheduled_at: nil,
|
||||
sensitive: true,
|
||||
spoiler_text: "spoiler",
|
||||
text: "hi",
|
||||
visibility: "unlisted"
|
||||
},
|
||||
scheduled_at: Utils.to_masto_date(scheduled_activity.scheduled_at)
|
||||
}
|
||||
|
||||
assert expected == result
|
||||
end
|
||||
end
|
||||
|
|
@ -1,664 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.HTML
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserRelationship
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
import OpenApiSpex.TestAssertions
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "has an emoji reaction list" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "☕")
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "🍵")
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 2, me: false},
|
||||
%{name: "🍵", count: 1, me: false}
|
||||
]
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 2, me: true},
|
||||
%{name: "🍵", count: 1, me: false}
|
||||
]
|
||||
end
|
||||
|
||||
test "works correctly with badly formatted emojis" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "yo"})
|
||||
|
||||
activity
|
||||
|> Object.normalize(false)
|
||||
|> Object.update_data(%{"reactions" => %{"☕" => [user.ap_id], "x" => 1}})
|
||||
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 1, me: true}
|
||||
]
|
||||
end
|
||||
|
||||
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
status =
|
||||
StatusView.render("show.json",
|
||||
activity: activity,
|
||||
with_direct_conversation_id: true,
|
||||
for: user
|
||||
)
|
||||
|
||||
assert status[:pleroma][:direct_conversation_id] == participation.id
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
assert status[:pleroma][:direct_conversation_id] == nil
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "returns the direct conversation id when given the `direct_conversation_id` option" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
status =
|
||||
StatusView.render("show.json",
|
||||
activity: activity,
|
||||
direct_conversation_id: participation.id,
|
||||
for: user
|
||||
)
|
||||
|
||||
assert status[:pleroma][:direct_conversation_id] == participation.id
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "returns a temporary ap_id based user for activities missing db users" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
|
||||
|
||||
Repo.delete(user)
|
||||
Cachex.clear(:user_cache)
|
||||
|
||||
finger_url =
|
||||
"https://localhost/.well-known/webfinger?resource=acct:#{user.nickname}@localhost"
|
||||
|
||||
Tesla.Mock.mock_global(fn
|
||||
%{method: :get, url: "http://localhost/.well-known/host-meta"} ->
|
||||
%Tesla.Env{status: 404, body: ""}
|
||||
|
||||
%{method: :get, url: "https://localhost/.well-known/host-meta"} ->
|
||||
%Tesla.Env{status: 404, body: ""}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: ^finger_url
|
||||
} ->
|
||||
%Tesla.Env{status: 404, body: ""}
|
||||
end)
|
||||
|
||||
%{account: ms_user} = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert ms_user.acct == "erroruser@example.com"
|
||||
end
|
||||
|
||||
test "tries to get a user by nickname if fetching by ap_id doesn't work" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
|
||||
|
||||
{:ok, user} =
|
||||
user
|
||||
|> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"})
|
||||
|> Repo.update()
|
||||
|
||||
Cachex.clear(:user_cache)
|
||||
|
||||
result = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert result[:account][:id] == to_string(user.id)
|
||||
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "a note with null content" do
|
||||
note = insert(:note_activity)
|
||||
note_object = Object.normalize(note)
|
||||
|
||||
data =
|
||||
note_object.data
|
||||
|> Map.put("content", nil)
|
||||
|
||||
Object.change(note_object, %{data: data})
|
||||
|> Object.update_and_set_cache()
|
||||
|
||||
User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
status = StatusView.render("show.json", %{activity: note})
|
||||
|
||||
assert status.content == ""
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "a note activity" do
|
||||
note = insert(:note_activity)
|
||||
object_data = Object.normalize(note).data
|
||||
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||
|
||||
convo_id = Utils.context_to_conversation_id(object_data["context"])
|
||||
|
||||
status = StatusView.render("show.json", %{activity: note})
|
||||
|
||||
created_at =
|
||||
(object_data["published"] || "")
|
||||
|> String.replace(~r/\.\d+Z/, ".000Z")
|
||||
|
||||
expected = %{
|
||||
id: to_string(note.id),
|
||||
uri: object_data["id"],
|
||||
url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
|
||||
account: AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
|
||||
in_reply_to_id: nil,
|
||||
in_reply_to_account_id: nil,
|
||||
card: nil,
|
||||
reblog: nil,
|
||||
content: HTML.filter_tags(object_data["content"]),
|
||||
text: nil,
|
||||
created_at: created_at,
|
||||
reblogs_count: 0,
|
||||
replies_count: 0,
|
||||
favourites_count: 0,
|
||||
reblogged: false,
|
||||
bookmarked: false,
|
||||
favourited: false,
|
||||
muted: false,
|
||||
pinned: false,
|
||||
sensitive: false,
|
||||
poll: nil,
|
||||
spoiler_text: HTML.filter_tags(object_data["summary"]),
|
||||
visibility: "public",
|
||||
media_attachments: [],
|
||||
mentions: [],
|
||||
tags: [
|
||||
%{
|
||||
name: "#{object_data["tag"]}",
|
||||
url: "/tag/#{object_data["tag"]}"
|
||||
}
|
||||
],
|
||||
application: %{
|
||||
name: "Web",
|
||||
website: nil
|
||||
},
|
||||
language: nil,
|
||||
emojis: [
|
||||
%{
|
||||
shortcode: "2hu",
|
||||
url: "corndog.png",
|
||||
static_url: "corndog.png",
|
||||
visible_in_picker: false
|
||||
}
|
||||
],
|
||||
pleroma: %{
|
||||
local: true,
|
||||
conversation_id: convo_id,
|
||||
in_reply_to_account_acct: nil,
|
||||
content: %{"text/plain" => HTML.strip_tags(object_data["content"])},
|
||||
spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])},
|
||||
expires_at: nil,
|
||||
direct_conversation_id: nil,
|
||||
thread_muted: false,
|
||||
emoji_reactions: [],
|
||||
parent_visible: false
|
||||
}
|
||||
}
|
||||
|
||||
assert status == expected
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "tells if the message is muted for some reason" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, other_user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "test"})
|
||||
|
||||
relationships_opt = UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
opts = %{activity: activity}
|
||||
status = StatusView.render("show.json", opts)
|
||||
assert status.muted == false
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
|
||||
status = StatusView.render("show.json", Map.put(opts, :relationships, relationships_opt))
|
||||
assert status.muted == false
|
||||
|
||||
for_opts = %{activity: activity, for: user}
|
||||
status = StatusView.render("show.json", for_opts)
|
||||
assert status.muted == true
|
||||
|
||||
status = StatusView.render("show.json", Map.put(for_opts, :relationships, relationships_opt))
|
||||
assert status.muted == true
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "tells if the message is thread muted" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, other_user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "test"})
|
||||
status = StatusView.render("show.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.pleroma.thread_muted == false
|
||||
|
||||
{:ok, activity} = CommonAPI.add_mute(user, activity)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.pleroma.thread_muted == true
|
||||
end
|
||||
|
||||
test "tells if the status is bookmarked" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Cute girls doing cute things"})
|
||||
status = StatusView.render("show.json", %{activity: activity})
|
||||
|
||||
assert status.bookmarked == false
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.bookmarked == false
|
||||
|
||||
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
|
||||
|
||||
activity = Activity.get_by_id_with_object(activity.id)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.bookmarked == true
|
||||
end
|
||||
|
||||
test "a reply" do
|
||||
note = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "he", in_reply_to_status_id: note.id})
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity})
|
||||
|
||||
assert status.in_reply_to_id == to_string(note.id)
|
||||
|
||||
[status] = StatusView.render("index.json", %{activities: [activity], as: :activity})
|
||||
|
||||
assert status.in_reply_to_id == to_string(note.id)
|
||||
end
|
||||
|
||||
test "contains mentions" do
|
||||
user = insert(:user)
|
||||
mentioned = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hi @#{mentioned.nickname}"})
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity})
|
||||
|
||||
assert status.mentions ==
|
||||
Enum.map([mentioned], fn u -> AccountView.render("mention.json", %{user: u}) end)
|
||||
|
||||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "create mentions from the 'to' field" do
|
||||
%User{ap_id: recipient_ap_id} = insert(:user)
|
||||
cc = insert_pair(:user) |> Enum.map(& &1.ap_id)
|
||||
|
||||
object =
|
||||
insert(:note, %{
|
||||
data: %{
|
||||
"to" => [recipient_ap_id],
|
||||
"cc" => cc
|
||||
}
|
||||
})
|
||||
|
||||
activity =
|
||||
insert(:note_activity, %{
|
||||
note: object,
|
||||
recipients: [recipient_ap_id | cc]
|
||||
})
|
||||
|
||||
assert length(activity.recipients) == 3
|
||||
|
||||
%{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
|
||||
|
||||
assert length(mentions) == 1
|
||||
assert mention.url == recipient_ap_id
|
||||
end
|
||||
|
||||
test "create mentions from the 'tag' field" do
|
||||
recipient = insert(:user)
|
||||
cc = insert_pair(:user) |> Enum.map(& &1.ap_id)
|
||||
|
||||
object =
|
||||
insert(:note, %{
|
||||
data: %{
|
||||
"cc" => cc,
|
||||
"tag" => [
|
||||
%{
|
||||
"href" => recipient.ap_id,
|
||||
"name" => recipient.nickname,
|
||||
"type" => "Mention"
|
||||
},
|
||||
%{
|
||||
"href" => "https://example.com/search?tag=test",
|
||||
"name" => "#test",
|
||||
"type" => "Hashtag"
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
activity =
|
||||
insert(:note_activity, %{
|
||||
note: object,
|
||||
recipients: [recipient.ap_id | cc]
|
||||
})
|
||||
|
||||
assert length(activity.recipients) == 3
|
||||
|
||||
%{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
|
||||
|
||||
assert length(mentions) == 1
|
||||
assert mention.url == recipient.ap_id
|
||||
end
|
||||
|
||||
test "attachments" do
|
||||
object = %{
|
||||
"type" => "Image",
|
||||
"url" => [
|
||||
%{
|
||||
"mediaType" => "image/png",
|
||||
"href" => "someurl"
|
||||
}
|
||||
],
|
||||
"uuid" => 6
|
||||
}
|
||||
|
||||
expected = %{
|
||||
id: "1638338801",
|
||||
type: "image",
|
||||
url: "someurl",
|
||||
remote_url: "someurl",
|
||||
preview_url: "someurl",
|
||||
text_url: "someurl",
|
||||
description: nil,
|
||||
pleroma: %{mime_type: "image/png"}
|
||||
}
|
||||
|
||||
api_spec = Pleroma.Web.ApiSpec.spec()
|
||||
|
||||
assert expected == StatusView.render("attachment.json", %{attachment: object})
|
||||
assert_schema(expected, "Attachment", api_spec)
|
||||
|
||||
# If theres a "id", use that instead of the generated one
|
||||
object = Map.put(object, "id", 2)
|
||||
result = StatusView.render("attachment.json", %{attachment: object})
|
||||
|
||||
assert %{id: "2"} = result
|
||||
assert_schema(result, "Attachment", api_spec)
|
||||
end
|
||||
|
||||
test "put the url advertised in the Activity in to the url attribute" do
|
||||
id = "https://wedistribute.org/wp-json/pterotype/v1/object/85810"
|
||||
[activity] = Activity.search(nil, id)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity})
|
||||
|
||||
assert status.uri == id
|
||||
assert status.url == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/"
|
||||
end
|
||||
|
||||
test "a reblog" do
|
||||
user = insert(:user)
|
||||
activity = insert(:note_activity)
|
||||
|
||||
{:ok, reblog} = CommonAPI.repeat(activity.id, user)
|
||||
|
||||
represented = StatusView.render("show.json", %{for: user, activity: reblog})
|
||||
|
||||
assert represented[:id] == to_string(reblog.id)
|
||||
assert represented[:reblog][:id] == to_string(activity.id)
|
||||
assert represented[:emojis] == []
|
||||
assert_schema(represented, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "a peertube video" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, object} =
|
||||
Pleroma.Object.Fetcher.fetch_object_from_id(
|
||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
||||
)
|
||||
|
||||
%Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
|
||||
represented = StatusView.render("show.json", %{for: user, activity: activity})
|
||||
|
||||
assert represented[:id] == to_string(activity.id)
|
||||
assert length(represented[:media_attachments]) == 1
|
||||
assert_schema(represented, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "funkwhale audio" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, object} =
|
||||
Pleroma.Object.Fetcher.fetch_object_from_id(
|
||||
"https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871"
|
||||
)
|
||||
|
||||
%Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
|
||||
represented = StatusView.render("show.json", %{for: user, activity: activity})
|
||||
|
||||
assert represented[:id] == to_string(activity.id)
|
||||
assert length(represented[:media_attachments]) == 1
|
||||
end
|
||||
|
||||
test "a Mobilizon event" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, object} =
|
||||
Pleroma.Object.Fetcher.fetch_object_from_id(
|
||||
"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
|
||||
)
|
||||
|
||||
%Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
|
||||
represented = StatusView.render("show.json", %{for: user, activity: activity})
|
||||
|
||||
assert represented[:id] == to_string(activity.id)
|
||||
|
||||
assert represented[:url] ==
|
||||
"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
|
||||
|
||||
assert represented[:content] ==
|
||||
"<p><a href=\"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39\">Mobilizon Launching Party</a></p><p>Mobilizon is now federated! 🎉</p><p></p><p>You can view this event from other instances if they are subscribed to mobilizon.org, and soon directly from Mastodon and Pleroma. It is possible that you may see some comments from other instances, including Mastodon ones, just below.</p><p></p><p>With a Mobilizon account on an instance, you may <strong>participate</strong> at events from other instances and <strong>add comments</strong> on events.</p><p></p><p>Of course, it's still <u>a work in progress</u>: if reports made from an instance on events and comments can be federated, you can't block people right now, and moderators actions are rather limited, but this <strong>will definitely get fixed over time</strong> until first stable version next year.</p><p></p><p>Anyway, if you want to come up with some feedback, head over to our forum or - if you feel you have technical skills and are familiar with it - on our Gitlab repository.</p><p></p><p>Also, to people that want to set Mobilizon themselves even though we really don't advise to do that for now, we have a little documentation but it's quite the early days and you'll probably need some help. No worries, you can chat with us on our Forum or though our Matrix channel.</p><p></p><p>Check our website for more informations and follow us on Twitter or Mastodon.</p>"
|
||||
end
|
||||
|
||||
describe "build_tags/1" do
|
||||
test "it returns a a dictionary tags" do
|
||||
object_tags = [
|
||||
"fediverse",
|
||||
"mastodon",
|
||||
"nextcloud",
|
||||
%{
|
||||
"href" => "https://kawen.space/users/lain",
|
||||
"name" => "@lain@kawen.space",
|
||||
"type" => "Mention"
|
||||
}
|
||||
]
|
||||
|
||||
assert StatusView.build_tags(object_tags) == [
|
||||
%{name: "fediverse", url: "/tag/fediverse"},
|
||||
%{name: "mastodon", url: "/tag/mastodon"},
|
||||
%{name: "nextcloud", url: "/tag/nextcloud"}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rich media cards" do
|
||||
test "a rich media card without a site name renders correctly" do
|
||||
page_url = "http://example.com"
|
||||
|
||||
card = %{
|
||||
url: page_url,
|
||||
image: page_url <> "/example.jpg",
|
||||
title: "Example website"
|
||||
}
|
||||
|
||||
%{provider_name: "example.com"} =
|
||||
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||
end
|
||||
|
||||
test "a rich media card without a site name or image renders correctly" do
|
||||
page_url = "http://example.com"
|
||||
|
||||
card = %{
|
||||
url: page_url,
|
||||
title: "Example website"
|
||||
}
|
||||
|
||||
%{provider_name: "example.com"} =
|
||||
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||
end
|
||||
|
||||
test "a rich media card without an image renders correctly" do
|
||||
page_url = "http://example.com"
|
||||
|
||||
card = %{
|
||||
url: page_url,
|
||||
site_name: "Example site name",
|
||||
title: "Example website"
|
||||
}
|
||||
|
||||
%{provider_name: "example.com"} =
|
||||
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||
end
|
||||
|
||||
test "a rich media card with all relevant data renders correctly" do
|
||||
page_url = "http://example.com"
|
||||
|
||||
card = %{
|
||||
url: page_url,
|
||||
site_name: "Example site name",
|
||||
title: "Example website",
|
||||
image: page_url <> "/example.jpg",
|
||||
description: "Example description"
|
||||
}
|
||||
|
||||
%{provider_name: "example.com"} =
|
||||
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||
end
|
||||
end
|
||||
|
||||
test "does not embed a relationship in the account" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "drink more water"
|
||||
})
|
||||
|
||||
result = StatusView.render("show.json", %{activity: activity, for: other_user})
|
||||
|
||||
assert result[:account][:pleroma][:relationship] == %{}
|
||||
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "does not embed a relationship in the account in reposts" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "˙˙ɐʎns"
|
||||
})
|
||||
|
||||
{:ok, activity} = CommonAPI.repeat(activity.id, other_user)
|
||||
|
||||
result = StatusView.render("show.json", %{activity: activity, for: user})
|
||||
|
||||
assert result[:account][:pleroma][:relationship] == %{}
|
||||
assert result[:reblog][:account][:pleroma][:relationship] == %{}
|
||||
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "visibility/list" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, list} = Pleroma.List.create("foo", user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
|
||||
|
||||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status.visibility == "list"
|
||||
end
|
||||
|
||||
test "has a field for parent visibility" do
|
||||
user = insert(:user)
|
||||
poster = insert(:user)
|
||||
|
||||
{:ok, invisible} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
|
||||
|
||||
{:ok, visible} =
|
||||
CommonAPI.post(poster, %{status: "hey", visibility: "private", in_reply_to_id: invisible.id})
|
||||
|
||||
status = StatusView.render("show.json", activity: visible, for: user)
|
||||
refute status.pleroma.parent_visible
|
||||
|
||||
status = StatusView.render("show.json", activity: visible, for: poster)
|
||||
assert status.pleroma.parent_visible
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue