Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F33103428
activity_pub_controller_test.exs
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
67 KB
Referenced Files
None
Subscribers
None
activity_pub_controller_test.exs
View Options
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule
Pleroma.Web.ActivityPub.ActivityPubControllerTest
do
use
Pleroma.Web.ConnCase
use
Oban.Testing
,
repo
:
Pleroma.Repo
alias
Pleroma.Activity
alias
Pleroma.Delivery
alias
Pleroma.Object
alias
Pleroma.Tests.ObanHelpers
alias
Pleroma.User
alias
Pleroma.Web.ActivityPub.ActivityPub
alias
Pleroma.Web.ActivityPub.ObjectView
alias
Pleroma.Web.ActivityPub.Relay
alias
Pleroma.Web.ActivityPub.UserView
alias
Pleroma.Web.ActivityPub.Utils
alias
Pleroma.Web.CommonAPI
alias
Pleroma.Web.Endpoint
alias
Pleroma.Workers.ReceiverWorker
import
Pleroma.Factory
require
Pleroma.Constants
setup
do
Mox
.
stub_with
(
Pleroma.UnstubbedConfigMock
,
Pleroma.Test.StaticConfig
)
:ok
end
setup_all
do
Tesla.Mock
.
mock_global
(
fn
env
->
apply
(
HttpRequestMock
,
:request
,
[
env
])
end
)
:ok
end
setup
do
:
clear_config
([
:instance
,
:federating
],
true
)
describe
"/relay"
do
setup
do
:
clear_config
([
:instance
,
:allow_relay
])
test
"with the relay active, it returns the relay user"
,
%{
conn
:
conn
}
do
res
=
conn
|>
get
(
activity_pub_path
(
conn
,
:relay
))
|>
json_response
(
200
)
assert
res
[
"id"
]
=~
"/relay"
end
test
"with the relay disabled, it returns 404"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:allow_relay
],
false
)
conn
|>
get
(
activity_pub_path
(
conn
,
:relay
))
|>
json_response
(
404
)
end
test
"on non-federating instance, it returns 404"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:federating
],
false
)
user
=
insert
(
:user
)
conn
|>
assign
(
:user
,
user
)
|>
get
(
activity_pub_path
(
conn
,
:relay
))
|>
json_response
(
404
)
end
end
describe
"/internal/fetch"
do
test
"it returns the internal fetch user"
,
%{
conn
:
conn
}
do
res
=
conn
|>
get
(
activity_pub_path
(
conn
,
:internal_fetch
))
|>
json_response
(
200
)
assert
res
[
"id"
]
=~
"/fetch"
end
test
"on non-federating instance, it returns 404"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:federating
],
false
)
user
=
insert
(
:user
)
conn
|>
assign
(
:user
,
user
)
|>
get
(
activity_pub_path
(
conn
,
:internal_fetch
))
|>
json_response
(
404
)
end
end
describe
"/users/:nickname"
do
test
"it returns a json representation of the user with accept application/json"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
"
)
user
=
User
.
get_cached_by_id
(
user
.
id
)
assert
json_response
(
conn
,
200
)
==
UserView
.
render
(
"user.json"
,
%{
user
:
user
})
end
test
"it returns a json representation of the user with accept application/activity+json"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
"
)
user
=
User
.
get_cached_by_id
(
user
.
id
)
assert
json_response
(
conn
,
200
)
==
UserView
.
render
(
"user.json"
,
%{
user
:
user
})
end
test
"it returns a json representation of the user with accept application/ld+json"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
)
|>
get
(
"/users/
#{
user
.
nickname
}
"
)
user
=
User
.
get_cached_by_id
(
user
.
id
)
assert
json_response
(
conn
,
200
)
==
UserView
.
render
(
"user.json"
,
%{
user
:
user
})
end
test
"it returns 404 for remote users"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
local
:
false
,
nickname
:
"remoteuser@example.com"
)
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
.json"
)
assert
json_response
(
conn
,
404
)
end
test
"it returns error when user is not found"
,
%{
conn
:
conn
}
do
response
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/users/jimm"
)
|>
json_response
(
404
)
assert
response
==
"Not found"
end
end
describe
"mastodon compatibility routes"
do
test
"it returns a json representation of the object with accept application/json"
,
%{
conn
:
conn
}
do
{
:ok
,
object
}
=
%{
"type"
=>
"Note"
,
"content"
=>
"hey"
,
"id"
=>
Endpoint
.
url
()
<>
"/users/raymoo/statuses/999999999"
,
"actor"
=>
Endpoint
.
url
()
<>
"/users/raymoo"
,
"to"
=>
[
Pleroma.Constants
.
as_public
()]
}
|>
Object
.
create
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/users/raymoo/statuses/999999999"
)
assert
json_response
(
conn
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
object
})
end
test
"it returns a json representation of the activity with accept application/json"
,
%{
conn
:
conn
}
do
{
:ok
,
object
}
=
%{
"type"
=>
"Note"
,
"content"
=>
"hey"
,
"id"
=>
Endpoint
.
url
()
<>
"/users/raymoo/statuses/999999999"
,
"actor"
=>
Endpoint
.
url
()
<>
"/users/raymoo"
,
"to"
=>
[
Pleroma.Constants
.
as_public
()]
}
|>
Object
.
create
()
{
:ok
,
activity
,
_
}
=
%{
"id"
=>
object
.
data
[
"id"
]
<>
"/activity"
,
"type"
=>
"Create"
,
"object"
=>
object
.
data
[
"id"
],
"actor"
=>
object
.
data
[
"actor"
],
"to"
=>
object
.
data
[
"to"
]
}
|>
ActivityPub
.
persist
(
local
:
true
)
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/users/raymoo/statuses/999999999/activity"
)
assert
json_response
(
conn
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
activity
})
end
end
describe
"/objects/:uuid"
do
test
"it doesn't return a local-only object"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"test"
,
visibility
:
"local"
})
assert
Pleroma.Web.ActivityPub.Visibility
.
local_public?
(
post
)
object
=
Object
.
normalize
(
post
,
fetch
:
false
)
uuid
=
String
.
split
(
object
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn
,
404
)
end
test
"returns local-only objects when authenticated"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"test"
,
visibility
:
"local"
})
assert
Pleroma.Web.ActivityPub.Visibility
.
local_public?
(
post
)
object
=
Object
.
normalize
(
post
,
fetch
:
false
)
uuid
=
String
.
split
(
object
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
assert
response
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
response
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
object
})
end
test
"does not return local-only objects for remote users"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
reader
=
insert
(
:user
,
local
:
false
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"test @
#{
reader
.
nickname
}
"
,
visibility
:
"local"
})
assert
Pleroma.Web.ActivityPub.Visibility
.
local_public?
(
post
)
object
=
Object
.
normalize
(
post
,
fetch
:
false
)
uuid
=
String
.
split
(
object
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
assert
response
=
conn
|>
assign
(
:user
,
reader
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
json_response
(
response
,
404
)
end
test
"it returns a json representation of the object with accept application/json"
,
%{
conn
:
conn
}
do
note
=
insert
(
:note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
note
})
end
test
"it returns a json representation of the object with accept application/activity+json"
,
%{
conn
:
conn
}
do
note
=
insert
(
:note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
note
})
end
test
"it returns a json representation of the object with accept application/ld+json"
,
%{
conn
:
conn
}
do
note
=
insert
(
:note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
note
})
end
test
"does not cache authenticated response"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
reader
=
insert
(
:user
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"test @
#{
reader
.
nickname
}
"
,
visibility
:
"local"
})
object
=
Object
.
normalize
(
post
,
fetch
:
false
)
uuid
=
String
.
split
(
object
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
assert
response
=
conn
|>
assign
(
:user
,
reader
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
json_response
(
response
,
200
)
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
|>
json_response
(
404
)
end
test
"it returns 404 for non-public messages"
,
%{
conn
:
conn
}
do
note
=
insert
(
:direct_note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn
,
404
)
end
test
"returns visible non-public messages when authenticated"
,
%{
conn
:
conn
}
do
note
=
insert
(
:direct_note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
user
=
User
.
get_by_ap_id
(
note
.
data
[
"actor"
])
marisa
=
insert
(
:user
)
assert
conn
|>
assign
(
:user
,
marisa
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
|>
json_response
(
404
)
assert
response
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
|>
json_response
(
200
)
assert
response
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
note
})
end
test
"it returns 404 for tombstone objects"
,
%{
conn
:
conn
}
do
tombstone
=
insert
(
:tombstone
)
uuid
=
String
.
split
(
tombstone
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn
,
404
)
end
test
"it caches a response"
,
%{
conn
:
conn
}
do
note
=
insert
(
:note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn1
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn1
,
:ok
)
assert
Enum
.
any?
(
conn1
.
resp_headers
,
&
(
&1
==
{
"x-cache"
,
"MISS from Pleroma"
}))
conn2
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn1
,
:ok
)
==
json_response
(
conn2
,
:ok
)
assert
Enum
.
any?
(
conn2
.
resp_headers
,
&
(
&1
==
{
"x-cache"
,
"HIT from Pleroma"
}))
end
test
"cached purged after object deletion"
,
%{
conn
:
conn
}
do
note
=
insert
(
:note
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn1
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
json_response
(
conn1
,
:ok
)
assert
Enum
.
any?
(
conn1
.
resp_headers
,
&
(
&1
==
{
"x-cache"
,
"MISS from Pleroma"
}))
Object
.
delete
(
note
)
conn2
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/objects/
#{
uuid
}
"
)
assert
"Not found"
==
json_response
(
conn2
,
:not_found
)
end
end
describe
"/activities/:uuid"
do
test
"it doesn't return a local-only activity"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"test"
,
visibility
:
"local"
})
assert
Pleroma.Web.ActivityPub.Visibility
.
local_public?
(
post
)
uuid
=
String
.
split
(
post
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
conn
,
404
)
end
test
"returns local-only activities when authenticated"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"test"
,
visibility
:
"local"
})
assert
Pleroma.Web.ActivityPub.Visibility
.
local_public?
(
post
)
uuid
=
String
.
split
(
post
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
assert
response
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
response
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
post
})
end
test
"it returns a json representation of the activity"
,
%{
conn
:
conn
}
do
activity
=
insert
(
:note_activity
)
uuid
=
String
.
split
(
activity
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
conn
,
200
)
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
activity
})
end
test
"it returns 404 for non-public activities"
,
%{
conn
:
conn
}
do
activity
=
insert
(
:direct_note_activity
)
uuid
=
String
.
split
(
activity
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
conn
,
404
)
end
test
"returns visible non-public messages when authenticated"
,
%{
conn
:
conn
}
do
note
=
insert
(
:direct_note_activity
)
uuid
=
String
.
split
(
note
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
user
=
User
.
get_by_ap_id
(
note
.
data
[
"actor"
])
marisa
=
insert
(
:user
)
assert
conn
|>
assign
(
:user
,
marisa
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
|>
json_response
(
404
)
assert
response
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
|>
json_response
(
200
)
assert
response
==
ObjectView
.
render
(
"object.json"
,
%{
object
:
note
})
end
test
"it caches a response"
,
%{
conn
:
conn
}
do
activity
=
insert
(
:note_activity
)
uuid
=
String
.
split
(
activity
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn1
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
conn1
,
:ok
)
assert
Enum
.
any?
(
conn1
.
resp_headers
,
&
(
&1
==
{
"x-cache"
,
"MISS from Pleroma"
}))
conn2
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
conn1
,
:ok
)
==
json_response
(
conn2
,
:ok
)
assert
Enum
.
any?
(
conn2
.
resp_headers
,
&
(
&1
==
{
"x-cache"
,
"HIT from Pleroma"
}))
end
test
"cached purged after activity deletion"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
activity
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"cofe"
})
uuid
=
String
.
split
(
activity
.
data
[
"id"
],
"/"
)
|>
List
.
last
()
conn1
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
json_response
(
conn1
,
:ok
)
assert
Enum
.
any?
(
conn1
.
resp_headers
,
&
(
&1
==
{
"x-cache"
,
"MISS from Pleroma"
}))
Activity
.
delete_all_by_object_ap_id
(
activity
.
object
.
data
[
"id"
])
conn2
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/activities/
#{
uuid
}
"
)
assert
"Not found"
==
json_response
(
conn2
,
:not_found
)
end
end
describe
"/inbox"
do
test
"it inserts an incoming activity into the database"
,
%{
conn
:
conn
}
do
data
=
File
.
read!
(
"test/fixtures/mastodon-post-activity.json"
)
|>
Jason
.
decode!
()
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"it inserts an incoming activity into the database"
<>
"even if we can't fetch the user but have it in our db"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
ap_id
:
"https://mastodon.example.org/users/raymoo"
,
local
:
false
,
last_refreshed_at
:
nil
)
data
=
File
.
read!
(
"test/fixtures/mastodon-post-activity.json"
)
|>
Jason
.
decode!
()
|>
Map
.
put
(
"actor"
,
user
.
ap_id
)
|>
put_in
([
"object"
,
"attributedTo"
],
user
.
ap_id
)
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"accept follow activity"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:federating
],
true
)
relay
=
Relay
.
get_actor
()
assert
{
:ok
,
%
Activity
{}
=
activity
}
=
Relay
.
follow
(
"https://relay.mastodon.host/actor"
)
followed_relay
=
Pleroma.User
.
get_by_ap_id
(
"https://relay.mastodon.host/actor"
)
relay
=
refresh_record
(
relay
)
accept
=
File
.
read!
(
"test/fixtures/relay/accept-follow.json"
)
|>
String
.
replace
(
"{{ap_id}}"
,
relay
.
ap_id
)
|>
String
.
replace
(
"{{activity_id}}"
,
activity
.
data
[
"id"
])
assert
"ok"
==
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
accept
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Pleroma.FollowingRelationship
.
following?
(
relay
,
followed_relay
)
Mix
.
shell
(
Mix.Shell.Process
)
on_exit
(
fn
->
Mix
.
shell
(
Mix.Shell.IO
)
end
)
:ok
=
Mix.Tasks.Pleroma.Relay
.
run
([
"list"
])
assert_receive
{
:mix_shell
,
:info
,
[
"https://relay.mastodon.host/actor"
]}
end
test
"without valid signature, "
<>
"it accepts Create activities and requires enabled federation"
,
%{
conn
:
conn
}
do
data
=
File
.
read!
(
"test/fixtures/mastodon-post-activity.json"
)
|>
Jason
.
decode!
()
non_create_data
=
File
.
read!
(
"test/fixtures/mastodon-announce.json"
)
|>
Jason
.
decode!
()
conn
=
put_req_header
(
conn
,
"content-type"
,
"application/activity+json"
)
clear_config
([
:instance
,
:federating
],
false
)
conn
|>
post
(
"/inbox"
,
data
)
|>
json_response
(
403
)
conn
|>
post
(
"/inbox"
,
non_create_data
)
|>
json_response
(
403
)
clear_config
([
:instance
,
:federating
],
true
)
ret_conn
=
post
(
conn
,
"/inbox"
,
data
)
assert
"ok"
==
json_response
(
ret_conn
,
200
)
conn
|>
post
(
"/inbox"
,
non_create_data
)
|>
json_response
(
400
)
end
# When activity is delivered to the inbox and we cannot immediately verify signature
# we capture all the params and process it later in the Oban job.
# Once we begin processing it through Oban we risk fetching the actor to validate the
# activity which just leads to inserting a new user to process a Delete not relevant to us.
test
"Activities of certain types from an unknown actor are discarded"
,
%{
conn
:
conn
}
do
example_bad_types
=
Pleroma.Constants
.
activity_types
()
--
Pleroma.Constants
.
allowed_activity_types_from_strangers
()
Enum
.
each
(
example_bad_types
,
fn
bad_type
->
params
=
%{
"type"
=>
bad_type
,
"actor"
=>
"https://unknown.mastodon.instance/users/somebody"
}
|>
Jason
.
encode!
()
conn
|>
assign
(
:valid_signature
,
false
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
params
)
|>
json_response
(
400
)
assert
all_enqueued
()
==
[]
end
)
end
test
"Unknown activity types are discarded"
,
%{
conn
:
conn
}
do
unknown_types
=
[
"Poke"
,
"Read"
,
"Dazzle"
]
Enum
.
each
(
unknown_types
,
fn
bad_type
->
params
=
%{
"type"
=>
bad_type
,
"actor"
=>
"https://unknown.mastodon.instance/users/somebody"
}
|>
Jason
.
encode!
()
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
params
)
|>
json_response
(
400
)
assert
all_enqueued
()
==
[]
end
)
end
test
"accepts Add/Remove activities"
,
%{
conn
:
conn
}
do
object_id
=
"c61d6733-e256-4fe1-ab13-1e369789423f"
status
=
File
.
read!
(
"test/fixtures/statuses/note.json"
)
|>
String
.
replace
(
"{{nickname}}"
,
"lain"
)
|>
String
.
replace
(
"{{object_id}}"
,
object_id
)
object_url
=
"https://example.com/objects/
#{
object_id
}
"
user
=
File
.
read!
(
"test/fixtures/users_mock/user.json"
)
|>
String
.
replace
(
"{{nickname}}"
,
"lain"
)
actor
=
"https://example.com/users/lain"
Tesla.Mock
.
mock
(
fn
%{
method
:
:get
,
url
:
^
object_url
}
->
%
Tesla.Env
{
status
:
200
,
body
:
status
,
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
%{
method
:
:get
,
url
:
^
actor
}
->
%
Tesla.Env
{
status
:
200
,
body
:
user
,
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
%{
method
:
:get
,
url
:
"https://example.com/users/lain/collections/featured"
}
->
%
Tesla.Env
{
status
:
200
,
body
:
"test/fixtures/users_mock/masto_featured.json"
|>
File
.
read!
()
|>
String
.
replace
(
"{{domain}}"
,
"example.com"
)
|>
String
.
replace
(
"{{nickname}}"
,
"lain"
),
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
end
)
data
=
%{
"id"
=>
"https://example.com/objects/d61d6733-e256-4fe1-ab13-1e369789423f"
,
"actor"
=>
actor
,
"object"
=>
object_url
,
"target"
=>
"https://example.com/users/lain/collections/featured"
,
"type"
=>
"Add"
,
"to"
=>
[
Pleroma.Constants
.
as_public
()]
}
assert
"ok"
==
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
user
=
User
.
get_cached_by_ap_id
(
data
[
"actor"
])
assert
user
.
pinned_objects
[
data
[
"object"
]]
data
=
%{
"id"
=>
"https://example.com/objects/d61d6733-e256-4fe1-ab13-1e369789423d"
,
"actor"
=>
actor
,
"object"
=>
object_url
,
"target"
=>
"https://example.com/users/lain/collections/featured"
,
"type"
=>
"Remove"
,
"to"
=>
[
Pleroma.Constants
.
as_public
()]
}
assert
"ok"
==
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
user
=
refresh_record
(
user
)
refute
user
.
pinned_objects
[
data
[
"object"
]]
end
test
"mastodon pin/unpin"
,
%{
conn
:
conn
}
do
status_id
=
"105786274556060421"
status
=
File
.
read!
(
"test/fixtures/statuses/masto-note.json"
)
|>
String
.
replace
(
"{{nickname}}"
,
"lain"
)
|>
String
.
replace
(
"{{status_id}}"
,
status_id
)
status_url
=
"https://example.com/users/lain/statuses/
#{
status_id
}
"
user
=
File
.
read!
(
"test/fixtures/users_mock/user.json"
)
|>
String
.
replace
(
"{{nickname}}"
,
"lain"
)
actor
=
"https://example.com/users/lain"
Tesla.Mock
.
mock
(
fn
%{
method
:
:get
,
url
:
^
status_url
}
->
%
Tesla.Env
{
status
:
200
,
body
:
status
,
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
%{
method
:
:get
,
url
:
^
actor
}
->
%
Tesla.Env
{
status
:
200
,
body
:
user
,
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
%{
method
:
:get
,
url
:
"https://example.com/users/lain/collections/featured"
}
->
%
Tesla.Env
{
status
:
200
,
body
:
"test/fixtures/users_mock/masto_featured.json"
|>
File
.
read!
()
|>
String
.
replace
(
"{{domain}}"
,
"example.com"
)
|>
String
.
replace
(
"{{nickname}}"
,
"lain"
),
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
end
)
data
=
%{
"@context"
=>
"https://www.w3.org/ns/activitystreams"
,
"actor"
=>
actor
,
"object"
=>
status_url
,
"target"
=>
"https://example.com/users/lain/collections/featured"
,
"type"
=>
"Add"
}
assert
"ok"
==
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_object_ap_id_with_object
(
data
[
"object"
])
user
=
User
.
get_cached_by_ap_id
(
data
[
"actor"
])
assert
user
.
pinned_objects
[
data
[
"object"
]]
data
=
%{
"actor"
=>
actor
,
"object"
=>
status_url
,
"target"
=>
"https://example.com/users/lain/collections/featured"
,
"type"
=>
"Remove"
}
assert
"ok"
==
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_object_ap_id_with_object
(
data
[
"object"
])
user
=
refresh_record
(
user
)
refute
user
.
pinned_objects
[
data
[
"object"
]]
end
end
describe
"/users/:nickname/inbox"
do
setup
do
data
=
File
.
read!
(
"test/fixtures/mastodon-post-activity.json"
)
|>
Jason
.
decode!
()
[
data
:
data
]
end
test
"it inserts an incoming activity into the database"
,
%{
conn
:
conn
,
data
:
data
}
do
user
=
insert
(
:user
)
data
=
data
|>
Map
.
put
(
"bcc"
,
[
user
.
ap_id
])
|>
Kernel
.
put_in
([
"object"
,
"bcc"
],
[
user
.
ap_id
])
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"it accepts messages with to as string instead of array"
,
%{
conn
:
conn
,
data
:
data
}
do
user
=
insert
(
:user
)
data
=
data
|>
Map
.
put
(
"to"
,
user
.
ap_id
)
|>
Map
.
put
(
"cc"
,
[])
|>
Kernel
.
put_in
([
"object"
,
"to"
],
user
.
ap_id
)
|>
Kernel
.
put_in
([
"object"
,
"cc"
],
[])
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"it accepts messages with cc as string instead of array"
,
%{
conn
:
conn
,
data
:
data
}
do
user
=
insert
(
:user
)
data
=
data
|>
Map
.
put
(
"to"
,
[])
|>
Map
.
put
(
"cc"
,
user
.
ap_id
)
|>
Kernel
.
put_in
([
"object"
,
"to"
],
[])
|>
Kernel
.
put_in
([
"object"
,
"cc"
],
user
.
ap_id
)
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
%
Activity
{}
=
activity
=
Activity
.
get_by_ap_id
(
data
[
"id"
])
assert
user
.
ap_id
in
activity
.
recipients
end
test
"it accepts messages with bcc as string instead of array"
,
%{
conn
:
conn
,
data
:
data
}
do
user
=
insert
(
:user
)
data
=
data
|>
Map
.
put
(
"to"
,
[])
|>
Map
.
put
(
"cc"
,
[])
|>
Map
.
put
(
"bcc"
,
user
.
ap_id
)
|>
Kernel
.
put_in
([
"object"
,
"to"
],
[])
|>
Kernel
.
put_in
([
"object"
,
"cc"
],
[])
|>
Kernel
.
put_in
([
"object"
,
"bcc"
],
user
.
ap_id
)
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"it accepts announces with to as string instead of array"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
post
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"hey"
})
announcer
=
insert
(
:user
,
local
:
false
)
data
=
%{
"@context"
=>
"https://www.w3.org/ns/activitystreams"
,
"actor"
=>
announcer
.
ap_id
,
"id"
=>
"
#{
announcer
.
ap_id
}
/statuses/19512778738411822/activity"
,
"object"
=>
post
.
data
[
"object"
],
"to"
=>
"https://www.w3.org/ns/activitystreams
#
Public"
,
"cc"
=>
[
user
.
ap_id
],
"type"
=>
"Announce"
}
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
%
Activity
{}
=
activity
=
Activity
.
get_by_ap_id
(
data
[
"id"
])
assert
"https://www.w3.org/ns/activitystreams
#
Public"
in
activity
.
recipients
end
test
"it accepts messages from actors that are followed by the user"
,
%{
conn
:
conn
,
data
:
data
}
do
recipient
=
insert
(
:user
)
actor
=
insert
(
:user
,
%{
ap_id
:
"http://mastodon.example.org/users/actor"
})
{
:ok
,
recipient
,
actor
}
=
User
.
follow
(
recipient
,
actor
)
object
=
data
[
"object"
]
|>
Map
.
put
(
"attributedTo"
,
actor
.
ap_id
)
data
=
data
|>
Map
.
put
(
"actor"
,
actor
.
ap_id
)
|>
Map
.
put
(
"object"
,
object
)
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
recipient
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"it rejects reads from other users"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
other_user
=
insert
(
:user
)
conn
=
conn
|>
assign
(
:user
,
other_user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/inbox"
)
assert
json_response
(
conn
,
403
)
end
test
"it returns a note activity in a collection"
,
%{
conn
:
conn
}
do
note_activity
=
insert
(
:direct_note_activity
)
note_object
=
Object
.
normalize
(
note_activity
,
fetch
:
false
)
user
=
User
.
get_cached_by_ap_id
(
hd
(
note_activity
.
data
[
"to"
]))
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/inbox?page=true"
)
assert
response
(
conn
,
200
)
=~
note_object
.
data
[
"content"
]
end
test
"it removes all follower collections but actor's"
,
%{
conn
:
conn
}
do
[
actor
,
recipient
]
=
insert_pair
(
:user
)
to
=
[
recipient
.
ap_id
,
recipient
.
follower_address
,
"https://www.w3.org/ns/activitystreams
#
Public"
]
cc
=
[
recipient
.
follower_address
,
actor
.
follower_address
]
data
=
%{
"@context"
=>
[
"https://www.w3.org/ns/activitystreams"
],
"type"
=>
"Create"
,
"id"
=>
Utils
.
generate_activity_id
(),
"to"
=>
to
,
"cc"
=>
cc
,
"actor"
=>
actor
.
ap_id
,
"object"
=>
%{
"type"
=>
"Note"
,
"to"
=>
to
,
"cc"
=>
cc
,
"content"
=>
"It's a note"
,
"attributedTo"
=>
actor
.
ap_id
,
"id"
=>
Utils
.
generate_object_id
()
}
}
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
recipient
.
nickname
}
/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
activity
=
Activity
.
get_by_ap_id
(
data
[
"id"
])
assert
activity
.
id
assert
actor
.
follower_address
in
activity
.
recipients
assert
actor
.
follower_address
in
activity
.
data
[
"cc"
]
refute
recipient
.
follower_address
in
activity
.
recipients
refute
recipient
.
follower_address
in
activity
.
data
[
"cc"
]
refute
recipient
.
follower_address
in
activity
.
data
[
"to"
]
end
test
"it requires authentication"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
=
put_req_header
(
conn
,
"accept"
,
"application/activity+json"
)
ret_conn
=
get
(
conn
,
"/users/
#{
user
.
nickname
}
/inbox"
)
assert
json_response
(
ret_conn
,
403
)
ret_conn
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/inbox"
)
assert
json_response
(
ret_conn
,
200
)
end
test
"forwarded report"
,
%{
conn
:
conn
}
do
admin
=
insert
(
:user
,
is_admin
:
true
)
actor
=
insert
(
:user
,
local
:
false
)
remote_domain
=
URI
.
parse
(
actor
.
ap_id
)
.
host
reported_user
=
insert
(
:user
)
note
=
insert
(
:note_activity
,
user
:
reported_user
)
data
=
%{
"@context"
=>
[
"https://www.w3.org/ns/activitystreams"
,
"https://
#{
remote_domain
}
/schemas/litepub-0.1.jsonld"
,
%{
"@language"
=>
"und"
}
],
"actor"
=>
actor
.
ap_id
,
# CC and TO might either not exist at all, or be empty. We should be able to handle either.
# "cc" => [],
"content"
=>
"test"
,
"context"
=>
"context"
,
"id"
=>
"http://
#{
remote_domain
}
/activities/02be56cf-35e3-46b4-b2c6-47ae08dfee9e"
,
"nickname"
=>
reported_user
.
nickname
,
"object"
=>
[
reported_user
.
ap_id
,
%{
"actor"
=>
%{
"actor_type"
=>
"Person"
,
"approval_pending"
=>
false
,
"avatar"
=>
""
,
"confirmation_pending"
=>
false
,
"deactivated"
=>
false
,
"display_name"
=>
"test user"
,
"id"
=>
reported_user
.
id
,
"local"
=>
false
,
"nickname"
=>
reported_user
.
nickname
,
"registration_reason"
=>
nil
,
"roles"
=>
%{
"admin"
=>
false
,
"moderator"
=>
false
},
"tags"
=>
[],
"url"
=>
reported_user
.
ap_id
},
"content"
=>
""
,
"id"
=>
note
.
data
[
"id"
],
"published"
=>
note
.
data
[
"published"
],
"type"
=>
"Note"
}
],
"published"
=>
note
.
data
[
"published"
],
"state"
=>
"open"
,
"to"
=>
[],
"type"
=>
"Flag"
}
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
reported_user
.
nickname
}
/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Pleroma.Repo
.
aggregate
(
Activity
,
:count
,
:id
)
==
2
ObanHelpers
.
perform_all
()
Swoosh.TestAssertions
.
assert_email_sent
(
to
:
{
admin
.
name
,
admin
.
email
},
html_body
:
~r/Reported Account:/i
)
end
test
"forwarded report from mastodon"
,
%{
conn
:
conn
}
do
admin
=
insert
(
:user
,
is_admin
:
true
)
actor
=
insert
(
:user
,
local
:
false
)
remote_domain
=
URI
.
parse
(
actor
.
ap_id
)
.
host
remote_actor
=
"https://
#{
remote_domain
}
/actor"
[
reported_user
,
another
]
=
insert_list
(
2
,
:user
)
note
=
insert
(
:note_activity
,
user
:
reported_user
)
Pleroma.Web.CommonAPI
.
favorite
(
note
.
id
,
another
)
mock_json_body
=
"test/fixtures/mastodon/application_actor.json"
|>
File
.
read!
()
|>
String
.
replace
(
"{{DOMAIN}}"
,
remote_domain
)
Tesla.Mock
.
mock
(
fn
%{
url
:
^
remote_actor
}
->
%
Tesla.Env
{
status
:
200
,
body
:
mock_json_body
,
headers
:
[{
"content-type"
,
"application/activity+json"
}]
}
end
)
data
=
%{
"@context"
=>
"https://www.w3.org/ns/activitystreams"
,
"actor"
=>
remote_actor
,
"content"
=>
"test report"
,
"id"
=>
"https://
#{
remote_domain
}
/e3b12fd1-948c-446e-b93b-a5e67edbe1d8"
,
"object"
=>
[
reported_user
.
ap_id
,
note
.
data
[
"object"
]
],
"type"
=>
"Flag"
}
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
reported_user
.
nickname
}
/inbox"
,
data
)
|>
json_response
(
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
flag_activity
=
"Flag"
|>
Pleroma.Activity.Queries
.
by_type
()
|>
Pleroma.Repo
.
one
()
reported_user_ap_id
=
reported_user
.
ap_id
[
^
reported_user_ap_id
,
flag_data
]
=
flag_activity
.
data
[
"object"
]
Enum
.
each
(
~w(actor content id published type)
,
&
Map
.
has_key?
(
flag_data
,
&1
))
ObanHelpers
.
perform_all
()
Swoosh.TestAssertions
.
assert_email_sent
(
to
:
{
admin
.
name
,
admin
.
email
},
html_body
:
~r/
#{
note
.
data
[
"object"
]
}
/i
)
end
test
"it accepts an incoming Block"
,
%{
conn
:
conn
,
data
:
data
}
do
user
=
insert
(
:user
)
data
=
data
|>
Map
.
put
(
"type"
,
"Block"
)
|>
Map
.
put
(
"to"
,
[
user
.
ap_id
])
|>
Map
.
put
(
"cc"
,
[])
|>
Map
.
put
(
"object"
,
user
.
ap_id
)
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"ok"
==
json_response
(
conn
,
200
)
ObanHelpers
.
perform
(
all_enqueued
(
worker
:
ReceiverWorker
))
assert
Activity
.
get_by_ap_id
(
data
[
"id"
])
end
test
"it returns an error when receiving an activity sent to a deactivated user"
,
%{
conn
:
conn
,
data
:
data
}
do
user
=
insert
(
:user
)
{
:ok
,
_
}
=
User
.
set_activation
(
user
,
false
)
data
=
data
|>
Map
.
put
(
"bcc"
,
[
user
.
ap_id
])
|>
Kernel
.
put_in
([
"object"
,
"bcc"
],
[
user
.
ap_id
])
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"User deactivated"
==
json_response
(
conn
,
404
)
end
test
"it returns an error when receiving an activity sent from a deactivated user"
,
%{
conn
:
conn
,
data
:
data
}
do
sender
=
insert
(
:user
)
user
=
insert
(
:user
)
{
:ok
,
_
}
=
User
.
set_activation
(
sender
,
false
)
data
=
data
|>
Map
.
put
(
"bcc"
,
[
user
.
ap_id
])
|>
Map
.
put
(
"actor"
,
sender
.
ap_id
)
|>
Kernel
.
put_in
([
"object"
,
"bcc"
],
[
user
.
ap_id
])
conn
=
conn
|>
assign
(
:valid_signature
,
true
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/inbox"
,
data
)
assert
"Sender deactivated"
==
json_response
(
conn
,
404
)
end
end
describe
"GET /users/:nickname/outbox"
do
setup
do
Mox
.
stub_with
(
Pleroma.StaticStubbedConfigMock
,
Pleroma.Config
)
:ok
end
test
"it paginates correctly"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
=
assign
(
conn
,
:user
,
user
)
outbox_endpoint
=
user
.
ap_id
<>
"/outbox"
_posts
=
for
i
<-
0
..
25
do
{
:ok
,
activity
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"post
#{
i
}
"
})
activity
end
result
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
outbox_endpoint
<>
"?page=true"
)
|>
json_response
(
200
)
result_ids
=
Enum
.
map
(
result
[
"orderedItems"
],
fn
x
->
x
[
"id"
]
end
)
assert
length
(
result
[
"orderedItems"
])
==
20
assert
length
(
result_ids
)
==
20
assert
result
[
"next"
]
assert
String
.
starts_with?
(
result
[
"next"
],
outbox_endpoint
)
result_next
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
result
[
"next"
])
|>
json_response
(
200
)
result_next_ids
=
Enum
.
map
(
result_next
[
"orderedItems"
],
fn
x
->
x
[
"id"
]
end
)
assert
length
(
result_next
[
"orderedItems"
])
==
6
assert
length
(
result_next_ids
)
==
6
refute
Enum
.
find
(
result_next_ids
,
fn
x
->
x
in
result_ids
end
)
refute
Enum
.
find
(
result_ids
,
fn
x
->
x
in
result_next_ids
end
)
assert
String
.
starts_with?
(
result
[
"id"
],
outbox_endpoint
)
result_next_again
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
result_next
[
"id"
])
|>
json_response
(
200
)
assert
result_next
==
result_next_again
end
test
"it returns 200 even if there're no activities"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
outbox_endpoint
=
user
.
ap_id
<>
"/outbox"
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
outbox_endpoint
)
result
=
json_response
(
conn
,
200
)
assert
outbox_endpoint
==
result
[
"id"
]
end
test
"it returns a local note activity when authenticated as local user"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
reader
=
insert
(
:user
)
{
:ok
,
note_activity
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"mew mew"
,
visibility
:
"local"
})
ap_id
=
note_activity
.
data
[
"id"
]
resp
=
conn
|>
assign
(
:user
,
reader
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/outbox?page=true"
)
|>
json_response
(
200
)
assert
%{
"orderedItems"
=>
[%{
"id"
=>
^
ap_id
}]}
=
resp
end
test
"it does not return a local note activity when unauthenticated"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
{
:ok
,
_note_activity
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"mew mew"
,
visibility
:
"local"
})
resp
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/outbox?page=true"
)
|>
json_response
(
200
)
assert
%{
"orderedItems"
=>
[]}
=
resp
end
test
"it does not return a local note activity when C2S API is disabled"
,
%{
conn
:
conn
}
do
clear_config
([
:activitypub
,
:client_api_enabled
],
false
)
user
=
insert
(
:user
)
reader
=
insert
(
:user
)
{
:ok
,
_note_activity
}
=
CommonAPI
.
post
(
user
,
%{
status
:
"mew mew"
,
visibility
:
"local"
})
resp
=
conn
|>
assign
(
:user
,
reader
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/outbox?page=true"
)
|>
json_response
(
200
)
assert
%{
"orderedItems"
=>
[]}
=
resp
end
test
"it returns a note activity in a collection"
,
%{
conn
:
conn
}
do
note_activity
=
insert
(
:note_activity
)
note_object
=
Object
.
normalize
(
note_activity
,
fetch
:
false
)
user
=
User
.
get_cached_by_ap_id
(
note_activity
.
data
[
"actor"
])
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/outbox?page=true"
)
assert
response
(
conn
,
200
)
=~
note_object
.
data
[
"content"
]
end
test
"it returns an announce activity in a collection"
,
%{
conn
:
conn
}
do
announce_activity
=
insert
(
:announce_activity
)
user
=
User
.
get_cached_by_ap_id
(
announce_activity
.
data
[
"actor"
])
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
"/users/
#{
user
.
nickname
}
/outbox?page=true"
)
assert
response
(
conn
,
200
)
=~
announce_activity
.
data
[
"object"
]
end
test
"It returns poll Answers when authenticated"
,
%{
conn
:
conn
}
do
poller
=
insert
(
:user
)
voter
=
insert
(
:user
)
{
:ok
,
activity
}
=
CommonAPI
.
post
(
poller
,
%{
status
:
"suya..."
,
poll
:
%{
options
:
[
"suya"
,
"suya."
,
"suya.."
],
expires_in
:
10
}
})
assert
question
=
Object
.
normalize
(
activity
,
fetch
:
false
)
{
:ok
,
[
activity
],
_object
}
=
CommonAPI
.
vote
(
question
,
voter
,
[
1
])
assert
outbox_get
=
conn
|>
assign
(
:user
,
voter
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
voter
.
ap_id
<>
"/outbox?page=true"
)
|>
json_response
(
200
)
assert
[
answer_outbox
]
=
outbox_get
[
"orderedItems"
]
assert
answer_outbox
[
"id"
]
==
activity
.
data
[
"id"
]
end
test
"it works with authorized fetch forced when authenticated"
do
clear_config
([
:activitypub
,
:authorized_fetch_mode
],
true
)
user
=
insert
(
:user
)
outbox_endpoint
=
user
.
ap_id
<>
"/outbox"
conn
=
build_conn
()
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
outbox_endpoint
)
assert
json_response
(
conn
,
200
)
end
test
"it fails with authorized fetch forced when unauthenticated"
,
%{
conn
:
conn
}
do
clear_config
([
:activitypub
,
:authorized_fetch_mode
],
true
)
user
=
insert
(
:user
)
outbox_endpoint
=
user
.
ap_id
<>
"/outbox"
conn
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
outbox_endpoint
)
assert
response
(
conn
,
401
)
end
end
describe
"POST /users/:nickname/outbox (C2S)"
do
setup
do
:
clear_config
([
:instance
,
:limit
])
setup
do
[
activity
:
%{
"@context"
=>
"https://www.w3.org/ns/activitystreams"
,
"type"
=>
"Create"
,
"object"
=>
%{
"type"
=>
"Note"
,
"content"
=>
"AP C2S test"
,
"to"
=>
"https://www.w3.org/ns/activitystreams
#
Public"
,
"cc"
=>
[]
}
}
]
end
test
"it rejects posts from other users / unauthenticated users"
,
%{
conn
:
conn
,
activity
:
activity
}
do
user
=
insert
(
:user
)
other_user
=
insert
(
:user
)
conn
=
put_req_header
(
conn
,
"content-type"
,
"application/activity+json"
)
conn
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
403
)
conn
|>
assign
(
:user
,
other_user
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
403
)
end
test
"it inserts an incoming create activity into the database"
,
%{
conn
:
conn
,
activity
:
activity
}
do
user
=
insert
(
:user
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
201
)
assert
Activity
.
get_by_ap_id
(
result
[
"id"
])
assert
result
[
"object"
]
assert
%
Object
{
data
:
object
}
=
Object
.
normalize
(
result
[
"object"
],
fetch
:
false
)
assert
object
[
"content"
]
==
activity
[
"object"
][
"content"
]
end
test
"it rejects anything beyond 'Note' creations"
,
%{
conn
:
conn
,
activity
:
activity
}
do
user
=
insert
(
:user
)
activity
=
activity
|>
put_in
([
"object"
,
"type"
],
"Benis"
)
_result
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
400
)
end
test
"it inserts an incoming sensitive activity into the database"
,
%{
conn
:
conn
,
activity
:
activity
}
do
user
=
insert
(
:user
)
conn
=
assign
(
conn
,
:user
,
user
)
object
=
Map
.
put
(
activity
[
"object"
],
"sensitive"
,
true
)
activity
=
Map
.
put
(
activity
,
"object"
,
object
)
response
=
conn
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
201
)
assert
Activity
.
get_by_ap_id
(
response
[
"id"
])
assert
response
[
"object"
]
assert
%
Object
{
data
:
response_object
}
=
Object
.
normalize
(
response
[
"object"
],
fetch
:
false
)
assert
response_object
[
"sensitive"
]
==
true
assert
response_object
[
"content"
]
==
activity
[
"object"
][
"content"
]
representation
=
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
get
(
response
[
"id"
])
|>
json_response
(
200
)
assert
representation
[
"object"
][
"sensitive"
]
==
true
end
test
"it rejects an incoming activity with bogus type"
,
%{
conn
:
conn
,
activity
:
activity
}
do
user
=
insert
(
:user
)
activity
=
Map
.
put
(
activity
,
"type"
,
"BadType"
)
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
assert
json_response
(
conn
,
400
)
end
test
"it erects a tombstone when receiving a delete activity"
,
%{
conn
:
conn
}
do
note_activity
=
insert
(
:note_activity
)
note_object
=
Object
.
normalize
(
note_activity
,
fetch
:
false
)
user
=
User
.
get_cached_by_ap_id
(
note_activity
.
data
[
"actor"
])
data
=
%{
"type"
=>
"Delete"
,
"object"
=>
%{
"id"
=>
note_object
.
data
[
"id"
]
}
}
result
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
data
)
|>
json_response
(
201
)
assert
Activity
.
get_by_ap_id
(
result
[
"id"
])
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
,
fetch
:
false
)
user
=
insert
(
:user
)
data
=
%{
type
:
"Delete"
,
object
:
%{
id
:
note_object
.
data
[
"id"
]
}
}
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
data
)
assert
json_response
(
conn
,
403
)
end
test
"it rejects update activity of object from other actor"
,
%{
conn
:
conn
}
do
note_activity
=
insert
(
:note_activity
)
note_object
=
Object
.
normalize
(
note_activity
,
fetch
:
false
)
user
=
insert
(
:user
)
data
=
%{
type
:
"Update"
,
object
:
%{
id
:
note_object
.
data
[
"id"
]
}
}
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
data
)
assert
json_response
(
conn
,
400
)
assert
note_object
==
Object
.
normalize
(
note_activity
,
fetch
:
false
)
end
test
"it increases like count when receiving a like action"
,
%{
conn
:
conn
}
do
note_activity
=
insert
(
:note_activity
)
note_object
=
Object
.
normalize
(
note_activity
,
fetch
:
false
)
user
=
User
.
get_cached_by_ap_id
(
note_activity
.
data
[
"actor"
])
data
=
%{
type
:
"Like"
,
object
:
%{
id
:
note_object
.
data
[
"id"
]
}
}
conn
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
data
)
result
=
json_response
(
conn
,
201
)
assert
Activity
.
get_by_ap_id
(
result
[
"id"
])
assert
object
=
Object
.
get_by_ap_id
(
note_object
.
data
[
"id"
])
assert
object
.
data
[
"like_count"
]
==
1
end
test
"it doesn't spreads faulty attributedTo or actor fields"
,
%{
conn
:
conn
,
activity
:
activity
}
do
reimu
=
insert
(
:user
,
nickname
:
"reimu"
)
cirno
=
insert
(
:user
,
nickname
:
"cirno"
)
assert
reimu
.
ap_id
assert
cirno
.
ap_id
activity
=
activity
|>
put_in
([
"object"
,
"actor"
],
reimu
.
ap_id
)
|>
put_in
([
"object"
,
"attributedTo"
],
reimu
.
ap_id
)
|>
put_in
([
"actor"
],
reimu
.
ap_id
)
|>
put_in
([
"attributedTo"
],
reimu
.
ap_id
)
_reimu_outbox
=
conn
|>
assign
(
:user
,
cirno
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
reimu
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
403
)
cirno_outbox
=
conn
|>
assign
(
:user
,
cirno
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
cirno
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
201
)
assert
cirno_outbox
[
"attributedTo"
]
==
nil
assert
cirno_outbox
[
"actor"
]
==
cirno
.
ap_id
assert
cirno_object
=
Object
.
normalize
(
cirno_outbox
[
"object"
],
fetch
:
false
)
assert
cirno_object
.
data
[
"actor"
]
==
cirno
.
ap_id
assert
cirno_object
.
data
[
"attributedTo"
]
==
cirno
.
ap_id
end
test
"Character limitation"
,
%{
conn
:
conn
,
activity
:
activity
}
do
clear_config
([
:instance
,
:limit
],
5
)
user
=
insert
(
:user
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
put_req_header
(
"content-type"
,
"application/activity+json"
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity
)
|>
json_response
(
400
)
assert
result
==
"Character limit (5 characters) exceeded, contains 11 characters"
end
end
describe
"/relay/followers"
do
test
"it returns relay followers"
,
%{
conn
:
conn
}
do
relay_actor
=
Relay
.
get_actor
()
user
=
insert
(
:user
)
User
.
follow
(
user
,
relay_actor
)
result
=
conn
|>
get
(
"/relay/followers"
)
|>
json_response
(
200
)
assert
result
[
"first"
][
"orderedItems"
]
==
[
user
.
ap_id
]
end
test
"on non-federating instance, it returns 404"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:federating
],
false
)
user
=
insert
(
:user
)
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/relay/followers"
)
|>
json_response
(
404
)
end
end
describe
"/relay/following"
do
test
"it returns relay following"
,
%{
conn
:
conn
}
do
result
=
conn
|>
get
(
"/relay/following"
)
|>
json_response
(
200
)
assert
result
[
"first"
][
"orderedItems"
]
==
[]
end
test
"on non-federating instance, it returns 404"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:federating
],
false
)
user
=
insert
(
:user
)
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/relay/following"
)
|>
json_response
(
404
)
end
end
describe
"/users/:nickname/followers"
do
test
"it returns the followers in a collection"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
user_two
=
insert
(
:user
)
User
.
follow
(
user
,
user_two
)
result
=
conn
|>
assign
(
:user
,
user_two
)
|>
get
(
"/users/
#{
user_two
.
nickname
}
/followers"
)
|>
json_response
(
200
)
assert
result
[
"first"
][
"orderedItems"
]
==
[
user
.
ap_id
]
end
test
"it returns a uri if the user has 'hide_followers' set"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
user_two
=
insert
(
:user
,
hide_followers
:
true
)
User
.
follow
(
user
,
user_two
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user_two
.
nickname
}
/followers"
)
|>
json_response
(
200
)
assert
is_binary
(
result
[
"first"
])
end
test
"it returns a 403 error on pages, if the user has 'hide_followers' set and the request is from another user"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
other_user
=
insert
(
:user
,
hide_followers
:
true
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
other_user
.
nickname
}
/followers?page=1"
)
assert
result
.
status
==
403
assert
result
.
resp_body
==
""
end
test
"it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
hide_followers
:
true
)
other_user
=
insert
(
:user
)
{
:ok
,
user
,
_other_user
,
_activity
}
=
CommonAPI
.
follow
(
user
,
other_user
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/followers?page=1"
)
|>
json_response
(
200
)
assert
result
[
"totalItems"
]
==
1
assert
result
[
"orderedItems"
]
==
[
other_user
.
ap_id
]
end
test
"it works for more than 10 users"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
Enum
.
each
(
1
..
15
,
fn
_
->
other_user
=
insert
(
:user
)
User
.
follow
(
other_user
,
user
)
end
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/followers"
)
|>
json_response
(
200
)
assert
length
(
result
[
"first"
][
"orderedItems"
])
==
10
assert
result
[
"first"
][
"totalItems"
]
==
15
assert
result
[
"totalItems"
]
==
15
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/followers?page=2"
)
|>
json_response
(
200
)
assert
length
(
result
[
"orderedItems"
])
==
5
assert
result
[
"totalItems"
]
==
15
end
test
"does not require authentication"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
|>
get
(
"/users/
#{
user
.
nickname
}
/followers"
)
|>
json_response
(
200
)
end
end
describe
"/users/:nickname/following"
do
test
"it returns the following in a collection"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
user_two
=
insert
(
:user
)
User
.
follow
(
user
,
user_two
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/following"
)
|>
json_response
(
200
)
assert
result
[
"first"
][
"orderedItems"
]
==
[
user_two
.
ap_id
]
end
test
"it returns a uri if the user has 'hide_follows' set"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
user_two
=
insert
(
:user
,
hide_follows
:
true
)
User
.
follow
(
user
,
user_two
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user_two
.
nickname
}
/following"
)
|>
json_response
(
200
)
assert
is_binary
(
result
[
"first"
])
end
test
"it returns a 403 error on pages, if the user has 'hide_follows' set and the request is from another user"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
user_two
=
insert
(
:user
,
hide_follows
:
true
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user_two
.
nickname
}
/following?page=1"
)
assert
result
.
status
==
403
assert
result
.
resp_body
==
""
end
test
"it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
hide_follows
:
true
)
other_user
=
insert
(
:user
)
{
:ok
,
_other_user
,
user
,
_activity
}
=
CommonAPI
.
follow
(
other_user
,
user
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/following?page=1"
)
|>
json_response
(
200
)
assert
result
[
"totalItems"
]
==
1
assert
result
[
"orderedItems"
]
==
[
other_user
.
ap_id
]
end
test
"it works for more than 10 users"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
Enum
.
each
(
1
..
15
,
fn
_
->
user
=
User
.
get_cached_by_id
(
user
.
id
)
other_user
=
insert
(
:user
)
User
.
follow
(
user
,
other_user
)
end
)
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/following"
)
|>
json_response
(
200
)
assert
length
(
result
[
"first"
][
"orderedItems"
])
==
10
assert
result
[
"first"
][
"totalItems"
]
==
15
assert
result
[
"totalItems"
]
==
15
result
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/users/
#{
user
.
nickname
}
/following?page=2"
)
|>
json_response
(
200
)
assert
length
(
result
[
"orderedItems"
])
==
5
assert
result
[
"totalItems"
]
==
15
end
test
"does not require authentication"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
|>
get
(
"/users/
#{
user
.
nickname
}
/following"
)
|>
json_response
(
200
)
end
end
describe
"delivery tracking"
do
test
"it tracks a signed object fetch"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
local
:
false
)
activity
=
insert
(
:note_activity
)
object
=
Object
.
normalize
(
activity
,
fetch
:
false
)
object_path
=
String
.
trim_leading
(
object
.
data
[
"id"
],
Pleroma.Web.Endpoint
.
url
())
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
assign
(
:user
,
user
)
|>
get
(
object_path
)
|>
json_response
(
200
)
assert
Delivery
.
get
(
object
.
id
,
user
.
id
)
end
test
"it tracks a signed activity fetch"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
local
:
false
)
activity
=
insert
(
:note_activity
)
object
=
Object
.
normalize
(
activity
,
fetch
:
false
)
activity_path
=
String
.
trim_leading
(
activity
.
data
[
"id"
],
Pleroma.Web.Endpoint
.
url
())
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
assign
(
:user
,
user
)
|>
get
(
activity_path
)
|>
json_response
(
200
)
assert
Delivery
.
get
(
object
.
id
,
user
.
id
)
end
test
"it tracks a signed object fetch when the json is cached"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
local
:
false
)
other_user
=
insert
(
:user
,
local
:
false
)
activity
=
insert
(
:note_activity
)
object
=
Object
.
normalize
(
activity
,
fetch
:
false
)
object_path
=
String
.
trim_leading
(
object
.
data
[
"id"
],
Pleroma.Web.Endpoint
.
url
())
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
assign
(
:user
,
user
)
|>
get
(
object_path
)
|>
json_response
(
200
)
build_conn
()
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
assign
(
:user
,
other_user
)
|>
get
(
object_path
)
|>
json_response
(
200
)
assert
Delivery
.
get
(
object
.
id
,
user
.
id
)
assert
Delivery
.
get
(
object
.
id
,
other_user
.
id
)
end
test
"it tracks a signed activity fetch when the json is cached"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
,
local
:
false
)
other_user
=
insert
(
:user
,
local
:
false
)
activity
=
insert
(
:note_activity
)
object
=
Object
.
normalize
(
activity
,
fetch
:
false
)
activity_path
=
String
.
trim_leading
(
activity
.
data
[
"id"
],
Pleroma.Web.Endpoint
.
url
())
conn
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
assign
(
:user
,
user
)
|>
get
(
activity_path
)
|>
json_response
(
200
)
build_conn
()
|>
put_req_header
(
"accept"
,
"application/activity+json"
)
|>
assign
(
:user
,
other_user
)
|>
get
(
activity_path
)
|>
json_response
(
200
)
assert
Delivery
.
get
(
object
.
id
,
user
.
id
)
assert
Delivery
.
get
(
object
.
id
,
other_user
.
id
)
end
end
describe
"Additional ActivityPub C2S endpoints"
do
test
"GET /api/ap/whoami"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
conn
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/api/ap/whoami"
)
user
=
User
.
get_cached_by_id
(
user
.
id
)
assert
UserView
.
render
(
"user.json"
,
%{
user
:
user
})
==
json_response
(
conn
,
200
)
conn
|>
get
(
"/api/ap/whoami"
)
|>
json_response
(
403
)
end
setup
do
:
clear_config
([
:media_proxy
])
setup
do
:
clear_config
([
Pleroma.Upload
])
test
"POST /api/ap/upload_media"
,
%{
conn
:
conn
}
do
user
=
insert
(
:user
)
desc
=
"Description of the image"
image
=
%
Plug.Upload
{
content_type
:
"image/jpeg"
,
path
:
Path
.
absname
(
"test/fixtures/image.jpg"
),
filename
:
"an_image.jpg"
}
object
=
conn
|>
assign
(
:user
,
user
)
|>
post
(
"/api/ap/upload_media"
,
%{
"file"
=>
image
,
"description"
=>
desc
})
|>
json_response
(
:created
)
assert
object
[
"name"
]
==
desc
assert
object
[
"type"
]
==
"Document"
assert
object
[
"actor"
]
==
user
.
ap_id
assert
[%{
"href"
=>
object_href
,
"mediaType"
=>
object_mediatype
}]
=
object
[
"url"
]
assert
is_binary
(
object_href
)
assert
object_mediatype
==
"image/jpeg"
assert
String
.
ends_with?
(
object_href
,
".jpg"
)
activity_request
=
%{
"@context"
=>
"https://www.w3.org/ns/activitystreams"
,
"type"
=>
"Create"
,
"object"
=>
%{
"type"
=>
"Note"
,
"content"
=>
"AP C2S test, attachment"
,
"attachment"
=>
[
object
],
"to"
=>
"https://www.w3.org/ns/activitystreams
#
Public"
,
"cc"
=>
[]
}
}
activity_response
=
conn
|>
assign
(
:user
,
user
)
|>
post
(
"/users/
#{
user
.
nickname
}
/outbox"
,
activity_request
)
|>
json_response
(
:created
)
assert
activity_response
[
"id"
]
assert
activity_response
[
"object"
]
assert
activity_response
[
"actor"
]
==
user
.
ap_id
assert
%
Object
{
data
:
%{
"attachment"
=>
[
attachment
]}}
=
Object
.
normalize
(
activity_response
[
"object"
],
fetch
:
false
)
assert
attachment
[
"type"
]
==
"Document"
assert
attachment
[
"name"
]
==
desc
assert
[
%{
"href"
=>
^
object_href
,
"type"
=>
"Link"
,
"mediaType"
=>
^
object_mediatype
}
]
=
attachment
[
"url"
]
# Fails if unauthenticated
conn
|>
post
(
"/api/ap/upload_media"
,
%{
"file"
=>
image
,
"description"
=>
desc
})
|>
json_response
(
403
)
end
test
"they don't work when C2S API is disabled"
,
%{
conn
:
conn
}
do
clear_config
([
:activitypub
,
:client_api_enabled
],
false
)
user
=
insert
(
:user
)
assert
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/api/ap/whoami"
)
|>
response
(
403
)
desc
=
"Description of the image"
image
=
%
Plug.Upload
{
content_type
:
"image/jpeg"
,
path
:
Path
.
absname
(
"test/fixtures/image.jpg"
),
filename
:
"an_image.jpg"
}
assert
conn
|>
assign
(
:user
,
user
)
|>
post
(
"/api/ap/upload_media"
,
%{
"file"
=>
image
,
"description"
=>
desc
})
|>
response
(
403
)
end
end
test
"pinned collection"
,
%{
conn
:
conn
}
do
clear_config
([
:instance
,
:max_pinned_statuses
],
2
)
user
=
insert
(
:user
)
objects
=
insert_list
(
2
,
:note
,
user
:
user
)
Enum
.
reduce
(
objects
,
user
,
fn
%{
data
:
%{
"id"
=>
object_id
}},
user
->
{
:ok
,
updated
}
=
User
.
add_pinned_object_id
(
user
,
object_id
)
updated
end
)
%{
nickname
:
nickname
,
featured_address
:
featured_address
,
pinned_objects
:
pinned_objects
}
=
refresh_record
(
user
)
%{
"id"
=>
^
featured_address
,
"orderedItems"
=>
items
,
"totalItems"
=>
2
}
=
conn
|>
get
(
"/users/
#{
nickname
}
/collections/featured"
)
|>
json_response
(
200
)
object_ids
=
Enum
.
map
(
items
,
&
&1
[
"id"
])
assert
Enum
.
all?
(
pinned_objects
,
fn
{
obj_id
,
_
}
->
obj_id
in
object_ids
end
)
end
end
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jan 20, 1:49 PM (8 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
973762
Default Alt Text
activity_pub_controller_test.exs (67 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline
Log In to Comment