3.0 KiB · text 5af55d9
defmodule GitGudWeb.WellKnownController do
@moduledoc """
Standard `.well-known` endpoints used by AP-aware clients to discover
our instance + resolve `acct:` URIs.
* `/.well-known/webfinger?resource=acct:<handle>@<host>`
* `/.well-known/nodeinfo`
* `/nodeinfo/2.1`
"""
use GitGudWeb, :controller
alias GitGud.Federation
def webfinger(conn, %{"resource" => "acct:" <> account}) do
case parse_account(account) do
{:ok, handle, host} ->
if same_host?(host) do
render_webfinger(conn, handle)
else
send_resp(conn, 404, "")
end
:error ->
send_resp(conn, 400, "")
end
end
def webfinger(conn, _params), do: send_resp(conn, 400, "")
defp parse_account(account) do
case String.split(account, "@", parts: 2) do
[handle, host] when handle != "" and host != "" -> {:ok, handle, host}
_ -> :error
end
end
defp same_host?(host) do
URI.parse(Federation.base_url()).host == host
end
defp render_webfinger(conn, handle) do
case Federation.find_local_actor_by_handle(handle) do
nil ->
send_resp(conn, 404, "")
actor ->
body =
%{
"subject" => "acct:#{handle}@#{URI.parse(Federation.base_url()).host}",
"aliases" => [actor.actor_url],
"links" => [
%{
"rel" => "self",
"type" => "application/activity+json",
"href" => actor.actor_url
},
%{
"rel" => "http://webfinger.net/rel/profile-page",
"type" => "text/html",
"href" => actor.actor_url
}
]
}
|> Jason.encode!()
conn
|> put_resp_content_type("application/jrd+json", nil)
|> send_resp(200, body)
end
end
def nodeinfo_index(conn, _params) do
body =
%{
"links" => [
%{
"rel" => "http://nodeinfo.diaspora.software/ns/schema/2.1",
"href" => Federation.base_url() <> "/nodeinfo/2.1"
}
]
}
|> Jason.encode!()
conn
|> put_resp_content_type("application/json", nil)
|> send_resp(200, body)
end
def nodeinfo_2_1(conn, _params) do
body =
%{
"version" => "2.1",
"software" => %{
"name" => "gitgud",
"version" => Application.spec(:git_gud, :vsn) |> to_string(),
"repository" => "https://github.com/anthropics/gitgud"
},
"protocols" => ["activitypub"],
"services" => %{"inbound" => [], "outbound" => []},
"openRegistrations" => false,
"usage" => %{
"users" => %{"total" => 0},
"localPosts" => 0
},
"metadata" => %{
"nodeName" => "GitGud",
"features" => ["forgefed"]
}
}
|> Jason.encode!()
conn
|> put_resp_content_type("application/json", nil)
|> send_resp(200, body)
end
end