update adminfe
[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]
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 OpenApiSpex.Plug.PutApiSpec,
23 [module: Pleroma.Web.ApiSpec] when action == :confirmation_resend
24 )
25
26 plug(Pleroma.Web.ApiSpec.CastAndValidate)
27
28 plug(
29 :skip_plug,
30 [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirmation_resend
31 )
32
33 plug(
34 OAuthScopesPlug,
35 %{scopes: ["follow", "write:follows"]} when action in [:subscribe, :unsubscribe]
36 )
37
38 plug(
39 OAuthScopesPlug,
40 %{scopes: ["write:accounts"]}
41 # Note: the following actions are not permission-secured in Mastodon:
42 when action in [
43 :update_avatar,
44 :update_banner,
45 :update_background
46 ]
47 )
48
49 plug(
50 OAuthScopesPlug,
51 %{scopes: ["read:favourites"], fallback: :proceed_unauthenticated} when action == :favourites
52 )
53
54 plug(RateLimiter, [name: :account_confirmation_resend] when action == :confirmation_resend)
55
56 plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
57 plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
58
59 defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation
60
61 @doc "POST /api/v1/pleroma/accounts/confirmation_resend"
62 def confirmation_resend(conn, params) do
63 nickname_or_email = params[:email] || params[:nickname]
64
65 with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
66 {:ok, _} <- User.try_send_confirmation_email(user) do
67 json_response(conn, :no_content, "")
68 end
69 end
70
71 @doc "PATCH /api/v1/pleroma/accounts/update_avatar"
72 def update_avatar(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do
73 {:ok, _user} =
74 user
75 |> Changeset.change(%{avatar: nil})
76 |> User.update_and_set_cache()
77
78 json(conn, %{url: nil})
79 end
80
81 def update_avatar(%{assigns: %{user: user}, body_params: params} = conn, _params) do
82 {:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar)
83 {:ok, _user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache()
84 %{"url" => [%{"href" => href} | _]} = data
85
86 json(conn, %{url: href})
87 end
88
89 @doc "PATCH /api/v1/pleroma/accounts/update_banner"
90 def update_banner(%{assigns: %{user: user}, body_params: %{banner: ""}} = conn, _) do
91 with {:ok, _user} <- User.update_banner(user, %{}) do
92 json(conn, %{url: nil})
93 end
94 end
95
96 def update_banner(%{assigns: %{user: user}, body_params: params} = conn, _) do
97 with {:ok, object} <- ActivityPub.upload(%{img: params[:banner]}, type: :banner),
98 {:ok, _user} <- User.update_banner(user, object.data) do
99 %{"url" => [%{"href" => href} | _]} = object.data
100
101 json(conn, %{url: href})
102 end
103 end
104
105 @doc "PATCH /api/v1/pleroma/accounts/update_background"
106 def update_background(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do
107 with {:ok, _user} <- User.update_background(user, %{}) do
108 json(conn, %{url: nil})
109 end
110 end
111
112 def update_background(%{assigns: %{user: user}, body_params: params} = conn, _) do
113 with {:ok, object} <- ActivityPub.upload(params, type: :background),
114 {:ok, _user} <- User.update_background(user, object.data) do
115 %{"url" => [%{"href" => href} | _]} = object.data
116
117 json(conn, %{url: href})
118 end
119 end
120
121 @doc "GET /api/v1/pleroma/accounts/:id/favourites"
122 def favourites(%{assigns: %{account: %{hide_favorites: true}}} = conn, _params) do
123 render_error(conn, :forbidden, "Can't get favorites")
124 end
125
126 def favourites(%{assigns: %{user: for_user, account: user}} = conn, params) do
127 params =
128 params
129 |> Map.put(:type, "Create")
130 |> Map.put(:favorited_by, user.ap_id)
131 |> Map.put(:blocking_user, for_user)
132
133 recipients =
134 if for_user do
135 [Pleroma.Constants.as_public()] ++ [for_user.ap_id | User.following(for_user)]
136 else
137 [Pleroma.Constants.as_public()]
138 end
139
140 activities =
141 recipients
142 |> ActivityPub.fetch_activities(params)
143 |> Enum.reverse()
144
145 conn
146 |> add_link_headers(activities)
147 |> put_view(StatusView)
148 |> render("index.json",
149 activities: activities,
150 for: for_user,
151 as: :activity
152 )
153 end
154
155 @doc "POST /api/v1/pleroma/accounts/:id/subscribe"
156 def subscribe(%{assigns: %{user: user, account: subscription_target}} = conn, _params) do
157 with {:ok, _subscription} <- User.subscribe(user, subscription_target) do
158 render(conn, "relationship.json", user: user, target: subscription_target)
159 else
160 {:error, message} -> json_response(conn, :forbidden, %{error: message})
161 end
162 end
163
164 @doc "POST /api/v1/pleroma/accounts/:id/unsubscribe"
165 def unsubscribe(%{assigns: %{user: user, account: subscription_target}} = conn, _params) do
166 with {:ok, _subscription} <- User.unsubscribe(user, subscription_target) do
167 render(conn, "relationship.json", user: user, target: subscription_target)
168 else
169 {:error, message} -> json_response(conn, :forbidden, %{error: message})
170 end
171 end
172 end