a61f891c7f09a4157b1a0dcf91dc23528435e0c0
[akkoma] / lib / pleroma / web / twitter_api / controllers / util_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.TwitterAPI.UtilController do
6 use Pleroma.Web, :controller
7
8 require Logger
9
10 alias Pleroma.Config
11 alias Pleroma.Emoji
12 alias Pleroma.Healthcheck
13 alias Pleroma.Notification
14 alias Pleroma.Plugs.OAuthScopesPlug
15 alias Pleroma.User
16 alias Pleroma.Web
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.WebFinger
19
20 plug(
21 OAuthScopesPlug,
22 %{scopes: ["follow", "write:follows"]}
23 when action in [:do_remote_follow, :follow_import]
24 )
25
26 plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import)
27
28 plug(
29 OAuthScopesPlug,
30 %{scopes: ["write:accounts"]}
31 when action in [
32 :change_email,
33 :change_password,
34 :delete_account,
35 :update_notificaton_settings,
36 :disable_account
37 ]
38 )
39
40 plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read)
41
42 plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version])
43
44 def help_test(conn, _params) do
45 json(conn, "ok")
46 end
47
48 def remote_subscribe(conn, %{"nickname" => nick, "profile" => _}) do
49 with %User{} = user <- User.get_cached_by_nickname(nick),
50 avatar = User.avatar_url(user) do
51 conn
52 |> render("subscribe.html", %{nickname: nick, avatar: avatar, error: false})
53 else
54 _e ->
55 render(conn, "subscribe.html", %{
56 nickname: nick,
57 avatar: nil,
58 error: "Could not find user"
59 })
60 end
61 end
62
63 def remote_subscribe(conn, %{"user" => %{"nickname" => nick, "profile" => profile}}) do
64 with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile),
65 %User{ap_id: ap_id} <- User.get_cached_by_nickname(nick) do
66 conn
67 |> Phoenix.Controller.redirect(external: String.replace(template, "{uri}", ap_id))
68 else
69 _e ->
70 render(conn, "subscribe.html", %{
71 nickname: nick,
72 avatar: nil,
73 error: "Something went wrong."
74 })
75 end
76 end
77
78 def notifications_read(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
79 with {:ok, _} <- Notification.read_one(user, notification_id) do
80 json(conn, %{status: "success"})
81 else
82 {:error, message} ->
83 conn
84 |> put_resp_content_type("application/json")
85 |> send_resp(403, Jason.encode!(%{"error" => message}))
86 end
87 end
88
89 def config(%{assigns: %{format: "xml"}} = conn, _params) do
90 instance = Pleroma.Config.get(:instance)
91
92 response = """
93 <config>
94 <site>
95 <name>#{Keyword.get(instance, :name)}</name>
96 <site>#{Web.base_url()}</site>
97 <textlimit>#{Keyword.get(instance, :limit)}</textlimit>
98 <closed>#{!Keyword.get(instance, :registrations_open)}</closed>
99 </site>
100 </config>
101 """
102
103 conn
104 |> put_resp_content_type("application/xml")
105 |> send_resp(200, response)
106 end
107
108 def config(conn, _params) do
109 instance = Pleroma.Config.get(:instance)
110
111 vapid_public_key = Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
112
113 uploadlimit = %{
114 uploadlimit: to_string(Keyword.get(instance, :upload_limit)),
115 avatarlimit: to_string(Keyword.get(instance, :avatar_upload_limit)),
116 backgroundlimit: to_string(Keyword.get(instance, :background_upload_limit)),
117 bannerlimit: to_string(Keyword.get(instance, :banner_upload_limit))
118 }
119
120 data = %{
121 name: Keyword.get(instance, :name),
122 description: Keyword.get(instance, :description),
123 server: Web.base_url(),
124 textlimit: to_string(Keyword.get(instance, :limit)),
125 uploadlimit: uploadlimit,
126 closed: bool_to_val(Keyword.get(instance, :registrations_open), "0", "1"),
127 private: bool_to_val(Keyword.get(instance, :public, true), "0", "1"),
128 vapidPublicKey: vapid_public_key,
129 accountActivationRequired:
130 bool_to_val(Keyword.get(instance, :account_activation_required, false)),
131 invitesEnabled: bool_to_val(Keyword.get(instance, :invites_enabled, false)),
132 safeDMMentionsEnabled: bool_to_val(Pleroma.Config.get([:instance, :safe_dm_mentions]))
133 }
134
135 managed_config = Keyword.get(instance, :managed_config)
136
137 data =
138 if managed_config do
139 pleroma_fe = Pleroma.Config.get([:frontend_configurations, :pleroma_fe])
140 Map.put(data, "pleromafe", pleroma_fe)
141 else
142 data
143 end
144
145 json(conn, %{site: data})
146 end
147
148 defp bool_to_val(true), do: "1"
149 defp bool_to_val(_), do: "0"
150 defp bool_to_val(true, val, _), do: val
151 defp bool_to_val(_, _, val), do: val
152
153 def frontend_configurations(conn, _params) do
154 config =
155 Pleroma.Config.get(:frontend_configurations, %{})
156 |> Enum.into(%{})
157
158 json(conn, config)
159 end
160
161 def version(%{assigns: %{format: "xml"}} = conn, _params) do
162 version = Pleroma.Application.named_version()
163
164 conn
165 |> put_resp_content_type("application/xml")
166 |> send_resp(200, "<version>#{version}</version>")
167 end
168
169 def version(conn, _params) do
170 json(conn, Pleroma.Application.named_version())
171 end
172
173 def emoji(conn, _params) do
174 emoji =
175 Enum.reduce(Emoji.get_all(), %{}, fn {code, %Emoji{file: file, tags: tags}}, acc ->
176 Map.put(acc, code, %{image_url: file, tags: tags})
177 end)
178
179 json(conn, emoji)
180 end
181
182 def update_notificaton_settings(%{assigns: %{user: user}} = conn, params) do
183 with {:ok, _} <- User.update_notification_settings(user, params) do
184 json(conn, %{status: "success"})
185 end
186 end
187
188 def follow_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
189 follow_import(conn, %{"list" => File.read!(listfile.path)})
190 end
191
192 def follow_import(%{assigns: %{user: follower}} = conn, %{"list" => list}) do
193 with lines <- String.split(list, "\n"),
194 followed_identifiers <-
195 Enum.map(lines, fn line ->
196 String.split(line, ",") |> List.first()
197 end)
198 |> List.delete("Account address") do
199 User.follow_import(follower, followed_identifiers)
200 json(conn, "job started")
201 end
202 end
203
204 def blocks_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
205 blocks_import(conn, %{"list" => File.read!(listfile.path)})
206 end
207
208 def blocks_import(%{assigns: %{user: blocker}} = conn, %{"list" => list}) do
209 with blocked_identifiers <- String.split(list) do
210 User.blocks_import(blocker, blocked_identifiers)
211 json(conn, "job started")
212 end
213 end
214
215 def change_password(%{assigns: %{user: user}} = conn, params) do
216 case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
217 {:ok, user} ->
218 with {:ok, _user} <-
219 User.reset_password(user, %{
220 password: params["new_password"],
221 password_confirmation: params["new_password_confirmation"]
222 }) do
223 json(conn, %{status: "success"})
224 else
225 {:error, changeset} ->
226 {_, {error, _}} = Enum.at(changeset.errors, 0)
227 json(conn, %{error: "New password #{error}."})
228
229 _ ->
230 json(conn, %{error: "Unable to change password."})
231 end
232
233 {:error, msg} ->
234 json(conn, %{error: msg})
235 end
236 end
237
238 def change_email(%{assigns: %{user: user}} = conn, params) do
239 case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
240 {:ok, user} ->
241 with {:ok, _user} <- User.change_email(user, params["email"]) do
242 json(conn, %{status: "success"})
243 else
244 {:error, changeset} ->
245 {_, {error, _}} = Enum.at(changeset.errors, 0)
246 json(conn, %{error: "Email #{error}."})
247
248 _ ->
249 json(conn, %{error: "Unable to change email."})
250 end
251
252 {:error, msg} ->
253 json(conn, %{error: msg})
254 end
255 end
256
257 def delete_account(%{assigns: %{user: user}} = conn, params) do
258 case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
259 {:ok, user} ->
260 User.delete(user)
261 json(conn, %{status: "success"})
262
263 {:error, msg} ->
264 json(conn, %{error: msg})
265 end
266 end
267
268 def disable_account(%{assigns: %{user: user}} = conn, params) do
269 case CommonAPI.Utils.confirm_current_password(user, params["password"]) do
270 {:ok, user} ->
271 User.deactivate_async(user)
272 json(conn, %{status: "success"})
273
274 {:error, msg} ->
275 json(conn, %{error: msg})
276 end
277 end
278
279 def captcha(conn, _params) do
280 json(conn, Pleroma.Captcha.new())
281 end
282
283 def healthcheck(conn, _params) do
284 with true <- Config.get([:instance, :healthcheck]),
285 %{healthy: true} = info <- Healthcheck.system_info() do
286 json(conn, info)
287 else
288 %{healthy: false} = info ->
289 service_unavailable(conn, info)
290
291 _ ->
292 service_unavailable(conn, %{})
293 end
294 end
295
296 defp service_unavailable(conn, info) do
297 conn
298 |> put_status(:service_unavailable)
299 |> json(info)
300 end
301 end