Merge branch 'patch-2' into 'develop'
[akkoma] / test / web / activity_pub / transmogrifier_test.exs
1 defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
2 use Pleroma.DataCase
3 alias Pleroma.Web.ActivityPub.Transmogrifier
4 alias Pleroma.Web.ActivityPub.Utils
5 alias Pleroma.Web.ActivityPub.ActivityPub
6 alias Pleroma.Web.OStatus
7 alias Pleroma.Activity
8 alias Pleroma.User
9 alias Pleroma.Repo
10 alias Pleroma.Web.Websub.WebsubClientSubscription
11
12 import Pleroma.Factory
13 alias Pleroma.Web.CommonAPI
14
15 describe "handle_incoming" do
16 test "it ignores an incoming notice if we already have it" do
17 activity = insert(:note_activity)
18
19 data =
20 File.read!("test/fixtures/mastodon-post-activity.json")
21 |> Poison.decode!()
22 |> Map.put("object", activity.data["object"])
23
24 {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
25
26 assert activity == returned_activity
27 end
28
29 test "it fetches replied-to activities if we don't have them" do
30 data =
31 File.read!("test/fixtures/mastodon-post-activity.json")
32 |> Poison.decode!()
33
34 object =
35 data["object"]
36 |> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
37
38 data =
39 data
40 |> Map.put("object", object)
41
42 {:ok, returned_activity} = Transmogrifier.handle_incoming(data)
43
44 assert activity =
45 Activity.get_create_activity_by_object_ap_id(
46 "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
47 )
48
49 assert returned_activity.data["object"]["inReplyToAtomUri"] ==
50 "https://shitposter.club/notice/2827873"
51
52 assert returned_activity.data["object"]["inReplyToStatusId"] == activity.id
53 end
54
55 test "it works for incoming notices" do
56 data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
57
58 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
59
60 assert data["id"] ==
61 "http://mastodon.example.org/users/admin/statuses/99512778738411822/activity"
62
63 assert data["context"] ==
64 "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
65
66 assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
67
68 assert data["cc"] == [
69 "http://mastodon.example.org/users/admin/followers",
70 "http://localtesting.pleroma.lol/users/lain"
71 ]
72
73 assert data["actor"] == "http://mastodon.example.org/users/admin"
74
75 object = data["object"]
76 assert object["id"] == "http://mastodon.example.org/users/admin/statuses/99512778738411822"
77
78 assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
79
80 assert object["cc"] == [
81 "http://mastodon.example.org/users/admin/followers",
82 "http://localtesting.pleroma.lol/users/lain"
83 ]
84
85 assert object["actor"] == "http://mastodon.example.org/users/admin"
86 assert object["attributedTo"] == "http://mastodon.example.org/users/admin"
87
88 assert object["context"] ==
89 "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
90
91 assert object["sensitive"] == true
92
93 user = User.get_by_ap_id(object["actor"])
94
95 assert user.info["note_count"] == 1
96 end
97
98 test "it works for incoming notices with hashtags" do
99 data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!()
100
101 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
102 assert Enum.at(data["object"]["tag"], 2) == "moo"
103 end
104
105 test "it works for incoming notices with contentMap" do
106 data =
107 File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!()
108
109 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
110
111 assert data["object"]["content"] ==
112 "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
113 end
114
115 test "it works for incoming notices with to/cc not being an array (kroeg)" do
116 data = File.read!("test/fixtures/kroeg-post-activity.json") |> Poison.decode!()
117
118 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
119
120 assert data["object"]["content"] ==
121 "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
122 end
123
124 test "it works for incoming announces with actor being inlined (kroeg)" do
125 data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!()
126
127 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
128
129 assert data["actor"] == "https://puckipedia.com/"
130 end
131
132 test "it works for incoming notices with tag not being an array (kroeg)" do
133 data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
134
135 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
136
137 assert data["object"]["emoji"] == %{
138 "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
139 }
140
141 data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
142
143 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
144
145 assert "test" in data["object"]["tag"]
146 end
147
148 test "it works for incoming follow requests" do
149 user = insert(:user)
150
151 data =
152 File.read!("test/fixtures/mastodon-follow-activity.json")
153 |> Poison.decode!()
154 |> Map.put("object", user.ap_id)
155
156 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
157
158 assert data["actor"] == "http://mastodon.example.org/users/admin"
159 assert data["type"] == "Follow"
160 assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
161 assert User.following?(User.get_by_ap_id(data["actor"]), user)
162 end
163
164 test "it works for incoming follow requests from hubzilla" do
165 user = insert(:user)
166
167 data =
168 File.read!("test/fixtures/hubzilla-follow-activity.json")
169 |> Poison.decode!()
170 |> Map.put("object", user.ap_id)
171 |> Utils.normalize_params()
172
173 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
174
175 assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
176 assert data["type"] == "Follow"
177 assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
178 assert User.following?(User.get_by_ap_id(data["actor"]), user)
179 end
180
181 test "it works for incoming likes" do
182 user = insert(:user)
183 {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
184
185 data =
186 File.read!("test/fixtures/mastodon-like.json")
187 |> Poison.decode!()
188 |> Map.put("object", activity.data["object"]["id"])
189
190 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
191
192 assert data["actor"] == "http://mastodon.example.org/users/admin"
193 assert data["type"] == "Like"
194 assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
195 assert data["object"] == activity.data["object"]["id"]
196 end
197
198 test "it returns an error for incoming unlikes wihout a like activity" do
199 user = insert(:user)
200 {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
201
202 data =
203 File.read!("test/fixtures/mastodon-undo-like.json")
204 |> Poison.decode!()
205 |> Map.put("object", activity.data["object"]["id"])
206
207 assert Transmogrifier.handle_incoming(data) == :error
208 end
209
210 test "it works for incoming unlikes with an existing like activity" do
211 user = insert(:user)
212 {:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
213
214 like_data =
215 File.read!("test/fixtures/mastodon-like.json")
216 |> Poison.decode!()
217 |> Map.put("object", activity.data["object"]["id"])
218
219 {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
220
221 data =
222 File.read!("test/fixtures/mastodon-undo-like.json")
223 |> Poison.decode!()
224 |> Map.put("object", like_data)
225 |> Map.put("actor", like_data["actor"])
226
227 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
228
229 assert data["actor"] == "http://mastodon.example.org/users/admin"
230 assert data["type"] == "Undo"
231 assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
232 assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
233 end
234
235 test "it works for incoming announces" do
236 data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!()
237
238 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
239
240 assert data["actor"] == "http://mastodon.example.org/users/admin"
241 assert data["type"] == "Announce"
242
243 assert data["id"] ==
244 "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
245
246 assert data["object"] ==
247 "http://mastodon.example.org/users/admin/statuses/99541947525187367"
248
249 assert Activity.get_create_activity_by_object_ap_id(data["object"])
250 end
251
252 test "it works for incoming announces with an existing activity" do
253 user = insert(:user)
254 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
255
256 data =
257 File.read!("test/fixtures/mastodon-announce.json")
258 |> Poison.decode!()
259 |> Map.put("object", activity.data["object"]["id"])
260
261 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
262
263 assert data["actor"] == "http://mastodon.example.org/users/admin"
264 assert data["type"] == "Announce"
265
266 assert data["id"] ==
267 "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
268
269 assert data["object"] == activity.data["object"]["id"]
270
271 assert Activity.get_create_activity_by_object_ap_id(data["object"]).id == activity.id
272 end
273
274 test "it works for incoming update activities" do
275 data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
276
277 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
278 update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
279
280 object =
281 update_data["object"]
282 |> Map.put("actor", data["actor"])
283 |> Map.put("id", data["actor"])
284
285 update_data =
286 update_data
287 |> Map.put("actor", data["actor"])
288 |> Map.put("object", object)
289
290 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
291
292 user = User.get_cached_by_ap_id(data["actor"])
293 assert user.name == "gargle"
294
295 assert user.avatar["url"] == [
296 %{
297 "href" =>
298 "https://cd.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
299 }
300 ]
301
302 assert user.info["banner"]["url"] == [
303 %{
304 "href" =>
305 "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
306 }
307 ]
308
309 assert user.bio == "<p>Some bio</p>"
310 end
311
312 test "it works for incoming update activities which lock the account" do
313 data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
314
315 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
316 update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
317
318 object =
319 update_data["object"]
320 |> Map.put("actor", data["actor"])
321 |> Map.put("id", data["actor"])
322 |> Map.put("manuallyApprovesFollowers", true)
323
324 update_data =
325 update_data
326 |> Map.put("actor", data["actor"])
327 |> Map.put("object", object)
328
329 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
330
331 user = User.get_cached_by_ap_id(data["actor"])
332 assert user.info["locked"] == true
333 end
334
335 test "it works for incoming deletes" do
336 activity = insert(:note_activity)
337
338 data =
339 File.read!("test/fixtures/mastodon-delete.json")
340 |> Poison.decode!()
341
342 object =
343 data["object"]
344 |> Map.put("id", activity.data["object"]["id"])
345
346 data =
347 data
348 |> Map.put("object", object)
349 |> Map.put("actor", activity.data["actor"])
350
351 {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
352
353 refute Repo.get(Activity, activity.id)
354 end
355
356 test "it works for incoming unannounces with an existing notice" do
357 user = insert(:user)
358 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
359
360 announce_data =
361 File.read!("test/fixtures/mastodon-announce.json")
362 |> Poison.decode!()
363 |> Map.put("object", activity.data["object"]["id"])
364
365 {:ok, %Activity{data: announce_data, local: false}} =
366 Transmogrifier.handle_incoming(announce_data)
367
368 data =
369 File.read!("test/fixtures/mastodon-undo-announce.json")
370 |> Poison.decode!()
371 |> Map.put("object", announce_data)
372 |> Map.put("actor", announce_data["actor"])
373
374 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
375
376 assert data["type"] == "Undo"
377 assert data["object"]["type"] == "Announce"
378 assert data["object"]["object"] == activity.data["object"]["id"]
379
380 assert data["object"]["id"] ==
381 "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
382 end
383
384 test "it works for incomming unfollows with an existing follow" do
385 user = insert(:user)
386
387 follow_data =
388 File.read!("test/fixtures/mastodon-follow-activity.json")
389 |> Poison.decode!()
390 |> Map.put("object", user.ap_id)
391
392 {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
393
394 data =
395 File.read!("test/fixtures/mastodon-unfollow-activity.json")
396 |> Poison.decode!()
397 |> Map.put("object", follow_data)
398
399 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
400
401 assert data["type"] == "Undo"
402 assert data["object"]["type"] == "Follow"
403 assert data["object"]["object"] == user.ap_id
404 assert data["actor"] == "http://mastodon.example.org/users/admin"
405
406 refute User.following?(User.get_by_ap_id(data["actor"]), user)
407 end
408
409 test "it works for incoming blocks" do
410 user = insert(:user)
411
412 data =
413 File.read!("test/fixtures/mastodon-block-activity.json")
414 |> Poison.decode!()
415 |> Map.put("object", user.ap_id)
416
417 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
418
419 assert data["type"] == "Block"
420 assert data["object"] == user.ap_id
421 assert data["actor"] == "http://mastodon.example.org/users/admin"
422
423 blocker = User.get_by_ap_id(data["actor"])
424
425 assert User.blocks?(blocker, user)
426 end
427
428 test "incoming blocks successfully tear down any follow relationship" do
429 blocker = insert(:user)
430 blocked = insert(:user)
431
432 data =
433 File.read!("test/fixtures/mastodon-block-activity.json")
434 |> Poison.decode!()
435 |> Map.put("object", blocked.ap_id)
436 |> Map.put("actor", blocker.ap_id)
437
438 {:ok, blocker} = User.follow(blocker, blocked)
439 {:ok, blocked} = User.follow(blocked, blocker)
440
441 assert User.following?(blocker, blocked)
442 assert User.following?(blocked, blocker)
443
444 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
445
446 assert data["type"] == "Block"
447 assert data["object"] == blocked.ap_id
448 assert data["actor"] == blocker.ap_id
449
450 blocker = User.get_by_ap_id(data["actor"])
451 blocked = User.get_by_ap_id(data["object"])
452
453 assert User.blocks?(blocker, blocked)
454
455 refute User.following?(blocker, blocked)
456 refute User.following?(blocked, blocker)
457 end
458
459 test "it works for incoming unblocks with an existing block" do
460 user = insert(:user)
461
462 block_data =
463 File.read!("test/fixtures/mastodon-block-activity.json")
464 |> Poison.decode!()
465 |> Map.put("object", user.ap_id)
466
467 {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
468
469 data =
470 File.read!("test/fixtures/mastodon-unblock-activity.json")
471 |> Poison.decode!()
472 |> Map.put("object", block_data)
473
474 {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
475 assert data["type"] == "Undo"
476 assert data["object"]["type"] == "Block"
477 assert data["object"]["object"] == user.ap_id
478 assert data["actor"] == "http://mastodon.example.org/users/admin"
479
480 blocker = User.get_by_ap_id(data["actor"])
481
482 refute User.blocks?(blocker, user)
483 end
484
485 test "it works for incoming accepts which were pre-accepted" do
486 follower = insert(:user)
487 followed = insert(:user)
488
489 {:ok, follower} = User.follow(follower, followed)
490 assert User.following?(follower, followed) == true
491
492 {:ok, follow_activity} = ActivityPub.follow(follower, followed)
493
494 accept_data =
495 File.read!("test/fixtures/mastodon-accept-activity.json")
496 |> Poison.decode!()
497 |> Map.put("actor", followed.ap_id)
498
499 object =
500 accept_data["object"]
501 |> Map.put("actor", follower.ap_id)
502 |> Map.put("id", follow_activity.data["id"])
503
504 accept_data = Map.put(accept_data, "object", object)
505
506 {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
507 refute activity.local
508
509 assert activity.data["object"] == follow_activity.data["id"]
510
511 follower = Repo.get(User, follower.id)
512
513 assert User.following?(follower, followed) == true
514 end
515
516 test "it works for incoming accepts which were orphaned" do
517 follower = insert(:user)
518 followed = insert(:user, %{info: %{"locked" => true}})
519
520 {:ok, follow_activity} = ActivityPub.follow(follower, followed)
521
522 accept_data =
523 File.read!("test/fixtures/mastodon-accept-activity.json")
524 |> Poison.decode!()
525 |> Map.put("actor", followed.ap_id)
526
527 accept_data =
528 Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
529
530 {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
531 assert activity.data["object"] == follow_activity.data["id"]
532
533 follower = Repo.get(User, follower.id)
534
535 assert User.following?(follower, followed) == true
536 end
537
538 test "it works for incoming accepts which are referenced by IRI only" do
539 follower = insert(:user)
540 followed = insert(:user, %{info: %{"locked" => true}})
541
542 {:ok, follow_activity} = ActivityPub.follow(follower, followed)
543
544 accept_data =
545 File.read!("test/fixtures/mastodon-accept-activity.json")
546 |> Poison.decode!()
547 |> Map.put("actor", followed.ap_id)
548 |> Map.put("object", follow_activity.data["id"])
549
550 {:ok, activity} = Transmogrifier.handle_incoming(accept_data)
551 assert activity.data["object"] == follow_activity.data["id"]
552
553 follower = Repo.get(User, follower.id)
554
555 assert User.following?(follower, followed) == true
556 end
557
558 test "it fails for incoming accepts which cannot be correlated" do
559 follower = insert(:user)
560 followed = insert(:user, %{info: %{"locked" => true}})
561
562 accept_data =
563 File.read!("test/fixtures/mastodon-accept-activity.json")
564 |> Poison.decode!()
565 |> Map.put("actor", followed.ap_id)
566
567 accept_data =
568 Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
569
570 :error = Transmogrifier.handle_incoming(accept_data)
571
572 follower = Repo.get(User, follower.id)
573
574 refute User.following?(follower, followed) == true
575 end
576
577 test "it fails for incoming rejects which cannot be correlated" do
578 follower = insert(:user)
579 followed = insert(:user, %{info: %{"locked" => true}})
580
581 accept_data =
582 File.read!("test/fixtures/mastodon-reject-activity.json")
583 |> Poison.decode!()
584 |> Map.put("actor", followed.ap_id)
585
586 accept_data =
587 Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id))
588
589 :error = Transmogrifier.handle_incoming(accept_data)
590
591 follower = Repo.get(User, follower.id)
592
593 refute User.following?(follower, followed) == true
594 end
595
596 test "it works for incoming rejects which are orphaned" do
597 follower = insert(:user)
598 followed = insert(:user, %{info: %{"locked" => true}})
599
600 {:ok, follower} = User.follow(follower, followed)
601 {:ok, _follow_activity} = ActivityPub.follow(follower, followed)
602
603 assert User.following?(follower, followed) == true
604
605 reject_data =
606 File.read!("test/fixtures/mastodon-reject-activity.json")
607 |> Poison.decode!()
608 |> Map.put("actor", followed.ap_id)
609
610 reject_data =
611 Map.put(reject_data, "object", Map.put(reject_data["object"], "actor", follower.ap_id))
612
613 {:ok, activity} = Transmogrifier.handle_incoming(reject_data)
614 refute activity.local
615
616 follower = Repo.get(User, follower.id)
617
618 assert User.following?(follower, followed) == false
619 end
620
621 test "it works for incoming rejects which are referenced by IRI only" do
622 follower = insert(:user)
623 followed = insert(:user, %{info: %{"locked" => true}})
624
625 {:ok, follower} = User.follow(follower, followed)
626 {:ok, follow_activity} = ActivityPub.follow(follower, followed)
627
628 assert User.following?(follower, followed) == true
629
630 reject_data =
631 File.read!("test/fixtures/mastodon-reject-activity.json")
632 |> Poison.decode!()
633 |> Map.put("actor", followed.ap_id)
634 |> Map.put("object", follow_activity.data["id"])
635
636 {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data)
637
638 follower = Repo.get(User, follower.id)
639
640 assert User.following?(follower, followed) == false
641 end
642
643 test "it rejects activities without a valid ID" do
644 user = insert(:user)
645
646 data =
647 File.read!("test/fixtures/mastodon-follow-activity.json")
648 |> Poison.decode!()
649 |> Map.put("object", user.ap_id)
650 |> Map.put("id", "")
651
652 :error = Transmogrifier.handle_incoming(data)
653 end
654 end
655
656 describe "prepare outgoing" do
657 test "it turns mentions into tags" do
658 user = insert(:user)
659 other_user = insert(:user)
660
661 {:ok, activity} =
662 CommonAPI.post(user, %{"status" => "hey, @#{other_user.nickname}, how are ya? #2hu"})
663
664 {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
665 object = modified["object"]
666
667 expected_mention = %{
668 "href" => other_user.ap_id,
669 "name" => "@#{other_user.nickname}",
670 "type" => "Mention"
671 }
672
673 expected_tag = %{
674 "href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
675 "type" => "Hashtag",
676 "name" => "#2hu"
677 }
678
679 assert Enum.member?(object["tag"], expected_tag)
680 assert Enum.member?(object["tag"], expected_mention)
681 end
682
683 test "it adds the sensitive property" do
684 user = insert(:user)
685
686 {:ok, activity} = CommonAPI.post(user, %{"status" => "#nsfw hey"})
687 {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
688
689 assert modified["object"]["sensitive"]
690 end
691
692 test "it adds the json-ld context and the conversation property" do
693 user = insert(:user)
694
695 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
696 {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
697
698 assert modified["@context"] == "https://www.w3.org/ns/activitystreams"
699 assert modified["object"]["conversation"] == modified["context"]
700 end
701
702 test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
703 user = insert(:user)
704
705 {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
706 {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
707
708 assert modified["object"]["actor"] == modified["object"]["attributedTo"]
709 end
710
711 test "it translates ostatus IDs to external URLs" do
712 incoming = File.read!("test/fixtures/incoming_note_activity.xml")
713 {:ok, [referent_activity]} = OStatus.handle_incoming(incoming)
714
715 user = insert(:user)
716
717 {:ok, activity, _} = CommonAPI.favorite(referent_activity.id, user)
718 {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
719
720 assert modified["object"] == "http://gs.example.org:4040/index.php/notice/29"
721 end
722
723 test "it translates ostatus reply_to IDs to external URLs" do
724 incoming = File.read!("test/fixtures/incoming_note_activity.xml")
725 {:ok, [referred_activity]} = OStatus.handle_incoming(incoming)
726
727 user = insert(:user)
728
729 {:ok, activity} =
730 CommonAPI.post(user, %{"status" => "HI!", "in_reply_to_status_id" => referred_activity.id})
731
732 {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
733
734 assert modified["object"]["inReplyTo"] == "http://gs.example.org:4040/index.php/notice/29"
735 end
736 end
737
738 describe "user upgrade" do
739 test "it upgrades a user to activitypub" do
740 user =
741 insert(:user, %{
742 nickname: "rye@niu.moe",
743 local: false,
744 ap_id: "https://niu.moe/users/rye",
745 follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
746 })
747
748 user_two = insert(:user, %{following: [user.follower_address]})
749
750 {:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
751 {:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"})
752 assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
753
754 user = Repo.get(User, user.id)
755 assert user.info["note_count"] == 1
756
757 {:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
758 assert user.info["ap_enabled"]
759 assert user.info["note_count"] == 1
760 assert user.follower_address == "https://niu.moe/users/rye/followers"
761
762 # Wait for the background task
763 :timer.sleep(1000)
764
765 user = Repo.get(User, user.id)
766 assert user.info["note_count"] == 1
767
768 activity = Repo.get(Activity, activity.id)
769 assert user.follower_address in activity.recipients
770
771 assert %{
772 "url" => [
773 %{
774 "href" =>
775 "https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
776 }
777 ]
778 } = user.avatar
779
780 assert %{
781 "url" => [
782 %{
783 "href" =>
784 "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
785 }
786 ]
787 } = user.info["banner"]
788
789 refute "..." in activity.recipients
790
791 unrelated_activity = Repo.get(Activity, unrelated_activity.id)
792 refute user.follower_address in unrelated_activity.recipients
793
794 user_two = Repo.get(User, user_two.id)
795 assert user.follower_address in user_two.following
796 refute "..." in user_two.following
797 end
798 end
799
800 describe "maybe_retire_websub" do
801 test "it deletes all websub client subscripitions with the user as topic" do
802 subscription = %WebsubClientSubscription{topic: "https://niu.moe/users/rye.atom"}
803 {:ok, ws} = Repo.insert(subscription)
804
805 subscription = %WebsubClientSubscription{topic: "https://niu.moe/users/pasty.atom"}
806 {:ok, ws2} = Repo.insert(subscription)
807
808 Transmogrifier.maybe_retire_websub("https://niu.moe/users/rye")
809
810 refute Repo.get(WebsubClientSubscription, ws.id)
811 assert Repo.get(WebsubClientSubscription, ws2.id)
812 end
813 end
814
815 describe "actor rewriting" do
816 test "it fixes the actor URL property to be a proper URI" do
817 data = %{
818 "url" => %{"href" => "http://example.com"}
819 }
820
821 rewritten = Transmogrifier.maybe_fix_user_object(data)
822 assert rewritten["url"] == "http://example.com"
823 end
824 end
825
826 describe "actor origin containment" do
827 test "it rejects objects with a bogus origin" do
828 {:error, _} = ActivityPub.fetch_object_from_id("https://info.pleroma.site/activity.json")
829 end
830
831 test "it rejects activities which reference objects with bogus origins" do
832 user = insert(:user, %{local: false})
833
834 data = %{
835 "@context" => "https://www.w3.org/ns/activitystreams",
836 "id" => user.ap_id <> "/activities/1234",
837 "actor" => user.ap_id,
838 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
839 "object" => "https://info.pleroma.site/activity.json",
840 "type" => "Announce"
841 }
842
843 :error = Transmogrifier.handle_incoming(data)
844 end
845 end
846 end