aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorlain <lain@soykaf.club>2018-05-26 15:15:52 +0200
committerlain <lain@soykaf.club>2018-05-26 15:15:52 +0200
commit745072b2cc0ce3be6e1896bcacffb5e48782f6da (patch)
tree2d46ec202c6c0bb4e1469da1cd7d369559b8be52 /lib
parente1fe46e1cfccb7971032ecfa04426413f0c00ac6 (diff)
parent0a6c897c9488b26273a5fbb2de1ae1bfa0c96675 (diff)
downloadpleroma-745072b2cc0ce3be6e1896bcacffb5e48782f6da.tar.gz
Merge branch 'kaniini/pleroma-feature/activitypub-accept-reject-conformance' into develop
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/plugs/http_signature.ex2
-rw-r--r--lib/pleroma/user.ex32
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex15
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex82
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex13
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex2
-rw-r--r--lib/pleroma/web/http_signatures/http_signatures.ex4
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex4
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex2
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex2
10 files changed, 132 insertions, 26 deletions
diff --git a/lib/pleroma/plugs/http_signature.ex b/lib/pleroma/plugs/http_signature.ex
index 2d0e10cad..38bcd3a78 100644
--- a/lib/pleroma/plugs/http_signature.ex
+++ b/lib/pleroma/plugs/http_signature.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
end
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}")
[signature | _] = get_req_header(conn, "signature")
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 508f14584..75e173d0c 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -67,7 +67,8 @@ defmodule Pleroma.User do
%{
following_count: length(user.following) - oneself,
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
@@ -167,6 +168,35 @@ defmodule Pleroma.User do
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
ap_followers = followed.follower_address
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 8485a8009..1a1bfbffd 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -95,6 +95,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
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
# only accept false as false value
local = !(params[:local] == false)
@@ -464,6 +475,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
"url" => [%{"href" => data["image"]["url"]}]
}
+ locked = data["manuallyApprovesFollowers"] || false
data = Transmogrifier.maybe_fix_user_object(data)
user_data = %{
@@ -471,7 +483,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
info: %{
"ap_enabled" => true,
"source_data" => data,
- "banner" => banner
+ "banner" => banner,
+ "locked" => locked
},
avatar: avatar,
nickname: "#{data["preferredUsername"]}@#{URI.parse(data["id"]).host}",
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index eada4334e..3c9377be9 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Activity
alias Pleroma.Repo
alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Utils
import Ecto.Query
@@ -145,6 +146,78 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
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(
%{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = _data
) do
@@ -207,11 +280,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def handle_incoming(
%{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data
) do
- object_id =
- case object_id do
- %{"id" => id} -> id
- id -> id
- end
+ object_id = Utils.get_ap_id(object_id)
with %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <-
@@ -314,9 +383,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
- # TODO
- # Accept
-
def handle_incoming(_), do: :error
def get_obj_helper(id) do
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index cb2e1e078..56b80a8db 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -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,
# so figure out what the actor's URI is based on what we have.
- def normalize_actor(actor) do
- cond do
- is_binary(actor) ->
- actor
-
- is_map(actor) ->
- actor["id"]
+ def get_ap_id(object) do
+ case object do
+ %{"id" => id} -> id
+ id -> id
end
end
def normalize_params(params) do
- Map.put(params, "actor", normalize_actor(params["actor"]))
+ Map.put(params, "actor", get_ap_id(params["actor"]))
end
def make_json_ld_header do
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index ffd76b529..f4b2e0610 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"name" => user.name,
"summary" => user.bio,
"url" => user.ap_id,
- "manuallyApprovesFollowers" => false,
+ "manuallyApprovesFollowers" => user.info["locked"] || false,
"publicKey" => %{
"id" => "#{user.ap_id}#main-key",
"owner" => user.ap_id,
diff --git a/lib/pleroma/web/http_signatures/http_signatures.ex b/lib/pleroma/web/http_signatures/http_signatures.ex
index 4e0adbc1d..5e42a871b 100644
--- a/lib/pleroma/web/http_signatures/http_signatures.ex
+++ b/lib/pleroma/web/http_signatures/http_signatures.ex
@@ -32,14 +32,14 @@ defmodule Pleroma.Web.HTTPSignatures do
def validate_conn(conn) do
# 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.
- 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
if validate_conn(conn, public_key) do
true
else
Logger.debug("Could not validate, re-fetching user and trying 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, public_key} <- User.get_public_key_for_ap_id(actor_id) do
validate_conn(conn, public_key)
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 460942f1a..e12d3fb5b 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -429,7 +429,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
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
render(conn, AccountView, "relationship.json", %{user: follower, target: followed})
else
@@ -442,7 +442,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
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
render(conn, AccountView, "account.json", %{user: followed})
else
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index f378bb36e..9db683f44 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
username: hd(String.split(user.nickname, "@")),
acct: user.nickname,
display_name: user.name || user.nickname,
- locked: false,
+ locked: user_info.locked,
created_at: Utils.to_masto_date(user.inserted_at),
followers_count: user_info.follower_count,
following_count: user_info.following_count,
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 3ccdaed6f..331efa90b 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -25,7 +25,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
def follow(%User{} = follower, params) do
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, follower, followed, activity}
else