Extract keys to their own table, match keyID #816

Merged
floatingghost merged 19 commits from keys-extraction into develop 2024-10-30 15:08:12 +00:00
5 changed files with 40 additions and 24 deletions
Showing only changes of commit 58d5d9d7bf - Show all commits

View file

@ -6,7 +6,6 @@ defmodule Pleroma.Signature do
@behaviour HTTPSignatures.Adapter @behaviour HTTPSignatures.Adapter
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.User.SigningKey alias Pleroma.User.SigningKey
require Logger require Logger

View file

@ -4,7 +4,6 @@ defmodule Pleroma.User.SigningKey do
import Ecto.Changeset import Ecto.Changeset
alias Pleroma.User alias Pleroma.User
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.HTTP
require Logger require Logger
@ -136,7 +135,7 @@ def public_key_pem(%User{} = user) do
end end
end end
def public_key_pem(e) do def public_key_pem(_e) do
{:error, "key not found"} {:error, "key not found"}
end end
@ -190,7 +189,7 @@ def fetch_remote_key(key_id) do
resp = Pleroma.Object.Fetcher.fetch_and_contain_remote_object_from_id(key_id) resp = Pleroma.Object.Fetcher.fetch_and_contain_remote_object_from_id(key_id)
case resp do case resp do
{:ok, _original_url, body} -> {:ok, _body} ->
case handle_signature_response(resp) do case handle_signature_response(resp) do
{:ok, ap_id, public_key_pem} -> {:ok, ap_id, public_key_pem} ->
Logger.debug("Fetched remote key: #{ap_id}") Logger.debug("Fetched remote key: #{ap_id}")
@ -227,16 +226,13 @@ defp extract_key_details(%{"id" => ap_id, "publicKey" => public_key}) do
end end
end end
defp handle_signature_response({:ok, _original_url, body}) do defp handle_signature_response({:ok, body}) do
case Jason.decode(body) do case body do
{:ok, %{"id" => _user_id, "publicKey" => _public_key} = body} -> %{"id" => _user_id, "publicKey" => _public_key} ->
extract_key_details(body) extract_key_details(body)
{:ok, %{"error" => error}} -> %{"error" => error} ->
{:error, error} {:error, error}
{:error, _} ->
{:error, "Could not parse key"}
end end
end end

View file

@ -14,7 +14,7 @@ def call(conn, _opts) do
key_id = key_id_from_conn(conn) key_id = key_id_from_conn(conn)
unless is_nil(key_id) do unless is_nil(key_id) do
User.SigningKey.fetch_remote_key(key_id) User.SigningKey.get_or_fetch_by_key_id(key_id)
# now we SHOULD have the user that owns the key locally. maybe. # now we SHOULD have the user that owns the key locally. maybe.
# if we don't, we'll error out when we try to validate. # if we don't, we'll error out when we try to validate.
end end

View file

@ -1094,7 +1094,7 @@ test "it returns a note activity in a collection", %{conn: conn} do
test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do
user = user =
insert(:user) insert(:user, ap_id: data["actor"])
|> with_signing_key() |> with_signing_key()
data = Map.put(data, "bcc", [user.ap_id]) data = Map.put(data, "bcc", [user.ap_id])
@ -1277,12 +1277,22 @@ test "forwarded report from mastodon", %{conn: conn} do
|> File.read!() |> File.read!()
|> String.replace("{{DOMAIN}}", remote_domain) |> String.replace("{{DOMAIN}}", remote_domain)
Tesla.Mock.mock(fn %{url: ^remote_actor} -> key_url = "#{remote_actor}#main-key"
%Tesla.Env{
status: 200, Tesla.Mock.mock(fn
body: mock_json_body, %{url: ^remote_actor} ->
headers: [{"content-type", "application/activity+json"}] %Tesla.Env{
} status: 200,
body: mock_json_body,
headers: [{"content-type", "application/activity+json"}]
}
%{url: ^key_url} ->
%Tesla.Env{
status: 200,
body: mock_json_body,
headers: [{"content-type", "application/activity+json"}]
}
end) end)
data = %{ data = %{

View file

@ -11,7 +11,9 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
test "Renders a user, including the public key" do test "Renders a user, including the public key" do
user = insert(:user) user =
insert(:user)
|> with_signing_key()
result = UserView.render("user.json", %{user: user}) result = UserView.render("user.json", %{user: user})
@ -37,7 +39,9 @@ test "Renders profile fields" do
end end
test "Renders with emoji tags" do test "Renders with emoji tags" do
user = insert(:user, emoji: %{"bib" => "/test"}) user =
insert(:user, emoji: %{"bib" => "/test"})
|> with_signing_key()
assert %{ assert %{
"tag" => [ "tag" => [
@ -74,13 +78,18 @@ test "Does not add an avatar image if the user hasn't set one" do
end end
test "renders an invisible user with the invisible property set to true" do test "renders an invisible user with the invisible property set to true" do
user = insert(:user, invisible: true) user =
insert(:user, invisible: true)
|> with_signing_key()
assert %{"invisible" => true} = UserView.render("service.json", %{user: user}) assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
end end
test "service has a few essential fields" do test "service has a few essential fields" do
user = insert(:user) user =
insert(:user)
|> with_signing_key()
result = UserView.render("service.json", %{user: user}) result = UserView.render("service.json", %{user: user})
assert result["id"] assert result["id"]
assert result["type"] == "Application" assert result["type"] == "Application"
@ -120,7 +129,9 @@ test "remote users have an empty endpoints structure" do
end end
test "instance users do not expose oAuth endpoints" do test "instance users do not expose oAuth endpoints" do
user = insert(:user, nickname: nil, local: true) user =
insert(:user, nickname: nil, local: true)
|> with_signing_key()
result = UserView.render("user.json", %{user: user}) result = UserView.render("user.json", %{user: user})