admin_api_controller.ex 8.57 KB
Newer Older
1
# Pleroma: A lightweight social networking server
kaniini's avatar
kaniini committed
2
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3
4
# SPDX-License-Identifier: AGPL-3.0-only

5
defmodule Pleroma.Web.AdminAPI.AdminAPIController do
Haelwenn's avatar
Haelwenn committed
6
  use Pleroma.Web, :controller
7
  alias Pleroma.User
Alexander Strizhakov's avatar
Alexander Strizhakov committed
8
  alias Pleroma.UserInviteToken
9
  alias Pleroma.Web.ActivityPub.Relay
10
  alias Pleroma.Web.AdminAPI.AccountView
11
  alias Pleroma.Web.AdminAPI.Search
12

13
14
  import Pleroma.Web.ControllerHelper, only: [json_response: 3]

Haelwenn's avatar
Haelwenn committed
15
16
  require Logger

17
18
  @users_page_size 50

Haelwenn's avatar
Haelwenn committed
19
20
  action_fallback(:errors)

21
  def user_delete(conn, %{"nickname" => nickname}) do
minibikini's avatar
minibikini committed
22
    User.get_cached_by_nickname(nickname)
23
    |> User.delete()
24
25

    conn
26
    |> json(nickname)
Haelwenn's avatar
Haelwenn committed
27
28
  end

29
  def user_follow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do
minibikini's avatar
minibikini committed
30
31
    with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
         %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
32
33
34
35
36
37
38
39
      User.follow(follower, followed)
    end

    conn
    |> json("ok")
  end

  def user_unfollow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do
minibikini's avatar
minibikini committed
40
41
    with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
         %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
42
43
44
45
46
47
48
      User.unfollow(follower, followed)
    end

    conn
    |> json("ok")
  end

49
50
51
52
  def user_create(
        conn,
        %{"nickname" => nickname, "email" => email, "password" => password}
      ) do
53
    user_data = %{
54
      nickname: nickname,
55
      name: nickname,
56
57
58
      email: email,
      password: password,
      password_confirmation: password,
59
      bio: "."
60
61
    }

62
63
    changeset = User.register_changeset(%User{}, user_data, confirmed: true)
    {:ok, user} = User.register(changeset)
64
65

    conn
66
    |> json(user.nickname)
67
68
  end

69
  def user_show(conn, %{"nickname" => nickname}) do
minibikini's avatar
minibikini committed
70
    with %User{} = user <- User.get_cached_by_nickname(nickname) do
71
72
73
74
75
76
77
      conn
      |> json(AccountView.render("show.json", %{user: user}))
    else
      _ -> {:error, :not_found}
    end
  end

Maxim Filippov's avatar
Maxim Filippov committed
78
  def user_toggle_activation(conn, %{"nickname" => nickname}) do
minibikini's avatar
minibikini committed
79
    user = User.get_cached_by_nickname(nickname)
Maxim Filippov's avatar
Maxim Filippov committed
80
81
82
83

    {:ok, updated_user} = User.deactivate(user, !user.info.deactivated)

    conn
84
    |> json(AccountView.render("show.json", %{user: updated_user}))
Maxim Filippov's avatar
Maxim Filippov committed
85
86
  end

87
88
89
90
91
92
93
94
95
96
  def tag_users(conn, %{"nicknames" => nicknames, "tags" => tags}) do
    with {:ok, _} <- User.tag(nicknames, tags),
         do: json_response(conn, :no_content, "")
  end

  def untag_users(conn, %{"nicknames" => nicknames, "tags" => tags}) do
    with {:ok, _} <- User.untag(nicknames, tags),
         do: json_response(conn, :no_content, "")
  end

97
  def list_users(conn, params) do
Maxim Filippov's avatar
Maxim Filippov committed
98
    {page, page_size} = page_params(params)
99
100
101
102
103
104
105
    filters = maybe_parse_filters(params["filters"])

    search_params = %{
      query: params["query"],
      page: page,
      page_size: page_size
    }
Maxim Filippov's avatar
Maxim Filippov committed
106

107
    with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
Maxim Filippov's avatar
Maxim Filippov committed
108
109
110
111
112
113
114
115
116
         do:
           conn
           |> json(
             AccountView.render("index.json",
               users: users,
               count: count,
               page_size: page_size
             )
           )
Maxim Filippov's avatar
Maxim Filippov committed
117
118
  end

119
120
121
122
123
124
125
126
127
128
129
130
131
  @filters ~w(local external active deactivated)

  defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}

  @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
  defp maybe_parse_filters(filters) do
    filters
    |> String.split(",")
    |> Enum.filter(&Enum.member?(@filters, &1))
    |> Enum.map(&String.to_atom(&1))
    |> Enum.into(%{}, &{&1, true})
  end

132
133
  def right_add(conn, %{"permission_group" => permission_group, "nickname" => nickname})
      when permission_group in ["moderator", "admin"] do
minibikini's avatar
minibikini committed
134
    user = User.get_cached_by_nickname(nickname)
135
136

    info =
lain's avatar
lain committed
137
      %{}
138
      |> Map.put("is_" <> permission_group, true)
139

lain's avatar
lain committed
140
141
142
    info_cng = User.Info.admin_api_update(user.info, info)

    cng =
Maksim's avatar
updates    
Maksim committed
143
144
      user
      |> Ecto.Changeset.change()
lain's avatar
lain committed
145
146
      |> Ecto.Changeset.put_embed(:info, info_cng)

Maksim's avatar
Maksim committed
147
    {:ok, _user} = User.update_and_set_cache(cng)
148

Maksim's avatar
Maksim committed
149
150
151
152
    json(conn, info)
  end

  def right_add(conn, _) do
153
    conn
Maksim's avatar
Maksim committed
154
155
    |> put_status(404)
    |> json(%{error: "No such permission_group"})
156
157
  end

158
  def right_get(conn, %{"nickname" => nickname}) do
minibikini's avatar
minibikini committed
159
    user = User.get_cached_by_nickname(nickname)
160
161

    conn
lain's avatar
lain committed
162
163
164
165
    |> json(%{
      is_moderator: user.info.is_moderator,
      is_admin: user.info.is_admin
    })
166
167
  end

168
169
170
  def right_delete(
        %{assigns: %{user: %User{:nickname => admin_nickname}}} = conn,
        %{
171
          "permission_group" => permission_group,
172
173
174
          "nickname" => nickname
        }
      )
175
      when permission_group in ["moderator", "admin"] do
176
177
    if admin_nickname == nickname do
      conn
178
      |> put_status(403)
179
180
      |> json(%{error: "You can't revoke your own admin status."})
    else
minibikini's avatar
minibikini committed
181
      user = User.get_cached_by_nickname(nickname)
182

183
      info =
lain's avatar
lain committed
184
        %{}
185
        |> Map.put("is_" <> permission_group, false)
186

lain's avatar
lain committed
187
188
189
190
191
192
      info_cng = User.Info.admin_api_update(user.info, info)

      cng =
        Ecto.Changeset.change(user)
        |> Ecto.Changeset.put_embed(:info, info_cng)

Maksim's avatar
Maksim committed
193
      {:ok, _user} = User.update_and_set_cache(cng)
194

Maksim's avatar
Maksim committed
195
      json(conn, info)
196
    end
197
198
199
200
201
  end

  def right_delete(conn, _) do
    conn
    |> put_status(404)
202
    |> json(%{error: "No such permission_group"})
Haelwenn's avatar
Haelwenn committed
203
204
  end

205
206
  def set_activation_status(conn, %{"nickname" => nickname, "status" => status}) do
    with {:ok, status} <- Ecto.Type.cast(:boolean, status),
minibikini's avatar
minibikini committed
207
         %User{} = user <- User.get_cached_by_nickname(nickname),
208
209
210
211
         {:ok, _} <- User.deactivate(user, !status),
         do: json_response(conn, :no_content, "")
  end

212
  def relay_follow(conn, %{"relay_url" => target}) do
Maksim's avatar
Maksim committed
213
214
    with {:ok, _message} <- Relay.follow(target) do
      json(conn, target)
215
    else
Maksim's avatar
Maksim committed
216
217
218
219
      _ ->
        conn
        |> put_status(500)
        |> json(target)
220
    end
Haelwenn's avatar
Haelwenn committed
221
222
  end

223
  def relay_unfollow(conn, %{"relay_url" => target}) do
Maksim's avatar
Maksim committed
224
225
    with {:ok, _message} <- Relay.unfollow(target) do
      json(conn, target)
226
    else
Maksim's avatar
Maksim committed
227
228
229
230
      _ ->
        conn
        |> put_status(500)
        |> json(target)
231
    end
Haelwenn's avatar
Haelwenn committed
232
233
  end

234
235
236
237
238
  @doc "Sends registration invite via email"
  def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
    with true <-
           Pleroma.Config.get([:instance, :invites_enabled]) &&
             !Pleroma.Config.get([:instance, :registrations_open]),
239
         {:ok, invite_token} <- UserInviteToken.create_invite(),
240
         email <-
241
242
243
244
245
246
           Pleroma.Emails.UserEmail.user_invitation_email(
             user,
             invite_token,
             email,
             params["name"]
           ),
247
         {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
248
249
250
251
      json_response(conn, :no_content, "")
    end
  end

Maksim's avatar
Maksim committed
252
  @doc "Get a account registeration invite token (base64 string)"
253
254
255
256
257
258
259
260
261
  def get_invite_token(conn, params) do
    options = params["invite"] || %{}
    {:ok, invite} = UserInviteToken.create_invite(options)

    conn
    |> json(invite.token)
  end

  @doc "Get list of created invites"
262
  def invites(conn, _params) do
263
264
265
266
267
268
269
    invites = UserInviteToken.list_invites()

    conn
    |> json(AccountView.render("invites.json", %{invites: invites}))
  end

  @doc "Revokes invite by token"
270
  def revoke_invite(conn, %{"token" => token}) do
271
272
    invite = UserInviteToken.find_by_token!(token)
    {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true})
273
274

    conn
275
    |> json(AccountView.render("invite.json", %{invite: updated_invite}))
Haelwenn's avatar
Haelwenn committed
276
277
  end

Maksim's avatar
Maksim committed
278
  @doc "Get a password reset token (base64 string) for given nickname"
279
  def get_password_reset(conn, %{"nickname" => nickname}) do
minibikini's avatar
minibikini committed
280
    (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
281
282
283
    {:ok, token} = Pleroma.PasswordResetToken.create_token(user)

    conn
284
285
286
    |> json(token.token)
  end

287
288
289
290
291
292
  def errors(conn, {:error, :not_found}) do
    conn
    |> put_status(404)
    |> json("Not found")
  end

293
294
295
296
297
298
299
300
301
302
  def errors(conn, {:param_cast, _}) do
    conn
    |> put_status(400)
    |> json("Invalid parameters")
  end

  def errors(conn, _) do
    conn
    |> put_status(500)
    |> json("Something went wrong")
Haelwenn's avatar
Haelwenn committed
303
  end
Maxim Filippov's avatar
Maxim Filippov committed
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

  defp page_params(params) do
    {get_page(params["page"]), get_page_size(params["page_size"])}
  end

  defp get_page(page_string) when is_nil(page_string), do: 1

  defp get_page(page_string) do
    case Integer.parse(page_string) do
      {page, _} -> page
      :error -> 1
    end
  end

  defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size

  defp get_page_size(page_size_string) do
    case Integer.parse(page_size_string) do
      {page_size, _} -> page_size
      :error -> @users_page_size
    end
  end
Haelwenn's avatar
Haelwenn committed
326
end