Merge remote-tracking branch 'origin/develop' into instance_rules
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
commit
6051715a99
1114 changed files with 53017 additions and 6853 deletions
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Activity.Ir.TopicsTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Activity.Ir.Topics
|
||||
|
|
@ -13,6 +13,29 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
|
|||
|
||||
import Mock
|
||||
|
||||
describe "chat message" do
|
||||
test "Create produces no topics" do
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"type" => "ChatMessage"}},
|
||||
data: %{"type" => "Create"}
|
||||
}
|
||||
|
||||
assert [] == Topics.get_activity_topics(activity)
|
||||
end
|
||||
|
||||
test "Delete produces user and user:pleroma_chat" do
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"type" => "ChatMessage"}},
|
||||
data: %{"type" => "Delete"}
|
||||
}
|
||||
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
assert [_, _] = topics
|
||||
assert "user" in topics
|
||||
assert "user:pleroma_chat" in topics
|
||||
end
|
||||
end
|
||||
|
||||
describe "poll answer" do
|
||||
test "produce no topics" do
|
||||
activity = %Activity{object: %Object{data: %{"type" => "Answer"}}}
|
||||
|
|
@ -35,7 +58,7 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
|
|||
setup do
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"type" => "Note"}},
|
||||
data: %{"to" => [Pleroma.Constants.as_public()]}
|
||||
data: %{"to" => [Pleroma.Constants.as_public()], "type" => "Create"}
|
||||
}
|
||||
|
||||
{:ok, activity: activity}
|
||||
|
|
@ -114,6 +137,55 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "public visibility Announces" do
|
||||
setup do
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"attachment" => []}},
|
||||
data: %{"type" => "Announce", "to" => [Pleroma.Constants.as_public()]}
|
||||
}
|
||||
|
||||
{:ok, activity: activity}
|
||||
end
|
||||
|
||||
test "does not generate public topics", %{activity: activity} do
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
refute "public" in topics
|
||||
refute "public:remote" in topics
|
||||
refute "public:local" in topics
|
||||
end
|
||||
end
|
||||
|
||||
describe "local-public visibility create events" do
|
||||
setup do
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"attachment" => []}},
|
||||
data: %{"type" => "Create", "to" => [Pleroma.Web.ActivityPub.Utils.as_local_public()]}
|
||||
}
|
||||
|
||||
{:ok, activity: activity}
|
||||
end
|
||||
|
||||
test "doesn't produce public topics", %{activity: activity} do
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
refute Enum.member?(topics, "public")
|
||||
end
|
||||
|
||||
test "produces public:local topics", %{activity: activity} do
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
assert Enum.member?(topics, "public:local")
|
||||
end
|
||||
|
||||
test "with no attachments doesn't produce public:media topics", %{activity: activity} do
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
refute Enum.member?(topics, "public:media")
|
||||
refute Enum.member?(topics, "public:local:media")
|
||||
end
|
||||
end
|
||||
|
||||
describe "public visibility create events with attachments" do
|
||||
setup do
|
||||
activity = %Activity{
|
||||
|
|
@ -152,9 +224,36 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "local-public visibility create events with attachments" do
|
||||
setup do
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"attachment" => ["foo"]}},
|
||||
data: %{"type" => "Create", "to" => [Pleroma.Web.ActivityPub.Utils.as_local_public()]}
|
||||
}
|
||||
|
||||
{:ok, activity: activity}
|
||||
end
|
||||
|
||||
test "do not produce public:media topics", %{activity: activity} do
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
refute Enum.member?(topics, "public:media")
|
||||
end
|
||||
|
||||
test "produces public:local:media topics", %{activity: activity} do
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
assert Enum.member?(topics, "public:local:media")
|
||||
end
|
||||
end
|
||||
|
||||
describe "non-public visibility" do
|
||||
test "produces direct topic" do
|
||||
activity = %Activity{object: %Object{data: %{"type" => "Note"}}, data: %{"to" => []}}
|
||||
activity = %Activity{
|
||||
object: %Object{data: %{"type" => "Note"}},
|
||||
data: %{"to" => [], "type" => "Create"}
|
||||
}
|
||||
|
||||
topics = Topics.get_activity_topics(activity)
|
||||
|
||||
assert Enum.member?(topics, "direct")
|
||||
|
|
|
|||
|
|
@ -278,4 +278,78 @@ defmodule Pleroma.ActivityTest do
|
|||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 2
|
||||
end
|
||||
|
||||
describe "associated_object_id() sql function" do
|
||||
test "with json object" do
|
||||
%{rows: [[object_id]]} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"""
|
||||
select associated_object_id('{"object": {"id":"foobar"}}'::jsonb);
|
||||
"""
|
||||
)
|
||||
|
||||
assert object_id == "foobar"
|
||||
end
|
||||
|
||||
test "with string object" do
|
||||
%{rows: [[object_id]]} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"""
|
||||
select associated_object_id('{"object": "foobar"}'::jsonb);
|
||||
"""
|
||||
)
|
||||
|
||||
assert object_id == "foobar"
|
||||
end
|
||||
|
||||
test "with array object" do
|
||||
%{rows: [[object_id]]} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"""
|
||||
select associated_object_id('{"object": ["foobar", {}]}'::jsonb);
|
||||
"""
|
||||
)
|
||||
|
||||
assert object_id == "foobar"
|
||||
end
|
||||
|
||||
test "invalid" do
|
||||
%{rows: [[object_id]]} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"""
|
||||
select associated_object_id('{"object": {}}'::jsonb);
|
||||
"""
|
||||
)
|
||||
|
||||
assert is_nil(object_id)
|
||||
end
|
||||
|
||||
test "invalid object id" do
|
||||
%{rows: [[object_id]]} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"""
|
||||
select associated_object_id('{"object": {"id": 123}}'::jsonb);
|
||||
"""
|
||||
)
|
||||
|
||||
assert is_nil(object_id)
|
||||
end
|
||||
|
||||
test "no object field" do
|
||||
%{rows: [[object_id]]} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"""
|
||||
select associated_object_id('{}'::jsonb);
|
||||
"""
|
||||
)
|
||||
|
||||
assert is_nil(object_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
40
test/pleroma/announcement_read_relationship_test.exs
Normal file
40
test/pleroma/announcement_read_relationship_test.exs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.AnnouncementReadRelationshipTest do
|
||||
alias Pleroma.AnnouncementReadRelationship
|
||||
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
{:ok, user: insert(:user), announcement: insert(:announcement)}
|
||||
end
|
||||
|
||||
describe "mark_read/2" do
|
||||
test "should insert relationship", %{user: user, announcement: announcement} do
|
||||
{:ok, _} = AnnouncementReadRelationship.mark_read(user, announcement)
|
||||
|
||||
assert AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mark_unread/2" do
|
||||
test "should delete relationship", %{user: user, announcement: announcement} do
|
||||
{:ok, _} = AnnouncementReadRelationship.mark_read(user, announcement)
|
||||
|
||||
assert :ok = AnnouncementReadRelationship.mark_unread(user, announcement)
|
||||
refute AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
|
||||
test "should not fail if relationship does not exist", %{
|
||||
user: user,
|
||||
announcement: announcement
|
||||
} do
|
||||
assert :ok = AnnouncementReadRelationship.mark_unread(user, announcement)
|
||||
refute AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
end
|
||||
end
|
||||
98
test/pleroma/announcement_test.exs
Normal file
98
test/pleroma/announcement_test.exs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.AnnouncementTest do
|
||||
alias Pleroma.Announcement
|
||||
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "list_all_visible_when/1" do
|
||||
setup do: {:ok, time: NaiveDateTime.utc_now()}
|
||||
|
||||
test "with no start or end time", %{time: time} do
|
||||
_announcement = insert(:announcement)
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with start time before current", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: before_now})
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with start time after current", %{time: time} do
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: after_now})
|
||||
|
||||
assert [] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with end time after current", %{time: time} do
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{ends_at: after_now})
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with end time before current", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{ends_at: before_now})
|
||||
|
||||
assert [] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with both start and end time", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: before_now, ends_at: after_now})
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with both start and end time, current not in the range", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: after_now, ends_at: before_now})
|
||||
|
||||
assert [] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
end
|
||||
|
||||
describe "announcements formatting" do
|
||||
test "it formats links" do
|
||||
raw = "something on https://pleroma.social ."
|
||||
announcement = insert(:announcement, %{data: %{"content" => raw}})
|
||||
|
||||
assert announcement.rendered["content"] =~ ~r(<a.+?https://pleroma.social)
|
||||
assert announcement.data["content"] == raw
|
||||
end
|
||||
|
||||
test "it formats mentions" do
|
||||
user = insert(:user)
|
||||
raw = "something on @#{user.nickname} ."
|
||||
announcement = insert(:announcement, %{data: %{"content" => raw}})
|
||||
|
||||
assert announcement.rendered["content"] =~ ~r(<a.+?#{user.nickname})
|
||||
assert announcement.data["content"] == raw
|
||||
end
|
||||
|
||||
test "it formats tags" do
|
||||
raw = "something on #mew ."
|
||||
announcement = insert(:announcement, %{data: %{"content" => raw}})
|
||||
|
||||
assert announcement.rendered["content"] =~ ~r(<a.+?#mew)
|
||||
assert announcement.data["content"] == raw
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.BBS.HandlerTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.BBS.Handler
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import ExUnit.CaptureIO
|
||||
import Pleroma.Factory
|
||||
import Ecto.Query
|
||||
|
||||
test "getting the home timeline" do
|
||||
user = insert(:user)
|
||||
followed = insert(:user)
|
||||
|
||||
{:ok, user, followed} = User.follow(user, followed)
|
||||
|
||||
{:ok, _first} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, _second} = CommonAPI.post(followed, %{status: "hello"})
|
||||
|
||||
output =
|
||||
capture_io(fn ->
|
||||
Handler.handle_command(%{user: user}, "home")
|
||||
end)
|
||||
|
||||
assert output =~ user.nickname
|
||||
assert output =~ followed.nickname
|
||||
|
||||
assert output =~ "hey"
|
||||
assert output =~ "hello"
|
||||
end
|
||||
|
||||
test "posting" do
|
||||
user = insert(:user)
|
||||
|
||||
output =
|
||||
capture_io(fn ->
|
||||
Handler.handle_command(%{user: user}, "p this is a test post")
|
||||
end)
|
||||
|
||||
assert output =~ "Posted"
|
||||
|
||||
activity =
|
||||
Repo.one(
|
||||
from(a in Activity,
|
||||
where: fragment("?->>'type' = ?", a.data, "Create")
|
||||
)
|
||||
)
|
||||
|
||||
assert activity.actor == user.ap_id
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
assert object.data["content"] == "this is a test post"
|
||||
end
|
||||
|
||||
test "replying" do
|
||||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{status: "this is a test post"})
|
||||
activity_object = Object.normalize(activity, fetch: false)
|
||||
|
||||
output =
|
||||
capture_io(fn ->
|
||||
Handler.handle_command(%{user: user}, "r #{activity.id} this is a reply")
|
||||
end)
|
||||
|
||||
assert output =~ "Replied"
|
||||
|
||||
reply =
|
||||
Repo.one(
|
||||
from(a in Activity,
|
||||
where: fragment("?->>'type' = ?", a.data, "Create"),
|
||||
where: a.actor == ^user.ap_id
|
||||
)
|
||||
)
|
||||
|
||||
assert reply.actor == user.ap_id
|
||||
|
||||
reply_object_data = Object.normalize(reply, fetch: false).data
|
||||
assert reply_object_data["content"] == "this is a reply"
|
||||
assert reply_object_data["inReplyTo"] == activity_object.data["id"]
|
||||
end
|
||||
end
|
||||
|
|
@ -11,6 +11,62 @@ defmodule Pleroma.Config.DeprecationWarningsTest do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.Config.DeprecationWarnings
|
||||
|
||||
describe "filter exiftool" do
|
||||
test "gives warning when still used" do
|
||||
clear_config(
|
||||
[Pleroma.Upload, :filters],
|
||||
[Pleroma.Upload.Filter.Exiftool]
|
||||
)
|
||||
|
||||
assert capture_log(fn -> DeprecationWarnings.check_exiftool_filter() end) =~
|
||||
"""
|
||||
!!!DEPRECATION WARNING!!!
|
||||
Your config is using Exiftool as a filter instead of Exiftool.StripLocation. This should work for now, but you are advised to change to the new configuration to prevent possible issues later:
|
||||
|
||||
```
|
||||
config :pleroma, Pleroma.Upload,
|
||||
filters: [Pleroma.Upload.Filter.Exiftool]
|
||||
```
|
||||
|
||||
Is now
|
||||
|
||||
|
||||
```
|
||||
config :pleroma, Pleroma.Upload,
|
||||
filters: [Pleroma.Upload.Filter.Exiftool.StripLocation]
|
||||
```
|
||||
"""
|
||||
end
|
||||
|
||||
test "changes setting to exiftool strip location" do
|
||||
clear_config(
|
||||
[Pleroma.Upload, :filters],
|
||||
[Pleroma.Upload.Filter.Exiftool, Pleroma.Upload.Filter.Exiftool.ReadDescription]
|
||||
)
|
||||
|
||||
expected_config = [
|
||||
Pleroma.Upload.Filter.Exiftool.StripLocation,
|
||||
Pleroma.Upload.Filter.Exiftool.ReadDescription
|
||||
]
|
||||
|
||||
capture_log(fn -> DeprecationWarnings.warn() end)
|
||||
|
||||
assert Config.get([Pleroma.Upload]) |> Keyword.get(:filters, []) == expected_config
|
||||
end
|
||||
|
||||
test "doesn't give a warning with correct config" do
|
||||
clear_config(
|
||||
[Pleroma.Upload, :filters],
|
||||
[
|
||||
Pleroma.Upload.Filter.Exiftool.StripLocation,
|
||||
Pleroma.Upload.Filter.Exiftool.ReadDescription
|
||||
]
|
||||
)
|
||||
|
||||
assert capture_log(fn -> DeprecationWarnings.check_exiftool_filter() end) == ""
|
||||
end
|
||||
end
|
||||
|
||||
describe "simple policy tuples" do
|
||||
test "gives warning when there are still strings" do
|
||||
clear_config([:mrf_simple],
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ defmodule Pleroma.Config.LoaderTest do
|
|||
config = Loader.read("test/fixtures/config/temp.secret.exs")
|
||||
assert config[:pleroma][:first_setting][:key] == "value"
|
||||
assert config[:pleroma][:first_setting][:key2] == [Pleroma.Repo]
|
||||
assert config[:quack][:level] == :info
|
||||
end
|
||||
|
||||
test "filter_group/2" do
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@ defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
|
|||
describe "load/2" do
|
||||
test "loads release defaults config and warns about non-existent runtime config" do
|
||||
ExUnit.CaptureIO.capture_io(fn ->
|
||||
merged = ReleaseRuntimeProvider.load([], [])
|
||||
merged = ReleaseRuntimeProvider.load([], config_path: "/var/empty/config.exs")
|
||||
assert merged == Pleroma.Config.Holder.release_defaults()
|
||||
end) =~
|
||||
"!!! Config path is not declared! Please ensure it exists and that PLEROMA_CONFIG_PATH is unset or points to an existing file"
|
||||
end
|
||||
|
||||
test "merged runtime config" do
|
||||
assert :ok == File.chmod!("test/fixtures/config/temp.secret.exs", 0o640)
|
||||
|
||||
merged =
|
||||
ReleaseRuntimeProvider.load([], config_path: "test/fixtures/config/temp.secret.exs")
|
||||
|
||||
|
|
@ -25,6 +27,8 @@ defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
|
|||
end
|
||||
|
||||
test "merged exported config" do
|
||||
assert :ok == File.chmod!("test/fixtures/config/temp.exported_from_db.secret.exs", 0o640)
|
||||
|
||||
ExUnit.CaptureIO.capture_io(fn ->
|
||||
merged =
|
||||
ReleaseRuntimeProvider.load([],
|
||||
|
|
@ -37,6 +41,9 @@ defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
|
|||
end
|
||||
|
||||
test "runtime config is merged with exported config" do
|
||||
assert :ok == File.chmod!("test/fixtures/config/temp.secret.exs", 0o640)
|
||||
assert :ok == File.chmod!("test/fixtures/config/temp.exported_from_db.secret.exs", 0o640)
|
||||
|
||||
merged =
|
||||
ReleaseRuntimeProvider.load([],
|
||||
config_path: "test/fixtures/config/temp.secret.exs",
|
||||
|
|
|
|||
|
|
@ -15,13 +15,11 @@ defmodule Pleroma.Config.TransferTaskTest do
|
|||
test "transfer config values from db to env" do
|
||||
refute Application.get_env(:pleroma, :test_key)
|
||||
refute Application.get_env(:idna, :test_key)
|
||||
refute Application.get_env(:quack, :test_key)
|
||||
refute Application.get_env(:postgrex, :test_key)
|
||||
initial = Application.get_env(:logger, :level)
|
||||
|
||||
insert(:config, key: :test_key, value: [live: 2, com: 3])
|
||||
insert(:config, group: :idna, key: :test_key, value: [live: 15, com: 35])
|
||||
insert(:config, group: :quack, key: :test_key, value: [:test_value1, :test_value2])
|
||||
insert(:config, group: :postgrex, key: :test_key, value: :value)
|
||||
insert(:config, group: :logger, key: :level, value: :debug)
|
||||
|
||||
|
|
@ -29,36 +27,32 @@ defmodule Pleroma.Config.TransferTaskTest do
|
|||
|
||||
assert Application.get_env(:pleroma, :test_key) == [live: 2, com: 3]
|
||||
assert Application.get_env(:idna, :test_key) == [live: 15, com: 35]
|
||||
assert Application.get_env(:quack, :test_key) == [:test_value1, :test_value2]
|
||||
assert Application.get_env(:logger, :level) == :debug
|
||||
assert Application.get_env(:postgrex, :test_key) == :value
|
||||
|
||||
on_exit(fn ->
|
||||
Application.delete_env(:pleroma, :test_key)
|
||||
Application.delete_env(:idna, :test_key)
|
||||
Application.delete_env(:quack, :test_key)
|
||||
Application.delete_env(:postgrex, :test_key)
|
||||
Application.put_env(:logger, :level, initial)
|
||||
end)
|
||||
end
|
||||
|
||||
test "transfer config values for 1 group and some keys" do
|
||||
level = Application.get_env(:quack, :level)
|
||||
meta = Application.get_env(:quack, :meta)
|
||||
level = Application.get_env(:somegroup, :level)
|
||||
meta = Application.get_env(:somegroup, :meta)
|
||||
|
||||
insert(:config, group: :quack, key: :level, value: :info)
|
||||
insert(:config, group: :quack, key: :meta, value: [:none])
|
||||
insert(:config, group: :somegroup, key: :level, value: :info)
|
||||
insert(:config, group: :somegroup, key: :meta, value: [:none])
|
||||
|
||||
TransferTask.start_link([])
|
||||
|
||||
assert Application.get_env(:quack, :level) == :info
|
||||
assert Application.get_env(:quack, :meta) == [:none]
|
||||
default = Pleroma.Config.Holder.default_config(:quack, :webhook_url)
|
||||
assert Application.get_env(:quack, :webhook_url) == default
|
||||
assert Application.get_env(:somegroup, :level) == :info
|
||||
assert Application.get_env(:somegroup, :meta) == [:none]
|
||||
|
||||
on_exit(fn ->
|
||||
Application.put_env(:quack, :level, level)
|
||||
Application.put_env(:quack, :meta, meta)
|
||||
Application.put_env(:somegroup, :level, level)
|
||||
Application.put_env(:somegroup, :meta, meta)
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
@ -79,35 +73,70 @@ defmodule Pleroma.Config.TransferTaskTest do
|
|||
|
||||
describe "pleroma restart" do
|
||||
setup do
|
||||
on_exit(fn -> Restarter.Pleroma.refresh() end)
|
||||
on_exit(fn ->
|
||||
Restarter.Pleroma.refresh()
|
||||
|
||||
# Restarter.Pleroma.refresh/0 is an asynchronous call.
|
||||
# A GenServer will first finish the previous call before starting a new one.
|
||||
# Here we do a synchronous call.
|
||||
# That way we are sure that the previous call has finished before we continue.
|
||||
# See https://stackoverflow.com/questions/51361856/how-to-use-task-await-with-genserver
|
||||
Restarter.Pleroma.rebooted?()
|
||||
end)
|
||||
end
|
||||
|
||||
@tag :erratic
|
||||
test "don't restart if no reboot time settings were changed" do
|
||||
clear_config(:emoji)
|
||||
insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]])
|
||||
|
||||
refute String.contains?(
|
||||
capture_log(fn -> TransferTask.start_link([]) end),
|
||||
capture_log(fn ->
|
||||
TransferTask.start_link([])
|
||||
|
||||
# TransferTask.start_link/1 is an asynchronous call.
|
||||
# A GenServer will first finish the previous call before starting a new one.
|
||||
# Here we do a synchronous call.
|
||||
# That way we are sure that the previous call has finished before we continue.
|
||||
Restarter.Pleroma.rebooted?()
|
||||
end),
|
||||
"pleroma restarted"
|
||||
)
|
||||
end
|
||||
|
||||
@tag :erratic
|
||||
test "on reboot time key" do
|
||||
clear_config(:shout)
|
||||
insert(:config, key: :shout, value: [enabled: false])
|
||||
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
|
||||
|
||||
# Note that we don't actually restart Pleroma.
|
||||
# See module Restarter.Pleroma
|
||||
assert capture_log(fn ->
|
||||
TransferTask.start_link([])
|
||||
|
||||
# TransferTask.start_link/1 is an asynchronous call.
|
||||
# A GenServer will first finish the previous call before starting a new one.
|
||||
# Here we do a synchronous call.
|
||||
# That way we are sure that the previous call has finished before we continue.
|
||||
Restarter.Pleroma.rebooted?()
|
||||
end) =~ "pleroma restarted"
|
||||
end
|
||||
|
||||
@tag :erratic
|
||||
test "on reboot time subkey" do
|
||||
clear_config(Pleroma.Captcha)
|
||||
insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
|
||||
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
|
||||
|
||||
# Note that we don't actually restart Pleroma.
|
||||
# See module Restarter.Pleroma
|
||||
assert capture_log(fn ->
|
||||
TransferTask.start_link([])
|
||||
|
||||
# TransferTask.start_link/1 is an asynchronous call.
|
||||
# A GenServer will first finish the previous call before starting a new one.
|
||||
# Here we do a synchronous call.
|
||||
# That way we are sure that the previous call has finished before we continue.
|
||||
Restarter.Pleroma.rebooted?()
|
||||
end) =~ "pleroma restarted"
|
||||
end
|
||||
|
||||
@tag :erratic
|
||||
test "don't restart pleroma on reboot time key and subkey if there is false flag" do
|
||||
clear_config(:shout)
|
||||
clear_config(Pleroma.Captcha)
|
||||
|
|
@ -116,7 +145,15 @@ defmodule Pleroma.Config.TransferTaskTest do
|
|||
insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
|
||||
|
||||
refute String.contains?(
|
||||
capture_log(fn -> TransferTask.load_and_update_env([], false) end),
|
||||
capture_log(fn ->
|
||||
TransferTask.load_and_update_env([], false)
|
||||
|
||||
# TransferTask.start_link/1 is an asynchronous call.
|
||||
# A GenServer will first finish the previous call before starting a new one.
|
||||
# Here we do a synchronous call.
|
||||
# That way we are sure that the previous call has finished before we continue.
|
||||
Restarter.Pleroma.rebooted?()
|
||||
end),
|
||||
"pleroma restarted"
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ defmodule Pleroma.ConfigDBTest do
|
|||
|
||||
test "get_all_as_keyword/0" do
|
||||
saved = insert(:config)
|
||||
insert(:config, group: ":quack", key: ":level", value: :info)
|
||||
insert(:config, group: ":quack", key: ":meta", value: [:none])
|
||||
insert(:config, group: ":goose", key: ":level", value: :info)
|
||||
insert(:config, group: ":goose", key: ":meta", value: [:none])
|
||||
|
||||
insert(:config,
|
||||
group: ":quack",
|
||||
group: ":goose",
|
||||
key: ":webhook_url",
|
||||
value: "https://hooks.slack.com/services/KEY/some_val"
|
||||
value: "https://gander.com/"
|
||||
)
|
||||
|
||||
config = ConfigDB.get_all_as_keyword()
|
||||
|
|
@ -31,9 +31,9 @@ defmodule Pleroma.ConfigDBTest do
|
|||
{saved.key, saved.value}
|
||||
]
|
||||
|
||||
assert config[:quack][:level] == :info
|
||||
assert config[:quack][:meta] == [:none]
|
||||
assert config[:quack][:webhook_url] == "https://hooks.slack.com/services/KEY/some_val"
|
||||
assert config[:goose][:level] == :info
|
||||
assert config[:goose][:meta] == [:none]
|
||||
assert config[:goose][:webhook_url] == "https://gander.com/"
|
||||
end
|
||||
|
||||
describe "update_or_create/1" do
|
||||
|
|
@ -238,10 +238,11 @@ defmodule Pleroma.ConfigDBTest do
|
|||
end
|
||||
|
||||
test "ssl options" do
|
||||
assert ConfigDB.to_elixir_types([":tlsv1", ":tlsv1.1", ":tlsv1.2"]) == [
|
||||
assert ConfigDB.to_elixir_types([":tlsv1", ":tlsv1.1", ":tlsv1.2", ":tlsv1.3"]) == [
|
||||
:tlsv1,
|
||||
:"tlsv1.1",
|
||||
:"tlsv1.2"
|
||||
:"tlsv1.2",
|
||||
:"tlsv1.3"
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -266,10 +267,6 @@ defmodule Pleroma.ConfigDBTest do
|
|||
assert ConfigDB.to_elixir_types("ExSyslogger") == ExSyslogger
|
||||
end
|
||||
|
||||
test "Quack.Logger module" do
|
||||
assert ConfigDB.to_elixir_types("Quack.Logger") == Quack.Logger
|
||||
end
|
||||
|
||||
test "Swoosh.Adapters modules" do
|
||||
assert ConfigDB.to_elixir_types("Swoosh.Adapters.SMTP") == Swoosh.Adapters.SMTP
|
||||
assert ConfigDB.to_elixir_types("Swoosh.Adapters.AmazonSES") == Swoosh.Adapters.AmazonSES
|
||||
|
|
@ -446,13 +443,13 @@ defmodule Pleroma.ConfigDBTest do
|
|||
|
||||
test "common keyword" do
|
||||
assert ConfigDB.to_elixir_types([
|
||||
%{"tuple" => [":level", ":warn"]},
|
||||
%{"tuple" => [":level", ":warning"]},
|
||||
%{"tuple" => [":meta", [":all"]]},
|
||||
%{"tuple" => [":path", ""]},
|
||||
%{"tuple" => [":val", nil]},
|
||||
%{"tuple" => [":webhook_url", "https://hooks.slack.com/services/YOUR-KEY-HERE"]}
|
||||
]) == [
|
||||
level: :warn,
|
||||
level: :warning,
|
||||
meta: [:all],
|
||||
path: "",
|
||||
val: nil,
|
||||
|
|
|
|||
|
|
@ -122,11 +122,11 @@ defmodule Pleroma.Conversation.ParticipationTest do
|
|||
end
|
||||
|
||||
test "it marks a participation as read" do
|
||||
participation = insert(:participation, %{read: false})
|
||||
participation = insert(:participation, %{updated_at: ~N[2017-07-17 17:09:58], read: false})
|
||||
{:ok, updated_participation} = Participation.mark_as_read(participation)
|
||||
|
||||
assert updated_participation.read
|
||||
assert updated_participation.updated_at == participation.updated_at
|
||||
assert :gt = NaiveDateTime.compare(updated_participation.updated_at, participation.updated_at)
|
||||
end
|
||||
|
||||
test "it marks a participation as unread" do
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ defmodule Pleroma.ConversationTest do
|
|||
|
||||
setup_all do: clear_config([:instance, :federating], true)
|
||||
|
||||
setup do
|
||||
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it goes through old direct conversations" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ defmodule Pleroma.Docs.GeneratorTest do
|
|||
key: :versions,
|
||||
type: {:list, :atom},
|
||||
description: "List of TLS version to use",
|
||||
suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2"]
|
||||
suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2", ":tlsv1.3"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -213,7 +213,7 @@ defmodule Pleroma.Docs.GeneratorTest do
|
|||
test "suggestion for tls versions" do
|
||||
[%{children: children} | _] = Generator.convert_to_strings(@descriptions)
|
||||
child = Enum.at(children, 8)
|
||||
assert child[:suggestions] == [":tlsv1", ":tlsv1.1", ":tlsv1.2"]
|
||||
assert child[:suggestions] == [":tlsv1", ":tlsv1.1", ":tlsv1.2", ":tlsv1.3"]
|
||||
end
|
||||
|
||||
test "subgroup with module name" do
|
||||
|
|
|
|||
90
test/pleroma/docs/translator/compiler_test.exs
Normal file
90
test/pleroma/docs/translator/compiler_test.exs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Docs.Translator.CompilerTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pleroma.Docs.Translator.Compiler
|
||||
|
||||
@descriptions [
|
||||
%{
|
||||
key: "1",
|
||||
label: "1",
|
||||
description: "2",
|
||||
children: [
|
||||
%{
|
||||
key: "3",
|
||||
label: "3",
|
||||
description: "4"
|
||||
},
|
||||
%{
|
||||
key: "5",
|
||||
label: "5",
|
||||
description: "6"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: "7",
|
||||
label: "7",
|
||||
description: "8",
|
||||
children: [
|
||||
%{
|
||||
key: "9",
|
||||
description: "9",
|
||||
children: [
|
||||
%{
|
||||
key: "10",
|
||||
description: "10",
|
||||
children: [
|
||||
%{key: "11", description: "11"},
|
||||
%{description: "12"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
label: "13"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
group: "14",
|
||||
label: "14"
|
||||
},
|
||||
%{
|
||||
group: "15",
|
||||
key: "15",
|
||||
label: "15"
|
||||
},
|
||||
%{
|
||||
group: {":subgroup", "16"},
|
||||
label: "16"
|
||||
}
|
||||
]
|
||||
|
||||
describe "extract_strings/1" do
|
||||
test "it extracts all labels and descriptions" do
|
||||
strings = Compiler.extract_strings(@descriptions)
|
||||
assert length(strings) == 16
|
||||
|
||||
assert {["1"], "label", "1"} in strings
|
||||
assert {["1"], "description", "2"} in strings
|
||||
assert {["1", "3"], "label", "3"} in strings
|
||||
assert {["1", "3"], "description", "4"} in strings
|
||||
assert {["1", "5"], "label", "5"} in strings
|
||||
assert {["1", "5"], "description", "6"} in strings
|
||||
assert {["7"], "label", "7"} in strings
|
||||
assert {["7"], "description", "8"} in strings
|
||||
assert {["7", "9"], "description", "9"} in strings
|
||||
assert {["7", "9", "10"], "description", "10"} in strings
|
||||
assert {["7", "9", "10", "11"], "description", "11"} in strings
|
||||
assert {["7", "9", "10", nil], "description", "12"} in strings
|
||||
assert {["7", nil], "label", "13"} in strings
|
||||
assert {["14"], "label", "14"} in strings
|
||||
assert {["15-15"], "label", "15"} in strings
|
||||
assert {["16"], "label", "16"} in strings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUriTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri
|
||||
|
||||
test "diaspora://" do
|
||||
text = "diaspora://alice@fediverse.example/post/deadbeefdeadbeefdeadbeefdeadbeef"
|
||||
assert {:ok, ^text} = BareUri.cast(text)
|
||||
end
|
||||
|
||||
test "nostr:" do
|
||||
text = "nostr:note1gwdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
assert {:ok, ^text} = BareUri.cast(text)
|
||||
end
|
||||
|
||||
test "errors for non-URIs" do
|
||||
assert :error == BareUri.cast(1)
|
||||
assert :error == BareUri.cast("foo")
|
||||
assert :error == BareUri.cast("foo bar")
|
||||
end
|
||||
end
|
||||
|
|
@ -90,4 +90,8 @@ defmodule Pleroma.Emoji.PackTest do
|
|||
|
||||
assert updated_pack.files_count == 1
|
||||
end
|
||||
|
||||
test "load_pack/1 ignores path traversal in a forged pack name", %{pack: pack} do
|
||||
assert {:ok, ^pack} = Pack.load_pack("../../../../../dump_pack")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ defmodule Pleroma.HTMLTest do
|
|||
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 />
|
||||
this is an inline emoji: <img class="emoji" src="http://example.com/image.jpg"><br />
|
||||
<script>alert('hacked')</script>
|
||||
"""
|
||||
|
||||
|
|
@ -24,6 +25,10 @@ defmodule Pleroma.HTMLTest do
|
|||
<img src="http://example.com/image.jpg" onerror="alert('hacked')">
|
||||
"""
|
||||
|
||||
@html_stillimage_sample """
|
||||
<img class="still-image" src="http://example.com/image.jpg">
|
||||
"""
|
||||
|
||||
@html_span_class_sample """
|
||||
<span class="animate-spin">hi</span>
|
||||
"""
|
||||
|
|
@ -45,6 +50,7 @@ defmodule Pleroma.HTMLTest do
|
|||
this is a link with allowed "rel" attribute: example.com
|
||||
this is a link with not allowed "rel" attribute: example.com
|
||||
this is an image:
|
||||
this is an inline emoji:
|
||||
alert('hacked')
|
||||
"""
|
||||
|
||||
|
|
@ -67,6 +73,7 @@ defmodule Pleroma.HTMLTest do
|
|||
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/>
|
||||
this is an inline emoji: <img class="emoji" src="http://example.com/image.jpg"/><br/>
|
||||
alert('hacked')
|
||||
"""
|
||||
|
||||
|
|
@ -90,6 +97,15 @@ defmodule Pleroma.HTMLTest do
|
|||
HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||
end
|
||||
|
||||
test "does not allow images with invalid classes" do
|
||||
expected = """
|
||||
<img src="http://example.com/image.jpg"/>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@html_stillimage_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||
end
|
||||
|
||||
test "does allow microformats" do
|
||||
expected = """
|
||||
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
||||
|
|
@ -121,6 +137,7 @@ defmodule Pleroma.HTMLTest do
|
|||
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/>
|
||||
this is an inline emoji: <img class="emoji" src="http://example.com/image.jpg"/><br/>
|
||||
alert('hacked')
|
||||
"""
|
||||
|
||||
|
|
@ -143,6 +160,15 @@ defmodule Pleroma.HTMLTest do
|
|||
assert expected == HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
|
||||
test "does not allow images with invalid classes" do
|
||||
expected = """
|
||||
<img src="http://example.com/image.jpg"/>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@html_stillimage_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||
end
|
||||
|
||||
test "does allow microformats" do
|
||||
expected = """
|
||||
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.HTTP.AdapterHelper.HackneyTest do
|
||||
use ExUnit.Case, async: true
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
|
||||
alias Pleroma.HTTP.AdapterHelper.Hackney
|
||||
|
|
|
|||
45
test/pleroma/http/web_push_test.exs
Normal file
45
test/pleroma/http/web_push_test.exs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.HTTP.WebPushTest do
|
||||
use ExUnit.Case
|
||||
|
||||
import Tesla.Mock
|
||||
alias Pleroma.HTTP
|
||||
|
||||
@push_url "https://some-push-server/"
|
||||
|
||||
setup do
|
||||
mock(fn
|
||||
%{
|
||||
method: :post,
|
||||
url: @push_url,
|
||||
headers: headers
|
||||
} ->
|
||||
if {"content-type", "octet-stream"} in headers do
|
||||
%Tesla.Env{
|
||||
status: 200
|
||||
}
|
||||
else
|
||||
%Tesla.Env{
|
||||
status: 403
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "post" do
|
||||
response =
|
||||
HTTP.WebPush.post(
|
||||
@push_url,
|
||||
"encrypted payload",
|
||||
%{"authorization" => "WebPush"},
|
||||
[]
|
||||
)
|
||||
|
||||
assert {:ok, %{status: 200}} = response
|
||||
end
|
||||
end
|
||||
|
|
@ -31,14 +31,6 @@ defmodule Pleroma.Instances.InstanceTest do
|
|||
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
|
||||
|
|
@ -161,6 +153,66 @@ defmodule Pleroma.Instances.InstanceTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "get_or_update_metadata/1" do
|
||||
test "Scrapes Wildebeest NodeInfo" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://wildebeest.example.org/.well-known/nodeinfo"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/wildebeest-well-known-nodeinfo.json")
|
||||
}
|
||||
|
||||
%{url: "https://wildebeest.example.org/nodeinfo/2.1"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/wildebeest-nodeinfo21.json")
|
||||
}
|
||||
end)
|
||||
|
||||
expected = %{
|
||||
software_name: "wildebeest",
|
||||
software_repository: "https://github.com/cloudflare/wildebeest",
|
||||
software_version: "0.0.1"
|
||||
}
|
||||
|
||||
assert expected ==
|
||||
Instance.get_or_update_metadata(URI.parse("https://wildebeest.example.org/"))
|
||||
|
||||
expected = %Pleroma.Instances.Instance.Pleroma.Instances.Metadata{
|
||||
software_name: "wildebeest",
|
||||
software_repository: "https://github.com/cloudflare/wildebeest",
|
||||
software_version: "0.0.1"
|
||||
}
|
||||
|
||||
assert expected ==
|
||||
Repo.get_by(Pleroma.Instances.Instance, %{host: "wildebeest.example.org"}).metadata
|
||||
end
|
||||
|
||||
test "Scrapes Mastodon NodeInfo" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://mastodon.example.org/.well-known/nodeinfo"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/mastodon-well-known-nodeinfo.json")
|
||||
}
|
||||
|
||||
%{url: "https://mastodon.example.org/nodeinfo/2.0"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/mastodon-nodeinfo20.json")
|
||||
}
|
||||
end)
|
||||
|
||||
expected = %{
|
||||
software_name: "mastodon",
|
||||
software_version: "4.1.0"
|
||||
}
|
||||
|
||||
assert expected ==
|
||||
Instance.get_or_update_metadata(URI.parse("https://mastodon.example.org/"))
|
||||
end
|
||||
end
|
||||
|
||||
test "delete_users_and_activities/1 deletes remote instance users and activities" do
|
||||
[mario, luigi, _peach, wario] =
|
||||
users = [
|
||||
|
|
|
|||
|
|
@ -31,22 +31,41 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
WebsocketClient.start_link(self(), path, headers)
|
||||
end
|
||||
|
||||
defp decode_json(json) do
|
||||
with {:ok, %{"event" => event, "payload" => payload_text}} <- Jason.decode(json),
|
||||
{:ok, payload} <- Jason.decode(payload_text) do
|
||||
{:ok, %{"event" => event, "payload" => payload}}
|
||||
end
|
||||
end
|
||||
|
||||
# Turns atom keys to strings
|
||||
defp atom_key_to_string(json) do
|
||||
json
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
end
|
||||
|
||||
test "refuses invalid requests" do
|
||||
capture_log(fn ->
|
||||
assert {:error, {404, _}} = start_socket()
|
||||
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
|
||||
assert {:error, %WebSockex.RequestError{code: 404}} = start_socket("?stream=ncjdk")
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
||||
test "requires authentication and a valid token for protected streams" do
|
||||
capture_log(fn ->
|
||||
assert {:error, {401, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
||||
assert {:error, {401, _}} = start_socket("?stream=user")
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} =
|
||||
start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
||||
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} = start_socket("?stream=user")
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
||||
test "allows unified stream" do
|
||||
assert {:ok, _} = start_socket()
|
||||
end
|
||||
|
||||
test "allows public streams without authentication" do
|
||||
assert {:ok, _} = start_socket("?stream=public")
|
||||
assert {:ok, _} = start_socket("?stream=public:local")
|
||||
|
|
@ -68,12 +87,143 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json", activity: activity, for: nil)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
|> atom_key_to_string()
|
||||
|
||||
assert json == view_json
|
||||
end
|
||||
|
||||
describe "subscribing via WebSocket" do
|
||||
test "can subscribe" do
|
||||
user = insert(:user)
|
||||
{:ok, pid} = start_socket()
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "public"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "nice echo chamber"})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
assert {:ok, json} = Jason.decode(raw_json)
|
||||
|
||||
assert "update" == json["event"]
|
||||
assert json["payload"]
|
||||
assert {:ok, json} = Jason.decode(json["payload"])
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json", activity: activity, for: nil)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
|
||||
assert json == view_json
|
||||
end
|
||||
|
||||
test "can subscribe to multiple streams" do
|
||||
user = insert(:user)
|
||||
{:ok, pid} = start_socket()
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "public"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "subscribe", stream: "hashtag", tag: "mew"} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "nice echo chamber #mew"})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
assert {:ok, %{"stream" => stream1}} = Jason.decode(raw_json)
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
assert {:ok, %{"stream" => stream2}} = Jason.decode(raw_json)
|
||||
|
||||
streams = [stream1, stream2]
|
||||
assert ["hashtag", "mew"] in streams
|
||||
assert ["public"] in streams
|
||||
end
|
||||
|
||||
test "won't double subscribe" do
|
||||
user = insert(:user)
|
||||
{:ok, pid} = start_socket()
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "public"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "public"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "ignored"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "nice echo chamber"})
|
||||
|
||||
assert_receive {:text, _}, 1_000
|
||||
refute_receive {:text, _}, 1_000
|
||||
end
|
||||
|
||||
test "rejects invalid streams" do
|
||||
{:ok, pid} = start_socket()
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "nonsense"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "error", "error" => "bad_topic"}
|
||||
}} = decode_json(raw_json)
|
||||
end
|
||||
|
||||
test "can unsubscribe" do
|
||||
user = insert(:user)
|
||||
{:ok, pid} = start_socket()
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "public"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
WebsocketClient.send_text(pid, %{type: "unsubscribe", stream: "public"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "unsubscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "nice echo chamber"})
|
||||
refute_receive {:text, _}, 1_000
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a valid user token" do
|
||||
setup do
|
||||
{:ok, app} =
|
||||
|
|
@ -91,7 +241,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
{:ok, token} = OAuth.Token.exchange_token(app, auth)
|
||||
|
||||
%{user: user, token: token}
|
||||
%{app: app, user: user, token: token}
|
||||
end
|
||||
|
||||
test "accepts valid tokens", state do
|
||||
|
|
@ -102,7 +252,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
capture_log(fn ->
|
||||
assert {:error, {401, _}} = start_socket("?stream=user")
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} = start_socket("?stream=user")
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
|
@ -111,7 +261,9 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||
|
||||
capture_log(fn ->
|
||||
assert {:error, {401, _}} = start_socket("?stream=user:notification")
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} =
|
||||
start_socket("?stream=user:notification")
|
||||
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
|
@ -120,11 +272,225 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||
|
||||
capture_log(fn ->
|
||||
assert {:error, {401, _}} =
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} =
|
||||
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
||||
test "accepts valid token on client-sent event", %{token: token} do
|
||||
assert {:ok, pid} = start_socket()
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "pleroma:authenticate", token: token.token} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "pleroma:authenticate", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "user"} |> Jason.encode!())
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
end
|
||||
|
||||
test "rejects invalid token on client-sent event" do
|
||||
assert {:ok, pid} = start_socket()
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "pleroma:authenticate", token: "Something else"} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{
|
||||
"type" => "pleroma:authenticate",
|
||||
"result" => "error",
|
||||
"error" => "unauthorized"
|
||||
}
|
||||
}} = decode_json(raw_json)
|
||||
end
|
||||
|
||||
test "rejects new authenticate request if already logged-in", %{token: token} do
|
||||
assert {:ok, pid} = start_socket()
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "pleroma:authenticate", token: token.token} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "pleroma:authenticate", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "pleroma:authenticate", token: "Something else"} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{
|
||||
"type" => "pleroma:authenticate",
|
||||
"result" => "error",
|
||||
"error" => "already_authenticated"
|
||||
}
|
||||
}} = decode_json(raw_json)
|
||||
end
|
||||
|
||||
test "accepts the 'list' stream", %{token: token, user: user} do
|
||||
posting_user = insert(:user)
|
||||
|
||||
{:ok, list} = Pleroma.List.create("test", user)
|
||||
Pleroma.List.follow(list, posting_user)
|
||||
|
||||
assert {:ok, _} = start_socket("?stream=list&access_token=#{token.token}&list=#{list.id}")
|
||||
|
||||
assert {:ok, pid} = start_socket("?access_token=#{token.token}")
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "subscribe", stream: "list", list: list.id} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||
}} = decode_json(raw_json)
|
||||
|
||||
WebsocketClient.send_text(
|
||||
pid,
|
||||
%{type: "subscribe", stream: "list", list: to_string(list.id)} |> Jason.encode!()
|
||||
)
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "pleroma:respond",
|
||||
"payload" => %{"type" => "subscribe", "result" => "ignored"}
|
||||
}} = decode_json(raw_json)
|
||||
end
|
||||
|
||||
test "disconnect when token is revoked", %{app: app, user: user, token: token} do
|
||||
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
{:ok, auth} = OAuth.Authorization.create_authorization(app, user)
|
||||
|
||||
{:ok, token2} = OAuth.Token.exchange_token(app, auth)
|
||||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token2.token}")
|
||||
|
||||
OAuth.Token.Strategy.Revoke.revoke(token)
|
||||
|
||||
assert_receive {:close, _}
|
||||
assert_receive {:close, _}
|
||||
refute_receive {:close, _}
|
||||
end
|
||||
|
||||
test "receives private statuses", %{user: reading_user, token: token} do
|
||||
user = insert(:user)
|
||||
CommonAPI.follow(reading_user, user)
|
||||
|
||||
{:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "nice echo chamber", visibility: "private"})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
assert {:ok, json} = Jason.decode(raw_json)
|
||||
|
||||
assert "update" == json["event"]
|
||||
assert json["payload"]
|
||||
assert {:ok, json} = Jason.decode(json["payload"])
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json",
|
||||
activity: activity,
|
||||
for: reading_user
|
||||
)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
|
||||
assert json == view_json
|
||||
end
|
||||
|
||||
test "receives edits", %{user: reading_user, token: token} do
|
||||
user = insert(:user)
|
||||
CommonAPI.follow(reading_user, user)
|
||||
|
||||
{:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "nice echo chamber", visibility: "private"})
|
||||
|
||||
assert_receive {:text, _raw_json}, 1_000
|
||||
|
||||
{:ok, _} = CommonAPI.update(user, activity, %{status: "mew mew", visibility: "private"})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
activity = Pleroma.Activity.normalize(activity)
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json",
|
||||
activity: activity,
|
||||
for: reading_user
|
||||
)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
|
||||
assert {:ok, %{"event" => "status.update", "payload" => ^view_json}} = decode_json(raw_json)
|
||||
end
|
||||
|
||||
test "receives notifications", %{user: reading_user, token: token} do
|
||||
user = insert(:user)
|
||||
CommonAPI.follow(reading_user, user)
|
||||
|
||||
{:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||
|
||||
{:ok, %Pleroma.Activity{id: activity_id} = _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "nice echo chamber @#{reading_user.nickname}",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"event" => "notification",
|
||||
"payload" => %{
|
||||
"status" => %{
|
||||
"id" => ^activity_id
|
||||
}
|
||||
}
|
||||
}} = decode_json(raw_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.NotificationTest do
|
||||
use Pleroma.DataCase
|
||||
use Pleroma.DataCase, async: false
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
|
|
@ -21,6 +21,11 @@ defmodule Pleroma.NotificationTest do
|
|||
alias Pleroma.Web.Push
|
||||
alias Pleroma.Web.Streamer
|
||||
|
||||
setup do
|
||||
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "create_notifications" do
|
||||
test "never returns nil" do
|
||||
user = insert(:user)
|
||||
|
|
@ -32,20 +37,26 @@ defmodule Pleroma.NotificationTest do
|
|||
refute {:ok, [nil]} == Notification.create_notifications(activity)
|
||||
end
|
||||
|
||||
test "creates a notification for a report" do
|
||||
test "creates a report notification only for privileged users" do
|
||||
reporting_user = insert(:user)
|
||||
reported_user = insert(:user)
|
||||
{:ok, moderator_user} = insert(:user) |> User.admin_api_update(%{is_moderator: true})
|
||||
moderator_user = insert(:user, is_moderator: true)
|
||||
|
||||
{:ok, activity} = CommonAPI.report(reporting_user, %{account_id: reported_user.id})
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
{:ok, activity1} = CommonAPI.report(reporting_user, %{account_id: reported_user.id})
|
||||
{:ok, []} = Notification.create_notifications(activity1)
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
clear_config([:instance, :moderator_privileges], [:reports_manage_reports])
|
||||
{:ok, activity2} = CommonAPI.report(reporting_user, %{account_id: reported_user.id})
|
||||
{:ok, [notification]} = Notification.create_notifications(activity2)
|
||||
|
||||
assert notification.user_id == moderator_user.id
|
||||
assert notification.type == "pleroma:report"
|
||||
end
|
||||
|
||||
test "suppresses notification to reporter if reporter is an admin" do
|
||||
test "suppresses notifications for own reports" do
|
||||
clear_config([:instance, :admin_privileges], [:reports_manage_reports])
|
||||
|
||||
reporting_admin = insert(:user, is_admin: true)
|
||||
reported_user = insert(:user)
|
||||
other_admin = insert(:user, is_admin: true)
|
||||
|
|
@ -127,6 +138,28 @@ defmodule Pleroma.NotificationTest do
|
|||
subscriber_notifications = Notification.for_user(subscriber)
|
||||
assert Enum.empty?(subscriber_notifications)
|
||||
end
|
||||
|
||||
test "it sends edited notifications to those who repeated a status" do
|
||||
user = insert(:user)
|
||||
repeated_user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity_one} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, _activity_two} = CommonAPI.repeat(activity_one.id, repeated_user)
|
||||
|
||||
{:ok, _edit_activity} =
|
||||
CommonAPI.update(user, activity_one, %{
|
||||
status: "hey @#{other_user.nickname}! mew mew"
|
||||
})
|
||||
|
||||
assert [%{type: "reblog"}] = Notification.for_user(user)
|
||||
assert [%{type: "update"}] = Notification.for_user(repeated_user)
|
||||
assert [%{type: "mention"}] = Notification.for_user(other_user)
|
||||
end
|
||||
end
|
||||
|
||||
test "create_poll_notifications/1" do
|
||||
|
|
@ -224,7 +257,7 @@ defmodule Pleroma.NotificationTest do
|
|||
task =
|
||||
Task.async(fn ->
|
||||
{:ok, _topic} = Streamer.get_topic_and_add_socket("user", user, oauth_token)
|
||||
assert_receive {:render_with_user, _, _, _}, 4_000
|
||||
assert_receive {:render_with_user, _, _, _, _}, 4_000
|
||||
end)
|
||||
|
||||
task_user_notification =
|
||||
|
|
@ -232,7 +265,7 @@ defmodule Pleroma.NotificationTest do
|
|||
{:ok, _topic} =
|
||||
Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)
|
||||
|
||||
assert_receive {:render_with_user, _, _, _}, 4_000
|
||||
assert_receive {:render_with_user, _, _, _, _}, 4_000
|
||||
end)
|
||||
|
||||
activity = insert(:note_activity)
|
||||
|
|
@ -306,6 +339,32 @@ defmodule Pleroma.NotificationTest do
|
|||
refute Notification.create_notification(activity, followed)
|
||||
end
|
||||
|
||||
test "it disables notifications from non-followees" do
|
||||
follower = insert(:user)
|
||||
|
||||
followed =
|
||||
insert(:user,
|
||||
notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
|
||||
)
|
||||
|
||||
CommonAPI.follow(follower, followed)
|
||||
{:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
|
||||
refute Notification.create_notification(activity, followed)
|
||||
end
|
||||
|
||||
test "it allows notifications from followees" do
|
||||
poster = insert(:user)
|
||||
|
||||
receiver =
|
||||
insert(:user,
|
||||
notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
|
||||
)
|
||||
|
||||
CommonAPI.follow(receiver, poster)
|
||||
{:ok, activity} = CommonAPI.post(poster, %{status: "hey @#{receiver.nickname}"})
|
||||
assert Notification.create_notification(activity, receiver)
|
||||
end
|
||||
|
||||
test "it doesn't create a notification for user if he is the activity author" do
|
||||
activity = insert(:note_activity)
|
||||
author = User.get_cached_by_ap_id(activity.data["actor"])
|
||||
|
|
@ -520,25 +579,6 @@ defmodule Pleroma.NotificationTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "destroy_multiple_from_types/2" do
|
||||
test "clears all notifications of a certain type for a given user" do
|
||||
report_activity = insert(:report_activity)
|
||||
user1 = insert(:user, is_moderator: true, is_admin: true)
|
||||
user2 = insert(:user, is_moderator: true, is_admin: true)
|
||||
{:ok, _} = Notification.create_notifications(report_activity)
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user2, %{
|
||||
status: "hey @#{user1.nickname} !"
|
||||
})
|
||||
|
||||
Notification.destroy_multiple_from_types(user1, ["pleroma:report"])
|
||||
|
||||
assert [%Pleroma.Notification{type: "mention"}] = Notification.for_user(user1)
|
||||
assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user2)
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_read_up_to()" do
|
||||
test "it sets all notifications as read up to a specified notification ID" do
|
||||
user = insert(:user)
|
||||
|
|
@ -839,6 +879,30 @@ defmodule Pleroma.NotificationTest do
|
|||
assert [other_user] == enabled_receivers
|
||||
assert [] == disabled_receivers
|
||||
end
|
||||
|
||||
test "it sends edited notifications to those who repeated a status" do
|
||||
user = insert(:user)
|
||||
repeated_user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity_one} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, _activity_two} = CommonAPI.repeat(activity_one.id, repeated_user)
|
||||
|
||||
{:ok, edit_activity} =
|
||||
CommonAPI.update(user, activity_one, %{
|
||||
status: "hey @#{other_user.nickname}! mew mew"
|
||||
})
|
||||
|
||||
{enabled_receivers, _disabled_receivers} =
|
||||
Notification.get_notified_from_activity(edit_activity)
|
||||
|
||||
assert repeated_user in enabled_receivers
|
||||
assert other_user not in enabled_receivers
|
||||
end
|
||||
end
|
||||
|
||||
describe "notification lifecycle" do
|
||||
|
|
@ -1192,5 +1256,32 @@ defmodule Pleroma.NotificationTest do
|
|||
|
||||
assert length(Notification.for_user(user)) == 1
|
||||
end
|
||||
|
||||
test "it returns notifications when related object is without content and filters are defined",
|
||||
%{user: user} do
|
||||
followed_user = insert(:user, is_locked: true)
|
||||
|
||||
insert(:filter, user: followed_user, phrase: "test", hide: true)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
|
||||
refute FollowingRelationship.following?(user, followed_user)
|
||||
assert [notification] = Notification.for_user(followed_user)
|
||||
|
||||
assert %{type: "follow_request"} =
|
||||
NotificationView.render("show.json", %{
|
||||
notification: notification,
|
||||
for: followed_user
|
||||
})
|
||||
|
||||
assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
|
||||
|
||||
assert [notification] = Notification.for_user(followed_user)
|
||||
|
||||
assert %{type: "follow"} =
|
||||
NotificationView.render("show.json", %{
|
||||
notification: notification,
|
||||
for: followed_user
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,10 +6,15 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
setup do
|
||||
|
|
@ -159,6 +164,17 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
"https://patch.cx/media/03ca3c8b4ac3ddd08bf0f84be7885f2f88de0f709112131a22d83650819e36c2.json"
|
||||
)
|
||||
end
|
||||
|
||||
test "it resets instance reachability on successful fetch" do
|
||||
id = "http://mastodon.example.org/@admin/99541947525187367"
|
||||
Instances.set_consistently_unreachable(id)
|
||||
refute Instances.reachable?(id)
|
||||
|
||||
{:ok, _object} =
|
||||
Fetcher.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
|
||||
|
||||
assert Instances.reachable?(id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "implementation quirks" do
|
||||
|
|
@ -269,4 +285,331 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
refute called(Pleroma.Signature.sign(:_, :_))
|
||||
end
|
||||
end
|
||||
|
||||
describe "refetching" do
|
||||
setup do
|
||||
insert(:user, ap_id: "https://mastodon.social/users/emelie")
|
||||
|
||||
object1 = %{
|
||||
"id" => "https://mastodon.social/1",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"type" => "Note",
|
||||
"content" => "test 1",
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z",
|
||||
"updated" => "2023-05-09 23:43:20Z"
|
||||
}
|
||||
|
||||
{:ok, local_object1, _} = ObjectValidator.validate(object1, [])
|
||||
|
||||
object2 = %{
|
||||
"id" => "https://mastodon.social/2",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"type" => "Note",
|
||||
"content" => "test 2",
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z",
|
||||
"updated" => "2023-05-09 23:43:25Z",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Note",
|
||||
"content" => "orig 2",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z",
|
||||
"updated" => "2023-05-09 23:43:21Z"
|
||||
}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, local_object2, _} = ObjectValidator.validate(object2, [])
|
||||
|
||||
mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://mastodon.social/1"
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: Jason.encode!(object1 |> Map.put("updated", "2023-05-09 23:44:20Z"))
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://mastodon.social/2"
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: Jason.encode!(object2 |> Map.put("updated", "2023-05-09 23:44:20Z"))
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://mastodon.social/users/emelie/collections/featured"
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
Jason.encode!(%{
|
||||
"id" => "https://mastodon.social/users/emelie/collections/featured",
|
||||
"type" => "OrderedCollection",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"orderedItems" => [],
|
||||
"totalItems" => 0
|
||||
})
|
||||
}
|
||||
|
||||
env ->
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
|
||||
%{object1: local_object1, object2: local_object2}
|
||||
end
|
||||
|
||||
test "it keeps formerRepresentations if remote does not have this attr", %{object1: object1} do
|
||||
full_object1 =
|
||||
object1
|
||||
|> Map.merge(%{
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Note",
|
||||
"content" => "orig 2",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => [],
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"summary" => "",
|
||||
"published" => "2023-05-08 23:43:20Z"
|
||||
}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
})
|
||||
|
||||
{:ok, o} = Object.create(full_object1)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{"formerRepresentations" => %{"orderedItems" => [%{"content" => "orig 2"}]}} =
|
||||
refetched.data
|
||||
end
|
||||
|
||||
test "it uses formerRepresentations from remote if possible", %{object2: object2} do
|
||||
{:ok, o} = Object.create(object2)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{"formerRepresentations" => %{"orderedItems" => [%{"content" => "orig 2"}]}} =
|
||||
refetched.data
|
||||
end
|
||||
|
||||
test "it replaces formerRepresentations with the one from remote", %{object2: object2} do
|
||||
full_object2 =
|
||||
object2
|
||||
|> Map.merge(%{
|
||||
"content" => "mew mew #def",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{"type" => "Note", "content" => "mew mew 2"}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
})
|
||||
|
||||
{:ok, o} = Object.create(full_object2)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{
|
||||
"content" => "test 2",
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => "orig 2"}]}
|
||||
} = refetched.data
|
||||
end
|
||||
|
||||
test "it adds to formerRepresentations if the remote does not have one and the object has changed",
|
||||
%{object1: object1} do
|
||||
full_object1 =
|
||||
object1
|
||||
|> Map.merge(%{
|
||||
"content" => "mew mew #def",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{"type" => "Note", "content" => "mew mew 1"}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
})
|
||||
|
||||
{:ok, o} = Object.create(full_object1)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{
|
||||
"content" => "test 1",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{"content" => "mew mew #def"},
|
||||
%{"content" => "mew mew 1"}
|
||||
],
|
||||
"totalItems" => 2
|
||||
}
|
||||
} = refetched.data
|
||||
end
|
||||
|
||||
test "it keeps the history intact if only updated time has changed",
|
||||
%{object1: object1} do
|
||||
full_object1 =
|
||||
object1
|
||||
|> Map.merge(%{
|
||||
"updated" => "2023-05-08 23:43:47Z",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{"type" => "Note", "content" => "mew mew 1"}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
})
|
||||
|
||||
{:ok, o} = Object.create(full_object1)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{
|
||||
"content" => "test 1",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{"content" => "mew mew 1"}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
} = refetched.data
|
||||
end
|
||||
|
||||
test "it goes through ObjectValidator and MRF", %{object2: object2} do
|
||||
with_mock Pleroma.Web.ActivityPub.MRF, [:passthrough],
|
||||
filter: fn
|
||||
%{"type" => "Note"} = object ->
|
||||
{:ok, Map.put(object, "content", "MRFd content")}
|
||||
|
||||
arg ->
|
||||
passthrough([arg])
|
||||
end do
|
||||
{:ok, o} = Object.create(object2)
|
||||
|
||||
assert {:ok, refetched} = Fetcher.refetch_object(o)
|
||||
|
||||
assert %{"content" => "MRFd content"} = refetched.data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch with history" do
|
||||
setup do
|
||||
object2 = %{
|
||||
"id" => "https://mastodon.social/2",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"type" => "Note",
|
||||
"content" => "test 2",
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => ["https://mastodon.social/users/emelie/followers"],
|
||||
"to" => [],
|
||||
"summary" => "",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Note",
|
||||
"content" => "orig 2",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"bcc" => [],
|
||||
"bto" => [],
|
||||
"cc" => ["https://mastodon.social/users/emelie/followers"],
|
||||
"to" => [],
|
||||
"summary" => ""
|
||||
}
|
||||
],
|
||||
"totalItems" => 1
|
||||
}
|
||||
}
|
||||
|
||||
mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://mastodon.social/2"
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: Jason.encode!(object2)
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://mastodon.social/users/emelie/collections/featured"
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
Jason.encode!(%{
|
||||
"id" => "https://mastodon.social/users/emelie/collections/featured",
|
||||
"type" => "OrderedCollection",
|
||||
"actor" => "https://mastodon.social/users/emelie",
|
||||
"attributedTo" => "https://mastodon.social/users/emelie",
|
||||
"orderedItems" => [],
|
||||
"totalItems" => 0
|
||||
})
|
||||
}
|
||||
|
||||
env ->
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
|
||||
%{object2: object2}
|
||||
end
|
||||
|
||||
test "it gets history", %{object2: object2} do
|
||||
{:ok, object} = Fetcher.fetch_object_from_id(object2["id"])
|
||||
|
||||
assert %{
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [%{}]
|
||||
}
|
||||
} = object.data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
76
test/pleroma/object/updater_test.exs
Normal file
76
test/pleroma/object/updater_test.exs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Object.UpdaterTest do
|
||||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Object.Updater
|
||||
|
||||
describe "make_update_object_data/3" do
|
||||
setup do
|
||||
note = insert(:note)
|
||||
%{original_data: note.data}
|
||||
end
|
||||
|
||||
test "it makes an updated field", %{original_data: original_data} do
|
||||
new_data = Map.put(original_data, "content", "new content")
|
||||
|
||||
date = Pleroma.Web.ActivityPub.Utils.make_date()
|
||||
update_object_data = Updater.make_update_object_data(original_data, new_data, date)
|
||||
assert %{"updated" => ^date} = update_object_data
|
||||
end
|
||||
|
||||
test "it creates formerRepresentations", %{original_data: original_data} do
|
||||
new_data = Map.put(original_data, "content", "new content")
|
||||
|
||||
date = Pleroma.Web.ActivityPub.Utils.make_date()
|
||||
update_object_data = Updater.make_update_object_data(original_data, new_data, date)
|
||||
|
||||
history_item = original_data |> Map.drop(["id", "formerRepresentations"])
|
||||
|
||||
assert %{
|
||||
"formerRepresentations" => %{
|
||||
"totalItems" => 1,
|
||||
"orderedItems" => [^history_item]
|
||||
}
|
||||
} = update_object_data
|
||||
end
|
||||
end
|
||||
|
||||
describe "make_new_object_data_from_update_object/2" do
|
||||
test "it reuses formerRepresentations if it exists" do
|
||||
%{data: original_data} = insert(:note)
|
||||
|
||||
new_data =
|
||||
original_data
|
||||
|> Map.put("content", "edited")
|
||||
|
||||
date = Pleroma.Web.ActivityPub.Utils.make_date()
|
||||
update_object_data = Updater.make_update_object_data(original_data, new_data, date)
|
||||
|
||||
history = update_object_data["formerRepresentations"]["orderedItems"]
|
||||
|
||||
update_object_data =
|
||||
update_object_data
|
||||
|> put_in(
|
||||
["formerRepresentations", "orderedItems"],
|
||||
history ++ [Map.put(original_data, "summary", "additional summary")]
|
||||
)
|
||||
|> put_in(["formerRepresentations", "totalItems"], length(history) + 1)
|
||||
|
||||
%{
|
||||
updated_data: updated_data,
|
||||
updated: updated,
|
||||
used_history_in_new_object?: used_history_in_new_object?
|
||||
} = Updater.make_new_object_data_from_update_object(original_data, update_object_data)
|
||||
|
||||
assert updated
|
||||
assert used_history_in_new_object?
|
||||
assert updated_data["formerRepresentations"] == update_object_data["formerRepresentations"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.ObjectTest do
|
|||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
|
|
@ -15,10 +16,12 @@ defmodule Pleroma.ObjectTest do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
ConfigMock |> stub_with(Pleroma.Test.StaticConfig)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
|
@ -444,4 +447,42 @@ defmodule Pleroma.ObjectTest do
|
|||
Enum.sort_by(object.hashtags, & &1.name)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_emoji_reactions/1" do
|
||||
test "3-tuple current format" do
|
||||
object = %Object{
|
||||
data: %{
|
||||
"reactions" => [
|
||||
["x", ["https://some/user"], "https://some/emoji"]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
assert Object.get_emoji_reactions(object) == object.data["reactions"]
|
||||
end
|
||||
|
||||
test "2-tuple legacy format" do
|
||||
object = %Object{
|
||||
data: %{
|
||||
"reactions" => [
|
||||
["x", ["https://some/user"]]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
assert Object.get_emoji_reactions(object) == [["x", ["https://some/user"], nil]]
|
||||
end
|
||||
|
||||
test "Map format" do
|
||||
object = %Object{
|
||||
data: %{
|
||||
"reactions" => %{
|
||||
"x" => ["https://some/user"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert Object.get_emoji_reactions(object) == [["x", ["https://some/user"], nil]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,4 +13,27 @@ defmodule Pleroma.ReportNoteTest do
|
|||
assert {:ok, note} = ReportNote.create(user.id, report.id, "naughty boy")
|
||||
assert note.content == "naughty boy"
|
||||
end
|
||||
|
||||
test "create/3 with very long content" do
|
||||
user = insert(:user)
|
||||
report = insert(:report_activity)
|
||||
|
||||
very_long_content = """
|
||||
] pwgen 25 15
|
||||
eJ9eeceiquoolei2queeLeimi aiN9ie2iokie8chush7aiph5N ulaNgaighoPiequaipuzoog8F
|
||||
Ohphei0hee6hoo0wah4Aasah9 ziel3Yo3eew4neiy3ekiesh8u ue9ShahTh7oongoPheeneijah
|
||||
ohGheeCh6aloque0Neviopou3 ush2oobohxeec4aequeich3Oo Ze3eighoowiojadohch8iCa1n
|
||||
Yu4yieBie9eengoich8fae4th chohqu6exooSiibogh3iefeez peephahtaik9quie5mohD9nee
|
||||
eeQuur3rie5mei8ieng6iesie wei1meinguv0Heidoov8Ibaed deemo2Poh6ohc3eiBeez1uox2
|
||||
] pwgen 25 15
|
||||
eJ9eeceiquoolei2queeLeimi aiN9ie2iokie8chush7aiph5N ulaNgaighoPiequaipuzoog8F
|
||||
Ohphei0hee6hoo0wah4Aasah9 ziel3Yo3eew4neiy3ekiesh8u ue9ShahTh7oongoPheeneijah
|
||||
ohGheeCh6aloque0Neviopou3 ush2oobohxeec4aequeich3Oo Ze3eighoowiojadohch8iCa1n
|
||||
Yu4yieBie9eengoich8fae4th chohqu6exooSiibogh3iefeez peephahtaik9quie5mohD9nee
|
||||
eeQuur3rie5mei8ieng6iesie wei1meinguv0Heidoov8Ibaed deemo2Poh6ohc3eiBeez1uox2
|
||||
"""
|
||||
|
||||
assert {:ok, note} = ReportNote.create(user.id, report.id, very_long_content)
|
||||
assert note.content == very_long_content
|
||||
end
|
||||
end
|
||||
|
|
|
|||
103
test/pleroma/resilience_test.exs
Normal file
103
test/pleroma/resilience_test.exs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ResilienceTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
setup do
|
||||
# user = insert(:user)
|
||||
%{user: user, conn: conn} = oauth_access(["write", "read"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, post_one} = CommonAPI.post(user, %{status: "Here is a post"})
|
||||
{:ok, like} = CommonAPI.favorite(other_user, post_one.id)
|
||||
|
||||
%{
|
||||
user: user,
|
||||
other_user: other_user,
|
||||
post_one: post_one,
|
||||
like: like,
|
||||
conn: conn
|
||||
}
|
||||
end
|
||||
|
||||
test "after destruction of like activities, things still work", %{
|
||||
user: user,
|
||||
post_one: post,
|
||||
other_user: other_user,
|
||||
conn: conn,
|
||||
like: like
|
||||
} do
|
||||
post = Repo.get(Activity, post.id)
|
||||
|
||||
# Rendering the liked status
|
||||
rendered_for_user = StatusView.render("show.json", %{activity: post, for: user})
|
||||
assert rendered_for_user.favourites_count == 1
|
||||
|
||||
rendered_for_other_user = StatusView.render("show.json", %{activity: post, for: other_user})
|
||||
assert rendered_for_other_user.favourites_count == 1
|
||||
assert rendered_for_other_user.favourited
|
||||
|
||||
# Getting the favourited by
|
||||
[liking_user] =
|
||||
conn
|
||||
|> get("/api/v1/statuses/#{post.id}/favourited_by")
|
||||
|> json_response(200)
|
||||
|
||||
assert liking_user["id"] == other_user.id
|
||||
|
||||
# We have one notification
|
||||
[notification] =
|
||||
conn
|
||||
|> get("/api/v1/notifications")
|
||||
|> json_response(200)
|
||||
|
||||
assert notification["type"] == "favourite"
|
||||
|
||||
# Destroying the like
|
||||
Repo.delete(like)
|
||||
post = Repo.get(Activity, post.id)
|
||||
|
||||
# Rendering the liked status
|
||||
rendered_for_user = StatusView.render("show.json", %{activity: post, for: user})
|
||||
assert rendered_for_user.favourites_count == 1
|
||||
|
||||
rendered_for_other_user = StatusView.render("show.json", %{activity: post, for: other_user})
|
||||
assert rendered_for_other_user.favourites_count == 1
|
||||
assert rendered_for_other_user.favourited
|
||||
|
||||
# Getting the favourited by
|
||||
[liking_user] =
|
||||
conn
|
||||
|> get("/api/v1/statuses/#{post.id}/favourited_by")
|
||||
|> json_response(200)
|
||||
|
||||
assert liking_user["id"] == other_user.id
|
||||
|
||||
# Notification is removed
|
||||
|
||||
assert [] ==
|
||||
conn
|
||||
|> get("/api/v1/notifications")
|
||||
|> json_response(200)
|
||||
|
||||
# Favoriting again doesn't hurt
|
||||
{:ok, _like_two} = CommonAPI.favorite(other_user, post.id)
|
||||
|
||||
post = Repo.get(Activity, post.id)
|
||||
|
||||
# Rendering the liked status
|
||||
rendered_for_user = StatusView.render("show.json", %{activity: post, for: user})
|
||||
assert rendered_for_user.favourites_count == 1
|
||||
|
||||
# General fallout: Can't unfavorite stuff anymore. Acceptable for remote users.
|
||||
end
|
||||
end
|
||||
|
|
@ -3,19 +3,23 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ScheduledActivityTest do
|
||||
use Pleroma.DataCase
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.ScheduledActivity
|
||||
alias Pleroma.Test.StaticConfig
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: clear_config([ScheduledActivity, :enabled])
|
||||
|
||||
setup [:ensure_local_uploader]
|
||||
|
||||
describe "creation" do
|
||||
test "scheduled activities with jobs when ScheduledActivity enabled" do
|
||||
clear_config([ScheduledActivity, :enabled], true)
|
||||
ConfigMock
|
||||
|> stub(:get, fn
|
||||
[ScheduledActivity, :enabled] -> true
|
||||
path -> StaticConfig.get(path)
|
||||
end)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
|
|
@ -34,7 +38,12 @@ defmodule Pleroma.ScheduledActivityTest do
|
|||
end
|
||||
|
||||
test "scheduled activities without jobs when ScheduledActivity disabled" do
|
||||
clear_config([ScheduledActivity, :enabled], false)
|
||||
ConfigMock
|
||||
|> stub(:get, fn
|
||||
[ScheduledActivity, :enabled] -> false
|
||||
path -> StaticConfig.get(path)
|
||||
end)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
|
|
@ -53,6 +62,9 @@ defmodule Pleroma.ScheduledActivityTest do
|
|||
end
|
||||
|
||||
test "when daily user limit is exceeded" do
|
||||
ConfigMock
|
||||
|> stub_with(StaticConfig)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
|
|
@ -69,6 +81,9 @@ defmodule Pleroma.ScheduledActivityTest do
|
|||
end
|
||||
|
||||
test "when total user limit is exceeded" do
|
||||
ConfigMock
|
||||
|> stub_with(StaticConfig)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
today =
|
||||
|
|
@ -89,6 +104,9 @@ defmodule Pleroma.ScheduledActivityTest do
|
|||
end
|
||||
|
||||
test "when scheduled_at is earlier than 5 minute from now" do
|
||||
ConfigMock
|
||||
|> stub_with(StaticConfig)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
scheduled_at =
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Activity.SearchTest do
|
||||
alias Pleroma.Activity.Search
|
||||
defmodule Pleroma.Search.DatabaseSearchTest do
|
||||
alias Pleroma.Search.DatabaseSearch, as: Search
|
||||
alias Pleroma.Web.CommonAPI
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -18,6 +18,23 @@ defmodule Pleroma.Activity.SearchTest do
|
|||
assert result.id == post.id
|
||||
end
|
||||
|
||||
test "it finds local-only posts for authenticated users" do
|
||||
user = insert(:user)
|
||||
reader = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes", visibility: "local"})
|
||||
|
||||
[result] = Search.search(reader, "wednesday")
|
||||
|
||||
assert result.id == post.id
|
||||
end
|
||||
|
||||
test "it does not find local-only posts for anonymous users" do
|
||||
user = insert(:user)
|
||||
{:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes", visibility: "local"})
|
||||
|
||||
assert [] = Search.search(nil, "wednesday")
|
||||
end
|
||||
|
||||
test "using plainto_tsquery on postgres < 11" do
|
||||
old_version = :persistent_term.get({Pleroma.Repo, :postgres_version})
|
||||
:persistent_term.put({Pleroma.Repo, :postgres_version}, 10.0)
|
||||
160
test/pleroma/search/meilisearch_test.exs
Normal file
160
test/pleroma/search/meilisearch_test.exs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Search.MeilisearchTest do
|
||||
require Pleroma.Constants
|
||||
|
||||
use Pleroma.DataCase, async: true
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
import Mox
|
||||
|
||||
alias Pleroma.Search.Meilisearch
|
||||
alias Pleroma.UnstubbedConfigMock, as: Config
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.SearchIndexingWorker
|
||||
|
||||
describe "meilisearch" do
|
||||
test "indexes a local post on creation" do
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :put,
|
||||
url: "http://127.0.0.1:7700/indexes/objects/documents",
|
||||
body: body
|
||||
} ->
|
||||
assert match?(
|
||||
[%{"content" => "guys i just don't wanna leave the swamp"}],
|
||||
Jason.decode!(body)
|
||||
)
|
||||
|
||||
# To make sure that the worker is called
|
||||
send(self(), "posted_to_meilisearch")
|
||||
|
||||
%{
|
||||
"enqueuedAt" => "2023-11-12T12:36:46.927517Z",
|
||||
"indexUid" => "objects",
|
||||
"status" => "enqueued",
|
||||
"taskUid" => 6,
|
||||
"type" => "documentAdditionOrUpdate"
|
||||
}
|
||||
|> json()
|
||||
end)
|
||||
|
||||
Config
|
||||
|> expect(:get, 3, fn
|
||||
[Pleroma.Search, :module], nil ->
|
||||
Meilisearch
|
||||
|
||||
[Pleroma.Search.Meilisearch, :url], nil ->
|
||||
"http://127.0.0.1:7700"
|
||||
|
||||
[Pleroma.Search.Meilisearch, :private_key], nil ->
|
||||
"secret"
|
||||
end)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "guys i just don't wanna leave the swamp",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
args = %{"op" => "add_to_index", "activity" => activity.id}
|
||||
|
||||
assert_enqueued(
|
||||
worker: SearchIndexingWorker,
|
||||
args: args
|
||||
)
|
||||
|
||||
assert :ok = perform_job(SearchIndexingWorker, args)
|
||||
assert_received("posted_to_meilisearch")
|
||||
end
|
||||
|
||||
test "doesn't index posts that are not public" do
|
||||
user = insert(:user)
|
||||
|
||||
Enum.each(["private", "direct"], fn visibility ->
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "guys i just don't wanna leave the swamp",
|
||||
visibility: visibility
|
||||
})
|
||||
|
||||
args = %{"op" => "add_to_index", "activity" => activity.id}
|
||||
|
||||
Config
|
||||
|> expect(:get, fn
|
||||
[Pleroma.Search, :module], nil ->
|
||||
Meilisearch
|
||||
end)
|
||||
|
||||
assert_enqueued(worker: SearchIndexingWorker, args: args)
|
||||
assert :ok = perform_job(SearchIndexingWorker, args)
|
||||
end)
|
||||
end
|
||||
|
||||
test "deletes posts from index when deleted locally" do
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :put,
|
||||
url: "http://127.0.0.1:7700/indexes/objects/documents",
|
||||
body: body
|
||||
} ->
|
||||
assert match?(
|
||||
[%{"content" => "guys i just don't wanna leave the swamp"}],
|
||||
Jason.decode!(body)
|
||||
)
|
||||
|
||||
%{
|
||||
"enqueuedAt" => "2023-11-12T12:36:46.927517Z",
|
||||
"indexUid" => "objects",
|
||||
"status" => "enqueued",
|
||||
"taskUid" => 6,
|
||||
"type" => "documentAdditionOrUpdate"
|
||||
}
|
||||
|> json()
|
||||
|
||||
%{method: :delete, url: "http://127.0.0.1:7700/indexes/objects/documents/" <> id} ->
|
||||
send(self(), "called_delete")
|
||||
assert String.length(id) > 1
|
||||
json(%{})
|
||||
end)
|
||||
|
||||
Config
|
||||
|> expect(:get, 6, fn
|
||||
[Pleroma.Search, :module], nil ->
|
||||
Meilisearch
|
||||
|
||||
[Pleroma.Search.Meilisearch, :url], nil ->
|
||||
"http://127.0.0.1:7700"
|
||||
|
||||
[Pleroma.Search.Meilisearch, :private_key], nil ->
|
||||
"secret"
|
||||
end)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "guys i just don't wanna leave the swamp",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
args = %{"op" => "add_to_index", "activity" => activity.id}
|
||||
assert_enqueued(worker: SearchIndexingWorker, args: args)
|
||||
assert :ok = perform_job(SearchIndexingWorker, args)
|
||||
|
||||
{:ok, _} = CommonAPI.delete(activity.id, user)
|
||||
|
||||
delete_args = %{"op" => "remove_from_index", "object" => activity.object.id}
|
||||
assert_enqueued(worker: SearchIndexingWorker, args: delete_args)
|
||||
assert :ok = perform_job(SearchIndexingWorker, delete_args)
|
||||
|
||||
assert_received("called_delete")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -43,10 +43,7 @@ defmodule Pleroma.SignatureTest do
|
|||
end
|
||||
|
||||
test "it returns error when not found user" do
|
||||
assert capture_log(fn ->
|
||||
assert Signature.fetch_public_key(make_fake_conn("https://test-ap-id")) ==
|
||||
{:error, :error}
|
||||
end) =~ "[error] Could not decode user"
|
||||
assert Signature.fetch_public_key(make_fake_conn("https://test-ap-id")) == {:error, :error}
|
||||
end
|
||||
|
||||
test "it returns error if public key is nil" do
|
||||
|
|
@ -109,6 +106,11 @@ defmodule Pleroma.SignatureTest do
|
|||
{:ok, "https://example.com/users/1234"}
|
||||
end
|
||||
|
||||
test "it deduces the actor id for gotoSocial" do
|
||||
assert Signature.key_id_to_actor_id("https://example.com/users/1234/main-key") ==
|
||||
{:ok, "https://example.com/users/1234"}
|
||||
end
|
||||
|
||||
test "it calls webfinger for 'acct:' accounts" do
|
||||
with_mock(Pleroma.Web.WebFinger,
|
||||
finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end
|
||||
|
|
|
|||
|
|
@ -20,6 +20,20 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadataTest do
|
|||
assert meta.blurhash
|
||||
end
|
||||
|
||||
test "it blurhashes images with an alpha component" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "an… image.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/png_with_transparency.png"),
|
||||
tempfile: Path.absname("test/fixtures/png_with_transparency.png")
|
||||
}
|
||||
|
||||
{:ok, :filtered, meta} = AnalyzeMetadata.filter(upload)
|
||||
|
||||
assert %{width: 320, height: 320} = meta
|
||||
assert meta.blurhash == "eXJi-E:SwCEm5rCmn$+YWYn+15K#5A$xxCi{SiV]s*W:Efa#s.jE-T"
|
||||
end
|
||||
|
||||
test "adds the dimensions for videos" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "coolvideo.mp4",
|
||||
|
|
|
|||
144
test/pleroma/upload/filter/exiftool/read_description_test.exs
Normal file
144
test/pleroma/upload/filter/exiftool/read_description_test.exs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.Exiftool.ReadDescriptionTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Upload.Filter
|
||||
|
||||
@uploads %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
test "keeps description when not empty" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
tempfile:
|
||||
Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
description: "Some description"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :noop}
|
||||
end
|
||||
|
||||
test "otherwise returns ImageDescription when present" do
|
||||
uploads_after = %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
tempfile:
|
||||
Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
description: "a descriptive white pixel"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(@uploads) ==
|
||||
{:ok, :filtered, uploads_after}
|
||||
end
|
||||
|
||||
test "Ignores warnings" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract_and_stray_data_after.png",
|
||||
content_type: "image/png",
|
||||
path:
|
||||
Path.absname(
|
||||
"test/fixtures/image_with_imagedescription_and_caption-abstract_and_stray_data_after.png"
|
||||
),
|
||||
tempfile:
|
||||
Path.absname(
|
||||
"test/fixtures/image_with_imagedescription_and_caption-abstract_and_stray_data_after.png"
|
||||
)
|
||||
}
|
||||
|
||||
assert {:ok, :filtered, %{description: "a descriptive white pixel"}} =
|
||||
Filter.Exiftool.ReadDescription.filter(uploads)
|
||||
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "image_with_stray_data_after.png",
|
||||
content_type: "image/png",
|
||||
path: Path.absname("test/fixtures/image_with_stray_data_after.png"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_stray_data_after.png")
|
||||
}
|
||||
|
||||
assert {:ok, :filtered, %{description: nil}} = Filter.Exiftool.ReadDescription.filter(uploads)
|
||||
end
|
||||
|
||||
test "otherwise returns iptc:Caption-Abstract when present" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "image_with_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
upload_after = %Pleroma.Upload{
|
||||
name: "image_with_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
description: "an abstract white pixel"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(upload) ==
|
||||
{:ok, :filtered, upload_after}
|
||||
end
|
||||
|
||||
test "otherwise returns nil" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "image_with_no_description.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_no_description.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_no_description.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :filtered, uploads}
|
||||
end
|
||||
|
||||
test "Return nil when image description from EXIF data exceeds the maximum length" do
|
||||
clear_config([:instance, :description_limit], 5)
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(@uploads) ==
|
||||
{:ok, :filtered, @uploads}
|
||||
end
|
||||
|
||||
test "Ignores content with only whitespace" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "non-existant.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path:
|
||||
Path.absname(
|
||||
"test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg"
|
||||
),
|
||||
tempfile:
|
||||
Path.absname(
|
||||
"test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg"
|
||||
),
|
||||
description: nil
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :filtered, uploads}
|
||||
end
|
||||
|
||||
test "Return nil when image description from EXIF data can't be read" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "non-existant.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/non-existant.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/non-existant_tmp.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :filtered, uploads}
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.ExiftoolTest do
|
||||
defmodule Pleroma.Upload.Filter.Exiftool.StripLocationTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Upload.Filter
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ defmodule Pleroma.Upload.Filter.ExiftoolTest do
|
|||
tempfile: Path.absname("test/fixtures/DSCN0010_tmp.jpg")
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.filter(upload) == {:ok, :filtered}
|
||||
assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :filtered}
|
||||
|
||||
{exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.jpg"])
|
||||
{exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.jpg"])
|
||||
|
|
@ -31,12 +31,19 @@ defmodule Pleroma.Upload.Filter.ExiftoolTest do
|
|||
refute String.match?(exif_filtered, ~r/GPS/)
|
||||
end
|
||||
|
||||
test "verify webp files are skipped" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "sample.webp",
|
||||
content_type: "image/webp"
|
||||
}
|
||||
test "verify webp, heic, svg files are skipped" do
|
||||
uploads =
|
||||
~w{webp heic svg svg+xml}
|
||||
|> Enum.map(fn type ->
|
||||
%Pleroma.Upload{
|
||||
name: "sample.#{type}",
|
||||
content_type: "image/#{type}"
|
||||
}
|
||||
end)
|
||||
|
||||
assert Filter.Exiftool.filter(upload) == {:ok, :noop}
|
||||
uploads
|
||||
|> Enum.each(fn upload ->
|
||||
assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :noop}
|
||||
end)
|
||||
end
|
||||
end
|
||||
32
test/pleroma/upload/filter/only_media_test.exs
Normal file
32
test/pleroma/upload/filter/only_media_test.exs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.OnlyMediaTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.Upload.Filter.OnlyMedia
|
||||
|
||||
test "Allows media Content-Type" do
|
||||
["audio/mpeg", "image/jpeg", "video/mp4"]
|
||||
|> Enum.each(fn type ->
|
||||
upload = %Upload{
|
||||
content_type: type
|
||||
}
|
||||
|
||||
assert {:ok, :noop} = OnlyMedia.filter(upload)
|
||||
end)
|
||||
end
|
||||
|
||||
test "Disallows non-media Content-Type" do
|
||||
["application/javascript", "application/pdf", "text/html"]
|
||||
|> Enum.each(fn type ->
|
||||
upload = %Upload{
|
||||
content_type: type
|
||||
}
|
||||
|
||||
assert {:error, _} = OnlyMedia.filter(upload)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -6,10 +6,19 @@ defmodule Pleroma.UploadTest do
|
|||
use Pleroma.DataCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mox
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.Uploaders.Uploader
|
||||
|
||||
setup do
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
@upload_file %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_tmp.jpg"),
|
||||
|
|
@ -49,20 +58,22 @@ defmodule Pleroma.UploadTest do
|
|||
test "it returns file" do
|
||||
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||
|
||||
assert Upload.store(@upload_file) ==
|
||||
{:ok,
|
||||
%{
|
||||
"name" => "image.jpg",
|
||||
"type" => "Document",
|
||||
"mediaType" => "image/jpeg",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "http://localhost:4001/media/post-process-file.jpg",
|
||||
"mediaType" => "image/jpeg",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}}
|
||||
assert {:ok, result} = Upload.store(@upload_file)
|
||||
|
||||
assert result ==
|
||||
%{
|
||||
"id" => result["id"],
|
||||
"name" => "image.jpg",
|
||||
"type" => "Document",
|
||||
"mediaType" => "image/jpeg",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "http://localhost:4001/media/post-process-file.jpg",
|
||||
"mediaType" => "image/jpeg",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Task.await(Agent.get(TestUploaderSuccess, fn task_pid -> task_pid end))
|
||||
end
|
||||
|
|
@ -234,6 +245,8 @@ defmodule Pleroma.UploadTest do
|
|||
describe "Setting a custom base_url for uploaded media" do
|
||||
setup do: clear_config([Pleroma.Upload, :base_url], "https://cache.pleroma.social")
|
||||
|
||||
# This seems to be backwards. Skipped for that reason
|
||||
@tag skip: true
|
||||
test "returns a media url with configured base_url" do
|
||||
base_url = Pleroma.Config.get([Pleroma.Upload, :base_url])
|
||||
|
||||
|
|
|
|||
|
|
@ -3,22 +3,27 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Uploaders.S3Test do
|
||||
use Pleroma.DataCase
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Uploaders.S3
|
||||
alias Pleroma.Uploaders.S3.ExAwsMock
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
setup do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3)
|
||||
clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com")
|
||||
clear_config([Pleroma.Uploaders.S3])
|
||||
clear_config([Pleroma.Uploaders.S3, :bucket], "test_bucket")
|
||||
end
|
||||
|
||||
describe "get_file/1" do
|
||||
test "it returns path to local folder for files" do
|
||||
test "it returns url for files" do
|
||||
ConfigMock
|
||||
|> expect(:get, 6, fn key ->
|
||||
[
|
||||
{Pleroma.Upload,
|
||||
[uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]},
|
||||
{Pleroma.Uploaders.S3, [bucket: "test_bucket"]}
|
||||
]
|
||||
|> get_in(key)
|
||||
end)
|
||||
|
||||
assert S3.get_file("test_image.jpg") == {
|
||||
:ok,
|
||||
{:url, "https://s3.amazonaws.com/test_bucket/test_image.jpg"}
|
||||
|
|
@ -26,13 +31,16 @@ defmodule Pleroma.Uploaders.S3Test do
|
|||
end
|
||||
|
||||
test "it returns path without bucket when truncated_namespace set to ''" do
|
||||
clear_config([Pleroma.Uploaders.S3],
|
||||
bucket: "test_bucket",
|
||||
bucket_namespace: "myaccount",
|
||||
truncated_namespace: ""
|
||||
)
|
||||
|
||||
clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com")
|
||||
ConfigMock
|
||||
|> expect(:get, 6, fn key ->
|
||||
[
|
||||
{Pleroma.Upload,
|
||||
[uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]},
|
||||
{Pleroma.Uploaders.S3,
|
||||
[bucket: "test_bucket", truncated_namespace: "", bucket_namespace: "myaccount"]}
|
||||
]
|
||||
|> get_in(key)
|
||||
end)
|
||||
|
||||
assert S3.get_file("test_image.jpg") == {
|
||||
:ok,
|
||||
|
|
@ -41,10 +49,15 @@ defmodule Pleroma.Uploaders.S3Test do
|
|||
end
|
||||
|
||||
test "it returns path with bucket namespace when namespace is set" do
|
||||
clear_config([Pleroma.Uploaders.S3],
|
||||
bucket: "test_bucket",
|
||||
bucket_namespace: "family"
|
||||
)
|
||||
ConfigMock
|
||||
|> expect(:get, 6, fn key ->
|
||||
[
|
||||
{Pleroma.Upload,
|
||||
[uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]},
|
||||
{Pleroma.Uploaders.S3, [bucket: "test_bucket", bucket_namespace: "family"]}
|
||||
]
|
||||
|> get_in(key)
|
||||
end)
|
||||
|
||||
assert S3.get_file("test_image.jpg") == {
|
||||
:ok,
|
||||
|
|
@ -62,28 +75,42 @@ defmodule Pleroma.Uploaders.S3Test do
|
|||
tempfile: Path.absname("test/instance_static/add/shortcode.png")
|
||||
}
|
||||
|
||||
ConfigMock
|
||||
|> expect(:get, fn [Pleroma.Uploaders.S3] ->
|
||||
[
|
||||
bucket: "test_bucket"
|
||||
]
|
||||
end)
|
||||
|
||||
[file_upload: file_upload]
|
||||
end
|
||||
|
||||
test "save file", %{file_upload: file_upload} do
|
||||
with_mock ExAws, request: fn _ -> {:ok, :ok} end do
|
||||
assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}}
|
||||
end
|
||||
ExAwsMock
|
||||
|> expect(:request, fn _req -> {:ok, %{status_code: 200}} end)
|
||||
|
||||
assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}}
|
||||
end
|
||||
|
||||
test "returns error", %{file_upload: file_upload} do
|
||||
with_mock ExAws, request: fn _ -> {:error, "S3 Upload failed"} end do
|
||||
assert capture_log(fn ->
|
||||
assert S3.put_file(file_upload) == {:error, "S3 Upload failed"}
|
||||
end) =~ "Elixir.Pleroma.Uploaders.S3: {:error, \"S3 Upload failed\"}"
|
||||
end
|
||||
ExAwsMock
|
||||
|> expect(:request, fn _req -> {:error, "S3 Upload failed"} end)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert S3.put_file(file_upload) == {:error, "S3 Upload failed"}
|
||||
end) =~ "Elixir.Pleroma.Uploaders.S3: {:error, \"S3 Upload failed\"}"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_file/1" do
|
||||
test_with_mock "deletes file", ExAws, request: fn _req -> {:ok, %{status_code: 204}} end do
|
||||
test "deletes file" do
|
||||
ExAwsMock
|
||||
|> expect(:request, fn _req -> {:ok, %{status_code: 204}} end)
|
||||
|
||||
ConfigMock
|
||||
|> expect(:get, fn [Pleroma.Uploaders.S3, :bucket] -> "test_bucket" end)
|
||||
|
||||
assert :ok = S3.delete_file("image.jpg")
|
||||
assert_called(ExAws.request(:_))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
51
test/pleroma/user/backup_async_test.exs
Normal file
51
test/pleroma/user/backup_async_test.exs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.User.BackupAsyncTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mox
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.User.Backup
|
||||
alias Pleroma.User.Backup.ProcessorMock
|
||||
|
||||
setup do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
|
||||
{:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
%{backup: backup}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it handles unrecoverable exceptions", %{backup: backup} do
|
||||
ProcessorMock
|
||||
|> expect(:do_process, fn _, _ ->
|
||||
raise "mock exception"
|
||||
end)
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Config)
|
||||
|
||||
{:error, %{backup: backup, reason: :exit}} = Backup.process(backup, ProcessorMock)
|
||||
|
||||
assert backup.state == :failed
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it handles timeouts", %{backup: backup} do
|
||||
ProcessorMock
|
||||
|> expect(:do_process, fn _, _ ->
|
||||
Process.sleep(:timer.seconds(4))
|
||||
end)
|
||||
|
||||
ConfigMock
|
||||
|> expect(:get, fn [Pleroma.User.Backup, :process_wait_time] -> :timer.seconds(2) end)
|
||||
|
||||
{:error, %{backup: backup, reason: :timeout}} = Backup.process(backup, ProcessorMock)
|
||||
|
||||
assert backup.state == :failed
|
||||
end
|
||||
end
|
||||
|
|
@ -9,10 +9,14 @@ defmodule Pleroma.User.BackupTest do
|
|||
import Mock
|
||||
import Pleroma.Factory
|
||||
import Swoosh.TestAssertions
|
||||
import Mox
|
||||
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Uploaders.S3.ExAwsMock
|
||||
alias Pleroma.User.Backup
|
||||
alias Pleroma.User.Backup.ProcessorMock
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.BackupWorker
|
||||
|
||||
|
|
@ -20,17 +24,25 @@ defmodule Pleroma.User.BackupTest do
|
|||
clear_config([Pleroma.Upload, :uploader])
|
||||
clear_config([Backup, :limit_days])
|
||||
clear_config([Pleroma.Emails.Mailer, :enabled], true)
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Config)
|
||||
|
||||
ProcessorMock
|
||||
|> stub_with(Pleroma.User.Backup.Processor)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it requries enabled email" do
|
||||
test "it does not requrie enabled email" do
|
||||
clear_config([Pleroma.Emails.Mailer, :enabled], false)
|
||||
user = insert(:user)
|
||||
assert {:error, "Backups require enabled email"} == Backup.create(user)
|
||||
assert {:ok, _} = Backup.create(user)
|
||||
end
|
||||
|
||||
test "it requries user's email" do
|
||||
test "it does not require user's email" do
|
||||
user = insert(:user, %{email: nil})
|
||||
assert {:error, "Email is required"} == Backup.create(user)
|
||||
assert {:ok, _} = Backup.create(user)
|
||||
end
|
||||
|
||||
test "it creates a backup record and an Oban job" do
|
||||
|
|
@ -39,7 +51,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
assert_enqueued(worker: BackupWorker, args: args)
|
||||
|
||||
backup = Backup.get(args["backup_id"])
|
||||
assert %Backup{user_id: ^user_id, processed: false, file_size: 0} = backup
|
||||
assert %Backup{user_id: ^user_id, processed: false, file_size: 0, state: :pending} = backup
|
||||
end
|
||||
|
||||
test "it return an error if the export limit is over" do
|
||||
|
|
@ -59,7 +71,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id, state: :complete} = backup
|
||||
|
||||
delete_job_args = %{"op" => "delete", "backup_id" => backup_id}
|
||||
|
||||
|
|
@ -75,6 +87,66 @@ defmodule Pleroma.User.BackupTest do
|
|||
)
|
||||
end
|
||||
|
||||
test "it updates states of the backup" do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user)
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id, state: :complete} = backup
|
||||
|
||||
delete_job_args = %{"op" => "delete", "backup_id" => backup_id}
|
||||
|
||||
assert_enqueued(worker: BackupWorker, args: delete_job_args)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, delete_job_args)
|
||||
refute Backup.get(backup_id)
|
||||
|
||||
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
|
||||
|
||||
assert_email_sent(
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
test "it does not send an email if the user does not have an email" do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user, %{email: nil})
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
||||
test "it does not send an email if mailer is not on" do
|
||||
clear_config([Pleroma.Emails.Mailer, :enabled], false)
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user)
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
||||
test "it does not send an email if the user has an empty email" do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user, %{email: ""})
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
||||
test "it removes outdated backups after creating a fresh one" do
|
||||
clear_config([Backup, :limit_days], -1)
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
|
|
@ -111,7 +183,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
Bookmark.create(user.id, status3.id)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
assert {:ok, path} = Backup.export(backup)
|
||||
assert {:ok, path} = Backup.export(backup, self())
|
||||
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(path), [:memory])
|
||||
assert {:ok, {'actor.json', json}} = :zip.zip_get('actor.json', zipfile)
|
||||
|
||||
|
|
@ -193,6 +265,55 @@ defmodule Pleroma.User.BackupTest do
|
|||
File.rm!(path)
|
||||
end
|
||||
|
||||
test "it counts the correct number processed" do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
|
||||
Enum.map(1..120, fn i ->
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "status #{i}"})
|
||||
CommonAPI.favorite(user, status.id)
|
||||
Bookmark.create(user.id, status.id)
|
||||
end)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
{:ok, backup} = Backup.process(backup)
|
||||
|
||||
assert backup.processed_number == 1 + 120 + 120 + 120
|
||||
|
||||
Backup.delete(backup)
|
||||
end
|
||||
|
||||
test "it handles errors" do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
|
||||
Enum.map(1..120, fn i ->
|
||||
{:ok, _status} = CommonAPI.post(user, %{status: "status #{i}"})
|
||||
end)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
|
||||
with_mock Pleroma.Web.ActivityPub.Transmogrifier,
|
||||
[:passthrough],
|
||||
prepare_outgoing: fn data ->
|
||||
object =
|
||||
data["object"]
|
||||
|> Pleroma.Object.normalize(fetch: false)
|
||||
|> Map.get(:data)
|
||||
|
||||
data = data |> Map.put("object", object)
|
||||
|
||||
if String.contains?(data["object"]["content"], "119"),
|
||||
do: raise(%Postgrex.Error{}),
|
||||
else: {:ok, data}
|
||||
end do
|
||||
{:ok, backup} = Backup.process(backup)
|
||||
assert backup.processed
|
||||
assert backup.state == :complete
|
||||
assert backup.processed_number == 1 + 119
|
||||
|
||||
Backup.delete(backup)
|
||||
end
|
||||
end
|
||||
|
||||
describe "it uploads and deletes a backup archive" do
|
||||
setup do
|
||||
clear_config([Pleroma.Upload, :base_url], "https://s3.amazonaws.com")
|
||||
|
|
@ -209,7 +330,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
Bookmark.create(user.id, status3.id)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
assert {:ok, path} = Backup.export(backup)
|
||||
assert {:ok, path} = Backup.export(backup, self())
|
||||
|
||||
[path: path, backup: backup]
|
||||
end
|
||||
|
|
@ -218,14 +339,14 @@ defmodule Pleroma.User.BackupTest do
|
|||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3)
|
||||
clear_config([Pleroma.Uploaders.S3, :streaming_enabled], false)
|
||||
|
||||
with_mock ExAws,
|
||||
request: fn
|
||||
%{http_method: :put} -> {:ok, :ok}
|
||||
%{http_method: :delete} -> {:ok, %{status_code: 204}}
|
||||
end do
|
||||
assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path)
|
||||
assert {:ok, _backup} = Backup.delete(backup)
|
||||
end
|
||||
ExAwsMock
|
||||
|> expect(:request, 2, fn
|
||||
%{http_method: :put} -> {:ok, :ok}
|
||||
%{http_method: :delete} -> {:ok, %{status_code: 204}}
|
||||
end)
|
||||
|
||||
assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path)
|
||||
assert {:ok, _backup} = Backup.delete(backup)
|
||||
end
|
||||
|
||||
test "Local", %{path: path, backup: backup} do
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.User.ImportTest do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.User.QueryTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Pleroma.DataCase, async: false
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
|
@ -44,4 +44,63 @@ defmodule Pleroma.User.QueryTest do
|
|||
|> User.Query.build()
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
describe "is_privileged param" do
|
||||
setup do
|
||||
%{
|
||||
user: insert(:user, local: true, is_admin: false, is_moderator: false),
|
||||
moderator_user: insert(:user, local: true, is_admin: false, is_moderator: true),
|
||||
admin_user: insert(:user, local: true, is_admin: true, is_moderator: false),
|
||||
admin_moderator_user: insert(:user, local: true, is_admin: true, is_moderator: true),
|
||||
remote_user: insert(:user, local: false, is_admin: true, is_moderator: true),
|
||||
non_active_user:
|
||||
insert(:user, local: true, is_admin: true, is_moderator: true, is_active: false)
|
||||
}
|
||||
end
|
||||
|
||||
test "doesn't return any users when there are no privileged roles" do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
|
||||
assert [] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
end
|
||||
|
||||
test "returns moderator users if they are privileged", %{
|
||||
moderator_user: moderator_user,
|
||||
admin_moderator_user: admin_moderator_user
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
clear_config([:instance, :moderator_privileges], [:cofe])
|
||||
|
||||
assert [_, _] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
assert moderator_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
assert admin_moderator_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
end
|
||||
|
||||
test "returns admin users if they are privileged", %{
|
||||
admin_user: admin_user,
|
||||
admin_moderator_user: admin_moderator_user
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [:cofe])
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
|
||||
assert [_, _] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
assert admin_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
assert admin_moderator_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
end
|
||||
|
||||
test "returns admin and moderator users if they are both privileged", %{
|
||||
moderator_user: moderator_user,
|
||||
admin_user: admin_user,
|
||||
admin_moderator_user: admin_moderator_user
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [:cofe])
|
||||
clear_config([:instance, :moderator_privileges], [:cofe])
|
||||
|
||||
assert [_, _, _] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
assert admin_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
assert moderator_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
assert admin_moderator_user in (User.Query.build(%{is_privileged: :cofe}) |> Repo.all())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@
|
|||
defmodule Pleroma.UserRelationshipTest do
|
||||
alias Pleroma.UserRelationship
|
||||
|
||||
use Pleroma.DataCase, async: true
|
||||
use Pleroma.DataCase, async: false
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "*_exists?/2" do
|
||||
|
|
@ -79,7 +80,12 @@ defmodule Pleroma.UserRelationshipTest do
|
|||
end
|
||||
|
||||
test "if record already exists, returns it", %{users: [user1, user2]} do
|
||||
user_block = UserRelationship.create_block(user1, user2)
|
||||
user_block =
|
||||
with_mock NaiveDateTime, [:passthrough], utc_now: fn -> ~N[2017-03-17 17:09:58] end do
|
||||
{:ok, %{inserted_at: ~N[2017-03-17 17:09:58]}} =
|
||||
UserRelationship.create_block(user1, user2)
|
||||
end
|
||||
|
||||
assert user_block == UserRelationship.create_block(user1, user2)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.UserSearchTest do
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
use Pleroma.DataCase
|
||||
|
||||
|
|
@ -65,6 +64,14 @@ defmodule Pleroma.UserSearchTest do
|
|||
assert found_user.id == user.id
|
||||
end
|
||||
|
||||
test "excludes deactivated users from results" do
|
||||
user = insert(:user, %{nickname: "john t1000"})
|
||||
insert(:user, %{is_active: false, nickname: "john t800"})
|
||||
|
||||
[found_user] = User.search("john")
|
||||
assert found_user.id == user.id
|
||||
end
|
||||
|
||||
# Note: as in Mastodon, `is_discoverable` doesn't anyhow relate to user searchability
|
||||
test "includes non-discoverable users in results" do
|
||||
insert(:user, %{nickname: "john 3000", is_discoverable: false})
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
defmodule Pleroma.UserTest do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Builders.UserBuilder
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
|
|
@ -13,13 +12,18 @@ defmodule Pleroma.UserTest do
|
|||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
use Pleroma.DataCase
|
||||
use Pleroma.DataCase, async: false
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
import Swoosh.TestAssertions
|
||||
|
||||
setup do
|
||||
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
|
||||
:ok
|
||||
end
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
|
|
@ -311,7 +315,7 @@ defmodule Pleroma.UserTest do
|
|||
describe "unfollow/2" do
|
||||
setup do: clear_config([:instance, :external_user_synchronization])
|
||||
|
||||
test "unfollow with syncronizes external user" do
|
||||
test "unfollow with synchronizes external user" do
|
||||
clear_config([:instance, :external_user_synchronization], true)
|
||||
|
||||
followed =
|
||||
|
|
@ -473,12 +477,7 @@ defmodule Pleroma.UserTest do
|
|||
reject_deletes: []
|
||||
)
|
||||
|
||||
setup do:
|
||||
clear_config(:mrf,
|
||||
policies: [
|
||||
Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
||||
]
|
||||
)
|
||||
setup do: clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
|
||||
|
||||
test "it sends a welcome chat message when Simple policy applied to local instance" do
|
||||
clear_config([:mrf_simple, :media_nsfw], [{"localhost", ""}])
|
||||
|
|
@ -591,6 +590,21 @@ defmodule Pleroma.UserTest do
|
|||
refute_email_sent()
|
||||
end
|
||||
|
||||
test "it works when the registering user does not provide an email" do
|
||||
clear_config([Pleroma.Emails.Mailer, :enabled], false)
|
||||
clear_config([:instance, :account_activation_required], false)
|
||||
clear_config([:instance, :account_approval_required], true)
|
||||
|
||||
cng = User.register_changeset(%User{}, @full_user_data |> Map.put(:email, ""))
|
||||
|
||||
# The user is still created
|
||||
assert {:ok, %User{nickname: "nick"}} = User.register(cng)
|
||||
|
||||
# No emails are sent
|
||||
ObanHelpers.perform_all()
|
||||
refute_email_sent()
|
||||
end
|
||||
|
||||
test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
|
||||
clear_config([:instance, :account_activation_required], true)
|
||||
|
||||
|
|
@ -618,9 +632,10 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
|
||||
test "it restricts certain nicknames" do
|
||||
clear_config([User, :restricted_nicknames], ["about"])
|
||||
[restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
|
||||
|
||||
assert is_bitstring(restricted_name)
|
||||
assert is_binary(restricted_name)
|
||||
|
||||
params =
|
||||
@full_user_data
|
||||
|
|
@ -631,6 +646,23 @@ defmodule Pleroma.UserTest do
|
|||
refute changeset.valid?
|
||||
end
|
||||
|
||||
test "it is case-insensitive when restricting nicknames" do
|
||||
clear_config([User, :restricted_nicknames], ["about"])
|
||||
[restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
|
||||
|
||||
assert is_binary(restricted_name)
|
||||
|
||||
restricted_upcase_name = String.upcase(restricted_name)
|
||||
|
||||
params =
|
||||
@full_user_data
|
||||
|> Map.put(:nickname, restricted_upcase_name)
|
||||
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
||||
refute changeset.valid?
|
||||
end
|
||||
|
||||
test "it blocks blacklisted email domains" do
|
||||
clear_config([User, :email_blacklist], ["trolling.world"])
|
||||
|
||||
|
|
@ -639,6 +671,11 @@ defmodule Pleroma.UserTest do
|
|||
changeset = User.register_changeset(%User{}, params)
|
||||
refute changeset.valid?
|
||||
|
||||
# Block with case-insensitive match
|
||||
params = Map.put(@full_user_data, :email, "troll@TrOlLing.wOrld")
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
refute changeset.valid?
|
||||
|
||||
# Block with subdomain match
|
||||
params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
|
@ -654,14 +691,14 @@ defmodule Pleroma.UserTest do
|
|||
assert changeset.valid?
|
||||
end
|
||||
|
||||
test "it sets the password_hash and ap_id" do
|
||||
test "it sets the password_hash, ap_id, private key and followers collection address" do
|
||||
changeset = User.register_changeset(%User{}, @full_user_data)
|
||||
|
||||
assert changeset.valid?
|
||||
|
||||
assert is_binary(changeset.changes[:password_hash])
|
||||
assert is_binary(changeset.changes[:keys])
|
||||
assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
|
||||
|
||||
assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
|
||||
end
|
||||
|
||||
|
|
@ -827,6 +864,123 @@ defmodule Pleroma.UserTest do
|
|||
freshed_user = refresh_record(user)
|
||||
assert freshed_user == fetched_user
|
||||
end
|
||||
|
||||
test "gets an existing user by nickname starting with http" do
|
||||
user = insert(:user, nickname: "httpssome")
|
||||
{:ok, fetched_user} = User.get_or_fetch("httpssome")
|
||||
|
||||
assert user == fetched_user
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_or_fetch/1 remote users with tld, while BE is runned on subdomain" do
|
||||
setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true)
|
||||
|
||||
test "for mastodon" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
|> String.replace("{{nickname}}", "a"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
end
|
||||
|
||||
test "for pleroma" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetching a user from nickname or trying to build one" do
|
||||
|
|
@ -1123,7 +1277,7 @@ defmodule Pleroma.UserTest do
|
|||
user = insert(:user)
|
||||
muted_user = insert(:user)
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
|
||||
{:ok, _user_relationships} = User.mute(user, muted_user, %{duration: 60})
|
||||
assert User.mutes?(user, muted_user)
|
||||
|
||||
worker = Pleroma.Workers.MuteExpireWorker
|
||||
|
|
@ -1695,7 +1849,6 @@ defmodule Pleroma.UserTest do
|
|||
confirmation_token: "qqqq",
|
||||
domain_blocks: ["lain.com"],
|
||||
is_active: false,
|
||||
ap_enabled: true,
|
||||
is_moderator: true,
|
||||
is_admin: true,
|
||||
mascot: %{"a" => "b"},
|
||||
|
|
@ -1736,7 +1889,6 @@ defmodule Pleroma.UserTest do
|
|||
confirmation_token: nil,
|
||||
domain_blocks: [],
|
||||
is_active: false,
|
||||
ap_enabled: false,
|
||||
is_moderator: false,
|
||||
is_admin: false,
|
||||
mascot: nil,
|
||||
|
|
@ -1799,8 +1951,8 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "get_public_key_for_ap_id fetches a user that's not in the db" do
|
||||
assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
|
||||
test "get_public_key_for_ap_id returns correctly for user that's not in the db" do
|
||||
assert :error = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
|
||||
end
|
||||
|
||||
describe "per-user rich-text filtering" do
|
||||
|
|
@ -1883,31 +2035,82 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "superuser?/1" do
|
||||
describe "privileged?/1" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:cofe, :suya])
|
||||
clear_config([:instance, :moderator_privileges], [:cofe, :suya])
|
||||
end
|
||||
|
||||
test "returns false for unprivileged users" do
|
||||
user = insert(:user, local: true)
|
||||
|
||||
refute User.superuser?(user)
|
||||
refute User.privileged?(user, :cofe)
|
||||
end
|
||||
|
||||
test "returns false for remote users" do
|
||||
user = insert(:user, local: false)
|
||||
remote_admin_user = insert(:user, local: false, is_admin: true)
|
||||
|
||||
refute User.superuser?(user)
|
||||
refute User.superuser?(remote_admin_user)
|
||||
refute User.privileged?(user, :cofe)
|
||||
refute User.privileged?(remote_admin_user, :cofe)
|
||||
end
|
||||
|
||||
test "returns true for local moderators" do
|
||||
test "returns true for local moderators if, and only if, they are privileged" do
|
||||
user = insert(:user, local: true, is_moderator: true)
|
||||
|
||||
assert User.superuser?(user)
|
||||
assert User.privileged?(user, :cofe)
|
||||
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
|
||||
refute User.privileged?(user, :cofe)
|
||||
end
|
||||
|
||||
test "returns true for local admins" do
|
||||
test "returns true for local admins if, and only if, they are privileged" do
|
||||
user = insert(:user, local: true, is_admin: true)
|
||||
|
||||
assert User.superuser?(user)
|
||||
assert User.privileged?(user, :cofe)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
refute User.privileged?(user, :cofe)
|
||||
end
|
||||
end
|
||||
|
||||
describe "privileges/1" do
|
||||
setup do
|
||||
clear_config([:instance, :moderator_privileges], [:cofe, :only_moderator])
|
||||
clear_config([:instance, :admin_privileges], [:cofe, :only_admin])
|
||||
end
|
||||
|
||||
test "returns empty list for users without roles" do
|
||||
user = insert(:user, local: true)
|
||||
|
||||
assert [] == User.privileges(user)
|
||||
end
|
||||
|
||||
test "returns list of privileges for moderators" do
|
||||
moderator = insert(:user, is_moderator: true, local: true)
|
||||
|
||||
assert [:cofe, :only_moderator] == User.privileges(moderator) |> Enum.sort()
|
||||
end
|
||||
|
||||
test "returns list of privileges for admins" do
|
||||
admin = insert(:user, is_admin: true, local: true)
|
||||
|
||||
assert [:cofe, :only_admin] == User.privileges(admin) |> Enum.sort()
|
||||
end
|
||||
|
||||
test "returns list of unique privileges for users who are both moderator and admin" do
|
||||
moderator_admin = insert(:user, is_moderator: true, is_admin: true, local: true)
|
||||
|
||||
assert [:cofe, :only_admin, :only_moderator] ==
|
||||
User.privileges(moderator_admin) |> Enum.sort()
|
||||
end
|
||||
|
||||
test "returns empty list for remote users" do
|
||||
remote_moderator_admin = insert(:user, is_moderator: true, is_admin: true, local: false)
|
||||
|
||||
assert [] == User.privileges(remote_moderator_admin)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1950,13 +2153,77 @@ defmodule Pleroma.UserTest do
|
|||
assert User.visible_for(user, other_user) == :visible
|
||||
end
|
||||
|
||||
test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
|
||||
test "returns true when the account is unconfirmed and being viewed by a privileged account (privilege :users_manage_activation_state, confirmation required)" do
|
||||
clear_config([:instance, :account_activation_required], true)
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
|
||||
|
||||
user = insert(:user, local: true, is_confirmed: false)
|
||||
other_user = insert(:user, local: true, is_admin: true)
|
||||
|
||||
assert User.visible_for(user, other_user) == :visible
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
refute User.visible_for(user, other_user) == :visible
|
||||
end
|
||||
end
|
||||
|
||||
describe "all_users_with_privilege/1" do
|
||||
setup do
|
||||
%{
|
||||
user: insert(:user, local: true, is_admin: false, is_moderator: false),
|
||||
moderator_user: insert(:user, local: true, is_admin: false, is_moderator: true),
|
||||
admin_user: insert(:user, local: true, is_admin: true, is_moderator: false),
|
||||
admin_moderator_user: insert(:user, local: true, is_admin: true, is_moderator: true),
|
||||
remote_user: insert(:user, local: false, is_admin: true, is_moderator: true),
|
||||
non_active_user:
|
||||
insert(:user, local: true, is_admin: true, is_moderator: true, is_active: false)
|
||||
}
|
||||
end
|
||||
|
||||
test "doesn't return any users when there are no privileged roles" do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
|
||||
assert [] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
end
|
||||
|
||||
test "returns moderator users if they are privileged", %{
|
||||
moderator_user: moderator_user,
|
||||
admin_moderator_user: admin_moderator_user
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
clear_config([:instance, :moderator_privileges], [:cofe])
|
||||
|
||||
assert [_, _] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
assert moderator_user in User.all_users_with_privilege(:cofe)
|
||||
assert admin_moderator_user in User.all_users_with_privilege(:cofe)
|
||||
end
|
||||
|
||||
test "returns admin users if they are privileged", %{
|
||||
admin_user: admin_user,
|
||||
admin_moderator_user: admin_moderator_user
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [:cofe])
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
|
||||
assert [_, _] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
assert admin_user in User.all_users_with_privilege(:cofe)
|
||||
assert admin_moderator_user in User.all_users_with_privilege(:cofe)
|
||||
end
|
||||
|
||||
test "returns admin and moderator users if they are both privileged", %{
|
||||
moderator_user: moderator_user,
|
||||
admin_user: admin_user,
|
||||
admin_moderator_user: admin_moderator_user
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [:cofe])
|
||||
clear_config([:instance, :moderator_privileges], [:cofe])
|
||||
|
||||
assert [_, _, _] = User.Query.build(%{is_privileged: :cofe}) |> Repo.all()
|
||||
assert admin_user in User.all_users_with_privilege(:cofe)
|
||||
assert moderator_user in User.all_users_with_privilege(:cofe)
|
||||
assert admin_moderator_user in User.all_users_with_privilege(:cofe)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -2108,21 +2375,6 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "ensure_keys_present" do
|
||||
test "it creates keys for a user and stores them in info" do
|
||||
user = insert(:user)
|
||||
refute is_binary(user.keys)
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
assert is_binary(user.keys)
|
||||
end
|
||||
|
||||
test "it doesn't create keys if there already are some" do
|
||||
user = insert(:user, keys: "xxx")
|
||||
{:ok, user} = User.ensure_keys_present(user)
|
||||
assert user.keys == "xxx"
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_ap_ids_by_nicknames" do
|
||||
test "it returns a list of AP ids for a given set of nicknames" do
|
||||
user = insert(:user)
|
||||
|
|
@ -2211,26 +2463,6 @@ defmodule Pleroma.UserTest do
|
|||
assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
|
||||
assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
|
||||
end
|
||||
|
||||
test "removes report notifs when user isn't superuser any more" do
|
||||
report_activity = insert(:report_activity)
|
||||
user = insert(:user, is_moderator: true, is_admin: true)
|
||||
{:ok, _} = Notification.create_notifications(report_activity)
|
||||
|
||||
assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
|
||||
|
||||
{:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
|
||||
# is still superuser because still admin
|
||||
assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
|
||||
|
||||
{:ok, user} = user |> User.admin_api_update(%{is_moderator: true, is_admin: false})
|
||||
# is still superuser because still moderator
|
||||
assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
|
||||
|
||||
{:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
|
||||
# is not a superuser any more
|
||||
assert [] = Notification.for_user(user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "following/followers synchronization" do
|
||||
|
|
@ -2244,8 +2476,7 @@ defmodule Pleroma.UserTest do
|
|||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
|
|
@ -2257,7 +2488,7 @@ defmodule Pleroma.UserTest do
|
|||
assert other_user.follower_count == 1
|
||||
end
|
||||
|
||||
test "syncronizes the counters with the remote instance for the followed when enabled" do
|
||||
test "synchronizes the counters with the remote instance for the followed when enabled" do
|
||||
clear_config([:instance, :external_user_synchronization], false)
|
||||
|
||||
user = insert(:user)
|
||||
|
|
@ -2266,8 +2497,7 @@ defmodule Pleroma.UserTest do
|
|||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
|
|
@ -2279,7 +2509,7 @@ defmodule Pleroma.UserTest do
|
|||
assert other_user.follower_count == 437
|
||||
end
|
||||
|
||||
test "syncronizes the counters with the remote instance for the follower when enabled" do
|
||||
test "synchronizes the counters with the remote instance for the follower when enabled" do
|
||||
clear_config([:instance, :external_user_synchronization], false)
|
||||
|
||||
user = insert(:user)
|
||||
|
|
@ -2288,8 +2518,7 @@ defmodule Pleroma.UserTest do
|
|||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
|
|
@ -2579,6 +2808,82 @@ defmodule Pleroma.UserTest do
|
|||
object_id
|
||||
end
|
||||
|
||||
describe "add_alias/2" do
|
||||
test "should add alias for another user" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
assert {:ok, user_updated} = user |> User.add_alias(user2)
|
||||
|
||||
assert user_updated.also_known_as |> length() == 1
|
||||
assert user2.ap_id in user_updated.also_known_as
|
||||
end
|
||||
|
||||
test "should add multiple aliases" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
|
||||
assert {:ok, user} = user |> User.add_alias(user2)
|
||||
assert {:ok, user_updated} = user |> User.add_alias(user3)
|
||||
|
||||
assert user_updated.also_known_as |> length() == 2
|
||||
assert user2.ap_id in user_updated.also_known_as
|
||||
assert user3.ap_id in user_updated.also_known_as
|
||||
end
|
||||
|
||||
test "should not add duplicate aliases" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
assert {:ok, user} = user |> User.add_alias(user2)
|
||||
|
||||
assert {:ok, user_updated} = user |> User.add_alias(user2)
|
||||
|
||||
assert user_updated.also_known_as |> length() == 1
|
||||
assert user2.ap_id in user_updated.also_known_as
|
||||
end
|
||||
end
|
||||
|
||||
describe "alias_users/1" do
|
||||
test "should get aliases for a user" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user, also_known_as: [user.ap_id])
|
||||
|
||||
aliases = user2 |> User.alias_users()
|
||||
|
||||
assert aliases |> length() == 1
|
||||
|
||||
alias_user = aliases |> Enum.at(0)
|
||||
|
||||
assert alias_user.ap_id == user.ap_id
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_alias/2" do
|
||||
test "should delete existing alias" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user, also_known_as: [user.ap_id])
|
||||
|
||||
assert {:ok, user_updated} = user2 |> User.delete_alias(user)
|
||||
|
||||
assert user_updated.also_known_as == []
|
||||
end
|
||||
|
||||
test "should report error on non-existing alias" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user, also_known_as: [user.ap_id])
|
||||
|
||||
assert {:error, :no_such_alias} = user3 |> User.delete_alias(user2)
|
||||
|
||||
user3_updated = User.get_cached_by_ap_id(user3.ap_id)
|
||||
|
||||
assert user3_updated.also_known_as |> length() == 1
|
||||
assert user.ap_id in user3_updated.also_known_as
|
||||
end
|
||||
end
|
||||
|
||||
describe "account endorsements" do
|
||||
test "it pins people" do
|
||||
user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
setup do
|
||||
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
|
||||
:ok
|
||||
end
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
|
|
@ -247,6 +252,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert json_response(response, 200) == ObjectView.render("object.json", %{object: object})
|
||||
end
|
||||
|
||||
test "does not return local-only objects for remote users", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
reader = insert(:user, local: false)
|
||||
|
||||
{:ok, post} =
|
||||
CommonAPI.post(user, %{status: "test @#{reader.nickname}", visibility: "local"})
|
||||
|
||||
assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post)
|
||||
|
||||
object = Object.normalize(post, fetch: false)
|
||||
uuid = String.split(object.data["id"], "/") |> List.last()
|
||||
|
||||
assert response =
|
||||
conn
|
||||
|> assign(:user, reader)
|
||||
|> put_req_header("accept", "application/activity+json")
|
||||
|> get("/objects/#{uuid}")
|
||||
|
||||
json_response(response, 404)
|
||||
end
|
||||
|
||||
test "it returns a json representation of the object with accept application/json", %{
|
||||
conn: conn
|
||||
} do
|
||||
|
|
@ -554,7 +580,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
user =
|
||||
insert(:user,
|
||||
ap_id: "https://mastodon.example.org/users/raymoo",
|
||||
ap_enabled: true,
|
||||
local: false,
|
||||
last_refreshed_at: nil
|
||||
)
|
||||
|
|
@ -870,6 +895,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
test "it rejects an invalid incoming activity", %{conn: conn, data: data} do
|
||||
user = insert(:user, is_active: false)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("bcc", [user.ap_id])
|
||||
|> Kernel.put_in(["object", "bcc"], [user.ap_id])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{user.nickname}/inbox", data)
|
||||
|
||||
assert "Invalid request." == json_response(conn, 400)
|
||||
end
|
||||
|
||||
test "it accepts messages with to as string instead of array", %{conn: conn, data: data} do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
@ -1297,6 +1339,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert outbox_endpoint == result["id"]
|
||||
end
|
||||
|
||||
test "it returns a local note activity when authenticated as local user", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
reader = insert(:user)
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{status: "mew mew", visibility: "local"})
|
||||
ap_id = note_activity.data["id"]
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> assign(:user, reader)
|
||||
|> put_req_header("accept", "application/activity+json")
|
||||
|> get("/users/#{user.nickname}/outbox?page=true")
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"orderedItems" => [%{"id" => ^ap_id}]} = resp
|
||||
end
|
||||
|
||||
test "it does not return a local note activity when unauthenticated", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, _note_activity} = CommonAPI.post(user, %{status: "mew mew", visibility: "local"})
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> put_req_header("accept", "application/activity+json")
|
||||
|> get("/users/#{user.nickname}/outbox?page=true")
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"orderedItems" => []} = resp
|
||||
end
|
||||
|
||||
test "it returns a note activity in a collection", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
note_object = Object.normalize(note_activity, fetch: false)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
|
@ -19,11 +20,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
|
|
@ -174,7 +180,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
|
||||
assert user.ap_id == user_id
|
||||
assert user.nickname == "admin@mastodon.example.org"
|
||||
assert user.ap_enabled
|
||||
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
|
||||
end
|
||||
|
||||
|
|
@ -554,7 +559,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert activity.data["ok"] == data["ok"]
|
||||
assert activity.data["id"] == given_id
|
||||
assert activity.data["context"] == "blabla"
|
||||
assert activity.data["context_id"]
|
||||
end
|
||||
|
||||
test "adds a context when none is there" do
|
||||
|
|
@ -576,8 +580,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
assert is_binary(activity.data["context"])
|
||||
assert is_binary(object.data["context"])
|
||||
assert activity.data["context_id"]
|
||||
assert object.data["context_id"]
|
||||
end
|
||||
|
||||
test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
|
||||
|
|
@ -774,6 +776,34 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 2
|
||||
end
|
||||
|
||||
test "increates quotes count", %{user: user} do
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
|
||||
ap_id = activity.data["id"]
|
||||
quote_data = %{status: "1", quote_id: activity.id}
|
||||
|
||||
# public
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(quote_data, :visibility, "public"))
|
||||
assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["quotesCount"] == 1
|
||||
|
||||
# unlisted
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(quote_data, :visibility, "unlisted"))
|
||||
assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["quotesCount"] == 2
|
||||
|
||||
# private
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(quote_data, :visibility, "private"))
|
||||
assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["quotesCount"] == 2
|
||||
|
||||
# direct
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(quote_data, :visibility, "direct"))
|
||||
assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["quotesCount"] == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch activities for recipients" do
|
||||
|
|
@ -1345,6 +1375,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
%{test_file: test_file}
|
||||
end
|
||||
|
||||
test "strips / from filename", %{test_file: file} do
|
||||
file = %Plug.Upload{file | filename: "../../../../../nested/bad.jpg"}
|
||||
{:ok, %Object{} = object} = ActivityPub.upload(file)
|
||||
[%{"href" => href}] = object.data["url"]
|
||||
assert Regex.match?(~r"/bad.jpg$", href)
|
||||
refute Regex.match?(~r"/nested/", href)
|
||||
end
|
||||
|
||||
test "sets a description if given", %{test_file: file} do
|
||||
{:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
|
||||
assert object.data["name"] == "a cool file"
|
||||
|
|
@ -1507,6 +1545,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
reporter_ap_id = reporter.ap_id
|
||||
target_ap_id = target_account.ap_id
|
||||
activity_ap_id = activity.data["id"]
|
||||
object_ap_id = activity.object.data["id"]
|
||||
|
||||
activity_with_object = Activity.get_by_ap_id_with_object(activity_ap_id)
|
||||
|
||||
|
|
@ -1518,6 +1557,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
reported_activity: activity,
|
||||
content: content,
|
||||
activity_ap_id: activity_ap_id,
|
||||
object_ap_id: object_ap_id,
|
||||
activity_with_object: activity_with_object,
|
||||
reporter_ap_id: reporter_ap_id,
|
||||
target_ap_id: target_ap_id
|
||||
|
|
@ -1531,7 +1571,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
target_account: target_account,
|
||||
reported_activity: reported_activity,
|
||||
content: content,
|
||||
activity_ap_id: activity_ap_id,
|
||||
object_ap_id: object_ap_id,
|
||||
activity_with_object: activity_with_object,
|
||||
reporter_ap_id: reporter_ap_id,
|
||||
target_ap_id: target_ap_id
|
||||
|
|
@ -1547,7 +1587,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
note_obj = %{
|
||||
"type" => "Note",
|
||||
"id" => activity_ap_id,
|
||||
"id" => object_ap_id,
|
||||
"content" => content,
|
||||
"published" => activity_with_object.object.data["published"],
|
||||
"actor" =>
|
||||
|
|
@ -1571,6 +1611,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
context: context,
|
||||
target_account: target_account,
|
||||
reported_activity: reported_activity,
|
||||
object_ap_id: object_ap_id,
|
||||
content: content
|
||||
},
|
||||
Utils,
|
||||
|
|
@ -1585,8 +1626,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
content: content
|
||||
})
|
||||
|
||||
new_data =
|
||||
put_in(activity.data, ["object"], [target_account.ap_id, reported_activity.data["id"]])
|
||||
new_data = put_in(activity.data, ["object"], [target_account.ap_id, object_ap_id])
|
||||
|
||||
assert_called(Utils.maybe_federate(%{activity | data: new_data}))
|
||||
end
|
||||
|
|
@ -1612,7 +1652,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
})
|
||||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 1
|
||||
assert Repo.aggregate(Object, :count, :id) == 2
|
||||
assert Repo.aggregate(Object, :count, :id) == 1
|
||||
assert Repo.aggregate(Notification, :count, :id) == 0
|
||||
end
|
||||
end
|
||||
|
|
@ -1665,7 +1705,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
|
||||
describe "fetch_follow_information_for_user" do
|
||||
test "syncronizes following/followers counters" do
|
||||
test "synchronizes following/followers counters" do
|
||||
user =
|
||||
insert(:user,
|
||||
local: false,
|
||||
|
|
@ -1836,9 +1876,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
"target" => ^new_ap_id,
|
||||
"type" => "Move"
|
||||
},
|
||||
local: true
|
||||
local: true,
|
||||
recipients: recipients
|
||||
} = activity
|
||||
|
||||
assert old_user.follower_address in recipients
|
||||
|
||||
params = %{
|
||||
"op" => "move_following",
|
||||
"origin_id" => old_user.id,
|
||||
|
|
@ -1869,6 +1912,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert {:error, "Target account must have the origin in `alsoKnownAs`"} =
|
||||
ActivityPub.move(old_user, new_user)
|
||||
end
|
||||
|
||||
test "do not move remote user following relationships" do
|
||||
%{ap_id: old_ap_id} = old_user = insert(:user)
|
||||
%{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
|
||||
follower_remote = insert(:user, local: false)
|
||||
|
||||
User.follow(follower_remote, old_user)
|
||||
|
||||
assert User.following?(follower_remote, old_user)
|
||||
|
||||
assert {:ok, activity} = ActivityPub.move(old_user, new_user)
|
||||
|
||||
assert %Activity{
|
||||
actor: ^old_ap_id,
|
||||
data: %{
|
||||
"actor" => ^old_ap_id,
|
||||
"object" => ^old_ap_id,
|
||||
"target" => ^new_ap_id,
|
||||
"type" => "Move"
|
||||
},
|
||||
local: true
|
||||
} = activity
|
||||
|
||||
params = %{
|
||||
"op" => "move_following",
|
||||
"origin_id" => old_user.id,
|
||||
"target_id" => new_user.id
|
||||
}
|
||||
|
||||
assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params)
|
||||
|
||||
Pleroma.Workers.BackgroundWorker.perform(%Oban.Job{args: params})
|
||||
|
||||
assert User.following?(follower_remote, old_user)
|
||||
refute User.following?(follower_remote, new_user)
|
||||
end
|
||||
end
|
||||
|
||||
test "doesn't retrieve replies activities with exclude_replies" do
|
||||
|
|
@ -2607,4 +2686,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, user} = ActivityPub.make_user_from_ap_id("https://princess.cat/users/mewmew")
|
||||
assert user.name == " "
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "pin_data_from_featured_collection will ignore unsupported values" do
|
||||
assert %{} ==
|
||||
ActivityPub.pin_data_from_featured_collection(%{
|
||||
"type" => "OrderedCollection",
|
||||
"first" => "https://social.example/users/alice/collections/featured?page=true"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,5 +44,34 @@ defmodule Pleroma.Web.ActivityPub.BuilderTest do
|
|||
|
||||
assert {:ok, ^expected, []} = Builder.note(draft)
|
||||
end
|
||||
|
||||
test "quote post" do
|
||||
user = insert(:user)
|
||||
note = insert(:note)
|
||||
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
context: "2hu",
|
||||
content_html: "<h1>This is :moominmamma: note</h1>",
|
||||
quote_post: note,
|
||||
extra: %{}
|
||||
}
|
||||
|
||||
expected = %{
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [],
|
||||
"content" => "<h1>This is :moominmamma: note</h1>",
|
||||
"context" => "2hu",
|
||||
"sensitive" => false,
|
||||
"type" => "Note",
|
||||
"quoteUrl" => note.data["id"],
|
||||
"cc" => [],
|
||||
"summary" => nil,
|
||||
"tag" => [],
|
||||
"to" => []
|
||||
}
|
||||
|
||||
assert {:ok, ^expected, []} = Builder.note(draft)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
|
|||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy
|
||||
|
||||
@linkless_message %{
|
||||
|
|
@ -49,11 +50,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
|
|||
|
||||
assert user.note_count == 0
|
||||
|
||||
message =
|
||||
@linkful_message
|
||||
|> Map.put("actor", user.ap_id)
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"actor" => user.ap_id,
|
||||
"object" => %{
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"content" => "<a href='https://example.com'>hi world!</a>"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content" => "mew"
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, _} = AntiLinkSpamPolicy.filter(message)
|
||||
{:reject, _} = MRF.filter_one(AntiLinkSpamPolicy, message)
|
||||
end
|
||||
|
||||
test "it allows posts with links for local users" do
|
||||
|
|
@ -67,6 +80,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
|
|||
|
||||
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it disallows posts with links in history" 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
|
||||
end
|
||||
|
||||
describe "with old user" do
|
||||
|
|
|
|||
425
test/pleroma/web/activity_pub/mrf/emoji_policy_test.exs
Normal file
425
test/pleroma/web/activity_pub/mrf/emoji_policy_test.exs
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.EmojiPolicy
|
||||
|
||||
setup do: clear_config(:mrf_emoji)
|
||||
|
||||
setup do
|
||||
clear_config([:mrf_emoji], %{
|
||||
remove_url: [],
|
||||
remove_shortcode: [],
|
||||
federated_timeline_removal_url: [],
|
||||
federated_timeline_removal_shortcode: []
|
||||
})
|
||||
end
|
||||
|
||||
@emoji_tags [
|
||||
%{
|
||||
"icon" => %{
|
||||
"type" => "Image",
|
||||
"url" => "https://example.org/emoji/biribiri/mikoto_smile2.png"
|
||||
},
|
||||
"id" => "https://example.org/emoji/biribiri/mikoto_smile2.png",
|
||||
"name" => ":mikoto_smile2:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
},
|
||||
%{
|
||||
"icon" => %{
|
||||
"type" => "Image",
|
||||
"url" => "https://example.org/emoji/biribiri/mikoto_smile3.png"
|
||||
},
|
||||
"id" => "https://example.org/emoji/biribiri/mikoto_smile3.png",
|
||||
"name" => ":mikoto_smile3:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
},
|
||||
%{
|
||||
"icon" => %{
|
||||
"type" => "Image",
|
||||
"url" => "https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
},
|
||||
"id" => "https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png",
|
||||
"name" => ":nekomimi_girl_emoji_007:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
},
|
||||
%{
|
||||
"icon" => %{
|
||||
"type" => "Image",
|
||||
"url" => "https://example.org/test.png"
|
||||
},
|
||||
"id" => "https://example.org/test.png",
|
||||
"name" => ":test:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
|
||||
@misc_tags [%{"type" => "Placeholder"}]
|
||||
|
||||
@user_data %{
|
||||
"type" => "Person",
|
||||
"id" => "https://example.org/placeholder",
|
||||
"name" => "lol",
|
||||
"tag" => @emoji_tags ++ @misc_tags
|
||||
}
|
||||
|
||||
@status_data %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"id" => "https://example.org/placeholder",
|
||||
"content" => "lol",
|
||||
"tag" => @emoji_tags ++ @misc_tags,
|
||||
"emoji" => %{
|
||||
"mikoto_smile2" => "https://example.org/emoji/biribiri/mikoto_smile2.png",
|
||||
"mikoto_smile3" => "https://example.org/emoji/biribiri/mikoto_smile3.png",
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png",
|
||||
"test" => "https://example.org/test.png"
|
||||
},
|
||||
"to" => ["https://example.org/self", Pleroma.Constants.as_public()],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
},
|
||||
"to" => ["https://example.org/self", Pleroma.Constants.as_public()],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
}
|
||||
|
||||
@status_data_with_history %{
|
||||
"type" => "Create",
|
||||
"object" =>
|
||||
@status_data["object"]
|
||||
|> Map.merge(%{
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [@status_data["object"] |> Map.put("content", "older")],
|
||||
"totalItems" => 1
|
||||
}
|
||||
}),
|
||||
"to" => ["https://example.org/self", Pleroma.Constants.as_public()],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
}
|
||||
|
||||
@emoji_react_data %{
|
||||
"type" => "EmojiReact",
|
||||
"tag" => [@emoji_tags |> Enum.at(3)],
|
||||
"object" => "https://example.org/someobject",
|
||||
"to" => ["https://example.org/self"],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
}
|
||||
|
||||
@emoji_react_data_matching_regex %{
|
||||
"type" => "EmojiReact",
|
||||
"tag" => [@emoji_tags |> Enum.at(1)],
|
||||
"object" => "https://example.org/someobject",
|
||||
"to" => ["https://example.org/self"],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
}
|
||||
|
||||
@emoji_react_data_matching_nothing %{
|
||||
"type" => "EmojiReact",
|
||||
"tag" => [@emoji_tags |> Enum.at(2)],
|
||||
"object" => "https://example.org/someobject",
|
||||
"to" => ["https://example.org/self"],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
}
|
||||
|
||||
@emoji_react_data_unicode %{
|
||||
"type" => "EmojiReact",
|
||||
"content" => "😍",
|
||||
"object" => "https://example.org/someobject",
|
||||
"to" => ["https://example.org/self"],
|
||||
"cc" => ["https://example.org/someone"]
|
||||
}
|
||||
|
||||
describe "remove_url" do
|
||||
setup do
|
||||
clear_config([:mrf_emoji, :remove_url], [
|
||||
"https://example.org/test.png",
|
||||
~r{/biribiri/mikoto_smile[23]\.png},
|
||||
"nekomimi_girl_emoji"
|
||||
])
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "processes user" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @user_data)
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
assert %{"tag" => ^expected_tags} = filtered
|
||||
end
|
||||
|
||||
test "processes status" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @status_data)
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
expected_emoji = %{
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
}
|
||||
|
||||
assert %{"object" => %{"tag" => ^expected_tags, "emoji" => ^expected_emoji}} = filtered
|
||||
end
|
||||
|
||||
test "processes status with history" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @status_data_with_history)
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
expected_emoji = %{
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
}
|
||||
|
||||
assert %{
|
||||
"object" => %{
|
||||
"tag" => ^expected_tags,
|
||||
"emoji" => ^expected_emoji,
|
||||
"formerRepresentations" => %{"orderedItems" => [item]}
|
||||
}
|
||||
} = filtered
|
||||
|
||||
assert %{"tag" => ^expected_tags, "emoji" => ^expected_emoji} = item
|
||||
end
|
||||
|
||||
test "processes updates" do
|
||||
{:ok, filtered} =
|
||||
MRF.filter_one(EmojiPolicy, @status_data_with_history |> Map.put("type", "Update"))
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
expected_emoji = %{
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
}
|
||||
|
||||
assert %{
|
||||
"object" => %{
|
||||
"tag" => ^expected_tags,
|
||||
"emoji" => ^expected_emoji,
|
||||
"formerRepresentations" => %{"orderedItems" => [item]}
|
||||
}
|
||||
} = filtered
|
||||
|
||||
assert %{"tag" => ^expected_tags, "emoji" => ^expected_emoji} = item
|
||||
end
|
||||
|
||||
test "processes EmojiReact" do
|
||||
assert {:reject, "[EmojiPolicy] Rejected for having disallowed emoji"} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data)
|
||||
|
||||
assert {:reject, "[EmojiPolicy] Rejected for having disallowed emoji"} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data_matching_regex)
|
||||
|
||||
assert {:ok, @emoji_react_data_matching_nothing} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data_matching_nothing)
|
||||
|
||||
assert {:ok, @emoji_react_data_unicode} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data_unicode)
|
||||
end
|
||||
end
|
||||
|
||||
describe "remove_shortcode" do
|
||||
setup do
|
||||
clear_config([:mrf_emoji, :remove_shortcode], [
|
||||
"test",
|
||||
~r{mikoto_s},
|
||||
"nekomimi_girl_emoji"
|
||||
])
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "processes user" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @user_data)
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
assert %{"tag" => ^expected_tags} = filtered
|
||||
end
|
||||
|
||||
test "processes status" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @status_data)
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
expected_emoji = %{
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
}
|
||||
|
||||
assert %{"object" => %{"tag" => ^expected_tags, "emoji" => ^expected_emoji}} = filtered
|
||||
end
|
||||
|
||||
test "processes status with history" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @status_data_with_history)
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
expected_emoji = %{
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
}
|
||||
|
||||
assert %{
|
||||
"object" => %{
|
||||
"tag" => ^expected_tags,
|
||||
"emoji" => ^expected_emoji,
|
||||
"formerRepresentations" => %{"orderedItems" => [item]}
|
||||
}
|
||||
} = filtered
|
||||
|
||||
assert %{"tag" => ^expected_tags, "emoji" => ^expected_emoji} = item
|
||||
end
|
||||
|
||||
test "processes updates" do
|
||||
{:ok, filtered} =
|
||||
MRF.filter_one(EmojiPolicy, @status_data_with_history |> Map.put("type", "Update"))
|
||||
|
||||
expected_tags = [@emoji_tags |> Enum.at(2)] ++ @misc_tags
|
||||
|
||||
expected_emoji = %{
|
||||
"nekomimi_girl_emoji_007" =>
|
||||
"https://example.org/emoji/nekomimi_girl_emoji/nekomimi_girl_emoji_007.png"
|
||||
}
|
||||
|
||||
assert %{
|
||||
"object" => %{
|
||||
"tag" => ^expected_tags,
|
||||
"emoji" => ^expected_emoji,
|
||||
"formerRepresentations" => %{"orderedItems" => [item]}
|
||||
}
|
||||
} = filtered
|
||||
|
||||
assert %{"tag" => ^expected_tags, "emoji" => ^expected_emoji} = item
|
||||
end
|
||||
|
||||
test "processes EmojiReact" do
|
||||
assert {:reject, "[EmojiPolicy] Rejected for having disallowed emoji"} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data)
|
||||
|
||||
assert {:reject, "[EmojiPolicy] Rejected for having disallowed emoji"} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data_matching_regex)
|
||||
|
||||
assert {:ok, @emoji_react_data_matching_nothing} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data_matching_nothing)
|
||||
|
||||
assert {:ok, @emoji_react_data_unicode} ==
|
||||
MRF.filter_one(EmojiPolicy, @emoji_react_data_unicode)
|
||||
end
|
||||
end
|
||||
|
||||
describe "federated_timeline_removal_url" do
|
||||
setup do
|
||||
clear_config([:mrf_emoji, :federated_timeline_removal_url], [
|
||||
"https://example.org/test.png",
|
||||
~r{/biribiri/mikoto_smile[23]\.png},
|
||||
"nekomimi_girl_emoji"
|
||||
])
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "processes status" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @status_data)
|
||||
|
||||
expected_tags = @status_data["object"]["tag"]
|
||||
expected_emoji = @status_data["object"]["emoji"]
|
||||
|
||||
expected_to = ["https://example.org/self"]
|
||||
expected_cc = [Pleroma.Constants.as_public(), "https://example.org/someone"]
|
||||
|
||||
assert %{
|
||||
"to" => ^expected_to,
|
||||
"cc" => ^expected_cc,
|
||||
"object" => %{"tag" => ^expected_tags, "emoji" => ^expected_emoji}
|
||||
} = filtered
|
||||
end
|
||||
|
||||
test "ignore updates" do
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, @status_data |> Map.put("type", "Update"))
|
||||
|
||||
expected_tags = @status_data["object"]["tag"]
|
||||
expected_emoji = @status_data["object"]["emoji"]
|
||||
|
||||
expected_to = ["https://example.org/self", Pleroma.Constants.as_public()]
|
||||
expected_cc = ["https://example.org/someone"]
|
||||
|
||||
assert %{
|
||||
"to" => ^expected_to,
|
||||
"cc" => ^expected_cc,
|
||||
"object" => %{"tag" => ^expected_tags, "emoji" => ^expected_emoji}
|
||||
} = filtered
|
||||
end
|
||||
|
||||
test "processes status with history" do
|
||||
status =
|
||||
@status_data_with_history
|
||||
|> put_in(["object", "tag"], @misc_tags)
|
||||
|> put_in(["object", "emoji"], %{})
|
||||
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, status)
|
||||
|
||||
expected_tags = @status_data["object"]["tag"]
|
||||
expected_emoji = @status_data["object"]["emoji"]
|
||||
|
||||
expected_to = ["https://example.org/self"]
|
||||
expected_cc = [Pleroma.Constants.as_public(), "https://example.org/someone"]
|
||||
|
||||
assert %{
|
||||
"to" => ^expected_to,
|
||||
"cc" => ^expected_cc,
|
||||
"object" => %{
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [%{"tag" => ^expected_tags, "emoji" => ^expected_emoji}]
|
||||
}
|
||||
}
|
||||
} = filtered
|
||||
end
|
||||
end
|
||||
|
||||
describe "edge cases" do
|
||||
setup do
|
||||
clear_config([:mrf_emoji, :remove_url], [
|
||||
"https://example.org/test.png",
|
||||
~r{/biribiri/mikoto_smile[23]\.png},
|
||||
"nekomimi_girl_emoji"
|
||||
])
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "non-statuses" do
|
||||
answer = @status_data |> put_in(["object", "type"], "Answer")
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, answer)
|
||||
|
||||
assert filtered == answer
|
||||
end
|
||||
|
||||
test "without tag" do
|
||||
status = @status_data |> Map.put("object", Map.drop(@status_data["object"], ["tag"]))
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, status)
|
||||
|
||||
refute Map.has_key?(filtered["object"], "tag")
|
||||
end
|
||||
|
||||
test "without emoji" do
|
||||
status = @status_data |> Map.put("object", Map.drop(@status_data["object"], ["emoji"]))
|
||||
{:ok, filtered} = MRF.filter_one(EmojiPolicy, status)
|
||||
|
||||
refute Map.has_key?(filtered["object"], "emoji")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
|
|||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
|
||||
|
||||
describe "rewrites summary" do
|
||||
|
|
@ -35,10 +36,58 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
|
|||
assert {:ok, res} = EnsureRePrepended.filter(message)
|
||||
assert res["object"]["summary"] == "re: object-summary"
|
||||
end
|
||||
|
||||
test "it adds `re:` to history" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}},
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = MRF.filter_one(EnsureRePrepended, message)
|
||||
assert res["object"]["summary"] == "re: object-summary"
|
||||
|
||||
assert Enum.at(res["object"]["formerRepresentations"]["orderedItems"], 0)["summary"] ==
|
||||
"re: object-summary"
|
||||
end
|
||||
|
||||
test "it accepts Updates" do
|
||||
message = %{
|
||||
"type" => "Update",
|
||||
"object" => %{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}},
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"summary" => "object-summary",
|
||||
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = MRF.filter_one(EnsureRePrepended, message)
|
||||
assert res["object"]["summary"] == "re: object-summary"
|
||||
|
||||
assert Enum.at(res["object"]["formerRepresentations"]["orderedItems"], 0)["summary"] ==
|
||||
"re: object-summary"
|
||||
end
|
||||
end
|
||||
|
||||
describe "skip filter" do
|
||||
test "it skip if type isn't 'Create'" do
|
||||
test "it skip if type isn't 'Create' or 'Update'" do
|
||||
message = %{
|
||||
"type" => "Annotation",
|
||||
"object" => %{"summary" => "object-summary"}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicyTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.MRF.FollowBotPolicy
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContentTest do
|
|||
|
||||
alias Pleroma.Constants
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
|
|
@ -161,4 +162,149 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContentTest do
|
|||
assert filtered ==
|
||||
"<p><span class=\"recipients-inline\"><span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{luigi.id}\" href=\"#{luigi.ap_id}\" rel=\"ugc\">@<span>luigi</span></a></span> </span>I'ma tired...</p>"
|
||||
end
|
||||
|
||||
test "aware of history" do
|
||||
mario = insert(:user, nickname: "mario")
|
||||
wario = insert(:user, nickname: "wario")
|
||||
|
||||
{:ok, post1} = CommonAPI.post(mario, %{status: "Letsa go!"})
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => wario.ap_id,
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => wario.ap_id,
|
||||
"content" => "WHA-HA!",
|
||||
"to" => [
|
||||
mario.ap_id,
|
||||
Constants.as_public()
|
||||
],
|
||||
"inReplyTo" => post1.object.data["id"],
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Note",
|
||||
"actor" => wario.ap_id,
|
||||
"content" => "WHA-HA!",
|
||||
"to" => [
|
||||
mario.ap_id,
|
||||
Constants.as_public()
|
||||
],
|
||||
"inReplyTo" => post1.object.data["id"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expected =
|
||||
"<span class=\"recipients-inline\"><span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{mario.id}\" href=\"#{mario.ap_id}\" rel=\"ugc\">@<span>mario</span></a></span> </span>WHA-HA!"
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"object" => %{
|
||||
"content" => ^expected,
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => ^expected}]}
|
||||
}
|
||||
}} = MRF.filter_one(ForceMentionsInContent, activity)
|
||||
end
|
||||
|
||||
test "works with Updates" do
|
||||
mario = insert(:user, nickname: "mario")
|
||||
wario = insert(:user, nickname: "wario")
|
||||
|
||||
{:ok, post1} = CommonAPI.post(mario, %{status: "Letsa go!"})
|
||||
|
||||
activity = %{
|
||||
"type" => "Update",
|
||||
"actor" => wario.ap_id,
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => wario.ap_id,
|
||||
"content" => "WHA-HA!",
|
||||
"to" => [
|
||||
mario.ap_id,
|
||||
Constants.as_public()
|
||||
],
|
||||
"inReplyTo" => post1.object.data["id"],
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Note",
|
||||
"actor" => wario.ap_id,
|
||||
"content" => "WHA-HA!",
|
||||
"to" => [
|
||||
mario.ap_id,
|
||||
Constants.as_public()
|
||||
],
|
||||
"inReplyTo" => post1.object.data["id"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expected =
|
||||
"<span class=\"recipients-inline\"><span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{mario.id}\" href=\"#{mario.ap_id}\" rel=\"ugc\">@<span>mario</span></a></span> </span>WHA-HA!"
|
||||
|
||||
assert {:ok,
|
||||
%{
|
||||
"object" => %{
|
||||
"content" => ^expected,
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => ^expected}]}
|
||||
}
|
||||
}} = MRF.filter_one(ForceMentionsInContent, activity)
|
||||
end
|
||||
|
||||
test "don't add duplicate mentions for mastodon or misskey posts" do
|
||||
[zero, rogerick, greg] = [
|
||||
insert(:user,
|
||||
ap_id: "https://pleroma.example.com/users/zero",
|
||||
uri: "https://pleroma.example.com/users/zero",
|
||||
nickname: "zero@pleroma.example.com",
|
||||
local: false
|
||||
),
|
||||
insert(:user,
|
||||
ap_id: "https://misskey.example.com/users/104ab42f11",
|
||||
uri: "https://misskey.example.com/@rogerick",
|
||||
nickname: "rogerick@misskey.example.com",
|
||||
local: false
|
||||
),
|
||||
insert(:user,
|
||||
ap_id: "https://mastodon.example.com/users/greg",
|
||||
uri: "https://mastodon.example.com/@greg",
|
||||
nickname: "greg@mastodon.example.com",
|
||||
local: false
|
||||
)
|
||||
]
|
||||
|
||||
{:ok, post} = CommonAPI.post(rogerick, %{status: "eugh"})
|
||||
|
||||
inline_mentions = [
|
||||
"<span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{rogerick.id}\" href=\"#{rogerick.ap_id}\" rel=\"ugc\">@<span>rogerick</span></a></span>",
|
||||
"<span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{greg.id}\" href=\"#{greg.uri}\" rel=\"ugc\">@<span>greg</span></a></span>"
|
||||
]
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => zero.ap_id,
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => zero.ap_id,
|
||||
"content" => "#{Enum.at(inline_mentions, 0)} #{Enum.at(inline_mentions, 1)} erm",
|
||||
"to" => [
|
||||
rogerick.ap_id,
|
||||
greg.ap_id,
|
||||
Constants.as_public()
|
||||
],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => filtered}}} = ForceMentionsInContent.filter(activity)
|
||||
|
||||
assert filtered ==
|
||||
"#{Enum.at(inline_mentions, 0)} #{Enum.at(inline_mentions, 1)} erm"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,6 +20,76 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicyTest do
|
|||
assert modified["object"]["sensitive"]
|
||||
end
|
||||
|
||||
test "it is history-aware" do
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "hey",
|
||||
"tag" => []
|
||||
}
|
||||
}
|
||||
|
||||
activity_data =
|
||||
activity
|
||||
|> put_in(
|
||||
["object", "formerRepresentations"],
|
||||
%{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
Map.put(
|
||||
activity["object"],
|
||||
"tag",
|
||||
[%{"type" => "Hashtag", "name" => "#nsfw"}]
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
{:ok, modified} =
|
||||
Pleroma.Web.ActivityPub.MRF.filter_one(
|
||||
Pleroma.Web.ActivityPub.MRF.HashtagPolicy,
|
||||
activity_data
|
||||
)
|
||||
|
||||
refute modified["object"]["sensitive"]
|
||||
assert Enum.at(modified["object"]["formerRepresentations"]["orderedItems"], 0)["sensitive"]
|
||||
end
|
||||
|
||||
test "it works with Update" do
|
||||
activity = %{
|
||||
"type" => "Update",
|
||||
"object" => %{
|
||||
"content" => "hey",
|
||||
"tag" => []
|
||||
}
|
||||
}
|
||||
|
||||
activity_data =
|
||||
activity
|
||||
|> put_in(
|
||||
["object", "formerRepresentations"],
|
||||
%{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
Map.put(
|
||||
activity["object"],
|
||||
"tag",
|
||||
[%{"type" => "Hashtag", "name" => "#nsfw"}]
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
{:ok, modified} =
|
||||
Pleroma.Web.ActivityPub.MRF.filter_one(
|
||||
Pleroma.Web.ActivityPub.MRF.HashtagPolicy,
|
||||
activity_data
|
||||
)
|
||||
|
||||
refute modified["object"]["sensitive"]
|
||||
assert Enum.at(modified["object"]["formerRepresentations"]["orderedItems"], 0)["sensitive"]
|
||||
end
|
||||
|
||||
test "it doesn't sets the sensitive property with irrelevant hashtags" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
|||
112
test/pleroma/web/activity_pub/mrf/inline_quote_policy_test.exs
Normal file
112
test/pleroma/web/activity_pub/mrf/inline_quote_policy_test.exs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicyTest do
|
||||
alias Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy
|
||||
use Pleroma.DataCase
|
||||
|
||||
test "adds quote URL to post content" do
|
||||
quote_url = "https://gleasonator.com/objects/1234"
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://gleasonator.com/users/alex",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "Nice post",
|
||||
"quoteUrl" => quote_url
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity)
|
||||
|
||||
assert filtered ==
|
||||
"Nice post<span class=\"quote-inline\"><br/><br/><bdi>RT:</bdi> <a href=\"https://gleasonator.com/objects/1234\">https://gleasonator.com/objects/1234</a></span>"
|
||||
end
|
||||
|
||||
test "adds quote URL to post content, custom template" do
|
||||
clear_config([:mrf_inline_quote, :template], "{url}'s quoting")
|
||||
quote_url = "https://gleasonator.com/objects/1234"
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://gleasonator.com/users/alex",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "Nice post",
|
||||
"quoteUrl" => quote_url
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity)
|
||||
|
||||
assert filtered ==
|
||||
"Nice post<span class=\"quote-inline\"><br/><br/><a href=\"https://gleasonator.com/objects/1234\">https://gleasonator.com/objects/1234</a>'s quoting</span>"
|
||||
end
|
||||
|
||||
test "doesn't add line breaks to markdown posts" do
|
||||
quote_url = "https://gleasonator.com/objects/1234"
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://gleasonator.com/users/alex",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "<p>Nice post</p>",
|
||||
"quoteUrl" => quote_url
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => filtered}}} = InlineQuotePolicy.filter(activity)
|
||||
|
||||
assert filtered ==
|
||||
"<p>Nice post<span class=\"quote-inline\"><br/><br/><bdi>RT:</bdi> <a href=\"https://gleasonator.com/objects/1234\">https://gleasonator.com/objects/1234</a></span></p>"
|
||||
end
|
||||
|
||||
test "ignores Misskey quote posts" do
|
||||
object = File.read!("test/fixtures/quote_post/misskey_quote_post.json") |> Jason.decode!()
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://misskey.io/users/7rkrarq81i",
|
||||
"object" => object
|
||||
}
|
||||
|
||||
{:ok, filtered} = InlineQuotePolicy.filter(activity)
|
||||
assert filtered == activity
|
||||
end
|
||||
|
||||
test "ignores Fedibird quote posts" do
|
||||
object = File.read!("test/fixtures/quote_post/fedibird_quote_post.json") |> Jason.decode!()
|
||||
|
||||
# Normally the ObjectValidator will fix this before it reaches MRF
|
||||
object = Map.put(object, "quoteUrl", object["quoteURL"])
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://fedibird.com/users/noellabo",
|
||||
"object" => object
|
||||
}
|
||||
|
||||
{:ok, filtered} = InlineQuotePolicy.filter(activity)
|
||||
assert filtered == activity
|
||||
end
|
||||
|
||||
test "skips objects which already have an .inline-quote span" do
|
||||
object =
|
||||
File.read!("test/fixtures/quote_post/fedibird_quote_mismatched.json") |> Jason.decode!()
|
||||
|
||||
# Normally the ObjectValidator will fix this before it reaches MRF
|
||||
object = Map.put(object, "quoteUrl", object["quoteUri"])
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://fedibird.com/users/noellabo",
|
||||
"object" => object
|
||||
}
|
||||
|
||||
{:ok, filtered} = InlineQuotePolicy.filter(activity)
|
||||
assert filtered == activity
|
||||
end
|
||||
end
|
||||
|
|
@ -79,6 +79,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
KeywordPolicy.filter(message)
|
||||
end)
|
||||
end
|
||||
|
||||
test "rejects if string matches in history" do
|
||||
clear_config([:mrf_keyword, :reject], ["pun"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that compLAINer is a good",
|
||||
"summary" => "",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"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 Updates" do
|
||||
clear_config([:mrf_keyword, :reject], ["pun"])
|
||||
|
||||
message = %{
|
||||
"type" => "Update",
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that compLAINer is a good",
|
||||
"summary" => "",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"content" => "just a daily reminder that compLAINer is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} =
|
||||
KeywordPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
|
||||
describe "delisting from ftl based on keywords" do
|
||||
|
|
@ -157,6 +205,31 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
|
||||
end)
|
||||
end
|
||||
|
||||
test "delists if string matches in history" do
|
||||
clear_config([: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",
|
||||
"summary" => "",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"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
|
||||
end
|
||||
|
||||
describe "replacing keywords" do
|
||||
|
|
@ -221,5 +294,63 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
result == "ZFS is free software"
|
||||
end)
|
||||
end
|
||||
|
||||
test "replaces keyword if string matches in history" do
|
||||
clear_config([:mrf_keyword, :replace], [{"opensource", "free software"}])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{
|
||||
"content" => "ZFS is opensource",
|
||||
"summary" => "",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{"content" => "ZFS is opensource mew mew", "summary" => ""}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
"object" => %{
|
||||
"content" => "ZFS is free software",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [%{"content" => "ZFS is free software mew mew"}]
|
||||
}
|
||||
}
|
||||
}} = KeywordPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "replaces keyword in Updates" do
|
||||
clear_config([:mrf_keyword, :replace], [{"opensource", "free software"}])
|
||||
|
||||
message = %{
|
||||
"type" => "Update",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{
|
||||
"content" => "ZFS is opensource",
|
||||
"summary" => "",
|
||||
"formerRepresentations" => %{
|
||||
"type" => "OrderedCollection",
|
||||
"orderedItems" => [
|
||||
%{"content" => "ZFS is opensource mew mew", "summary" => ""}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
"object" => %{
|
||||
"content" => "ZFS is free software",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [%{"content" => "ZFS is free software mew mew"}]
|
||||
}
|
||||
}
|
||||
}} = KeywordPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
|
|||
use Pleroma.Tests.Helpers
|
||||
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
@message %{
|
||||
"type" => "Create",
|
||||
|
|
@ -22,6 +25,32 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
|
|||
}
|
||||
}
|
||||
|
||||
@message_with_history %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "content",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Note",
|
||||
"content" => "content",
|
||||
"attachment" => [
|
||||
%{"url" => [%{"href" => "http://example.com/image.jpg"}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setup do
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
setup do: clear_config([:media_proxy, :enabled], true)
|
||||
|
||||
test "it prefetches media proxy URIs" do
|
||||
|
|
@ -50,4 +79,28 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
|
|||
refute called(HTTP.get(:_, :_, :_))
|
||||
end
|
||||
end
|
||||
|
||||
test "history-aware" do
|
||||
Tesla.Mock.mock(fn %{method: :get, url: "http://example.com/image.jpg"} ->
|
||||
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||
end)
|
||||
|
||||
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
|
||||
MRF.filter_one(MediaProxyWarmingPolicy, @message_with_history)
|
||||
|
||||
assert called(HTTP.get(:_, :_, :_))
|
||||
end
|
||||
end
|
||||
|
||||
test "works with Updates" do
|
||||
Tesla.Mock.mock(fn %{method: :get, url: "http://example.com/image.jpg"} ->
|
||||
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||
end)
|
||||
|
||||
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
|
||||
MRF.filter_one(MediaProxyWarmingPolicy, @message_with_history |> Map.put("type", "Update"))
|
||||
|
||||
assert called(HTTP.get(:_, :_, :_))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -151,4 +151,27 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicyTest do
|
|||
|
||||
assert NoEmptyPolicy.filter(message) == {:reject, "[NoEmptyPolicy]"}
|
||||
end
|
||||
|
||||
test "works with Update" do
|
||||
message = %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"object" => %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"attachment" => [],
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"source" => "",
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type" => "Note"
|
||||
},
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type" => "Update"
|
||||
}
|
||||
|
||||
assert NoEmptyPolicy.filter(message) == {:reject, "[NoEmptyPolicy]"}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
|
||||
|
||||
test "it clears content object" do
|
||||
|
|
@ -20,6 +21,46 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
|
|||
assert res["object"]["content"] == ""
|
||||
end
|
||||
|
||||
test "history-aware" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => ".",
|
||||
"attachment" => "image",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [%{"content" => ".", "attachment" => "image"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = MRF.filter_one(NoPlaceholderTextPolicy, message)
|
||||
|
||||
assert %{
|
||||
"content" => "",
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => ""}]}
|
||||
} = res["object"]
|
||||
end
|
||||
|
||||
test "works with Updates" do
|
||||
message = %{
|
||||
"type" => "Update",
|
||||
"object" => %{
|
||||
"content" => ".",
|
||||
"attachment" => "image",
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [%{"content" => ".", "attachment" => "image"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = MRF.filter_one(NoPlaceholderTextPolicy, message)
|
||||
|
||||
assert %{
|
||||
"content" => "",
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => ""}]}
|
||||
} = res["object"]
|
||||
end
|
||||
|
||||
@messages [
|
||||
%{
|
||||
"type" => "Create",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
|
||||
|
||||
@html_sample """
|
||||
|
|
@ -16,24 +17,58 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
|
|||
<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')
|
||||
"""
|
||||
@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')
|
||||
"""
|
||||
|
||||
test "it filter html tags" do
|
||||
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
|
||||
|
||||
assert {:ok, res} = NormalizeMarkup.filter(message)
|
||||
assert res["object"]["content"] == expected
|
||||
assert res["object"]["content"] == @expected
|
||||
end
|
||||
|
||||
test "it skips filter if type isn't `Create`" do
|
||||
test "history-aware" do
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => @html_sample,
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => @html_sample}]}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = MRF.filter_one(NormalizeMarkup, message)
|
||||
|
||||
assert %{
|
||||
"content" => @expected,
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => @expected}]}
|
||||
} = res["object"]
|
||||
end
|
||||
|
||||
test "works with Updates" do
|
||||
message = %{
|
||||
"type" => "Update",
|
||||
"object" => %{
|
||||
"content" => @html_sample,
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => @html_sample}]}
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, res} = MRF.filter_one(NormalizeMarkup, message)
|
||||
|
||||
assert %{
|
||||
"content" => @expected,
|
||||
"formerRepresentations" => %{"orderedItems" => [%{"content" => @expected}]}
|
||||
} = res["object"]
|
||||
end
|
||||
|
||||
test "it skips filter if type isn't `Create` or `Update`" do
|
||||
message = %{"type" => "Note", "object" => %{}}
|
||||
|
||||
assert {:ok, res} = NormalizeMarkup.filter(message)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicyTest do
|
||||
alias Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy
|
||||
|
||||
use Pleroma.DataCase
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
test "Add quote url to Link tag" do
|
||||
quote_url = "https://gleasonator.com/objects/1234"
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://gleasonator.com/users/alex",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "Nice post",
|
||||
"quoteUrl" => quote_url
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => object}} = QuoteToLinkTagPolicy.filter(activity)
|
||||
|
||||
assert object["tag"] == [
|
||||
%{
|
||||
"type" => "Link",
|
||||
"href" => quote_url,
|
||||
"mediaType" => Pleroma.Constants.activity_json_canonical_mime_type()
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
test "Add quote url to Link tag, append to the end" do
|
||||
quote_url = "https://gleasonator.com/objects/1234"
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://gleasonator.com/users/alex",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "Nice post",
|
||||
"quoteUrl" => quote_url,
|
||||
"tag" => [%{"type" => "Hashtag", "name" => "#foo"}]
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => object}} = QuoteToLinkTagPolicy.filter(activity)
|
||||
|
||||
assert [_, tag] = object["tag"]
|
||||
|
||||
assert tag == %{
|
||||
"type" => "Link",
|
||||
"href" => quote_url,
|
||||
"mediaType" => Pleroma.Constants.activity_json_canonical_mime_type()
|
||||
}
|
||||
end
|
||||
|
||||
test "Bypass posts without quoteUrl" do
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"actor" => "https://gleasonator.com/users/alex",
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"content" => "Nice post"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, ^activity} = QuoteToLinkTagPolicy.filter(activity)
|
||||
end
|
||||
end
|
||||
|
|
@ -57,6 +57,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "works with Updates" do
|
||||
clear_config([:mrf_simple, :media_removal], [{"remote.instance", "Some reason"}])
|
||||
media_message = build_media_message(type: "Update")
|
||||
|
||||
assert SimplePolicy.filter(media_message) ==
|
||||
{:ok,
|
||||
media_message
|
||||
|> Map.put("object", Map.delete(media_message["object"], "attachment"))}
|
||||
end
|
||||
end
|
||||
|
||||
describe "when :media_nsfw" do
|
||||
|
|
@ -90,12 +100,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
end
|
||||
|
||||
test "works with Updates" do
|
||||
clear_config([:mrf_simple, :media_nsfw], [{"remote.instance", "Whetever"}])
|
||||
media_message = build_media_message(type: "Update")
|
||||
|
||||
assert SimplePolicy.filter(media_message) ==
|
||||
{:ok, put_in(media_message, ["object", "sensitive"], true)}
|
||||
end
|
||||
end
|
||||
|
||||
defp build_media_message do
|
||||
defp build_media_message(opts \\ []) do
|
||||
%{
|
||||
"actor" => "https://remote.instance/users/bob",
|
||||
"type" => "Create",
|
||||
"type" => opts[:type] || "Create",
|
||||
"object" => %{
|
||||
"attachment" => [%{}],
|
||||
"tag" => ["foo"],
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
|
|||
|> File.exists?()
|
||||
end
|
||||
|
||||
test "reject shortcode", %{message: message} do
|
||||
test "reject regex shortcode", %{message: message} do
|
||||
refute "firedfox" in installed()
|
||||
|
||||
clear_config(:mrf_steal_emoji,
|
||||
|
|
@ -74,6 +74,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
|
|||
refute "firedfox" in installed()
|
||||
end
|
||||
|
||||
test "reject string shortcode", %{message: message} do
|
||||
refute "firedfox" in installed()
|
||||
|
||||
clear_config(:mrf_steal_emoji,
|
||||
hosts: ["example.org"],
|
||||
size_limit: 284_468,
|
||||
rejected_shortcodes: ["firedfox"]
|
||||
)
|
||||
|
||||
assert {:ok, _message} = StealEmojiPolicy.filter(message)
|
||||
|
||||
refute "firedfox" in installed()
|
||||
end
|
||||
|
||||
test "reject if size is above the limit", %{message: message} do
|
||||
refute "firedfox" in installed()
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
|
|||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
|
||||
test "removes attachments in Updates" do
|
||||
actor = insert(:user, tags: ["mrf_tag:media-strip"])
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Update",
|
||||
"object" => %{"attachment" => ["file1"]}
|
||||
}
|
||||
|
||||
except_message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Update",
|
||||
"object" => %{}
|
||||
}
|
||||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
|
||||
describe "mrf_tag:media-force-nsfw" do
|
||||
|
|
@ -119,5 +137,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
|
|||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
|
||||
test "Mark as sensitive on presence of attachments in Updates" do
|
||||
actor = insert(:user, tags: ["mrf_tag:media-force-nsfw"])
|
||||
|
||||
message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Update",
|
||||
"object" => %{"tag" => ["test"], "attachment" => ["file1"]}
|
||||
}
|
||||
|
||||
except_message = %{
|
||||
"actor" => actor.ap_id,
|
||||
"type" => "Update",
|
||||
"object" => %{"tag" => ["test"], "attachment" => ["file1"], "sensitive" => true}
|
||||
}
|
||||
|
||||
assert TagPolicy.filter(message) == {:ok, except_message}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
19
test/pleroma/web/activity_pub/mrf/utils_test.exs
Normal file
19
test/pleroma/web/activity_pub/mrf/utils_test.exs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.UtilsTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.Utils
|
||||
|
||||
describe "describe_regex_or_string/1" do
|
||||
test "describes regex" do
|
||||
assert "~r/foo/i" == Utils.describe_regex_or_string(~r/foo/i)
|
||||
end
|
||||
|
||||
test "returns string as-is" do
|
||||
assert "foo" == Utils.describe_regex_or_string("foo")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRFTest do
|
||||
use ExUnit.Case, async: true
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
||||
|
|
@ -31,6 +32,54 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
|
|||
test "a basic note validates", %{note: note} do
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "a note from factory validates" do
|
||||
note = insert(:note)
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note.data)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Note with history" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = Pleroma.Web.CommonAPI.post(user, %{status: "mew mew :dinosaur:"})
|
||||
{:ok, edit} = Pleroma.Web.CommonAPI.update(user, activity, %{status: "edited :blank:"})
|
||||
|
||||
{:ok, %{"object" => external_rep}} =
|
||||
Pleroma.Web.ActivityPub.Transmogrifier.prepare_outgoing(edit.data)
|
||||
|
||||
%{external_rep: external_rep}
|
||||
end
|
||||
|
||||
test "edited note", %{external_rep: external_rep} do
|
||||
assert %{"formerRepresentations" => %{"orderedItems" => [%{"tag" => [_]}]}} = external_rep
|
||||
|
||||
{:ok, validate_res, []} = ObjectValidator.validate(external_rep, [])
|
||||
|
||||
assert %{"formerRepresentations" => %{"orderedItems" => [%{"emoji" => %{"dinosaur" => _}}]}} =
|
||||
validate_res
|
||||
end
|
||||
|
||||
test "edited note, badly-formed formerRepresentations", %{external_rep: external_rep} do
|
||||
external_rep = Map.put(external_rep, "formerRepresentations", %{})
|
||||
|
||||
assert {:error, _} = ObjectValidator.validate(external_rep, [])
|
||||
end
|
||||
|
||||
test "edited note, badly-formed history item", %{external_rep: external_rep} do
|
||||
history_item =
|
||||
Enum.at(external_rep["formerRepresentations"]["orderedItems"], 0)
|
||||
|> Map.put("type", "Foo")
|
||||
|
||||
external_rep =
|
||||
put_in(
|
||||
external_rep,
|
||||
["formerRepresentations", "orderedItems"],
|
||||
[history_item]
|
||||
)
|
||||
|
||||
assert {:error, _} = ObjectValidator.validate(external_rep, [])
|
||||
end
|
||||
end
|
||||
|
||||
test "a Note from Roadhouse validates" do
|
||||
|
|
@ -43,4 +92,77 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
|
|||
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "a note with an attachment should work", _ do
|
||||
insert(:user, %{ap_id: "https://owncast.localhost.localdomain/federation/user/streamer"})
|
||||
|
||||
note =
|
||||
"test/fixtures/owncast-note-with-attachment.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "a Note without replies/first/items validates" do
|
||||
insert(:user, ap_id: "https://mastodon.social/users/emelie")
|
||||
|
||||
note =
|
||||
"test/fixtures/tesla_mock/status.emelie.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|> pop_in(["replies", "first", "items"])
|
||||
|> elem(1)
|
||||
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "Fedibird quote post" do
|
||||
insert(:user, ap_id: "https://fedibird.com/users/noellabo")
|
||||
|
||||
data = File.read!("test/fixtures/quote_post/fedibird_quote_post.json") |> Jason.decode!()
|
||||
cng = ArticleNotePageValidator.cast_and_validate(data)
|
||||
|
||||
assert cng.valid?
|
||||
assert cng.changes.quoteUrl == "https://misskey.io/notes/8vsn2izjwh"
|
||||
end
|
||||
|
||||
test "Fedibird quote post with quoteUri field" do
|
||||
insert(:user, ap_id: "https://fedibird.com/users/noellabo")
|
||||
|
||||
data = File.read!("test/fixtures/quote_post/fedibird_quote_uri.json") |> Jason.decode!()
|
||||
cng = ArticleNotePageValidator.cast_and_validate(data)
|
||||
|
||||
assert cng.valid?
|
||||
assert cng.changes.quoteUrl == "https://fedibird.com/users/yamako/statuses/107699333438289729"
|
||||
end
|
||||
|
||||
test "Misskey quote post" do
|
||||
insert(:user, ap_id: "https://misskey.io/users/7rkrarq81i")
|
||||
|
||||
data = File.read!("test/fixtures/quote_post/misskey_quote_post.json") |> Jason.decode!()
|
||||
cng = ArticleNotePageValidator.cast_and_validate(data)
|
||||
|
||||
assert cng.valid?
|
||||
assert cng.changes.quoteUrl == "https://misskey.io/notes/8vs6wxufd0"
|
||||
end
|
||||
|
||||
test "Parse tag as quote" do
|
||||
# https://codeberg.org/fediverse/fep/src/branch/main/fep/e232/fep-e232.md
|
||||
|
||||
insert(:user, ap_id: "https://server.example/users/1")
|
||||
|
||||
data = File.read!("test/fixtures/quote_post/fep-e232-tag-example.json") |> Jason.decode!()
|
||||
cng = ArticleNotePageValidator.cast_and_validate(data)
|
||||
|
||||
assert cng.valid?
|
||||
assert cng.changes.quoteUrl == "https://server.example/objects/123"
|
||||
|
||||
assert Enum.at(cng.changes.tag, 0).changes == %{
|
||||
type: "Link",
|
||||
mediaType: "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
|
||||
href: "https://server.example/objects/123",
|
||||
name: "RE: https://server.example/objects/123"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,12 +5,27 @@
|
|||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
|
||||
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "attachments" do
|
||||
test "fails without url" do
|
||||
attachment = %{
|
||||
"mediaType" => "",
|
||||
"name" => "",
|
||||
"summary" => "298p3RG7j27tfsZ9RQ.jpg",
|
||||
"type" => "Document"
|
||||
}
|
||||
|
||||
assert {:error, _cng} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
end
|
||||
|
||||
test "works with honkerific attachments" do
|
||||
attachment = %{
|
||||
"mediaType" => "",
|
||||
|
|
@ -27,6 +42,46 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
|
|||
assert attachment.mediaType == "application/octet-stream"
|
||||
end
|
||||
|
||||
test "works with an unknown but valid mime type" do
|
||||
attachment = %{
|
||||
"mediaType" => "x-custom/x-type",
|
||||
"type" => "Document",
|
||||
"url" => "https://example.org"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "x-custom/x-type"
|
||||
end
|
||||
|
||||
test "works with invalid mime types" do
|
||||
attachment = %{
|
||||
"mediaType" => "x-customx-type",
|
||||
"type" => "Document",
|
||||
"url" => "https://example.org"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "application/octet-stream"
|
||||
|
||||
attachment = %{
|
||||
"mediaType" => "https://example.org",
|
||||
"type" => "Document",
|
||||
"url" => "https://example.org"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "application/octet-stream"
|
||||
end
|
||||
|
||||
test "it turns mastodon attachments into our attachments" do
|
||||
attachment = %{
|
||||
"url" =>
|
||||
|
|
@ -63,6 +118,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
|
|||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
{:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
|
||||
|
||||
{:ok, attachment} =
|
||||
|
|
|
|||
|
|
@ -5,11 +5,13 @@
|
|||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "chat message create activities" do
|
||||
|
|
@ -82,6 +84,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do
|
|||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
{:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
|
||||
|
||||
valid_chat_message =
|
||||
|
|
@ -103,6 +108,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do
|
|||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
{:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
|
||||
|
||||
valid_chat_message =
|
||||
|
|
@ -124,6 +132,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do
|
|||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
{:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
|
||||
|
||||
valid_chat_message =
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidatorTest do
|
|||
{:ok, object_data} = ObjectValidator.cast_and_apply(note_activity["object"])
|
||||
meta = [object_data: ObjectValidator.stringify_keys(object_data)]
|
||||
|
||||
%{valid?: true} = CreateGenericValidator.cast_and_validate(note_activity, meta)
|
||||
assert %{valid?: true} = CreateGenericValidator.cast_and_validate(note_activity, meta)
|
||||
end
|
||||
|
||||
test "a Create/Note with mismatched context is invalid" do
|
||||
test "a Create/Note with mismatched context uses the Note's context" do
|
||||
user = insert(:user)
|
||||
|
||||
note = %{
|
||||
|
|
@ -54,6 +54,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidatorTest do
|
|||
{:ok, object_data} = ObjectValidator.cast_and_apply(note_activity["object"])
|
||||
meta = [object_data: ObjectValidator.stringify_keys(object_data)]
|
||||
|
||||
%{valid?: false} = CreateGenericValidator.cast_and_validate(note_activity, meta)
|
||||
validated = CreateGenericValidator.cast_and_validate(note_activity, meta)
|
||||
|
||||
assert validated.valid?
|
||||
assert {:context, note["context"]} in validated.changes
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidationTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Pleroma.DataCase, async: false
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
|
|
@ -90,17 +90,26 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidationTest do
|
|||
assert {:actor, {"is not allowed to modify object", []}} in cng.errors
|
||||
end
|
||||
|
||||
test "it's valid if the actor of the object is a local superuser",
|
||||
test "it's only valid if the actor of the object is a privileged local user",
|
||||
%{valid_post_delete: valid_post_delete} do
|
||||
clear_config([:instance, :moderator_privileges], [:messages_delete])
|
||||
|
||||
user =
|
||||
insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo")
|
||||
|
||||
valid_other_actor =
|
||||
post_delete_with_moderator_actor =
|
||||
valid_post_delete
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|
||||
{:ok, _, meta} = ObjectValidator.validate(valid_other_actor, [])
|
||||
{:ok, _, meta} = ObjectValidator.validate(post_delete_with_moderator_actor, [])
|
||||
|
||||
assert meta[:do_not_federate]
|
||||
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(post_delete_with_moderator_actor, [])
|
||||
|
||||
assert {:actor, {"is not allowed to modify object", []}} in cng.errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -38,16 +38,70 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactHandlingTest do
|
|||
assert {:content, {"can't be blank", [validation: :required]}} in cng.errors
|
||||
end
|
||||
|
||||
test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do
|
||||
test "it is valid when custom emoji is used", %{valid_emoji_react: valid_emoji_react} do
|
||||
without_emoji_content =
|
||||
valid_emoji_react
|
||||
|> Map.put("content", "x")
|
||||
|> Map.put("content", ":hello:")
|
||||
|> Map.put("tag", [
|
||||
%{
|
||||
"type" => "Emoji",
|
||||
"name" => ":hello:",
|
||||
"icon" => %{"url" => "http://somewhere", "type" => "Image"}
|
||||
}
|
||||
])
|
||||
|
||||
{:ok, _, _} = ObjectValidator.validate(without_emoji_content, [])
|
||||
end
|
||||
|
||||
test "it is not valid when custom emoji don't have a matching tag", %{
|
||||
valid_emoji_react: valid_emoji_react
|
||||
} do
|
||||
without_emoji_content =
|
||||
valid_emoji_react
|
||||
|> Map.put("content", ":hello:")
|
||||
|> Map.put("tag", [
|
||||
%{
|
||||
"type" => "Emoji",
|
||||
"name" => ":whoops:",
|
||||
"icon" => %{"url" => "http://somewhere", "type" => "Image"}
|
||||
}
|
||||
])
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(without_emoji_content, [])
|
||||
|
||||
refute cng.valid?
|
||||
|
||||
assert {:content, {"must be a single character emoji", []}} in cng.errors
|
||||
assert {:tag, {"does not contain an Emoji tag", []}} in cng.errors
|
||||
end
|
||||
|
||||
test "it is not valid when custom emoji have no tags", %{
|
||||
valid_emoji_react: valid_emoji_react
|
||||
} do
|
||||
without_emoji_content =
|
||||
valid_emoji_react
|
||||
|> Map.put("content", ":hello:")
|
||||
|> Map.put("tag", [])
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(without_emoji_content, [])
|
||||
|
||||
refute cng.valid?
|
||||
|
||||
assert {:tag, {"does not contain an Emoji tag", []}} in cng.errors
|
||||
end
|
||||
|
||||
test "it is not valid when custom emoji doesn't match a shortcode format", %{
|
||||
valid_emoji_react: valid_emoji_react
|
||||
} do
|
||||
without_emoji_content =
|
||||
valid_emoji_react
|
||||
|> Map.put("content", "hello")
|
||||
|> Map.put("tag", [])
|
||||
|
||||
{:error, cng} = ObjectValidator.validate(without_emoji_content, [])
|
||||
|
||||
refute cng.valid?
|
||||
|
||||
assert {:tag, {"does not contain an Emoji tag", []}} in cng.errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateHandlingTest do
|
|||
test "returns an error if the object can't be updated by the actor", %{
|
||||
valid_update: valid_update
|
||||
} do
|
||||
other_user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
|
||||
update =
|
||||
valid_update
|
||||
|
|
@ -40,5 +40,129 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateHandlingTest do
|
|||
|
||||
assert {:error, _cng} = ObjectValidator.validate(update, [])
|
||||
end
|
||||
|
||||
test "validates as long as the object is same-origin with the actor", %{
|
||||
valid_update: valid_update
|
||||
} do
|
||||
other_user = insert(:user)
|
||||
|
||||
update =
|
||||
valid_update
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|
||||
assert {:ok, _update, []} = ObjectValidator.validate(update, [])
|
||||
end
|
||||
|
||||
test "validates if the object is not of an Actor type" do
|
||||
note = insert(:note)
|
||||
updated_note = note.data |> Map.put("content", "edited content")
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, update, _} = Builder.update(other_user, updated_note)
|
||||
|
||||
assert {:ok, _update, _} = ObjectValidator.validate(update, [])
|
||||
end
|
||||
end
|
||||
|
||||
describe "update note" do
|
||||
test "converts object into Pleroma's format" do
|
||||
mastodon_tags = [
|
||||
%{
|
||||
"icon" => %{
|
||||
"mediaType" => "image/png",
|
||||
"type" => "Image",
|
||||
"url" => "https://somewhere.org/emoji/url/1.png"
|
||||
},
|
||||
"id" => "https://somewhere.org/emoji/1",
|
||||
"name" => ":some_emoji:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "2021-04-07T11:00:00Z"
|
||||
}
|
||||
]
|
||||
|
||||
user = insert(:user)
|
||||
note = insert(:note, user: user)
|
||||
|
||||
updated_note =
|
||||
note.data
|
||||
|> Map.put("content", "edited content")
|
||||
|> Map.put("tag", mastodon_tags)
|
||||
|
||||
{:ok, update, _} = Builder.update(user, updated_note)
|
||||
|
||||
assert {:ok, _update, meta} = ObjectValidator.validate(update, [])
|
||||
|
||||
assert %{"emoji" => %{"some_emoji" => "https://somewhere.org/emoji/url/1.png"}} =
|
||||
meta[:object_data]
|
||||
end
|
||||
|
||||
test "returns no object_data in meta for a local Update" do
|
||||
user = insert(:user)
|
||||
note = insert(:note, user: user)
|
||||
|
||||
updated_note =
|
||||
note.data
|
||||
|> Map.put("content", "edited content")
|
||||
|
||||
{:ok, update, _} = Builder.update(user, updated_note)
|
||||
|
||||
assert {:ok, _update, meta} = ObjectValidator.validate(update, local: true)
|
||||
assert is_nil(meta[:object_data])
|
||||
end
|
||||
|
||||
test "returns object_data in meta for a remote Update" do
|
||||
user = insert(:user)
|
||||
note = insert(:note, user: user)
|
||||
|
||||
updated_note =
|
||||
note.data
|
||||
|> Map.put("content", "edited content")
|
||||
|
||||
{:ok, update, _} = Builder.update(user, updated_note)
|
||||
|
||||
assert {:ok, _update, meta} = ObjectValidator.validate(update, local: false)
|
||||
assert meta[:object_data]
|
||||
|
||||
assert {:ok, _update, meta} = ObjectValidator.validate(update, [])
|
||||
assert meta[:object_data]
|
||||
end
|
||||
end
|
||||
|
||||
describe "update with history" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = Pleroma.Web.CommonAPI.post(user, %{status: "mew mew :dinosaur:"})
|
||||
{:ok, edit} = Pleroma.Web.CommonAPI.update(user, activity, %{status: "edited :blank:"})
|
||||
{:ok, external_rep} = Pleroma.Web.ActivityPub.Transmogrifier.prepare_outgoing(edit.data)
|
||||
%{external_rep: external_rep}
|
||||
end
|
||||
|
||||
test "edited note", %{external_rep: external_rep} do
|
||||
{:ok, _validate_res, meta} = ObjectValidator.validate(external_rep, [])
|
||||
|
||||
assert %{"formerRepresentations" => %{"orderedItems" => [%{"emoji" => %{"dinosaur" => _}}]}} =
|
||||
meta[:object_data]
|
||||
end
|
||||
|
||||
test "edited note, badly-formed formerRepresentations", %{external_rep: external_rep} do
|
||||
external_rep = put_in(external_rep, ["object", "formerRepresentations"], %{})
|
||||
|
||||
assert {:error, _} = ObjectValidator.validate(external_rep, [])
|
||||
end
|
||||
|
||||
test "edited note, badly-formed history item", %{external_rep: external_rep} do
|
||||
history_item =
|
||||
Enum.at(external_rep["object"]["formerRepresentations"]["orderedItems"], 0)
|
||||
|> Map.put("type", "Foo")
|
||||
|
||||
external_rep =
|
||||
put_in(
|
||||
external_rep,
|
||||
["object", "formerRepresentations", "orderedItems"],
|
||||
[history_item]
|
||||
)
|
||||
|
||||
assert {:error, _} = ObjectValidator.validate(external_rep, [])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -276,8 +276,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
|
|
@ -313,8 +312,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
|
|
@ -333,11 +331,40 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
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"]
|
||||
})
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(
|
||||
Publisher,
|
||||
%{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
test_with_mock "Publishes to directly addressed actors with higher priority.",
|
||||
Pleroma.Web.Federator.Publisher,
|
||||
[:passthrough],
|
||||
[] do
|
||||
note_activity = insert(:direct_note_activity)
|
||||
|
||||
actor = Pleroma.User.get_by_ap_id(note_activity.data["actor"])
|
||||
|
||||
res = Publisher.publish(actor, note_activity)
|
||||
|
||||
assert res == :ok
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(
|
||||
Publisher,
|
||||
%{
|
||||
inbox: :_,
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
},
|
||||
priority: 0
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -348,8 +375,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
|
|
@ -382,15 +408,13 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
)
|
||||
|
||||
another_fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain2.com/users/nick1/inbox"
|
||||
)
|
||||
|
||||
actor = insert(:user)
|
||||
|
|
@ -419,19 +443,27 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
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"]
|
||||
})
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(
|
||||
Publisher,
|
||||
%{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
)
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
})
|
||||
Pleroma.Web.Federator.Publisher.enqueue_one(
|
||||
Publisher,
|
||||
%{
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -118,7 +118,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
describe "update users" do
|
||||
setup do
|
||||
user = insert(:user, local: false)
|
||||
{:ok, update_data, []} = Builder.update(user, %{"id" => user.ap_id, "name" => "new name!"})
|
||||
|
||||
{:ok, update_data, []} =
|
||||
Builder.update(user, %{"id" => user.ap_id, "type" => "Person", "name" => "new name!"})
|
||||
|
||||
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
|
||||
|
||||
%{user: user, update_data: update_data, update: update}
|
||||
|
|
@ -140,6 +143,298 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "update notes" do
|
||||
setup do
|
||||
make_time = fn ->
|
||||
Pleroma.Web.ActivityPub.Utils.make_date()
|
||||
end
|
||||
|
||||
user = insert(:user)
|
||||
note = insert(:note, user: user, data: %{"published" => make_time.()})
|
||||
_note_activity = insert(:note_activity, note: note)
|
||||
|
||||
updated_note =
|
||||
note.data
|
||||
|> Map.put("summary", "edited summary")
|
||||
|> Map.put("content", "edited content")
|
||||
|> Map.put("updated", make_time.())
|
||||
|
||||
{:ok, update_data, []} = Builder.update(user, updated_note)
|
||||
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
|
||||
|
||||
%{
|
||||
user: user,
|
||||
note: note,
|
||||
object_id: note.id,
|
||||
update_data: update_data,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
}
|
||||
end
|
||||
|
||||
test "it updates the note", %{
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
updated_time = updated_note["updated"]
|
||||
|
||||
new_note = Pleroma.Object.get_by_id(object_id)
|
||||
|
||||
assert %{
|
||||
"summary" => "edited summary",
|
||||
"content" => "edited content",
|
||||
"updated" => ^updated_time
|
||||
} = new_note.data
|
||||
end
|
||||
|
||||
test "it rejects updates with no updated attribute in object", %{
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
old_note = Pleroma.Object.get_by_id(object_id)
|
||||
updated_note = Map.drop(updated_note, ["updated"])
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
new_note = Pleroma.Object.get_by_id(object_id)
|
||||
assert old_note.data == new_note.data
|
||||
end
|
||||
|
||||
test "it rejects updates with updated attribute older than what we have in the original object",
|
||||
%{
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
old_note = Pleroma.Object.get_by_id(object_id)
|
||||
{:ok, creation_time, _} = DateTime.from_iso8601(old_note.data["published"])
|
||||
|
||||
updated_note =
|
||||
Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(creation_time, -10)))
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
new_note = Pleroma.Object.get_by_id(object_id)
|
||||
assert old_note.data == new_note.data
|
||||
end
|
||||
|
||||
test "it rejects updates with updated attribute older than the last Update", %{
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
old_note = Pleroma.Object.get_by_id(object_id)
|
||||
{:ok, creation_time, _} = DateTime.from_iso8601(old_note.data["published"])
|
||||
|
||||
updated_note =
|
||||
Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(creation_time, +10)))
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
|
||||
old_note = Pleroma.Object.get_by_id(object_id)
|
||||
{:ok, update_time, _} = DateTime.from_iso8601(old_note.data["updated"])
|
||||
|
||||
updated_note =
|
||||
Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(update_time, -5)))
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
|
||||
new_note = Pleroma.Object.get_by_id(object_id)
|
||||
assert old_note.data == new_note.data
|
||||
end
|
||||
|
||||
test "it updates using object_data", %{
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
updated_note = Map.put(updated_note, "summary", "mew mew")
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
new_note = Pleroma.Object.get_by_id(object_id)
|
||||
assert %{"summary" => "mew mew", "content" => "edited content"} = new_note.data
|
||||
end
|
||||
|
||||
test "it records the original note in formerRepresentations", %{
|
||||
note: note,
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
%{data: new_note} = Pleroma.Object.get_by_id(object_id)
|
||||
assert %{"summary" => "edited summary", "content" => "edited content"} = new_note
|
||||
|
||||
assert [Map.drop(note.data, ["id", "formerRepresentations"])] ==
|
||||
new_note["formerRepresentations"]["orderedItems"]
|
||||
|
||||
assert new_note["formerRepresentations"]["totalItems"] == 1
|
||||
end
|
||||
|
||||
test "it puts the original note at the front of formerRepresentations", %{
|
||||
user: user,
|
||||
note: note,
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
%{data: first_edit} = Pleroma.Object.get_by_id(object_id)
|
||||
|
||||
second_updated_note =
|
||||
note.data
|
||||
|> Map.put("summary", "edited summary 2")
|
||||
|> Map.put("content", "edited content 2")
|
||||
|> Map.put(
|
||||
"updated",
|
||||
first_edit["updated"]
|
||||
|> DateTime.from_iso8601()
|
||||
|> elem(1)
|
||||
|> DateTime.add(10)
|
||||
|> DateTime.to_iso8601()
|
||||
)
|
||||
|
||||
{:ok, second_update_data, []} = Builder.update(user, second_updated_note)
|
||||
{:ok, update, _meta} = ActivityPub.persist(second_update_data, local: true)
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: second_updated_note)
|
||||
%{data: new_note} = Pleroma.Object.get_by_id(object_id)
|
||||
assert %{"summary" => "edited summary 2", "content" => "edited content 2"} = new_note
|
||||
|
||||
original_version = Map.drop(note.data, ["id", "formerRepresentations"])
|
||||
first_edit = Map.drop(first_edit, ["id", "formerRepresentations"])
|
||||
|
||||
assert [first_edit, original_version] ==
|
||||
new_note["formerRepresentations"]["orderedItems"]
|
||||
|
||||
assert new_note["formerRepresentations"]["totalItems"] == 2
|
||||
end
|
||||
|
||||
test "it does not prepend to formerRepresentations if no actual changes are made", %{
|
||||
note: note,
|
||||
object_id: object_id,
|
||||
update: update,
|
||||
updated_note: updated_note
|
||||
} do
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
%{data: first_edit} = Pleroma.Object.get_by_id(object_id)
|
||||
|
||||
updated_note =
|
||||
updated_note
|
||||
|> Map.put(
|
||||
"updated",
|
||||
first_edit["updated"]
|
||||
|> DateTime.from_iso8601()
|
||||
|> elem(1)
|
||||
|> DateTime.add(10)
|
||||
|> DateTime.to_iso8601()
|
||||
)
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
|
||||
%{data: new_note} = Pleroma.Object.get_by_id(object_id)
|
||||
assert %{"summary" => "edited summary", "content" => "edited content"} = new_note
|
||||
|
||||
original_version = Map.drop(note.data, ["id", "formerRepresentations"])
|
||||
|
||||
assert [original_version] ==
|
||||
new_note["formerRepresentations"]["orderedItems"]
|
||||
|
||||
assert new_note["formerRepresentations"]["totalItems"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "update questions" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
question =
|
||||
insert(:question,
|
||||
user: user,
|
||||
data: %{"published" => Pleroma.Web.ActivityPub.Utils.make_date()}
|
||||
)
|
||||
|
||||
%{user: user, data: question.data, id: question.id}
|
||||
end
|
||||
|
||||
test "allows updating choice count without generating edit history", %{
|
||||
user: user,
|
||||
data: data,
|
||||
id: id
|
||||
} do
|
||||
new_choices =
|
||||
data["oneOf"]
|
||||
|> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
|
||||
|
||||
updated_question =
|
||||
data
|
||||
|> Map.put("oneOf", new_choices)
|
||||
|> Map.put("updated", Pleroma.Web.ActivityPub.Utils.make_date())
|
||||
|
||||
{:ok, update_data, []} = Builder.update(user, updated_question)
|
||||
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
|
||||
|
||||
%{data: new_question} = Pleroma.Object.get_by_id(id)
|
||||
|
||||
assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
|
||||
new_question["oneOf"]
|
||||
|
||||
refute Map.has_key?(new_question, "formerRepresentations")
|
||||
end
|
||||
|
||||
test "allows updating choice count without updated field", %{
|
||||
user: user,
|
||||
data: data,
|
||||
id: id
|
||||
} do
|
||||
new_choices =
|
||||
data["oneOf"]
|
||||
|> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
|
||||
|
||||
updated_question =
|
||||
data
|
||||
|> Map.put("oneOf", new_choices)
|
||||
|
||||
{:ok, update_data, []} = Builder.update(user, updated_question)
|
||||
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
|
||||
|
||||
%{data: new_question} = Pleroma.Object.get_by_id(id)
|
||||
|
||||
assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
|
||||
new_question["oneOf"]
|
||||
|
||||
refute Map.has_key?(new_question, "formerRepresentations")
|
||||
end
|
||||
|
||||
test "allows updating choice count with updated field same as the creation date", %{
|
||||
user: user,
|
||||
data: data,
|
||||
id: id
|
||||
} do
|
||||
new_choices =
|
||||
data["oneOf"]
|
||||
|> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
|
||||
|
||||
updated_question =
|
||||
data
|
||||
|> Map.put("oneOf", new_choices)
|
||||
|> Map.put("updated", data["published"])
|
||||
|
||||
{:ok, update_data, []} = Builder.update(user, updated_question)
|
||||
{:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
|
||||
|
||||
{:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
|
||||
|
||||
%{data: new_question} = Pleroma.Object.get_by_id(id)
|
||||
|
||||
assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
|
||||
new_question["oneOf"]
|
||||
|
||||
refute Map.has_key?(new_question, "formerRepresentations")
|
||||
end
|
||||
end
|
||||
|
||||
describe "EmojiReact objects" do
|
||||
setup do
|
||||
poster = insert(:user)
|
||||
|
|
@ -158,7 +453,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
object = Object.get_by_ap_id(emoji_react.data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
assert ["👌", [user.ap_id]] in object.data["reactions"]
|
||||
assert ["👌", [user.ap_id], nil] in object.data["reactions"]
|
||||
end
|
||||
|
||||
test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
|
||||
|
|
@ -544,9 +839,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
]) do
|
||||
{:ok, announce, _} = SideEffects.handle(announce)
|
||||
|
||||
assert called(
|
||||
Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce)
|
||||
)
|
||||
assert called(Pleroma.Web.Streamer.stream(["user", "list"], announce))
|
||||
|
||||
assert called(Pleroma.Web.Push.send(:_))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -34,7 +34,87 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do
|
|||
object = Object.get_by_ap_id(data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
assert match?([["👌", _]], object.data["reactions"])
|
||||
assert match?([["👌", _, nil]], object.data["reactions"])
|
||||
end
|
||||
|
||||
test "it works for incoming custom emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/custom-emoji-reaction.json")
|
||||
|> Jason.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"] == "https://misskey.local.live/likes/917ocsybgp"
|
||||
assert data["object"] == activity.data["object"]
|
||||
assert data["content"] == ":hanapog:"
|
||||
|
||||
assert data["tag"] == [
|
||||
%{
|
||||
"id" => "https://misskey.local.live/emojis/hanapog",
|
||||
"type" => "Emoji",
|
||||
"name" => "hanapog",
|
||||
"updated" => "2022-06-07T12:00:05.773Z",
|
||||
"icon" => %{
|
||||
"type" => "Image",
|
||||
"url" =>
|
||||
"https://misskey.local.live/files/webpublic-8f8a9768-7264-4171-88d6-2356aabeadcd"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
object = Object.get_by_ap_id(data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
|
||||
assert match?(
|
||||
[
|
||||
[
|
||||
"hanapog",
|
||||
_,
|
||||
"https://misskey.local.live/files/webpublic-8f8a9768-7264-4171-88d6-2356aabeadcd"
|
||||
]
|
||||
],
|
||||
object.data["reactions"]
|
||||
)
|
||||
end
|
||||
|
||||
test "it works for incoming unqualified emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
# woman detective emoji, unqualified
|
||||
unqualified_emoji = [0x1F575, 0x200D, 0x2640] |> List.to_string()
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|> Map.put("content", unqualified_emoji)
|
||||
|
||||
{: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"]
|
||||
# woman detective emoji, fully qualified
|
||||
emoji = [0x1F575, 0xFE0F, 0x200D, 0x2640, 0xFE0F] |> List.to_string()
|
||||
assert data["content"] == emoji
|
||||
|
||||
object = Object.get_by_ap_id(data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
assert match?([[^emoji, _, _]], object.data["reactions"])
|
||||
end
|
||||
|
||||
test "it reject invalid emoji reactions" do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.Transmogrifier.ImageHandlingTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
test "Hubzilla Image object" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://hub.somaton.com/channel/testc6"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/hubzilla-actor.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
}
|
||||
end)
|
||||
|
||||
data = File.read!("test/fixtures/hubzilla-create-image.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
assert object.data["cc"] == ["https://hub.somaton.com/followers/testc6"]
|
||||
|
||||
assert object.data["attachment"] == [
|
||||
%{
|
||||
"mediaType" => "image/jpeg",
|
||||
"type" => "Link",
|
||||
"url" => [
|
||||
%{
|
||||
"height" => 2200,
|
||||
"href" =>
|
||||
"https://hub.somaton.com/photo/452583b2-7e1f-4ac3-8334-ff666f134afe-0.jpg",
|
||||
"mediaType" => "image/jpeg",
|
||||
"type" => "Link",
|
||||
"width" => 2200
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
@ -104,6 +104,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
|||
end
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|
|
@ -707,4 +708,43 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
|||
}
|
||||
]
|
||||
end
|
||||
|
||||
test "the standalone note uses its own ID when context is missing" do
|
||||
insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8")
|
||||
|
||||
activity =
|
||||
"test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{} = modified} = Transmogrifier.handle_incoming(activity)
|
||||
object = Object.normalize(modified, fetch: false)
|
||||
|
||||
assert object.data["context"] == object.data["id"]
|
||||
assert modified.data["context"] == object.data["id"]
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "the reply note uses its parent's ID when context is missing and reply is unreachable" do
|
||||
insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8")
|
||||
|
||||
activity =
|
||||
"test/fixtures/tesla_mock/mk.absturztau.be-93e7nm8wqg-activity.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
object =
|
||||
activity["object"]
|
||||
|> Map.put("inReplyTo", "https://404.site/object/went-to-buy-milk")
|
||||
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("object", object)
|
||||
|
||||
{:ok, %Activity{} = modified} = Transmogrifier.handle_incoming(activity)
|
||||
object = Object.normalize(modified, fetch: false)
|
||||
|
||||
assert object.data["context"] == object.data["inReplyTo"]
|
||||
assert modified.data["context"] == object.data["inReplyTo"]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do
|
|||
assert object.data["context"] ==
|
||||
"tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation"
|
||||
|
||||
assert object.data["context_id"]
|
||||
|
||||
assert object.data["anyOf"] == []
|
||||
|
||||
assert Enum.sort(object.data["oneOf"]) ==
|
||||
|
|
@ -68,7 +66,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.QuestionHandlingTest do
|
|||
reply_object = Object.normalize(reply_activity, fetch: false)
|
||||
|
||||
assert reply_object.data["context"] == object.data["context"]
|
||||
assert reply_object.data["context_id"] == object.data["context_id"]
|
||||
end
|
||||
|
||||
test "Mastodon Question activity with HTML tags in plaintext" do
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
|
@ -61,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
note_obj = %{
|
||||
"type" => "Note",
|
||||
"id" => activity.data["id"],
|
||||
"id" => activity.object.data["id"],
|
||||
"content" => "test post",
|
||||
"published" => object.data["published"],
|
||||
"actor" => AccountView.render("show.json", %{user: user, skip_visibility_check: true})
|
||||
|
|
@ -108,15 +107,54 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert activity.data["type"] == "Move"
|
||||
end
|
||||
|
||||
test "a reply with mismatched context is rejected" do
|
||||
insert(:user, ap_id: "https://macgirvin.com/channel/mike")
|
||||
test "it fixes both the Create and object contexts in a reply" do
|
||||
insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8")
|
||||
insert(:user, ap_id: "https://p.helene.moe/users/helene")
|
||||
|
||||
note_activity =
|
||||
"test/fixtures/roadhouse-create-activity.json"
|
||||
create_activity =
|
||||
"test/fixtures/create-pleroma-reply-to-misskey-thread.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
assert {:error, _} = Transmogrifier.handle_incoming(note_activity)
|
||||
assert {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(create_activity)
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert activity.data["context"] == object.data["context"]
|
||||
end
|
||||
|
||||
test "it keeps link tags" do
|
||||
insert(:user, ap_id: "https://example.org/users/alice")
|
||||
|
||||
message = File.read!("test/fixtures/fep-e232.json") |> Jason.decode!()
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
object = Object.normalize(activity)
|
||||
assert [%{"type" => "Mention"}, %{"type" => "Link"}] = object.data["tag"]
|
||||
end) =~ "Error while fetching"
|
||||
end
|
||||
|
||||
test "it accepts quote posts" do
|
||||
insert(:user, ap_id: "https://misskey.io/users/7rkrarq81i")
|
||||
|
||||
object = File.read!("test/fixtures/quote_post/misskey_quote_post.json") |> Jason.decode!()
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"type" => "Create",
|
||||
"actor" => "https://misskey.io/users/7rkrarq81i",
|
||||
"object" => object
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
# Object was created in the database
|
||||
object = Object.normalize(activity)
|
||||
assert object.data["quoteUrl"] == "https://misskey.io/notes/8vs6wxufd0"
|
||||
|
||||
# It fetched the quoted post
|
||||
assert Object.normalize("https://misskey.io/notes/8vs6wxufd0")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -227,7 +265,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert is_nil(modified["object"]["like_count"])
|
||||
assert is_nil(modified["object"]["announcements"])
|
||||
assert is_nil(modified["object"]["announcement_count"])
|
||||
assert is_nil(modified["object"]["context_id"])
|
||||
assert is_nil(modified["object"]["generator"])
|
||||
end
|
||||
|
||||
|
|
@ -242,7 +279,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert is_nil(modified["object"]["like_count"])
|
||||
assert is_nil(modified["object"]["announcements"])
|
||||
assert is_nil(modified["object"]["announcement_count"])
|
||||
assert is_nil(modified["object"]["context_id"])
|
||||
assert is_nil(modified["object"]["likes"])
|
||||
end
|
||||
|
||||
|
|
@ -312,68 +348,41 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
|
||||
assert url == "http://localhost:4001/emoji/dino%20walking.gif"
|
||||
end
|
||||
end
|
||||
|
||||
describe "user upgrade" do
|
||||
test "it upgrades a user to activitypub" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
nickname: "rye@niu.moe",
|
||||
local: false,
|
||||
ap_id: "https://niu.moe/users/rye",
|
||||
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
|
||||
})
|
||||
test "Updates of Notes are handled" do
|
||||
user = insert(:user)
|
||||
|
||||
user_two = insert(:user)
|
||||
Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "everybody do the dinosaur :dinosaur:"})
|
||||
{:ok, update} = CommonAPI.update(user, activity, %{status: "mew mew :blank:"})
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{status: "test"})
|
||||
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 1
|
||||
|
||||
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert user.ap_enabled
|
||||
assert user.note_count == 1
|
||||
assert user.follower_address == "https://niu.moe/users/rye/followers"
|
||||
assert user.following_address == "https://niu.moe/users/rye/following"
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 1
|
||||
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
assert user.follower_address in activity.recipients
|
||||
{:ok, prepared} = Transmogrifier.prepare_outgoing(update.data)
|
||||
|
||||
assert %{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
|
||||
}
|
||||
]
|
||||
} = user.avatar
|
||||
"content" => "mew mew :blank:",
|
||||
"tag" => [%{"name" => ":blank:", "type" => "Emoji"}],
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"content" => "everybody do the dinosaur :dinosaur:",
|
||||
"tag" => [%{"name" => ":dinosaur:", "type" => "Emoji"}]
|
||||
}
|
||||
]
|
||||
}
|
||||
} = prepared["object"]
|
||||
end
|
||||
|
||||
assert %{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
|
||||
}
|
||||
]
|
||||
} = user.banner
|
||||
test "it prepares a quote post" do
|
||||
user = insert(:user)
|
||||
|
||||
refute "..." in activity.recipients
|
||||
{:ok, quoted_post} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, quote_post} = CommonAPI.post(user, %{status: "hey", quote_id: quoted_post.id})
|
||||
|
||||
unrelated_activity = Activity.get_by_id(unrelated_activity.id)
|
||||
refute user.follower_address in unrelated_activity.recipients
|
||||
{:ok, modified} = Transmogrifier.prepare_outgoing(quote_post.data)
|
||||
|
||||
user_two = User.get_cached_by_id(user_two.id)
|
||||
assert User.following?(user_two, user)
|
||||
refute "..." in User.following(user_two)
|
||||
%{data: %{"id" => quote_id}} = Object.normalize(quoted_post)
|
||||
|
||||
assert modified["object"]["quoteUrl"] == quote_id
|
||||
assert modified["object"]["quoteUri"] == quote_id
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -575,4 +584,43 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert Transmogrifier.fix_attachments(object) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "prepare_object/1" do
|
||||
test "it processes history" do
|
||||
original = %{
|
||||
"formerRepresentations" => %{
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"generator" => %{},
|
||||
"emoji" => %{"blobcat" => "http://localhost:4001/emoji/blobcat.png"}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
processed = Transmogrifier.prepare_object(original)
|
||||
|
||||
history_item = Enum.at(processed["formerRepresentations"]["orderedItems"], 0)
|
||||
|
||||
refute Map.has_key?(history_item, "generator")
|
||||
|
||||
assert [%{"name" => ":blobcat:"}] = history_item["tag"]
|
||||
end
|
||||
|
||||
test "it works when there is no or bad history" do
|
||||
original = %{
|
||||
"formerRepresentations" => %{
|
||||
"items" => [
|
||||
%{
|
||||
"generator" => %{},
|
||||
"emoji" => %{"blobcat" => "http://localhost:4001/emoji/blobcat.png"}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
processed = Transmogrifier.prepare_object(original)
|
||||
assert processed["formerRepresentations"] == original["formerRepresentations"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,6 +16,41 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
describe "strip_report_status_data/1" do
|
||||
test "does not break on issues with the reported activites" do
|
||||
reporter = insert(:user)
|
||||
target_account = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"})
|
||||
context = Utils.generate_context_id()
|
||||
content = "foobar"
|
||||
post_id = activity.data["id"]
|
||||
|
||||
res =
|
||||
Utils.make_flag_data(
|
||||
%{
|
||||
actor: reporter,
|
||||
context: context,
|
||||
account: target_account,
|
||||
statuses: [%{"id" => post_id}],
|
||||
content: content
|
||||
},
|
||||
%{}
|
||||
)
|
||||
|
||||
res =
|
||||
res
|
||||
|> Map.put("object", res["object"] ++ [nil, 1, 5, "123"])
|
||||
|
||||
{:ok, activity} = Pleroma.Web.ActivityPub.ActivityPub.insert(res)
|
||||
|
||||
[user_id, object | _] = activity.data["object"]
|
||||
|
||||
{:ok, stripped} = Utils.strip_report_status_data(activity)
|
||||
|
||||
assert stripped.data["object"] == [user_id, object["id"]]
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch the latest Follow" do
|
||||
test "fetches the latest Follow activity" do
|
||||
%Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
|
||||
|
|
@ -429,7 +464,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
object = Object.normalize(note_activity, fetch: false)
|
||||
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
|
||||
|
|
@ -437,7 +471,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
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)
|
||||
|
|
@ -454,13 +487,11 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
})
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -477,7 +508,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
content = "foobar"
|
||||
|
||||
target_ap_id = target_account.ap_id
|
||||
activity_ap_id = activity.data["id"]
|
||||
object_ap_id = activity.object.data["id"]
|
||||
|
||||
res =
|
||||
Utils.make_flag_data(
|
||||
|
|
@ -493,7 +524,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
|
||||
note_obj = %{
|
||||
"type" => "Note",
|
||||
"id" => activity_ap_id,
|
||||
"id" => object_ap_id,
|
||||
"content" => content,
|
||||
"published" => activity.object.data["published"],
|
||||
"actor" =>
|
||||
|
|
@ -508,6 +539,49 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
"state" => "open"
|
||||
} = res
|
||||
end
|
||||
|
||||
test "returns map with Flag object with a non-Create Activity" do
|
||||
reporter = insert(:user)
|
||||
posting_account = insert(:user)
|
||||
target_account = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(posting_account, %{status: "foobar"})
|
||||
{:ok, like} = CommonAPI.favorite(target_account, activity.id)
|
||||
context = Utils.generate_context_id()
|
||||
content = "foobar"
|
||||
|
||||
target_ap_id = target_account.ap_id
|
||||
object_ap_id = activity.object.data["id"]
|
||||
|
||||
res =
|
||||
Utils.make_flag_data(
|
||||
%{
|
||||
actor: reporter,
|
||||
context: context,
|
||||
account: target_account,
|
||||
statuses: [%{"id" => like.data["id"]}],
|
||||
content: content
|
||||
},
|
||||
%{}
|
||||
)
|
||||
|
||||
note_obj = %{
|
||||
"type" => "Note",
|
||||
"id" => object_ap_id,
|
||||
"content" => content,
|
||||
"published" => activity.object.data["published"],
|
||||
"actor" =>
|
||||
AccountView.render("show.json", %{user: posting_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
|
||||
|
|
@ -548,15 +622,38 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
end
|
||||
|
||||
describe "get_cached_emoji_reactions/1" do
|
||||
test "returns the data or an emtpy list" do
|
||||
test "returns the normalized 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"]]]
|
||||
assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"], nil]]
|
||||
|
||||
object = insert(:note, data: %{"reactions" => %{}})
|
||||
assert Utils.get_cached_emoji_reactions(object) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "add_emoji_reaction_to_object/1" do
|
||||
test "works with legacy 2-tuple format" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
|
||||
note =
|
||||
insert(:note,
|
||||
user: user,
|
||||
data: %{
|
||||
"reactions" => [["😿", [other_user.ap_id]]]
|
||||
}
|
||||
)
|
||||
|
||||
_activity = insert(:note_activity, user: user, note: note)
|
||||
|
||||
Utils.add_emoji_reaction_to_object(
|
||||
%Activity{data: %{"content" => "😿", "actor" => third_user.ap_id}},
|
||||
note
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -81,4 +81,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
|
|||
assert result["object"] == object.data["id"]
|
||||
assert result["type"] == "Announce"
|
||||
end
|
||||
|
||||
test "renders an undo announce activity" do
|
||||
note = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, announce} = CommonAPI.repeat(note.id, user)
|
||||
{:ok, undo} = CommonAPI.unrepeat(note.id, user)
|
||||
|
||||
result = ObjectView.render("object.json", %{object: undo})
|
||||
|
||||
assert result["id"] == undo.data["id"]
|
||||
assert result["object"] == announce.data["id"]
|
||||
assert result["type"] == "Undo"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
|
||||
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})
|
||||
|
||||
|
|
@ -55,7 +54,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
|
||||
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"]
|
||||
|
|
@ -67,8 +65,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
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"
|
||||
|
|
@ -80,6 +76,15 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
|
||||
end
|
||||
|
||||
test "service has a few essential fields" do
|
||||
user = insert(:user)
|
||||
result = UserView.render("service.json", %{user: user})
|
||||
assert result["id"]
|
||||
assert result["type"] == "Application"
|
||||
assert result["inbox"]
|
||||
assert result["outbox"]
|
||||
end
|
||||
|
||||
test "renders AKAs" do
|
||||
akas = ["https://i.tusooa.xyz/users/test-pleroma"]
|
||||
user = insert(:user, also_known_as: akas)
|
||||
|
|
@ -89,7 +94,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
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})
|
||||
|
||||
|
|
@ -105,7 +109,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
|
||||
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})
|
||||
|
||||
|
|
@ -115,7 +118,6 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
|
||||
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})
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
|
|
@ -15,6 +15,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
alias Pleroma.ModerationLog
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
|
|
@ -92,18 +93,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
describe "PUT /api/pleroma/admin/users/tag" do
|
||||
setup %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_tags])
|
||||
|
||||
user1 = insert(:user, %{tags: ["x"]})
|
||||
user2 = insert(:user, %{tags: ["y"]})
|
||||
user3 = insert(:user, %{tags: ["unchanged"]})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> put(
|
||||
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
|
||||
"#{user2.nickname}&tags[]=foo&tags[]=bar"
|
||||
)
|
||||
|
||||
%{conn: conn, user1: user1, user2: user2, user3: user3}
|
||||
end
|
||||
|
||||
|
|
@ -113,6 +108,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
user1: user1,
|
||||
user2: user2
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> put(
|
||||
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
|
||||
"#{user2.nickname}&tags[]=foo&tags[]=bar"
|
||||
)
|
||||
|
||||
assert empty_json_response(conn)
|
||||
assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
|
||||
assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
|
||||
|
|
@ -130,26 +133,43 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"@#{admin.nickname} added tags: #{tags} to users: #{users}"
|
||||
end
|
||||
|
||||
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
|
||||
test "it does not modify tags of not specified users", %{
|
||||
conn: conn,
|
||||
user1: user1,
|
||||
user2: user2,
|
||||
user3: user3
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> put(
|
||||
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
|
||||
"#{user2.nickname}&tags[]=foo&tags[]=bar"
|
||||
)
|
||||
|
||||
assert empty_json_response(conn)
|
||||
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_tags", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> put("/api/pleroma/admin/users/tag?nicknames[]=nickname&tags[]=foo&tags[]=bar")
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/pleroma/admin/users/tag" do
|
||||
setup %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_tags])
|
||||
user1 = insert(:user, %{tags: ["x"]})
|
||||
user2 = insert(:user, %{tags: ["y", "z"]})
|
||||
user3 = insert(:user, %{tags: ["unchanged"]})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete(
|
||||
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
|
||||
"#{user2.nickname}&tags[]=x&tags[]=z"
|
||||
)
|
||||
|
||||
%{conn: conn, user1: user1, user2: user2, user3: user3}
|
||||
end
|
||||
|
||||
|
|
@ -159,6 +179,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
user1: user1,
|
||||
user2: user2
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete(
|
||||
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
|
||||
"#{user2.nickname}&tags[]=x&tags[]=z"
|
||||
)
|
||||
|
||||
assert empty_json_response(conn)
|
||||
assert User.get_cached_by_id(user1.id).tags == []
|
||||
assert User.get_cached_by_id(user2.id).tags == ["y"]
|
||||
|
|
@ -176,10 +204,34 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
"@#{admin.nickname} removed tags: #{tags} from users: #{users}"
|
||||
end
|
||||
|
||||
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
|
||||
test "it does not modify tags of not specified users", %{
|
||||
conn: conn,
|
||||
user1: user1,
|
||||
user2: user2,
|
||||
user3: user3
|
||||
} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete(
|
||||
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
|
||||
"#{user2.nickname}&tags[]=x&tags[]=z"
|
||||
)
|
||||
|
||||
assert empty_json_response(conn)
|
||||
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_tags", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete("/api/pleroma/admin/users/tag?nicknames[]=nickname&tags[]=foo&tags[]=bar")
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/users/:nickname/permission_group" do
|
||||
|
|
@ -271,21 +323,38 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
describe "/api/pleroma/admin/users/:nickname/password_reset" do
|
||||
test "it returns a password reset link", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
|
||||
user = insert(:user)
|
||||
|
||||
resp = json_response(conn, 200)
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
|
||||
|
||||
assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
|
||||
resp = json_response(conn, 200)
|
||||
|
||||
assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> get("/api/pleroma/admin/users/nickname/password_reset")
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT disable_mfa" do
|
||||
test "returns 200 and disable 2fa", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
multi_factor_authentication_settings: %MFA.Settings{
|
||||
|
|
@ -307,6 +376,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
end
|
||||
|
||||
test "returns 404 if user not found", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
|
||||
|
|
@ -314,6 +385,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
assert response == %{"error" => "Not found"}
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/restart" do
|
||||
|
|
@ -344,6 +425,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
describe "GET /api/pleroma/admin/users/:nickname/statuses" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
insert(:note_activity, user: user)
|
||||
|
|
@ -360,6 +443,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert length(activities) == 3
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_read", %{conn: conn, user: user} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "renders user's statuses with pagination", %{conn: conn, user: user} do
|
||||
%{"total" => 3, "activities" => [activity1]} =
|
||||
conn
|
||||
|
|
@ -421,21 +512,32 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
describe "GET /api/pleroma/admin/users/:nickname/chats" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
test "renders user's chats", %{conn: conn, user: user} do
|
||||
recipients = insert_list(3, :user)
|
||||
|
||||
Enum.each(recipients, fn recipient ->
|
||||
CommonAPI.post_chat_message(user, recipient, "yo")
|
||||
end)
|
||||
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
test "renders user's chats", %{conn: conn, user: user} do
|
||||
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats")
|
||||
|
||||
assert json_response(conn, 200) |> length() == 3
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_read", %{conn: conn, user: user} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/users/:nickname/chats unauthorized" do
|
||||
|
|
@ -471,6 +573,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
describe "GET /api/pleroma/admin/moderation_log" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:moderation_log_read])
|
||||
moderator = insert(:user, is_moderator: true)
|
||||
|
||||
%{moderator: moderator}
|
||||
|
|
@ -675,6 +778,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert get_in(first_entry, ["data", "message"]) ==
|
||||
"@#{moderator.nickname} unfollowed relay: https://example.org/relay"
|
||||
end
|
||||
|
||||
test "it requires privileged role :moderation_log_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> get("/api/pleroma/admin/moderation_log")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated",
|
||||
|
|
@ -688,6 +800,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
describe "GET /users/:nickname/credentials" do
|
||||
test "gets the user credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
user = insert(:user)
|
||||
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
|
||||
|
||||
|
|
@ -696,6 +809,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
end
|
||||
|
||||
test "returns 403 if requested by a non-admin" do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
|
|
@ -705,6 +819,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/users/nickname/credentials")
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /users/:nickname/credentials" do
|
||||
|
|
@ -714,6 +838,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
end
|
||||
|
||||
test "changes password and email", %{conn: conn, admin: admin, user: user} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
|
||||
assert user.password_reset_pending == false
|
||||
|
||||
conn =
|
||||
|
|
@ -756,6 +882,19 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_manage_credentials", %{conn: conn, user: user} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
|
||||
"password" => "new_password",
|
||||
"email" => "new_email@example.com",
|
||||
"name" => "new_name"
|
||||
})
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "changes actor type from permitted list", %{conn: conn, user: user} do
|
||||
assert user.actor_type == "Person"
|
||||
|
||||
|
|
@ -784,6 +923,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
describe "PATCH /users/:nickname/force_password_reset" do
|
||||
test "sets password_reset_pending to true", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
user = insert(:user)
|
||||
assert user.password_reset_pending == false
|
||||
|
||||
|
|
@ -796,10 +936,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
assert User.get_by_id(user.id).password_reset_pending == true
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> patch("/api/pleroma/admin/users/force_password_reset", %{nickname: "nickname"})
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /confirm_email" do
|
||||
test "it confirms emails of two users", %{conn: conn, admin: admin} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
[first_user, second_user] = insert_pair(:user, is_confirmed: false)
|
||||
|
||||
refute first_user.is_confirmed
|
||||
|
|
@ -826,10 +977,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{second_user.nickname}"
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> patch("/api/pleroma/admin/users/confirm_email", %{nicknames: ["nickname"]})
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /resend_confirmation_email" do
|
||||
test "it resend emails for two users", %{conn: conn, admin: admin} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_credentials])
|
||||
[first_user, second_user] = insert_pair(:user, is_confirmed: false)
|
||||
|
||||
ret_conn =
|
||||
|
|
@ -855,9 +1017,23 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
|
||||
|> assert_email_sent()
|
||||
end
|
||||
|
||||
test "it requires privileged role :users_manage_credentials", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> patch("/api/pleroma/admin/users/resend_confirmation_email", %{nicknames: ["nickname"]})
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/stats" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:statistics_read])
|
||||
end
|
||||
|
||||
test "status visibility count", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
|
|
@ -890,10 +1066,21 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
|
||||
response["status_visibility"]
|
||||
end
|
||||
|
||||
test "it requires privileged role :statistics_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn
|
||||
|> get("/api/pleroma/admin/stats", instance: "lain.wired")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/backups" do
|
||||
test "it creates a backup", %{conn: conn} do
|
||||
ConfigMock
|
||||
|> Mox.stub_with(Pleroma.Config)
|
||||
|
||||
admin = %{id: admin_id, nickname: admin_nickname} = insert(:user, is_admin: true)
|
||||
token = insert(:oauth_admin_token, user: admin)
|
||||
user = %{id: user_id, nickname: user_nickname} = insert(:user)
|
||||
|
|
@ -958,6 +1145,34 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
assert Repo.aggregate(Pleroma.User.Backup, :count) == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/pleroma/admin/reload_emoji" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:emoji_manage_emoji])
|
||||
|
||||
admin = insert(:user, is_admin: true)
|
||||
token = insert(:oauth_admin_token, user: admin)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, token)
|
||||
|
||||
{:ok, %{conn: conn, admin: admin}}
|
||||
end
|
||||
|
||||
test "it requires privileged role :emoji_manage_emoji", %{conn: conn} do
|
||||
assert conn
|
||||
|> post("/api/v1/pleroma/admin/reload_emoji")
|
||||
|> json_response(200)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn
|
||||
|> post("/api/v1/pleroma/admin/reload_emoji")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Needed for testing
|
||||
|
|
|
|||
|
|
@ -0,0 +1,375 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.AnnouncementControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:announcements_manage_announcements])
|
||||
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/v1/pleroma/admin/announcements" do
|
||||
test "it lists all announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id}] = response
|
||||
end
|
||||
|
||||
test "it requires privileged role :announcements_manage_announcements", %{conn: conn} do
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
|
||||
test "it paginates announcements", %{conn: conn} do
|
||||
_announcements = Enum.map(0..20, fn _ -> insert(:announcement) end)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert length(response) == 20
|
||||
end
|
||||
|
||||
test "it paginates announcements with custom params", %{conn: conn} do
|
||||
announcements = Enum.map(0..20, fn _ -> insert(:announcement) end)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", limit: 5, offset: 7)
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert length(response) == 5
|
||||
assert Enum.at(response, 0)["id"] == Enum.at(announcements, 7).id
|
||||
end
|
||||
|
||||
test "it returns empty list with out-of-bounds offset", %{conn: conn} do
|
||||
_announcements = Enum.map(0..20, fn _ -> insert(:announcement) end)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", offset: 21)
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [] = response
|
||||
end
|
||||
|
||||
test "it rejects invalid pagination params", %{conn: conn} do
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", limit: 0)
|
||||
|> json_response_and_validate_schema(400)
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", limit: -1)
|
||||
|> json_response_and_validate_schema(400)
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", offset: -1)
|
||||
|> json_response_and_validate_schema(400)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/v1/pleroma/admin/announcements/:id" do
|
||||
test "it displays one announcement", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"id" => ^id} = response
|
||||
end
|
||||
|
||||
test "it requires privileged role :announcements_manage_announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
|
||||
test "it returns not found for non-existent id", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements/#{id}xxx")
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v1/pleroma/admin/announcements/:id" do
|
||||
test "it deletes specified announcement", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "it requires privileged role :announcements_manage_announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
|
||||
test "it returns not found for non-existent id", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/admin/announcements/#{id}xxx")
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
|
||||
assert %{id: ^id} = Pleroma.Announcement.get_by_id(id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v1/pleroma/admin/announcements/:id" do
|
||||
test "it returns not found for non-existent id", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}xxx", %{})
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
|
||||
assert %{id: ^id} = Pleroma.Announcement.get_by_id(id)
|
||||
end
|
||||
|
||||
test "it updates a field", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: NaiveDateTime.to_iso8601(starts_at)
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert NaiveDateTime.compare(new.starts_at, starts_at) == :eq
|
||||
end
|
||||
|
||||
test "it requires privileged role :announcements_manage_announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: NaiveDateTime.to_iso8601(starts_at)
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: NaiveDateTime.to_iso8601(starts_at)
|
||||
})
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
|
||||
test "it updates with time with utc timezone", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
now = DateTime.now("Etc/UTC") |> elem(1) |> DateTime.truncate(:second)
|
||||
starts_at = DateTime.add(now, -10, :second)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: DateTime.to_iso8601(starts_at)
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert DateTime.compare(new.starts_at, starts_at) == :eq
|
||||
end
|
||||
|
||||
test "it updates a data field", %{conn: conn} do
|
||||
%{id: id} = announcement = insert(:announcement, data: %{"all_day" => true})
|
||||
|
||||
assert announcement.data["all_day"] == true
|
||||
|
||||
new_content = "new content"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
content: new_content
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["content"] == new_content
|
||||
assert response["all_day"] == true
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert new.data["content"] == new_content
|
||||
assert new.data["all_day"] == true
|
||||
end
|
||||
|
||||
test "it nullifies a nullable field", %{conn: conn} do
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
|
||||
%{id: id} = insert(:announcement, starts_at: starts_at)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: nil
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["starts_at"] == nil
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert new.starts_at == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/pleroma/admin/announcements" do
|
||||
test "it creates an announcement", %{conn: conn} do
|
||||
content = "test post announcement api"
|
||||
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
ends_at = NaiveDateTime.add(now, 10, :second)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/pleroma/admin/announcements", %{
|
||||
"content" => content,
|
||||
"starts_at" => NaiveDateTime.to_iso8601(starts_at),
|
||||
"ends_at" => NaiveDateTime.to_iso8601(ends_at),
|
||||
"all_day" => true
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"content" => ^content, "all_day" => true} = response
|
||||
|
||||
announcement = Pleroma.Announcement.get_by_id(response["id"])
|
||||
|
||||
assert not is_nil(announcement)
|
||||
|
||||
assert NaiveDateTime.compare(announcement.starts_at, starts_at) == :eq
|
||||
assert NaiveDateTime.compare(announcement.ends_at, ends_at) == :eq
|
||||
end
|
||||
|
||||
test "it requires privileged role :announcements_manage_announcements", %{conn: conn} do
|
||||
content = "test post announcement api"
|
||||
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
ends_at = NaiveDateTime.add(now, 10, :second)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/pleroma/admin/announcements", %{
|
||||
"content" => content,
|
||||
"starts_at" => NaiveDateTime.to_iso8601(starts_at),
|
||||
"ends_at" => NaiveDateTime.to_iso8601(ends_at),
|
||||
"all_day" => true
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/pleroma/admin/announcements", %{
|
||||
"content" => content,
|
||||
"starts_at" => NaiveDateTime.to_iso8601(starts_at),
|
||||
"ends_at" => NaiveDateTime.to_iso8601(ends_at),
|
||||
"all_day" => true
|
||||
})
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
|
||||
test "creating with time with utc timezones", %{conn: conn} do
|
||||
content = "test post announcement api"
|
||||
|
||||
now = DateTime.now("Etc/UTC") |> elem(1) |> DateTime.truncate(:second)
|
||||
starts_at = DateTime.add(now, -10, :second)
|
||||
ends_at = DateTime.add(now, 10, :second)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/pleroma/admin/announcements", %{
|
||||
"content" => content,
|
||||
"starts_at" => DateTime.to_iso8601(starts_at),
|
||||
"ends_at" => DateTime.to_iso8601(ends_at),
|
||||
"all_day" => true
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"content" => ^content, "all_day" => true} = response
|
||||
|
||||
announcement = Pleroma.Announcement.get_by_id(response["id"])
|
||||
|
||||
assert not is_nil(announcement)
|
||||
|
||||
assert DateTime.compare(announcement.starts_at, starts_at) == :eq
|
||||
assert DateTime.compare(announcement.ends_at, ends_at) == :eq
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.ChatControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -27,7 +27,10 @@ defmodule Pleroma.Web.AdminAPI.ChatControllerTest do
|
|||
end
|
||||
|
||||
describe "DELETE /api/pleroma/admin/chats/:id/messages/:message_id" do
|
||||
setup do: admin_setup()
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_delete])
|
||||
admin_setup()
|
||||
end
|
||||
|
||||
test "it deletes a message from the chat", %{conn: conn, admin: admin} do
|
||||
user = insert(:user)
|
||||
|
|
@ -53,17 +56,29 @@ defmodule Pleroma.Web.AdminAPI.ChatControllerTest do
|
|||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deleted chat message ##{cm_ref.id}"
|
||||
"@#{admin.nickname} deleted chat message ##{message.id}"
|
||||
|
||||
assert result["id"] == cm_ref.id
|
||||
refute MessageReference.get_by_id(cm_ref.id)
|
||||
refute MessageReference.get_by_id(recipient_cm_ref.id)
|
||||
assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id)
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_delete", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> delete("/api/pleroma/admin/chats/some_id/messages/some_ref_id")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/chats/:id/messages" do
|
||||
setup do: admin_setup()
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
admin_setup()
|
||||
end
|
||||
|
||||
test "it paginates", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
|
@ -114,10 +129,21 @@ defmodule Pleroma.Web.AdminAPI.ChatControllerTest do
|
|||
|
||||
assert length(result) == 3
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/chats/some_id/messages")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/chats/:id" do
|
||||
setup do: admin_setup()
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
admin_setup()
|
||||
end
|
||||
|
||||
test "it returns a chat", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
|
@ -135,6 +161,14 @@ defmodule Pleroma.Web.AdminAPI.ChatControllerTest do
|
|||
assert %{} = result["receiver"]
|
||||
refute result["account"]
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/chats/some_id")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "unauthorized chat moderation" do
|
||||
|
|
|
|||
|
|
@ -316,15 +316,16 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "save configs setting without explicit key", %{conn: conn} do
|
||||
level = Application.get_env(:quack, :level)
|
||||
meta = Application.get_env(:quack, :meta)
|
||||
webhook_url = Application.get_env(:quack, :webhook_url)
|
||||
adapter = Application.get_env(:http, :adapter)
|
||||
send_user_agent = Application.get_env(:http, :send_user_agent)
|
||||
user_agent = Application.get_env(:http, :user_agent)
|
||||
|
||||
on_exit(fn ->
|
||||
Application.put_env(:quack, :level, level)
|
||||
Application.put_env(:quack, :meta, meta)
|
||||
Application.put_env(:quack, :webhook_url, webhook_url)
|
||||
Application.put_env(:http, :adapter, adapter)
|
||||
Application.put_env(:http, :send_user_agent, send_user_agent)
|
||||
Application.put_env(:http, :user_agent, user_agent)
|
||||
end)
|
||||
|
||||
conn =
|
||||
|
|
@ -333,19 +334,19 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
|> post("/api/pleroma/admin/config", %{
|
||||
configs: [
|
||||
%{
|
||||
group: ":quack",
|
||||
key: ":level",
|
||||
value: ":info"
|
||||
group: ":http",
|
||||
key: ":adapter",
|
||||
value: [":someval"]
|
||||
},
|
||||
%{
|
||||
group: ":quack",
|
||||
key: ":meta",
|
||||
value: [":none"]
|
||||
group: ":http",
|
||||
key: ":send_user_agent",
|
||||
value: true
|
||||
},
|
||||
%{
|
||||
group: ":quack",
|
||||
key: ":webhook_url",
|
||||
value: "https://hooks.slack.com/services/KEY"
|
||||
group: ":http",
|
||||
key: ":user_agent",
|
||||
value: [":default"]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
@ -353,30 +354,30 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
assert json_response_and_validate_schema(conn, 200) == %{
|
||||
"configs" => [
|
||||
%{
|
||||
"group" => ":quack",
|
||||
"key" => ":level",
|
||||
"value" => ":info",
|
||||
"db" => [":level"]
|
||||
"group" => ":http",
|
||||
"key" => ":adapter",
|
||||
"value" => [":someval"],
|
||||
"db" => [":adapter"]
|
||||
},
|
||||
%{
|
||||
"group" => ":quack",
|
||||
"key" => ":meta",
|
||||
"value" => [":none"],
|
||||
"db" => [":meta"]
|
||||
"group" => ":http",
|
||||
"key" => ":send_user_agent",
|
||||
"value" => true,
|
||||
"db" => [":send_user_agent"]
|
||||
},
|
||||
%{
|
||||
"group" => ":quack",
|
||||
"key" => ":webhook_url",
|
||||
"value" => "https://hooks.slack.com/services/KEY",
|
||||
"db" => [":webhook_url"]
|
||||
"group" => ":http",
|
||||
"key" => ":user_agent",
|
||||
"value" => [":default"],
|
||||
"db" => [":user_agent"]
|
||||
}
|
||||
],
|
||||
"need_reboot" => false
|
||||
}
|
||||
|
||||
assert Application.get_env(:quack, :level) == :info
|
||||
assert Application.get_env(:quack, :meta) == [:none]
|
||||
assert Application.get_env(:quack, :webhook_url) == "https://hooks.slack.com/services/KEY"
|
||||
assert Application.get_env(:http, :adapter) == [:someval]
|
||||
assert Application.get_env(:http, :send_user_agent) == true
|
||||
assert Application.get_env(:http, :user_agent) == [:default]
|
||||
end
|
||||
|
||||
test "saving config with partial update", %{conn: conn} do
|
||||
|
|
@ -1501,15 +1502,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
clear_config(:database_config_whitelist, [
|
||||
{:pleroma, :instance},
|
||||
{:pleroma, :activitypub},
|
||||
{:pleroma, Pleroma.Upload},
|
||||
{:esshd}
|
||||
{:pleroma, Pleroma.Upload}
|
||||
])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/config/descriptions")
|
||||
|
||||
children = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
assert length(children) == 4
|
||||
assert length(children) == 3
|
||||
|
||||
assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3
|
||||
|
||||
|
|
@ -1521,9 +1521,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
|
||||
web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end)
|
||||
assert web_endpoint["children"]
|
||||
|
||||
esshd = Enum.find(children, fn c -> c["group"] == ":esshd" end)
|
||||
assert esshd["children"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do
|
|||
"build_url" => "http://gensokyo.2hu/builds/${ref}",
|
||||
"git" => nil,
|
||||
"installed" => true,
|
||||
"installed_refs" => ["fantasy"],
|
||||
"name" => "pleroma",
|
||||
"ref" => "fantasy"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.InstanceControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
|
|
@ -31,6 +31,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceControllerTest do
|
|||
end
|
||||
|
||||
test "GET /instances/:instance/statuses", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme")
|
||||
user2 = insert(:user, local: false, ap_id: "https://test.com/users/test")
|
||||
insert_pair(:note_activity, user: user)
|
||||
|
|
@ -60,9 +61,14 @@ defmodule Pleroma.Web.AdminAPI.InstanceControllerTest do
|
|||
|> json_response(200)
|
||||
|
||||
assert length(activities) == 3
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(:forbidden)
|
||||
end
|
||||
|
||||
test "DELETE /instances/:instance", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:instances_delete])
|
||||
user = insert(:user, nickname: "lain@lain.com")
|
||||
post = insert(:note_activity, user: user)
|
||||
|
||||
|
|
@ -76,5 +82,11 @@ defmodule Pleroma.Web.AdminAPI.InstanceControllerTest do
|
|||
assert response == "lain.com"
|
||||
refute Repo.reload(user).is_active
|
||||
refute Repo.reload(post)
|
||||
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn
|
||||
|> delete("/api/pleroma/admin/instances/lain.com")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.InstanceDocumentControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Pleroma.Web.ConnCase
|
||||
import Pleroma.Factory
|
||||
|
||||
@dir "test/tmp/instance_static"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -23,8 +23,25 @@ defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
|
|||
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)
|
||||
setup do
|
||||
clear_config([:instance, :registrations_open], false)
|
||||
clear_config([:instance, :invites_enabled], true)
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_invites])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_manage_invites", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json;charset=utf-8")
|
||||
|> post("/api/pleroma/admin/users/email_invite", %{
|
||||
email: "foo@bar.com",
|
||||
name: "J. D."
|
||||
})
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "sends invitation and returns 204", %{admin: admin, conn: conn} do
|
||||
recipient_email = "foo@bar.com"
|
||||
|
|
@ -114,8 +131,11 @@ defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
|
|||
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])
|
||||
setup do
|
||||
clear_config([:instance, :registrations_open])
|
||||
clear_config([:instance, :invites_enabled])
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_invites])
|
||||
end
|
||||
|
||||
test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do
|
||||
clear_config([:instance, :registrations_open], false)
|
||||
|
|
@ -157,6 +177,21 @@ defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
|
|||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/users/invite_token" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_invites])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_manage_invites", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/invite_token")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "without options", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|
|
@ -221,6 +256,18 @@ defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
|
|||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/users/invites" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_invites])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_manage_invites", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users/invites")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "no invites", %{conn: conn} do
|
||||
conn = get(conn, "/api/pleroma/admin/users/invites")
|
||||
|
||||
|
|
@ -249,6 +296,21 @@ defmodule Pleroma.Web.AdminAPI.InviteControllerTest do
|
|||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/users/revoke_invite" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_invites])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_manage_invites", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "with token", %{conn: conn} do
|
||||
{:ok, invite} = UserInviteToken.create_invite()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@
|
|||
defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
setup do: clear_config([:media_proxy])
|
||||
|
|
@ -128,6 +130,9 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do
|
|||
"http://example.com/media/fb1f4d.jpg"
|
||||
]
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
with_mocks [
|
||||
{MediaProxy.Invalidation.Script, [],
|
||||
[
|
||||
|
|
@ -150,6 +155,9 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do
|
|||
"http://example.com/media/fb1f4d.jpg"
|
||||
]
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
with_mocks [{MediaProxy.Invalidation.Script, [], [purge: fn _, _ -> {"ok", 0} end]}] do
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -27,6 +27,20 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/reports/:id" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:reports_manage_reports])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :reports_manage_reports", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/reports/report_id")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "returns report by its id", %{conn: conn} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
|
@ -55,6 +69,32 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
assert notes["content"] == "this is an admin note"
|
||||
end
|
||||
|
||||
test "renders reported content even if the status is deleted", %{conn: conn} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
activity = Activity.normalize(activity)
|
||||
|
||||
{:ok, %{id: report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
CommonAPI.delete(activity.id, target_user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/reports/#{report_id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["id"] == report_id
|
||||
|
||||
assert [status] = response["statuses"]
|
||||
assert activity.object.data["id"] == status["uri"]
|
||||
assert activity.object.data["content"] == status["content"]
|
||||
end
|
||||
|
||||
test "returns 404 when report id is invalid", %{conn: conn} do
|
||||
conn = get(conn, "/api/pleroma/admin/reports/test")
|
||||
|
||||
|
|
@ -64,6 +104,8 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
|
||||
describe "PATCH /api/pleroma/admin/reports" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:reports_manage_reports])
|
||||
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
|
|
@ -82,11 +124,30 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
})
|
||||
|
||||
%{
|
||||
reporter: reporter,
|
||||
id: report_id,
|
||||
second_report_id: second_report_id
|
||||
}
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :reports_manage_reports", %{
|
||||
conn: conn,
|
||||
id: id,
|
||||
admin: admin
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:token, insert(:oauth_token, user: admin, scopes: ["admin:write:reports"]))
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/reports", %{
|
||||
"reports" => [%{"state" => "resolved", "id" => id}]
|
||||
})
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
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"])
|
||||
|
|
@ -207,9 +268,43 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
assert ModerationLog.get_log_entry_message(second_log_entry) ==
|
||||
"@#{admin.nickname} updated report ##{second_report_id} (on user @#{second_activity.user_actor.nickname}) with 'closed' state"
|
||||
end
|
||||
|
||||
test "works if reporter is deactivated", %{
|
||||
conn: conn,
|
||||
id: id,
|
||||
reporter: reporter
|
||||
} do
|
||||
Pleroma.User.set_activation(reporter, false)
|
||||
|
||||
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_with_user_actor(id)
|
||||
assert activity.data["state"] == "resolved"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/reports" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:reports_manage_reports])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :reports_manage_reports", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> get(report_path(conn, :index))
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "returns empty response when no reports created", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|
|
@ -293,6 +388,34 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "renders content correctly", %{conn: conn} do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
note = insert(:note, user: target_user, data: %{"content" => "mew 1"})
|
||||
note2 = insert(:note, user: target_user, data: %{"content" => "mew 2"})
|
||||
activity = insert(:note_activity, user: target_user, note: note)
|
||||
activity2 = insert(:note_activity, user: target_user, note: note2)
|
||||
|
||||
{:ok, _report} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id, activity2.id]
|
||||
})
|
||||
|
||||
CommonAPI.delete(activity.id, target_user)
|
||||
CommonAPI.delete(activity2.id, target_user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get(report_path(conn, :index))
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [open_report] = response["reports"]
|
||||
assert %{"statuses" => [s1, s2]} = open_report
|
||||
assert "mew 1" in [s1["content"], s2["content"]]
|
||||
assert "mew 2" in [s1["content"], s2["content"]]
|
||||
end
|
||||
|
||||
test "returns 403 when requested by a non-admin" do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user)
|
||||
|
|
@ -346,6 +469,8 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
|
||||
describe "POST /api/pleroma/admin/reports/:id/notes" do
|
||||
setup %{conn: conn, admin: admin} do
|
||||
clear_config([:instance, :admin_privileges], [:reports_manage_reports])
|
||||
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
|
|
@ -374,6 +499,25 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
|
|||
}
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :reports_manage_reports", %{
|
||||
conn: conn,
|
||||
report_id: report_id
|
||||
} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
post_conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
|
||||
content: "this is disgusting2!"
|
||||
})
|
||||
|
||||
delete_conn = delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/note.id")
|
||||
|
||||
assert json_response(post_conn, :forbidden)
|
||||
assert json_response(delete_conn, :forbidden)
|
||||
end
|
||||
|
||||
test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
|
||||
assert [note, _] = Repo.all(ReportNote)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
|
|
@ -26,6 +26,10 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/statuses/:id" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
end
|
||||
|
||||
test "not found", %{conn: conn} do
|
||||
assert conn
|
||||
|> get("/api/pleroma/admin/statuses/not_found")
|
||||
|
|
@ -50,10 +54,17 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
|
|||
assert account["is_active"] == actor.is_active
|
||||
assert account["is_confirmed"] == actor.is_confirmed
|
||||
end
|
||||
|
||||
test "denies reading activity when not privileged", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn |> get("/api/pleroma/admin/statuses/some_id") |> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /api/pleroma/admin/statuses/:id" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_delete])
|
||||
activity = insert(:note_activity)
|
||||
|
||||
%{id: activity.id}
|
||||
|
|
@ -122,10 +133,20 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
|
|||
assert %{"error" => "test - Invalid value for enum."} =
|
||||
json_response_and_validate_schema(conn, :bad_request)
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_delete", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> put("/api/pleroma/admin/statuses/some_id", %{})
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/pleroma/admin/statuses/:id" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_delete])
|
||||
activity = insert(:note_activity)
|
||||
|
||||
%{id: activity.id}
|
||||
|
|
@ -149,9 +170,22 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
|
|||
|
||||
assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"}
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_delete", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> delete("/api/pleroma/admin/statuses/some_id")
|
||||
|> json_response(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/statuses" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:messages_read])
|
||||
end
|
||||
|
||||
test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do
|
||||
blocked = insert(:user)
|
||||
user = insert(:user)
|
||||
|
|
@ -197,5 +231,13 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do
|
|||
conn = get(conn, "/api/pleroma/admin/statuses?godmode=true")
|
||||
assert json_response_and_validate_schema(conn, 200) |> length() == 3
|
||||
end
|
||||
|
||||
test "it requires privileged role :messages_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/statuses")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
use Pleroma.Web.ConnCase, async: false
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Mock
|
||||
|
|
@ -19,6 +19,11 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
alias Pleroma.Web.Endpoint
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
setup do
|
||||
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
|
||||
:ok
|
||||
end
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
|
|
@ -38,6 +43,7 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
end
|
||||
|
||||
test "with valid `admin_token` query parameter, skips OAuth scopes check" do
|
||||
clear_config([:instance, :admin_privileges], [:users_read])
|
||||
clear_config([:admin_token], "password123")
|
||||
|
||||
user = insert(:user)
|
||||
|
|
@ -47,53 +53,10 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
assert json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
|
||||
%{admin: admin} do
|
||||
user = insert(:user)
|
||||
url = "/api/pleroma/admin/users/#{user.nickname}"
|
||||
|
||||
good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
|
||||
good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
|
||||
good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
|
||||
|
||||
bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
|
||||
bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
|
||||
bad_token3 = nil
|
||||
|
||||
for good_token <- [good_token1, good_token2, good_token3] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, good_token)
|
||||
|> get(url)
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
for good_token <- [good_token1, good_token2, good_token3] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, nil)
|
||||
|> assign(:token, good_token)
|
||||
|> get(url)
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
for bad_token <- [bad_token1, bad_token2, bad_token3] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, bad_token)
|
||||
|> get(url)
|
||||
|
||||
assert json_response_and_validate_schema(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/pleroma/admin/users" do
|
||||
test "single user", %{admin: admin, conn: conn} do
|
||||
clear_config([:instance, :federating], true)
|
||||
clear_config([:instance, :admin_privileges], [:users_delete])
|
||||
|
||||
user =
|
||||
insert(:user,
|
||||
|
|
@ -149,6 +112,8 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
end
|
||||
|
||||
test "multiple users", %{admin: admin, conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_delete])
|
||||
|
||||
user_one = insert(:user)
|
||||
user_two = insert(:user)
|
||||
|
||||
|
|
@ -168,6 +133,17 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
|
||||
assert response -- [user_one.nickname, user_two.nickname] == []
|
||||
end
|
||||
|
||||
test "Needs privileged role", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> delete("/api/pleroma/admin/users?nickname=nickname")
|
||||
|
||||
assert json_response(response, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/users" do
|
||||
|
|
@ -307,7 +283,19 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/users/:nickname" do
|
||||
describe "GET /api/pleroma/admin/users/:nickname" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:users_read])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users/user.nickname")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "Show", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
@ -323,6 +311,50 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
|
||||
assert %{"error" => "Not found"} == json_response_and_validate_schema(conn, 404)
|
||||
end
|
||||
|
||||
test "requires admin:read:accounts or broader scope",
|
||||
%{admin: admin} do
|
||||
user = insert(:user)
|
||||
url = "/api/pleroma/admin/users/#{user.nickname}"
|
||||
|
||||
good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
|
||||
good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
|
||||
good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
|
||||
|
||||
bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
|
||||
bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
|
||||
bad_token3 = nil
|
||||
|
||||
for good_token <- [good_token1, good_token2, good_token3] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, good_token)
|
||||
|> get(url)
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
for good_token <- [good_token1, good_token2, good_token3] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, nil)
|
||||
|> assign(:token, good_token)
|
||||
|> get(url)
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
for bad_token <- [bad_token1, bad_token2, bad_token3] do
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, bad_token)
|
||||
|> get(url)
|
||||
|
||||
assert json_response_and_validate_schema(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/pleroma/admin/users/follow" do
|
||||
|
|
@ -378,6 +410,18 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/users" do
|
||||
setup do
|
||||
clear_config([:instance, :admin_privileges], [:users_read])
|
||||
end
|
||||
|
||||
test "returns 403 if not privileged with :users_read", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn = get(conn, "/api/pleroma/admin/users?page=1")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "renders users array for the first page", %{conn: conn, admin: admin} do
|
||||
user = insert(:user, local: false, tags: ["foo", "bar"])
|
||||
user2 = insert(:user, is_approved: false, registration_reason: "I'm a chill dude")
|
||||
|
|
@ -810,49 +854,9 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
|
||||
user_one = insert(:user, is_active: false)
|
||||
user_two = insert(:user, is_active: false)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/activate",
|
||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||
)
|
||||
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
assert Enum.map(response["users"], & &1["is_active"]) == [true, true]
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
|
||||
user_one = insert(:user, is_active: true)
|
||||
user_two = insert(:user, is_active: true)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/deactivate",
|
||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||
)
|
||||
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
assert Enum.map(response["users"], & &1["is_active"]) == [false, false]
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_invites])
|
||||
|
||||
user_one = insert(:user, is_approved: false)
|
||||
user_two = insert(:user, is_approved: false)
|
||||
|
||||
|
|
@ -873,6 +877,21 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
"@#{admin.nickname} approved users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/approve returns 403 if not privileged with :users_manage_invites",
|
||||
%{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/approve",
|
||||
%{nicknames: ["user_one.nickname", "user_two.nickname"]}
|
||||
)
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do
|
||||
user1 = insert(:user, is_suggested: false)
|
||||
user2 = insert(:user, is_suggested: false)
|
||||
|
|
@ -923,24 +942,113 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
"@#{admin.nickname} removed suggested users: @#{user1.nickname}, @#{user2.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
|
||||
user = insert(:user)
|
||||
describe "user activation" do
|
||||
test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
|
||||
user_one = insert(:user, is_active: false)
|
||||
user_two = insert(:user, is_active: false)
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) ==
|
||||
user_response(
|
||||
user,
|
||||
%{"is_active" => !user.is_active}
|
||||
)
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/activate",
|
||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||
)
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
assert Enum.map(response["users"], & &1["is_active"]) == [true, true]
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deactivated users: @#{user.nickname}"
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
|
||||
|
||||
user_one = insert(:user, is_active: true)
|
||||
user_two = insert(:user, is_active: true)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/deactivate",
|
||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||
)
|
||||
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
assert Enum.map(response["users"], & &1["is_active"]) == [false, false]
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||
end
|
||||
|
||||
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [:users_manage_activation_state])
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) ==
|
||||
user_response(
|
||||
user,
|
||||
%{"is_active" => !user.is_active}
|
||||
)
|
||||
|
||||
log_entry = Repo.one(ModerationLog)
|
||||
|
||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||
"@#{admin.nickname} deactivated users: @#{user.nickname}"
|
||||
end
|
||||
|
||||
test "it requires privileged role :statuses_activation to activate", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/activate",
|
||||
%{nicknames: ["user_one.nickname", "user_two.nickname"]}
|
||||
)
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "it requires privileged role :statuses_activation to deactivate", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch(
|
||||
"/api/pleroma/admin/users/deactivate",
|
||||
%{nicknames: ["user_one.nickname", "user_two.nickname"]}
|
||||
)
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
|
||||
test "it requires privileged role :statuses_activation to toggle activation", %{conn: conn} do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/pleroma/admin/users/user.nickname/toggle_activation")
|
||||
|
||||
assert json_response(conn, :forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
defp user_response(user, attrs \\ %{}) do
|
||||
|
|
|
|||
56
test/pleroma/web/api_spec/scopes/compiler_test.exs
Normal file
56
test/pleroma/web/api_spec/scopes/compiler_test.exs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.Scopes.CompilerTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pleroma.Web.ApiSpec.Scopes.Compiler
|
||||
|
||||
@dummy_response %{}
|
||||
|
||||
@data %{
|
||||
paths: %{
|
||||
"/mew" => %OpenApiSpex.PathItem{
|
||||
post: %OpenApiSpex.Operation{
|
||||
security: [%{"oAuth" => ["a:b:c"]}],
|
||||
responses: @dummy_response
|
||||
},
|
||||
get: %OpenApiSpex.Operation{security: nil, responses: @dummy_response}
|
||||
},
|
||||
"/mew2" => %OpenApiSpex.PathItem{
|
||||
post: %OpenApiSpex.Operation{
|
||||
security: [%{"oAuth" => ["d:e", "f:g"]}],
|
||||
responses: @dummy_response
|
||||
},
|
||||
get: %OpenApiSpex.Operation{security: nil, responses: @dummy_response}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe "process_scope/1" do
|
||||
test "gives all higher-level scopes" do
|
||||
scopes = Compiler.process_scope("admin:read:accounts")
|
||||
|
||||
assert [_, _, _] = scopes
|
||||
assert "admin" in scopes
|
||||
assert "admin:read" in scopes
|
||||
assert "admin:read:accounts" in scopes
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_all_scopes_from/1" do
|
||||
test "extracts scopes" do
|
||||
scopes = Compiler.extract_all_scopes_from(@data)
|
||||
|
||||
assert [_, _, _, _, _, _, _] = scopes
|
||||
assert "a" in scopes
|
||||
assert "a:b" in scopes
|
||||
assert "a:b:c" in scopes
|
||||
assert "d" in scopes
|
||||
assert "d:e" in scopes
|
||||
assert "f" in scopes
|
||||
assert "f:g" in scopes
|
||||
end
|
||||
end
|
||||
end
|
||||
33
test/pleroma/web/common_api/activity_draft_test.exs
Normal file
33
test/pleroma/web/common_api/activity_draft_test.exs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.CommonAPI.ActivityDraftTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.ActivityDraft
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "create/2 with a quote post" do
|
||||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, direct} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
{:ok, private} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
{:ok, unlisted} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
|
||||
{:ok, local} = CommonAPI.post(user, %{status: ".", visibility: "local"})
|
||||
{:ok, public} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
|
||||
{:error, _} = ActivityDraft.create(user, %{status: "nice", quote_id: direct.id})
|
||||
{:ok, _} = ActivityDraft.create(user, %{status: "nice", quote_id: private.id})
|
||||
{:error, _} = ActivityDraft.create(another_user, %{status: "nice", quote_id: private.id})
|
||||
{:ok, _} = ActivityDraft.create(user, %{status: "nice", quote_id: unlisted.id})
|
||||
{:ok, _} = ActivityDraft.create(another_user, %{status: "nice", quote_id: unlisted.id})
|
||||
{:ok, _} = ActivityDraft.create(user, %{status: "nice", quote_id: local.id})
|
||||
{:ok, _} = ActivityDraft.create(another_user, %{status: "nice", quote_id: local.id})
|
||||
{:ok, _} = ActivityDraft.create(user, %{status: "nice", quote_id: public.id})
|
||||
{:ok, _} = ActivityDraft.create(another_user, %{status: "nice", quote_id: public.id})
|
||||
end
|
||||
end
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
||||
alias Pleroma.Builders.UserBuilder
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.ActivityDraft
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
|
|
@ -179,6 +178,10 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
code = "https://github.com/pragdave/earmark/"
|
||||
{result, [], []} = Utils.format_input(code, "text/markdown")
|
||||
assert result == ~s[<p><a href="#{code}">#{code}</a></p>]
|
||||
|
||||
code = "https://github.com/~foo/bar"
|
||||
{result, [], []} = Utils.format_input(code, "text/markdown")
|
||||
assert result == ~s[<p><a href="#{code}">#{code}</a></p>]
|
||||
end
|
||||
|
||||
test "link with local mention" do
|
||||
|
|
@ -197,7 +200,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
{result, _, []} = Utils.format_input(code, "text/markdown")
|
||||
|
||||
assert result ==
|
||||
~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{mario.ap_id}" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{luigi.id}" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what’s up?</p>]
|
||||
~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{mario.ap_id}" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{luigi.id}" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what's up?</p>]
|
||||
end
|
||||
|
||||
test "remote mentions" do
|
||||
|
|
@ -208,7 +211,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
{result, _, []} = Utils.format_input(code, "text/markdown")
|
||||
|
||||
assert result ==
|
||||
~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{mario.ap_id}" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{luigi.id}" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what’s up?</p>]
|
||||
~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{mario.ap_id}" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{luigi.id}" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what's up?</p>]
|
||||
end
|
||||
|
||||
test "raw HTML" do
|
||||
|
|
@ -226,7 +229,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
test "blockquote" do
|
||||
code = ~s[> whoms't are you quoting?]
|
||||
{result, [], []} = Utils.format_input(code, "text/markdown")
|
||||
assert result == "<blockquote><p>whoms’t are you quoting?</p></blockquote>"
|
||||
assert result == "<blockquote><p>whoms't are you quoting?</p></blockquote>"
|
||||
end
|
||||
|
||||
test "code" do
|
||||
|
|
@ -273,22 +276,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
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()
|
||||
|
|
@ -517,17 +504,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
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)
|
||||
|
|
@ -610,41 +586,61 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "attachments_from_ids_descs/2" do
|
||||
describe "attachments_from_ids_descs/3" do
|
||||
test "returns [] when attachment ids is empty" do
|
||||
assert Utils.attachments_from_ids_descs([], "{}") == []
|
||||
assert Utils.attachments_from_ids_descs([], "{}", nil) == []
|
||||
end
|
||||
|
||||
test "returns list attachments with desc" do
|
||||
object = insert(:note)
|
||||
user = insert(:user)
|
||||
object = insert(:attachment, %{user: user})
|
||||
desc = Jason.encode!(%{object.id => "test-desc"})
|
||||
|
||||
assert Utils.attachments_from_ids_descs(["#{object.id}", "34"], desc) == [
|
||||
assert Utils.attachments_from_ids_descs(["#{object.id}", "34"], desc, user) == [
|
||||
Map.merge(object.data, %{"name" => "test-desc"})
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "attachments_from_ids/1" do
|
||||
describe "attachments_from_ids/2" do
|
||||
test "returns attachments with descs" do
|
||||
object = insert(:note)
|
||||
user = insert(:user)
|
||||
object = insert(:attachment, %{user: user})
|
||||
desc = Jason.encode!(%{object.id => "test-desc"})
|
||||
|
||||
assert Utils.attachments_from_ids(%{
|
||||
media_ids: ["#{object.id}"],
|
||||
descriptions: desc
|
||||
}) == [
|
||||
assert Utils.attachments_from_ids(
|
||||
%{
|
||||
media_ids: ["#{object.id}"],
|
||||
descriptions: desc
|
||||
},
|
||||
user
|
||||
) == [
|
||||
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]
|
||||
user = insert(:user)
|
||||
object = insert(:attachment, %{user: user})
|
||||
assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}, user) == [object.data]
|
||||
end
|
||||
|
||||
test "returns [] when not pass media_ids" do
|
||||
assert Utils.attachments_from_ids(%{}) == []
|
||||
assert Utils.attachments_from_ids(%{}, nil) == []
|
||||
end
|
||||
|
||||
test "returns [] when media_ids not belong to current user" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
object = insert(:attachment, %{user: user})
|
||||
|
||||
assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}, user2) == []
|
||||
end
|
||||
|
||||
test "checks that the object is of upload type" do
|
||||
object = insert(:note)
|
||||
assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}, nil) == []
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPITest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
use Pleroma.DataCase, async: false
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Chat
|
||||
|
|
@ -13,6 +13,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Rule
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
|
@ -21,9 +22,10 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.PollWorker
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mock
|
||||
import Ecto.Query, only: [from: 2]
|
||||
import Mock
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
|
|
@ -32,6 +34,13 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
:ok
|
||||
end
|
||||
|
||||
setup do
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Test.StaticConfig)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
setup do: clear_config([:instance, :safe_dm_mentions])
|
||||
setup do: clear_config([:instance, :limit])
|
||||
setup do: clear_config([:instance, :max_pinned_statuses])
|
||||
|
|
@ -62,9 +71,11 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
describe "blocking" do
|
||||
setup do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
User.follow(blocker, blocked)
|
||||
User.follow(blocked, blocker)
|
||||
blocked = insert(:user, local: false)
|
||||
CommonAPI.follow(blocker, blocked)
|
||||
CommonAPI.follow(blocked, blocker)
|
||||
CommonAPI.accept_follow_request(blocker, blocked)
|
||||
CommonAPI.accept_follow_request(blocked, blocked)
|
||||
%{blocker: blocker, blocked: blocked}
|
||||
end
|
||||
|
||||
|
|
@ -73,6 +84,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
assert User.get_follow_state(blocker, blocked) == :follow_accept
|
||||
refute is_nil(Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(blocker, blocked))
|
||||
|
||||
assert {:ok, block} = CommonAPI.block(blocker, blocked)
|
||||
|
||||
assert block.local
|
||||
|
|
@ -80,6 +94,11 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
refute User.following?(blocker, blocked)
|
||||
refute User.following?(blocked, blocker)
|
||||
|
||||
refute User.get_follow_state(blocker, blocked)
|
||||
|
||||
assert %{data: %{"state" => "reject"}} =
|
||||
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(blocker, blocked)
|
||||
|
||||
assert called(Pleroma.Web.Federator.publish(block))
|
||||
end
|
||||
end
|
||||
|
|
@ -270,6 +289,24 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
|
||||
CommonAPI.post_chat_message(author, recipient, "GNO/Linux")
|
||||
end
|
||||
|
||||
test "it reject messages with attachments not belonging to user" do
|
||||
author = insert(:user)
|
||||
not_author = insert(:user)
|
||||
recipient = author
|
||||
|
||||
attachment = insert(:attachment, %{user: not_author})
|
||||
|
||||
{:error, message} =
|
||||
CommonAPI.post_chat_message(
|
||||
author,
|
||||
recipient,
|
||||
"123",
|
||||
media_id: attachment.id
|
||||
)
|
||||
|
||||
assert message == :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
describe "unblocking" do
|
||||
|
|
@ -322,7 +359,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it does not allow a user to delete their posts" do
|
||||
test "it does not allow a user to delete posts from another user" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
|
|
@ -332,7 +369,8 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
assert Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it allows moderators to delete other user's posts" do
|
||||
test "it allows privileged users to delete other user's posts" do
|
||||
clear_config([:instance, :moderator_privileges], [:messages_delete])
|
||||
user = insert(:user)
|
||||
moderator = insert(:user, is_moderator: true)
|
||||
|
||||
|
|
@ -344,19 +382,20 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it allows admins to delete other user's posts" do
|
||||
test "it doesn't allow unprivileged mods or admins to delete other user's posts" do
|
||||
clear_config([:instance, :admin_privileges], [])
|
||||
clear_config([:instance, :moderator_privileges], [])
|
||||
user = insert(:user)
|
||||
moderator = insert(:user, is_admin: true)
|
||||
moderator = insert(:user, is_moderator: true, is_admin: true)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
|
||||
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
|
||||
assert delete.local
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
assert {:error, "Could not delete"} = CommonAPI.delete(post.id, moderator)
|
||||
assert Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "superusers deleting non-local posts won't federate the delete" do
|
||||
test "privileged users deleting non-local posts won't federate the delete" do
|
||||
clear_config([:instance, :admin_privileges], [:messages_delete])
|
||||
# This is the user of the ingested activity
|
||||
_user =
|
||||
insert(:user,
|
||||
|
|
@ -365,7 +404,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
last_refreshed_at: NaiveDateTime.utc_now()
|
||||
)
|
||||
|
||||
moderator = insert(:user, is_admin: true)
|
||||
admin = insert(:user, is_admin: true)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|
|
@ -375,13 +414,27 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, admin)
|
||||
assert delete.local
|
||||
refute called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "it allows privileged users to delete banned user's posts" do
|
||||
clear_config([:instance, :moderator_privileges], [:messages_delete])
|
||||
user = insert(:user)
|
||||
moderator = insert(:user, is_moderator: true)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
|
||||
User.set_activation(user, false)
|
||||
|
||||
assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
|
||||
assert delete.local
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
end
|
||||
|
||||
test "favoriting race condition" do
|
||||
|
|
@ -507,6 +560,36 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
assert Object.tags(object) == ["2hu"]
|
||||
end
|
||||
|
||||
test "zwnj is treated as word character" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#ساٴينس"})
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert Object.tags(object) == ["ساٴينس"]
|
||||
end
|
||||
|
||||
test "allows lang attribute" do
|
||||
user = insert(:user)
|
||||
text = ~s{<span lang="en">something</span><p lang="diaetuitech_rpyhpgc">random</p>}
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: text, content_type: "text/html"})
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert object.data["content"] == text
|
||||
end
|
||||
|
||||
test "double dot in link is allowed" do
|
||||
user = insert(:user)
|
||||
text = "https://example.to/something..mp3"
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: text})
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert object.data["content"] == "<a href=\"#{text}\" rel=\"ugc\">#{text}</a>"
|
||||
end
|
||||
|
||||
test "it adds emoji in the object" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: ":firefox:"})
|
||||
|
|
@ -587,7 +670,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||
assert object.data["source"] == post
|
||||
assert object.data["source"]["content"] == post
|
||||
end
|
||||
|
||||
test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||
|
|
@ -604,7 +687,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
assert object.data["content"] == "<p><b>2hu</b></p>"
|
||||
assert object.data["source"] == post
|
||||
assert object.data["source"]["content"] == post
|
||||
end
|
||||
|
||||
test "it does not allow replies to direct messages that are not direct messages themselves" do
|
||||
|
|
@ -723,6 +806,65 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
scheduled_at: expires_at
|
||||
)
|
||||
end
|
||||
|
||||
test "it allows quote posting" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, quoted} = CommonAPI.post(user, %{status: "Hello world"})
|
||||
{:ok, quote_post} = CommonAPI.post(user, %{status: "nice post", quote_id: quoted.id})
|
||||
|
||||
quoted = Object.normalize(quoted)
|
||||
quote_post = Object.normalize(quote_post)
|
||||
|
||||
assert quote_post.data["quoteUrl"] == quoted.data["id"]
|
||||
|
||||
# The OP is not mentioned
|
||||
refute quoted.data["actor"] in quote_post.data["to"]
|
||||
end
|
||||
|
||||
test "quote posting with explicit addressing doesn't mention the OP" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, quoted} = CommonAPI.post(user, %{status: "Hello world"})
|
||||
|
||||
{:ok, quote_post} =
|
||||
CommonAPI.post(user, %{status: "nice post", quote_id: quoted.id, to: []})
|
||||
|
||||
assert Object.normalize(quote_post).data["to"] == [Pleroma.Constants.as_public()]
|
||||
end
|
||||
|
||||
test "quote posting visibility" do
|
||||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, direct} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
{:ok, private} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
{:ok, unlisted} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"})
|
||||
{:ok, local} = CommonAPI.post(user, %{status: ".", visibility: "local"})
|
||||
{:ok, public} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
|
||||
{:error, _} = CommonAPI.post(user, %{status: "nice", quote_id: direct.id})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "nice", quote_id: private.id})
|
||||
{:error, _} = CommonAPI.post(another_user, %{status: "nice", quote_id: private.id})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "nice", quote_id: unlisted.id})
|
||||
{:ok, _} = CommonAPI.post(another_user, %{status: "nice", quote_id: unlisted.id})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "nice", quote_id: local.id})
|
||||
{:ok, _} = CommonAPI.post(another_user, %{status: "nice", quote_id: local.id})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "nice", quote_id: public.id})
|
||||
{:ok, _} = CommonAPI.post(another_user, %{status: "nice", quote_id: public.id})
|
||||
end
|
||||
|
||||
test "it properly mentions punycode domain" do
|
||||
user = insert(:user)
|
||||
|
||||
_mentioned_user =
|
||||
insert(:user, ap_id: "https://xn--i2raa.com/users/yyy", nickname: "yyy@xn--i2raa.com")
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "hey @yyy@xn--i2raa.com", content_type: "text/markdown"})
|
||||
|
||||
assert "https://xn--i2raa.com/users/yyy" in Object.normalize(activity).data["to"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "reactions" do
|
||||
|
|
@ -1091,10 +1233,11 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
target_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"})
|
||||
activity = Activity.normalize(activity)
|
||||
|
||||
reporter_ap_id = reporter.ap_id
|
||||
target_ap_id = target_user.ap_id
|
||||
activity_ap_id = activity.data["id"]
|
||||
reported_object_ap_id = activity.object.data["id"]
|
||||
comment = "foobar"
|
||||
|
||||
report_data = %{
|
||||
|
|
@ -1105,7 +1248,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
note_obj = %{
|
||||
"type" => "Note",
|
||||
"id" => activity_ap_id,
|
||||
"id" => reported_object_ap_id,
|
||||
"content" => "foobar",
|
||||
"published" => activity.object.data["published"],
|
||||
"actor" => AccountView.render("show.json", %{user: target_user})
|
||||
|
|
@ -1127,6 +1270,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
test "updates report state" do
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
object = Object.normalize(activity)
|
||||
|
||||
{:ok, %Activity{id: report_id}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
|
|
@ -1139,10 +1283,36 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
assert report.data["state"] == "resolved"
|
||||
|
||||
[reported_user, activity_id] = report.data["object"]
|
||||
[reported_user, object_id] = report.data["object"]
|
||||
|
||||
assert reported_user == target_user.ap_id
|
||||
assert activity_id == activity.data["id"]
|
||||
assert object_id == object.data["id"]
|
||||
end
|
||||
|
||||
test "updates report state, don't strip when report_strip_status is false" do
|
||||
clear_config([:instance, :report_strip_status], false)
|
||||
|
||||
[reporter, target_user] = insert_pair(:user)
|
||||
activity = insert(:note_activity, user: target_user)
|
||||
|
||||
{:ok, %Activity{id: report_id, data: report_data}} =
|
||||
CommonAPI.report(reporter, %{
|
||||
account_id: target_user.id,
|
||||
comment: "I feel offended",
|
||||
status_ids: [activity.id]
|
||||
})
|
||||
|
||||
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
||||
|
||||
assert report.data["state"] == "resolved"
|
||||
|
||||
[reported_user, reported_activity] = report.data["object"]
|
||||
|
||||
assert reported_user == target_user.ap_id
|
||||
assert is_map(reported_activity)
|
||||
|
||||
assert reported_activity["content"] ==
|
||||
report_data["object"] |> Enum.at(1) |> Map.get("content")
|
||||
end
|
||||
|
||||
test "does not update report state when state is unsupported" do
|
||||
|
|
@ -1297,7 +1467,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
test "cancels a pending follow for a remote user" do
|
||||
follower = insert(:user)
|
||||
followed = insert(:user, is_locked: true, local: false, ap_enabled: true)
|
||||
followed = insert(:user, is_locked: true, local: false)
|
||||
|
||||
assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(follower, followed)
|
||||
|
|
@ -1569,4 +1739,128 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "update/3" do
|
||||
test "updates a post" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1"})
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "updated 2"
|
||||
assert Map.get(updated_object.data, "summary", "") == ""
|
||||
assert Map.has_key?(updated_object.data, "updated")
|
||||
end
|
||||
|
||||
test "does not change visibility" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1", visibility: "private"})
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "updated 2"
|
||||
assert Map.get(updated_object.data, "summary", "") == ""
|
||||
assert Visibility.get_visibility(updated_object) == "private"
|
||||
assert Visibility.get_visibility(updated) == "private"
|
||||
end
|
||||
|
||||
test "updates a post with emoji" do
|
||||
[{emoji1, _}, {emoji2, _} | _] = Pleroma.Emoji.get_all()
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1 :#{emoji1}:"})
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2 :#{emoji2}:"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "updated 2 :#{emoji2}:"
|
||||
assert %{^emoji2 => _} = updated_object.data["emoji"]
|
||||
end
|
||||
|
||||
test "updates a post with emoji and federate properly" do
|
||||
[{emoji1, _}, {emoji2, _} | _] = Pleroma.Emoji.get_all()
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1 :#{emoji1}:"})
|
||||
|
||||
clear_config([:instance, :federating], true)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _p -> nil end do
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2 :#{emoji2}:"})
|
||||
|
||||
assert updated.data["object"]["content"] == "updated 2 :#{emoji2}:"
|
||||
assert %{^emoji2 => _} = updated.data["object"]["emoji"]
|
||||
|
||||
assert called(Pleroma.Web.Federator.publish(updated))
|
||||
end
|
||||
end
|
||||
|
||||
test "editing a post that copied a remote title with remote emoji should keep that emoji" do
|
||||
remote_emoji_uri = "https://remote.org/emoji.png"
|
||||
|
||||
note =
|
||||
insert(
|
||||
:note,
|
||||
data: %{
|
||||
"summary" => ":remoteemoji:",
|
||||
"emoji" => %{
|
||||
"remoteemoji" => remote_emoji_uri
|
||||
},
|
||||
"tag" => [
|
||||
%{
|
||||
"type" => "Emoji",
|
||||
"name" => "remoteemoji",
|
||||
"icon" => %{"url" => remote_emoji_uri}
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
note_activity = insert(:note_activity, note: note)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, reply} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "reply",
|
||||
spoiler_text: ":remoteemoji:",
|
||||
in_reply_to_id: note_activity.id
|
||||
})
|
||||
|
||||
assert reply.object.data["emoji"]["remoteemoji"] == remote_emoji_uri
|
||||
|
||||
{:ok, edit} =
|
||||
CommonAPI.update(user, reply, %{status: "reply mew mew", spoiler_text: ":remoteemoji:"})
|
||||
|
||||
edited_note = Pleroma.Object.normalize(edit)
|
||||
|
||||
assert edited_note.data["emoji"]["remoteemoji"] == remote_emoji_uri
|
||||
end
|
||||
|
||||
test "respects MRF" do
|
||||
user = insert(:user)
|
||||
|
||||
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
|
||||
clear_config([:mrf_keyword, :replace], [{"updated", "mewmew"}])
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foo1", spoiler_text: "updated 1"})
|
||||
assert Object.normalize(activity).data["summary"] == "mewmew 1"
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "mewmew 2"
|
||||
assert Map.get(updated_object.data, "summary", "") == ""
|
||||
assert Map.has_key?(updated_object.data, "updated")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Endpoint.MetricsExporterTest do
|
||||
# Modifies AppEnv, has to stay synchronous
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Web.Endpoint.MetricsExporter
|
||||
|
||||
defp config do
|
||||
Application.get_env(:prometheus, MetricsExporter)
|
||||
end
|
||||
|
||||
describe "with default config" do
|
||||
test "does NOT expose app metrics", %{conn: conn} do
|
||||
conn
|
||||
|> get(config()[:path])
|
||||
|> json_response(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when enabled" do
|
||||
setup do
|
||||
initial_config = config()
|
||||
on_exit(fn -> Application.put_env(:prometheus, MetricsExporter, initial_config) end)
|
||||
|
||||
Application.put_env(
|
||||
:prometheus,
|
||||
MetricsExporter,
|
||||
Keyword.put(initial_config, :enabled, true)
|
||||
)
|
||||
end
|
||||
|
||||
test "serves app metrics", %{conn: conn} do
|
||||
conn = get(conn, config()[:path])
|
||||
assert response = response(conn, 200)
|
||||
|
||||
for metric <- [
|
||||
"http_requests_total",
|
||||
"http_request_duration_microseconds",
|
||||
"phoenix_controller_call_duration",
|
||||
"telemetry_scrape_duration",
|
||||
"erlang_vm_memory_atom_bytes_total"
|
||||
] do
|
||||
assert response =~ ~r/#{metric}/
|
||||
end
|
||||
end
|
||||
|
||||
test "when IP whitelist configured, " <>
|
||||
"serves app metrics only if client IP is whitelisted",
|
||||
%{conn: conn} do
|
||||
Application.put_env(
|
||||
:prometheus,
|
||||
MetricsExporter,
|
||||
Keyword.put(config(), :ip_whitelist, ["127.127.127.127", {1, 1, 1, 1}, '255.255.255.255'])
|
||||
)
|
||||
|
||||
conn
|
||||
|> get(config()[:path])
|
||||
|> json_response(404)
|
||||
|
||||
conn
|
||||
|> Map.put(:remote_ip, {127, 127, 127, 127})
|
||||
|> get(config()[:path])
|
||||
|> response(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -6,20 +6,6 @@ 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
|
||||
|
||||
test "GET /*path adds a title", %{conn: conn} do
|
||||
clear_config([:instance, :name], "a cool title")
|
||||
|
||||
|
|
@ -29,21 +15,28 @@ defmodule Pleroma.Web.FallbackTest do
|
|||
end
|
||||
|
||||
describe "preloaded data and metadata attached to" do
|
||||
test "GET /:maybe_nickname_or_id", %{conn: conn} do
|
||||
test "GET /:maybe_nickname_or_id with existing user", %{conn: conn} do
|
||||
clear_config([:instance, :name], "a cool title")
|
||||
user = insert(:user)
|
||||
|
||||
resp = get(conn, "/#{user.nickname}")
|
||||
|
||||
assert html_response(resp, 200) =~ "<title>a cool title</title>"
|
||||
refute html_response(resp, 200) =~ "<!--server-generated-meta-->"
|
||||
assert html_response(resp, 200) =~ "initial-results"
|
||||
end
|
||||
|
||||
test "GET /:maybe_nickname_or_id with missing user", %{conn: conn} do
|
||||
clear_config([:instance, :name], "a cool title")
|
||||
|
||||
user = insert(:user)
|
||||
user_missing = get(conn, "/foo")
|
||||
user_present = get(conn, "/#{user.nickname}")
|
||||
resp = get(conn, "/foo")
|
||||
|
||||
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"
|
||||
assert html_response(user_present, 200) =~ "<title>a cool title</title>"
|
||||
assert html_response(resp, 200) =~ "<title>a cool title</title>"
|
||||
refute html_response(resp, 200) =~ "initial-results"
|
||||
end
|
||||
|
||||
test "GET /*path", %{conn: conn} do
|
||||
assert conn
|
||||
refute conn
|
||||
|> get("/foo")
|
||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
||||
|
||||
|
|
@ -65,10 +58,12 @@ defmodule Pleroma.Web.FallbackTest do
|
|||
end
|
||||
|
||||
test "GET /main/all", %{conn: conn} do
|
||||
clear_config([:instance, :name], "a cool title")
|
||||
public_page = get(conn, "/main/all")
|
||||
|
||||
refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
|
||||
assert html_response(public_page, 200) =~ "initial-results"
|
||||
assert html_response(public_page, 200) =~ "<title>a cool title</title>"
|
||||
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