Skip to content

Commit

Permalink
Implement basic WebFinger endpoint
Browse files Browse the repository at this point in the history
As prep for ActivityPub!
  • Loading branch information
ku1ik committed Aug 25, 2023
1 parent e947c9e commit 2c6f28a
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/asciinema_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ defmodule AsciinemaWeb do
end
end

def json do
quote do
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end

def verified_routes do
quote do
use Phoenix.VerifiedRoutes,
Expand Down
20 changes: 20 additions & 0 deletions lib/asciinema_web/controllers/webfinger_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule AsciinemaWeb.WebFingerController do
use AsciinemaWeb, :new_controller
alias Asciinema.Accounts

def show(conn, %{"resource" => resource}) do
resource =
resource
|> String.trim()
|> String.downcase()

with "acct:" <> acct <- resource,
[username, domain] <- String.split(acct, "@"),
^domain <- AsciinemaWeb.Endpoint.host(),
{:username, user} when not is_nil(user) <- Accounts.lookup_user(username) do
render(conn, :show, user: user, domain: domain)
else
_ -> {:error, :not_found}
end
end
end
19 changes: 19 additions & 0 deletions lib/asciinema_web/controllers/webfinger_json.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule AsciinemaWeb.WebFingerJSON do
use AsciinemaWeb, :json

def show(%{user: %{username: username}, domain: domain}) do
%{
subject: "acct:#{username}@#{domain}",
aliases: [
url(~p"/~#{username}")
],
links: [
%{
rel: "http://webfinger.net/rel/profile-page",
type: "text/html",
href: url(~p"/~#{username}")
}
]
}
end
end
9 changes: 9 additions & 0 deletions lib/asciinema_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ defmodule AsciinemaWeb.Router do
plug :put_secure_browser_headers
end

pipeline :webfinger do
plug :put_format, :json
end

scope "/", AsciinemaWeb do
pipe_through :asciicast

Expand All @@ -54,6 +58,11 @@ defmodule AsciinemaWeb.Router do
get "/oembed", OembedController, :show
end

scope "/", AsciinemaWeb do
pipe_through :webfinger
get "/.well-known/webfinger", WebFingerController, :show
end

scope "/", AsciinemaWeb do
# Use the default browser stack
pipe_through :browser
Expand Down
48 changes: 48 additions & 0 deletions test/controllers/webfinger_controller_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
defmodule Asciinema.WebFingerControllerTest do
use AsciinemaWeb.ConnCase
import Asciinema.Factory

setup [:create_user]

describe "show" do
test "returns basic info", %{conn: conn} do
conn = get(conn, ~p"/.well-known/webfinger?resource=acct:Pinky@localhost")

assert json_response(conn, 200) == %{
"subject" => "acct:Pinky@localhost",
"aliases" => [
url(~p"/~Pinky")
],
"links" => [
%{
"rel" => "http://webfinger.net/rel/profile-page",
"type" => "text/html",
"href" => url(~p"/~Pinky")
}
]
}
end

test "does case-insensitive acct lookup", %{conn: conn} do
conn = get(conn, ~p"/.well-known/webfinger?resource=acct:pinky@lOcaLhOst")

assert %{"subject" => "acct:Pinky@localhost"} = json_response(conn, 200)
end

test "returns 404 when username not found", %{conn: conn} do
conn = get(conn, ~p"/.well-known/webfinger?resource=acct:nope@localhost")

assert json_response(conn, 404)
end

test "returns 404 when domain doesn't match", %{conn: conn} do
conn = get(conn, ~p"/.well-known/webfinger?resource=acct:[email protected]")

assert json_response(conn, 404)
end
end

defp create_user(_) do
%{user: insert(:user, username: "Pinky")}
end
end

0 comments on commit 2c6f28a

Please sign in to comment.