forked from AkkomaGang/akkoma
Merge branch 'kaniini/pleroma-feature/activitypub-accept-reject-conformance' into develop
This commit is contained in:
commit
745072b2cc
13 changed files with 327 additions and 30 deletions
|
@ -13,7 +13,7 @@ def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(conn, _opts) do
|
def call(conn, _opts) do
|
||||||
user = Utils.normalize_actor(conn.params["actor"])
|
user = Utils.get_ap_id(conn.params["actor"])
|
||||||
Logger.debug("Checking sig for #{user}")
|
Logger.debug("Checking sig for #{user}")
|
||||||
[signature | _] = get_req_header(conn, "signature")
|
[signature | _] = get_req_header(conn, "signature")
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,8 @@ def user_info(%User{} = user) do
|
||||||
%{
|
%{
|
||||||
following_count: length(user.following) - oneself,
|
following_count: length(user.following) - oneself,
|
||||||
note_count: user.info["note_count"] || 0,
|
note_count: user.info["note_count"] || 0,
|
||||||
follower_count: user.info["follower_count"] || 0
|
follower_count: user.info["follower_count"] || 0,
|
||||||
|
locked: user.info["locked"] || false
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -167,6 +168,35 @@ def register_changeset(struct, params \\ %{}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def maybe_direct_follow(%User{} = follower, %User{info: info} = followed) do
|
||||||
|
user_info = user_info(followed)
|
||||||
|
|
||||||
|
should_direct_follow =
|
||||||
|
cond do
|
||||||
|
# if the account is locked, don't pre-create the relationship
|
||||||
|
user_info.locked == true ->
|
||||||
|
false
|
||||||
|
|
||||||
|
# if the users are blocking each other, we shouldn't even be here, but check for it anyway
|
||||||
|
User.blocks?(follower, followed) == true or User.blocks?(followed, follower) == true ->
|
||||||
|
false
|
||||||
|
|
||||||
|
# if OStatus, then there is no three-way handshake to follow
|
||||||
|
User.ap_enabled?(followed) != true ->
|
||||||
|
true
|
||||||
|
|
||||||
|
# if there are no other reasons not to, just pre-create the relationship
|
||||||
|
true ->
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
if should_direct_follow do
|
||||||
|
follow(follower, followed)
|
||||||
|
else
|
||||||
|
follower
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def follow(%User{} = follower, %User{info: info} = followed) do
|
def follow(%User{} = follower, %User{info: info} = followed) do
|
||||||
ap_followers = followed.follower_address
|
ap_followers = followed.follower_address
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,17 @@ def accept(%{to: to, actor: actor, object: object} = params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reject(%{to: to, actor: actor, object: object} = params) do
|
||||||
|
# only accept false as false value
|
||||||
|
local = !(params[:local] == false)
|
||||||
|
|
||||||
|
with data <- %{"to" => to, "type" => "Reject", "actor" => actor, "object" => object},
|
||||||
|
{:ok, activity} <- insert(data, local),
|
||||||
|
:ok <- maybe_federate(activity) do
|
||||||
|
{:ok, activity}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update(%{to: to, cc: cc, actor: actor, object: object} = params) do
|
def update(%{to: to, cc: cc, actor: actor, object: object} = params) do
|
||||||
# only accept false as false value
|
# only accept false as false value
|
||||||
local = !(params[:local] == false)
|
local = !(params[:local] == false)
|
||||||
|
@ -464,6 +475,7 @@ def user_data_from_user_object(data) do
|
||||||
"url" => [%{"href" => data["image"]["url"]}]
|
"url" => [%{"href" => data["image"]["url"]}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locked = data["manuallyApprovesFollowers"] || false
|
||||||
data = Transmogrifier.maybe_fix_user_object(data)
|
data = Transmogrifier.maybe_fix_user_object(data)
|
||||||
|
|
||||||
user_data = %{
|
user_data = %{
|
||||||
|
@ -471,7 +483,8 @@ def user_data_from_user_object(data) do
|
||||||
info: %{
|
info: %{
|
||||||
"ap_enabled" => true,
|
"ap_enabled" => true,
|
||||||
"source_data" => data,
|
"source_data" => data,
|
||||||
"banner" => banner
|
"banner" => banner,
|
||||||
|
"locked" => locked
|
||||||
},
|
},
|
||||||
avatar: avatar,
|
avatar: avatar,
|
||||||
nickname: "#{data["preferredUsername"]}@#{URI.parse(data["id"]).host}",
|
nickname: "#{data["preferredUsername"]}@#{URI.parse(data["id"]).host}",
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
|
@ -145,6 +146,78 @@ def handle_incoming(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
|
||||||
|
with true <- id =~ "follows",
|
||||||
|
%User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
|
||||||
|
%Activity{} = activity <- Utils.fetch_latest_follow(follower, followed) do
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
_ -> {:error, nil}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp mastodon_follow_hack(_), do: {:error, nil}
|
||||||
|
|
||||||
|
defp get_follow_activity(follow_object, followed) do
|
||||||
|
with object_id when not is_nil(object_id) <- Utils.get_ap_id(follow_object),
|
||||||
|
{_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(object_id)} do
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
# Can't find the activity. This might a Mastodon 2.3 "Accept"
|
||||||
|
{:activity, nil} ->
|
||||||
|
mastodon_follow_hack(follow_object, followed)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error, nil}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_incoming(
|
||||||
|
%{"type" => "Accept", "object" => follow_object, "actor" => actor, "id" => id} = data
|
||||||
|
) do
|
||||||
|
with %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
|
||||||
|
{:ok, follow_activity} <- get_follow_activity(follow_object, followed),
|
||||||
|
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
|
||||||
|
{:ok, activity} <-
|
||||||
|
ActivityPub.accept(%{
|
||||||
|
to: follow_activity.data["to"],
|
||||||
|
type: "Accept",
|
||||||
|
actor: followed.ap_id,
|
||||||
|
object: follow_activity.data["id"],
|
||||||
|
local: false
|
||||||
|
}) do
|
||||||
|
if not User.following?(follower, followed) do
|
||||||
|
{:ok, follower} = User.follow(follower, followed)
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
_e -> :error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_incoming(
|
||||||
|
%{"type" => "Reject", "object" => follow_object, "actor" => actor, "id" => id} = data
|
||||||
|
) do
|
||||||
|
with %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
|
||||||
|
{:ok, follow_activity} <- get_follow_activity(follow_object, followed),
|
||||||
|
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
|
||||||
|
{:ok, activity} <-
|
||||||
|
ActivityPub.accept(%{
|
||||||
|
to: follow_activity.data["to"],
|
||||||
|
type: "Accept",
|
||||||
|
actor: followed.ap_id,
|
||||||
|
object: follow_activity.data["id"],
|
||||||
|
local: false
|
||||||
|
}) do
|
||||||
|
User.unfollow(follower, followed)
|
||||||
|
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
_e -> :error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def handle_incoming(
|
def handle_incoming(
|
||||||
%{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = _data
|
%{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = _data
|
||||||
) do
|
) do
|
||||||
|
@ -207,11 +280,7 @@ def handle_incoming(
|
||||||
def handle_incoming(
|
def handle_incoming(
|
||||||
%{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data
|
%{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data
|
||||||
) do
|
) do
|
||||||
object_id =
|
object_id = Utils.get_ap_id(object_id)
|
||||||
case object_id do
|
|
||||||
%{"id" => id} -> id
|
|
||||||
id -> id
|
|
||||||
end
|
|
||||||
|
|
||||||
with %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
|
with %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
|
||||||
{:ok, object} <-
|
{:ok, object} <-
|
||||||
|
@ -314,9 +383,6 @@ def handle_incoming(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO
|
|
||||||
# Accept
|
|
||||||
|
|
||||||
def handle_incoming(_), do: :error
|
def handle_incoming(_), do: :error
|
||||||
|
|
||||||
def get_obj_helper(id) do
|
def get_obj_helper(id) do
|
||||||
|
|
|
@ -7,18 +7,15 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
|
|
||||||
# Some implementations send the actor URI as the actor field, others send the entire actor object,
|
# Some implementations send the actor URI as the actor field, others send the entire actor object,
|
||||||
# so figure out what the actor's URI is based on what we have.
|
# so figure out what the actor's URI is based on what we have.
|
||||||
def normalize_actor(actor) do
|
def get_ap_id(object) do
|
||||||
cond do
|
case object do
|
||||||
is_binary(actor) ->
|
%{"id" => id} -> id
|
||||||
actor
|
id -> id
|
||||||
|
|
||||||
is_map(actor) ->
|
|
||||||
actor["id"]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_params(params) do
|
def normalize_params(params) do
|
||||||
Map.put(params, "actor", normalize_actor(params["actor"]))
|
Map.put(params, "actor", get_ap_id(params["actor"]))
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_json_ld_header do
|
def make_json_ld_header do
|
||||||
|
|
|
@ -26,7 +26,7 @@ def render("user.json", %{user: user}) do
|
||||||
"name" => user.name,
|
"name" => user.name,
|
||||||
"summary" => user.bio,
|
"summary" => user.bio,
|
||||||
"url" => user.ap_id,
|
"url" => user.ap_id,
|
||||||
"manuallyApprovesFollowers" => false,
|
"manuallyApprovesFollowers" => user.info["locked"] || false,
|
||||||
"publicKey" => %{
|
"publicKey" => %{
|
||||||
"id" => "#{user.ap_id}#main-key",
|
"id" => "#{user.ap_id}#main-key",
|
||||||
"owner" => user.ap_id,
|
"owner" => user.ap_id,
|
||||||
|
|
|
@ -32,14 +32,14 @@ def validate(headers, signature, public_key) do
|
||||||
def validate_conn(conn) do
|
def validate_conn(conn) do
|
||||||
# TODO: How to get the right key and see if it is actually valid for that request.
|
# TODO: How to get the right key and see if it is actually valid for that request.
|
||||||
# For now, fetch the key for the actor.
|
# For now, fetch the key for the actor.
|
||||||
with actor_id <- Utils.normalize_actor(conn.params["actor"]),
|
with actor_id <- Utils.get_ap_id(conn.params["actor"]),
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
||||||
if validate_conn(conn, public_key) do
|
if validate_conn(conn, public_key) do
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
Logger.debug("Could not validate, re-fetching user and trying one more time")
|
Logger.debug("Could not validate, re-fetching user and trying one more time")
|
||||||
# Fetch user anew and try one more time
|
# Fetch user anew and try one more time
|
||||||
with actor_id <- Utils.normalize_actor(conn.params["actor"]),
|
with actor_id <- Utils.get_ap_id(conn.params["actor"]),
|
||||||
{:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
|
{:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
||||||
validate_conn(conn, public_key)
|
validate_conn(conn, public_key)
|
||||||
|
|
|
@ -429,7 +429,7 @@ def following(conn, %{"id" => id}) do
|
||||||
|
|
||||||
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
||||||
with %User{} = followed <- Repo.get(User, id),
|
with %User{} = followed <- Repo.get(User, id),
|
||||||
{:ok, follower} <- User.follow(follower, followed),
|
{:ok, follower} <- User.maybe_direct_follow(follower, followed),
|
||||||
{:ok, _activity} <- ActivityPub.follow(follower, followed) do
|
{:ok, _activity} <- ActivityPub.follow(follower, followed) do
|
||||||
render(conn, AccountView, "relationship.json", %{user: follower, target: followed})
|
render(conn, AccountView, "relationship.json", %{user: follower, target: followed})
|
||||||
else
|
else
|
||||||
|
@ -442,7 +442,7 @@ def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
||||||
|
|
||||||
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
||||||
with %User{} = followed <- Repo.get_by(User, nickname: uri),
|
with %User{} = followed <- Repo.get_by(User, nickname: uri),
|
||||||
{:ok, follower} <- User.follow(follower, followed),
|
{:ok, follower} <- User.maybe_direct_follow(follower, followed),
|
||||||
{:ok, _activity} <- ActivityPub.follow(follower, followed) do
|
{:ok, _activity} <- ActivityPub.follow(follower, followed) do
|
||||||
render(conn, AccountView, "account.json", %{user: followed})
|
render(conn, AccountView, "account.json", %{user: followed})
|
||||||
else
|
else
|
||||||
|
|
|
@ -19,7 +19,7 @@ def render("account.json", %{user: user}) do
|
||||||
username: hd(String.split(user.nickname, "@")),
|
username: hd(String.split(user.nickname, "@")),
|
||||||
acct: user.nickname,
|
acct: user.nickname,
|
||||||
display_name: user.name || user.nickname,
|
display_name: user.name || user.nickname,
|
||||||
locked: false,
|
locked: user_info.locked,
|
||||||
created_at: Utils.to_masto_date(user.inserted_at),
|
created_at: Utils.to_masto_date(user.inserted_at),
|
||||||
followers_count: user_info.follower_count,
|
followers_count: user_info.follower_count,
|
||||||
following_count: user_info.following_count,
|
following_count: user_info.following_count,
|
||||||
|
|
|
@ -25,7 +25,7 @@ def delete(%User{} = user, id) do
|
||||||
|
|
||||||
def follow(%User{} = follower, params) do
|
def follow(%User{} = follower, params) do
|
||||||
with {:ok, %User{} = followed} <- get_user(params),
|
with {:ok, %User{} = followed} <- get_user(params),
|
||||||
{:ok, follower} <- User.follow(follower, followed),
|
{:ok, follower} <- User.maybe_direct_follow(follower, followed),
|
||||||
{:ok, activity} <- ActivityPub.follow(follower, followed) do
|
{:ok, activity} <- ActivityPub.follow(follower, followed) do
|
||||||
{:ok, follower, followed, activity}
|
{:ok, follower, followed, activity}
|
||||||
else
|
else
|
||||||
|
|
34
test/fixtures/mastodon-reject-activity.json
vendored
Normal file
34
test/fixtures/mastodon-reject-activity.json
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"type": "Reject",
|
||||||
|
"signature": {
|
||||||
|
"type": "RsaSignature2017",
|
||||||
|
"signatureValue": "rBzK4Kqhd4g7HDS8WE5oRbWQb2R+HF/6awbUuMWhgru/xCODT0SJWSri0qWqEO4fPcpoUyz2d25cw6o+iy9wiozQb3hQNnu69AR+H5Mytc06+g10KCHexbGhbAEAw/7IzmeXELHUbaqeduaDIbdt1zw4RkwLXdqgQcGXTJ6ND1wM3WMHXQCK1m0flasIXFoBxpliPAGiElV8s0+Ltuh562GvflG3kB3WO+j+NaR0ZfG5G9N88xMj9UQlCKit5gpAE5p6syUsCU2WGBHywTumv73i3OVTIFfq+P9AdMsRuzw1r7zoKEsthW4aOzLQDi01ZjvdBz8zH6JnjDU7SMN/Ig==",
|
||||||
|
"creator": "http://mastodon.example.org/users/admin#main-key",
|
||||||
|
"created": "2018-02-17T14:36:41Z"
|
||||||
|
},
|
||||||
|
"object": {
|
||||||
|
"type": "Follow",
|
||||||
|
"object": "http://mastodon.example.org/users/admin",
|
||||||
|
"id": "http://localtesting.pleroma.lol/users/lain#follows/4",
|
||||||
|
"actor": "http://localtesting.pleroma.lol/users/lain"
|
||||||
|
},
|
||||||
|
"nickname": "lain",
|
||||||
|
"id": "http://mastodon.example.org/users/admin#rejects/follows/4",
|
||||||
|
"actor": "http://mastodon.example.org/users/admin",
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"toot": "http://joinmastodon.org/ns#",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"ostatus": "http://ostatus.org#",
|
||||||
|
"movedTo": "as:movedTo",
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||||
|
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||||
|
"conversation": "ostatus:conversation",
|
||||||
|
"atomUri": "ostatus:atomUri",
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"Emoji": "toot:Emoji"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -2,13 +2,12 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.OStatus
|
alias Pleroma.Web.OStatus
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.Web.Websub.WebsubClientSubscription
|
alias Pleroma.Web.Websub.WebsubClientSubscription
|
||||||
alias Pleroma.Web.Websub.WebsubServerSubscription
|
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
@ -283,7 +282,7 @@ test "it works for incoming deletes" do
|
||||||
|> Map.put("object", object)
|
|> Map.put("object", object)
|
||||||
|> Map.put("actor", activity.data["actor"])
|
|> Map.put("actor", activity.data["actor"])
|
||||||
|
|
||||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
{:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
refute Repo.get(Activity, activity.id)
|
refute Repo.get(Activity, activity.id)
|
||||||
end
|
end
|
||||||
|
@ -385,6 +384,164 @@ test "it works for incoming unblocks with an existing block" do
|
||||||
|
|
||||||
refute User.blocks?(blocker, user)
|
refute User.blocks?(blocker, user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
{: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)
|
||||||
|
|
||||||
|
object =
|
||||||
|
accept_data["object"]
|
||||||
|
|> Map.put("actor", follower.ap_id)
|
||||||
|
|> Map.put("id", follow_activity.data["id"])
|
||||||
|
|
||||||
|
accept_data = Map.put(accept_data, "object", object)
|
||||||
|
|
||||||
|
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
|
||||||
|
refute activity.local
|
||||||
|
|
||||||
|
assert activity.data["object"] == follow_activity.data["id"]
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
assert User.following?(follower, followed) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it works for incoming accepts which were orphaned" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, %{info: %{"locked" => true}})
|
||||||
|
|
||||||
|
{: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))
|
||||||
|
|
||||||
|
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
|
||||||
|
assert activity.data["object"] == follow_activity.data["id"]
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
assert User.following?(follower, followed) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it works for incoming accepts which are referenced by IRI only" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, %{info: %{"locked" => true}})
|
||||||
|
|
||||||
|
{: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"])
|
||||||
|
|
||||||
|
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
|
||||||
|
assert activity.data["object"] == follow_activity.data["id"]
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
assert User.following?(follower, followed) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it fails for incoming accepts which cannot be correlated" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, %{info: %{"locked" => true}})
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
refute User.following?(follower, followed) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it fails for incoming rejects which cannot be correlated" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, %{info: %{"locked" => true}})
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
refute User.following?(follower, followed) == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it works for incoming rejects which are orphaned" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, %{info: %{"locked" => true}})
|
||||||
|
|
||||||
|
{: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)
|
||||||
|
|
||||||
|
reject_data =
|
||||||
|
Map.put(reject_data, "object", Map.put(reject_data["object"], "actor", follower.ap_id))
|
||||||
|
|
||||||
|
{:ok, activity} = Transmogrifier.handle_incoming(reject_data)
|
||||||
|
refute activity.local
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
assert User.following?(follower, followed) == false
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it works for incoming rejects which are referenced by IRI only" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user, %{info: %{"locked" => true}})
|
||||||
|
|
||||||
|
{: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)
|
||||||
|
|
||||||
|
follower = Repo.get(User, follower.id)
|
||||||
|
|
||||||
|
assert User.following?(follower, followed) == false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "prepare outgoing" do
|
describe "prepare outgoing" do
|
||||||
|
|
|
@ -298,7 +298,7 @@ test "deleting a list", %{conn: conn} do
|
||||||
test "list timeline", %{conn: conn} do
|
test "list timeline", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
|
{:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
|
||||||
{:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
|
{:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
|
||||||
{:ok, list} = Pleroma.List.create("name", user)
|
{:ok, list} = Pleroma.List.create("name", user)
|
||||||
{:ok, list} = Pleroma.List.follow(list, other_user)
|
{:ok, list} = Pleroma.List.follow(list, other_user)
|
||||||
|
|
Loading…
Reference in a new issue