aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma')
-rw-r--r--lib/pleroma/user.ex15
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex31
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex57
-rw-r--r--lib/pleroma/web/router.ex1
4 files changed, 81 insertions, 23 deletions
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 09ea80793..8115fb0fa 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1770,7 +1770,7 @@ defmodule Pleroma.User do
def fetch_by_ap_id(ap_id, opts \\ []), do: ActivityPub.make_user_from_ap_id(ap_id, opts)
- def get_or_fetch_by_ap_id(ap_id, opts \\ []) do
+ def get_or_fetch_by_ap_id(ap_id, opts \\ []) when is_binary(ap_id) do
cached_user = get_cached_by_ap_id(ap_id)
maybe_fetched_user = needs_update?(cached_user) && fetch_by_ap_id(ap_id, opts)
@@ -1787,6 +1787,13 @@ defmodule Pleroma.User do
end
end
+ def get_or_fetch_by_ap_id!(ap_id, opts \\ []) when is_binary(ap_id) do
+ case get_or_fetch_by_ap_id(ap_id, opts) do
+ {:ok, user} -> user
+ _ -> nil
+ end
+ end
+
@doc """
Creates an internal service actor by URI if missing.
Optionally takes nickname for addressing.
@@ -2097,9 +2104,9 @@ defmodule Pleroma.User do
}
end
- def ensure_keys_present(%{keys: keys} = user) when not is_nil(keys), do: {:ok, user}
+ def ensure_keys_present(%User{keys: keys} = user) when not is_nil(keys), do: {:ok, user}
- def ensure_keys_present(%User{} = user) do
+ def ensure_keys_present(%User{local: true} = user) do
with {:ok, pem} <- Keys.generate_rsa_pem() do
user
|> cast(%{keys: pem}, [:keys])
@@ -2108,6 +2115,8 @@ defmodule Pleroma.User do
end
end
+ def ensure_keys_present(%User{local: false}), do: {:error, :none}
+
def get_ap_ids_by_nicknames(nicknames) do
from(u in User,
where: u.nickname in ^nicknames,
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 732c44271..07692221a 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -42,7 +42,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
# Note: :following and :followers must be served even without authentication (as via :api)
plug(
EnsureAuthenticatedPlug
- when action in [:read_inbox, :update_outbox, :whoami, :upload_media]
+ when action in [:read_inbox, :update_outbox, :whoami, :upload_media, :proxy_url]
)
plug(
@@ -550,4 +550,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> json(object.data)
end
end
+
+ def proxy_url(%{assigns: %{user: %User{}}} = conn, %{"id" => id}) when is_binary(id) do
+ cond do
+ object = Object.normalize(id, true) ->
+ conn
+ |> maybe_set_tracking_data(object)
+ |> set_cache_ttl_for(object)
+ |> put_resp_content_type("application/activity+json")
+ |> put_view(ObjectView)
+ |> render("object.json", object: object)
+
+ object = Activity.get_by_ap_id_with_object(id) ->
+ conn
+ |> maybe_set_tracking_data(object)
+ |> set_cache_ttl_for(object)
+ |> put_resp_content_type("application/activity+json")
+ |> put_view(ObjectView)
+ |> render("object.json", object: object)
+
+ user = User.get_or_fetch_by_ap_id!(id) ->
+ conn
+ |> put_resp_content_type("application/activity+json")
+ |> put_view(UserView)
+ |> render("user.json", %{user: user})
+
+ true ->
+ {:error, :not_found}
+ end
+ end
end
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 3a4564912..715dc4c62 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
use Pleroma.Web, :view
alias Pleroma.Keys
+ alias Pleroma.Maps
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Transmogrifier
@@ -15,21 +16,27 @@ defmodule Pleroma.Web.ActivityPub.UserView do
import Ecto.Query
- def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do
+ def render("endpoints.json", %{user: %User{nickname: nil, local: true}}) do
%{"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox)}
end
- def render("endpoints.json", %{user: %User{local: true} = _user}) do
+ def render("endpoints.json", %{user: %User{local: true}}) do
%{
"oauthAuthorizationEndpoint" => Helpers.o_auth_url(Endpoint, :authorize),
"oauthRegistrationEndpoint" => Helpers.app_url(Endpoint, :create),
"oauthTokenEndpoint" => Helpers.o_auth_url(Endpoint, :token_exchange),
"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox),
- "uploadMedia" => Helpers.activity_pub_url(Endpoint, :upload_media)
+ "uploadMedia" => Helpers.activity_pub_url(Endpoint, :upload_media),
+ "proxyUrl" => Helpers.activity_pub_url(Endpoint, :proxy_url)
}
end
- def render("endpoints.json", _), do: %{}
+ def render("endpoints.json", %{user: %User{shared_inbox: shared_inbox}})
+ when is_binary(shared_inbox) do
+ %{"sharedInbox" => shared_inbox}
+ end
+
+ def render("endpoints.json", _), do: nil
def render("service.json", %{user: user}) do
{:ok, user} = User.ensure_keys_present(user)
@@ -59,6 +66,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"invisible" => User.invisible?(user)
}
|> Map.merge(Utils.make_json_ld_header())
+ |> Maps.put_if_present("endpoints", endpoints)
end
# the instance itself is not a Person, but instead an Application
@@ -68,11 +76,22 @@ defmodule Pleroma.Web.ActivityPub.UserView do
def render("user.json", %{user: %User{nickname: "internal." <> _} = user}),
do: render("service.json", %{user: user}) |> Map.put("preferredUsername", user.nickname)
- def render("user.json", %{user: user}) do
- {:ok, user} = User.ensure_keys_present(user)
- {:ok, _, public_key} = Keys.keys_from_pem(user.keys)
- public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
- public_key = :public_key.pem_encode([public_key])
+ def render("user.json", %{user: %User{} = user}) do
+ public_key =
+ with {:ok, user} <- User.ensure_keys_present(user) do
+ {:ok, _, public_key} = Keys.keys_from_pem(user.keys)
+ public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
+ public_key = :public_key.pem_encode([public_key])
+
+ %{
+ "id" => "#{user.ap_id}#main-key",
+ "owner" => user.ap_id,
+ "publicKeyPem" => public_key
+ }
+ else
+ _ -> nil
+ end
+
user = User.sanitize_html(user)
endpoints = render("endpoints.json", %{user: user})
@@ -90,24 +109,22 @@ defmodule Pleroma.Web.ActivityPub.UserView do
%{}
end
+ # FIXME: user.outbox
+ inbox = if user.local, do: "#{user.ap_id}/inbox", else: user.inbox
+ outbox = if user.local, do: "#{user.ap_id}/outbox", else: nil
+
%{
"id" => user.ap_id,
"type" => user.actor_type,
- "following" => "#{user.ap_id}/following",
- "followers" => "#{user.ap_id}/followers",
- "inbox" => "#{user.ap_id}/inbox",
- "outbox" => "#{user.ap_id}/outbox",
+ "following" => User.ap_following(user),
+ "followers" => User.ap_followers(user),
+ "inbox" => inbox,
+ "outbox" => outbox,
"preferredUsername" => user.nickname,
"name" => user.name,
"summary" => user.bio,
"url" => user.ap_id,
"manuallyApprovesFollowers" => user.locked,
- "publicKey" => %{
- "id" => "#{user.ap_id}#main-key",
- "owner" => user.ap_id,
- "publicKeyPem" => public_key
- },
- "endpoints" => endpoints,
"attachment" => fields,
"tag" => emoji_tags,
"discoverable" => user.discoverable,
@@ -116,6 +133,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
|> Map.merge(Utils.make_json_ld_header())
+ |> Maps.put_if_present("endpoints", endpoints)
+ |> Maps.put_if_present("publicKey", public_key)
end
def render("following.json", %{user: user, page: page} = opts) do
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index e22b31b4c..2a435c38c 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -625,6 +625,7 @@ defmodule Pleroma.Web.Router do
get("/users/:nickname/outbox", ActivityPubController, :outbox)
post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
post("/api/ap/upload_media", ActivityPubController, :upload_media)
+ post("/api/ap/proxy_url", ActivityPubController, :proxy_url)
# The following two are S2S as well, see `ActivityPub.fetch_follow_information_for_user/1`:
get("/users/:nickname/followers", ActivityPubController, :followers)