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