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