Merge branch 'feature/1710-consolidate-instance-info' into 'develop'
[akkoma] / lib / pleroma / web / pleroma_api / controllers / account_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.PleromaAPI.AccountController do
6 use Pleroma.Web, :controller
7
8 import Pleroma.Web.ControllerHelper,
9 only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2, skip_relationships?: 1]
10
11 alias Ecto.Changeset
12 alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
13 alias Pleroma.Plugs.OAuthScopesPlug
14 alias Pleroma.Plugs.RateLimiter
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.MastodonAPI.StatusView
18
19 require Pleroma.Constants
20
21 plug(
22 :skip_plug,
23 [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirmation_resend
24 )
25
26 plug(
27 OAuthScopesPlug,
28 %{scopes: ["follow", "write:follows"]} when action in [:subscribe, :unsubscribe]
29 )
30
31 plug(
32 OAuthScopesPlug,
33 %{scopes: ["write:accounts"]}
34 # Note: the following actions are not permission-secured in Mastodon:
35 when action in [
36 :update_avatar,
37 :update_banner,
38 :update_background
39 ]
40 )
41
42 plug(
43 OAuthScopesPlug,
44 %{scopes: ["read:favourites"], fallback: :proceed_unauthenticated} when action == :favourites
45 )
46
47 plug(RateLimiter, [name: :account_confirmation_resend] when action == :confirmation_resend)
48
49 plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
50 plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
51
52 @doc "POST /api/v1/pleroma/accounts/confirmation_resend"
53 def confirmation_resend(conn, params) do
54 nickname_or_email = params["email"] || params["nickname"]
55
56 with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
57 {:ok, _} <- User.try_send_confirmation_email(user) do
58 json_response(conn, :no_content, "")
59 end
60 end
61
62 @doc "PATCH /api/v1/pleroma/accounts/update_avatar"
63 def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
64 {:ok, _user} =
65 user
66 |> Changeset.change(%{avatar: nil})
67 |> User.update_and_set_cache()
68
69 json(conn, %{url: nil})
70 end
71
72 def update_avatar(%{assigns: %{user: user}} = conn, params) do
73 {:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar)
74 {:ok, _user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache()
75 %{"url" => [%{"href" => href} | _]} = data
76
77 json(conn, %{url: href})
78 end
79
80 @doc "PATCH /api/v1/pleroma/accounts/update_banner"
81 def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
82 with {:ok, _user} <- User.update_banner(user, %{}) do
83 json(conn, %{url: nil})
84 end
85 end
86
87 def update_banner(%{assigns: %{user: user}} = conn, params) do
88 with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner),
89 {:ok, _user} <- User.update_banner(user, object.data) do
90 %{"url" => [%{"href" => href} | _]} = object.data
91
92 json(conn, %{url: href})
93 end
94 end
95
96 @doc "PATCH /api/v1/pleroma/accounts/update_background"
97 def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
98 with {:ok, _user} <- User.update_background(user, %{}) do
99 json(conn, %{url: nil})
100 end
101 end
102
103 def update_background(%{assigns: %{user: user}} = conn, params) do
104 with {:ok, object} <- ActivityPub.upload(params, type: :background),
105 {:ok, _user} <- User.update_background(user, object.data) do
106 %{"url" => [%{"href" => href} | _]} = object.data
107
108 json(conn, %{url: href})
109 end
110 end
111
112 @doc "GET /api/v1/pleroma/accounts/:id/favourites"
113 def favourites(%{assigns: %{account: %{hide_favorites: true}}} = conn, _params) do
114 render_error(conn, :forbidden, "Can't get favorites")
115 end
116
117 def favourites(%{assigns: %{user: for_user, account: user}} = conn, params) do
118 params =
119 params
120 |> Map.put("type", "Create")
121 |> Map.put("favorited_by", user.ap_id)
122 |> Map.put("blocking_user", for_user)
123
124 recipients =
125 if for_user do
126 [Pleroma.Constants.as_public()] ++ [for_user.ap_id | User.following(for_user)]
127 else
128 [Pleroma.Constants.as_public()]
129 end
130
131 activities =
132 recipients
133 |> ActivityPub.fetch_activities(params)
134 |> Enum.reverse()
135
136 conn
137 |> add_link_headers(activities)
138 |> put_view(StatusView)
139 |> render("index.json",
140 activities: activities,
141 for: for_user,
142 as: :activity,
143 skip_relationships: skip_relationships?(params)
144 )
145 end
146
147 @doc "POST /api/v1/pleroma/accounts/:id/subscribe"
148 def subscribe(%{assigns: %{user: user, account: subscription_target}} = conn, _params) do
149 with {:ok, _subscription} <- User.subscribe(user, subscription_target) do
150 render(conn, "relationship.json", user: user, target: subscription_target)
151 else
152 {:error, message} -> json_response(conn, :forbidden, %{error: message})
153 end
154 end
155
156 @doc "POST /api/v1/pleroma/accounts/:id/unsubscribe"
157 def unsubscribe(%{assigns: %{user: user, account: subscription_target}} = conn, _params) do
158 with {:ok, _subscription} <- User.unsubscribe(user, subscription_target) do
159 render(conn, "relationship.json", user: user, target: subscription_target)
160 else
161 {:error, message} -> json_response(conn, :forbidden, %{error: message})
162 end
163 end
164 end