move things around
This commit is contained in:
parent
1c0d0fcd8d
commit
97cedc73b6
|
@ -2,8 +2,8 @@ defmodule Vonbraun.ActivityPub.Handler.Accept do
|
||||||
@behaviour Vonbraun.ActivityPub.HandlerBehaviour
|
@behaviour Vonbraun.ActivityPub.HandlerBehaviour
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
alias Vonbraun.Util
|
||||||
alias Vonbraun.Ecto.Schema.Actor
|
alias Vonbraun.Ecto.Schema.Actor
|
||||||
alias Vonbraun.ActivityPub.Object
|
|
||||||
|
|
||||||
@verb "Accept"
|
@verb "Accept"
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ defmodule Vonbraun.ActivityPub.Handler.Accept do
|
||||||
%{}
|
%{}
|
||||||
) do
|
) do
|
||||||
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
|
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
|
||||||
{:match, true} <- {:match, follow_actor_id == Object.my_id()},
|
{:match, true} <- {:match, follow_actor_id == Util.my_id()},
|
||||||
{:asked, {:ok, %Actor{:blocked => nil, :following_state => "accepted"}}} <-
|
{:asked, {:ok, %Actor{:blocked => nil, :following_state => "accepted"}}} <-
|
||||||
{:asked, Actor.mark_pending_follow(actor_id, "accepted", force: true)} do
|
{:asked, Actor.mark_pending_follow(actor_id, "accepted", force: true)} do
|
||||||
Logger.info("Now following: #{actor_id}")
|
Logger.info("Now following: #{actor_id}")
|
||||||
|
|
|
@ -5,6 +5,7 @@ defmodule Vonbraun.ActivityPub.Handler.Follow do
|
||||||
alias Vonbraun.ActivityPubReq
|
alias Vonbraun.ActivityPubReq
|
||||||
alias Vonbraun.Ecto.Schema.Actor
|
alias Vonbraun.Ecto.Schema.Actor
|
||||||
alias Vonbraun.ActivityPub.Object
|
alias Vonbraun.ActivityPub.Object
|
||||||
|
alias Vonbraun.Util
|
||||||
|
|
||||||
@verb "Follow"
|
@verb "Follow"
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ defmodule Vonbraun.ActivityPub.Handler.Follow do
|
||||||
actor = %{}
|
actor = %{}
|
||||||
)
|
)
|
||||||
when is_binary(follow_requester_id) and is_binary(follow_target) and is_binary(activity_id) do
|
when is_binary(follow_requester_id) and is_binary(follow_target) and is_binary(activity_id) do
|
||||||
with {:valid_target, true} <- {:valid_target, Object.my_id() == follow_target},
|
with {:valid_target, true} <- {:valid_target, Util.my_id() == follow_target},
|
||||||
{:add, {:ok, %Actor{:blocked => nil, :follows_me_state => follows_me_state}}}
|
{:add, {:ok, %Actor{:blocked => nil, :follows_me_state => follows_me_state}}}
|
||||||
when not is_nil(follows_me_state) <-
|
when not is_nil(follows_me_state) <-
|
||||||
{:add, Actor.maybe_add_follower(follow_requester_id)} do
|
{:add, Actor.maybe_add_follower(follow_requester_id)} do
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule Vonbraun.ActivityPub.Handler.Reject do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
alias Vonbraun.Ecto.Schema.Actor
|
alias Vonbraun.Ecto.Schema.Actor
|
||||||
alias Vonbraun.ActivityPub.Object
|
alias Vonbraun.Util
|
||||||
import Vonbraun.ActivityPub.Handler.Accept, only: [extract_follow_object_actor: 1]
|
import Vonbraun.ActivityPub.Handler.Accept, only: [extract_follow_object_actor: 1]
|
||||||
|
|
||||||
@verb "Reject"
|
@verb "Reject"
|
||||||
|
@ -16,7 +16,7 @@ defmodule Vonbraun.ActivityPub.Handler.Reject do
|
||||||
"object" => object = %{"type" => "Follow"}
|
"object" => object = %{"type" => "Follow"}
|
||||||
}) do
|
}) do
|
||||||
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
|
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
|
||||||
{:match, true} <- {:match, follow_actor_id == Object.my_id()},
|
{:match, true} <- {:match, follow_actor_id == Util.my_id()},
|
||||||
{:asked, {:ok, %Actor{:blocked => nil, :following_state => "accepted"}}} <-
|
{:asked, {:ok, %Actor{:blocked => nil, :following_state => "accepted"}}} <-
|
||||||
{:asked, Actor.mark_pending_follow(actor_id, "rejected", force: true)} do
|
{:asked, Actor.mark_pending_follow(actor_id, "rejected", force: true)} do
|
||||||
Logger.info("Now following: #{actor_id}")
|
Logger.info("Now following: #{actor_id}")
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule Vonbraun.ActivityPub.Handler.Undo do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
alias Vonbraun.Ecto.Schema.Actor
|
alias Vonbraun.Ecto.Schema.Actor
|
||||||
alias Vonbraun.ActivityPub.Object
|
alias Vonbraun.Util
|
||||||
import Vonbraun.ActivityPub.Handler.Accept, only: [extract_follow_object_actor: 1]
|
import Vonbraun.ActivityPub.Handler.Accept, only: [extract_follow_object_actor: 1]
|
||||||
|
|
||||||
@verb "Undo"
|
@verb "Undo"
|
||||||
|
@ -14,7 +14,7 @@ defmodule Vonbraun.ActivityPub.Handler.Undo do
|
||||||
|
|
||||||
def handle(%{"type" => @verb, "actor" => actor_id, "object" => object = %{"type" => "Follow"}}) do
|
def handle(%{"type" => @verb, "actor" => actor_id, "object" => object = %{"type" => "Follow"}}) do
|
||||||
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
|
with {:actor, {:ok, follow_actor_id}} <- {:actor, extract_follow_object_actor(object)},
|
||||||
{:match, true} <- {:match, follow_actor_id == Object.my_id()},
|
{:match, true} <- {:match, follow_actor_id == Util.my_id()},
|
||||||
{:asked, {:ok, %Actor{:following_state => nil}}} <-
|
{:asked, {:ok, %Actor{:following_state => nil}}} <-
|
||||||
{:asked, Actor.remove_follower(actor_id)} do
|
{:asked, Actor.remove_follower(actor_id)} do
|
||||||
{:ok, :removed_follower}
|
{:ok, :removed_follower}
|
||||||
|
|
|
@ -2,17 +2,7 @@ defmodule Vonbraun.ActivityPub.Object do
|
||||||
@context "https://www.w3.org/ns/activitystreams"
|
@context "https://www.w3.org/ns/activitystreams"
|
||||||
@public_to "https://www.w3.org/ns/activitystreams#Public"
|
@public_to "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
@spec my_id() :: String.t()
|
import Vonbraun.Util, only: [my_id: 0]
|
||||||
def my_id() do
|
|
||||||
domain = Application.fetch_env!(:vonbraun, :domain)
|
|
||||||
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
|
||||||
"https://#{domain}/users/#{nickname}"
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec my_key_id() :: String.t()
|
|
||||||
def my_key_id() do
|
|
||||||
"#{my_id()}#main-key"
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_context(object = %{"@context" => context})
|
def add_context(object = %{"@context" => context})
|
||||||
when is_list(context) or is_binary(context) do
|
when is_list(context) or is_binary(context) do
|
||||||
|
@ -112,6 +102,9 @@ defmodule Vonbraun.ActivityPub.Object do
|
||||||
to: to_follow_id
|
to: to_follow_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@spec accept_follow_activity(binary(), binary(), :accept | :reject) :: %{
|
||||||
|
optional(<<_::16, _::_*8>>) => any()
|
||||||
|
}
|
||||||
def accept_follow_activity(followee_id, activity_id, type \\ :accept)
|
def accept_follow_activity(followee_id, activity_id, type \\ :accept)
|
||||||
when is_binary(followee_id) and is_binary(activity_id) and type in [:accept, :reject] do
|
when is_binary(followee_id) and is_binary(activity_id) and type in [:accept, :reject] do
|
||||||
activity_type =
|
activity_type =
|
||||||
|
@ -132,4 +125,102 @@ defmodule Vonbraun.ActivityPub.Object do
|
||||||
|
|
||||||
activity(activity_type, accept_activity_id, object, to: followee_id)
|
activity(activity_type, accept_activity_id, object, to: followee_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_maybe_activitypub?(%{"@context" => @context}), do: true
|
||||||
|
|
||||||
|
def is_maybe_activitypub?(%{"@context" => context_list}) when is_list(context_list) do
|
||||||
|
Enum.reduce_while(context_list, false, fn
|
||||||
|
@context, _ ->
|
||||||
|
{:halt, true}
|
||||||
|
|
||||||
|
context = %{}, _ ->
|
||||||
|
if Enum.find(context, fn item -> elem(item, 1) == @context end) do
|
||||||
|
{:halt, true}
|
||||||
|
else
|
||||||
|
{:cont, false}
|
||||||
|
end
|
||||||
|
|
||||||
|
_, _ ->
|
||||||
|
{:cont, false}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_maybe_activitypub?(_), do: false
|
||||||
|
|
||||||
|
@spec fix_ld_properties(any()) ::
|
||||||
|
{:error, :child_id | :child_type | :id | :list | :type | :unknown}
|
||||||
|
| {:ok, list(list() | map()) | map()}
|
||||||
|
@doc """
|
||||||
|
If an object has type or id convert them to "@type" and "@id" respectively.
|
||||||
|
This is so that AP objects conform to JSON-LD for our purposes even though
|
||||||
|
they don't have to in the outside world. If the properties don't exist, they
|
||||||
|
are not added. Also fixes the properties of an "object" value, if present.
|
||||||
|
"""
|
||||||
|
def fix_ld_properties(object = %{}) do
|
||||||
|
has_unadorned_id? = Map.has_key?(object, "id")
|
||||||
|
has_id? = Map.has_key?(object, "@id")
|
||||||
|
has_unadored_type? = Map.has_key?(object, "type")
|
||||||
|
has_type? = Map.has_key?(object, "@type")
|
||||||
|
|
||||||
|
cond do
|
||||||
|
has_unadorned_id? && has_id? ->
|
||||||
|
{:error, :id}
|
||||||
|
|
||||||
|
has_unadored_type? && has_type? ->
|
||||||
|
{:error, :type}
|
||||||
|
|
||||||
|
true ->
|
||||||
|
object =
|
||||||
|
if has_unadorned_id? do
|
||||||
|
id = Map.get(object, "id")
|
||||||
|
object |> Map.delete("id") |> Map.put("@id", id)
|
||||||
|
else
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_unadored_type? do
|
||||||
|
type = Map.get(object, "type")
|
||||||
|
object |> Map.delete("type") |> Map.put("@type", type)
|
||||||
|
else
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
|
# I am just assuming here the object is a JSON-LD object, not sure yet
|
||||||
|
# if this is a valid assumption.
|
||||||
|
with {:object, child_object = %{}} <- {:object, Map.get(object, "object")},
|
||||||
|
{:valid, {:ok, child_object}} <- {:valid, fix_ld_properties(child_object)} do
|
||||||
|
{:ok, Map.put(object, "object", child_object)}
|
||||||
|
else
|
||||||
|
{:object, child_object} when is_nil(child_object) or is_binary(child_object) ->
|
||||||
|
{:ok, Map.put(object, "object", child_object)}
|
||||||
|
|
||||||
|
{:valid, {:error, :type}} ->
|
||||||
|
{:error, :child_type}
|
||||||
|
|
||||||
|
{:valid, {:error, :id}} ->
|
||||||
|
{:error, :child_id}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# I forgot why I wrote this lol.
|
||||||
|
def fix_ld_properties(list) when is_list(list) do
|
||||||
|
fixed_objects =
|
||||||
|
Enum.reduce_while(list, {:ok, []}, fn object, objects ->
|
||||||
|
case fix_ld_properties(object) do
|
||||||
|
{:ok, fixed_object} -> {:cont, [fixed_object | objects]}
|
||||||
|
{:error, _error} -> {:halt, :error}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
case fixed_objects do
|
||||||
|
:error ->
|
||||||
|
{:error, :list}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:ok, Enum.reverse(fixed_objects)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fix_ld_properties(_), do: {:error, :unknown}
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule Vonbraun.ActivityPubReq do
|
defmodule Vonbraun.ActivityPubReq do
|
||||||
require Logger
|
require Logger
|
||||||
alias Vonbraun.Cache
|
alias Vonbraun.Cache
|
||||||
|
alias Vonbraun.Util
|
||||||
alias Vonbraun.HTTPSignature
|
alias Vonbraun.HTTPSignature
|
||||||
alias Vonbraun.ActivityPub.Object
|
|
||||||
|
|
||||||
@ttl :timer.minutes(1)
|
@ttl :timer.minutes(1)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ defmodule Vonbraun.ActivityPubReq do
|
||||||
path
|
path
|
||||||
end
|
end
|
||||||
|
|
||||||
headers = HTTPSignature.add_get_signature(headers, Object.my_key_id(), target)
|
headers = HTTPSignature.add_get_signature(headers, Util.my_key_id(), target)
|
||||||
|
|
||||||
Req.get(url, headers: headers)
|
Req.get(url, headers: headers)
|
||||||
end
|
end
|
||||||
|
@ -39,7 +39,7 @@ defmodule Vonbraun.ActivityPubReq do
|
||||||
path
|
path
|
||||||
end
|
end
|
||||||
|
|
||||||
headers = HTTPSignature.add_post_signature(headers, Object.my_key_id(), target, body)
|
headers = HTTPSignature.add_post_signature(headers, Util.my_key_id(), target, body)
|
||||||
|
|
||||||
Logger.debug("POST payload is: `#{body}`")
|
Logger.debug("POST payload is: `#{body}`")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
defmodule Vonbraun.Util do
|
||||||
|
@spec my_id() :: String.t()
|
||||||
|
def my_id() do
|
||||||
|
domain = Application.fetch_env!(:vonbraun, :domain)
|
||||||
|
nickname = Application.fetch_env!(:vonbraun, :nickname)
|
||||||
|
"https://#{domain}/users/#{nickname}"
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec my_key_id() :: String.t()
|
||||||
|
def my_key_id() do
|
||||||
|
"#{my_id()}#main-key"
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue