47937beef430a6437dc782394c1b86762fd0be25
[akkoma] / lib / pleroma / web / activity_pub / activity_pub_controller.ex
1 defmodule Pleroma.Web.ActivityPub.ActivityPubController do
2 use Pleroma.Web, :controller
3 alias Pleroma.{User, Object}
4 alias Pleroma.Web.ActivityPub.{ObjectView, UserView}
5 alias Pleroma.Web.ActivityPub.ActivityPub
6 alias Pleroma.Web.ActivityPub.Relay
7 alias Pleroma.Web.ActivityPub.Utils
8 alias Pleroma.Web.Federator
9
10 require Logger
11
12 action_fallback(:errors)
13
14 plug(:relay_active? when action in [:relay])
15
16 def relay_active?(conn, _) do
17 if Keyword.get(Application.get_env(:pleroma, :instance), :allow_relay) do
18 conn
19 else
20 conn
21 |> put_status(404)
22 |> json(%{error: "not found"})
23 |> halt
24 end
25 end
26
27 def user(conn, %{"nickname" => nickname}) do
28 with %User{} = user <- User.get_cached_by_nickname(nickname),
29 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
30 conn
31 |> put_resp_header("content-type", "application/activity+json")
32 |> json(UserView.render("user.json", %{user: user}))
33 else
34 nil -> {:error, :not_found}
35 end
36 end
37
38 def object(conn, %{"uuid" => uuid}) do
39 with ap_id <- o_status_url(conn, :object, uuid),
40 %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
41 {_, true} <- {:public?, ActivityPub.is_public?(object)} do
42 conn
43 |> put_resp_header("content-type", "application/activity+json")
44 |> json(ObjectView.render("object.json", %{object: object}))
45 else
46 {:public?, false} ->
47 {:error, :not_found}
48 end
49 end
50
51 def following(conn, %{"nickname" => nickname, "page" => page}) do
52 with %User{} = user <- User.get_cached_by_nickname(nickname),
53 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
54 {page, _} = Integer.parse(page)
55
56 conn
57 |> put_resp_header("content-type", "application/activity+json")
58 |> json(UserView.render("following.json", %{user: user, page: page}))
59 end
60 end
61
62 def following(conn, %{"nickname" => nickname}) do
63 with %User{} = user <- User.get_cached_by_nickname(nickname),
64 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
65 conn
66 |> put_resp_header("content-type", "application/activity+json")
67 |> json(UserView.render("following.json", %{user: user}))
68 end
69 end
70
71 def followers(conn, %{"nickname" => nickname, "page" => page}) do
72 with %User{} = user <- User.get_cached_by_nickname(nickname),
73 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
74 {page, _} = Integer.parse(page)
75
76 conn
77 |> put_resp_header("content-type", "application/activity+json")
78 |> json(UserView.render("followers.json", %{user: user, page: page}))
79 end
80 end
81
82 def followers(conn, %{"nickname" => nickname}) do
83 with %User{} = user <- User.get_cached_by_nickname(nickname),
84 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
85 conn
86 |> put_resp_header("content-type", "application/activity+json")
87 |> json(UserView.render("followers.json", %{user: user}))
88 end
89 end
90
91 def outbox(conn, %{"nickname" => nickname, "max_id" => max_id}) do
92 with %User{} = user <- User.get_cached_by_nickname(nickname),
93 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
94 conn
95 |> put_resp_header("content-type", "application/activity+json")
96 |> json(UserView.render("outbox.json", %{user: user, max_id: max_id}))
97 end
98 end
99
100 def outbox(conn, %{"nickname" => nickname}) do
101 outbox(conn, %{"nickname" => nickname, "max_id" => nil})
102 end
103
104 def inbox(%{assigns: %{valid_signature: true}} = conn, %{"nickname" => nickname} = params) do
105 with %User{} = user <- User.get_cached_by_nickname(nickname),
106 true <- Utils.recipient_in_message(user.ap_id, params),
107 params <- Utils.maybe_splice_recipient(user.ap_id, params) do
108 Federator.enqueue(:incoming_ap_doc, params)
109 json(conn, "ok")
110 end
111 end
112
113 def inbox(%{assigns: %{valid_signature: true}} = conn, params) do
114 Federator.enqueue(:incoming_ap_doc, params)
115 json(conn, "ok")
116 end
117
118 # only accept relayed Creates
119 def inbox(conn, %{"type" => "Create"} = params) do
120 Logger.info(
121 "Signature missing or not from author, relayed Create message, fetching object from source"
122 )
123
124 ActivityPub.fetch_object_from_id(params["object"]["id"])
125
126 json(conn, "ok")
127 end
128
129 def inbox(conn, params) do
130 headers = Enum.into(conn.req_headers, %{})
131
132 if String.contains?(headers["signature"], params["actor"]) do
133 Logger.info(
134 "Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
135 )
136
137 Logger.info(inspect(conn.req_headers))
138 end
139
140 json(conn, "error")
141 end
142
143 def relay(conn, params) do
144 with %User{} = user <- Relay.get_actor(),
145 {:ok, user} <- Pleroma.Web.WebFinger.ensure_keys_present(user) do
146 conn
147 |> put_resp_header("content-type", "application/activity+json")
148 |> json(UserView.render("user.json", %{user: user}))
149 else
150 nil -> {:error, :not_found}
151 end
152 end
153
154 def errors(conn, {:error, :not_found}) do
155 conn
156 |> put_status(404)
157 |> json("Not found")
158 end
159
160 def errors(conn, _e) do
161 conn
162 |> put_status(500)
163 |> json("error")
164 end
165 end