twitter_api_controller.ex 18.4 KB
Newer Older
1
2
defmodule Pleroma.Web.TwitterAPI.Controller do
  use Pleroma.Web, :controller
3
  alias Pleroma.Formatter
4
  alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView}
lain's avatar
lain committed
5
  alias Pleroma.Web.CommonAPI
6
  alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
7
  alias Pleroma.{Repo, Activity, User, Notification}
lain's avatar
lain committed
8
  alias Pleroma.Web.ActivityPub.ActivityPub
9
  alias Pleroma.Web.ActivityPub.Utils
10
  alias Ecto.Changeset
11

lain's avatar
lain committed
12
13
  require Logger

href's avatar
href committed
14
  plug(:only_if_public_instance when action in [:public_timeline, :public_and_external_timeline])
15
16
  action_fallback(:errors)

17
  def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
lain's avatar
lain committed
18
19
    token = Phoenix.Token.sign(conn, "user socket", user.id)
    render(conn, UserView, "show.json", %{user: user, token: token})
20
21
  end

Thog's avatar
Thog committed
22
  def status_update(%{assigns: %{user: user}} = conn, %{"status" => _} = status_data) do
23
    with media_ids <- extract_media_ids(status_data),
lain's avatar
lain committed
24
25
         {:ok, activity} <-
           TwitterAPI.create_status(user, Map.put(status_data, "media_ids", media_ids)) do
dtluna's avatar
dtluna committed
26
      conn
lain's avatar
lain committed
27
      |> json(ActivityView.render("activity.json", activity: activity, for: user))
dtluna's avatar
dtluna committed
28
    else
29
      _ -> empty_status_reply(conn)
dtluna's avatar
dtluna committed
30
    end
lain's avatar
lain committed
31
32
  end

dtluna's avatar
dtluna committed
33
34
35
36
37
38
39
40
  def status_update(conn, _status_data) do
    empty_status_reply(conn)
  end

  defp empty_status_reply(conn) do
    bad_request_reply(conn, "Client must provide a 'status' parameter with a value.")
  end

lain's avatar
lain committed
41
42
43
  defp extract_media_ids(status_data) do
    with media_ids when not is_nil(media_ids) <- status_data["media_ids"],
         split_ids <- String.split(media_ids, ","),
lain's avatar
lain committed
44
45
46
47
         clean_ids <- Enum.reject(split_ids, fn id -> String.length(id) == 0 end) do
      clean_ids
    else
      _e -> []
lain's avatar
lain committed
48
49
50
    end
  end

lain's avatar
lain committed
51
  def public_and_external_timeline(%{assigns: %{user: user}} = conn, params) do
lain's avatar
lain committed
52
53
    params =
      params
54
      |> Map.put("type", ["Create", "Announce"])
lain's avatar
lain committed
55
56
57
      |> Map.put("blocking_user", user)

    activities = ActivityPub.fetch_public_activities(params)
lain's avatar
lain committed
58
59

    conn
lain's avatar
lain committed
60
    |> render(ActivityView, "index.json", %{activities: activities, for: user})
lain's avatar
lain committed
61
62
  end

63
  def public_timeline(%{assigns: %{user: user}} = conn, params) do
lain's avatar
lain committed
64
65
    params =
      params
66
      |> Map.put("type", ["Create", "Announce"])
lain's avatar
lain committed
67
68
69
70
      |> Map.put("local_only", true)
      |> Map.put("blocking_user", user)

    activities = ActivityPub.fetch_public_activities(params)
lain's avatar
lain committed
71
72

    conn
lain's avatar
lain committed
73
    |> render(ActivityView, "index.json", %{activities: activities, for: user})
lain's avatar
lain committed
74
75
  end

lain's avatar
lain committed
76
  def friends_timeline(%{assigns: %{user: user}} = conn, params) do
lain's avatar
lain committed
77
78
79
80
81
82
    params =
      params
      |> Map.put("type", ["Create", "Announce", "Follow", "Like"])
      |> Map.put("blocking_user", user)
      |> Map.put("user", user)

83
84
85
    activities =
      ActivityPub.fetch_activities([user.ap_id | user.following], params)
      |> ActivityPub.contain_timeline(user)
lain's avatar
lain committed
86
87

    conn
lain's avatar
lain committed
88
    |> render(ActivityView, "index.json", %{activities: activities, for: user})
lain's avatar
lain committed
89
90
  end

eal's avatar
eal committed
91
92
93
  def show_user(conn, params) do
    with {:ok, shown} <- TwitterAPI.get_user(params) do
      if user = conn.assigns.user do
lain's avatar
lain committed
94
        render(conn, UserView, "show.json", %{user: shown, for: user})
eal's avatar
eal committed
95
      else
lain's avatar
lain committed
96
        render(conn, UserView, "show.json", %{user: shown})
eal's avatar
eal committed
97
98
99
100
101
102
103
      end
    else
      {:error, msg} ->
        bad_request_reply(conn, msg)
    end
  end

dtluna's avatar
dtluna committed
104
  def user_timeline(%{assigns: %{user: user}} = conn, params) do
105
106
    case TwitterAPI.get_user(user, params) do
      {:ok, target_user} ->
107
        activities = ActivityPub.fetch_user_activities(target_user, user, params)
lain's avatar
lain committed
108

109
        conn
lain's avatar
lain committed
110
        |> render(ActivityView, "index.json", %{activities: activities, for: user})
lain's avatar
lain committed
111

112
113
114
      {:error, msg} ->
        bad_request_reply(conn, msg)
    end
dtluna's avatar
dtluna committed
115
116
  end

dtluna's avatar
dtluna committed
117
  def mentions_timeline(%{assigns: %{user: user}} = conn, params) do
118
119
120
121
122
    params =
      params
      |> Map.put("type", ["Create", "Announce", "Follow", "Like"])
      |> Map.put("blocking_user", user)

lain's avatar
lain committed
123
    activities = ActivityPub.fetch_activities([user.ap_id], params)
dtluna's avatar
dtluna committed
124
125

    conn
lain's avatar
lain committed
126
127
128
129
130
131
132
    |> render(ActivityView, "index.json", %{activities: activities, for: user})
  end

  def dm_timeline(%{assigns: %{user: user}} = conn, params) do
    query =
      ActivityPub.fetch_activities_query(
        [user.ap_id],
133
        Map.merge(params, %{"type" => "Create", "user" => user, visibility: "direct"})
lain's avatar
lain committed
134
135
136
137
138
      )

    activities = Repo.all(query)

    conn
lain's avatar
lain committed
139
    |> render(ActivityView, "index.json", %{activities: activities, for: user})
dtluna's avatar
dtluna committed
140
141
  end

142
143
144
145
146
147
148
  def notifications(%{assigns: %{user: user}} = conn, params) do
    notifications = Notification.for_user(user, params)

    conn
    |> render(NotificationView, "notification.json", %{notifications: notifications, for: user})
  end

149
150
151
152
153
154
155
156
157
158
159
160
161
  def notifications_read(%{assigns: %{user: user}} = conn, %{"latest_id" => latest_id} = params) do
    Notification.set_read_up_to(user, latest_id)

    notifications = Notification.for_user(user, params)

    conn
    |> render(NotificationView, "notification.json", %{notifications: notifications, for: user})
  end

  def notifications_read(%{assigns: %{user: user}} = conn, _) do
    bad_request_reply(conn, "You need to specify latest_id")
  end

162
163
  def follow(%{assigns: %{user: user}} = conn, params) do
    case TwitterAPI.follow(user, params) do
164
      {:ok, user, followed, _activity} ->
dtluna's avatar
dtluna committed
165
        render(conn, UserView, "show.json", %{user: followed, for: user})
lain's avatar
lain committed
166
167
168

      {:error, msg} ->
        forbidden_json_reply(conn, msg)
169
    end
lain's avatar
lain committed
170
171
  end

eal's avatar
eal committed
172
173
174
  def block(%{assigns: %{user: user}} = conn, params) do
    case TwitterAPI.block(user, params) do
      {:ok, user, blocked} ->
lain's avatar
lain committed
175
176
177
178
        render(conn, UserView, "show.json", %{user: blocked, for: user})

      {:error, msg} ->
        forbidden_json_reply(conn, msg)
eal's avatar
eal committed
179
180
181
182
183
184
    end
  end

  def unblock(%{assigns: %{user: user}} = conn, params) do
    case TwitterAPI.unblock(user, params) do
      {:ok, user, blocked} ->
lain's avatar
lain committed
185
186
187
188
        render(conn, UserView, "show.json", %{user: blocked, for: user})

      {:error, msg} ->
        forbidden_json_reply(conn, msg)
eal's avatar
eal committed
189
190
191
    end
  end

lain's avatar
lain committed
192
  def delete_post(%{assigns: %{user: user}} = conn, %{"id" => id}) do
normandy's avatar
normandy committed
193
    with {:ok, activity} <- TwitterAPI.delete(user, id) do
normandy's avatar
normandy committed
194
      render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
lain's avatar
lain committed
195
196
197
    end
  end

198
  def unfollow(%{assigns: %{user: user}} = conn, params) do
199
    case TwitterAPI.unfollow(user, params) do
200
      {:ok, user, unfollowed} ->
dtluna's avatar
dtluna committed
201
        render(conn, UserView, "show.json", %{user: unfollowed, for: user})
lain's avatar
lain committed
202
203
204

      {:error, msg} ->
        forbidden_json_reply(conn, msg)
205
    end
lain's avatar
lain committed
206
207
  end

208
  def fetch_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
lain's avatar
lain committed
209
210
    with %Activity{} = activity <- Repo.get(Activity, id),
         true <- ActivityPub.visible_for_user?(activity, user) do
lain's avatar
lain committed
211
      render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
lain's avatar
lain committed
212
    end
lain's avatar
lain committed
213
214
  end

215
  def fetch_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
216
217
    id = String.to_integer(id)

lain's avatar
lain committed
218
219
220
221
222
223
224
225
226
    with context when is_binary(context) <- TwitterAPI.conversation_id_to_context(id),
         activities <-
           ActivityPub.fetch_activities_for_context(context, %{
             "blocking_user" => user,
             "user" => user
           }) do
      conn
      |> render(ActivityView, "index.json", %{activities: activities, for: user})
    end
227
228
  end

lain's avatar
lain committed
229
230
  def upload(conn, %{"media" => media}) do
    response = TwitterAPI.upload(media)
lain's avatar
lain committed
231

lain's avatar
lain committed
232
233
234
235
    conn
    |> put_resp_content_type("application/atom+xml")
    |> send_resp(200, response)
  end
236

237
238
  def upload_json(conn, %{"media" => media}) do
    response = TwitterAPI.upload(media, "json")
lain's avatar
lain committed
239

240
241
242
243
    conn
    |> json_reply(200, response)
  end

lain's avatar
lain committed
244
  def get_by_id_or_ap_id(id) do
245
    activity = Repo.get(Activity, id) || Activity.get_create_activity_by_object_ap_id(id)
lain's avatar
lain committed
246

247
248
249
250
251
    if activity.data["type"] == "Create" do
      activity
    else
      Activity.get_create_activity_by_object_ap_id(activity.data["object"])
    end
lain's avatar
lain committed
252
253
  end

lain's avatar
lain committed
254
  def favorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do
255
256
    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
         {:ok, activity} <- TwitterAPI.fav(user, id) do
257
      render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
lain's avatar
lain committed
258
    end
lain's avatar
lain committed
259
260
  end

lain's avatar
lain committed
261
  def unfavorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do
262
263
    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
         {:ok, activity} <- TwitterAPI.unfav(user, id) do
264
      render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
lain's avatar
lain committed
265
    end
lain's avatar
lain committed
266
267
  end

lain's avatar
lain committed
268
  def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
269
270
    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
         {:ok, activity} <- TwitterAPI.repeat(user, id) do
271
      render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
dtluna's avatar
dtluna committed
272
    end
lain's avatar
lain committed
273
274
  end

275
276
277
278
279
280
281
  def unretweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
    with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
         {:ok, activity} <- TwitterAPI.unrepeat(user, id) do
      render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
    end
  end

282
283
  def register(conn, params) do
    with {:ok, user} <- TwitterAPI.register_user(params) do
dtluna's avatar
dtluna committed
284
      render(conn, UserView, "show.json", %{user: user})
285
286
    else
      {:error, errors} ->
lain's avatar
lain committed
287
288
        conn
        |> json_reply(400, Jason.encode!(errors))
289
290
291
    end
  end

lain's avatar
lain committed
292
  def update_avatar(%{assigns: %{user: user}} = conn, params) do
293
294
295
296
    upload_limit =
      Application.get_env(:pleroma, :instance)
      |> Keyword.fetch(:avatar_upload_limit)

href's avatar
href committed
297
    {:ok, object} = ActivityPub.upload(params, size_limit: upload_limit)
298
    change = Changeset.change(user, %{avatar: object.data})
lain's avatar
lain committed
299
    {:ok, user} = User.update_and_set_cache(change)
lain's avatar
lain committed
300
    CommonAPI.update(user)
lain's avatar
lain committed
301

dtluna's avatar
dtluna committed
302
    render(conn, UserView, "show.json", %{user: user, for: user})
lain's avatar
lain committed
303
304
  end

lain's avatar
lain committed
305
  def update_banner(%{assigns: %{user: user}} = conn, params) do
306
307
308
309
    upload_limit =
      Application.get_env(:pleroma, :instance)
      |> Keyword.fetch(:banner_upload_limit)

href's avatar
href committed
310
311
    with {:ok, object} <-
           ActivityPub.upload(%{"img" => params["banner"]}, size_limit: upload_limit),
lain's avatar
lain committed
312
313
         new_info <- Map.put(user.info, "banner", object.data),
         change <- User.info_changeset(user, %{info: new_info}),
lain's avatar
lain committed
314
315
         {:ok, user} <- User.update_and_set_cache(change) do
      CommonAPI.update(user)
lain's avatar
lain committed
316
317
318
      %{"url" => [%{"href" => href} | _]} = object.data
      response = %{url: href} |> Jason.encode!()

lain's avatar
lain committed
319
320
321
322
323
324
      conn
      |> json_reply(200, response)
    end
  end

  def update_background(%{assigns: %{user: user}} = conn, params) do
325
326
327
328
    upload_limit =
      Application.get_env(:pleroma, :instance)
      |> Keyword.fetch(:background_upload_limit)

href's avatar
href committed
329
    with {:ok, object} <- ActivityPub.upload(params, size_limit: upload_limit),
lain's avatar
lain committed
330
331
         new_info <- Map.put(user.info, "background", object.data),
         change <- User.info_changeset(user, %{info: new_info}),
lain's avatar
lain committed
332
         {:ok, _user} <- User.update_and_set_cache(change) do
lain's avatar
lain committed
333
334
335
      %{"url" => [%{"href" => href} | _]} = object.data
      response = %{url: href} |> Jason.encode!()

lain's avatar
lain committed
336
337
338
339
340
      conn
      |> json_reply(200, response)
    end
  end

lain's avatar
lain committed
341
342
  def external_profile(%{assigns: %{user: current_user}} = conn, %{"profileurl" => uri}) do
    with {:ok, user_map} <- TwitterAPI.get_external_profile(current_user, uri),
lain's avatar
lain committed
343
         response <- Jason.encode!(user_map) do
lain's avatar
lain committed
344
345
      conn
      |> json_reply(200, response)
lain's avatar
lain committed
346
347
348
349
350
    else
      _e ->
        conn
        |> put_status(404)
        |> json(%{error: "Can't find user"})
lain's avatar
lain committed
351
352
353
    end
  end

354
355
356
357
358
359
  def update_most_recent_notification(%{assigns: %{user: user}} = conn, %{"id" => id}) do
    with id when is_number(id) <- String.to_integer(id),
         info <- user.info,
         mrn <- max(id, user.info["most_recent_notification"] || 0),
         updated_info <- Map.put(info, "most_recent_notification", mrn),
         changeset <- User.info_changeset(user, %{info: updated_info}),
lain's avatar
lain committed
360
         {:ok, _user} <- User.update_and_set_cache(changeset) do
361
      conn
lain's avatar
lain committed
362
      |> json_reply(200, Jason.encode!(mrn))
363
364
365
366
367
    else
      _e -> bad_request_reply(conn, "Can't update.")
    end
  end

eal's avatar
eal committed
368
  def followers(conn, params) do
369
    with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
eal's avatar
eal committed
370
         {:ok, followers} <- User.get_followers(user) do
371
      render(conn, UserView, "index.json", %{users: followers, for: conn.assigns[:user]})
lain's avatar
lain committed
372
373
374
375
376
    else
      _e -> bad_request_reply(conn, "Can't get followers")
    end
  end

eal's avatar
eal committed
377
  def friends(conn, params) do
378
    with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
eal's avatar
eal committed
379
         {:ok, friends} <- User.get_friends(user) do
380
      render(conn, UserView, "index.json", %{users: friends, for: conn.assigns[:user]})
lain's avatar
lain committed
381
382
383
384
385
    else
      _e -> bad_request_reply(conn, "Can't get friends")
    end
  end

386
  def friend_requests(conn, params) do
387
    with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
388
         {:ok, friend_requests} <- User.get_follow_requests(user) do
389
      render(conn, UserView, "index.json", %{users: friend_requests, for: conn.assigns[:user]})
390
391
392
393
394
    else
      _e -> bad_request_reply(conn, "Can't get friend requests")
    end
  end

395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  def approve_friend_request(conn, %{"user_id" => uid} = params) do
    with followed <- conn.assigns[:user],
         uid when is_number(uid) <- String.to_integer(uid),
         %User{} = follower <- Repo.get(User, uid),
         {:ok, follower} <- User.maybe_follow(follower, followed),
         %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
         {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"),
         {:ok, _activity} <-
           ActivityPub.accept(%{
             to: [follower.ap_id],
             actor: followed.ap_id,
             object: follow_activity.data["id"],
             type: "Accept"
           }) do
      render(conn, UserView, "show.json", %{user: follower, for: followed})
    else
      e -> bad_request_reply(conn, "Can't approve user: #{inspect(e)}")
    end
  end

  def deny_friend_request(conn, %{"user_id" => uid} = params) do
    with followed <- conn.assigns[:user],
         uid when is_number(uid) <- String.to_integer(uid),
         %User{} = follower <- Repo.get(User, uid),
         %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
         {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"),
         {:ok, _activity} <-
           ActivityPub.reject(%{
             to: [follower.ap_id],
             actor: followed.ap_id,
             object: follow_activity.data["id"],
             type: "Reject"
           }) do
      render(conn, UserView, "show.json", %{user: follower, for: followed})
    else
      e -> bad_request_reply(conn, "Can't deny user: #{inspect(e)}")
    end
  end

eal's avatar
eal committed
434
435
  def friends_ids(%{assigns: %{user: user}} = conn, _params) do
    with {:ok, friends} <- User.get_friends(user) do
lain's avatar
lain committed
436
437
438
439
      ids =
        friends
        |> Enum.map(fn x -> x.id end)
        |> Jason.encode!()
440

eal's avatar
eal committed
441
442
443
444
445
446
      json(conn, ids)
    else
      _e -> bad_request_reply(conn, "Can't get friends")
    end
  end

447
  def empty_array(conn, _params) do
lain's avatar
lain committed
448
    json(conn, Jason.encode!([]))
449
  end
eal's avatar
eal committed
450

451
452
453
454
  def raw_empty_array(conn, _params) do
    json(conn, [])
  end

lain's avatar
lain committed
455
  def update_profile(%{assigns: %{user: user}} = conn, params) do
lain's avatar
lain committed
456
457
    params =
      if bio = params["description"] do
458
459
        mentions = Formatter.parse_mentions(bio)
        tags = Formatter.parse_tags(bio)
ensra's avatar
Format    
ensra committed
460

461
462
463
464
465
466
        emoji =
          (user.info["source_data"]["tag"] || [])
          |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
          |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
            {String.trim(name, ":"), url}
          end)
ensra's avatar
Format    
ensra committed
467

468
        bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
ensra's avatar
Format    
ensra committed
469
        Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
lain's avatar
lain committed
470
471
472
      else
        params
      end
lain's avatar
lain committed
473

474
475
476
477
478
479
480
481
482
483
484
485
486
487
    user =
      if locked = params["locked"] do
        with locked <- locked == "true",
             new_info <- Map.put(user.info, "locked", locked),
             change <- User.info_changeset(user, %{info: new_info}),
             {:ok, user} <- User.update_and_set_cache(change) do
          user
        else
          _e -> user
        end
      else
        user
      end

488
489
490
491
492
493
494
495
496
497
498
499
500
501
    user =
      if no_rich_text = params["no_rich_text"] do
        with no_rich_text <- no_rich_text == "true",
             new_info <- Map.put(user.info, "no_rich_text", no_rich_text),
             change <- User.info_changeset(user, %{info: new_info}),
             {:ok, user} <- User.update_and_set_cache(change) do
          user
        else
          _e -> user
        end
      else
        user
      end

502
503
504
505
506
507
508
509
510
511
512
513
514
    user =
      if default_scope = params["default_scope"] do
        with new_info <- Map.put(user.info, "default_scope", default_scope),
             change <- User.info_changeset(user, %{info: new_info}),
             {:ok, user} <- User.update_and_set_cache(change) do
          user
        else
          _e -> user
        end
      else
        user
      end

lain's avatar
lain committed
515
    with changeset <- User.update_changeset(user, params),
lain's avatar
lain committed
516
         {:ok, user} <- User.update_and_set_cache(changeset) do
lain's avatar
lain committed
517
      CommonAPI.update(user)
lain's avatar
lain committed
518
519
520
521
522
523
524
525
      render(conn, UserView, "user.json", %{user: user, for: user})
    else
      error ->
        Logger.debug("Can't update user: #{inspect(error)}")
        bad_request_reply(conn, "Can't update user")
    end
  end

Thog's avatar
Thog committed
526
  def search(%{assigns: %{user: user}} = conn, %{"q" => _query} = params) do
lain's avatar
lain committed
527
528
    activities = TwitterAPI.search(user, params)

lain's avatar
lain committed
529
    conn
lain's avatar
lain committed
530
    |> render(ActivityView, "index.json", %{activities: activities, for: user})
lain's avatar
lain committed
531
532
  end

533
534
535
536
537
538
539
  def search_user(%{assigns: %{user: user}} = conn, %{"query" => query}) do
    users = User.search(query, true)

    conn
    |> render(UserView, "index.json", %{users: users, for: user})
  end

540
  defp bad_request_reply(conn, error_message) do
dtluna's avatar
dtluna committed
541
    json = error_json(conn, error_message)
542
543
544
    json_reply(conn, 400, json)
  end

545
546
547
548
549
  defp json_reply(conn, status, json) do
    conn
    |> put_resp_content_type("application/json")
    |> send_resp(status, json)
  end
550
551

  defp forbidden_json_reply(conn, error_message) do
dtluna's avatar
dtluna committed
552
    json = error_json(conn, error_message)
553
554
    json_reply(conn, 403, json)
  end
dtluna's avatar
dtluna committed
555

href's avatar
href committed
556
557
558
559
560
561
562
563
  def only_if_public_instance(conn = %{conn: %{assigns: %{user: _user}}}, _), do: conn

  def only_if_public_instance(conn, _) do
    if Keyword.get(Application.get_env(:pleroma, :instance), :public) do
      conn
    else
      conn
      |> forbidden_json_reply("Invalid credentials.")
href's avatar
href committed
564
      |> halt()
href's avatar
href committed
565
566
567
    end
  end

dtluna's avatar
dtluna committed
568
  defp error_json(conn, error_message) do
lain's avatar
lain committed
569
    %{"error" => error_message, "request" => conn.request_path} |> Jason.encode!()
dtluna's avatar
dtluna committed
570
  end
571
572
573
574
575
576
577
578
579
580
581
582

  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")
  end
583
end