2018-12-23 15:11:29 -05:00
# Pleroma: A lightweight social networking server
2020-03-02 00:08:45 -05:00
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
2018-12-23 15:11:29 -05:00
# SPDX-License-Identifier: AGPL-3.0-only
2018-02-15 14:00:06 -05:00
defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
2020-01-25 02:47:30 -05:00
use Oban.Testing , repo : Pleroma.Repo
2018-02-15 14:00:06 -05:00
use Pleroma.DataCase
2020-01-25 02:47:30 -05:00
2019-03-04 21:52:23 -05:00
alias Pleroma.Activity
2019-03-14 15:04:33 -04:00
alias Pleroma.Object
2019-04-17 10:03:35 -04:00
alias Pleroma.Object.Fetcher
2019-08-13 13:20:26 -04:00
alias Pleroma.Tests.ObanHelpers
2019-03-04 21:52:23 -05:00
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
2018-02-15 14:00:06 -05:00
alias Pleroma.Web.ActivityPub.Transmogrifier
2019-10-23 15:27:22 -04:00
alias Pleroma.Web.AdminAPI.AccountView
2019-06-29 13:04:50 -04:00
alias Pleroma.Web.CommonAPI
2018-02-17 14:13:12 -05:00
2019-06-29 13:04:50 -04:00
import Mock
2018-02-17 08:11:20 -05:00
import Pleroma.Factory
2019-06-16 07:42:29 -04:00
import ExUnit.CaptureLog
2018-02-15 14:00:06 -05:00
2018-12-04 06:01:39 -05:00
setup_all do
Tesla.Mock . mock_global ( fn env -> apply ( HttpRequestMock , :request , [ env ] ) end )
2018-12-03 10:53:22 -05:00
:ok
end
2020-03-20 11:33:00 -04:00
setup do : clear_config ( [ :instance , :max_remote_account_fields ] )
2019-08-21 14:24:35 -04:00
2018-02-15 14:00:06 -05:00
describe " handle_incoming " do
2020-05-18 08:48:37 -04:00
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 works for incoming notices with url not being a string (prismo) " do
data = File . read! ( " test/fixtures/prismo-url-map.json " ) |> Poison . decode! ( )
{ :ok , % Activity { data : data , local : false } } = Transmogrifier . handle_incoming ( data )
object = Object . normalize ( data [ " object " ] )
assert object . data [ " url " ] == " https://prismo.news/posts/83 "
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
2018-02-19 11:37:45 -05:00
test " it ignores an incoming notice if we already have it " do
activity = insert ( :note_activity )
2018-03-30 09:01:53 -04:00
data =
File . read! ( " test/fixtures/mastodon-post-activity.json " )
|> Poison . decode! ( )
2019-07-08 12:53:02 -04:00
|> Map . put ( " object " , Object . normalize ( activity ) . data )
2018-02-19 11:37:45 -05:00
{ :ok , returned_activity } = Transmogrifier . handle_incoming ( data )
assert activity == returned_activity
end
2019-11-28 04:44:48 -05:00
@tag capture_log : true
2020-02-15 12:41:38 -05:00
test " it fetches reply-to activities if we don't have them " do
2018-03-30 09:01:53 -04:00
data =
File . read! ( " test/fixtures/mastodon-post-activity.json " )
|> Poison . decode! ( )
2018-02-21 09:22:24 -05:00
2018-03-30 09:01:53 -04:00
object =
data [ " object " ]
|> Map . put ( " inReplyTo " , " https://shitposter.club/notice/2827873 " )
2018-02-21 09:22:24 -05:00
2019-06-29 13:04:50 -04:00
data = Map . put ( data , " object " , object )
2018-02-21 09:22:24 -05:00
{ :ok , returned_activity } = Transmogrifier . handle_incoming ( data )
2019-07-09 14:46:16 -04:00
returned_object = Object . normalize ( returned_activity , false )
2018-02-21 09:22:24 -05:00
2018-03-30 09:01:53 -04:00
assert activity =
2019-01-21 01:14:20 -05:00
Activity . get_create_by_object_ap_id (
2018-03-30 09:01:53 -04:00
" tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment "
)
2018-11-25 17:31:07 -05:00
assert returned_object . data [ " inReplyToAtomUri " ] == " https://shitposter.club/notice/2827873 "
2018-02-25 04:56:01 -05:00
end
2020-02-15 12:41:38 -05:00
test " it does not fetch reply-to activities beyond max replies depth limit " do
2019-06-29 13:04:50 -04:00
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 ,
2020-02-15 12:41:38 -05:00
allowed_thread_distance? : fn _ -> false end do
2019-06-29 13:04:50 -04:00
{ :ok , returned_activity } = Transmogrifier . handle_incoming ( data )
2019-07-09 14:46:16 -04:00
returned_object = Object . normalize ( returned_activity , false )
2019-06-29 13:04:50 -04:00
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
2019-06-07 13:40:38 -04:00
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 " ]
2019-06-07 13:48:25 -04:00
|> Map . put ( " inReplyTo " , " https://404.site/whatever " )
2019-06-07 13:40:38 -04:00
data =
data
|> Map . put ( " object " , object )
2019-06-16 07:42:29 -04:00
assert capture_log ( fn ->
{ :ok , _returned_activity } = Transmogrifier . handle_incoming ( data )
2019-09-12 13:29:08 -04:00
end ) =~ " [error] Couldn't fetch \" https://404.site/whatever \" , error: nil "
2019-06-07 13:40:38 -04:00
end
2018-02-15 14:00:06 -05:00
test " it works for incoming notices " do
2018-03-30 09:01:53 -04:00
data = File . read! ( " test/fixtures/mastodon-post-activity.json " ) |> Poison . decode! ( )
2018-02-15 14:00:06 -05:00
{ :ok , % Activity { data : data , local : false } } = Transmogrifier . handle_incoming ( data )
2018-03-30 09:01:53 -04:00
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 "
2018-02-15 14:00:06 -05:00
assert data [ " to " ] == [ " https://www.w3.org/ns/activitystreams # Public " ]
2018-03-30 09:01:53 -04:00
2018-02-15 14:00:06 -05:00
assert data [ " cc " ] == [
2018-03-30 09:01:53 -04:00
" http://mastodon.example.org/users/admin/followers " ,
" http://localtesting.pleroma.lol/users/lain "
]
2018-02-15 14:00:06 -05:00
assert data [ " actor " ] == " http://mastodon.example.org/users/admin "
2019-07-08 12:53:02 -04:00
object_data = Object . normalize ( data [ " object " ] ) . data
assert object_data [ " id " ] ==
" http://mastodon.example.org/users/admin/statuses/99512778738411822 "
2018-02-15 14:00:06 -05:00
2019-07-08 12:53:02 -04:00
assert object_data [ " to " ] == [ " https://www.w3.org/ns/activitystreams # Public " ]
2018-03-30 09:01:53 -04:00
2019-07-08 12:53:02 -04:00
assert object_data [ " cc " ] == [
2018-03-30 09:01:53 -04:00
" http://mastodon.example.org/users/admin/followers " ,
" http://localtesting.pleroma.lol/users/lain "
]
2019-07-08 12:53:02 -04:00
assert object_data [ " actor " ] == " http://mastodon.example.org/users/admin "
assert object_data [ " attributedTo " ] == " http://mastodon.example.org/users/admin "
2018-03-30 09:01:53 -04:00
2019-07-08 12:53:02 -04:00
assert object_data [ " context " ] ==
2018-03-30 09:01:53 -04:00
" tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation "
2019-07-08 12:53:02 -04:00
assert object_data [ " sensitive " ] == true
2018-04-22 04:01:10 -04:00
2019-07-08 12:53:02 -04:00
user = User . get_cached_by_ap_id ( object_data [ " actor " ] )
2018-04-22 04:01:10 -04:00
2019-10-16 14:59:21 -04:00
assert user . note_count == 1
2018-02-15 14:00:06 -05:00
end
2018-02-17 08:55:44 -05:00
2018-03-24 17:39:37 -04:00
test " it works for incoming notices with hashtags " do
2018-03-30 09:01:53 -04:00
data = File . read! ( " test/fixtures/mastodon-post-activity-hashtag.json " ) |> Poison . decode! ( )
2018-03-24 17:39:37 -04:00
{ :ok , % Activity { data : data , local : false } } = Transmogrifier . handle_incoming ( data )
2018-11-25 17:31:07 -05:00
object = Object . normalize ( data [ " object " ] )
assert Enum . at ( object . data [ " tag " ] , 2 ) == " moo "
2018-03-24 17:39:37 -04:00
end
2019-05-15 13:10:16 -04:00
test " it works for incoming questions " do
data = File . read! ( " test/fixtures/mastodon-question-activity.json " ) |> Poison . decode! ( )
{ :ok , % Activity { local : false } = activity } = Transmogrifier . handle_incoming ( data )
object = Object . normalize ( activity )
assert Enum . all? ( object . data [ " oneOf " ] , fn choice ->
choice [ " name " ] in [
" Dunno " ,
" Everyone knows that! " ,
" 25 char limit is dumb " ,
" I can't even fit a funny "
]
end )
end
2019-09-27 08:40:31 -04:00
test " it works for incoming listens " do
data = %{
" @context " = > " https://www.w3.org/ns/activitystreams " ,
" to " = > [ " https://www.w3.org/ns/activitystreams # Public " ] ,
" cc " = > [ ] ,
" type " = > " Listen " ,
" id " = > " http://mastodon.example.org/users/admin/listens/1234/activity " ,
" actor " = > " http://mastodon.example.org/users/admin " ,
" object " = > %{
" type " = > " Audio " ,
" id " = > " http://mastodon.example.org/users/admin/listens/1234 " ,
" attributedTo " = > " http://mastodon.example.org/users/admin " ,
" title " = > " lain radio episode 1 " ,
" artist " = > " lain " ,
" album " = > " lain radio " ,
" length " = > 180_000
}
}
{ :ok , % Activity { local : false } = activity } = Transmogrifier . handle_incoming ( data )
object = Object . normalize ( activity )
assert object . data [ " title " ] == " lain radio episode 1 "
assert object . data [ " artist " ] == " lain "
assert object . data [ " album " ] == " lain radio "
assert object . data [ " length " ] == 180_000
end
2019-05-22 14:17:57 -04:00
test " it rewrites Note votes to Answers and increments vote counters on question activities " do
2019-05-21 07:12:10 -04:00
user = insert ( :user )
{ :ok , activity } =
CommonAPI . post ( user , %{
2020-05-12 15:59:26 -04:00
status : " suya... " ,
poll : %{ options : [ " suya " , " suya. " , " suya.. " ] , expires_in : 10 }
2019-05-21 07:12:10 -04:00
} )
object = Object . normalize ( activity )
data =
File . read! ( " test/fixtures/mastodon-vote.json " )
|> Poison . decode! ( )
|> Kernel . put_in ( [ " to " ] , user . ap_id )
|> Kernel . put_in ( [ " object " , " inReplyTo " ] , object . data [ " id " ] )
|> Kernel . put_in ( [ " object " , " to " ] , user . ap_id )
2019-05-22 14:17:57 -04:00
{ :ok , % Activity { local : false } = activity } = Transmogrifier . handle_incoming ( data )
answer_object = Object . normalize ( activity )
assert answer_object . data [ " type " ] == " Answer "
2019-05-21 07:12:10 -04:00
object = Object . get_by_ap_id ( object . data [ " id " ] )
assert Enum . any? (
object . data [ " oneOf " ] ,
fn
%{ " name " = > " suya.. " , " replies " = > %{ " totalItems " = > 1 } } -> true
_ -> false
end
)
end
2018-06-18 18:11:48 -04:00
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 )
2018-11-25 17:31:07 -05:00
object = Object . normalize ( data [ " object " ] )
2018-06-18 18:11:48 -04:00
2018-11-25 17:31:07 -05:00
assert object . data [ " content " ] ==
2018-06-18 18:11:48 -04:00
" <p><span class= \" h-card \" ><a href= \" http://localtesting.pleroma.lol/users/lain \" class= \" u-url mention \" >@<span>lain</span></a></span></p> "
end
2018-08-14 13:07:01 -04:00
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 )
2018-11-25 17:31:07 -05:00
object = Object . normalize ( data [ " object " ] )
2018-08-14 13:07:01 -04:00
2018-11-25 17:31:07 -05:00
assert object . data [ " content " ] ==
2018-08-14 13:07:01 -04:00
" <p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p> "
end
2019-03-19 13:49:29 -04:00
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 " , [ ] )
2019-07-14 13:49:12 -04:00
|> Map . put ( " id " , user . ap_id <> " /activities/12345678 " )
2019-03-19 13:49:29 -04:00
data = Map . put ( data , " object " , object )
{ :ok , % Activity { data : data , local : false } } = Transmogrifier . handle_incoming ( data )
assert data [ " cc " ] == [ User . ap_followers ( user ) ]
end
2019-03-19 13:53:40 -04:00
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 )
2019-07-14 13:49:12 -04:00
|> Map . put ( " id " , user . ap_id <> " /activities/12345678 " )
2019-03-19 13:53:40 -04:00
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 " ] )
2018-02-17 15:57:31 -05:00
end
2018-02-25 10:14:25 -05:00
2019-08-10 14:47:40 -04:00
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
2019-09-12 12:59:13 -04:00
test " it strips internal reactions " do
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " # cofe " } )
2020-05-05 06:28:28 -04:00
{ :ok , _ } = CommonAPI . react_with_emoji ( activity . id , user , " 📢 " )
2019-09-12 12:59:13 -04:00
%{ 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
2018-05-21 05:00:58 -04:00
test " it works for incomming unfollows with an existing follow " do
2018-05-17 23:55:00 -04:00
user = insert ( :user )
follow_data =
File . read! ( " test/fixtures/mastodon-follow-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " object " , user . ap_id )
{ :ok , % Activity { data : _ , local : false } } = Transmogrifier . handle_incoming ( follow_data )
data =
File . read! ( " test/fixtures/mastodon-unfollow-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " object " , follow_data )
{ :ok , % Activity { data : data , local : false } } = Transmogrifier . handle_incoming ( data )
assert data [ " type " ] == " Undo "
assert data [ " object " ] [ " type " ] == " Follow "
2018-05-19 21:23:52 -04:00
assert data [ " object " ] [ " object " ] == user . ap_id
2018-05-17 23:55:00 -04:00
assert data [ " actor " ] == " http://mastodon.example.org/users/admin "
2019-04-22 03:20:43 -04:00
refute User . following? ( User . get_cached_by_ap_id ( data [ " actor " ] ) , user )
2018-05-17 23:55:00 -04:00
end
2018-05-19 21:23:52 -04:00
2019-10-29 05:46:22 -04:00
test " it works for incoming follows to locked account " do
pending_follower = insert ( :user , ap_id : " http://mastodon.example.org/users/admin " )
user = insert ( :user , locked : true )
data =
File . read! ( " test/fixtures/mastodon-follow-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " object " , user . ap_id )
{ :ok , % Activity { data : data , local : false } } = Transmogrifier . handle_incoming ( data )
assert data [ " type " ] == " Follow "
assert data [ " object " ] == user . ap_id
assert data [ " state " ] == " pending "
assert data [ " actor " ] == " http://mastodon.example.org/users/admin "
assert [ ^ pending_follower ] = User . get_follow_requests ( user )
end
2018-05-25 08:51:04 -04:00
test " it works for incoming accepts which were pre-accepted " do
follower = insert ( :user )
followed = insert ( :user )
{ :ok , follower } = User . follow ( follower , followed )
assert User . following? ( follower , followed ) == true
2018-05-26 07:16:05 -04:00
{ :ok , follow_activity } = ActivityPub . follow ( follower , followed )
2018-05-25 08:51:04 -04:00
accept_data =
File . read! ( " test/fixtures/mastodon-accept-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
2018-05-26 09:11:50 -04:00
object =
accept_data [ " object " ]
|> Map . put ( " actor " , follower . ap_id )
|> Map . put ( " id " , follow_activity . data [ " id " ] )
2018-05-26 09:07:21 -04:00
2018-05-26 09:11:50 -04:00
accept_data = Map . put ( accept_data , " object " , object )
2018-05-25 08:51:04 -04:00
2018-05-26 08:07:46 -04:00
{ :ok , activity } = Transmogrifier . handle_incoming ( accept_data )
refute activity . local
assert activity . data [ " object " ] == follow_activity . data [ " id " ]
2018-05-25 08:51:04 -04:00
2019-10-11 05:48:58 -04:00
assert activity . data [ " id " ] == accept_data [ " id " ]
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-25 08:51:04 -04:00
assert User . following? ( follower , followed ) == true
end
test " it works for incoming accepts which were orphaned " do
follower = insert ( :user )
2019-10-16 14:59:21 -04:00
followed = insert ( :user , locked : true )
2018-05-25 08:51:04 -04:00
{ :ok , follow_activity } = ActivityPub . follow ( follower , followed )
accept_data =
File . read! ( " test/fixtures/mastodon-accept-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
accept_data =
Map . put ( accept_data , " object " , Map . put ( accept_data [ " object " ] , " actor " , follower . ap_id ) )
2018-05-26 08:07:46 -04:00
{ :ok , activity } = Transmogrifier . handle_incoming ( accept_data )
assert activity . data [ " object " ] == follow_activity . data [ " id " ]
2018-05-25 08:51:04 -04:00
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-25 08:51:04 -04:00
assert User . following? ( follower , followed ) == true
end
test " it works for incoming accepts which are referenced by IRI only " do
follower = insert ( :user )
2019-10-16 14:59:21 -04:00
followed = insert ( :user , locked : true )
2018-05-25 08:51:04 -04:00
{ :ok , follow_activity } = ActivityPub . follow ( follower , followed )
accept_data =
File . read! ( " test/fixtures/mastodon-accept-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
|> Map . put ( " object " , follow_activity . data [ " id " ] )
2018-05-26 08:07:46 -04:00
{ :ok , activity } = Transmogrifier . handle_incoming ( accept_data )
assert activity . data [ " object " ] == follow_activity . data [ " id " ]
2018-05-25 08:51:04 -04:00
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-25 08:51:04 -04:00
assert User . following? ( follower , followed ) == true
2020-05-12 06:29:37 -04:00
follower = User . get_by_id ( follower . id )
assert follower . following_count == 1
followed = User . get_by_id ( followed . id )
assert followed . follower_count == 1
2018-05-25 08:51:04 -04:00
end
2018-05-26 07:16:05 -04:00
test " it fails for incoming accepts which cannot be correlated " do
follower = insert ( :user )
2019-10-16 14:59:21 -04:00
followed = insert ( :user , locked : true )
2018-05-26 07:16:05 -04:00
accept_data =
File . read! ( " test/fixtures/mastodon-accept-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
accept_data =
Map . put ( accept_data , " object " , Map . put ( accept_data [ " object " ] , " actor " , follower . ap_id ) )
:error = Transmogrifier . handle_incoming ( accept_data )
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-26 07:16:05 -04:00
refute User . following? ( follower , followed ) == true
end
2018-05-26 08:07:46 -04:00
test " it fails for incoming rejects which cannot be correlated " do
follower = insert ( :user )
2019-10-16 14:59:21 -04:00
followed = insert ( :user , locked : true )
2018-05-26 08:07:46 -04:00
accept_data =
File . read! ( " test/fixtures/mastodon-reject-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
accept_data =
Map . put ( accept_data , " object " , Map . put ( accept_data [ " object " ] , " actor " , follower . ap_id ) )
:error = Transmogrifier . handle_incoming ( accept_data )
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-26 08:07:46 -04:00
refute User . following? ( follower , followed ) == true
end
2018-05-25 08:51:04 -04:00
test " it works for incoming rejects which are orphaned " do
follower = insert ( :user )
2019-10-16 14:59:21 -04:00
followed = insert ( :user , locked : true )
2018-05-25 08:51:04 -04:00
{ :ok , follower } = User . follow ( follower , followed )
2018-05-26 09:07:21 -04:00
{ :ok , _follow_activity } = ActivityPub . follow ( follower , followed )
2018-05-25 08:51:04 -04:00
assert User . following? ( follower , followed ) == true
reject_data =
File . read! ( " test/fixtures/mastodon-reject-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
reject_data =
Map . put ( reject_data , " object " , Map . put ( reject_data [ " object " ] , " actor " , follower . ap_id ) )
2018-05-26 08:07:46 -04:00
{ :ok , activity } = Transmogrifier . handle_incoming ( reject_data )
refute activity . local
2019-10-11 05:48:58 -04:00
assert activity . data [ " id " ] == reject_data [ " id " ]
2018-05-25 08:51:04 -04:00
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-25 08:51:04 -04:00
assert User . following? ( follower , followed ) == false
end
test " it works for incoming rejects which are referenced by IRI only " do
follower = insert ( :user )
2019-10-16 14:59:21 -04:00
followed = insert ( :user , locked : true )
2018-05-25 08:51:04 -04:00
{ :ok , follower } = User . follow ( follower , followed )
{ :ok , follow_activity } = ActivityPub . follow ( follower , followed )
assert User . following? ( follower , followed ) == true
reject_data =
File . read! ( " test/fixtures/mastodon-reject-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " actor " , followed . ap_id )
|> Map . put ( " object " , follow_activity . data [ " id " ] )
{ :ok , % Activity { data : _ } } = Transmogrifier . handle_incoming ( reject_data )
2019-04-22 03:20:43 -04:00
follower = User . get_cached_by_id ( follower . id )
2018-05-25 08:51:04 -04:00
assert User . following? ( follower , followed ) == false
end
2018-08-22 20:55:41 -04:00
test " it rejects activities without a valid ID " do
user = insert ( :user )
data =
File . read! ( " test/fixtures/mastodon-follow-activity.json " )
|> Poison . decode! ( )
|> Map . put ( " object " , user . ap_id )
|> Map . put ( " id " , " " )
:error = Transmogrifier . handle_incoming ( data )
end
2018-12-23 08:28:17 -05:00
2020-04-29 01:13:10 -04:00
test " skip converting the content when it is nil " do
object_id = " https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe "
{ :ok , object } = Fetcher . fetch_and_contain_remote_object_from_id ( object_id )
result =
Pleroma.Web.ActivityPub.Transmogrifier . fix_object ( Map . merge ( object , %{ " content " = > nil } ) )
assert result [ " content " ] == nil
end
2020-04-28 02:32:43 -04:00
test " it converts content of object to html " do
object_id = " https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe "
{ :ok , %{ " content " = > content_markdown } } =
Fetcher . fetch_and_contain_remote_object_from_id ( object_id )
{ :ok , % Pleroma.Object { data : %{ " content " = > content } } = object } =
Fetcher . fetch_object_from_id ( object_id )
assert content_markdown ==
" Support this and our other Michigan!/usr/group videos and meetings. Learn more at http://mug.org/membership \n \n Twenty Years in Jail: FreeBSD's Jails, Then and Now \n \n Jails started as a limited virtualization system, but over the last two years they've... "
assert content ==
" <p>Support this and our other Michigan!/usr/group videos and meetings. Learn more at <a href= \" http://mug.org/membership \" >http://mug.org/membership</a></p><p>Twenty Years in Jail: FreeBSD’ s Jails, Then and Now</p><p>Jails started as a limited virtualization system, but over the last two years they’ ve…</p> "
2020-04-12 23:53:45 -04:00
assert object . data [ " mediaType " ] == " text/html "
end
2018-12-23 08:28:17 -05:00
test " it remaps video URLs as attachments if necessary " do
{ :ok , object } =
2019-04-17 10:03:35 -04:00
Fetcher . fetch_object_from_id (
2018-12-23 08:28:17 -05:00
" https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3 "
)
assert object . data [ " url " ] ==
" https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3 "
2020-05-25 07:13:42 -04:00
assert object . data [ " attachment " ] == [
%{
" type " = > " Link " ,
" mediaType " = > " video/mp4 " ,
" url " = > [
%{
" href " = >
" https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4 " ,
" mediaType " = > " video/mp4 "
}
]
}
]
{ :ok , object } =
Fetcher . fetch_object_from_id (
" https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206 "
)
assert object . data [ " attachment " ] == [
%{
" type " = > " Link " ,
" mediaType " = > " video/mp4 " ,
" url " = > [
%{
" href " = >
" https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4 " ,
" mediaType " = > " video/mp4 "
}
]
}
]
assert object . data [ " url " ] ==
" https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206 "
2018-12-23 08:28:17 -05:00
end
2019-03-14 15:04:33 -04:00
test " it accepts Flag activities " do
user = insert ( :user )
other_user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " test post " } )
2019-07-08 12:53:02 -04:00
object = Object . normalize ( activity )
2019-03-14 15:04:33 -04:00
2019-10-23 15:27:22 -04:00
note_obj = %{
" type " = > " Note " ,
" id " = > activity . data [ " id " ] ,
" content " = > " test post " ,
" published " = > object . data [ " published " ] ,
" actor " = > AccountView . render ( " show.json " , %{ user : user } )
}
2019-03-14 15:04:33 -04:00
message = %{
" @context " = > " https://www.w3.org/ns/activitystreams " ,
" cc " = > [ user . ap_id ] ,
2019-10-27 09:17:37 -04:00
" object " = > [ user . ap_id , activity . data [ " id " ] ] ,
2019-03-14 15:04:33 -04:00
" type " = > " Flag " ,
" content " = > " blocked AND reported!!! " ,
" actor " = > other_user . ap_id
}
assert { :ok , activity } = Transmogrifier . handle_incoming ( message )
2019-10-23 15:27:22 -04:00
assert activity . data [ " object " ] == [ user . ap_id , note_obj ]
2019-03-14 15:04:33 -04:00
assert activity . data [ " content " ] == " blocked AND reported!!! "
assert activity . data [ " actor " ] == other_user . ap_id
assert activity . data [ " cc " ] == [ user . ap_id ]
end
2019-10-22 20:43:31 -04:00
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
2019-10-30 07:21:49 -04:00
test " it accepts Move activities " do
old_user = insert ( :user )
new_user = insert ( :user )
message = %{
" @context " = > " https://www.w3.org/ns/activitystreams " ,
" type " = > " Move " ,
" actor " = > old_user . ap_id ,
" object " = > old_user . ap_id ,
" target " = > new_user . ap_id
}
assert :error = Transmogrifier . handle_incoming ( message )
{ :ok , _new_user } = User . update_and_set_cache ( new_user , %{ also_known_as : [ old_user . ap_id ] } )
assert { :ok , % Activity { } = activity } = Transmogrifier . handle_incoming ( message )
assert activity . actor == old_user . ap_id
assert activity . data [ " actor " ] == old_user . ap_id
assert activity . data [ " object " ] == old_user . ap_id
assert activity . data [ " target " ] == new_user . ap_id
assert activity . data [ " type " ] == " Move "
end
2018-02-15 14:00:06 -05:00
end
2018-02-17 08:11:20 -05:00
2020-02-15 12:41:38 -05:00
describe " `handle_incoming/2`, Mastodon format `replies` handling " do
2020-03-20 11:33:00 -04:00
setup do : clear_config ( [ :activitypub , :note_replies_output_limit ] , 5 )
setup do : clear_config ( [ :instance , :federation_incoming_replies_max_depth ] )
2020-02-15 12:41:38 -05:00
setup do
2020-01-25 02:47:30 -05:00
data =
2020-02-10 03:46:16 -05:00
" test/fixtures/mastodon-post-activity.json "
|> File . read! ( )
2020-01-25 02:47:30 -05:00
|> Poison . decode! ( )
2020-02-10 03:46:16 -05:00
items = get_in ( data , [ " object " , " replies " , " first " , " items " ] )
assert length ( items ) > 0
2020-01-25 02:47:30 -05:00
2020-02-15 12:41:38 -05:00
%{ 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 )
2020-01-25 02:47:30 -05:00
{ :ok , _activity } = Transmogrifier . handle_incoming ( data )
for id <- items do
2020-02-15 12:41:38 -05:00
job_args = %{ " op " = > " fetch_remote " , " id " = > id , " depth " = > 1 }
2020-01-25 02:47:30 -05:00
assert_enqueued ( worker : Pleroma.Workers.RemoteFetcherWorker , args : job_args )
end
end
2020-02-15 12:41:38 -05:00
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
2020-03-20 11:33:00 -04:00
setup do : clear_config ( [ :activitypub , :note_replies_output_limit ] , 5 )
setup do : clear_config ( [ :instance , :federation_incoming_replies_max_depth ] )
2020-02-15 12:41:38 -05:00
setup do
2020-02-10 03:46:16 -05:00
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " post1 " } )
2020-01-25 02:47:30 -05:00
2020-02-10 03:46:16 -05:00
{ :ok , reply1 } =
2020-05-12 15:59:26 -04:00
CommonAPI . post ( user , %{ status : " reply1 " , in_reply_to_status_id : activity . id } )
2020-01-25 02:47:30 -05:00
2020-02-10 03:46:16 -05:00
{ :ok , reply2 } =
2020-05-12 15:59:26 -04:00
CommonAPI . post ( user , %{ status : " reply2 " , in_reply_to_status_id : activity . id } )
2020-02-10 03:46:16 -05:00
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 )
2020-02-15 12:41:38 -05:00
%{ 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 )
2020-02-10 03:46:16 -05:00
{ :ok , _activity } = Transmogrifier . handle_incoming ( federation_output )
for id <- replies_uris do
2020-02-15 12:41:38 -05:00
job_args = %{ " op " = > " fetch_remote " , " id " = > id , " depth " = > 1 }
2020-01-25 02:47:30 -05:00
assert_enqueued ( worker : Pleroma.Workers.RemoteFetcherWorker , args : job_args )
end
end
2020-02-15 12:41:38 -05:00
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
2020-01-25 02:47:30 -05:00
end
2018-02-17 08:11:20 -05:00
describe " prepare outgoing " do
2019-10-02 06:14:08 -04:00
test " it inlines private announced objects " do
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " hey " , visibility : " private " } )
2019-10-02 06:14:08 -04:00
2020-05-21 07:16:21 -04:00
{ :ok , announce_activity } = CommonAPI . repeat ( activity . id , user )
2019-10-02 06:14:08 -04:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( announce_activity . data )
assert modified [ " object " ] [ " content " ] == " hey "
assert modified [ " object " ] [ " actor " ] == modified [ " object " ] [ " attributedTo " ]
end
2018-02-17 08:11:20 -05:00
test " it turns mentions into tags " do
user = insert ( :user )
other_user = insert ( :user )
2018-03-30 09:01:53 -04:00
{ :ok , activity } =
2020-05-12 15:59:26 -04:00
CommonAPI . post ( user , %{ status : " hey, @ #{ other_user . nickname } , how are ya? # 2hu " } )
2018-02-17 08:11:20 -05:00
2020-05-25 09:08:43 -04:00
with_mock Pleroma.Notification ,
get_notified_from_activity : fn _ , _ -> [ ] end do
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
2018-02-17 08:11:20 -05:00
2020-05-25 09:08:43 -04:00
object = modified [ " object " ]
2018-02-19 04:39:03 -05:00
2020-05-25 09:08:43 -04:00
expected_mention = %{
" href " = > other_user . ap_id ,
" name " = > " @ #{ other_user . nickname } " ,
" type " = > " Mention "
}
2018-02-17 08:11:20 -05:00
2020-05-25 09:08:43 -04:00
expected_tag = %{
" href " = > Pleroma.Web.Endpoint . url ( ) <> " /tags/2hu " ,
" type " = > " Hashtag " ,
" name " = > " # 2hu "
}
refute called ( Pleroma.Notification . get_notified_from_activity ( :_ , :_ ) )
assert Enum . member? ( object [ " tag " ] , expected_tag )
assert Enum . member? ( object [ " tag " ] , expected_mention )
end
2018-02-17 08:11:20 -05:00
end
2018-02-18 08:07:13 -05:00
test " it adds the sensitive property " do
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " # nsfw hey " } )
2018-02-18 08:07:13 -05:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert modified [ " object " ] [ " sensitive " ]
end
2018-02-18 07:58:52 -05:00
test " it adds the json-ld context and the conversation property " do
2018-02-17 08:11:20 -05:00
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " hey " } )
2018-02-17 08:11:20 -05:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
2018-11-08 10:39:38 -05:00
assert modified [ " @context " ] ==
Pleroma.Web.ActivityPub.Utils . make_json_ld_header ( ) [ " @context " ]
2018-02-18 07:58:52 -05:00
assert modified [ " object " ] [ " conversation " ] == modified [ " context " ]
2018-02-17 08:11:20 -05:00
end
test " it sets the 'attributedTo' property to the actor of the object if it doesn't have one " do
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " hey " } )
2018-02-17 08:11:20 -05:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert modified [ " object " ] [ " actor " ] == modified [ " object " ] [ " attributedTo " ]
end
2018-03-13 13:46:37 -04:00
2018-11-10 07:16:10 -05:00
test " it strips internal hashtag data " do
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " # 2hu " } )
2018-11-10 07:16:10 -05:00
expected_tag = %{
" href " = > Pleroma.Web.Endpoint . url ( ) <> " /tags/2hu " ,
" type " = > " Hashtag " ,
" name " = > " # 2hu "
}
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert modified [ " object " ] [ " tag " ] == [ expected_tag ]
end
test " it strips internal fields " do
user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " # 2hu :firefox: " } )
2018-11-10 07:16:10 -05:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert length ( modified [ " object " ] [ " tag " ] ) == 2
assert is_nil ( modified [ " object " ] [ " emoji " ] )
assert is_nil ( modified [ " object " ] [ " like_count " ] )
assert is_nil ( modified [ " object " ] [ " announcements " ] )
assert is_nil ( modified [ " object " ] [ " announcement_count " ] )
assert is_nil ( modified [ " object " ] [ " context_id " ] )
end
2019-01-12 11:52:30 -05:00
test " it strips internal fields of article " do
activity = insert ( :article_activity )
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
2018-11-10 07:16:10 -05:00
assert length ( modified [ " object " ] [ " tag " ] ) == 2
assert is_nil ( modified [ " object " ] [ " emoji " ] )
assert is_nil ( modified [ " object " ] [ " like_count " ] )
assert is_nil ( modified [ " object " ] [ " announcements " ] )
assert is_nil ( modified [ " object " ] [ " announcement_count " ] )
assert is_nil ( modified [ " object " ] [ " context_id " ] )
2019-08-10 14:47:40 -04:00
assert is_nil ( modified [ " object " ] [ " likes " ] )
2019-01-09 03:22:00 -05:00
end
2018-12-23 10:55:07 -05:00
test " the directMessage flag is present " do
user = insert ( :user )
other_user = insert ( :user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " 2hu :moominmamma: " } )
2018-12-23 10:55:07 -05:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert modified [ " directMessage " ] == false
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " @ #{ other_user . nickname } :moominmamma: " } )
2018-12-23 10:55:07 -05:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert modified [ " directMessage " ] == false
{ :ok , activity } =
CommonAPI . post ( user , %{
2020-05-12 15:59:26 -04:00
status : " @ #{ other_user . nickname } :moominmamma: " ,
visibility : " direct "
2018-12-23 10:55:07 -05:00
} )
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert modified [ " directMessage " ] == true
end
2019-05-14 09:12:47 -04:00
test " it strips BCC field " do
user = insert ( :user )
{ :ok , list } = Pleroma.List . create ( " foo " , user )
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " foobar " , visibility : " list: #{ list . id } " } )
2019-05-14 09:12:47 -04:00
{ :ok , modified } = Transmogrifier . prepare_outgoing ( activity . data )
assert is_nil ( modified [ " bcc " ] )
end
2019-09-28 07:57:24 -04:00
test " it can handle Listen activities " do
listen_activity = insert ( :listen )
{ :ok , modified } = Transmogrifier . prepare_outgoing ( listen_activity . data )
assert modified [ " type " ] == " Listen "
2019-09-28 08:12:35 -04:00
user = insert ( :user )
{ :ok , activity } = CommonAPI . listen ( user , %{ " title " = > " lain radio episode 1 " } )
2019-09-30 09:13:25 -04:00
{ :ok , _modified } = Transmogrifier . prepare_outgoing ( activity . data )
2019-09-28 07:57:24 -04:00
end
2018-02-17 08:11:20 -05:00
end
2018-02-21 16:21:40 -05:00
describe " user upgrade " do
test " it upgrades a user to activitypub " do
2018-03-30 09:01:53 -04:00
user =
insert ( :user , %{
nickname : " rye@niu.moe " ,
local : false ,
ap_id : " https://niu.moe/users/rye " ,
follower_address : User . ap_followers ( % User { nickname : " rye@niu.moe " } )
} )
2019-10-10 15:35:32 -04:00
user_two = insert ( :user )
2020-03-28 11:49:03 -04:00
Pleroma.FollowingRelationship . follow ( user_two , user , :follow_accept )
2018-02-21 16:21:40 -05:00
2020-05-12 15:59:26 -04:00
{ :ok , activity } = CommonAPI . post ( user , %{ status : " test " } )
{ :ok , unrelated_activity } = CommonAPI . post ( user_two , %{ status : " test " } )
2018-02-24 04:42:47 -05:00
assert " http://localhost:4001/users/rye@niu.moe/followers " in activity . recipients
2018-02-21 16:21:40 -05:00
2019-04-22 03:20:43 -04:00
user = User . get_cached_by_id ( user . id )
2019-10-16 14:59:21 -04:00
assert user . note_count == 1
2018-02-21 16:21:40 -05:00
{ :ok , user } = Transmogrifier . upgrade_user_from_ap_id ( " https://niu.moe/users/rye " )
2019-08-13 13:20:26 -04:00
ObanHelpers . perform_all ( )
2019-10-16 14:59:21 -04:00
assert user . ap_enabled
assert user . note_count == 1
2018-02-21 16:21:40 -05:00
assert user . follower_address == " https://niu.moe/users/rye/followers "
2019-07-10 09:01:32 -04:00
assert user . following_address == " https://niu.moe/users/rye/following "
2018-02-21 16:21:40 -05:00
2019-04-22 03:20:43 -04:00
user = User . get_cached_by_id ( user . id )
2019-10-16 14:59:21 -04:00
assert user . note_count == 1
2018-02-21 16:21:40 -05:00
2019-04-02 06:08:03 -04:00
activity = Activity . get_by_id ( activity . id )
2018-02-21 16:21:40 -05:00
assert user . follower_address in activity . recipients
2018-03-30 09:01:53 -04:00
assert %{
" url " = > [
%{
" href " = >
" https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg "
}
]
} = user . avatar
assert %{
" url " = > [
%{
" href " = >
" https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png "
}
]
2019-10-16 14:59:21 -04:00
} = user . banner
2018-03-30 09:01:53 -04:00
2018-02-21 16:21:40 -05:00
refute " ... " in activity . recipients
2019-04-02 06:08:03 -04:00
unrelated_activity = Activity . get_by_id ( unrelated_activity . id )
2018-02-21 16:21:40 -05:00
refute user . follower_address in unrelated_activity . recipients
2019-04-22 03:20:43 -04:00
user_two = User . get_cached_by_id ( user_two . id )
2019-10-10 15:35:32 -04:00
assert User . following? ( user_two , user )
refute " ... " in User . following ( user_two )
2018-02-24 11:36:02 -05:00
end
end
2018-05-19 04:06:23 -04:00
describe " actor rewriting " do
test " it fixes the actor URL property to be a proper URI " do
data = %{
" url " = > %{ " href " = > " http://example.com " }
}
rewritten = Transmogrifier . maybe_fix_user_object ( data )
assert rewritten [ " url " ] == " http://example.com "
end
end
2018-09-01 19:33:10 -04:00
describe " actor origin containment " do
test " it rejects activities which reference objects with bogus origins " do
data = %{
" @context " = > " https://www.w3.org/ns/activitystreams " ,
2018-11-17 13:16:55 -05:00
" id " = > " http://mastodon.example.org/users/admin/activities/1234 " ,
" actor " = > " http://mastodon.example.org/users/admin " ,
2018-09-01 19:33:10 -04:00
" to " = > [ " https://www.w3.org/ns/activitystreams # Public " ] ,
" object " = > " https://info.pleroma.site/activity.json " ,
" type " = > " Announce "
}
2019-10-28 12:51:58 -04:00
assert capture_log ( fn ->
2020-05-18 09:47:26 -04:00
{ :error , _ } = Transmogrifier . handle_incoming ( data )
2019-10-28 12:51:58 -04:00
end ) =~ " Object containment failed "
2018-09-01 19:33:10 -04:00
end
2018-11-17 13:12:11 -05:00
2018-11-17 13:24:58 -05:00
test " it rejects activities which reference objects that have an incorrect attribution (variant 1) " do
2018-11-17 13:12:11 -05:00
data = %{
" @context " = > " https://www.w3.org/ns/activitystreams " ,
" id " = > " http://mastodon.example.org/users/admin/activities/1234 " ,
" actor " = > " http://mastodon.example.org/users/admin " ,
" to " = > [ " https://www.w3.org/ns/activitystreams # Public " ] ,
" object " = > " https://info.pleroma.site/activity2.json " ,
" type " = > " Announce "
}
2019-10-28 12:51:58 -04:00
assert capture_log ( fn ->
2020-05-18 09:47:26 -04:00
{ :error , _ } = Transmogrifier . handle_incoming ( data )
2019-10-28 12:51:58 -04:00
end ) =~ " Object containment failed "
2018-11-17 13:12:11 -05:00
end
2018-11-17 13:24:58 -05:00
test " it rejects activities which reference objects that have an incorrect attribution (variant 2) " do
data = %{
" @context " = > " https://www.w3.org/ns/activitystreams " ,
" id " = > " http://mastodon.example.org/users/admin/activities/1234 " ,
" actor " = > " http://mastodon.example.org/users/admin " ,
" to " = > [ " https://www.w3.org/ns/activitystreams # Public " ] ,
" object " = > " https://info.pleroma.site/activity3.json " ,
" type " = > " Announce "
}
2019-10-28 12:51:58 -04:00
assert capture_log ( fn ->
2020-05-18 09:47:26 -04:00
{ :error , _ } = Transmogrifier . handle_incoming ( data )
2019-10-28 12:51:58 -04:00
end ) =~ " Object containment failed "
2018-11-17 13:24:58 -05:00
end
2018-09-01 19:33:10 -04:00
end
2018-11-17 15:07:49 -05:00
2019-02-13 19:59:18 -05:00
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
2019-05-22 14:17:57 -04:00
test " Rewrites Answers to Notes " do
user = insert ( :user )
{ :ok , poll_activity } =
CommonAPI . post ( user , %{
2020-05-12 15:59:26 -04:00
status : " suya... " ,
poll : %{ options : [ " suya " , " suya. " , " suya.. " ] , expires_in : 10 }
2019-05-22 14:17:57 -04:00
} )
poll_object = Object . normalize ( poll_activity )
# TODO: Replace with CommonAPI vote creation when implemented
data =
File . read! ( " test/fixtures/mastodon-vote.json " )
|> Poison . decode! ( )
|> Kernel . put_in ( [ " to " ] , user . ap_id )
|> Kernel . put_in ( [ " object " , " inReplyTo " ] , poll_object . data [ " id " ] )
|> Kernel . put_in ( [ " object " , " to " ] , user . ap_id )
{ :ok , % Activity { local : false } = activity } = Transmogrifier . handle_incoming ( data )
{ :ok , data } = Transmogrifier . prepare_outgoing ( activity . data )
assert data [ " object " ] [ " type " ] == " Note "
end
2019-06-01 09:29:58 -04:00
2019-05-31 07:17:05 -04:00
describe " fix_explicit_addressing " do
2019-05-31 23:26:45 -04:00
setup do
2019-05-31 07:17:05 -04:00
user = insert ( :user )
2019-05-31 23:26:45 -04:00
[ user : user ]
end
2019-05-31 07:17:05 -04:00
2019-05-31 23:26:45 -04:00
test " moves non-explicitly mentioned actors to cc " , %{ user : user } do
2019-05-31 07:17:05 -04:00
explicitly_mentioned_actors = [
" https://pleroma.gold/users/user1 " ,
" https://pleroma.gold/user2 "
]
object = %{
" actor " = > user . ap_id ,
" to " = > explicitly_mentioned_actors ++ [ " https://social.beepboop.ga/users/dirb " ] ,
" cc " = > [ ] ,
" tag " = >
Enum . map ( explicitly_mentioned_actors , fn href ->
%{ " type " = > " Mention " , " href " = > href }
end )
}
fixed_object = Transmogrifier . fix_explicit_addressing ( object )
assert Enum . all? ( explicitly_mentioned_actors , & ( &1 in fixed_object [ " to " ] ) )
refute " https://social.beepboop.ga/users/dirb " in fixed_object [ " to " ]
assert " https://social.beepboop.ga/users/dirb " in fixed_object [ " cc " ]
end
2019-05-31 23:26:45 -04:00
test " does not move actor's follower collection to cc " , %{ user : user } do
2019-05-31 07:17:05 -04:00
object = %{
" actor " = > user . ap_id ,
" to " = > [ user . follower_address ] ,
" cc " = > [ ]
}
fixed_object = Transmogrifier . fix_explicit_addressing ( object )
assert user . follower_address in fixed_object [ " to " ]
refute user . follower_address in fixed_object [ " cc " ]
end
2019-05-31 23:26:45 -04:00
test " removes recipient's follower collection from cc " , %{ user : user } do
recipient = insert ( :user )
object = %{
" actor " = > user . ap_id ,
" to " = > [ recipient . ap_id , " https://www.w3.org/ns/activitystreams # Public " ] ,
" cc " = > [ user . follower_address , recipient . follower_address ]
}
fixed_object = Transmogrifier . fix_explicit_addressing ( object )
assert user . follower_address in fixed_object [ " cc " ]
refute recipient . follower_address in fixed_object [ " cc " ]
refute recipient . follower_address in fixed_object [ " to " ]
end
2019-05-31 07:17:05 -04:00
end
2019-09-10 09:43:10 -04:00
describe " fix_summary/1 " do
test " returns fixed object " do
assert Transmogrifier . fix_summary ( %{ " summary " = > nil } ) == %{ " summary " = > " " }
assert Transmogrifier . fix_summary ( %{ " summary " = > " ok " } ) == %{ " summary " = > " ok " }
assert Transmogrifier . fix_summary ( %{ } ) == %{ " summary " = > " " }
end
end
describe " fix_in_reply_to/2 " do
2020-03-20 11:33:00 -04:00
setup do : clear_config ( [ :instance , :federation_incoming_replies_max_depth ] )
2019-09-10 09:43:10 -04:00
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 inReplyToAtomUri 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 "
assert modified_object [ " inReplyToAtomUri " ] == " 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 " }
assert modified_object [ " inReplyToAtomUri " ] == " 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 " ]
assert modified_object [ " inReplyToAtomUri " ] == " 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 " ] == [ ]
assert modified_object [ " inReplyToAtomUri " ] == " "
end
2019-11-28 04:44:48 -05:00
@tag capture_log : true
2019-09-10 09:43:10 -04:00
test " returns modified object when allowed incoming reply " , %{ data : data } do
object_with_reply =
Map . put (
data [ " object " ] ,
" inReplyTo " ,
" https://shitposter.club/notice/2827873 "
)
Pleroma.Config . put ( [ :instance , :federation_incoming_replies_max_depth ] , 5 )
modified_object = Transmogrifier . fix_in_reply_to ( object_with_reply )
assert modified_object [ " inReplyTo " ] ==
" tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment "
assert modified_object [ " inReplyToAtomUri " ] == " https://shitposter.club/notice/2827873 "
assert modified_object [ " context " ] ==
" tag:shitposter.club,2017-05-05:objectType=thread:nonce=3c16e9c2681f6d26 "
end
end
describe " fix_url/1 " do
test " fixes data for object when url is map " do
object = %{
" url " = > %{
" type " = > " Link " ,
" mimeType " = > " video/mp4 " ,
" href " = > " https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4 "
}
}
assert Transmogrifier . fix_url ( object ) == %{
" url " = > " https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4 "
}
end
test " fixes data for video object " do
object = %{
" type " = > " Video " ,
" url " = > [
%{
" type " = > " Link " ,
" mimeType " = > " video/mp4 " ,
" href " = > " https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4 "
} ,
%{
" type " = > " Link " ,
" mimeType " = > " video/mp4 " ,
" href " = > " https://peertube46fb-ad81-2d4c2d1630e3-240.mp4 "
} ,
%{
" type " = > " Link " ,
" mimeType " = > " text/html " ,
" href " = > " https://peertube.-2d4c2d1630e3 "
} ,
%{
" type " = > " Link " ,
" mimeType " = > " text/html " ,
" href " = > " https://peertube.-2d4c2d16377-42 "
}
]
}
assert Transmogrifier . fix_url ( object ) == %{
" attachment " = > [
%{
" href " = > " https://peede8d-46fb-ad81-2d4c2d1630e3-480.mp4 " ,
" mimeType " = > " video/mp4 " ,
" type " = > " Link "
}
] ,
" type " = > " Video " ,
" url " = > " https://peertube.-2d4c2d1630e3 "
}
end
test " fixes url for not Video object " do
object = %{
" type " = > " Text " ,
" url " = > [
%{
" type " = > " Link " ,
" mimeType " = > " text/html " ,
" href " = > " https://peertube.-2d4c2d1630e3 "
} ,
%{
" type " = > " Link " ,
" mimeType " = > " text/html " ,
" href " = > " https://peertube.-2d4c2d16377-42 "
}
]
}
assert Transmogrifier . fix_url ( object ) == %{
" type " = > " Text " ,
" url " = > " https://peertube.-2d4c2d1630e3 "
}
assert Transmogrifier . fix_url ( %{ " type " = > " Text " , " url " = > [ ] } ) == %{
" type " = > " Text " ,
" url " = > " "
}
end
test " retunrs not modified object " do
assert Transmogrifier . fix_url ( %{ " type " = > " Text " } ) == %{ " type " = > " Text " }
end
end
2019-09-11 00:23:33 -04:00
describe " get_obj_helper/2 " do
test " returns nil when cannot normalize object " do
2019-10-28 12:51:58 -04:00
assert capture_log ( fn ->
refute Transmogrifier . get_obj_helper ( " test-obj-id " )
end ) =~ " Unsupported URI scheme "
2019-09-11 00:23:33 -04:00
end
2019-11-28 04:44:48 -05:00
@tag capture_log : true
2019-09-11 00:23:33 -04:00
test " returns {:ok, %Object{}} for success case " do
assert { :ok , % Object { } } =
Transmogrifier . get_obj_helper ( " https://shitposter.club/notice/2827873 " )
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 " ,
" url " = > [
2020-03-19 14:10:03 -04:00
%{ " href " = > " https://peertube.moe/stat-480.mp4 " , " mediaType " = > " video/mp4 " }
2019-09-11 00:23:33 -04:00
]
}
]
}
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 " ,
" url " = > [
2020-03-19 14:10:03 -04:00
%{ " href " = > " https://pe.er/stat-480.mp4 " , " mediaType " = > " video/mp4 " }
2019-09-11 00:23:33 -04:00
]
} ,
%{
" mediaType " = > " video/mp4 " ,
" url " = > [
2020-03-19 14:10:03 -04:00
%{ " href " = > " https://pe.er/stat-480.mp4 " , " mediaType " = > " video/mp4 " }
2019-09-11 00:23:33 -04:00
]
}
]
}
end
end
2019-09-11 16:19:06 -04:00
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
2020-01-22 13:10:17 -05:00
describe " set_replies/1 " do
2020-03-20 11:33:00 -04:00
setup do : clear_config ( [ :activitypub , :note_replies_output_limit ] , 2 )
2020-01-22 13:10:17 -05:00
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 )
2020-05-12 15:59:26 -04:00
{ :ok , %{ id : id1 } = activity } = CommonAPI . post ( user , %{ status : " 1 " } )
2020-01-22 13:10:17 -05:00
{ :ok , %{ id : id2 } = self_reply1 } =
2020-05-12 15:59:26 -04:00
CommonAPI . post ( user , %{ status : " self-reply 1 " , in_reply_to_status_id : id1 } )
2020-01-22 13:10:17 -05:00
{ :ok , self_reply2 } =
2020-05-12 15:59:26 -04:00
CommonAPI . post ( user , %{ status : " self-reply 2 " , in_reply_to_status_id : id1 } )
2020-01-22 13:10:17 -05:00
2020-02-08 11:58:02 -05:00
# Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2
2020-05-12 15:59:26 -04:00
{ :ok , _ } = CommonAPI . post ( user , %{ status : " self-reply 3 " , in_reply_to_status_id : id1 } )
2020-01-22 13:10:17 -05:00
{ :ok , _ } =
CommonAPI . post ( user , %{
2020-05-12 15:59:26 -04:00
status : " self-reply to self-reply " ,
in_reply_to_status_id : id2
2020-01-22 13:10:17 -05:00
} )
{ :ok , _ } =
CommonAPI . post ( another_user , %{
2020-05-12 15:59:26 -04:00
status : " another user's reply " ,
in_reply_to_status_id : id1
2020-01-22 13:10:17 -05:00
} )
object = Object . normalize ( activity )
2020-02-09 02:17:21 -05:00
replies_uris = Enum . map ( [ self_reply1 , self_reply2 ] , fn a -> a . object . data [ " id " ] end )
2020-01-22 13:10:17 -05:00
2020-02-09 09:34:48 -05:00
assert %{ " type " = > " Collection " , " items " = > ^ replies_uris } =
Transmogrifier . set_replies ( object . data ) [ " replies " ]
2020-01-22 13:10:17 -05:00
end
end
2020-04-03 07:03:32 -04:00
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
2018-02-15 14:00:06 -05:00
end