Merge branch 'admin-be' into 'develop'
[akkoma] / lib / pleroma / web / pleroma_api / controllers / pleroma_api_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
6 use Pleroma.Web, :controller
7
8 import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
9
10 alias Pleroma.Activity
11 alias Pleroma.Conversation.Participation
12 alias Pleroma.Notification
13 alias Pleroma.Object
14 alias Pleroma.Plugs.OAuthScopesPlug
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.MastodonAPI.AccountView
19 alias Pleroma.Web.MastodonAPI.ConversationView
20 alias Pleroma.Web.MastodonAPI.NotificationView
21 alias Pleroma.Web.MastodonAPI.StatusView
22
23 plug(
24 OAuthScopesPlug,
25 %{scopes: ["read:statuses"]}
26 when action in [:conversation, :conversation_statuses]
27 )
28
29 plug(
30 OAuthScopesPlug,
31 %{scopes: ["write:statuses"]}
32 when action in [:react_with_emoji, :unreact_with_emoji]
33 )
34
35 plug(
36 OAuthScopesPlug,
37 %{scopes: ["write:conversations"]} when action == :update_conversation
38 )
39
40 plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :read_notification)
41
42 plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
43
44 def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
45 with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
46 %Object{data: %{"reactions" => emoji_reactions}} when is_list(emoji_reactions) <-
47 Object.normalize(activity) do
48 reactions =
49 emoji_reactions
50 |> Enum.map(fn [emoji, users] ->
51 users = Enum.map(users, &User.get_cached_by_ap_id/1)
52 {emoji, AccountView.render("index.json", %{users: users, for: user, as: :user})}
53 end)
54
55 conn
56 |> json(reactions)
57 else
58 _e ->
59 conn
60 |> json([])
61 end
62 end
63
64 def react_with_emoji(%{assigns: %{user: user}} = conn, %{"id" => activity_id, "emoji" => emoji}) do
65 with {:ok, _activity, _object} <- CommonAPI.react_with_emoji(activity_id, user, emoji),
66 activity <- Activity.get_by_id(activity_id) do
67 conn
68 |> put_view(StatusView)
69 |> render("show.json", %{activity: activity, for: user, as: :activity})
70 end
71 end
72
73 def unreact_with_emoji(%{assigns: %{user: user}} = conn, %{
74 "id" => activity_id,
75 "emoji" => emoji
76 }) do
77 with {:ok, _activity, _object} <- CommonAPI.unreact_with_emoji(activity_id, user, emoji),
78 activity <- Activity.get_by_id(activity_id) do
79 conn
80 |> put_view(StatusView)
81 |> render("show.json", %{activity: activity, for: user, as: :activity})
82 end
83 end
84
85 def conversation(%{assigns: %{user: user}} = conn, %{"id" => participation_id}) do
86 with %Participation{} = participation <- Participation.get(participation_id),
87 true <- user.id == participation.user_id do
88 conn
89 |> put_view(ConversationView)
90 |> render("participation.json", %{participation: participation, for: user})
91 end
92 end
93
94 def conversation_statuses(
95 %{assigns: %{user: user}} = conn,
96 %{"id" => participation_id} = params
97 ) do
98 participation = Participation.get(participation_id, preload: [:conversation])
99
100 if user.id == participation.user_id do
101 params =
102 params
103 |> Map.put("blocking_user", user)
104 |> Map.put("muting_user", user)
105 |> Map.put("user", user)
106
107 activities =
108 participation.conversation.ap_id
109 |> ActivityPub.fetch_activities_for_context(params)
110 |> Enum.reverse()
111
112 conn
113 |> add_link_headers(activities)
114 |> put_view(StatusView)
115 |> render("index.json", %{activities: activities, for: user, as: :activity})
116 end
117 end
118
119 def update_conversation(
120 %{assigns: %{user: user}} = conn,
121 %{"id" => participation_id, "recipients" => recipients}
122 ) do
123 participation =
124 participation_id
125 |> Participation.get()
126
127 with true <- user.id == participation.user_id,
128 {:ok, participation} <- Participation.set_recipients(participation, recipients) do
129 conn
130 |> put_view(ConversationView)
131 |> render("participation.json", %{participation: participation, for: user})
132 end
133 end
134
135 def read_conversations(%{assigns: %{user: user}} = conn, _params) do
136 with {:ok, _, participations} <- Participation.mark_all_as_read(user) do
137 conn
138 |> add_link_headers(participations)
139 |> put_view(ConversationView)
140 |> render("participations.json", participations: participations, for: user)
141 end
142 end
143
144 def read_notification(%{assigns: %{user: user}} = conn, %{"id" => notification_id}) do
145 with {:ok, notification} <- Notification.read_one(user, notification_id) do
146 conn
147 |> put_view(NotificationView)
148 |> render("show.json", %{notification: notification, for: user})
149 else
150 {:error, message} ->
151 conn
152 |> put_status(:bad_request)
153 |> json(%{"error" => message})
154 end
155 end
156
157 def read_notification(%{assigns: %{user: user}} = conn, %{"max_id" => max_id}) do
158 with notifications <- Notification.set_read_up_to(user, max_id) do
159 notifications = Enum.take(notifications, 80)
160
161 conn
162 |> put_view(NotificationView)
163 |> render("index.json", %{notifications: notifications, for: user})
164 end
165 end
166 end