feat(activitypub): implement FEP-2677 to identify the application actor used for federation
Instead of always assuming it will be @relay@host.tld Closes #1367 Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
049ffd61b7
commit
f10977a99a
|
@ -13,7 +13,7 @@ defmodule Mobilizon.Federation.ActivityPub.Relay do
|
||||||
|
|
||||||
alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Transmogrifier}
|
alias Mobilizon.Federation.ActivityPub.{Actions, Activity, Transmogrifier}
|
||||||
alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor
|
alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor
|
||||||
alias Mobilizon.Federation.WebFinger
|
alias Mobilizon.Federation.{NodeInfo, WebFinger}
|
||||||
alias Mobilizon.GraphQL.API.Follows
|
alias Mobilizon.GraphQL.API.Follows
|
||||||
alias Mobilizon.Service.Workers.Background
|
alias Mobilizon.Service.Workers.Background
|
||||||
import Mobilizon.Federation.ActivityPub.Utils, only: [create_full_domain_string: 1]
|
import Mobilizon.Federation.ActivityPub.Utils, only: [create_full_domain_string: 1]
|
||||||
|
@ -192,10 +192,10 @@ defmodule Mobilizon.Federation.ActivityPub.Relay do
|
||||||
check_actor(address)
|
check_actor(address)
|
||||||
|
|
||||||
!is_nil(host) ->
|
!is_nil(host) ->
|
||||||
uri
|
case NodeInfo.application_actor(host) do
|
||||||
|> create_full_domain_string()
|
nil -> check_actor("relay@#{host}")
|
||||||
|> then(&Kernel.<>("relay@", &1))
|
actor_url when is_binary(actor_url) -> {:ok, actor_url}
|
||||||
|> check_actor()
|
end
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
{:error, :bad_url}
|
{:error, :bad_url}
|
||||||
|
|
33
lib/federation/node_info.ex
Normal file
33
lib/federation/node_info.ex
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule Mobilizon.Federation.NodeInfo do
|
||||||
|
@moduledoc """
|
||||||
|
Performs NodeInfo requests
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias Mobilizon.Service.HTTP.WebfingerClient
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@application_uri "https://www.w3.org/ns/activitystreams#Application"
|
||||||
|
@env Application.compile_env(:mobilizon, :env)
|
||||||
|
|
||||||
|
@spec application_actor(String.t()) :: String.t() | nil
|
||||||
|
def application_actor(host) do
|
||||||
|
prefix = if @env !== :dev, do: "https", else: "http"
|
||||||
|
|
||||||
|
case WebfingerClient.get("#{prefix}://#{host}/.well-known/nodeinfo") do
|
||||||
|
{:ok, %{body: body, status: code}} when code in 200..299 ->
|
||||||
|
extract_application_actor(body)
|
||||||
|
|
||||||
|
err ->
|
||||||
|
Logger.debug("Failed to fetch NodeInfo data #{inspect(err)}")
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp extract_application_actor(body) do
|
||||||
|
body
|
||||||
|
|> Enum.find(%{rel: @application_uri, href: nil}, fn %{rel: rel, href: href} ->
|
||||||
|
rel == @application_uri and is_binary(href)
|
||||||
|
end)
|
||||||
|
|> Map.get(:href)
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,13 +7,17 @@ defmodule Mobilizon.Web.NodeInfoController do
|
||||||
use Mobilizon.Web, :controller
|
use Mobilizon.Web, :controller
|
||||||
|
|
||||||
alias Mobilizon.Config
|
alias Mobilizon.Config
|
||||||
|
alias Mobilizon.Federation.ActivityPub.Relay
|
||||||
alias Mobilizon.Service.Statistics
|
alias Mobilizon.Service.Statistics
|
||||||
|
|
||||||
@node_info_supported_versions ["2.0", "2.1"]
|
@node_info_supported_versions ["2.0", "2.1"]
|
||||||
@node_info_schema_uri "http://nodeinfo.diaspora.software/ns/schema/"
|
@node_info_schema_uri "http://nodeinfo.diaspora.software/ns/schema/"
|
||||||
|
@application_uri "https://www.w3.org/ns/activitystreams#Application"
|
||||||
|
|
||||||
@spec schemas(Plug.Conn.t(), any) :: Plug.Conn.t()
|
@spec schemas(Plug.Conn.t(), any) :: Plug.Conn.t()
|
||||||
def schemas(conn, _params) do
|
def schemas(conn, _params) do
|
||||||
|
relay = Relay.get_actor()
|
||||||
|
|
||||||
links =
|
links =
|
||||||
@node_info_supported_versions
|
@node_info_supported_versions
|
||||||
|> Enum.map(fn version ->
|
|> Enum.map(fn version ->
|
||||||
|
@ -22,6 +26,12 @@ defmodule Mobilizon.Web.NodeInfoController do
|
||||||
href: url(~p"/.well-known/nodeinfo/#{version}")
|
href: url(~p"/.well-known/nodeinfo/#{version}")
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|> Kernel.++([
|
||||||
|
%{
|
||||||
|
rel: @application_uri,
|
||||||
|
href: relay.url
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
json(conn, %{
|
json(conn, %{
|
||||||
links: links
|
links: links
|
||||||
|
|
|
@ -2,12 +2,16 @@ defmodule Mobilizon.Web.NodeInfoControllerTest do
|
||||||
use Mobilizon.Web.ConnCase
|
use Mobilizon.Web.ConnCase
|
||||||
|
|
||||||
alias Mobilizon.Config
|
alias Mobilizon.Config
|
||||||
|
alias Mobilizon.Federation.ActivityPub.Relay
|
||||||
|
|
||||||
use Mobilizon.Web, :verified_routes
|
use Mobilizon.Web, :verified_routes
|
||||||
|
|
||||||
test "Get node info schemas", %{conn: conn} do
|
test "Get node info schemas", %{conn: conn} do
|
||||||
conn = get(conn, url(~p"/.well-known/nodeinfo"))
|
conn = get(conn, url(~p"/.well-known/nodeinfo"))
|
||||||
|
|
||||||
|
relay = Relay.get_actor()
|
||||||
|
relay_url = relay.url
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response(conn, 200) == %{
|
||||||
"links" => [
|
"links" => [
|
||||||
%{
|
%{
|
||||||
|
@ -17,6 +21,10 @@ defmodule Mobilizon.Web.NodeInfoControllerTest do
|
||||||
%{
|
%{
|
||||||
"href" => url(~p"/.well-known/nodeinfo/2.1"),
|
"href" => url(~p"/.well-known/nodeinfo/2.1"),
|
||||||
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.1"
|
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.1"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"href" => relay_url,
|
||||||
|
"rel" => "https://www.w3.org/ns/activitystreams#Application"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue