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