d9e41d356501bd1f4bf00810fb47570f2a26598c
[akkoma] / test / web / mastodon_api / mastodon_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
6 use Pleroma.Web.ConnCase
7
8 alias Pleroma.Web.TwitterAPI.TwitterAPI
9 alias Pleroma.Repo
10 alias Pleroma.User
11 alias Pleroma.Object
12 alias Pleroma.Activity
13 alias Pleroma.Notification
14 alias Pleroma.Web.OStatus
15 alias Pleroma.Web.CommonAPI
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.MastodonAPI.FilterView
18 alias Ecto.Changeset
19 import Pleroma.Factory
20 import ExUnit.CaptureLog
21 import Tesla.Mock
22
23 setup do
24 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
25 :ok
26 end
27
28 test "the home timeline", %{conn: conn} do
29 user = insert(:user)
30 following = insert(:user)
31
32 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
33
34 conn =
35 conn
36 |> assign(:user, user)
37 |> get("/api/v1/timelines/home")
38
39 assert Enum.empty?(json_response(conn, 200))
40
41 {:ok, user} = User.follow(user, following)
42
43 conn =
44 build_conn()
45 |> assign(:user, user)
46 |> get("/api/v1/timelines/home")
47
48 assert [%{"content" => "test"}] = json_response(conn, 200)
49 end
50
51 test "the public timeline", %{conn: conn} do
52 following = insert(:user)
53
54 capture_log(fn ->
55 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
56
57 {:ok, [_activity]} =
58 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
59
60 conn =
61 conn
62 |> get("/api/v1/timelines/public", %{"local" => "False"})
63
64 assert length(json_response(conn, 200)) == 2
65
66 conn =
67 build_conn()
68 |> get("/api/v1/timelines/public", %{"local" => "True"})
69
70 assert [%{"content" => "test"}] = json_response(conn, 200)
71
72 conn =
73 build_conn()
74 |> get("/api/v1/timelines/public", %{"local" => "1"})
75
76 assert [%{"content" => "test"}] = json_response(conn, 200)
77 end)
78 end
79
80 test "posting a status", %{conn: conn} do
81 user = insert(:user)
82
83 idempotency_key = "Pikachu rocks!"
84
85 conn_one =
86 conn
87 |> assign(:user, user)
88 |> put_req_header("idempotency-key", idempotency_key)
89 |> post("/api/v1/statuses", %{
90 "status" => "cofe",
91 "spoiler_text" => "2hu",
92 "sensitive" => "false"
93 })
94
95 {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
96 # Six hours
97 assert ttl > :timer.seconds(6 * 60 * 60 - 1)
98
99 assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
100 json_response(conn_one, 200)
101
102 assert Repo.get(Activity, id)
103
104 conn_two =
105 conn
106 |> assign(:user, user)
107 |> put_req_header("idempotency-key", idempotency_key)
108 |> post("/api/v1/statuses", %{
109 "status" => "cofe",
110 "spoiler_text" => "2hu",
111 "sensitive" => "false"
112 })
113
114 assert %{"id" => second_id} = json_response(conn_two, 200)
115
116 assert id == second_id
117
118 conn_three =
119 conn
120 |> assign(:user, user)
121 |> post("/api/v1/statuses", %{
122 "status" => "cofe",
123 "spoiler_text" => "2hu",
124 "sensitive" => "false"
125 })
126
127 assert %{"id" => third_id} = json_response(conn_three, 200)
128
129 refute id == third_id
130 end
131
132 test "posting a sensitive status", %{conn: conn} do
133 user = insert(:user)
134
135 conn =
136 conn
137 |> assign(:user, user)
138 |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
139
140 assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
141 assert Repo.get(Activity, id)
142 end
143
144 test "posting a status with OGP link preview", %{conn: conn} do
145 Pleroma.Config.put([:rich_media, :enabled], true)
146 user = insert(:user)
147
148 conn =
149 conn
150 |> assign(:user, user)
151 |> post("/api/v1/statuses", %{
152 "status" => "http://example.com/ogp"
153 })
154
155 assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
156 assert Repo.get(Activity, id)
157 Pleroma.Config.put([:rich_media, :enabled], false)
158 end
159
160 test "posting a direct status", %{conn: conn} do
161 user1 = insert(:user)
162 user2 = insert(:user)
163 content = "direct cofe @#{user2.nickname}"
164
165 conn =
166 conn
167 |> assign(:user, user1)
168 |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
169
170 assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200)
171 assert activity = Repo.get(Activity, id)
172 assert activity.recipients == [user2.ap_id, user1.ap_id]
173 assert activity.data["to"] == [user2.ap_id]
174 assert activity.data["cc"] == []
175 end
176
177 test "direct timeline", %{conn: conn} do
178 user_one = insert(:user)
179 user_two = insert(:user)
180
181 {:ok, user_two} = User.follow(user_two, user_one)
182
183 {:ok, direct} =
184 CommonAPI.post(user_one, %{
185 "status" => "Hi @#{user_two.nickname}!",
186 "visibility" => "direct"
187 })
188
189 {:ok, _follower_only} =
190 CommonAPI.post(user_one, %{
191 "status" => "Hi @#{user_two.nickname}!",
192 "visibility" => "private"
193 })
194
195 # Only direct should be visible here
196 res_conn =
197 conn
198 |> assign(:user, user_two)
199 |> get("api/v1/timelines/direct")
200
201 [status] = json_response(res_conn, 200)
202
203 assert %{"visibility" => "direct"} = status
204 assert status["url"] != direct.data["id"]
205
206 # User should be able to see his own direct message
207 res_conn =
208 build_conn()
209 |> assign(:user, user_one)
210 |> get("api/v1/timelines/direct")
211
212 [status] = json_response(res_conn, 200)
213
214 assert %{"visibility" => "direct"} = status
215
216 # Both should be visible here
217 res_conn =
218 conn
219 |> assign(:user, user_two)
220 |> get("api/v1/timelines/home")
221
222 [_s1, _s2] = json_response(res_conn, 200)
223
224 # Test pagination
225 Enum.each(1..20, fn _ ->
226 {:ok, _} =
227 CommonAPI.post(user_one, %{
228 "status" => "Hi @#{user_two.nickname}!",
229 "visibility" => "direct"
230 })
231 end)
232
233 res_conn =
234 conn
235 |> assign(:user, user_two)
236 |> get("api/v1/timelines/direct")
237
238 statuses = json_response(res_conn, 200)
239 assert length(statuses) == 20
240
241 res_conn =
242 conn
243 |> assign(:user, user_two)
244 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
245
246 [status] = json_response(res_conn, 200)
247
248 assert status["url"] != direct.data["id"]
249 end
250
251 test "doesn't include DMs from blocked users", %{conn: conn} do
252 blocker = insert(:user)
253 blocked = insert(:user)
254 user = insert(:user)
255 {:ok, blocker} = User.block(blocker, blocked)
256
257 {:ok, _blocked_direct} =
258 CommonAPI.post(blocked, %{
259 "status" => "Hi @#{blocker.nickname}!",
260 "visibility" => "direct"
261 })
262
263 {:ok, direct} =
264 CommonAPI.post(user, %{
265 "status" => "Hi @#{blocker.nickname}!",
266 "visibility" => "direct"
267 })
268
269 res_conn =
270 conn
271 |> assign(:user, user)
272 |> get("api/v1/timelines/direct")
273
274 [status] = json_response(res_conn, 200)
275 assert status["id"] == direct.id
276 end
277
278 test "replying to a status", %{conn: conn} do
279 user = insert(:user)
280
281 {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
282
283 conn =
284 conn
285 |> assign(:user, user)
286 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
287
288 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
289
290 activity = Repo.get(Activity, id)
291
292 assert activity.data["context"] == replied_to.data["context"]
293 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
294 end
295
296 test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
297 user = insert(:user)
298
299 conn =
300 conn
301 |> assign(:user, user)
302 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
303
304 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
305
306 activity = Repo.get(Activity, id)
307
308 assert activity
309 end
310
311 test "verify_credentials", %{conn: conn} do
312 user = insert(:user)
313
314 conn =
315 conn
316 |> assign(:user, user)
317 |> get("/api/v1/accounts/verify_credentials")
318
319 assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
320 assert id == to_string(user.id)
321 end
322
323 test "verify_credentials default scope unlisted", %{conn: conn} do
324 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
325
326 conn =
327 conn
328 |> assign(:user, user)
329 |> get("/api/v1/accounts/verify_credentials")
330
331 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
332 assert id == to_string(user.id)
333 end
334
335 test "get a status", %{conn: conn} do
336 activity = insert(:note_activity)
337
338 conn =
339 conn
340 |> get("/api/v1/statuses/#{activity.id}")
341
342 assert %{"id" => id} = json_response(conn, 200)
343 assert id == to_string(activity.id)
344 end
345
346 describe "deleting a status" do
347 test "when you created it", %{conn: conn} do
348 activity = insert(:note_activity)
349 author = User.get_by_ap_id(activity.data["actor"])
350
351 conn =
352 conn
353 |> assign(:user, author)
354 |> delete("/api/v1/statuses/#{activity.id}")
355
356 assert %{} = json_response(conn, 200)
357
358 refute Repo.get(Activity, activity.id)
359 end
360
361 test "when you didn't create it", %{conn: conn} do
362 activity = insert(:note_activity)
363 user = insert(:user)
364
365 conn =
366 conn
367 |> assign(:user, user)
368 |> delete("/api/v1/statuses/#{activity.id}")
369
370 assert %{"error" => _} = json_response(conn, 403)
371
372 assert Repo.get(Activity, activity.id) == activity
373 end
374
375 test "when you're an admin or moderator", %{conn: conn} do
376 activity1 = insert(:note_activity)
377 activity2 = insert(:note_activity)
378 admin = insert(:user, info: %{is_admin: true})
379 moderator = insert(:user, info: %{is_moderator: true})
380
381 res_conn =
382 conn
383 |> assign(:user, admin)
384 |> delete("/api/v1/statuses/#{activity1.id}")
385
386 assert %{} = json_response(res_conn, 200)
387
388 res_conn =
389 conn
390 |> assign(:user, moderator)
391 |> delete("/api/v1/statuses/#{activity2.id}")
392
393 assert %{} = json_response(res_conn, 200)
394
395 refute Repo.get(Activity, activity1.id)
396 refute Repo.get(Activity, activity2.id)
397 end
398 end
399
400 describe "filters" do
401 test "creating a filter", %{conn: conn} do
402 user = insert(:user)
403
404 filter = %Pleroma.Filter{
405 phrase: "knights",
406 context: ["home"]
407 }
408
409 conn =
410 conn
411 |> assign(:user, user)
412 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
413
414 assert response = json_response(conn, 200)
415 assert response["phrase"] == filter.phrase
416 assert response["context"] == filter.context
417 assert response["id"] != nil
418 assert response["id"] != ""
419 end
420
421 test "fetching a list of filters", %{conn: conn} do
422 user = insert(:user)
423
424 query_one = %Pleroma.Filter{
425 user_id: user.id,
426 filter_id: 1,
427 phrase: "knights",
428 context: ["home"]
429 }
430
431 query_two = %Pleroma.Filter{
432 user_id: user.id,
433 filter_id: 2,
434 phrase: "who",
435 context: ["home"]
436 }
437
438 {:ok, filter_one} = Pleroma.Filter.create(query_one)
439 {:ok, filter_two} = Pleroma.Filter.create(query_two)
440
441 response =
442 conn
443 |> assign(:user, user)
444 |> get("/api/v1/filters")
445 |> json_response(200)
446
447 assert response ==
448 render_json(
449 FilterView,
450 "filters.json",
451 filters: [filter_two, filter_one]
452 )
453 end
454
455 test "get a filter", %{conn: conn} do
456 user = insert(:user)
457
458 query = %Pleroma.Filter{
459 user_id: user.id,
460 filter_id: 2,
461 phrase: "knight",
462 context: ["home"]
463 }
464
465 {:ok, filter} = Pleroma.Filter.create(query)
466
467 conn =
468 conn
469 |> assign(:user, user)
470 |> get("/api/v1/filters/#{filter.filter_id}")
471
472 assert _response = json_response(conn, 200)
473 end
474
475 test "update a filter", %{conn: conn} do
476 user = insert(:user)
477
478 query = %Pleroma.Filter{
479 user_id: user.id,
480 filter_id: 2,
481 phrase: "knight",
482 context: ["home"]
483 }
484
485 {:ok, _filter} = Pleroma.Filter.create(query)
486
487 new = %Pleroma.Filter{
488 phrase: "nii",
489 context: ["home"]
490 }
491
492 conn =
493 conn
494 |> assign(:user, user)
495 |> put("/api/v1/filters/#{query.filter_id}", %{
496 phrase: new.phrase,
497 context: new.context
498 })
499
500 assert response = json_response(conn, 200)
501 assert response["phrase"] == new.phrase
502 assert response["context"] == new.context
503 end
504
505 test "delete a filter", %{conn: conn} do
506 user = insert(:user)
507
508 query = %Pleroma.Filter{
509 user_id: user.id,
510 filter_id: 2,
511 phrase: "knight",
512 context: ["home"]
513 }
514
515 {:ok, filter} = Pleroma.Filter.create(query)
516
517 conn =
518 conn
519 |> assign(:user, user)
520 |> delete("/api/v1/filters/#{filter.filter_id}")
521
522 assert response = json_response(conn, 200)
523 assert response == %{}
524 end
525 end
526
527 describe "lists" do
528 test "creating a list", %{conn: conn} do
529 user = insert(:user)
530
531 conn =
532 conn
533 |> assign(:user, user)
534 |> post("/api/v1/lists", %{"title" => "cuties"})
535
536 assert %{"title" => title} = json_response(conn, 200)
537 assert title == "cuties"
538 end
539
540 test "adding users to a list", %{conn: conn} do
541 user = insert(:user)
542 other_user = insert(:user)
543 {:ok, list} = Pleroma.List.create("name", user)
544
545 conn =
546 conn
547 |> assign(:user, user)
548 |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
549
550 assert %{} == json_response(conn, 200)
551 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
552 assert following == [other_user.follower_address]
553 end
554
555 test "removing users from a list", %{conn: conn} do
556 user = insert(:user)
557 other_user = insert(:user)
558 third_user = insert(:user)
559 {:ok, list} = Pleroma.List.create("name", user)
560 {:ok, list} = Pleroma.List.follow(list, other_user)
561 {:ok, list} = Pleroma.List.follow(list, third_user)
562
563 conn =
564 conn
565 |> assign(:user, user)
566 |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
567
568 assert %{} == json_response(conn, 200)
569 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
570 assert following == [third_user.follower_address]
571 end
572
573 test "listing users in a list", %{conn: conn} do
574 user = insert(:user)
575 other_user = insert(:user)
576 {:ok, list} = Pleroma.List.create("name", user)
577 {:ok, list} = Pleroma.List.follow(list, other_user)
578
579 conn =
580 conn
581 |> assign(:user, user)
582 |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
583
584 assert [%{"id" => id}] = json_response(conn, 200)
585 assert id == to_string(other_user.id)
586 end
587
588 test "retrieving a list", %{conn: conn} do
589 user = insert(:user)
590 {:ok, list} = Pleroma.List.create("name", user)
591
592 conn =
593 conn
594 |> assign(:user, user)
595 |> get("/api/v1/lists/#{list.id}")
596
597 assert %{"id" => id} = json_response(conn, 200)
598 assert id == to_string(list.id)
599 end
600
601 test "renaming a list", %{conn: conn} do
602 user = insert(:user)
603 {:ok, list} = Pleroma.List.create("name", user)
604
605 conn =
606 conn
607 |> assign(:user, user)
608 |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
609
610 assert %{"title" => name} = json_response(conn, 200)
611 assert name == "newname"
612 end
613
614 test "deleting a list", %{conn: conn} do
615 user = insert(:user)
616 {:ok, list} = Pleroma.List.create("name", user)
617
618 conn =
619 conn
620 |> assign(:user, user)
621 |> delete("/api/v1/lists/#{list.id}")
622
623 assert %{} = json_response(conn, 200)
624 assert is_nil(Repo.get(Pleroma.List, list.id))
625 end
626
627 test "list timeline", %{conn: conn} do
628 user = insert(:user)
629 other_user = insert(:user)
630 {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
631 {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
632 {:ok, list} = Pleroma.List.create("name", user)
633 {:ok, list} = Pleroma.List.follow(list, other_user)
634
635 conn =
636 conn
637 |> assign(:user, user)
638 |> get("/api/v1/timelines/list/#{list.id}")
639
640 assert [%{"id" => id}] = json_response(conn, 200)
641
642 assert id == to_string(activity_two.id)
643 end
644
645 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
646 user = insert(:user)
647 other_user = insert(:user)
648 {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
649
650 {:ok, _activity_two} =
651 TwitterAPI.create_status(other_user, %{
652 "status" => "Marisa is cute.",
653 "visibility" => "private"
654 })
655
656 {:ok, list} = Pleroma.List.create("name", user)
657 {:ok, list} = Pleroma.List.follow(list, other_user)
658
659 conn =
660 conn
661 |> assign(:user, user)
662 |> get("/api/v1/timelines/list/#{list.id}")
663
664 assert [%{"id" => id}] = json_response(conn, 200)
665
666 assert id == to_string(activity_one.id)
667 end
668 end
669
670 describe "notifications" do
671 test "list of notifications", %{conn: conn} do
672 user = insert(:user)
673 other_user = insert(:user)
674
675 {:ok, activity} =
676 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
677
678 {:ok, [_notification]} = Notification.create_notifications(activity)
679
680 conn =
681 conn
682 |> assign(:user, user)
683 |> get("/api/v1/notifications")
684
685 expected_response =
686 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
687 user.ap_id
688 }\">@<span>#{user.nickname}</span></a></span>"
689
690 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
691 assert response == expected_response
692 end
693
694 test "getting a single notification", %{conn: conn} do
695 user = insert(:user)
696 other_user = insert(:user)
697
698 {:ok, activity} =
699 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
700
701 {:ok, [notification]} = Notification.create_notifications(activity)
702
703 conn =
704 conn
705 |> assign(:user, user)
706 |> get("/api/v1/notifications/#{notification.id}")
707
708 expected_response =
709 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
710 user.ap_id
711 }\">@<span>#{user.nickname}</span></a></span>"
712
713 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
714 assert response == expected_response
715 end
716
717 test "dismissing a single notification", %{conn: conn} do
718 user = insert(:user)
719 other_user = insert(:user)
720
721 {:ok, activity} =
722 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
723
724 {:ok, [notification]} = Notification.create_notifications(activity)
725
726 conn =
727 conn
728 |> assign(:user, user)
729 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
730
731 assert %{} = json_response(conn, 200)
732 end
733
734 test "clearing all notifications", %{conn: conn} do
735 user = insert(:user)
736 other_user = insert(:user)
737
738 {:ok, activity} =
739 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
740
741 {:ok, [_notification]} = Notification.create_notifications(activity)
742
743 conn =
744 conn
745 |> assign(:user, user)
746 |> post("/api/v1/notifications/clear")
747
748 assert %{} = json_response(conn, 200)
749
750 conn =
751 build_conn()
752 |> assign(:user, user)
753 |> get("/api/v1/notifications")
754
755 assert all = json_response(conn, 200)
756 assert all == []
757 end
758 end
759
760 describe "reblogging" do
761 test "reblogs and returns the reblogged status", %{conn: conn} do
762 activity = insert(:note_activity)
763 user = insert(:user)
764
765 conn =
766 conn
767 |> assign(:user, user)
768 |> post("/api/v1/statuses/#{activity.id}/reblog")
769
770 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
771 json_response(conn, 200)
772
773 assert to_string(activity.id) == id
774 end
775 end
776
777 describe "unreblogging" do
778 test "unreblogs and returns the unreblogged status", %{conn: conn} do
779 activity = insert(:note_activity)
780 user = insert(:user)
781
782 {:ok, _, _} = CommonAPI.repeat(activity.id, user)
783
784 conn =
785 conn
786 |> assign(:user, user)
787 |> post("/api/v1/statuses/#{activity.id}/unreblog")
788
789 assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
790
791 assert to_string(activity.id) == id
792 end
793 end
794
795 describe "favoriting" do
796 test "favs a status and returns it", %{conn: conn} do
797 activity = insert(:note_activity)
798 user = insert(:user)
799
800 conn =
801 conn
802 |> assign(:user, user)
803 |> post("/api/v1/statuses/#{activity.id}/favourite")
804
805 assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
806 json_response(conn, 200)
807
808 assert to_string(activity.id) == id
809 end
810
811 test "returns 500 for a wrong id", %{conn: conn} do
812 user = insert(:user)
813
814 resp =
815 conn
816 |> assign(:user, user)
817 |> post("/api/v1/statuses/1/favourite")
818 |> json_response(500)
819
820 assert resp == "Something went wrong"
821 end
822 end
823
824 describe "unfavoriting" do
825 test "unfavorites a status and returns it", %{conn: conn} do
826 activity = insert(:note_activity)
827 user = insert(:user)
828
829 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
830
831 conn =
832 conn
833 |> assign(:user, user)
834 |> post("/api/v1/statuses/#{activity.id}/unfavourite")
835
836 assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
837 json_response(conn, 200)
838
839 assert to_string(activity.id) == id
840 end
841 end
842
843 describe "user timelines" do
844 test "gets a users statuses", %{conn: conn} do
845 user_one = insert(:user)
846 user_two = insert(:user)
847 user_three = insert(:user)
848
849 {:ok, user_three} = User.follow(user_three, user_one)
850
851 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
852
853 {:ok, direct_activity} =
854 CommonAPI.post(user_one, %{
855 "status" => "Hi, @#{user_two.nickname}.",
856 "visibility" => "direct"
857 })
858
859 {:ok, private_activity} =
860 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
861
862 resp =
863 conn
864 |> get("/api/v1/accounts/#{user_one.id}/statuses")
865
866 assert [%{"id" => id}] = json_response(resp, 200)
867 assert id == to_string(activity.id)
868
869 resp =
870 conn
871 |> assign(:user, user_two)
872 |> get("/api/v1/accounts/#{user_one.id}/statuses")
873
874 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
875 assert id_one == to_string(direct_activity.id)
876 assert id_two == to_string(activity.id)
877
878 resp =
879 conn
880 |> assign(:user, user_three)
881 |> get("/api/v1/accounts/#{user_one.id}/statuses")
882
883 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
884 assert id_one == to_string(private_activity.id)
885 assert id_two == to_string(activity.id)
886 end
887
888 test "unimplemented pinned statuses feature", %{conn: conn} do
889 note = insert(:note_activity)
890 user = User.get_by_ap_id(note.data["actor"])
891
892 conn =
893 conn
894 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
895
896 assert json_response(conn, 200) == []
897 end
898
899 test "gets an users media", %{conn: conn} do
900 note = insert(:note_activity)
901 user = User.get_by_ap_id(note.data["actor"])
902
903 file = %Plug.Upload{
904 content_type: "image/jpg",
905 path: Path.absname("test/fixtures/image.jpg"),
906 filename: "an_image.jpg"
907 }
908
909 media =
910 TwitterAPI.upload(file, user, "json")
911 |> Poison.decode!()
912
913 {:ok, image_post} =
914 TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
915
916 conn =
917 conn
918 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
919
920 assert [%{"id" => id}] = json_response(conn, 200)
921 assert id == to_string(image_post.id)
922
923 conn =
924 build_conn()
925 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
926
927 assert [%{"id" => id}] = json_response(conn, 200)
928 assert id == to_string(image_post.id)
929 end
930
931 test "gets a user's statuses without reblogs", %{conn: conn} do
932 user = insert(:user)
933 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
934 {:ok, _, _} = CommonAPI.repeat(post.id, user)
935
936 conn =
937 conn
938 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
939
940 assert [%{"id" => id}] = json_response(conn, 200)
941 assert id == to_string(post.id)
942
943 conn =
944 conn
945 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
946
947 assert [%{"id" => id}] = json_response(conn, 200)
948 assert id == to_string(post.id)
949 end
950 end
951
952 describe "user relationships" do
953 test "returns the relationships for the current user", %{conn: conn} do
954 user = insert(:user)
955 other_user = insert(:user)
956 {:ok, user} = User.follow(user, other_user)
957
958 conn =
959 conn
960 |> assign(:user, user)
961 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
962
963 assert [relationship] = json_response(conn, 200)
964
965 assert to_string(other_user.id) == relationship["id"]
966 end
967 end
968
969 describe "locked accounts" do
970 test "/api/v1/follow_requests works" do
971 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
972 other_user = insert(:user)
973
974 {:ok, _activity} = ActivityPub.follow(other_user, user)
975
976 user = Repo.get(User, user.id)
977 other_user = Repo.get(User, other_user.id)
978
979 assert User.following?(other_user, user) == false
980
981 conn =
982 build_conn()
983 |> assign(:user, user)
984 |> get("/api/v1/follow_requests")
985
986 assert [relationship] = json_response(conn, 200)
987 assert to_string(other_user.id) == relationship["id"]
988 end
989
990 test "/api/v1/follow_requests/:id/authorize works" do
991 user = insert(:user, %{info: %User.Info{locked: true}})
992 other_user = insert(:user)
993
994 {:ok, _activity} = ActivityPub.follow(other_user, user)
995
996 user = Repo.get(User, user.id)
997 other_user = Repo.get(User, other_user.id)
998
999 assert User.following?(other_user, user) == false
1000
1001 conn =
1002 build_conn()
1003 |> assign(:user, user)
1004 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
1005
1006 assert relationship = json_response(conn, 200)
1007 assert to_string(other_user.id) == relationship["id"]
1008
1009 user = Repo.get(User, user.id)
1010 other_user = Repo.get(User, other_user.id)
1011
1012 assert User.following?(other_user, user) == true
1013 end
1014
1015 test "verify_credentials", %{conn: conn} do
1016 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
1017
1018 conn =
1019 conn
1020 |> assign(:user, user)
1021 |> get("/api/v1/accounts/verify_credentials")
1022
1023 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
1024 assert id == to_string(user.id)
1025 end
1026
1027 test "/api/v1/follow_requests/:id/reject works" do
1028 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1029 other_user = insert(:user)
1030
1031 {:ok, _activity} = ActivityPub.follow(other_user, user)
1032
1033 user = Repo.get(User, user.id)
1034
1035 conn =
1036 build_conn()
1037 |> assign(:user, user)
1038 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
1039
1040 assert relationship = json_response(conn, 200)
1041 assert to_string(other_user.id) == relationship["id"]
1042
1043 user = Repo.get(User, user.id)
1044 other_user = Repo.get(User, other_user.id)
1045
1046 assert User.following?(other_user, user) == false
1047 end
1048 end
1049
1050 test "account fetching", %{conn: conn} do
1051 user = insert(:user)
1052
1053 conn =
1054 conn
1055 |> get("/api/v1/accounts/#{user.id}")
1056
1057 assert %{"id" => id} = json_response(conn, 200)
1058 assert id == to_string(user.id)
1059
1060 conn =
1061 build_conn()
1062 |> get("/api/v1/accounts/-1")
1063
1064 assert %{"error" => "Can't find user"} = json_response(conn, 404)
1065 end
1066
1067 test "media upload", %{conn: conn} do
1068 file = %Plug.Upload{
1069 content_type: "image/jpg",
1070 path: Path.absname("test/fixtures/image.jpg"),
1071 filename: "an_image.jpg"
1072 }
1073
1074 desc = "Description of the image"
1075
1076 user = insert(:user)
1077
1078 conn =
1079 conn
1080 |> assign(:user, user)
1081 |> post("/api/v1/media", %{"file" => file, "description" => desc})
1082
1083 assert media = json_response(conn, 200)
1084
1085 assert media["type"] == "image"
1086 assert media["description"] == desc
1087 assert media["id"]
1088
1089 object = Repo.get(Object, media["id"])
1090 assert object.data["actor"] == User.ap_id(user)
1091 end
1092
1093 test "hashtag timeline", %{conn: conn} do
1094 following = insert(:user)
1095
1096 capture_log(fn ->
1097 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
1098
1099 {:ok, [_activity]} =
1100 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
1101
1102 nconn =
1103 conn
1104 |> get("/api/v1/timelines/tag/2hu")
1105
1106 assert [%{"id" => id}] = json_response(nconn, 200)
1107
1108 assert id == to_string(activity.id)
1109
1110 # works for different capitalization too
1111 nconn =
1112 conn
1113 |> get("/api/v1/timelines/tag/2HU")
1114
1115 assert [%{"id" => id}] = json_response(nconn, 200)
1116
1117 assert id == to_string(activity.id)
1118 end)
1119 end
1120
1121 test "multi-hashtag timeline", %{conn: conn} do
1122 user = insert(:user)
1123
1124 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
1125 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
1126 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
1127
1128 any_test =
1129 conn
1130 |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
1131
1132 [status_none, status_test1, status_test] = json_response(any_test, 200)
1133
1134 assert to_string(activity_test.id) == status_test["id"]
1135 assert to_string(activity_test1.id) == status_test1["id"]
1136 assert to_string(activity_none.id) == status_none["id"]
1137
1138 restricted_test =
1139 conn
1140 |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
1141
1142 assert [status_test1] == json_response(restricted_test, 200)
1143
1144 all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
1145
1146 assert [status_none] == json_response(all_test, 200)
1147 end
1148
1149 test "getting followers", %{conn: conn} do
1150 user = insert(:user)
1151 other_user = insert(:user)
1152 {:ok, user} = User.follow(user, other_user)
1153
1154 conn =
1155 conn
1156 |> get("/api/v1/accounts/#{other_user.id}/followers")
1157
1158 assert [%{"id" => id}] = json_response(conn, 200)
1159 assert id == to_string(user.id)
1160 end
1161
1162 test "getting followers, hide_followers", %{conn: conn} do
1163 user = insert(:user)
1164 other_user = insert(:user, %{info: %{hide_followers: true}})
1165 {:ok, _user} = User.follow(user, other_user)
1166
1167 conn =
1168 conn
1169 |> get("/api/v1/accounts/#{other_user.id}/followers")
1170
1171 assert [] == json_response(conn, 200)
1172 end
1173
1174 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
1175 user = insert(:user)
1176 other_user = insert(:user, %{info: %{hide_followers: true}})
1177 {:ok, _user} = User.follow(user, other_user)
1178
1179 conn =
1180 conn
1181 |> assign(:user, other_user)
1182 |> get("/api/v1/accounts/#{other_user.id}/followers")
1183
1184 refute [] == json_response(conn, 200)
1185 end
1186
1187 test "getting followers, pagination", %{conn: conn} do
1188 user = insert(:user)
1189 follower1 = insert(:user)
1190 follower2 = insert(:user)
1191 follower3 = insert(:user)
1192 {:ok, _} = User.follow(follower1, user)
1193 {:ok, _} = User.follow(follower2, user)
1194 {:ok, _} = User.follow(follower3, user)
1195
1196 conn =
1197 conn
1198 |> assign(:user, user)
1199
1200 res_conn =
1201 conn
1202 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
1203
1204 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1205 assert id3 == follower3.id
1206 assert id2 == follower2.id
1207
1208 res_conn =
1209 conn
1210 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
1211
1212 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1213 assert id2 == follower2.id
1214 assert id1 == follower1.id
1215
1216 res_conn =
1217 conn
1218 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
1219
1220 assert [%{"id" => id2}] = json_response(res_conn, 200)
1221 assert id2 == follower2.id
1222
1223 assert [link_header] = get_resp_header(res_conn, "link")
1224 assert link_header =~ ~r/since_id=#{follower2.id}/
1225 assert link_header =~ ~r/max_id=#{follower2.id}/
1226 end
1227
1228 test "getting following", %{conn: conn} do
1229 user = insert(:user)
1230 other_user = insert(:user)
1231 {:ok, user} = User.follow(user, other_user)
1232
1233 conn =
1234 conn
1235 |> get("/api/v1/accounts/#{user.id}/following")
1236
1237 assert [%{"id" => id}] = json_response(conn, 200)
1238 assert id == to_string(other_user.id)
1239 end
1240
1241 test "getting following, hide_follows", %{conn: conn} do
1242 user = insert(:user, %{info: %{hide_follows: true}})
1243 other_user = insert(:user)
1244 {:ok, user} = User.follow(user, other_user)
1245
1246 conn =
1247 conn
1248 |> get("/api/v1/accounts/#{user.id}/following")
1249
1250 assert [] == json_response(conn, 200)
1251 end
1252
1253 test "getting following, hide_follows, same user requesting", %{conn: conn} do
1254 user = insert(:user, %{info: %{hide_follows: true}})
1255 other_user = insert(:user)
1256 {:ok, user} = User.follow(user, other_user)
1257
1258 conn =
1259 conn
1260 |> assign(:user, user)
1261 |> get("/api/v1/accounts/#{user.id}/following")
1262
1263 refute [] == json_response(conn, 200)
1264 end
1265
1266 test "getting following, pagination", %{conn: conn} do
1267 user = insert(:user)
1268 following1 = insert(:user)
1269 following2 = insert(:user)
1270 following3 = insert(:user)
1271 {:ok, _} = User.follow(user, following1)
1272 {:ok, _} = User.follow(user, following2)
1273 {:ok, _} = User.follow(user, following3)
1274
1275 conn =
1276 conn
1277 |> assign(:user, user)
1278
1279 res_conn =
1280 conn
1281 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
1282
1283 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1284 assert id3 == following3.id
1285 assert id2 == following2.id
1286
1287 res_conn =
1288 conn
1289 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
1290
1291 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1292 assert id2 == following2.id
1293 assert id1 == following1.id
1294
1295 res_conn =
1296 conn
1297 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
1298
1299 assert [%{"id" => id2}] = json_response(res_conn, 200)
1300 assert id2 == following2.id
1301
1302 assert [link_header] = get_resp_header(res_conn, "link")
1303 assert link_header =~ ~r/since_id=#{following2.id}/
1304 assert link_header =~ ~r/max_id=#{following2.id}/
1305 end
1306
1307 test "following / unfollowing a user", %{conn: conn} do
1308 user = insert(:user)
1309 other_user = insert(:user)
1310
1311 conn =
1312 conn
1313 |> assign(:user, user)
1314 |> post("/api/v1/accounts/#{other_user.id}/follow")
1315
1316 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1317
1318 user = Repo.get(User, user.id)
1319
1320 conn =
1321 build_conn()
1322 |> assign(:user, user)
1323 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1324
1325 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1326
1327 user = Repo.get(User, user.id)
1328
1329 conn =
1330 build_conn()
1331 |> assign(:user, user)
1332 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1333
1334 assert %{"id" => id} = json_response(conn, 200)
1335 assert id == to_string(other_user.id)
1336 end
1337
1338 test "muting / unmuting a user", %{conn: conn} do
1339 user = insert(:user)
1340 other_user = insert(:user)
1341
1342 conn =
1343 conn
1344 |> assign(:user, user)
1345 |> post("/api/v1/accounts/#{other_user.id}/mute")
1346
1347 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1348
1349 user = Repo.get(User, user.id)
1350
1351 conn =
1352 build_conn()
1353 |> assign(:user, user)
1354 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1355
1356 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1357 end
1358
1359 test "getting a list of mutes", %{conn: conn} do
1360 user = insert(:user)
1361 other_user = insert(:user)
1362
1363 {:ok, user} = User.mute(user, other_user)
1364
1365 conn =
1366 conn
1367 |> assign(:user, user)
1368 |> get("/api/v1/mutes")
1369
1370 other_user_id = to_string(other_user.id)
1371 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1372 end
1373
1374 test "blocking / unblocking a user", %{conn: conn} do
1375 user = insert(:user)
1376 other_user = insert(:user)
1377
1378 conn =
1379 conn
1380 |> assign(:user, user)
1381 |> post("/api/v1/accounts/#{other_user.id}/block")
1382
1383 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1384
1385 user = Repo.get(User, user.id)
1386
1387 conn =
1388 build_conn()
1389 |> assign(:user, user)
1390 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1391
1392 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1393 end
1394
1395 test "getting a list of blocks", %{conn: conn} do
1396 user = insert(:user)
1397 other_user = insert(:user)
1398
1399 {:ok, user} = User.block(user, other_user)
1400
1401 conn =
1402 conn
1403 |> assign(:user, user)
1404 |> get("/api/v1/blocks")
1405
1406 other_user_id = to_string(other_user.id)
1407 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1408 end
1409
1410 test "blocking / unblocking a domain", %{conn: conn} do
1411 user = insert(:user)
1412 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1413
1414 conn =
1415 conn
1416 |> assign(:user, user)
1417 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1418
1419 assert %{} = json_response(conn, 200)
1420 user = User.get_cached_by_ap_id(user.ap_id)
1421 assert User.blocks?(user, other_user)
1422
1423 conn =
1424 build_conn()
1425 |> assign(:user, user)
1426 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1427
1428 assert %{} = json_response(conn, 200)
1429 user = User.get_cached_by_ap_id(user.ap_id)
1430 refute User.blocks?(user, other_user)
1431 end
1432
1433 test "getting a list of domain blocks", %{conn: conn} do
1434 user = insert(:user)
1435
1436 {:ok, user} = User.block_domain(user, "bad.site")
1437 {:ok, user} = User.block_domain(user, "even.worse.site")
1438
1439 conn =
1440 conn
1441 |> assign(:user, user)
1442 |> get("/api/v1/domain_blocks")
1443
1444 domain_blocks = json_response(conn, 200)
1445
1446 assert "bad.site" in domain_blocks
1447 assert "even.worse.site" in domain_blocks
1448 end
1449
1450 test "unimplemented follow_requests, blocks, domain blocks" do
1451 user = insert(:user)
1452
1453 ["blocks", "domain_blocks", "follow_requests"]
1454 |> Enum.each(fn endpoint ->
1455 conn =
1456 build_conn()
1457 |> assign(:user, user)
1458 |> get("/api/v1/#{endpoint}")
1459
1460 assert [] = json_response(conn, 200)
1461 end)
1462 end
1463
1464 test "account search", %{conn: conn} do
1465 user = insert(:user)
1466 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1467 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1468
1469 results =
1470 conn
1471 |> assign(:user, user)
1472 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1473 |> json_response(200)
1474
1475 result_ids = for result <- results, do: result["acct"]
1476
1477 assert user_two.nickname in result_ids
1478 assert user_three.nickname in result_ids
1479
1480 results =
1481 conn
1482 |> assign(:user, user)
1483 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1484 |> json_response(200)
1485
1486 result_ids = for result <- results, do: result["acct"]
1487
1488 assert user_three.nickname in result_ids
1489 end
1490
1491 test "search", %{conn: conn} do
1492 user = insert(:user)
1493 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1494 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1495
1496 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1497
1498 {:ok, _activity} =
1499 CommonAPI.post(user, %{
1500 "status" => "This is about 2hu, but private",
1501 "visibility" => "private"
1502 })
1503
1504 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1505
1506 conn =
1507 conn
1508 |> get("/api/v1/search", %{"q" => "2hu"})
1509
1510 assert results = json_response(conn, 200)
1511
1512 [account | _] = results["accounts"]
1513 assert account["id"] == to_string(user_three.id)
1514
1515 assert results["hashtags"] == []
1516
1517 [status] = results["statuses"]
1518 assert status["id"] == to_string(activity.id)
1519 end
1520
1521 test "search fetches remote statuses", %{conn: conn} do
1522 capture_log(fn ->
1523 conn =
1524 conn
1525 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1526
1527 assert results = json_response(conn, 200)
1528
1529 [status] = results["statuses"]
1530 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1531 end)
1532 end
1533
1534 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1535 {:ok, activity} =
1536 CommonAPI.post(insert(:user), %{
1537 "status" => "This is about 2hu, but private",
1538 "visibility" => "private"
1539 })
1540
1541 capture_log(fn ->
1542 conn =
1543 conn
1544 |> get("/api/v1/search", %{"q" => activity.data["object"]["id"]})
1545
1546 assert results = json_response(conn, 200)
1547
1548 [] = results["statuses"]
1549 end)
1550 end
1551
1552 test "search fetches remote accounts", %{conn: conn} do
1553 conn =
1554 conn
1555 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1556
1557 assert results = json_response(conn, 200)
1558 [account] = results["accounts"]
1559 assert account["acct"] == "shp@social.heldscal.la"
1560 end
1561
1562 test "returns the favorites of a user", %{conn: conn} do
1563 user = insert(:user)
1564 other_user = insert(:user)
1565
1566 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1567 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1568
1569 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1570
1571 first_conn =
1572 conn
1573 |> assign(:user, user)
1574 |> get("/api/v1/favourites")
1575
1576 assert [status] = json_response(first_conn, 200)
1577 assert status["id"] == to_string(activity.id)
1578
1579 assert [{"link", _link_header}] =
1580 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1581
1582 # Honours query params
1583 {:ok, second_activity} =
1584 CommonAPI.post(other_user, %{
1585 "status" =>
1586 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1587 })
1588
1589 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1590
1591 last_like = status["id"]
1592
1593 second_conn =
1594 conn
1595 |> assign(:user, user)
1596 |> get("/api/v1/favourites?since_id=#{last_like}")
1597
1598 assert [second_status] = json_response(second_conn, 200)
1599 assert second_status["id"] == to_string(second_activity.id)
1600
1601 third_conn =
1602 conn
1603 |> assign(:user, user)
1604 |> get("/api/v1/favourites?limit=0")
1605
1606 assert [] = json_response(third_conn, 200)
1607 end
1608
1609 describe "updating credentials" do
1610 test "updates the user's bio", %{conn: conn} do
1611 user = insert(:user)
1612 user2 = insert(:user)
1613
1614 conn =
1615 conn
1616 |> assign(:user, user)
1617 |> patch("/api/v1/accounts/update_credentials", %{
1618 "note" => "I drink #cofe with @#{user2.nickname}"
1619 })
1620
1621 assert user = json_response(conn, 200)
1622
1623 assert user["note"] ==
1624 "I drink <a class=\"hashtag\" data-tag=\"cofe\" href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span class=\"h-card\"><a data-user=\"#{
1625 user2.id
1626 }\" class=\"u-url mention\" href=\"#{user2.ap_id}\">@<span>#{user2.nickname}</span></a></span>"
1627 end
1628
1629 test "updates the user's locking status", %{conn: conn} do
1630 user = insert(:user)
1631
1632 conn =
1633 conn
1634 |> assign(:user, user)
1635 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1636
1637 assert user = json_response(conn, 200)
1638 assert user["locked"] == true
1639 end
1640
1641 test "updates the user's name", %{conn: conn} do
1642 user = insert(:user)
1643
1644 conn =
1645 conn
1646 |> assign(:user, user)
1647 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1648
1649 assert user = json_response(conn, 200)
1650 assert user["display_name"] == "markorepairs"
1651 end
1652
1653 test "updates the user's avatar", %{conn: conn} do
1654 user = insert(:user)
1655
1656 new_avatar = %Plug.Upload{
1657 content_type: "image/jpg",
1658 path: Path.absname("test/fixtures/image.jpg"),
1659 filename: "an_image.jpg"
1660 }
1661
1662 conn =
1663 conn
1664 |> assign(:user, user)
1665 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1666
1667 assert user_response = json_response(conn, 200)
1668 assert user_response["avatar"] != User.avatar_url(user)
1669 end
1670
1671 test "updates the user's banner", %{conn: conn} do
1672 user = insert(:user)
1673
1674 new_header = %Plug.Upload{
1675 content_type: "image/jpg",
1676 path: Path.absname("test/fixtures/image.jpg"),
1677 filename: "an_image.jpg"
1678 }
1679
1680 conn =
1681 conn
1682 |> assign(:user, user)
1683 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1684
1685 assert user_response = json_response(conn, 200)
1686 assert user_response["header"] != User.banner_url(user)
1687 end
1688
1689 test "requires 'write' permission", %{conn: conn} do
1690 token1 = insert(:oauth_token, scopes: ["read"])
1691 token2 = insert(:oauth_token, scopes: ["write", "follow"])
1692
1693 for token <- [token1, token2] do
1694 conn =
1695 conn
1696 |> put_req_header("authorization", "Bearer #{token.token}")
1697 |> patch("/api/v1/accounts/update_credentials", %{})
1698
1699 if token == token1 do
1700 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
1701 else
1702 assert json_response(conn, 200)
1703 end
1704 end
1705 end
1706 end
1707
1708 test "get instance information", %{conn: conn} do
1709 user = insert(:user, %{local: true})
1710
1711 user2 = insert(:user, %{local: true})
1712 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1713
1714 insert(:user, %{local: false, nickname: "u@peer1.com"})
1715 insert(:user, %{local: false, nickname: "u@peer2.com"})
1716
1717 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
1718
1719 # Stats should count users with missing or nil `info.deactivated` value
1720 user = Repo.get(User, user.id)
1721 info_change = Changeset.change(user.info, %{deactivated: nil})
1722
1723 {:ok, _user} =
1724 user
1725 |> Changeset.change()
1726 |> Changeset.put_embed(:info, info_change)
1727 |> User.update_and_set_cache()
1728
1729 Pleroma.Stats.update_stats()
1730
1731 conn = get(conn, "/api/v1/instance")
1732
1733 assert result = json_response(conn, 200)
1734
1735 stats = result["stats"]
1736
1737 assert stats
1738 assert stats["user_count"] == 1
1739 assert stats["status_count"] == 1
1740 assert stats["domain_count"] == 2
1741 end
1742
1743 test "get peers", %{conn: conn} do
1744 insert(:user, %{local: false, nickname: "u@peer1.com"})
1745 insert(:user, %{local: false, nickname: "u@peer2.com"})
1746
1747 Pleroma.Stats.update_stats()
1748
1749 conn = get(conn, "/api/v1/instance/peers")
1750
1751 assert result = json_response(conn, 200)
1752
1753 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1754 end
1755
1756 test "put settings", %{conn: conn} do
1757 user = insert(:user)
1758
1759 conn =
1760 conn
1761 |> assign(:user, user)
1762 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1763
1764 assert _result = json_response(conn, 200)
1765
1766 user = User.get_cached_by_ap_id(user.ap_id)
1767 assert user.info.settings == %{"programming" => "socks"}
1768 end
1769
1770 describe "pinned statuses" do
1771 setup do
1772 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1773
1774 user = insert(:user)
1775 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
1776
1777 [user: user, activity: activity]
1778 end
1779
1780 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
1781 {:ok, _} = CommonAPI.pin(activity.id, user)
1782
1783 result =
1784 conn
1785 |> assign(:user, user)
1786 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1787 |> json_response(200)
1788
1789 id_str = to_string(activity.id)
1790
1791 assert [%{"id" => ^id_str, "pinned" => true}] = result
1792 end
1793
1794 test "pin status", %{conn: conn, user: user, activity: activity} do
1795 id_str = to_string(activity.id)
1796
1797 assert %{"id" => ^id_str, "pinned" => true} =
1798 conn
1799 |> assign(:user, user)
1800 |> post("/api/v1/statuses/#{activity.id}/pin")
1801 |> json_response(200)
1802
1803 assert [%{"id" => ^id_str, "pinned" => true}] =
1804 conn
1805 |> assign(:user, user)
1806 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1807 |> json_response(200)
1808 end
1809
1810 test "unpin status", %{conn: conn, user: user, activity: activity} do
1811 {:ok, _} = CommonAPI.pin(activity.id, user)
1812
1813 id_str = to_string(activity.id)
1814 user = refresh_record(user)
1815
1816 assert %{"id" => ^id_str, "pinned" => false} =
1817 conn
1818 |> assign(:user, user)
1819 |> post("/api/v1/statuses/#{activity.id}/unpin")
1820 |> json_response(200)
1821
1822 assert [] =
1823 conn
1824 |> assign(:user, user)
1825 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1826 |> json_response(200)
1827 end
1828
1829 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
1830 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
1831
1832 id_str_one = to_string(activity_one.id)
1833
1834 assert %{"id" => ^id_str_one, "pinned" => true} =
1835 conn
1836 |> assign(:user, user)
1837 |> post("/api/v1/statuses/#{id_str_one}/pin")
1838 |> json_response(200)
1839
1840 user = refresh_record(user)
1841
1842 assert %{"error" => "You have already pinned the maximum number of statuses"} =
1843 conn
1844 |> assign(:user, user)
1845 |> post("/api/v1/statuses/#{activity_two.id}/pin")
1846 |> json_response(400)
1847 end
1848
1849 test "Status rich-media Card", %{conn: conn, user: user} do
1850 Pleroma.Config.put([:rich_media, :enabled], true)
1851 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
1852
1853 response =
1854 conn
1855 |> get("/api/v1/statuses/#{activity.id}/card")
1856 |> json_response(200)
1857
1858 assert response == %{
1859 "image" => "http://ia.media-imdb.com/images/rock.jpg",
1860 "provider_name" => "www.imdb.com",
1861 "provider_url" => "http://www.imdb.com",
1862 "title" => "The Rock",
1863 "type" => "link",
1864 "url" => "http://www.imdb.com/title/tt0117500/",
1865 "description" => nil,
1866 "pleroma" => %{
1867 "opengraph" => %{
1868 "image" => "http://ia.media-imdb.com/images/rock.jpg",
1869 "title" => "The Rock",
1870 "type" => "video.movie",
1871 "url" => "http://www.imdb.com/title/tt0117500/"
1872 }
1873 }
1874 }
1875
1876 # works with private posts
1877 {:ok, activity} =
1878 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
1879
1880 response_two =
1881 conn
1882 |> assign(:user, user)
1883 |> get("/api/v1/statuses/#{activity.id}/card")
1884 |> json_response(200)
1885
1886 assert response_two == response
1887
1888 Pleroma.Config.put([:rich_media, :enabled], false)
1889 end
1890 end
1891
1892 test "bookmarks" do
1893 user = insert(:user)
1894 for_user = insert(:user)
1895
1896 {:ok, activity1} =
1897 CommonAPI.post(user, %{
1898 "status" => "heweoo?"
1899 })
1900
1901 {:ok, activity2} =
1902 CommonAPI.post(user, %{
1903 "status" => "heweoo!"
1904 })
1905
1906 response1 =
1907 build_conn()
1908 |> assign(:user, for_user)
1909 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
1910
1911 assert json_response(response1, 200)["bookmarked"] == true
1912
1913 response2 =
1914 build_conn()
1915 |> assign(:user, for_user)
1916 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
1917
1918 assert json_response(response2, 200)["bookmarked"] == true
1919
1920 bookmarks =
1921 build_conn()
1922 |> assign(:user, for_user)
1923 |> get("/api/v1/bookmarks")
1924
1925 assert [json_response(response2, 200), json_response(response1, 200)] ==
1926 json_response(bookmarks, 200)
1927
1928 response1 =
1929 build_conn()
1930 |> assign(:user, for_user)
1931 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
1932
1933 assert json_response(response1, 200)["bookmarked"] == false
1934
1935 bookmarks =
1936 build_conn()
1937 |> assign(:user, for_user)
1938 |> get("/api/v1/bookmarks")
1939
1940 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
1941 end
1942
1943 describe "conversation muting" do
1944 setup do
1945 user = insert(:user)
1946 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
1947
1948 [user: user, activity: activity]
1949 end
1950
1951 test "mute conversation", %{conn: conn, user: user, activity: activity} do
1952 id_str = to_string(activity.id)
1953
1954 assert %{"id" => ^id_str, "muted" => true} =
1955 conn
1956 |> assign(:user, user)
1957 |> post("/api/v1/statuses/#{activity.id}/mute")
1958 |> json_response(200)
1959 end
1960
1961 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
1962 {:ok, _} = CommonAPI.add_mute(user, activity)
1963
1964 id_str = to_string(activity.id)
1965 user = refresh_record(user)
1966
1967 assert %{"id" => ^id_str, "muted" => false} =
1968 conn
1969 |> assign(:user, user)
1970 |> post("/api/v1/statuses/#{activity.id}/unmute")
1971 |> json_response(200)
1972 end
1973 end
1974
1975 test "flavours switching (Pleroma Extension)", %{conn: conn} do
1976 user = insert(:user)
1977
1978 get_old_flavour =
1979 conn
1980 |> assign(:user, user)
1981 |> get("/api/v1/pleroma/flavour")
1982
1983 assert "glitch" == json_response(get_old_flavour, 200)
1984
1985 set_flavour =
1986 conn
1987 |> assign(:user, user)
1988 |> post("/api/v1/pleroma/flavour/vanilla")
1989
1990 assert "vanilla" == json_response(set_flavour, 200)
1991
1992 get_new_flavour =
1993 conn
1994 |> assign(:user, user)
1995 |> post("/api/v1/pleroma/flavour/vanilla")
1996
1997 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
1998 end
1999
2000 describe "reports" do
2001 setup do
2002 reporter = insert(:user)
2003 target_user = insert(:user)
2004
2005 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2006
2007 [reporter: reporter, target_user: target_user, activity: activity]
2008 end
2009
2010 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2011 assert %{"action_taken" => false, "id" => _} =
2012 conn
2013 |> assign(:user, reporter)
2014 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2015 |> json_response(200)
2016 end
2017
2018 test "submit a report with statuses and comment", %{
2019 conn: conn,
2020 reporter: reporter,
2021 target_user: target_user,
2022 activity: activity
2023 } do
2024 assert %{"action_taken" => false, "id" => _} =
2025 conn
2026 |> assign(:user, reporter)
2027 |> post("/api/v1/reports", %{
2028 "account_id" => target_user.id,
2029 "status_ids" => [activity.id],
2030 "comment" => "bad status!"
2031 })
2032 |> json_response(200)
2033 end
2034
2035 test "accound_id is required", %{
2036 conn: conn,
2037 reporter: reporter,
2038 activity: activity
2039 } do
2040 assert %{"error" => "Valid `account_id` required"} =
2041 conn
2042 |> assign(:user, reporter)
2043 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2044 |> json_response(400)
2045 end
2046
2047 test "comment must be up to the size specified in the config", %{
2048 conn: conn,
2049 reporter: reporter,
2050 target_user: target_user
2051 } do
2052 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2053 comment = String.pad_trailing("a", max_size + 1, "a")
2054
2055 error = %{"error" => "Comment must be up to #{max_size} characters"}
2056
2057 assert ^error =
2058 conn
2059 |> assign(:user, reporter)
2060 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2061 |> json_response(400)
2062 end
2063 end
2064
2065 describe "link headers" do
2066 test "preserves parameters in link headers", %{conn: conn} do
2067 user = insert(:user)
2068 other_user = insert(:user)
2069
2070 {:ok, activity1} =
2071 CommonAPI.post(other_user, %{
2072 "status" => "hi @#{user.nickname}",
2073 "visibility" => "public"
2074 })
2075
2076 {:ok, activity2} =
2077 CommonAPI.post(other_user, %{
2078 "status" => "hi @#{user.nickname}",
2079 "visibility" => "public"
2080 })
2081
2082 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2083 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2084
2085 conn =
2086 conn
2087 |> assign(:user, user)
2088 |> get("/api/v1/notifications", %{media_only: true})
2089
2090 assert [link_header] = get_resp_header(conn, "link")
2091 assert link_header =~ ~r/media_only=true/
2092 assert link_header =~ ~r/since_id=#{notification2.id}/
2093 assert link_header =~ ~r/max_id=#{notification1.id}/
2094 end
2095 end
2096 end