Credo fixes.
[akkoma] / test / web / activity_pub / side_effects_test.exs
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.ActivityPub.SideEffectsTest do
6 use Oban.Testing, repo: Pleroma.Repo
7 use Pleroma.DataCase
8
9 alias Pleroma.Activity
10 alias Pleroma.Chat
11 alias Pleroma.Notification
12 alias Pleroma.Object
13 alias Pleroma.Repo
14 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.ActivityPub.Builder
18 alias Pleroma.Web.ActivityPub.SideEffects
19 alias Pleroma.Web.CommonAPI
20
21 import Pleroma.Factory
22 import Mock
23
24 describe "delete objects" do
25 setup do
26 user = insert(:user)
27 other_user = insert(:user)
28
29 {:ok, op} = CommonAPI.post(other_user, %{"status" => "big oof"})
30 {:ok, post} = CommonAPI.post(user, %{"status" => "hey", "in_reply_to_id" => op})
31 object = Object.normalize(post)
32 {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
33 {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
34 {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
35 {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
36 %{user: user, delete: delete, post: post, object: object, delete_user: delete_user, op: op}
37 end
38
39 test "it handles object deletions", %{
40 delete: delete,
41 post: post,
42 object: object,
43 user: user,
44 op: op
45 } do
46 with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
47 stream_out: fn _ -> nil end,
48 stream_out_participations: fn _, _ -> nil end do
49 {:ok, delete, _} = SideEffects.handle(delete)
50 user = User.get_cached_by_ap_id(object.data["actor"])
51
52 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
53 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
54 end
55
56 object = Object.get_by_id(object.id)
57 assert object.data["type"] == "Tombstone"
58 refute Activity.get_by_id(post.id)
59
60 user = User.get_by_id(user.id)
61 assert user.note_count == 0
62
63 object = Object.normalize(op.data["object"], false)
64
65 assert object.data["repliesCount"] == 0
66 end
67
68 test "it handles user deletions", %{delete_user: delete, user: user} do
69 {:ok, _delete, _} = SideEffects.handle(delete)
70 ObanHelpers.perform_all()
71
72 assert User.get_cached_by_ap_id(user.ap_id).deactivated
73 end
74 end
75
76 describe "EmojiReact objects" do
77 setup do
78 poster = insert(:user)
79 user = insert(:user)
80
81 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
82
83 {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
84 {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
85
86 %{emoji_react: emoji_react, user: user, poster: poster}
87 end
88
89 test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
90 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
91 object = Object.get_by_ap_id(emoji_react.data["object"])
92
93 assert object.data["reaction_count"] == 1
94 assert ["👌", [user.ap_id]] in object.data["reactions"]
95 end
96
97 test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
98 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
99 assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
100 end
101 end
102
103 describe "Undo objects" do
104 setup do
105 poster = insert(:user)
106 user = insert(:user)
107 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
108 {:ok, like} = CommonAPI.favorite(user, post.id)
109 {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
110 {:ok, announce, _} = CommonAPI.repeat(post.id, user)
111 {:ok, block} = ActivityPub.block(user, poster)
112 User.block(user, poster)
113
114 {:ok, undo_data, _meta} = Builder.undo(user, like)
115 {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
116
117 {:ok, undo_data, _meta} = Builder.undo(user, reaction)
118 {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
119
120 {:ok, undo_data, _meta} = Builder.undo(user, announce)
121 {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
122
123 {:ok, undo_data, _meta} = Builder.undo(user, block)
124 {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
125
126 %{
127 like_undo: like_undo,
128 post: post,
129 like: like,
130 reaction_undo: reaction_undo,
131 reaction: reaction,
132 announce_undo: announce_undo,
133 announce: announce,
134 block_undo: block_undo,
135 block: block,
136 poster: poster,
137 user: user
138 }
139 end
140
141 test "deletes the original block", %{block_undo: block_undo, block: block} do
142 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
143 refute Activity.get_by_id(block.id)
144 end
145
146 test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
147 blocker = User.get_by_ap_id(block.data["actor"])
148 blocked = User.get_by_ap_id(block.data["object"])
149
150 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
151 refute User.blocks?(blocker, blocked)
152 end
153
154 test "an announce undo removes the announce from the object", %{
155 announce_undo: announce_undo,
156 post: post
157 } do
158 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
159
160 object = Object.get_by_ap_id(post.data["object"])
161
162 assert object.data["announcement_count"] == 0
163 assert object.data["announcements"] == []
164 end
165
166 test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
167 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
168 refute Activity.get_by_id(announce.id)
169 end
170
171 test "a reaction undo removes the reaction from the object", %{
172 reaction_undo: reaction_undo,
173 post: post
174 } do
175 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
176
177 object = Object.get_by_ap_id(post.data["object"])
178
179 assert object.data["reaction_count"] == 0
180 assert object.data["reactions"] == []
181 end
182
183 test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
184 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
185 refute Activity.get_by_id(reaction.id)
186 end
187
188 test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
189 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
190
191 object = Object.get_by_ap_id(post.data["object"])
192
193 assert object.data["like_count"] == 0
194 assert object.data["likes"] == []
195 end
196
197 test "deletes the original like", %{like_undo: like_undo, like: like} do
198 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
199 refute Activity.get_by_id(like.id)
200 end
201 end
202
203 describe "like objects" do
204 setup do
205 poster = insert(:user)
206 user = insert(:user)
207 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
208
209 {:ok, like_data, _meta} = Builder.like(user, post.object)
210 {:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
211
212 %{like: like, user: user, poster: poster}
213 end
214
215 test "add the like to the original object", %{like: like, user: user} do
216 {:ok, like, _} = SideEffects.handle(like)
217 object = Object.get_by_ap_id(like.data["object"])
218 assert object.data["like_count"] == 1
219 assert user.ap_id in object.data["likes"]
220 end
221
222 test "creates a notification", %{like: like, poster: poster} do
223 {:ok, like, _} = SideEffects.handle(like)
224 assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
225 end
226 end
227
228 describe "creation of ChatMessages" do
229 test "notifies the recipient" do
230 author = insert(:user, local: false)
231 recipient = insert(:user, local: true)
232
233 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
234
235 {:ok, create_activity_data, _meta} =
236 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
237
238 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
239
240 {:ok, _create_activity, _meta} =
241 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
242
243 assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id)
244 end
245
246 test "it creates a Chat for the local users and bumps the unread count" do
247 author = insert(:user, local: false)
248 recipient = insert(:user, local: true)
249
250 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
251
252 {:ok, create_activity_data, _meta} =
253 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
254
255 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
256
257 {:ok, _create_activity, _meta} =
258 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
259
260 # An object is created
261 assert Object.get_by_ap_id(chat_message_data["id"])
262
263 # The remote user won't get a chat
264 chat = Chat.get(author.id, recipient.ap_id)
265 refute chat
266
267 # The local user will get a chat
268 chat = Chat.get(recipient.id, author.ap_id)
269 assert chat
270
271 author = insert(:user, local: true)
272 recipient = insert(:user, local: true)
273
274 {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
275
276 {:ok, create_activity_data, _meta} =
277 Builder.create(author, chat_message_data["id"], [recipient.ap_id])
278
279 {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
280
281 {:ok, _create_activity, _meta} =
282 SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
283
284 # Both users are local and get the chat
285 chat = Chat.get(author.id, recipient.ap_id)
286 assert chat
287
288 chat = Chat.get(recipient.id, author.ap_id)
289 assert chat
290 end
291 end
292 end