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