5c06dc864fccfa48a9dd79f1b1ff8004defb83db
[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.Notification
11 alias Pleroma.Object
12 alias Pleroma.Repo
13 alias Pleroma.Tests.ObanHelpers
14 alias Pleroma.User
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.ActivityPub.Builder
17 alias Pleroma.Web.ActivityPub.SideEffects
18 alias Pleroma.Web.CommonAPI
19
20 import Pleroma.Factory
21 import Mock
22
23 describe "delete objects" do
24 setup do
25 user = insert(:user)
26 other_user = insert(:user)
27
28 {:ok, op} = CommonAPI.post(other_user, %{"status" => "big oof"})
29 {:ok, post} = CommonAPI.post(user, %{"status" => "hey", "in_reply_to_id" => op})
30 object = Object.normalize(post)
31 {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
32 {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
33 {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
34 {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
35 %{user: user, delete: delete, post: post, object: object, delete_user: delete_user, op: op}
36 end
37
38 test "it handles object deletions", %{
39 delete: delete,
40 post: post,
41 object: object,
42 user: user,
43 op: op
44 } do
45 with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
46 stream_out: fn _ -> nil end,
47 stream_out_participations: fn _, _ -> nil end do
48 {:ok, delete, _} = SideEffects.handle(delete)
49 user = User.get_cached_by_ap_id(object.data["actor"])
50
51 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
52 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
53 end
54
55 object = Object.get_by_id(object.id)
56 assert object.data["type"] == "Tombstone"
57 refute Activity.get_by_id(post.id)
58
59 user = User.get_by_id(user.id)
60 assert user.note_count == 0
61
62 object = Object.normalize(op.data["object"], false)
63
64 assert object.data["repliesCount"] == 0
65 end
66
67 test "it handles user deletions", %{delete_user: delete, user: user} do
68 {:ok, _delete, _} = SideEffects.handle(delete)
69 ObanHelpers.perform_all()
70
71 assert User.get_cached_by_ap_id(user.ap_id).deactivated
72 end
73 end
74
75 describe "EmojiReact objects" do
76 setup do
77 poster = insert(:user)
78 user = insert(:user)
79
80 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
81
82 {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
83 {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
84
85 %{emoji_react: emoji_react, user: user, poster: poster}
86 end
87
88 test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
89 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
90 object = Object.get_by_ap_id(emoji_react.data["object"])
91
92 assert object.data["reaction_count"] == 1
93 assert ["👌", [user.ap_id]] in object.data["reactions"]
94 end
95
96 test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
97 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
98 assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
99 end
100 end
101
102 describe "delete users with confirmation pending" do
103 setup do
104 user = insert(:user, confirmation_pending: true)
105 {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
106 {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
107 {:ok, delete: delete_user, user: user}
108 end
109
110 test "when activation is not required", %{delete: delete, user: user} do
111 clear_config([:instance, :account_activation_required], false)
112 {:ok, _, _} = SideEffects.handle(delete)
113 ObanHelpers.perform_all()
114
115 assert User.get_cached_by_id(user.id).deactivated
116 end
117
118 test "when activation is required", %{delete: delete, user: user} do
119 clear_config([:instance, :account_activation_required], true)
120 {:ok, _, _} = SideEffects.handle(delete)
121 ObanHelpers.perform_all()
122
123 refute User.get_cached_by_id(user.id)
124 end
125 end
126
127 describe "Undo objects" do
128 setup do
129 poster = insert(:user)
130 user = insert(:user)
131 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
132 {:ok, like} = CommonAPI.favorite(user, post.id)
133 {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
134 {:ok, announce, _} = CommonAPI.repeat(post.id, user)
135 {:ok, block} = ActivityPub.block(user, poster)
136 User.block(user, poster)
137
138 {:ok, undo_data, _meta} = Builder.undo(user, like)
139 {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
140
141 {:ok, undo_data, _meta} = Builder.undo(user, reaction)
142 {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
143
144 {:ok, undo_data, _meta} = Builder.undo(user, announce)
145 {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
146
147 {:ok, undo_data, _meta} = Builder.undo(user, block)
148 {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
149
150 %{
151 like_undo: like_undo,
152 post: post,
153 like: like,
154 reaction_undo: reaction_undo,
155 reaction: reaction,
156 announce_undo: announce_undo,
157 announce: announce,
158 block_undo: block_undo,
159 block: block,
160 poster: poster,
161 user: user
162 }
163 end
164
165 test "deletes the original block", %{block_undo: block_undo, block: block} do
166 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
167 refute Activity.get_by_id(block.id)
168 end
169
170 test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
171 blocker = User.get_by_ap_id(block.data["actor"])
172 blocked = User.get_by_ap_id(block.data["object"])
173
174 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
175 refute User.blocks?(blocker, blocked)
176 end
177
178 test "an announce undo removes the announce from the object", %{
179 announce_undo: announce_undo,
180 post: post
181 } do
182 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
183
184 object = Object.get_by_ap_id(post.data["object"])
185
186 assert object.data["announcement_count"] == 0
187 assert object.data["announcements"] == []
188 end
189
190 test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
191 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
192 refute Activity.get_by_id(announce.id)
193 end
194
195 test "a reaction undo removes the reaction from the object", %{
196 reaction_undo: reaction_undo,
197 post: post
198 } do
199 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
200
201 object = Object.get_by_ap_id(post.data["object"])
202
203 assert object.data["reaction_count"] == 0
204 assert object.data["reactions"] == []
205 end
206
207 test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
208 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
209 refute Activity.get_by_id(reaction.id)
210 end
211
212 test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
213 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
214
215 object = Object.get_by_ap_id(post.data["object"])
216
217 assert object.data["like_count"] == 0
218 assert object.data["likes"] == []
219 end
220
221 test "deletes the original like", %{like_undo: like_undo, like: like} do
222 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
223 refute Activity.get_by_id(like.id)
224 end
225 end
226
227 describe "like objects" do
228 setup do
229 poster = insert(:user)
230 user = insert(:user)
231 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
232
233 {:ok, like_data, _meta} = Builder.like(user, post.object)
234 {:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
235
236 %{like: like, user: user, poster: poster}
237 end
238
239 test "add the like to the original object", %{like: like, user: user} do
240 {:ok, like, _} = SideEffects.handle(like)
241 object = Object.get_by_ap_id(like.data["object"])
242 assert object.data["like_count"] == 1
243 assert user.ap_id in object.data["likes"]
244 end
245
246 test "creates a notification", %{like: like, poster: poster} do
247 {:ok, like, _} = SideEffects.handle(like)
248 assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
249 end
250 end
251 end