Merge branch 'develop' into feature/addressable-lists

This commit is contained in:
Egor Kislitsyn 2019-07-11 13:26:59 +07:00
commit 182f7bbb11
826 changed files with 14251 additions and 3303 deletions

View file

@ -15,6 +15,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
config_path = [:instance, :federating]
initial_setting = Pleroma.Config.get(config_path)
Pleroma.Config.put(config_path, true)
on_exit(fn -> Pleroma.Config.put(config_path, initial_setting) end)
:ok
end
@ -163,7 +170,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
describe "/object/:uuid/likes" do
test "it returns the like activities in a collection", %{conn: conn} do
like = insert(:like_activity)
uuid = String.split(like.data["object"], "/") |> List.last()
like_object_ap_id = Object.normalize(like).data["id"]
uuid = String.split(like_object_ap_id, "/") |> List.last()
result =
conn
@ -302,6 +310,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it returns a note activity in a collection", %{conn: conn} do
note_activity = insert(:direct_note_activity)
note_object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(hd(note_activity.data["to"]))
conn =
@ -310,7 +319,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> put_req_header("accept", "application/activity+json")
|> get("/users/#{user.nickname}/inbox")
assert response(conn, 200) =~ note_activity.data["object"]["content"]
assert response(conn, 200) =~ note_object.data["content"]
end
test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do
@ -388,6 +397,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it returns a note activity in a collection", %{conn: conn} do
note_activity = insert(:note_activity)
note_object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
conn =
@ -395,7 +405,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> put_req_header("accept", "application/activity+json")
|> get("/users/#{user.nickname}/outbox")
assert response(conn, 200) =~ note_activity.data["object"]["content"]
assert response(conn, 200) =~ note_object.data["content"]
end
test "it returns an announce activity in a collection", %{conn: conn} do
@ -457,12 +467,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it erects a tombstone when receiving a delete activity", %{conn: conn} do
note_activity = insert(:note_activity)
note_object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
data = %{
type: "Delete",
object: %{
id: note_activity.data["object"]["id"]
id: note_object.data["id"]
}
}
@ -475,19 +486,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
result = json_response(conn, 201)
assert Activity.get_by_ap_id(result["id"])
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
assert object
assert object = Object.get_by_ap_id(note_object.data["id"])
assert object.data["type"] == "Tombstone"
end
test "it rejects delete activity of object from other actor", %{conn: conn} do
note_activity = insert(:note_activity)
note_object = Object.normalize(note_activity)
user = insert(:user)
data = %{
type: "Delete",
object: %{
id: note_activity.data["object"]["id"]
id: note_object.data["id"]
}
}
@ -502,12 +513,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
test "it increases like count when receiving a like action", %{conn: conn} do
note_activity = insert(:note_activity)
note_object = Object.normalize(note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
data = %{
type: "Like",
object: %{
id: note_activity.data["object"]["id"]
id: note_object.data["id"]
}
}
@ -520,8 +532,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
result = json_response(conn, 201)
assert Activity.get_by_ap_id(result["id"])
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
assert object
assert object = Object.get_by_ap_id(note_object.data["id"])
assert object.data["like_count"] == 1
end
end

View file

@ -254,10 +254,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
}
{:ok, %Activity{} = activity} = ActivityPub.insert(data)
object = Object.normalize(activity.data["object"])
assert object = Object.normalize(activity)
assert is_binary(object.data["id"])
assert %Object{} = Object.get_by_ap_id(activity.data["object"])
end
end
@ -659,7 +657,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
describe "like an object" do
test "adds a like activity to the db" do
note_activity = insert(:note_activity)
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
assert object = Object.normalize(note_activity)
user = insert(:user)
user_two = insert(:user)
@ -678,19 +677,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert like_activity == same_like_activity
assert object.data["likes"] == [user.ap_id]
assert object.data["like_count"] == 1
[note_activity] = Activity.get_all_create_by_object_ap_id(object.data["id"])
assert note_activity.data["object"]["like_count"] == 1
{:ok, _like_activity, object} = ActivityPub.like(user_two, object)
assert object.data["like_count"] == 2
[note_activity] = Activity.get_all_create_by_object_ap_id(object.data["id"])
assert note_activity.data["object"]["like_count"] == 2
end
end
describe "unliking" do
test "unliking a previously liked object" do
note_activity = insert(:note_activity)
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
object = Object.normalize(note_activity)
user = insert(:user)
# Unliking something that hasn't been liked does nothing
@ -710,7 +713,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
describe "announcing an object" do
test "adds an announce activity to the db" do
note_activity = insert(:note_activity)
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
object = Object.normalize(note_activity)
user = insert(:user)
{:ok, announce_activity, object} = ActivityPub.announce(user, object)
@ -731,7 +734,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
describe "unannouncing an object" do
test "unannouncing a previously announced object" do
note_activity = insert(:note_activity)
object = Object.get_by_ap_id(note_activity.data["object"]["id"])
object = Object.normalize(note_activity)
user = insert(:user)
# Unannouncing an object that is not announced does nothing
@ -810,10 +813,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity.data["type"] == "Undo"
assert activity.data["actor"] == follower.ap_id
assert is_map(activity.data["object"])
assert activity.data["object"]["type"] == "Follow"
assert activity.data["object"]["object"] == followed.ap_id
assert activity.data["object"]["id"] == follow_activity.data["id"]
embedded_object = activity.data["object"]
assert is_map(embedded_object)
assert embedded_object["type"] == "Follow"
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
end
end
@ -839,22 +843,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert activity.data["type"] == "Undo"
assert activity.data["actor"] == blocker.ap_id
assert is_map(activity.data["object"])
assert activity.data["object"]["type"] == "Block"
assert activity.data["object"]["object"] == blocked.ap_id
assert activity.data["object"]["id"] == block_activity.data["id"]
embedded_object = activity.data["object"]
assert is_map(embedded_object)
assert embedded_object["type"] == "Block"
assert embedded_object["object"] == blocked.ap_id
assert embedded_object["id"] == block_activity.data["id"]
end
end
describe "deletion" do
test "it creates a delete activity and deletes the original object" do
note = insert(:note_activity)
object = Object.get_by_ap_id(note.data["object"]["id"])
object = Object.normalize(note)
{:ok, delete} = ActivityPub.delete(object)
assert delete.data["type"] == "Delete"
assert delete.data["actor"] == note.data["actor"]
assert delete.data["object"] == note.data["object"]["id"]
assert delete.data["object"] == object.data["id"]
assert Activity.get_by_id(delete.id) != nil
@ -900,13 +905,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do
user = insert(:user)
note = insert(:note_activity)
object = Object.normalize(note)
{:ok, object} =
Object.get_by_ap_id(note.data["object"]["id"])
object
|> Object.change(%{
data: %{
"actor" => note.data["object"]["actor"],
"id" => note.data["object"]["id"],
"actor" => object.data["actor"],
"id" => object.data["id"],
"to" => [user.ap_id],
"type" => "Note"
}
@ -1018,8 +1024,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert update.data["actor"] == user.ap_id
assert update.data["to"] == [user.follower_address]
assert update.data["object"]["id"] == user_data["id"]
assert update.data["object"]["type"] == user_data["type"]
assert embedded_object = update.data["object"]
assert embedded_object["id"] == user_data["id"]
assert embedded_object["type"] == user_data["type"]
end
end

View file

@ -0,0 +1,145 @@
# Pleroma: A lightweight social networking server
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
use Pleroma.DataCase
import Pleroma.Factory
import ExUnit.CaptureLog
alias Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy
@linkless_message %{
"type" => "Create",
"object" => %{
"content" => "hi world!"
}
}
@linkful_message %{
"type" => "Create",
"object" => %{
"content" => "<a href='https://example.com'>hi world!</a>"
}
}
@response_message %{
"type" => "Create",
"object" => %{
"name" => "yes",
"type" => "Answer"
}
}
describe "with new user" do
test "it allows posts without links" do
user = insert(:user)
assert user.info.note_count == 0
message =
@linkless_message
|> Map.put("actor", user.ap_id)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
end
test "it disallows posts with links" do
user = insert(:user)
assert user.info.note_count == 0
message =
@linkful_message
|> Map.put("actor", user.ap_id)
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end
end
describe "with old user" do
test "it allows posts without links" do
user = insert(:user, info: %{note_count: 1})
assert user.info.note_count == 1
message =
@linkless_message
|> Map.put("actor", user.ap_id)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
end
test "it allows posts with links" do
user = insert(:user, info: %{note_count: 1})
assert user.info.note_count == 1
message =
@linkful_message
|> Map.put("actor", user.ap_id)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
end
end
describe "with followed new user" do
test "it allows posts without links" do
user = insert(:user, info: %{follower_count: 1})
assert user.info.follower_count == 1
message =
@linkless_message
|> Map.put("actor", user.ap_id)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
end
test "it allows posts with links" do
user = insert(:user, info: %{follower_count: 1})
assert user.info.follower_count == 1
message =
@linkful_message
|> Map.put("actor", user.ap_id)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
end
end
describe "with unknown actors" do
test "it rejects posts without links" do
message =
@linkless_message
|> Map.put("actor", "http://invalid.actor")
assert capture_log(fn ->
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
end
test "it rejects posts with links" do
message =
@linkful_message
|> Map.put("actor", "http://invalid.actor")
assert capture_log(fn ->
{:reject, _} = AntiLinkSpamPolicy.filter(message)
end) =~ "[error] Could not decode user at fetch http://invalid.actor"
end
end
describe "with contentless-objects" do
test "it does not reject them or error out" do
user = insert(:user, info: %{note_count: 1})
message =
@response_message
|> Map.put("actor", user.ap_id)
{:ok, _message} = AntiLinkSpamPolicy.filter(message)
end
end
end

View file

@ -0,0 +1,82 @@
# Pleroma: A lightweight social networking server
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
use Pleroma.DataCase
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.MRF.EnsureRePrepended
describe "rewrites summary" do
test "it adds `re:` to summary object when child summary and parent summary equal" do
message = %{
"type" => "Create",
"object" => %{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "object-summary"}}}
}
}
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res["object"]["summary"] == "re: object-summary"
end
test "it adds `re:` to summary object when child summary containts re-subject of parent summary " do
message = %{
"type" => "Create",
"object" => %{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "re: object-summary"}}}
}
}
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res["object"]["summary"] == "re: object-summary"
end
end
describe "skip filter" do
test "it skip if type isn't 'Create'" do
message = %{
"type" => "Annotation",
"object" => %{"summary" => "object-summary"}
}
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res == message
end
test "it skip if summary is empty" do
message = %{
"type" => "Create",
"object" => %{
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
}
}
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res == message
end
test "it skip if inReplyTo is empty" do
message = %{"type" => "Create", "object" => %{"summary" => "summary"}}
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res == message
end
test "it skip if parent and child summary isn't equal" do
message = %{
"type" => "Create",
"object" => %{
"summary" => "object-summary",
"inReplyTo" => %Activity{object: %Object{data: %{"summary" => "summary"}}}
}
}
assert {:ok, res} = EnsureRePrepended.filter(message)
assert res == message
end
end
end

View file

@ -0,0 +1,45 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicyTest do
use Pleroma.DataCase
alias Pleroma.HTTP
alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy
import Mock
@message %{
"type" => "Create",
"object" => %{
"type" => "Note",
"content" => "content",
"attachment" => [
%{"url" => [%{"href" => "http://example.com/image.jpg"}]}
]
}
}
test "it prefetches media proxy URIs" do
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
MediaProxyWarmingPolicy.filter(@message)
assert called(HTTP.get(:_, :_, :_))
end
end
test "it does nothing when no attachments are present" do
object =
@message["object"]
|> Map.delete("attachment")
message =
@message
|> Map.put("object", object)
with_mock HTTP, get: fn _, _, _ -> {:ok, []} end do
MediaProxyWarmingPolicy.filter(message)
refute called(HTTP.get(:_, :_, :_))
end
end
end

View file

@ -0,0 +1,37 @@
# Pleroma: A lightweight social networking server
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
use Pleroma.DataCase
alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
test "it clears content object" do
message = %{
"type" => "Create",
"object" => %{"content" => ".", "attachment" => "image"}
}
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
assert res["object"]["content"] == ""
message = put_in(message, ["object", "content"], "<p>.</p>")
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
assert res["object"]["content"] == ""
end
@messages [
%{
"type" => "Create",
"object" => %{"content" => "test", "attachment" => "image"}
},
%{"type" => "Create", "object" => %{"content" => "."}},
%{"type" => "Create", "object" => %{"content" => "<p>.</p>"}}
]
test "it skips filter" do
Enum.each(@messages, fn message ->
assert {:ok, res} = NoPlaceholderTextPolicy.filter(message)
assert res == message
end)
end
end

View file

@ -0,0 +1,42 @@
# Pleroma: A lightweight social networking server
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
use Pleroma.DataCase
alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
@html_sample """
<b>this is in bold</b>
<p>this is a paragraph</p>
this is a linebreak<br />
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a>
this is an image: <img src="http://example.com/image.jpg"><br />
<script>alert('hacked')</script>
"""
test "it filter html tags" do
expected = """
<b>this is in bold</b>
<p>this is a paragraph</p>
this is a linebreak<br />
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
this is an image: <img src="http://example.com/image.jpg" /><br />
alert('hacked')
"""
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
assert {:ok, res} = NormalizeMarkup.filter(message)
assert res["object"]["content"] == expected
end
test "it skips filter if type isn't `Create`" do
message = %{"type" => "Note", "object" => %{}}
assert {:ok, res} = NormalizeMarkup.filter(message)
assert res == message
end
end

View file

@ -0,0 +1,105 @@
# Pleroma: A lightweight social networking server
# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.ActivityPub.MRF.RejectNonPublic
setup do
policy = Pleroma.Config.get([:mrf_rejectnonpublic])
on_exit(fn -> Pleroma.Config.put([:mrf_rejectnonpublic], policy) end)
:ok
end
describe "public message" do
test "it's allowed when address is public" do
actor = insert(:user, follower_address: "test-address")
message = %{
"actor" => actor.ap_id,
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
"type" => "Create"
}
assert {:ok, message} = RejectNonPublic.filter(message)
end
test "it's allowed when cc address contain public address" do
actor = insert(:user, follower_address: "test-address")
message = %{
"actor" => actor.ap_id,
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
"type" => "Create"
}
assert {:ok, message} = RejectNonPublic.filter(message)
end
end
describe "followers message" do
test "it's allowed when addrer of message in the follower addresses of user and it enabled in config" do
actor = insert(:user, follower_address: "test-address")
message = %{
"actor" => actor.ap_id,
"to" => ["test-address"],
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
"type" => "Create"
}
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], true)
assert {:ok, message} = RejectNonPublic.filter(message)
end
test "it's rejected when addrer of message in the follower addresses of user and it disabled in config" do
actor = insert(:user, follower_address: "test-address")
message = %{
"actor" => actor.ap_id,
"to" => ["test-address"],
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
"type" => "Create"
}
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false)
assert {:reject, nil} = RejectNonPublic.filter(message)
end
end
describe "direct message" do
test "it's allows when direct messages are allow" do
actor = insert(:user)
message = %{
"actor" => actor.ap_id,
"to" => ["https://www.w3.org/ns/activitystreams#Publid"],
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
"type" => "Create"
}
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], true)
assert {:ok, message} = RejectNonPublic.filter(message)
end
test "it's reject when direct messages aren't allow" do
actor = insert(:user)
message = %{
"actor" => actor.ap_id,
"to" => ["https://www.w3.org/ns/activitystreams#Publid~~~"],
"cc" => ["https://www.w3.org/ns/activitystreams#Publid"],
"type" => "Create"
}
Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false)
assert {:reject, nil} = RejectNonPublic.filter(message)
end
end
end

View file

@ -0,0 +1,123 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.ActivityPub.MRF.TagPolicy
@public "https://www.w3.org/ns/activitystreams#Public"
describe "mrf_tag:disable-any-subscription" do
test "rejects message" do
actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"])
message = %{"object" => actor.ap_id, "type" => "Follow"}
assert {:reject, nil} = TagPolicy.filter(message)
end
end
describe "mrf_tag:disable-remote-subscription" do
test "rejects non-local follow requests" do
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
assert {:reject, nil} = TagPolicy.filter(message)
end
test "allows non-local follow requests" do
actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])
follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: true)
message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id}
assert {:ok, message} = TagPolicy.filter(message)
end
end
describe "mrf_tag:sandbox" do
test "removes from public timelines" do
actor = insert(:user, tags: ["mrf_tag:sandbox"])
message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{},
"to" => [@public, "f"],
"cc" => [@public, "d"]
}
except_message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d"]},
"to" => ["f", actor.follower_address],
"cc" => ["d"]
}
assert TagPolicy.filter(message) == {:ok, except_message}
end
end
describe "mrf_tag:force-unlisted" do
test "removes from the federated timeline" do
actor = insert(:user, tags: ["mrf_tag:force-unlisted"])
message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{},
"to" => [@public, "f"],
"cc" => [actor.follower_address, "d"]
}
except_message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{"to" => ["f", actor.follower_address], "cc" => ["d", @public]},
"to" => ["f", actor.follower_address],
"cc" => ["d", @public]
}
assert TagPolicy.filter(message) == {:ok, except_message}
end
end
describe "mrf_tag:media-strip" do
test "removes attachments" do
actor = insert(:user, tags: ["mrf_tag:media-strip"])
message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{"attachment" => ["file1"]}
}
except_message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{}
}
assert TagPolicy.filter(message) == {:ok, except_message}
end
end
describe "mrf_tag:media-force-nsfw" do
test "Mark as sensitive on presence of attachments" do
actor = insert(:user, tags: ["mrf_tag:media-force-nsfw"])
message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{"tag" => ["test"], "attachment" => ["file1"]}
}
except_message = %{
"actor" => actor.ap_id,
"type" => "Create",
"object" => %{"tag" => ["test", "nsfw"], "attachment" => ["file1"], "sensitive" => true}
}
assert TagPolicy.filter(message) == {:ok, except_message}
end
end
end

View file

@ -0,0 +1,36 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy
setup do
policy = Pleroma.Config.get([:mrf_user_allowlist]) || []
on_exit(fn -> Pleroma.Config.put([:mrf_user_allowlist], policy) end)
:ok
end
test "pass filter if allow list is empty" do
actor = insert(:user)
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:ok, message}
end
test "pass filter if allow list isn't empty and user in allow list" do
actor = insert(:user)
Pleroma.Config.put([:mrf_user_allowlist, :localhost], [actor.ap_id, "test-ap-id"])
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:ok, message}
end
test "rejected if allow list isn't empty and user not in allow list" do
actor = insert(:user)
Pleroma.Config.put([:mrf_user_allowlist, :localhost], ["test-ap-id"])
message = %{"actor" => actor.ap_id}
assert UserAllowListPolicy.filter(message) == {:reject, nil}
end
end

View file

@ -0,0 +1,143 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do
use Pleroma.DataCase
alias Pleroma.Activity
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
import Pleroma.Factory
import Ecto.Query
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "handle_incoming" do
test "it works for incoming follow requests" do
user = insert(:user)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Follow"
assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
activity = Repo.get(Activity, activity.id)
assert activity.data["state"] == "accept"
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
test "with locked accounts, it does not create a follow or an accept" do
user = insert(:user, info: %{locked: true})
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["state"] == "pending"
refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
accepts =
from(
a in Activity,
where: fragment("?->>'type' = ?", a.data, "Accept")
)
|> Repo.all()
assert length(accepts) == 0
end
test "it works for follow requests when you are already followed, creating a new accept activity" do
# This is important because the remote might have the wrong idea about the
# current follow status. This can lead to instance A thinking that x@A is
# followed by y@B, but B thinks they are not. In this case, the follow can
# never go through again because it will never get an Accept.
user = insert(:user)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
accepts =
from(
a in Activity,
where: fragment("?->>'type' = ?", a.data, "Accept")
)
|> Repo.all()
assert length(accepts) == 1
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("id", String.replace(data["id"], "2", "3"))
|> Map.put("object", user.ap_id)
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
accepts =
from(
a in Activity,
where: fragment("?->>'type' = ?", a.data, "Accept")
)
|> Repo.all()
assert length(accepts) == 2
end
test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
Pleroma.Config.put([:user, :deny_follow_blocked], true)
user = insert(:user)
{:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
{:ok, user} = User.block(user, target)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
%Activity{} = activity = Activity.get_by_ap_id(id)
assert activity.data["state"] == "reject"
end
test "it works for incoming follow requests from hubzilla" do
user = insert(:user)
data =
File.read!("test/fixtures/hubzilla-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
|> Utils.normalize_params()
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
assert data["type"] == "Follow"
assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
end
end

View file

@ -11,12 +11,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OStatus
alias Pleroma.Web.Websub.WebsubClientSubscription
import Mock
import Pleroma.Factory
alias Pleroma.Web.CommonAPI
import ExUnit.CaptureLog
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
@ -30,7 +31,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"])
|> Map.put("object", Object.normalize(activity).data)
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
@ -46,12 +47,9 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
data["object"]
|> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
data =
data
|> Map.put("object", object)
data = Map.put(data, "object", object)
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
returned_object = Object.normalize(returned_activity.data["object"])
returned_object = Object.normalize(returned_activity, false)
assert activity =
Activity.get_create_by_object_ap_id(
@ -61,6 +59,50 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
end
test "it does not fetch replied-to activities beyond max_replies_depth" 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_incoming_reply_depth?: 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["inReplyToAtomUri"] ==
"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) =~ "[error] Couldn't fetch \"\"https://404.site/whatever\"\", error: nil"
end
test "it works for incoming notices" do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
@ -81,25 +123,27 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert data["actor"] == "http://mastodon.example.org/users/admin"
object = Object.normalize(data["object"]).data
assert object["id"] == "http://mastodon.example.org/users/admin/statuses/99512778738411822"
object_data = Object.normalize(data["object"]).data
assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
assert object_data["id"] ==
"http://mastodon.example.org/users/admin/statuses/99512778738411822"
assert object["cc"] == [
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["actor"] == "http://mastodon.example.org/users/admin"
assert object["attributedTo"] == "http://mastodon.example.org/users/admin"
assert object_data["actor"] == "http://mastodon.example.org/users/admin"
assert object_data["attributedTo"] == "http://mastodon.example.org/users/admin"
assert object["context"] ==
assert object_data["context"] ==
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
assert object["sensitive"] == true
assert object_data["sensitive"] == true
user = User.get_cached_by_ap_id(object["actor"])
user = User.get_cached_by_ap_id(object_data["actor"])
assert user.info.note_count == 1
end
@ -248,59 +292,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert object_data["cc"] == to
end
test "it works for incoming follow requests" do
user = insert(:user)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Follow"
assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
Pleroma.Config.put([:user, :deny_follow_blocked], true)
user = insert(:user)
{:ok, target} = User.get_or_fetch("http://mastodon.example.org/users/admin")
{:ok, user} = User.block(user, target)
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
%Activity{} = activity = Activity.get_by_ap_id(id)
assert activity.data["state"] == "reject"
end
test "it works for incoming follow requests from hubzilla" do
user = insert(:user)
data =
File.read!("test/fixtures/hubzilla-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
|> Utils.normalize_params()
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
assert data["type"] == "Follow"
assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
test "it works for incoming likes" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
@ -554,11 +545,38 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
data
|> Map.put("object", object)
:error = Transmogrifier.handle_incoming(data)
assert capture_log(fn ->
:error = Transmogrifier.handle_incoming(data)
end) =~
"[error] Could not decode user at fetch http://mastodon.example.org/users/gargron, {:error, {:error, :nxdomain}}"
assert Activity.get_by_id(activity.id)
end
test "it works for incoming user deletes" do
%{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
data =
File.read!("test/fixtures/mastodon-delete-user.json")
|> Poison.decode!()
{:ok, _} = Transmogrifier.handle_incoming(data)
refute User.get_cached_by_ap_id(ap_id)
end
test "it fails for incoming user deletes with spoofed origin" do
%{ap_id: ap_id} = insert(:user)
data =
File.read!("test/fixtures/mastodon-delete-user.json")
|> Poison.decode!()
|> Map.put("actor", ap_id)
assert :error == Transmogrifier.handle_incoming(data)
assert User.get_cached_by_ap_id(ap_id)
end
test "it works for incoming unannounces with an existing notice" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
@ -580,10 +598,11 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["type"] == "Undo"
assert data["object"]["type"] == "Announce"
assert data["object"]["object"] == activity.data["object"]
assert object_data = data["object"]
assert object_data["type"] == "Announce"
assert object_data["object"] == activity.data["object"]
assert data["object"]["id"] ==
assert object_data["id"] ==
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
end
@ -893,7 +912,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
object = Object.normalize(activity.data["object"])
object = Object.normalize(activity)
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",

View file

@ -1,7 +1,12 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.UtilsTest do
use Pleroma.DataCase
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
@ -247,4 +252,51 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
assert fetched_vote.id == vote.id
end
end
describe "update_follow_state_for_all/2" do
test "updates the state of all Follow activities with the same actor and object" do
user = insert(:user, info: %{locked: true})
follower = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, user)
{:ok, follow_activity_two} = ActivityPub.follow(follower, user)
data =
follow_activity_two.data
|> Map.put("state", "accept")
cng = Ecto.Changeset.change(follow_activity_two, data: data)
{:ok, follow_activity_two} = Repo.update(cng)
{:ok, follow_activity_two} =
Utils.update_follow_state_for_all(follow_activity_two, "accept")
assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
end
end
describe "update_follow_state/2" do
test "updates the state of the given follow activity" do
user = insert(:user, info: %{locked: true})
follower = insert(:user)
{:ok, follow_activity} = ActivityPub.follow(follower, user)
{:ok, follow_activity_two} = ActivityPub.follow(follower, user)
data =
follow_activity_two.data
|> Map.put("state", "accept")
cng = Ecto.Changeset.change(follow_activity_two, data: data)
{:ok, follow_activity_two} = Repo.update(cng)
{:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
assert Repo.get(Activity, follow_activity.id).data["state"] == "pending"
assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
end
end
end

View file

@ -1,7 +1,12 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.CommonAPI
@ -19,19 +24,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
test "renders a note activity" do
note = insert(:note_activity)
object = Object.normalize(note)
result = ObjectView.render("object.json", %{object: note})
assert result["id"] == note.data["id"]
assert result["to"] == note.data["to"]
assert result["object"]["type"] == "Note"
assert result["object"]["content"] == note.data["object"]["content"]
assert result["object"]["content"] == object.data["content"]
assert result["type"] == "Create"
assert result["@context"]
end
test "renders a like activity" do
note = insert(:note_activity)
object = Object.normalize(note)
user = insert(:user)
{:ok, like_activity, _} = CommonAPI.favorite(note.id, user)
@ -39,12 +46,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
result = ObjectView.render("object.json", %{object: like_activity})
assert result["id"] == like_activity.data["id"]
assert result["object"] == note.data["object"]["id"]
assert result["object"] == object.data["id"]
assert result["type"] == "Like"
end
test "renders an announce activity" do
note = insert(:note_activity)
object = Object.normalize(note)
user = insert(:user)
{:ok, announce_activity, _} = CommonAPI.repeat(note.id, user)
@ -52,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
result = ObjectView.render("object.json", %{object: announce_activity})
assert result["id"] == announce_activity.data["id"]
assert result["object"] == note.data["object"]["id"]
assert result["object"] == object.data["id"]
assert result["type"] == "Announce"
end
end

View file

@ -1,3 +1,7 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.UserViewTest do
use Pleroma.DataCase
import Pleroma.Factory

View file

@ -1,3 +1,7 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.VisibilityTest do
use Pleroma.DataCase