Merge remote-tracking branch 'upstream/develop' into registration-workflow
This commit is contained in:
commit
30ed7b502f
288 changed files with 3775 additions and 3624 deletions
67
test/fixtures/mastodon/application_actor.json
vendored
Normal file
67
test/fixtures/mastodon/application_actor.json
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
"IdentityProof": "toot:IdentityProof",
|
||||
"discoverable": "toot:discoverable",
|
||||
"Device": "toot:Device",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"Curve25519Key": "toot:Curve25519Key",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"deviceId": "toot:deviceId",
|
||||
"claim": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:claim"
|
||||
},
|
||||
"fingerprintKey": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:fingerprintKey"
|
||||
},
|
||||
"identityKey": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:identityKey"
|
||||
},
|
||||
"devices": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:devices"
|
||||
},
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"messageType": "toot:messageType",
|
||||
"cipherText": "toot:cipherText"
|
||||
}
|
||||
],
|
||||
"id": "https://{{DOMAIN}}/actor",
|
||||
"type": "Application",
|
||||
"inbox": "https://{{DOMAIN}}/actor/inbox",
|
||||
"preferredUsername": "{{DOMAIN}}",
|
||||
"url": "https://{{DOMAIN}}/about/more?instance_actor=true",
|
||||
"manuallyApprovesFollowers": true,
|
||||
"publicKey": {
|
||||
"id": "https://{{DOMAIN}}/actor#main-key",
|
||||
"owner": "https://{{DOMAIN}}/actor",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAA0CA08AMIIBCgKCAQEAyi2T2FFZJgRPY+96YQrn\n6J6eF2P60J+nz+/pRc/acv/Nx+NLxxPyXby0F2s60MV7uALRQbBBnf7oNKCd/T4S\nvbr7UXMCWTdaJBpYubMKWT9uBlaUUkUfqL+WTV+IQnlcKtssQ4+AwrAKAZXza8ws\nZypevOsLHzayyEzztmm1KQC9GCUOITCLf7Q6qEhy8z/HuqLBEC0Own0pD7QsbfcS\no1peuZY7g1E/jJ9HR9GqJccMaR0H28KmJ7tT1Yzlyf5uZMRIdPxsoMR9sGLjR2B8\noegSwaf9SogR3ScP395Tt/9Ud1VVzuhpoS8Uy7jKSs+3CuLJsEGoMrib8VyOwadS\n9wIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://{{DOMAIN}}/inbox"
|
||||
}
|
||||
}
|
||||
|
|
@ -231,4 +231,20 @@ defmodule Pleroma.ActivityTest do
|
|||
|
||||
assert [%Activity{id: ^id1}, %Activity{id: ^id2}] = activities
|
||||
end
|
||||
|
||||
test "get_by_object_ap_id_with_object/1" do
|
||||
user = insert(:user)
|
||||
another = insert(:user)
|
||||
|
||||
{:ok, %{id: id, object: %{data: %{"id" => obj_id}}}} =
|
||||
Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
|
||||
|
||||
Pleroma.Web.CommonAPI.favorite(another, id)
|
||||
|
||||
assert obj_id
|
||||
|> Pleroma.Activity.Queries.by_object_id()
|
||||
|> Repo.aggregate(:count, :id) == 2
|
||||
|
||||
assert %{id: ^id} = Activity.get_by_object_ap_id_with_object(obj_id)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ defmodule Pleroma.Config.DeprecationWarningsTest do
|
|||
alias Pleroma.Config.DeprecationWarnings
|
||||
|
||||
test "check_old_mrf_config/0" do
|
||||
clear_config([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.NoOpPolicy)
|
||||
clear_config([:instance, :rewrite_policy], [])
|
||||
clear_config([:instance, :mrf_transparency], true)
|
||||
clear_config([:instance, :mrf_transparency_exclusions], [])
|
||||
|
||||
|
|
|
|||
72
test/pleroma/frontend_test.exs
Normal file
72
test/pleroma/frontend_test.exs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.FrontendTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Frontend
|
||||
|
||||
@dir "test/frontend_static_test"
|
||||
|
||||
setup do
|
||||
File.mkdir_p!(@dir)
|
||||
clear_config([:instance, :static_dir], @dir)
|
||||
|
||||
on_exit(fn ->
|
||||
File.rm_rf(@dir)
|
||||
end)
|
||||
end
|
||||
|
||||
test "it downloads and unzips a known frontend" do
|
||||
clear_config([:frontends, :available], %{
|
||||
"pleroma" => %{
|
||||
"ref" => "fantasy",
|
||||
"name" => "pleroma",
|
||||
"build_url" => "http://gensokyo.2hu/builds/${ref}"
|
||||
}
|
||||
})
|
||||
|
||||
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} ->
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")}
|
||||
end)
|
||||
|
||||
Frontend.install("pleroma")
|
||||
|
||||
assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
|
||||
end
|
||||
|
||||
test "it also works given a file" do
|
||||
clear_config([:frontends, :available], %{
|
||||
"pleroma" => %{
|
||||
"ref" => "fantasy",
|
||||
"name" => "pleroma",
|
||||
"build_dir" => ""
|
||||
}
|
||||
})
|
||||
|
||||
folder = Path.join([@dir, "frontends", "pleroma", "fantasy"])
|
||||
previously_existing = Path.join([folder, "temp"])
|
||||
File.mkdir_p!(folder)
|
||||
File.write!(previously_existing, "yey")
|
||||
assert File.exists?(previously_existing)
|
||||
|
||||
Frontend.install("pleroma", file: "test/fixtures/tesla_mock/frontend.zip")
|
||||
|
||||
assert File.exists?(Path.join([folder, "test.txt"]))
|
||||
refute File.exists?(previously_existing)
|
||||
end
|
||||
|
||||
test "it downloads and unzips unknown frontends" do
|
||||
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")}
|
||||
end)
|
||||
|
||||
Frontend.install("unknown",
|
||||
ref: "baka",
|
||||
build_url: "http://gensokyo.2hu/madeup.zip",
|
||||
build_dir: ""
|
||||
)
|
||||
|
||||
assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"]))
|
||||
end
|
||||
end
|
||||
|
|
@ -65,12 +65,13 @@ defmodule Pleroma.UserSearchTest do
|
|||
assert found_user.id == user.id
|
||||
end
|
||||
|
||||
test "excludes users when discoverable is false" do
|
||||
# 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})
|
||||
insert(:user, %{nickname: "john 3001"})
|
||||
|
||||
users = User.search("john")
|
||||
assert Enum.count(users) == 1
|
||||
assert Enum.count(users) == 2
|
||||
end
|
||||
|
||||
test "excludes service actors from results" do
|
||||
|
|
|
|||
|
|
@ -213,6 +213,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
end
|
||||
|
||||
describe "/objects/:uuid" do
|
||||
test "it doesn't return a local-only object", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "test", visibility: "local"})
|
||||
|
||||
assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post)
|
||||
|
||||
object = Object.normalize(post, false)
|
||||
uuid = String.split(object.data["id"], "/") |> List.last()
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> get("/objects/#{uuid}")
|
||||
|
||||
assert json_response(conn, 404)
|
||||
end
|
||||
|
||||
test "it returns a json representation of the object with accept application/json", %{
|
||||
conn: conn
|
||||
} do
|
||||
|
|
@ -326,6 +343,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
end
|
||||
|
||||
describe "/activities/:uuid" do
|
||||
test "it doesn't return a local-only activity", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "test", visibility: "local"})
|
||||
|
||||
assert Pleroma.Web.ActivityPub.Visibility.is_local_public?(post)
|
||||
|
||||
uuid = String.split(post.data["id"], "/") |> List.last()
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "application/json")
|
||||
|> get("/activities/#{uuid}")
|
||||
|
||||
assert json_response(conn, 404)
|
||||
end
|
||||
|
||||
test "it returns a json representation of the activity", %{conn: conn} do
|
||||
activity = insert(:note_activity)
|
||||
uuid = String.split(activity.data["id"], "/") |> List.last()
|
||||
|
|
@ -766,6 +799,142 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|
||||
assert json_response(ret_conn, 200)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "forwarded report", %{conn: conn} do
|
||||
admin = insert(:user, is_admin: true)
|
||||
actor = insert(:user, local: false)
|
||||
remote_domain = URI.parse(actor.ap_id).host
|
||||
reported_user = insert(:user)
|
||||
|
||||
note = insert(:note_activity, user: reported_user)
|
||||
|
||||
data = %{
|
||||
"@context" => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://#{remote_domain}/schemas/litepub-0.1.jsonld",
|
||||
%{
|
||||
"@language" => "und"
|
||||
}
|
||||
],
|
||||
"actor" => actor.ap_id,
|
||||
"cc" => [
|
||||
reported_user.ap_id
|
||||
],
|
||||
"content" => "test",
|
||||
"context" => "context",
|
||||
"id" => "http://#{remote_domain}/activities/02be56cf-35e3-46b4-b2c6-47ae08dfee9e",
|
||||
"nickname" => reported_user.nickname,
|
||||
"object" => [
|
||||
reported_user.ap_id,
|
||||
%{
|
||||
"actor" => %{
|
||||
"actor_type" => "Person",
|
||||
"approval_pending" => false,
|
||||
"avatar" => "",
|
||||
"confirmation_pending" => false,
|
||||
"deactivated" => false,
|
||||
"display_name" => "test user",
|
||||
"id" => reported_user.id,
|
||||
"local" => false,
|
||||
"nickname" => reported_user.nickname,
|
||||
"registration_reason" => nil,
|
||||
"roles" => %{
|
||||
"admin" => false,
|
||||
"moderator" => false
|
||||
},
|
||||
"tags" => [],
|
||||
"url" => reported_user.ap_id
|
||||
},
|
||||
"content" => "",
|
||||
"id" => note.data["id"],
|
||||
"published" => note.data["published"],
|
||||
"type" => "Note"
|
||||
}
|
||||
],
|
||||
"published" => note.data["published"],
|
||||
"state" => "open",
|
||||
"to" => [],
|
||||
"type" => "Flag"
|
||||
}
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{reported_user.nickname}/inbox", data)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
|
||||
assert Pleroma.Repo.aggregate(Activity, :count, :id) == 2
|
||||
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
to: {admin.name, admin.email},
|
||||
html_body: ~r/Reported Account:/i
|
||||
)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "forwarded report from mastodon", %{conn: conn} do
|
||||
admin = insert(:user, is_admin: true)
|
||||
actor = insert(:user, local: false)
|
||||
remote_domain = URI.parse(actor.ap_id).host
|
||||
remote_actor = "https://#{remote_domain}/actor"
|
||||
[reported_user, another] = insert_list(2, :user)
|
||||
|
||||
note = insert(:note_activity, user: reported_user)
|
||||
|
||||
Pleroma.Web.CommonAPI.favorite(another, note.id)
|
||||
|
||||
mock_json_body =
|
||||
"test/fixtures/mastodon/application_actor.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{DOMAIN}}", remote_domain)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^remote_actor} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: mock_json_body,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"actor" => remote_actor,
|
||||
"content" => "test report",
|
||||
"id" => "https://#{remote_domain}/e3b12fd1-948c-446e-b93b-a5e67edbe1d8",
|
||||
"nickname" => reported_user.nickname,
|
||||
"object" => [
|
||||
reported_user.ap_id,
|
||||
note.data["object"]
|
||||
],
|
||||
"type" => "Flag"
|
||||
}
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{reported_user.nickname}/inbox", data)
|
||||
|> json_response(200)
|
||||
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
|
||||
flag_activity = "Flag" |> Pleroma.Activity.Queries.by_type() |> Pleroma.Repo.one()
|
||||
reported_user_ap_id = reported_user.ap_id
|
||||
|
||||
[^reported_user_ap_id, flag_data] = flag_activity.data["object"]
|
||||
|
||||
Enum.each(~w(actor content id published type), &Map.has_key?(flag_data, &1))
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
Swoosh.TestAssertions.assert_email_sent(
|
||||
to: {admin.name, admin.email},
|
||||
html_body: ~r/#{note.data["object"]}/i
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /users/:nickname/outbox" do
|
||||
|
|
|
|||
|
|
@ -1298,6 +1298,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
assert_called(Utils.maybe_federate(%{activity | data: new_data}))
|
||||
end
|
||||
|
||||
test_with_mock "reverts on error",
|
||||
%{
|
||||
reporter: reporter,
|
||||
context: context,
|
||||
target_account: target_account,
|
||||
reported_activity: reported_activity,
|
||||
content: content
|
||||
},
|
||||
Utils,
|
||||
[:passthrough],
|
||||
maybe_federate: fn _ -> {:error, :reverted} end do
|
||||
assert {:error, :reverted} =
|
||||
ActivityPub.flag(%{
|
||||
actor: reporter,
|
||||
context: context,
|
||||
account: target_account,
|
||||
statuses: [reported_activity],
|
||||
content: content
|
||||
})
|
||||
|
||||
assert Repo.aggregate(Activity, :count, :id) == 1
|
||||
assert Repo.aggregate(Object, :count, :id) == 2
|
||||
assert Repo.aggregate(Notification, :count, :id) == 0
|
||||
end
|
||||
end
|
||||
|
||||
test "fetch_activities/2 returns activities addressed to a list " do
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy
|
||||
|
||||
import Mock
|
||||
|
|
@ -25,13 +25,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
|
|||
setup do: clear_config([:media_proxy, :enabled], true)
|
||||
|
||||
test "it prefetches media proxy URIs" 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
|
||||
MediaProxyWarmingPolicy.filter(@message)
|
||||
|
||||
ObanHelpers.perform_all()
|
||||
# Performing jobs which has been just enqueued
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert called(HTTP.get(:_, :_, :_))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,749 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
setup do: clear_config([:instance, :max_remote_account_fields])
|
||||
|
||||
describe "handle_incoming" do
|
||||
test "it works for incoming notices with tag not being an array (kroeg)" do
|
||||
data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["emoji"] == %{
|
||||
"icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
|
||||
}
|
||||
|
||||
data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert "test" in object.data["tag"]
|
||||
end
|
||||
|
||||
test "it cleans up incoming notices which are not really DMs" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
to = [user.ap_id, other_user.ap_id]
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", [])
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", [])
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["to"] == []
|
||||
assert data["cc"] == to
|
||||
|
||||
object_data = Object.normalize(activity).data
|
||||
|
||||
assert object_data["to"] == []
|
||||
assert object_data["cc"] == to
|
||||
end
|
||||
|
||||
test "it ignores an incoming notice if we already have it" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", Object.normalize(activity).data)
|
||||
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert activity == returned_activity
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it fetches reply-to activities if we don't have them" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
returned_object = Object.normalize(returned_activity, false)
|
||||
|
||||
assert %Activity{} =
|
||||
Activity.get_create_by_object_ap_id(
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
)
|
||||
|
||||
assert returned_object.data["inReplyTo"] ==
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
end
|
||||
|
||||
test "it does not fetch reply-to activities beyond max replies depth limit" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
allowed_thread_distance?: fn _ -> false end do
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
returned_object = Object.normalize(returned_activity, false)
|
||||
|
||||
refute Activity.get_create_by_object_ap_id(
|
||||
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
||||
)
|
||||
|
||||
assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873"
|
||||
end
|
||||
end
|
||||
|
||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://404.site/whatever")
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
assert capture_log(fn ->
|
||||
{:ok, _returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
end) =~ "[warn] Couldn't fetch \"https://404.site/whatever\", error: nil"
|
||||
end
|
||||
|
||||
test "it does not work for deactivated users" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
|
||||
insert(:user, ap_id: data["actor"], deactivated: true)
|
||||
|
||||
assert {:error, _} = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it works for incoming notices" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99512778738411822/activity"
|
||||
|
||||
assert data["context"] ==
|
||||
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
|
||||
|
||||
assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
assert data["cc"] == [
|
||||
"http://mastodon.example.org/users/admin/followers",
|
||||
"http://localtesting.pleroma.lol/users/lain"
|
||||
]
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
object_data = Object.normalize(data["object"]).data
|
||||
|
||||
assert object_data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99512778738411822"
|
||||
|
||||
assert object_data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
assert object_data["cc"] == [
|
||||
"http://mastodon.example.org/users/admin/followers",
|
||||
"http://localtesting.pleroma.lol/users/lain"
|
||||
]
|
||||
|
||||
assert object_data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert object_data["attributedTo"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
assert object_data["context"] ==
|
||||
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
|
||||
|
||||
assert object_data["sensitive"] == true
|
||||
|
||||
user = User.get_cached_by_ap_id(object_data["actor"])
|
||||
|
||||
assert user.note_count == 1
|
||||
end
|
||||
|
||||
test "it works for incoming notices without the sensitive property but an nsfw hashtag" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-nsfw.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
object_data = Object.normalize(data["object"], false).data
|
||||
|
||||
assert object_data["sensitive"] == true
|
||||
end
|
||||
|
||||
test "it works for incoming notices with hashtags" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert Enum.at(object.data["tag"], 2) == "moo"
|
||||
end
|
||||
|
||||
test "it works for incoming notices with contentMap" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["content"] ==
|
||||
"<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
|
||||
end
|
||||
|
||||
test "it works for incoming notices with to/cc not being an array (kroeg)" do
|
||||
data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["content"] ==
|
||||
"<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
|
||||
end
|
||||
|
||||
test "it ensures that as:Public activities make it to their followers collection" do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"])
|
||||
|> Map.put("cc", [])
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("attributedTo", user.ap_id)
|
||||
|> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"])
|
||||
|> Map.put("cc", [])
|
||||
|> Map.put("id", user.ap_id <> "/activities/12345678")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["cc"] == [User.ap_followers(user)]
|
||||
end
|
||||
|
||||
test "it ensures that address fields become lists" do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|> Map.put("to", nil)
|
||||
|> Map.put("cc", nil)
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("attributedTo", user.ap_id)
|
||||
|> Map.put("to", nil)
|
||||
|> Map.put("cc", nil)
|
||||
|> Map.put("id", user.ap_id <> "/activities/12345678")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert !is_nil(data["to"])
|
||||
assert !is_nil(data["cc"])
|
||||
end
|
||||
|
||||
test "it strips internal likes" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
likes = %{
|
||||
"first" =>
|
||||
"http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes?page=1",
|
||||
"id" => "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes",
|
||||
"totalItems" => 3,
|
||||
"type" => "OrderedCollection"
|
||||
}
|
||||
|
||||
object = Map.put(data["object"], "likes", likes)
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{object: object}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute Map.has_key?(object.data, "likes")
|
||||
end
|
||||
|
||||
test "it strips internal reactions" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
|
||||
|
||||
%{object: object} = Activity.get_by_id_with_object(activity.id)
|
||||
assert Map.has_key?(object.data, "reactions")
|
||||
assert Map.has_key?(object.data, "reaction_count")
|
||||
|
||||
object_data = Transmogrifier.strip_internal_fields(object.data)
|
||||
refute Map.has_key?(object_data, "reactions")
|
||||
refute Map.has_key?(object_data, "reaction_count")
|
||||
end
|
||||
|
||||
test "it correctly processes messages with non-array to field" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "blah blah blah",
|
||||
"type" => "Note",
|
||||
"attributedTo" => user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["to"]
|
||||
end
|
||||
|
||||
test "it correctly processes messages with non-array cc field" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => user.follower_address,
|
||||
"cc" => "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "blah blah blah",
|
||||
"type" => "Note",
|
||||
"attributedTo" => user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
|
||||
assert [user.follower_address] == activity.data["to"]
|
||||
end
|
||||
|
||||
test "it correctly processes messages with weirdness in address fields" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => [nil, user.follower_address],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Public", ["¿"]],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "…",
|
||||
"type" => "Note",
|
||||
"attributedTo" => user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
|
||||
assert [user.follower_address] == activity.data["to"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "`handle_incoming/2`, Mastodon format `replies` handling" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
|
||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||
|
||||
setup do
|
||||
data =
|
||||
"test/fixtures/mastodon-post-activity.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
items = get_in(data, ["object", "replies", "first", "items"])
|
||||
assert length(items) > 0
|
||||
|
||||
%{data: data, items: items}
|
||||
end
|
||||
|
||||
test "schedules background fetching of `replies` items if max thread depth limit allows", %{
|
||||
data: data,
|
||||
items: items
|
||||
} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
for id <- items do
|
||||
job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
|
||||
assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
|
||||
end
|
||||
end
|
||||
|
||||
test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
|
||||
%{data: data} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "`handle_incoming/2`, Pleroma format `replies` handling" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
|
||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "post1"})
|
||||
|
||||
{:ok, reply1} =
|
||||
CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id})
|
||||
|
||||
{:ok, reply2} =
|
||||
CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: activity.id})
|
||||
|
||||
replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end)
|
||||
|
||||
{:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
|
||||
Repo.delete(activity.object)
|
||||
Repo.delete(activity)
|
||||
|
||||
%{federation_output: federation_output, replies_uris: replies_uris}
|
||||
end
|
||||
|
||||
test "schedules background fetching of `replies` items if max thread depth limit allows", %{
|
||||
federation_output: federation_output,
|
||||
replies_uris: replies_uris
|
||||
} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
|
||||
|
||||
for id <- replies_uris do
|
||||
job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
|
||||
assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
|
||||
end
|
||||
end
|
||||
|
||||
test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
|
||||
%{federation_output: federation_output} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
|
||||
|
||||
assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "reserialization" do
|
||||
test "successfully reserializes a message with inReplyTo == nil" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Note",
|
||||
"content" => "Hi",
|
||||
"inReplyTo" => nil,
|
||||
"attributedTo" => user.ap_id
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
{:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
end
|
||||
|
||||
test "successfully reserializes a message with AS2 objects in IR" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Note",
|
||||
"content" => "Hi",
|
||||
"inReplyTo" => nil,
|
||||
"attributedTo" => user.ap_id,
|
||||
"tag" => [
|
||||
%{"name" => "#2hu", "href" => "http://example.com/2hu", "type" => "Hashtag"},
|
||||
%{"name" => "Bob", "href" => "http://example.com/bob", "type" => "Mention"}
|
||||
]
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
{:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_in_reply_to/2" do
|
||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||
|
||||
setup do
|
||||
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
[data: data]
|
||||
end
|
||||
|
||||
test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do
|
||||
assert Transmogrifier.fix_in_reply_to(data) == data
|
||||
end
|
||||
|
||||
test "returns object with inReplyTo when denied incoming reply", %{data: data} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
object_with_reply =
|
||||
Map.put(data["object"], "inReplyTo", "https://shitposter.club/notice/2827873")
|
||||
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873"
|
||||
|
||||
object_with_reply =
|
||||
Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"})
|
||||
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"}
|
||||
|
||||
object_with_reply =
|
||||
Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"])
|
||||
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"]
|
||||
|
||||
object_with_reply = Map.put(data["object"], "inReplyTo", [])
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == []
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns modified object when allowed incoming reply", %{data: data} do
|
||||
object_with_reply =
|
||||
Map.put(
|
||||
data["object"],
|
||||
"inReplyTo",
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
)
|
||||
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5)
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
|
||||
assert modified_object["inReplyTo"] ==
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
|
||||
assert modified_object["context"] ==
|
||||
"tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4"
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_attachments/1" do
|
||||
test "returns not modified object" do
|
||||
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
assert Transmogrifier.fix_attachments(data) == data
|
||||
end
|
||||
|
||||
test "returns modified object when attachment is map" do
|
||||
assert Transmogrifier.fix_attachments(%{
|
||||
"attachment" => %{
|
||||
"mediaType" => "video/mp4",
|
||||
"url" => "https://peertube.moe/stat-480.mp4"
|
||||
}
|
||||
}) == %{
|
||||
"attachment" => [
|
||||
%{
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "https://peertube.moe/stat-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
test "returns modified object when attachment is list" do
|
||||
assert Transmogrifier.fix_attachments(%{
|
||||
"attachment" => [
|
||||
%{"mediaType" => "video/mp4", "url" => "https://pe.er/stat-480.mp4"},
|
||||
%{"mimeType" => "video/mp4", "href" => "https://pe.er/stat-480.mp4"}
|
||||
]
|
||||
}) == %{
|
||||
"attachment" => [
|
||||
%{
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "https://pe.er/stat-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "https://pe.er/stat-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_emoji/1" do
|
||||
test "returns not modified object when object not contains tags" do
|
||||
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
assert Transmogrifier.fix_emoji(data) == data
|
||||
end
|
||||
|
||||
test "returns object with emoji when object contains list tags" do
|
||||
assert Transmogrifier.fix_emoji(%{
|
||||
"tag" => [
|
||||
%{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}},
|
||||
%{"type" => "Hashtag"}
|
||||
]
|
||||
}) == %{
|
||||
"emoji" => %{"bib" => "/test"},
|
||||
"tag" => [
|
||||
%{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"},
|
||||
%{"type" => "Hashtag"}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
test "returns object with emoji when object contains map tag" do
|
||||
assert Transmogrifier.fix_emoji(%{
|
||||
"tag" => %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}}
|
||||
}) == %{
|
||||
"emoji" => %{"bib" => "/test"},
|
||||
"tag" => %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_replies/1" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 2)
|
||||
|
||||
test "returns unmodified object if activity doesn't have self-replies" do
|
||||
data = Jason.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
assert Transmogrifier.set_replies(data) == data
|
||||
end
|
||||
|
||||
test "sets `replies` collection with a limited number of self-replies" do
|
||||
[user, another_user] = insert_list(2, :user)
|
||||
|
||||
{:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"})
|
||||
|
||||
{:ok, %{id: id2} = self_reply1} =
|
||||
CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1})
|
||||
|
||||
{:ok, self_reply2} =
|
||||
CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1})
|
||||
|
||||
# Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "self-reply to self-reply",
|
||||
in_reply_to_status_id: id2
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(another_user, %{
|
||||
status: "another user's reply",
|
||||
in_reply_to_status_id: id1
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end)
|
||||
|
||||
assert %{"type" => "Collection", "items" => ^replies_uris} =
|
||||
Transmogrifier.set_replies(object.data)["replies"]
|
||||
end
|
||||
end
|
||||
|
||||
test "take_emoji_tags/1" do
|
||||
user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})
|
||||
|
||||
assert Transmogrifier.take_emoji_tags(user) == [
|
||||
%{
|
||||
"icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
|
||||
"id" => "https://example.org/firefox.png",
|
||||
"name" => ":firefox:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
@ -26,310 +26,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
setup do: clear_config([:instance, :max_remote_account_fields])
|
||||
|
||||
describe "handle_incoming" do
|
||||
test "it works for incoming notices with tag not being an array (kroeg)" do
|
||||
data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["emoji"] == %{
|
||||
"icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
|
||||
}
|
||||
|
||||
data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert "test" in object.data["tag"]
|
||||
end
|
||||
|
||||
test "it cleans up incoming notices which are not really DMs" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
to = [user.ap_id, other_user.ap_id]
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", [])
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", [])
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["to"] == []
|
||||
assert data["cc"] == to
|
||||
|
||||
object_data = Object.normalize(activity).data
|
||||
|
||||
assert object_data["to"] == []
|
||||
assert object_data["cc"] == to
|
||||
end
|
||||
|
||||
test "it ignores an incoming notice if we already have it" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", Object.normalize(activity).data)
|
||||
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert activity == returned_activity
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it fetches reply-to activities if we don't have them" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://mstdn.io/users/mayuutann/statuses/99568293732299394")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
returned_object = Object.normalize(returned_activity, false)
|
||||
|
||||
assert %Activity{} =
|
||||
Activity.get_create_by_object_ap_id(
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
)
|
||||
|
||||
assert returned_object.data["inReplyTo"] ==
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
end
|
||||
|
||||
test "it does not fetch reply-to activities beyond max replies depth limit" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
allowed_thread_distance?: fn _ -> false end do
|
||||
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
returned_object = Object.normalize(returned_activity, false)
|
||||
|
||||
refute Activity.get_create_by_object_ap_id(
|
||||
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
||||
)
|
||||
|
||||
assert returned_object.data["inReplyTo"] == "https://shitposter.club/notice/2827873"
|
||||
end
|
||||
end
|
||||
|
||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://404.site/whatever")
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
assert capture_log(fn ->
|
||||
{:ok, _returned_activity} = Transmogrifier.handle_incoming(data)
|
||||
end) =~ "[warn] Couldn't fetch \"https://404.site/whatever\", error: nil"
|
||||
end
|
||||
|
||||
test "it does not work for deactivated users" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
|
||||
|
||||
insert(:user, ap_id: data["actor"], deactivated: true)
|
||||
|
||||
assert {:error, _} = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it works for incoming notices" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99512778738411822/activity"
|
||||
|
||||
assert data["context"] ==
|
||||
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
|
||||
|
||||
assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
assert data["cc"] == [
|
||||
"http://mastodon.example.org/users/admin/followers",
|
||||
"http://localtesting.pleroma.lol/users/lain"
|
||||
]
|
||||
|
||||
assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
object_data = Object.normalize(data["object"]).data
|
||||
|
||||
assert object_data["id"] ==
|
||||
"http://mastodon.example.org/users/admin/statuses/99512778738411822"
|
||||
|
||||
assert object_data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
assert object_data["cc"] == [
|
||||
"http://mastodon.example.org/users/admin/followers",
|
||||
"http://localtesting.pleroma.lol/users/lain"
|
||||
]
|
||||
|
||||
assert object_data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
assert object_data["attributedTo"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
assert object_data["context"] ==
|
||||
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
|
||||
|
||||
assert object_data["sensitive"] == true
|
||||
|
||||
user = User.get_cached_by_ap_id(object_data["actor"])
|
||||
|
||||
assert user.note_count == 1
|
||||
end
|
||||
|
||||
test "it works for incoming notices without the sensitive property but an nsfw hashtag" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-nsfw.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
object_data = Object.normalize(data["object"], false).data
|
||||
|
||||
assert object_data["sensitive"] == true
|
||||
end
|
||||
|
||||
test "it works for incoming notices with hashtags" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert Enum.at(object.data["tag"], 2) == "moo"
|
||||
end
|
||||
|
||||
test "it works for incoming notices with contentMap" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["content"] ==
|
||||
"<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
|
||||
end
|
||||
|
||||
test "it works for incoming notices with to/cc not being an array (kroeg)" do
|
||||
data = File.read!("test/fixtures/kroeg-post-activity.json") |> Poison.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
object = Object.normalize(data["object"])
|
||||
|
||||
assert object.data["content"] ==
|
||||
"<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
|
||||
end
|
||||
|
||||
test "it ensures that as:Public activities make it to their followers collection" do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"])
|
||||
|> Map.put("cc", [])
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("attributedTo", user.ap_id)
|
||||
|> Map.put("to", ["https://www.w3.org/ns/activitystreams#Public"])
|
||||
|> Map.put("cc", [])
|
||||
|> Map.put("id", user.ap_id <> "/activities/12345678")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["cc"] == [User.ap_followers(user)]
|
||||
end
|
||||
|
||||
test "it ensures that address fields become lists" do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", user.ap_id)
|
||||
|> Map.put("to", nil)
|
||||
|> Map.put("cc", nil)
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("attributedTo", user.ap_id)
|
||||
|> Map.put("to", nil)
|
||||
|> Map.put("cc", nil)
|
||||
|> Map.put("id", user.ap_id <> "/activities/12345678")
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert !is_nil(data["to"])
|
||||
assert !is_nil(data["cc"])
|
||||
end
|
||||
|
||||
test "it strips internal likes" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
|
||||
likes = %{
|
||||
"first" =>
|
||||
"http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes?page=1",
|
||||
"id" => "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes",
|
||||
"totalItems" => 3,
|
||||
"type" => "OrderedCollection"
|
||||
}
|
||||
|
||||
object = Map.put(data["object"], "likes", likes)
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, %Activity{object: object}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute Map.has_key?(object.data, "likes")
|
||||
end
|
||||
|
||||
test "it strips internal reactions" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "📢")
|
||||
|
||||
%{object: object} = Activity.get_by_id_with_object(activity.id)
|
||||
assert Map.has_key?(object.data, "reactions")
|
||||
assert Map.has_key?(object.data, "reaction_count")
|
||||
|
||||
object_data = Transmogrifier.strip_internal_fields(object.data)
|
||||
refute Map.has_key?(object_data, "reactions")
|
||||
refute Map.has_key?(object_data, "reaction_count")
|
||||
end
|
||||
|
||||
test "it works for incoming unfollows with an existing follow" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
@ -387,73 +83,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert activity.data["cc"] == [user.ap_id]
|
||||
end
|
||||
|
||||
test "it correctly processes messages with non-array to field" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "blah blah blah",
|
||||
"type" => "Note",
|
||||
"attributedTo" => user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["to"]
|
||||
end
|
||||
|
||||
test "it correctly processes messages with non-array cc field" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => user.follower_address,
|
||||
"cc" => "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "blah blah blah",
|
||||
"type" => "Note",
|
||||
"attributedTo" => user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
|
||||
assert [user.follower_address] == activity.data["to"]
|
||||
end
|
||||
|
||||
test "it correctly processes messages with weirdness in address fields" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => [nil, user.follower_address],
|
||||
"cc" => ["https://www.w3.org/ns/activitystreams#Public", ["¿"]],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "…",
|
||||
"type" => "Note",
|
||||
"attributedTo" => user.ap_id,
|
||||
"inReplyTo" => nil
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"]
|
||||
assert [user.follower_address] == activity.data["to"]
|
||||
end
|
||||
|
||||
test "it accepts Move activities" do
|
||||
old_user = insert(:user)
|
||||
new_user = insert(:user)
|
||||
|
|
@ -479,95 +108,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "`handle_incoming/2`, Mastodon format `replies` handling" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
|
||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||
|
||||
setup do
|
||||
data =
|
||||
"test/fixtures/mastodon-post-activity.json"
|
||||
|> File.read!()
|
||||
|> Poison.decode!()
|
||||
|
||||
items = get_in(data, ["object", "replies", "first", "items"])
|
||||
assert length(items) > 0
|
||||
|
||||
%{data: data, items: items}
|
||||
end
|
||||
|
||||
test "schedules background fetching of `replies` items if max thread depth limit allows", %{
|
||||
data: data,
|
||||
items: items
|
||||
} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 10)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
for id <- items do
|
||||
job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
|
||||
assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
|
||||
end
|
||||
end
|
||||
|
||||
test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
|
||||
%{data: data} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "`handle_incoming/2`, Pleroma format `replies` handling" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 5)
|
||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "post1"})
|
||||
|
||||
{:ok, reply1} =
|
||||
CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id})
|
||||
|
||||
{:ok, reply2} =
|
||||
CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: activity.id})
|
||||
|
||||
replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end)
|
||||
|
||||
{:ok, federation_output} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
|
||||
Repo.delete(activity.object)
|
||||
Repo.delete(activity)
|
||||
|
||||
%{federation_output: federation_output, replies_uris: replies_uris}
|
||||
end
|
||||
|
||||
test "schedules background fetching of `replies` items if max thread depth limit allows", %{
|
||||
federation_output: federation_output,
|
||||
replies_uris: replies_uris
|
||||
} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 1)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
|
||||
|
||||
for id <- replies_uris do
|
||||
job_args = %{"op" => "fetch_remote", "id" => id, "depth" => 1}
|
||||
assert_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker, args: job_args)
|
||||
end
|
||||
end
|
||||
|
||||
test "does NOT schedule background fetching of `replies` beyond max thread depth limit allows",
|
||||
%{federation_output: federation_output} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
{:ok, _activity} = Transmogrifier.handle_incoming(federation_output)
|
||||
|
||||
assert all_enqueued(worker: Pleroma.Workers.RemoteFetcherWorker) == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "prepare outgoing" do
|
||||
test "it inlines private announced objects" do
|
||||
user = insert(:user)
|
||||
|
|
@ -864,60 +404,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "reserialization" do
|
||||
test "successfully reserializes a message with inReplyTo == nil" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Note",
|
||||
"content" => "Hi",
|
||||
"inReplyTo" => nil,
|
||||
"attributedTo" => user.ap_id
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
{:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
end
|
||||
|
||||
test "successfully reserializes a message with AS2 objects in IR" do
|
||||
user = insert(:user)
|
||||
|
||||
message = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc" => [],
|
||||
"type" => "Note",
|
||||
"content" => "Hi",
|
||||
"inReplyTo" => nil,
|
||||
"attributedTo" => user.ap_id,
|
||||
"tag" => [
|
||||
%{"name" => "#2hu", "href" => "http://example.com/2hu", "type" => "Hashtag"},
|
||||
%{"name" => "Bob", "href" => "http://example.com/bob", "type" => "Mention"}
|
||||
]
|
||||
},
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||
|
||||
{:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_explicit_addressing" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
|
@ -983,64 +469,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "fix_in_reply_to/2" do
|
||||
setup do: clear_config([:instance, :federation_incoming_replies_max_depth])
|
||||
|
||||
setup do
|
||||
data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
[data: data]
|
||||
end
|
||||
|
||||
test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do
|
||||
assert Transmogrifier.fix_in_reply_to(data) == data
|
||||
end
|
||||
|
||||
test "returns object with inReplyTo when denied incoming reply", %{data: data} do
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
object_with_reply =
|
||||
Map.put(data["object"], "inReplyTo", "https://shitposter.club/notice/2827873")
|
||||
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == "https://shitposter.club/notice/2827873"
|
||||
|
||||
object_with_reply =
|
||||
Map.put(data["object"], "inReplyTo", %{"id" => "https://shitposter.club/notice/2827873"})
|
||||
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == %{"id" => "https://shitposter.club/notice/2827873"}
|
||||
|
||||
object_with_reply =
|
||||
Map.put(data["object"], "inReplyTo", ["https://shitposter.club/notice/2827873"])
|
||||
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == ["https://shitposter.club/notice/2827873"]
|
||||
|
||||
object_with_reply = Map.put(data["object"], "inReplyTo", [])
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
assert modified_object["inReplyTo"] == []
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns modified object when allowed incoming reply", %{data: data} do
|
||||
object_with_reply =
|
||||
Map.put(
|
||||
data["object"],
|
||||
"inReplyTo",
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
)
|
||||
|
||||
Pleroma.Config.put([:instance, :federation_incoming_replies_max_depth], 5)
|
||||
modified_object = Transmogrifier.fix_in_reply_to(object_with_reply)
|
||||
|
||||
assert modified_object["inReplyTo"] ==
|
||||
"https://mstdn.io/users/mayuutann/statuses/99568293732299394"
|
||||
|
||||
assert modified_object["context"] ==
|
||||
"tag:shitposter.club,2018-02-22:objectType=thread:nonce=e5a7c72d60a9c0e4"
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_url/1" do
|
||||
test "fixes data for object when url is map" do
|
||||
object = %{
|
||||
|
|
@ -1076,155 +504,4 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_attachments/1" do
|
||||
test "returns not modified object" do
|
||||
data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
assert Transmogrifier.fix_attachments(data) == data
|
||||
end
|
||||
|
||||
test "returns modified object when attachment is map" do
|
||||
assert Transmogrifier.fix_attachments(%{
|
||||
"attachment" => %{
|
||||
"mediaType" => "video/mp4",
|
||||
"url" => "https://peertube.moe/stat-480.mp4"
|
||||
}
|
||||
}) == %{
|
||||
"attachment" => [
|
||||
%{
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "https://peertube.moe/stat-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
test "returns modified object when attachment is list" do
|
||||
assert Transmogrifier.fix_attachments(%{
|
||||
"attachment" => [
|
||||
%{"mediaType" => "video/mp4", "url" => "https://pe.er/stat-480.mp4"},
|
||||
%{"mimeType" => "video/mp4", "href" => "https://pe.er/stat-480.mp4"}
|
||||
]
|
||||
}) == %{
|
||||
"attachment" => [
|
||||
%{
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "https://pe.er/stat-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" => "https://pe.er/stat-480.mp4",
|
||||
"mediaType" => "video/mp4",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "fix_emoji/1" do
|
||||
test "returns not modified object when object not contains tags" do
|
||||
data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
assert Transmogrifier.fix_emoji(data) == data
|
||||
end
|
||||
|
||||
test "returns object with emoji when object contains list tags" do
|
||||
assert Transmogrifier.fix_emoji(%{
|
||||
"tag" => [
|
||||
%{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}},
|
||||
%{"type" => "Hashtag"}
|
||||
]
|
||||
}) == %{
|
||||
"emoji" => %{"bib" => "/test"},
|
||||
"tag" => [
|
||||
%{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"},
|
||||
%{"type" => "Hashtag"}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
test "returns object with emoji when object contains map tag" do
|
||||
assert Transmogrifier.fix_emoji(%{
|
||||
"tag" => %{"type" => "Emoji", "name" => ":bib:", "icon" => %{"url" => "/test"}}
|
||||
}) == %{
|
||||
"emoji" => %{"bib" => "/test"},
|
||||
"tag" => %{"icon" => %{"url" => "/test"}, "name" => ":bib:", "type" => "Emoji"}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "set_replies/1" do
|
||||
setup do: clear_config([:activitypub, :note_replies_output_limit], 2)
|
||||
|
||||
test "returns unmodified object if activity doesn't have self-replies" do
|
||||
data = Poison.decode!(File.read!("test/fixtures/mastodon-post-activity.json"))
|
||||
assert Transmogrifier.set_replies(data) == data
|
||||
end
|
||||
|
||||
test "sets `replies` collection with a limited number of self-replies" do
|
||||
[user, another_user] = insert_list(2, :user)
|
||||
|
||||
{:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"})
|
||||
|
||||
{:ok, %{id: id2} = self_reply1} =
|
||||
CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1})
|
||||
|
||||
{:ok, self_reply2} =
|
||||
CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1})
|
||||
|
||||
# Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "self-reply to self-reply",
|
||||
in_reply_to_status_id: id2
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(another_user, %{
|
||||
status: "another user's reply",
|
||||
in_reply_to_status_id: id1
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
replies_uris = Enum.map([self_reply1, self_reply2], fn a -> a.object.data["id"] end)
|
||||
|
||||
assert %{"type" => "Collection", "items" => ^replies_uris} =
|
||||
Transmogrifier.set_replies(object.data)["replies"]
|
||||
end
|
||||
end
|
||||
|
||||
test "take_emoji_tags/1" do
|
||||
user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})
|
||||
|
||||
assert Transmogrifier.take_emoji_tags(user) == [
|
||||
%{
|
||||
"icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
|
||||
"id" => "https://example.org/firefox.png",
|
||||
"name" => ":firefox:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Config
|
||||
|
||||
@dir "test/frontend_static_test"
|
||||
|
||||
setup do
|
||||
clear_config([:instance, :static_dir], @dir)
|
||||
File.mkdir_p!(Pleroma.Frontend.dir())
|
||||
|
||||
on_exit(fn ->
|
||||
File.rm_rf(@dir)
|
||||
end)
|
||||
|
||||
admin = insert(:user, is_admin: true)
|
||||
token = insert(:oauth_admin_token, user: admin)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, token)
|
||||
|
||||
{:ok, %{admin: admin, token: token, conn: conn}}
|
||||
end
|
||||
|
||||
describe "GET /api/pleroma/admin/frontends" do
|
||||
test "it lists available frontends", %{conn: conn} do
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/frontends")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert Enum.map(response, & &1["name"]) ==
|
||||
Enum.map(Config.get([:frontends, :available]), fn {_, map} -> map["name"] end)
|
||||
|
||||
refute Enum.any?(response, fn frontend -> frontend["installed"] == true end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/admin/frontends/install" do
|
||||
test "from available frontends", %{conn: conn} do
|
||||
clear_config([:frontends, :available], %{
|
||||
"pleroma" => %{
|
||||
"ref" => "fantasy",
|
||||
"name" => "pleroma",
|
||||
"build_url" => "http://gensokyo.2hu/builds/${ref}"
|
||||
}
|
||||
})
|
||||
|
||||
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} ->
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")}
|
||||
end)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/frontends/install", %{name: "pleroma"})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/admin/frontends")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response == [
|
||||
%{
|
||||
"build_url" => "http://gensokyo.2hu/builds/${ref}",
|
||||
"git" => nil,
|
||||
"installed" => true,
|
||||
"name" => "pleroma",
|
||||
"ref" => "fantasy"
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
test "from a file", %{conn: conn} do
|
||||
clear_config([:frontends, :available], %{
|
||||
"pleroma" => %{
|
||||
"ref" => "fantasy",
|
||||
"name" => "pleroma",
|
||||
"build_dir" => ""
|
||||
}
|
||||
})
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/frontends/install", %{
|
||||
name: "pleroma",
|
||||
file: "test/fixtures/tesla_mock/frontend.zip"
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
|
||||
end
|
||||
|
||||
test "from an URL", %{conn: conn} do
|
||||
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")}
|
||||
end)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/frontends/install", %{
|
||||
name: "unknown",
|
||||
ref: "baka",
|
||||
build_url: "http://gensokyo.2hu/madeup.zip",
|
||||
build_dir: ""
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"]))
|
||||
end
|
||||
|
||||
test "failing returns an error", %{conn: conn} do
|
||||
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
|
||||
%Tesla.Env{status: 404, body: ""}
|
||||
end)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/frontends/install", %{
|
||||
name: "unknown",
|
||||
ref: "baka",
|
||||
build_url: "http://gensokyo.2hu/madeup.zip",
|
||||
build_dir: ""
|
||||
})
|
||||
|> json_response_and_validate_schema(400)
|
||||
|
||||
assert result == %{"error" => "Could not download or unzip the frontend"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -203,6 +203,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do
|
|||
assert count == 1
|
||||
end
|
||||
|
||||
# Note: as in Mastodon, `is_discoverable` doesn't anyhow relate to user searchability
|
||||
test "it returns non-discoverable users" do
|
||||
insert(:user)
|
||||
insert(:user, is_discoverable: false)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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
|
||||
use Pleroma.DataCase
|
||||
|
||||
|
|
@ -235,9 +236,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
test "for public posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "public"}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public", nil)
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 1
|
||||
|
|
@ -252,9 +253,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil)
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
mentions: [mentioned_user.ap_id],
|
||||
visibility: "public",
|
||||
in_reply_to: activity
|
||||
}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 1
|
||||
|
|
@ -268,9 +275,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
test "for unlisted posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "unlisted"}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted", nil)
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 2
|
||||
assert length(cc) == 1
|
||||
|
|
@ -285,9 +292,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil)
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
mentions: [mentioned_user.ap_id],
|
||||
visibility: "unlisted",
|
||||
in_reply_to: activity
|
||||
}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 3
|
||||
assert length(cc) == 1
|
||||
|
|
@ -301,9 +314,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
test "for private posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "private"}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private", nil)
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
assert length(to) == 2
|
||||
assert Enum.empty?(cc)
|
||||
|
||||
|
|
@ -316,9 +329,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil)
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
mentions: [mentioned_user.ap_id],
|
||||
visibility: "private",
|
||||
in_reply_to: activity
|
||||
}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 2
|
||||
assert Enum.empty?(cc)
|
||||
|
|
@ -330,9 +349,9 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
test "for direct posts, not a reply" do
|
||||
user = insert(:user)
|
||||
mentioned_user = insert(:user)
|
||||
mentions = [mentioned_user.ap_id]
|
||||
draft = %ActivityDraft{user: user, mentions: [mentioned_user.ap_id], visibility: "direct"}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct", nil)
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 1
|
||||
assert Enum.empty?(cc)
|
||||
|
|
@ -345,9 +364,15 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
mentioned_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
|
||||
mentions = [mentioned_user.ap_id]
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil)
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
mentions: [mentioned_user.ap_id],
|
||||
visibility: "direct",
|
||||
in_reply_to: activity
|
||||
}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 1
|
||||
assert Enum.empty?(cc)
|
||||
|
|
@ -356,7 +381,14 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
|
||||
{:ok, direct_activity} = CommonAPI.post(third_user, %{status: "uguu", visibility: "direct"})
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(user, mentions, direct_activity, "direct", nil)
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
mentions: [mentioned_user.ap_id],
|
||||
visibility: "direct",
|
||||
in_reply_to: direct_activity
|
||||
}
|
||||
|
||||
{to, cc} = Utils.get_to_and_cc(draft)
|
||||
|
||||
assert length(to) == 2
|
||||
assert Enum.empty?(cc)
|
||||
|
|
@ -532,26 +564,26 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "make_note_data/11" do
|
||||
describe "make_note_data/1" do
|
||||
test "returns note data" do
|
||||
user = insert(:user)
|
||||
note = insert(:note)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
|
||||
assert Utils.make_note_data(
|
||||
user.ap_id,
|
||||
[user2.ap_id],
|
||||
"2hu",
|
||||
"<h1>This is :moominmamma: note</h1>",
|
||||
[],
|
||||
note.id,
|
||||
[name: "jimm"],
|
||||
"test summary",
|
||||
[user3.ap_id],
|
||||
false,
|
||||
%{"custom_tag" => "test"}
|
||||
) == %{
|
||||
draft = %ActivityDraft{
|
||||
user: user,
|
||||
to: [user2.ap_id],
|
||||
context: "2hu",
|
||||
content_html: "<h1>This is :moominmamma: note</h1>",
|
||||
in_reply_to: note.id,
|
||||
tags: [name: "jimm"],
|
||||
summary: "test summary",
|
||||
cc: [user3.ap_id],
|
||||
extra: %{"custom_tag" => "test"}
|
||||
}
|
||||
|
||||
assert Utils.make_note_data(draft) == %{
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [],
|
||||
"cc" => [user3.ap_id],
|
||||
|
|
|
|||
|
|
@ -1277,4 +1277,128 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
} = CommonAPI.get_user("")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with `local` visibility" do
|
||||
setup do: clear_config([:instance, :federating], true)
|
||||
|
||||
test "post" do
|
||||
user = insert(:user)
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"})
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
assert_not_called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "delete" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, %Activity{id: activity_id}} =
|
||||
CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"})
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"deleted_activity_id" => ^activity_id}} = activity} =
|
||||
CommonAPI.delete(activity_id, user)
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
assert_not_called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "repeat" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, %Activity{id: activity_id}} =
|
||||
CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"type" => "Announce"}} = activity} =
|
||||
CommonAPI.repeat(activity_id, user)
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "unrepeat" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, %Activity{id: activity_id}} =
|
||||
CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
assert {:ok, _} = CommonAPI.repeat(activity_id, user)
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"type" => "Undo"}} = activity} =
|
||||
CommonAPI.unrepeat(activity_id, user)
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "favorite" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"type" => "Like"}} = activity} =
|
||||
CommonAPI.favorite(user, activity.id)
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "unfavorite" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
{:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, activity} = CommonAPI.unfavorite(activity.id, user)
|
||||
assert Visibility.is_local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "react_with_emoji" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"type" => "EmojiReact"}} = activity} =
|
||||
CommonAPI.react_with_emoji(activity.id, user, "👍")
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "unreact_with_emoji" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
{:ok, _reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"type" => "Undo"}} = activity} =
|
||||
CommonAPI.unreact_with_emoji(activity.id, user, "👍")
|
||||
|
||||
assert Visibility.is_local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.FedSockets.FedRegistryTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias Pleroma.Web.FedSockets
|
||||
alias Pleroma.Web.FedSockets.FedRegistry
|
||||
alias Pleroma.Web.FedSockets.SocketInfo
|
||||
|
||||
@good_domain "http://good.domain"
|
||||
@good_domain_origin "good.domain:80"
|
||||
|
||||
setup do
|
||||
start_supervised({Pleroma.Web.FedSockets.Supervisor, []})
|
||||
build_test_socket(@good_domain)
|
||||
Process.sleep(10)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "add_fed_socket/1 without conflicting sockets" do
|
||||
test "can be added" do
|
||||
Process.sleep(10)
|
||||
assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
assert origin == "good.domain:80"
|
||||
end
|
||||
|
||||
test "multiple origins can be added" do
|
||||
build_test_socket("http://anothergood.domain")
|
||||
Process.sleep(10)
|
||||
|
||||
assert {:ok, %SocketInfo{origin: origin_1}} =
|
||||
FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
|
||||
assert {:ok, %SocketInfo{origin: origin_2}} =
|
||||
FedRegistry.get_fed_socket("anothergood.domain:80")
|
||||
|
||||
assert origin_1 == "good.domain:80"
|
||||
assert origin_2 == "anothergood.domain:80"
|
||||
assert FedRegistry.list_all() |> Enum.count() == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "add_fed_socket/1 when duplicate sockets conflict" do
|
||||
setup do
|
||||
build_test_socket(@good_domain)
|
||||
build_test_socket(@good_domain)
|
||||
Process.sleep(10)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "will be ignored" do
|
||||
assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} =
|
||||
FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
|
||||
assert origin == "good.domain:80"
|
||||
|
||||
assert FedRegistry.list_all() |> Enum.count() == 1
|
||||
end
|
||||
|
||||
test "the newer process will be closed" do
|
||||
pid_two = build_test_socket(@good_domain)
|
||||
|
||||
assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} =
|
||||
FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
|
||||
assert origin == "good.domain:80"
|
||||
Process.sleep(10)
|
||||
|
||||
refute Process.alive?(pid_two)
|
||||
|
||||
assert FedRegistry.list_all() |> Enum.count() == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_fed_socket/1" do
|
||||
test "returns missing for unknown hosts" do
|
||||
assert {:error, :missing} = FedRegistry.get_fed_socket("not_a_dmoain")
|
||||
end
|
||||
|
||||
test "returns rejected for hosts previously rejected" do
|
||||
"rejected.domain:80"
|
||||
|> FedSockets.uri_for_origin()
|
||||
|> FedRegistry.set_host_rejected()
|
||||
|
||||
assert {:error, :rejected} = FedRegistry.get_fed_socket("rejected.domain:80")
|
||||
end
|
||||
|
||||
test "can retrieve a previously added SocketInfo" do
|
||||
build_test_socket(@good_domain)
|
||||
Process.sleep(10)
|
||||
assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
assert origin == "good.domain:80"
|
||||
end
|
||||
|
||||
test "removes references to SocketInfos when the process crashes" do
|
||||
assert {:ok, %SocketInfo{origin: origin, pid: pid}} =
|
||||
FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
|
||||
assert origin == "good.domain:80"
|
||||
|
||||
Process.exit(pid, :testing)
|
||||
Process.sleep(100)
|
||||
assert {:error, :missing} = FedRegistry.get_fed_socket(@good_domain_origin)
|
||||
end
|
||||
end
|
||||
|
||||
def build_test_socket(uri) do
|
||||
Kernel.spawn(fn -> fed_socket_almost(uri) end)
|
||||
end
|
||||
|
||||
def fed_socket_almost(origin) do
|
||||
FedRegistry.add_fed_socket(origin)
|
||||
|
||||
receive do
|
||||
:close ->
|
||||
:ok
|
||||
after
|
||||
5_000 -> :timeout
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.FedSockets.FetchRegistryTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias Pleroma.Web.FedSockets.FetchRegistry
|
||||
alias Pleroma.Web.FedSockets.FetchRegistry.FetchRegistryData
|
||||
|
||||
@json_message "hello"
|
||||
@json_reply "hello back"
|
||||
|
||||
setup do
|
||||
start_supervised(
|
||||
{Pleroma.Web.FedSockets.Supervisor,
|
||||
[
|
||||
ping_interval: 8,
|
||||
connection_duration: 15,
|
||||
rejection_duration: 5,
|
||||
fed_socket_fetches: [default: 10, interval: 10]
|
||||
]}
|
||||
)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "fetches can be stored" do
|
||||
uuid = FetchRegistry.register_fetch(@json_message)
|
||||
|
||||
assert {:error, :waiting} = FetchRegistry.check_fetch(uuid)
|
||||
end
|
||||
|
||||
test "fetches can return" do
|
||||
uuid = FetchRegistry.register_fetch(@json_message)
|
||||
task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end)
|
||||
|
||||
assert {:error, :waiting} = FetchRegistry.check_fetch(uuid)
|
||||
Task.await(task)
|
||||
|
||||
assert {:ok, %FetchRegistryData{received_json: received_json}} =
|
||||
FetchRegistry.check_fetch(uuid)
|
||||
|
||||
assert received_json == @json_reply
|
||||
end
|
||||
|
||||
test "fetches are deleted once popped from stack" do
|
||||
uuid = FetchRegistry.register_fetch(@json_message)
|
||||
task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end)
|
||||
Task.await(task)
|
||||
|
||||
assert {:ok, %FetchRegistryData{received_json: received_json}} =
|
||||
FetchRegistry.check_fetch(uuid)
|
||||
|
||||
assert received_json == @json_reply
|
||||
assert {:ok, @json_reply} = FetchRegistry.pop_fetch(uuid)
|
||||
|
||||
assert {:error, :missing} = FetchRegistry.check_fetch(uuid)
|
||||
end
|
||||
|
||||
test "fetches can time out" do
|
||||
uuid = FetchRegistry.register_fetch(@json_message)
|
||||
assert {:error, :waiting} = FetchRegistry.check_fetch(uuid)
|
||||
Process.sleep(500)
|
||||
assert {:error, :missing} = FetchRegistry.check_fetch(uuid)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.FedSockets.SocketInfoTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias Pleroma.Web.FedSockets
|
||||
alias Pleroma.Web.FedSockets.SocketInfo
|
||||
|
||||
describe "uri_for_origin" do
|
||||
test "provides the fed_socket URL given the origin information" do
|
||||
endpoint = "example.com:4000"
|
||||
assert FedSockets.uri_for_origin(endpoint) =~ "ws://"
|
||||
assert FedSockets.uri_for_origin(endpoint) =~ endpoint
|
||||
end
|
||||
end
|
||||
|
||||
describe "origin" do
|
||||
test "will provide the origin field given a url" do
|
||||
endpoint = "example.com:4000"
|
||||
assert SocketInfo.origin("ws://#{endpoint}") == endpoint
|
||||
assert SocketInfo.origin("http://#{endpoint}") == endpoint
|
||||
assert SocketInfo.origin("https://#{endpoint}") == endpoint
|
||||
end
|
||||
|
||||
test "will proide the origin field given a uri" do
|
||||
endpoint = "example.com:4000"
|
||||
uri = URI.parse("http://#{endpoint}")
|
||||
|
||||
assert SocketInfo.origin(uri) == endpoint
|
||||
end
|
||||
end
|
||||
|
||||
describe "touch" do
|
||||
test "will update the TTL" do
|
||||
endpoint = "example.com:4000"
|
||||
socket = SocketInfo.build("ws://#{endpoint}")
|
||||
Process.sleep(2)
|
||||
touched_socket = SocketInfo.touch(socket)
|
||||
|
||||
assert socket.connected_until < touched_socket.connected_until
|
||||
end
|
||||
end
|
||||
|
||||
describe "expired?" do
|
||||
setup do
|
||||
start_supervised(
|
||||
{Pleroma.Web.FedSockets.Supervisor,
|
||||
[
|
||||
ping_interval: 8,
|
||||
connection_duration: 5,
|
||||
rejection_duration: 5,
|
||||
fed_socket_rejections: [lazy: true]
|
||||
]}
|
||||
)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "tests if the TTL is exceeded" do
|
||||
endpoint = "example.com:4000"
|
||||
socket = SocketInfo.build("ws://#{endpoint}")
|
||||
refute SocketInfo.expired?(socket)
|
||||
Process.sleep(10)
|
||||
|
||||
assert SocketInfo.expired?(socket)
|
||||
end
|
||||
end
|
||||
|
||||
describe "creating outgoing connection records" do
|
||||
test "can be passed a string" do
|
||||
assert %{conn_pid: :pid, origin: _origin} = SocketInfo.build("example.com:4000", :pid)
|
||||
end
|
||||
|
||||
test "can be passed a URI" do
|
||||
uri = URI.parse("http://example.com:4000")
|
||||
assert %{conn_pid: :pid, origin: origin} = SocketInfo.build(uri, :pid)
|
||||
assert origin =~ "example.com:4000"
|
||||
end
|
||||
|
||||
test "will include the port number" do
|
||||
assert %{conn_pid: :pid, origin: origin} = SocketInfo.build("http://example.com:4000", :pid)
|
||||
|
||||
assert origin =~ ":4000"
|
||||
end
|
||||
|
||||
test "will provide the port if missing" do
|
||||
assert %{conn_pid: :pid, origin: "example.com:80"} =
|
||||
SocketInfo.build("http://example.com", :pid)
|
||||
|
||||
assert %{conn_pid: :pid, origin: "example.com:443"} =
|
||||
SocketInfo.build("https://example.com", :pid)
|
||||
end
|
||||
end
|
||||
|
||||
describe "creating incoming connection records" do
|
||||
test "can be passed a string" do
|
||||
assert %{pid: _, origin: _origin} = SocketInfo.build("example.com:4000")
|
||||
end
|
||||
|
||||
test "can be passed a URI" do
|
||||
uri = URI.parse("example.com:4000")
|
||||
assert %{pid: _, origin: _origin} = SocketInfo.build(uri)
|
||||
end
|
||||
|
||||
test "will include the port number" do
|
||||
assert %{pid: _, origin: origin} = SocketInfo.build("http://example.com:4000")
|
||||
|
||||
assert origin =~ ":4000"
|
||||
end
|
||||
|
||||
test "will provide the port if missing" do
|
||||
assert %{pid: _, origin: "example.com:80"} = SocketInfo.build("http://example.com")
|
||||
assert %{pid: _, origin: "example.com:443"} = SocketInfo.build("https://example.com")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -436,6 +436,39 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct")
|
||||
assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
test "muted reactions", %{user: user, conn: conn} do
|
||||
user2 = insert(:user)
|
||||
User.mute(user, user2)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "."})
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "🎅")
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/statuses")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
}
|
||||
] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/statuses?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
}
|
||||
] = result
|
||||
end
|
||||
end
|
||||
|
||||
defp local_and_remote_activities(%{local: local, remote: remote}) do
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
|||
assert result = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
email = Pleroma.Config.get([:instance, :email])
|
||||
thumbnail = Pleroma.Web.base_url() <> Pleroma.Config.get([:instance, :instance_thumbnail])
|
||||
background = Pleroma.Web.base_url() <> Pleroma.Config.get([:instance, :background_image])
|
||||
|
||||
# Note: not checking for "max_toot_chars" since it's optional
|
||||
assert %{
|
||||
"uri" => _,
|
||||
|
|
@ -24,7 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
|||
"streaming_api" => _
|
||||
},
|
||||
"stats" => _,
|
||||
"thumbnail" => _,
|
||||
"thumbnail" => from_config_thumbnail,
|
||||
"languages" => _,
|
||||
"registrations" => _,
|
||||
"approval_required" => _,
|
||||
|
|
@ -33,7 +36,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
|||
"avatar_upload_limit" => _,
|
||||
"background_upload_limit" => _,
|
||||
"banner_upload_limit" => _,
|
||||
"background_image" => _,
|
||||
"background_image" => from_config_background,
|
||||
"chat_limit" => _,
|
||||
"description_limit" => _
|
||||
} = result
|
||||
|
|
@ -45,6 +48,8 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
|||
assert result["pleroma"]["vapid_public_key"]
|
||||
|
||||
assert email == from_config_email
|
||||
assert thumbnail == from_config_thumbnail
|
||||
assert background == from_config_background
|
||||
end
|
||||
|
||||
test "get instance stats", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
test "posting a status with OGP link preview", %{conn: conn} do
|
||||
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
clear_config([:rich_media, :enabled], true)
|
||||
|
||||
conn =
|
||||
|
|
@ -1197,7 +1197,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
test "returns rich-media card", %{conn: conn, user: user} do
|
||||
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp"})
|
||||
|
||||
|
|
@ -1242,7 +1242,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
test "replaces missing description with an empty string", %{conn: conn, user: user} do
|
||||
Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp-missing-data"})
|
||||
|
||||
|
|
@ -1740,4 +1740,94 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|> get("/api/v1/statuses/#{activity.id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "posting a local only status" do
|
||||
%{user: _user, conn: conn} = oauth_access(["write:statuses"])
|
||||
|
||||
conn_one =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses", %{
|
||||
"status" => "cofe",
|
||||
"visibility" => "local"
|
||||
})
|
||||
|
||||
local = Pleroma.Constants.as_local_public()
|
||||
|
||||
assert %{"content" => "cofe", "id" => id, "visibility" => "local"} =
|
||||
json_response(conn_one, 200)
|
||||
|
||||
assert %Activity{id: ^id, data: %{"to" => [^local]}} = Activity.get_by_id(id)
|
||||
end
|
||||
|
||||
describe "muted reactions" do
|
||||
test "index" do
|
||||
%{conn: conn, user: user} = oauth_access(["read:statuses"])
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||
User.mute(user, other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/statuses/?ids[]=#{activity.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
}
|
||||
] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/statuses/?ids[]=#{activity.id}&with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
}
|
||||
] = result
|
||||
end
|
||||
|
||||
test "show" do
|
||||
# %{conn: conn, user: user, token: token} = oauth_access(["read:statuses"])
|
||||
%{conn: conn, user: user, token: _token} = oauth_access(["read:statuses"])
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||
User.mute(user, other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/statuses/#{activity.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
} = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/statuses/#{activity.id}?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
} = result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,21 +45,77 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "creates push subscription" do
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
describe "when disabled" do
|
||||
test "POST returns error", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> post("/api/v1/push/subscription", %{subscription: @sub})
|
||||
|> post("/api/v1/push/subscription", %{
|
||||
"data" => %{"alerts" => %{"mention" => true}},
|
||||
"subscription" => @sub
|
||||
})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "GET returns error", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> get("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "PUT returns error", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "DELETE returns error", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> delete("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "creates push subscription" do
|
||||
test "ignores unsupported types", %{conn: conn} do
|
||||
result =
|
||||
conn
|
||||
|> post("/api/v1/push/subscription", %{
|
||||
"data" => %{
|
||||
"alerts" => %{
|
||||
"fake_unsupported_type" => true
|
||||
}
|
||||
},
|
||||
"subscription" => @sub
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
refute %{
|
||||
"alerts" => %{
|
||||
"fake_unsupported_type" => true
|
||||
}
|
||||
} == result
|
||||
end
|
||||
|
||||
test "successful creation", %{conn: conn} do
|
||||
result =
|
||||
conn
|
||||
|> post("/api/v1/push/subscription", %{
|
||||
"data" => %{
|
||||
"alerts" => %{"mention" => true, "test" => true, "pleroma:chat_mention" => true}
|
||||
"alerts" => %{
|
||||
"mention" => true,
|
||||
"favourite" => true,
|
||||
"follow" => true,
|
||||
"reblog" => true,
|
||||
"pleroma:chat_mention" => true,
|
||||
"pleroma:emoji_reaction" => true
|
||||
}
|
||||
},
|
||||
"subscription" => @sub
|
||||
})
|
||||
|
|
@ -68,7 +124,14 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|
|||
[subscription] = Pleroma.Repo.all(Subscription)
|
||||
|
||||
assert %{
|
||||
"alerts" => %{"mention" => true, "pleroma:chat_mention" => true},
|
||||
"alerts" => %{
|
||||
"mention" => true,
|
||||
"favourite" => true,
|
||||
"follow" => true,
|
||||
"reblog" => true,
|
||||
"pleroma:chat_mention" => true,
|
||||
"pleroma:emoji_reaction" => true
|
||||
},
|
||||
"endpoint" => subscription.endpoint,
|
||||
"id" => to_string(subscription.id),
|
||||
"server_key" => @server_key
|
||||
|
|
@ -77,14 +140,6 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|
|||
end
|
||||
|
||||
describe "gets a user subscription" do
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> get("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error when user hasn't subscription", %{conn: conn} do
|
||||
res =
|
||||
conn
|
||||
|
|
@ -124,30 +179,47 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|
|||
insert(:push_subscription,
|
||||
user: user,
|
||||
token: token,
|
||||
data: %{"alerts" => %{"mention" => true}}
|
||||
data: %{
|
||||
"alerts" => %{
|
||||
"mention" => true,
|
||||
"favourite" => true,
|
||||
"follow" => true,
|
||||
"reblog" => true,
|
||||
"pleroma:chat_mention" => true,
|
||||
"pleroma:emoji_reaction" => true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
%{conn: conn, user: user, token: token, subscription: subscription}
|
||||
end
|
||||
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns updated subsciption", %{conn: conn, subscription: subscription} do
|
||||
res =
|
||||
conn
|
||||
|> put("/api/v1/push/subscription", %{
|
||||
data: %{"alerts" => %{"mention" => false, "follow" => true}}
|
||||
data: %{
|
||||
"alerts" => %{
|
||||
"mention" => false,
|
||||
"favourite" => false,
|
||||
"follow" => false,
|
||||
"reblog" => false,
|
||||
"pleroma:chat_mention" => false,
|
||||
"pleroma:emoji_reaction" => false
|
||||
}
|
||||
}
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
expect = %{
|
||||
"alerts" => %{"follow" => true, "mention" => false},
|
||||
"alerts" => %{
|
||||
"mention" => false,
|
||||
"favourite" => false,
|
||||
"follow" => false,
|
||||
"reblog" => false,
|
||||
"pleroma:chat_mention" => false,
|
||||
"pleroma:emoji_reaction" => false
|
||||
},
|
||||
"endpoint" => "https://example.com/example/1234",
|
||||
"id" => to_string(subscription.id),
|
||||
"server_key" => @server_key
|
||||
|
|
@ -158,14 +230,6 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
|
|||
end
|
||||
|
||||
describe "deletes the user subscription" do
|
||||
test "returns error when push disabled ", %{conn: conn} do
|
||||
assert_error_when_disable_push do
|
||||
conn
|
||||
|> delete("/api/v1/push/subscription", %{})
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error when user hasn't subscription", %{conn: conn} do
|
||||
res =
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -54,6 +54,42 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
|||
assert private_activity.id in status_ids
|
||||
refute direct_activity.id in status_ids
|
||||
end
|
||||
|
||||
test "muted emotions", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "."})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||
User.mute(user, other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/timelines/home")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
}
|
||||
] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/timelines/home?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
}
|
||||
] = result
|
||||
end
|
||||
end
|
||||
|
||||
describe "public" do
|
||||
|
|
@ -159,6 +195,48 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
|||
|
||||
assert length(json_response_and_validate_schema(conn, :ok)) == 1
|
||||
end
|
||||
|
||||
test "muted emotions", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "."})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||
User.mute(user, other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/timelines/public")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
}
|
||||
] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/timelines/public?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
}
|
||||
] = result
|
||||
end
|
||||
end
|
||||
|
||||
defp local_and_remote_activities do
|
||||
|
|
@ -428,6 +506,44 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
|||
|
||||
assert id == to_string(activity_one.id)
|
||||
end
|
||||
|
||||
test "muted emotions", %{user: user, conn: conn} do
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user2, %{status: "."})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user3, "🎅")
|
||||
User.mute(user, user3)
|
||||
|
||||
{:ok, list} = Pleroma.List.create("name", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, user2)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/timelines/list/#{list.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
}
|
||||
] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/timelines/list/#{list.id}?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
}
|
||||
] = result
|
||||
end
|
||||
end
|
||||
|
||||
describe "hashtag" do
|
||||
|
|
@ -476,6 +592,48 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
|||
|
||||
assert [status_none] == json_response_and_validate_schema(all_test, :ok)
|
||||
end
|
||||
|
||||
test "muted emotions", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test #2hu"})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||
User.mute(user, other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/timelines/tag/2hu")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => []
|
||||
}
|
||||
}
|
||||
] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/timelines/tag/2hu?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"pleroma" => %{
|
||||
"emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
|
||||
}
|
||||
}
|
||||
] = result
|
||||
end
|
||||
end
|
||||
|
||||
describe "hashtag timeline handling of :restrict_unauthenticated setting" do
|
||||
|
|
|
|||
|
|
@ -73,6 +73,50 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
]
|
||||
end
|
||||
|
||||
test "doesn't show reactions from muted and blocked users" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
|
||||
|
||||
{:ok, _} = User.mute(user, other_user)
|
||||
{:ok, _} = User.block(other_user, third_user)
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 1, me: false}
|
||||
]
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == []
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "☕")
|
||||
|
||||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 2, me: false}
|
||||
]
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 1, me: false}
|
||||
]
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: other_user)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{name: "☕", count: 1, me: true}
|
||||
]
|
||||
end
|
||||
|
||||
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexingTest do
|
|||
}) == []
|
||||
end
|
||||
|
||||
test "for local user when discoverable is false" do
|
||||
test "for local user when `is_discoverable` is false" do
|
||||
assert Pleroma.Web.Metadata.Providers.RestrictIndexing.build_tags(%{
|
||||
user: %Pleroma.User{local: true, is_discoverable: false}
|
||||
}) == [{:meta, [name: "robots", content: "noindex, noarchive"], []}]
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MetadataTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "restrict indexing remote users" do
|
||||
test "for remote user" do
|
||||
user = insert(:user, local: false)
|
||||
|
||||
assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~
|
||||
"<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||
end
|
||||
|
||||
test "for local user" do
|
||||
user = insert(:user, is_discoverable: false)
|
||||
|
||||
assert Pleroma.Web.Metadata.build_tags(%{user: user}) =~
|
||||
"<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||
end
|
||||
|
||||
test "for local user set to discoverable" do
|
||||
user = insert(:user, is_discoverable: true)
|
||||
|
||||
refute Pleroma.Web.Metadata.build_tags(%{user: user}) =~
|
||||
"<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||
end
|
||||
end
|
||||
|
||||
describe "no metadata for private instances" do
|
||||
test "for local user set to discoverable" do
|
||||
clear_config([:instance, :public], false)
|
||||
user = insert(:user, bio: "This is my secret fedi account bio", is_discoverable: true)
|
||||
|
||||
assert "" = Pleroma.Web.Metadata.build_tags(%{user: user})
|
||||
end
|
||||
|
||||
test "search exclusion metadata is included" do
|
||||
clear_config([:instance, :public], false)
|
||||
user = insert(:user, bio: "This is my secret fedi account bio", is_discoverable: false)
|
||||
|
||||
assert ~s(<meta content="noindex, noarchive" name="robots">) ==
|
||||
Pleroma.Web.Metadata.build_tags(%{user: user})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -106,6 +106,48 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionControllerTest do
|
|||
result
|
||||
end
|
||||
|
||||
test "GET /api/v1/pleroma/statuses/:id/reactions?with_muted=true", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
|
||||
token = insert(:oauth_token, user: user, scopes: ["read:statuses"])
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "🎅")
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user3, "🎅")
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"name" => "🎅", "count" => 2}] = result
|
||||
|
||||
User.mute(user, user3)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"name" => "🎅", "count" => 1}] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> assign(:token, token)
|
||||
|> get("/api/v1/pleroma/statuses/#{activity.id}/reactions?with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"name" => "🎅", "count" => 2}] = result
|
||||
end
|
||||
|
||||
test "GET /api/v1/pleroma/statuses/:id/reactions with :show_reactions disabled", %{conn: conn} do
|
||||
clear_config([:instance, :show_reactions], false)
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageReferenceViewTest do
|
|||
|
||||
clear_config([:rich_media, :enabled], true)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
Tesla.Mock.mock_global(fn
|
||||
%{url: "https://example.com/ogp"} ->
|
||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")}
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -184,6 +184,24 @@ defmodule Pleroma.Web.Push.ImplTest do
|
|||
"New Favorite"
|
||||
end
|
||||
|
||||
test "renders title and body for pleroma:emoji_reaction activity" do
|
||||
user = insert(:user, nickname: "Bob")
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "This post is a really good post!"
|
||||
})
|
||||
|
||||
{:ok, activity} = CommonAPI.react_with_emoji(activity.id, user, "👍")
|
||||
object = Object.normalize(activity)
|
||||
|
||||
assert Impl.format_body(%{activity: activity, type: "pleroma:emoji_reaction"}, user, object) ==
|
||||
"@Bob reacted with 👍"
|
||||
|
||||
assert Impl.format_title(%{activity: activity, type: "pleroma:emoji_reaction"}) ==
|
||||
"New Reaction"
|
||||
end
|
||||
|
||||
test "renders title for create activity with direct visibility" do
|
||||
user = insert(:user, nickname: "Bob")
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,48 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do
|
|||
|
||||
assert response =~ "<h2>Password Reset for #{user.nickname}</h2>"
|
||||
end
|
||||
|
||||
test "it returns an error when the token has expired", %{conn: conn} do
|
||||
clear_config([:instance, :password_reset_token_validity], 0)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, token} = PasswordResetToken.create_token(user)
|
||||
|
||||
:timer.sleep(2000)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/pleroma/password_reset/#{token.token}")
|
||||
|> html_response(:ok)
|
||||
|
||||
assert response =~ "<h2>Invalid Token</h2>"
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/pleroma/password_reset" do
|
||||
test "it fails for an expired token", %{conn: conn} do
|
||||
clear_config([:instance, :password_reset_token_validity], 0)
|
||||
|
||||
user = insert(:user)
|
||||
{:ok, token} = PasswordResetToken.create_token(user)
|
||||
:timer.sleep(2000)
|
||||
{:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})
|
||||
|
||||
params = %{
|
||||
"password" => "test",
|
||||
password_confirmation: "test",
|
||||
token: token.token
|
||||
}
|
||||
|
||||
response =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> post("/api/pleroma/password_reset", %{data: params})
|
||||
|> html_response(:ok)
|
||||
|
||||
refute response =~ "<h2>Password changed!</h2>"
|
||||
end
|
||||
|
||||
test "it returns HTTP 200", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, token} = PasswordResetToken.create_token(user)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ defmodule Pleroma.Factory do
|
|||
}
|
||||
end
|
||||
|
||||
def user_factory do
|
||||
def user_factory(attrs \\ %{}) do
|
||||
user = %User{
|
||||
name: sequence(:name, &"Test テスト User #{&1}"),
|
||||
email: sequence(:email, &"user#{&1}@example.com"),
|
||||
|
|
@ -39,13 +39,29 @@ defmodule Pleroma.Factory do
|
|||
ap_enabled: true
|
||||
}
|
||||
|
||||
%{
|
||||
user
|
||||
| ap_id: User.ap_id(user),
|
||||
follower_address: User.ap_followers(user),
|
||||
following_address: User.ap_following(user),
|
||||
raw_bio: user.bio
|
||||
}
|
||||
urls =
|
||||
if attrs[:local] == false do
|
||||
base_domain = Enum.random(["domain1.com", "domain2.com", "domain3.com"])
|
||||
|
||||
ap_id = "https://#{base_domain}/users/#{user.nickname}"
|
||||
|
||||
%{
|
||||
ap_id: ap_id,
|
||||
follower_address: ap_id <> "/followers",
|
||||
following_address: ap_id <> "/following"
|
||||
}
|
||||
else
|
||||
%{
|
||||
ap_id: User.ap_id(user),
|
||||
follower_address: User.ap_followers(user),
|
||||
following_address: User.ap_following(user)
|
||||
}
|
||||
end
|
||||
|
||||
user
|
||||
|> Map.put(:raw_bio, user.bio)
|
||||
|> Map.merge(urls)
|
||||
|> merge_attributes(attrs)
|
||||
end
|
||||
|
||||
def user_relationship_factory(attrs \\ %{}) do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue