Merge remote-tracking branch 'upstream/develop' into oauth-token-id
This commit is contained in:
commit
e7ac15905e
81 changed files with 2056 additions and 322 deletions
|
|
@ -254,4 +254,26 @@ defmodule Pleroma.ActivityTest do
|
|||
|
||||
assert %{id: ^id} = Activity.get_by_object_ap_id_with_object(obj_id)
|
||||
end
|
||||
|
||||
test "add_by_params_query/3" do
|
||||
user = insert(:user)
|
||||
|
||||
note = insert(:note_activity, user: user)
|
||||
|
||||
insert(:add_activity, user: user, note: note)
|
||||
insert(:add_activity, user: user, note: note)
|
||||
insert(:add_activity, user: user)
|
||||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 4
|
||||
|
||||
add_query =
|
||||
Activity.add_by_params_query(note.data["object"], user.ap_id, user.featured_address)
|
||||
|
||||
assert Repo.aggregate(add_query, :count, :id) == 2
|
||||
|
||||
Repo.delete_all(add_query)
|
||||
assert Repo.aggregate(add_query, :count, :id) == 0
|
||||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 2
|
||||
end
|
||||
end
|
||||
|
|
|
|||
45
test/pleroma/config/release_runtime_provider_test.exs
Normal file
45
test/pleroma/config/release_runtime_provider_test.exs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
defmodule Pleroma.Config.ReleaseRuntimeProviderTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pleroma.Config.ReleaseRuntimeProvider
|
||||
|
||||
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([], [])
|
||||
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
|
||||
merged =
|
||||
ReleaseRuntimeProvider.load([], config_path: "test/fixtures/config/temp.secret.exs")
|
||||
|
||||
assert merged[:pleroma][:first_setting] == [key: "value", key2: [Pleroma.Repo]]
|
||||
assert merged[:pleroma][:second_setting] == [key: "value2", key2: ["Activity"]]
|
||||
end
|
||||
|
||||
test "merged exported config" do
|
||||
ExUnit.CaptureIO.capture_io(fn ->
|
||||
merged =
|
||||
ReleaseRuntimeProvider.load([],
|
||||
exported_config_path: "test/fixtures/config/temp.exported_from_db.secret.exs"
|
||||
)
|
||||
|
||||
assert merged[:pleroma][:exported_config_merged]
|
||||
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 "runtime config is merged with exported config" do
|
||||
merged =
|
||||
ReleaseRuntimeProvider.load([],
|
||||
config_path: "test/fixtures/config/temp.secret.exs",
|
||||
exported_config_path: "test/fixtures/config/temp.exported_from_db.secret.exs"
|
||||
)
|
||||
|
||||
assert merged[:pleroma][:first_setting] == [key2: [Pleroma.Repo], key: "new value"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2338,4 +2338,49 @@ defmodule Pleroma.UserTest do
|
|||
assert User.active_user_count(6) == 3
|
||||
assert User.active_user_count(1) == 1
|
||||
end
|
||||
|
||||
describe "pins" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
[user: user, object_id: object_id_from_created_activity(user)]
|
||||
end
|
||||
|
||||
test "unique pins", %{user: user, object_id: object_id} do
|
||||
assert {:ok, %{pinned_objects: %{^object_id => pinned_at1} = pins} = updated_user} =
|
||||
User.add_pinned_object_id(user, object_id)
|
||||
|
||||
assert Enum.count(pins) == 1
|
||||
|
||||
assert {:ok, %{pinned_objects: %{^object_id => pinned_at2} = pins}} =
|
||||
User.add_pinned_object_id(updated_user, object_id)
|
||||
|
||||
assert pinned_at1 == pinned_at2
|
||||
|
||||
assert Enum.count(pins) == 1
|
||||
end
|
||||
|
||||
test "respects max_pinned_statuses limit", %{user: user, object_id: object_id} do
|
||||
clear_config([:instance, :max_pinned_statuses], 1)
|
||||
{:ok, updated} = User.add_pinned_object_id(user, object_id)
|
||||
|
||||
object_id2 = object_id_from_created_activity(user)
|
||||
|
||||
{:error, %{errors: errors}} = User.add_pinned_object_id(updated, object_id2)
|
||||
assert Keyword.has_key?(errors, :pinned_objects)
|
||||
end
|
||||
|
||||
test "remove_pinned_object_id/2", %{user: user, object_id: object_id} do
|
||||
assert {:ok, updated} = User.add_pinned_object_id(user, object_id)
|
||||
|
||||
{:ok, after_remove} = User.remove_pinned_object_id(updated, object_id)
|
||||
assert after_remove.pinned_objects == %{}
|
||||
end
|
||||
end
|
||||
|
||||
defp object_id_from_created_activity(user) do
|
||||
%{id: id} = insert(:note_activity, user: user)
|
||||
%{object: %{data: %{"id" => object_id}}} = Activity.get_by_id_with_object(id)
|
||||
object_id
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -636,6 +636,186 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|> post("/inbox", non_create_data)
|
||||
|> json_response(400)
|
||||
end
|
||||
|
||||
test "accepts Add/Remove activities", %{conn: conn} do
|
||||
object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
|
||||
|
||||
status =
|
||||
File.read!("test/fixtures/statuses/note.json")
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|> String.replace("{{object_id}}", object_id)
|
||||
|
||||
object_url = "https://example.com/objects/#{object_id}"
|
||||
|
||||
user =
|
||||
File.read!("test/fixtures/users_mock/user.json")
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|
||||
actor = "https://example.com/users/lain"
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^object_url
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: status,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: ^actor
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://example.com/users/lain/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/users_mock/masto_featured.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{nickname}}", "lain"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
data = %{
|
||||
"id" => "https://example.com/objects/d61d6733-e256-4fe1-ab13-1e369789423f",
|
||||
"actor" => actor,
|
||||
"object" => object_url,
|
||||
"target" => "https://example.com/users/lain/collections/featured",
|
||||
"type" => "Add",
|
||||
"to" => [Pleroma.Constants.as_public()]
|
||||
}
|
||||
|
||||
assert "ok" ==
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", data)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
assert Activity.get_by_ap_id(data["id"])
|
||||
user = User.get_cached_by_ap_id(data["actor"])
|
||||
assert user.pinned_objects[data["object"]]
|
||||
|
||||
data = %{
|
||||
"id" => "https://example.com/objects/d61d6733-e256-4fe1-ab13-1e369789423d",
|
||||
"actor" => actor,
|
||||
"object" => object_url,
|
||||
"target" => "https://example.com/users/lain/collections/featured",
|
||||
"type" => "Remove",
|
||||
"to" => [Pleroma.Constants.as_public()]
|
||||
}
|
||||
|
||||
assert "ok" ==
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", data)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
user = refresh_record(user)
|
||||
refute user.pinned_objects[data["object"]]
|
||||
end
|
||||
|
||||
test "mastodon pin/unpin", %{conn: conn} do
|
||||
status_id = "105786274556060421"
|
||||
|
||||
status =
|
||||
File.read!("test/fixtures/statuses/masto-note.json")
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|> String.replace("{{status_id}}", status_id)
|
||||
|
||||
status_url = "https://example.com/users/lain/statuses/#{status_id}"
|
||||
|
||||
user =
|
||||
File.read!("test/fixtures/users_mock/user.json")
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|
||||
actor = "https://example.com/users/lain"
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^status_url
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: status,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: ^actor
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://example.com/users/lain/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/users_mock/masto_featured.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{nickname}}", "lain"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"actor" => actor,
|
||||
"object" => status_url,
|
||||
"target" => "https://example.com/users/lain/collections/featured",
|
||||
"type" => "Add"
|
||||
}
|
||||
|
||||
assert "ok" ==
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", data)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
assert Activity.get_by_object_ap_id_with_object(data["object"])
|
||||
user = User.get_cached_by_ap_id(data["actor"])
|
||||
assert user.pinned_objects[data["object"]]
|
||||
|
||||
data = %{
|
||||
"actor" => actor,
|
||||
"object" => status_url,
|
||||
"target" => "https://example.com/users/lain/collections/featured",
|
||||
"type" => "Remove"
|
||||
}
|
||||
|
||||
assert "ok" ==
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", data)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
assert Activity.get_by_object_ap_id_with_object(data["object"])
|
||||
user = refresh_record(user)
|
||||
refute user.pinned_objects[data["object"]]
|
||||
end
|
||||
end
|
||||
|
||||
describe "/users/:nickname/inbox" do
|
||||
|
|
@ -1772,4 +1952,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|> json_response(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "pinned collection", %{conn: conn} do
|
||||
clear_config([:instance, :max_pinned_statuses], 2)
|
||||
user = insert(:user)
|
||||
objects = insert_list(2, :note, user: user)
|
||||
|
||||
Enum.reduce(objects, user, fn %{data: %{"id" => object_id}}, user ->
|
||||
{:ok, updated} = User.add_pinned_object_id(user, object_id)
|
||||
updated
|
||||
end)
|
||||
|
||||
%{nickname: nickname, featured_address: featured_address, pinned_objects: pinned_objects} =
|
||||
refresh_record(user)
|
||||
|
||||
%{"id" => ^featured_address, "orderedItems" => items} =
|
||||
conn
|
||||
|> get("/users/#{nickname}/collections/featured")
|
||||
|> json_response(200)
|
||||
|
||||
object_ids = Enum.map(items, & &1["id"])
|
||||
|
||||
assert Enum.all?(pinned_objects, fn {obj_id, _} ->
|
||||
obj_id in object_ids
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -235,6 +235,83 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}]
|
||||
}
|
||||
end
|
||||
|
||||
test "fetches user featured collection" do
|
||||
ap_id = "https://example.com/users/lain"
|
||||
|
||||
featured_url = "https://example.com/users/lain/collections/featured"
|
||||
|
||||
user_data =
|
||||
"test/fixtures/users_mock/user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("featured", featured_url)
|
||||
|> Jason.encode!()
|
||||
|
||||
object_id = Ecto.UUID.generate()
|
||||
|
||||
featured_data =
|
||||
"test/fixtures/mastodon/collections/featured.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|> String.replace("{{object_id}}", object_id)
|
||||
|
||||
object_url = "https://example.com/objects/#{object_id}"
|
||||
|
||||
object_data =
|
||||
"test/fixtures/statuses/note.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{object_id}}", object_id)
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^ap_id
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: ^featured_url
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: featured_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
Tesla.Mock.mock_global(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^object_url
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: object_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
{:ok, user} = ActivityPub.make_user_from_ap_id(ap_id)
|
||||
Process.sleep(50)
|
||||
|
||||
assert user.featured_address == featured_url
|
||||
assert Map.has_key?(user.pinned_objects, object_url)
|
||||
|
||||
in_db = Pleroma.User.get_by_ap_id(ap_id)
|
||||
assert in_db.featured_address == featured_url
|
||||
assert Map.has_key?(user.pinned_objects, object_url)
|
||||
|
||||
assert %{data: %{"id" => ^object_url}} = Object.get_by_ap_id(object_url)
|
||||
end
|
||||
end
|
||||
|
||||
test "it fetches the appropriate tag-restricted posts" do
|
||||
|
|
|
|||
126
test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs
Normal file
126
test/pleroma/web/activity_pub/mrf/follow_bot_policy_test.exs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
# 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.FollowBotPolicyTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.MRF.FollowBotPolicy
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "FollowBotPolicy" do
|
||||
test "follows remote users" do
|
||||
bot = insert(:user, actor_type: "Service")
|
||||
remote_user = insert(:user, local: false)
|
||||
clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => [remote_user.follower_address],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "Test post",
|
||||
"type" => "Note",
|
||||
"attributedTo" => remote_user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => remote_user.ap_id
|
||||
}
|
||||
|
||||
refute User.following?(bot, remote_user)
|
||||
|
||||
assert User.get_follow_requests(remote_user) |> length == 0
|
||||
|
||||
FollowBotPolicy.filter(message)
|
||||
|
||||
assert User.get_follow_requests(remote_user) |> length == 1
|
||||
end
|
||||
|
||||
test "does not follow users with #nobot in bio" do
|
||||
bot = insert(:user, actor_type: "Service")
|
||||
remote_user = insert(:user, %{local: false, bio: "go away bots! #nobot"})
|
||||
clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => [remote_user.follower_address],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "I don't like follow bots",
|
||||
"type" => "Note",
|
||||
"attributedTo" => remote_user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => remote_user.ap_id
|
||||
}
|
||||
|
||||
refute User.following?(bot, remote_user)
|
||||
|
||||
assert User.get_follow_requests(remote_user) |> length == 0
|
||||
|
||||
FollowBotPolicy.filter(message)
|
||||
|
||||
assert User.get_follow_requests(remote_user) |> length == 0
|
||||
end
|
||||
|
||||
test "does not follow local users" do
|
||||
bot = insert(:user, actor_type: "Service")
|
||||
local_user = insert(:user, local: true)
|
||||
clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => [local_user.follower_address],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "Hi I'm a local user",
|
||||
"type" => "Note",
|
||||
"attributedTo" => local_user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => local_user.ap_id
|
||||
}
|
||||
|
||||
refute User.following?(bot, local_user)
|
||||
|
||||
assert User.get_follow_requests(local_user) |> length == 0
|
||||
|
||||
FollowBotPolicy.filter(message)
|
||||
|
||||
assert User.get_follow_requests(local_user) |> length == 0
|
||||
end
|
||||
|
||||
test "does not follow users requiring follower approval" do
|
||||
bot = insert(:user, actor_type: "Service")
|
||||
remote_user = insert(:user, %{local: false, is_locked: true})
|
||||
clear_config([:mrf_follow_bot, :follower_nickname], bot.nickname)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => [remote_user.follower_address],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "I don't like randos following me",
|
||||
"type" => "Note",
|
||||
"attributedTo" => remote_user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => remote_user.ap_id
|
||||
}
|
||||
|
||||
refute User.following?(bot, remote_user)
|
||||
|
||||
assert User.get_follow_requests(remote_user) |> length == 0
|
||||
|
||||
FollowBotPolicy.filter(message)
|
||||
|
||||
assert User.get_follow_requests(remote_user) |> length == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -25,9 +25,6 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
|||
MRFMock
|
||||
|> expect(:pipeline_filter, fn o, m -> {:ok, o, m} end)
|
||||
|
||||
ActivityPubMock
|
||||
|> expect(:persist, fn o, m -> {:ok, o, m} end)
|
||||
|
||||
SideEffectsMock
|
||||
|> expect(:handle, fn o, m -> {:ok, o, m} end)
|
||||
|> expect(:handle_after_transaction, fn m -> m end)
|
||||
|
|
@ -42,6 +39,9 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
|||
|
||||
activity_with_object = %{activity | data: Map.put(activity.data, "object", object)}
|
||||
|
||||
ActivityPubMock
|
||||
|> expect(:persist, fn _, m -> {:ok, activity, m} end)
|
||||
|
||||
FederatorMock
|
||||
|> expect(:publish, fn ^activity_with_object -> :ok end)
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
|||
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(
|
||||
activity,
|
||||
activity.data,
|
||||
meta
|
||||
)
|
||||
end
|
||||
|
|
@ -59,6 +59,9 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
|||
activity = insert(:note_activity)
|
||||
meta = [local: true]
|
||||
|
||||
ActivityPubMock
|
||||
|> expect(:persist, fn _, m -> {:ok, activity, m} end)
|
||||
|
||||
FederatorMock
|
||||
|> expect(:publish, fn ^activity -> :ok end)
|
||||
|
||||
|
|
@ -66,29 +69,35 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
|||
|> expect(:get, fn [:instance, :federating] -> true end)
|
||||
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity.data, meta)
|
||||
end
|
||||
|
||||
test "it goes through validation, filtering, persisting, side effects without federation for remote activities" do
|
||||
activity = insert(:note_activity)
|
||||
meta = [local: false]
|
||||
|
||||
ActivityPubMock
|
||||
|> expect(:persist, fn _, m -> {:ok, activity, m} end)
|
||||
|
||||
ConfigMock
|
||||
|> expect(:get, fn [:instance, :federating] -> true end)
|
||||
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity.data, meta)
|
||||
end
|
||||
|
||||
test "it goes through validation, filtering, persisting, side effects without federation for local activities if federation is deactivated" do
|
||||
activity = insert(:note_activity)
|
||||
meta = [local: true]
|
||||
|
||||
ActivityPubMock
|
||||
|> expect(:persist, fn _, m -> {:ok, activity, m} end)
|
||||
|
||||
ConfigMock
|
||||
|> expect(:get, fn [:instance, :federating] -> false end)
|
||||
|
||||
assert {:ok, ^activity, ^meta} =
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity.data, meta)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
defmodule Pleroma.Web.ActivityPub.Transmogrifier.AddRemoveHandlingTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
test "it accepts Add/Remove activities" do
|
||||
user =
|
||||
"test/fixtures/users_mock/user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|
||||
object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
|
||||
|
||||
object =
|
||||
"test/fixtures/statuses/note.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "lain")
|
||||
|> String.replace("{{object_id}}", object_id)
|
||||
|
||||
object_url = "https://example.com/objects/#{object_id}"
|
||||
|
||||
actor = "https://example.com/users/lain"
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^actor
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: ^object_url
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: object,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://example.com/users/lain/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/users_mock/masto_featured.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{nickname}}", "lain"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
message = %{
|
||||
"id" => "https://example.com/objects/d61d6733-e256-4fe1-ab13-1e369789423f",
|
||||
"actor" => actor,
|
||||
"object" => object_url,
|
||||
"target" => "https://example.com/users/lain/collections/featured",
|
||||
"type" => "Add",
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"cc" => ["https://example.com/users/lain/followers"]
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
assert activity.data == message
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
assert user.pinned_objects[object_url]
|
||||
|
||||
remove = %{
|
||||
"id" => "http://localhost:400/objects/d61d6733-e256-4fe1-ab13-1e369789423d",
|
||||
"actor" => actor,
|
||||
"object" => object_url,
|
||||
"target" => "https://example.com/users/lain/collections/featured",
|
||||
"type" => "Remove",
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"cc" => ["https://example.com/users/lain/followers"]
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(remove)
|
||||
assert activity.data == remove
|
||||
|
||||
user = refresh_record(user)
|
||||
refute user.pinned_objects[object_url]
|
||||
end
|
||||
|
||||
test "Add/Remove activities for remote users without featured address" do
|
||||
user = insert(:user, local: false, domain: "example.com")
|
||||
|
||||
user =
|
||||
user
|
||||
|> Ecto.Changeset.change(featured_address: nil)
|
||||
|> Repo.update!()
|
||||
|
||||
%{host: host} = URI.parse(user.ap_id)
|
||||
|
||||
user_data =
|
||||
"test/fixtures/users_mock/user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", user.nickname)
|
||||
|
||||
object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
|
||||
|
||||
object =
|
||||
"test/fixtures/statuses/note.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", user.nickname)
|
||||
|> String.replace("{{object_id}}", object_id)
|
||||
|
||||
object_url = "https://#{host}/objects/#{object_id}"
|
||||
|
||||
actor = "https://#{host}/users/#{user.nickname}"
|
||||
|
||||
featured = "https://#{host}/users/#{user.nickname}/collections/featured"
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^actor
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: ^object_url
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: object,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{method: :get, url: ^featured} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/users_mock/masto_featured.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "#{host}")
|
||||
|> String.replace("{{nickname}}", user.nickname),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
message = %{
|
||||
"id" => "https://#{host}/objects/d61d6733-e256-4fe1-ab13-1e369789423f",
|
||||
"actor" => actor,
|
||||
"object" => object_url,
|
||||
"target" => "https://#{host}/users/#{user.nickname}/collections/featured",
|
||||
"type" => "Add",
|
||||
"to" => [Pleroma.Constants.as_public()],
|
||||
"cc" => ["https://#{host}/users/#{user.nickname}/followers"]
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
assert activity.data == message
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
assert user.pinned_objects[object_url]
|
||||
end
|
||||
end
|
||||
|
|
@ -1410,6 +1410,82 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
"need_reboot" => false
|
||||
}
|
||||
end
|
||||
|
||||
test "custom instance thumbnail", %{conn: conn} do
|
||||
clear_config([:instance])
|
||||
|
||||
params = %{
|
||||
"group" => ":pleroma",
|
||||
"key" => ":instance",
|
||||
"value" => [
|
||||
%{
|
||||
"tuple" => [
|
||||
":instance_thumbnail",
|
||||
"https://example.com/media/new_thumbnail.jpg"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
res =
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/config", %{"configs" => [params]})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert res == %{
|
||||
"configs" => [
|
||||
%{
|
||||
"db" => [":instance_thumbnail"],
|
||||
"group" => ":pleroma",
|
||||
"key" => ":instance",
|
||||
"value" => params["value"]
|
||||
}
|
||||
],
|
||||
"need_reboot" => false
|
||||
}
|
||||
|
||||
_res =
|
||||
assert conn
|
||||
|> get("/api/v1/instance")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert res = %{"thumbnail" => "https://example.com/media/new_thumbnail.jpg"}
|
||||
end
|
||||
|
||||
test "Concurrent Limiter", %{conn: conn} do
|
||||
clear_config([ConcurrentLimiter])
|
||||
|
||||
params = %{
|
||||
"group" => ":pleroma",
|
||||
"key" => "ConcurrentLimiter",
|
||||
"value" => [
|
||||
%{
|
||||
"tuple" => [
|
||||
"Pleroma.Web.RichMedia.Helpers",
|
||||
[
|
||||
%{"tuple" => [":max_running", 6]},
|
||||
%{"tuple" => [":max_waiting", 6]}
|
||||
]
|
||||
]
|
||||
},
|
||||
%{
|
||||
"tuple" => [
|
||||
"Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy",
|
||||
[
|
||||
%{"tuple" => [":max_running", 7]},
|
||||
%{"tuple" => [":max_waiting", 7]}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/config", %{"configs" => [params]})
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/config/descriptions" do
|
||||
|
|
|
|||
|
|
@ -827,13 +827,17 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
[user: user, activity: activity]
|
||||
end
|
||||
|
||||
test "activity not found error", %{user: user} do
|
||||
assert {:error, :not_found} = CommonAPI.pin("id", user)
|
||||
end
|
||||
|
||||
test "pin status", %{user: user, activity: activity} do
|
||||
assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
|
||||
|
||||
id = activity.id
|
||||
%{data: %{"id" => object_id}} = Object.normalize(activity)
|
||||
user = refresh_record(user)
|
||||
|
||||
assert %User{pinned_activities: [^id]} = user
|
||||
assert user.pinned_objects |> Map.keys() == [object_id]
|
||||
end
|
||||
|
||||
test "pin poll", %{user: user} do
|
||||
|
|
@ -845,10 +849,11 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
|
||||
|
||||
id = activity.id
|
||||
%{data: %{"id" => object_id}} = Object.normalize(activity)
|
||||
|
||||
user = refresh_record(user)
|
||||
|
||||
assert %User{pinned_activities: [^id]} = user
|
||||
assert user.pinned_objects |> Map.keys() == [object_id]
|
||||
end
|
||||
|
||||
test "unlisted statuses can be pinned", %{user: user} do
|
||||
|
|
@ -859,7 +864,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
test "only self-authored can be pinned", %{activity: activity} do
|
||||
user = insert(:user)
|
||||
|
||||
assert {:error, "Could not pin"} = CommonAPI.pin(activity.id, user)
|
||||
assert {:error, :ownership_error} = CommonAPI.pin(activity.id, user)
|
||||
end
|
||||
|
||||
test "max pinned statuses", %{user: user, activity: activity_one} do
|
||||
|
|
@ -869,8 +874,12 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
user = refresh_record(user)
|
||||
|
||||
assert {:error, "You have already pinned the maximum number of statuses"} =
|
||||
CommonAPI.pin(activity_two.id, user)
|
||||
assert {:error, :pinned_statuses_limit_reached} = CommonAPI.pin(activity_two.id, user)
|
||||
end
|
||||
|
||||
test "only public can be pinned", %{user: user} do
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "private status", visibility: "private"})
|
||||
{:error, :visibility_error} = CommonAPI.pin(activity.id, user)
|
||||
end
|
||||
|
||||
test "unpin status", %{user: user, activity: activity} do
|
||||
|
|
@ -884,7 +893,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
user = refresh_record(user)
|
||||
|
||||
assert %User{pinned_activities: []} = user
|
||||
assert user.pinned_objects == %{}
|
||||
end
|
||||
|
||||
test "should unpin when deleting a status", %{user: user, activity: activity} do
|
||||
|
|
@ -896,7 +905,40 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
user = refresh_record(user)
|
||||
|
||||
assert %User{pinned_activities: []} = user
|
||||
assert user.pinned_objects == %{}
|
||||
end
|
||||
|
||||
test "ephemeral activity won't be deleted if was pinned", %{user: user} do
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Hello!", expires_in: 601})
|
||||
|
||||
assert Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity.id)
|
||||
|
||||
{:ok, _activity} = CommonAPI.pin(activity.id, user)
|
||||
refute Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity.id)
|
||||
|
||||
user = refresh_record(user)
|
||||
{:ok, _} = CommonAPI.unpin(activity.id, user)
|
||||
|
||||
# recreates expiration job on unpin
|
||||
assert Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity.id)
|
||||
end
|
||||
|
||||
test "ephemeral activity deletion job won't be deleted on pinning error", %{
|
||||
user: user,
|
||||
activity: activity
|
||||
} do
|
||||
clear_config([:instance, :max_pinned_statuses], 1)
|
||||
|
||||
{:ok, _activity} = CommonAPI.pin(activity.id, user)
|
||||
|
||||
{:ok, activity2} = CommonAPI.post(user, %{status: "another status", expires_in: 601})
|
||||
|
||||
assert Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity2.id)
|
||||
|
||||
user = refresh_record(user)
|
||||
{:error, :pinned_statuses_limit_reached} = CommonAPI.pin(activity2.id, user)
|
||||
|
||||
assert Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity2.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1209,20 +1209,27 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
setup do: clear_config([:instance, :max_pinned_statuses], 1)
|
||||
|
||||
test "pin status", %{conn: conn, user: user, activity: activity} do
|
||||
id_str = to_string(activity.id)
|
||||
id = activity.id
|
||||
|
||||
assert %{"id" => ^id_str, "pinned" => true} =
|
||||
assert %{"id" => ^id, "pinned" => true} =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses/#{activity.id}/pin")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id_str, "pinned" => true}] =
|
||||
assert [%{"id" => ^id, "pinned" => true}] =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "non authenticated user", %{activity: activity} do
|
||||
assert build_conn()
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses/#{activity.id}/pin")
|
||||
|> json_response(403) == %{"error" => "Invalid credentials."}
|
||||
end
|
||||
|
||||
test "/pin: returns 400 error when activity is not public", %{conn: conn, user: user} do
|
||||
{:ok, dm} = CommonAPI.post(user, %{status: "test", visibility: "direct"})
|
||||
|
||||
|
|
@ -1231,7 +1238,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses/#{dm.id}/pin")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 400) == %{"error" => "Could not pin"}
|
||||
assert json_response_and_validate_schema(conn, 422) == %{
|
||||
"error" => "Non-public status cannot be pinned"
|
||||
}
|
||||
end
|
||||
|
||||
test "pin by another user", %{activity: activity} do
|
||||
%{conn: conn} = oauth_access(["write:accounts"])
|
||||
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses/#{activity.id}/pin")
|
||||
|> json_response(422) == %{"error" => "Someone else's status cannot be pinned"}
|
||||
end
|
||||
|
||||
test "unpin status", %{conn: conn, user: user, activity: activity} do
|
||||
|
|
@ -1252,13 +1270,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "/unpin: returns 400 error when activity is not exist", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses/1/unpin")
|
||||
|
||||
assert json_response_and_validate_schema(conn, 400) == %{"error" => "Could not unpin"}
|
||||
test "/unpin: returns 404 error when activity doesn't exist", %{conn: conn} do
|
||||
assert conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses/1/unpin")
|
||||
|> json_response_and_validate_schema(404) == %{"error" => "Record not found"}
|
||||
end
|
||||
|
||||
test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
|
||||
|
|
|
|||
|
|
@ -286,7 +286,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
direct_conversation_id: nil,
|
||||
thread_muted: false,
|
||||
emoji_reactions: [],
|
||||
parent_visible: false
|
||||
parent_visible: false,
|
||||
pinned_at: nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,16 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
|||
body: File.read!("test/fixtures/tesla_mock/status.emelie.json")
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://mastodon.social/users/emelie/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "mastodon.social")
|
||||
|> String.replace("{{nickname}}", "emelie")
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://mastodon.social/users/emelie"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
|
|
@ -52,6 +62,16 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
|||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: File.read!("test/fixtures/tesla_mock/emelie.json")
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://mastodon.social/users/emelie/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "mastodon.social")
|
||||
|> String.replace("{{nickname}}", "emelie")
|
||||
}
|
||||
end)
|
||||
|
||||
response =
|
||||
|
|
@ -70,6 +90,16 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
|||
headers: [{"content-type", "application/activity+json"}],
|
||||
body: File.read!("test/fixtures/tesla_mock/emelie.json")
|
||||
}
|
||||
|
||||
%{method: :get, url: "https://mastodon.social/users/emelie/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "mastodon.social")
|
||||
|> String.replace("{{nickname}}", "emelie")
|
||||
}
|
||||
end)
|
||||
|
||||
user = insert(:user)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue