[Credo] Change quoted string with 3+ quotes to sigils
[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 Ecto.Changeset
9 alias Pleroma.Activity
10 alias Pleroma.Notification
11 alias Pleroma.Object
12 alias Pleroma.Repo
13 alias Pleroma.User
14 alias Pleroma.Web.ActivityPub.ActivityPub
15 alias Pleroma.Web.CommonAPI
16 alias Pleroma.Web.MastodonAPI.FilterView
17 alias Pleroma.Web.OStatus
18 alias Pleroma.Web.TwitterAPI.TwitterAPI
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 "account fetching also works nickname", %{conn: conn} do
1068 user = insert(:user)
1069
1070 conn =
1071 conn
1072 |> get("/api/v1/accounts/#{user.nickname}")
1073
1074 assert %{"id" => id} = json_response(conn, 200)
1075 assert id == user.id
1076 end
1077
1078 test "media upload", %{conn: conn} do
1079 file = %Plug.Upload{
1080 content_type: "image/jpg",
1081 path: Path.absname("test/fixtures/image.jpg"),
1082 filename: "an_image.jpg"
1083 }
1084
1085 desc = "Description of the image"
1086
1087 user = insert(:user)
1088
1089 conn =
1090 conn
1091 |> assign(:user, user)
1092 |> post("/api/v1/media", %{"file" => file, "description" => desc})
1093
1094 assert media = json_response(conn, 200)
1095
1096 assert media["type"] == "image"
1097 assert media["description"] == desc
1098 assert media["id"]
1099
1100 object = Repo.get(Object, media["id"])
1101 assert object.data["actor"] == User.ap_id(user)
1102 end
1103
1104 test "hashtag timeline", %{conn: conn} do
1105 following = insert(:user)
1106
1107 capture_log(fn ->
1108 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
1109
1110 {:ok, [_activity]} =
1111 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
1112
1113 nconn =
1114 conn
1115 |> get("/api/v1/timelines/tag/2hu")
1116
1117 assert [%{"id" => id}] = json_response(nconn, 200)
1118
1119 assert id == to_string(activity.id)
1120
1121 # works for different capitalization too
1122 nconn =
1123 conn
1124 |> get("/api/v1/timelines/tag/2HU")
1125
1126 assert [%{"id" => id}] = json_response(nconn, 200)
1127
1128 assert id == to_string(activity.id)
1129 end)
1130 end
1131
1132 test "multi-hashtag timeline", %{conn: conn} do
1133 user = insert(:user)
1134
1135 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
1136 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
1137 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
1138
1139 any_test =
1140 conn
1141 |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
1142
1143 [status_none, status_test1, status_test] = json_response(any_test, 200)
1144
1145 assert to_string(activity_test.id) == status_test["id"]
1146 assert to_string(activity_test1.id) == status_test1["id"]
1147 assert to_string(activity_none.id) == status_none["id"]
1148
1149 restricted_test =
1150 conn
1151 |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
1152
1153 assert [status_test1] == json_response(restricted_test, 200)
1154
1155 all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
1156
1157 assert [status_none] == json_response(all_test, 200)
1158 end
1159
1160 test "getting followers", %{conn: conn} do
1161 user = insert(:user)
1162 other_user = insert(:user)
1163 {:ok, user} = User.follow(user, other_user)
1164
1165 conn =
1166 conn
1167 |> get("/api/v1/accounts/#{other_user.id}/followers")
1168
1169 assert [%{"id" => id}] = json_response(conn, 200)
1170 assert id == to_string(user.id)
1171 end
1172
1173 test "getting followers, hide_followers", %{conn: conn} do
1174 user = insert(:user)
1175 other_user = insert(:user, %{info: %{hide_followers: true}})
1176 {:ok, _user} = User.follow(user, other_user)
1177
1178 conn =
1179 conn
1180 |> get("/api/v1/accounts/#{other_user.id}/followers")
1181
1182 assert [] == json_response(conn, 200)
1183 end
1184
1185 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
1186 user = insert(:user)
1187 other_user = insert(:user, %{info: %{hide_followers: true}})
1188 {:ok, _user} = User.follow(user, other_user)
1189
1190 conn =
1191 conn
1192 |> assign(:user, other_user)
1193 |> get("/api/v1/accounts/#{other_user.id}/followers")
1194
1195 refute [] == json_response(conn, 200)
1196 end
1197
1198 test "getting followers, pagination", %{conn: conn} do
1199 user = insert(:user)
1200 follower1 = insert(:user)
1201 follower2 = insert(:user)
1202 follower3 = insert(:user)
1203 {:ok, _} = User.follow(follower1, user)
1204 {:ok, _} = User.follow(follower2, user)
1205 {:ok, _} = User.follow(follower3, user)
1206
1207 conn =
1208 conn
1209 |> assign(:user, user)
1210
1211 res_conn =
1212 conn
1213 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
1214
1215 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1216 assert id3 == follower3.id
1217 assert id2 == follower2.id
1218
1219 res_conn =
1220 conn
1221 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
1222
1223 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1224 assert id2 == follower2.id
1225 assert id1 == follower1.id
1226
1227 res_conn =
1228 conn
1229 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
1230
1231 assert [%{"id" => id2}] = json_response(res_conn, 200)
1232 assert id2 == follower2.id
1233
1234 assert [link_header] = get_resp_header(res_conn, "link")
1235 assert link_header =~ ~r/since_id=#{follower2.id}/
1236 assert link_header =~ ~r/max_id=#{follower2.id}/
1237 end
1238
1239 test "getting following", %{conn: conn} do
1240 user = insert(:user)
1241 other_user = insert(:user)
1242 {:ok, user} = User.follow(user, other_user)
1243
1244 conn =
1245 conn
1246 |> get("/api/v1/accounts/#{user.id}/following")
1247
1248 assert [%{"id" => id}] = json_response(conn, 200)
1249 assert id == to_string(other_user.id)
1250 end
1251
1252 test "getting following, hide_follows", %{conn: conn} do
1253 user = insert(:user, %{info: %{hide_follows: true}})
1254 other_user = insert(:user)
1255 {:ok, user} = User.follow(user, other_user)
1256
1257 conn =
1258 conn
1259 |> get("/api/v1/accounts/#{user.id}/following")
1260
1261 assert [] == json_response(conn, 200)
1262 end
1263
1264 test "getting following, hide_follows, same user requesting", %{conn: conn} do
1265 user = insert(:user, %{info: %{hide_follows: true}})
1266 other_user = insert(:user)
1267 {:ok, user} = User.follow(user, other_user)
1268
1269 conn =
1270 conn
1271 |> assign(:user, user)
1272 |> get("/api/v1/accounts/#{user.id}/following")
1273
1274 refute [] == json_response(conn, 200)
1275 end
1276
1277 test "getting following, pagination", %{conn: conn} do
1278 user = insert(:user)
1279 following1 = insert(:user)
1280 following2 = insert(:user)
1281 following3 = insert(:user)
1282 {:ok, _} = User.follow(user, following1)
1283 {:ok, _} = User.follow(user, following2)
1284 {:ok, _} = User.follow(user, following3)
1285
1286 conn =
1287 conn
1288 |> assign(:user, user)
1289
1290 res_conn =
1291 conn
1292 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
1293
1294 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1295 assert id3 == following3.id
1296 assert id2 == following2.id
1297
1298 res_conn =
1299 conn
1300 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
1301
1302 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1303 assert id2 == following2.id
1304 assert id1 == following1.id
1305
1306 res_conn =
1307 conn
1308 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
1309
1310 assert [%{"id" => id2}] = json_response(res_conn, 200)
1311 assert id2 == following2.id
1312
1313 assert [link_header] = get_resp_header(res_conn, "link")
1314 assert link_header =~ ~r/since_id=#{following2.id}/
1315 assert link_header =~ ~r/max_id=#{following2.id}/
1316 end
1317
1318 test "following / unfollowing a user", %{conn: conn} do
1319 user = insert(:user)
1320 other_user = insert(:user)
1321
1322 conn =
1323 conn
1324 |> assign(:user, user)
1325 |> post("/api/v1/accounts/#{other_user.id}/follow")
1326
1327 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1328
1329 user = Repo.get(User, user.id)
1330
1331 conn =
1332 build_conn()
1333 |> assign(:user, user)
1334 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1335
1336 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1337
1338 user = Repo.get(User, user.id)
1339
1340 conn =
1341 build_conn()
1342 |> assign(:user, user)
1343 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1344
1345 assert %{"id" => id} = json_response(conn, 200)
1346 assert id == to_string(other_user.id)
1347 end
1348
1349 test "muting / unmuting a user", %{conn: conn} do
1350 user = insert(:user)
1351 other_user = insert(:user)
1352
1353 conn =
1354 conn
1355 |> assign(:user, user)
1356 |> post("/api/v1/accounts/#{other_user.id}/mute")
1357
1358 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1359
1360 user = Repo.get(User, user.id)
1361
1362 conn =
1363 build_conn()
1364 |> assign(:user, user)
1365 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1366
1367 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1368 end
1369
1370 test "getting a list of mutes", %{conn: conn} do
1371 user = insert(:user)
1372 other_user = insert(:user)
1373
1374 {:ok, user} = User.mute(user, other_user)
1375
1376 conn =
1377 conn
1378 |> assign(:user, user)
1379 |> get("/api/v1/mutes")
1380
1381 other_user_id = to_string(other_user.id)
1382 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1383 end
1384
1385 test "blocking / unblocking a user", %{conn: conn} do
1386 user = insert(:user)
1387 other_user = insert(:user)
1388
1389 conn =
1390 conn
1391 |> assign(:user, user)
1392 |> post("/api/v1/accounts/#{other_user.id}/block")
1393
1394 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1395
1396 user = Repo.get(User, user.id)
1397
1398 conn =
1399 build_conn()
1400 |> assign(:user, user)
1401 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1402
1403 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1404 end
1405
1406 test "getting a list of blocks", %{conn: conn} do
1407 user = insert(:user)
1408 other_user = insert(:user)
1409
1410 {:ok, user} = User.block(user, other_user)
1411
1412 conn =
1413 conn
1414 |> assign(:user, user)
1415 |> get("/api/v1/blocks")
1416
1417 other_user_id = to_string(other_user.id)
1418 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1419 end
1420
1421 test "blocking / unblocking a domain", %{conn: conn} do
1422 user = insert(:user)
1423 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1424
1425 conn =
1426 conn
1427 |> assign(:user, user)
1428 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1429
1430 assert %{} = json_response(conn, 200)
1431 user = User.get_cached_by_ap_id(user.ap_id)
1432 assert User.blocks?(user, other_user)
1433
1434 conn =
1435 build_conn()
1436 |> assign(:user, user)
1437 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1438
1439 assert %{} = json_response(conn, 200)
1440 user = User.get_cached_by_ap_id(user.ap_id)
1441 refute User.blocks?(user, other_user)
1442 end
1443
1444 test "getting a list of domain blocks", %{conn: conn} do
1445 user = insert(:user)
1446
1447 {:ok, user} = User.block_domain(user, "bad.site")
1448 {:ok, user} = User.block_domain(user, "even.worse.site")
1449
1450 conn =
1451 conn
1452 |> assign(:user, user)
1453 |> get("/api/v1/domain_blocks")
1454
1455 domain_blocks = json_response(conn, 200)
1456
1457 assert "bad.site" in domain_blocks
1458 assert "even.worse.site" in domain_blocks
1459 end
1460
1461 test "unimplemented follow_requests, blocks, domain blocks" do
1462 user = insert(:user)
1463
1464 ["blocks", "domain_blocks", "follow_requests"]
1465 |> Enum.each(fn endpoint ->
1466 conn =
1467 build_conn()
1468 |> assign(:user, user)
1469 |> get("/api/v1/#{endpoint}")
1470
1471 assert [] = json_response(conn, 200)
1472 end)
1473 end
1474
1475 test "account search", %{conn: conn} do
1476 user = insert(:user)
1477 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1478 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1479
1480 results =
1481 conn
1482 |> assign(:user, user)
1483 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1484 |> json_response(200)
1485
1486 result_ids = for result <- results, do: result["acct"]
1487
1488 assert user_two.nickname in result_ids
1489 assert user_three.nickname in result_ids
1490
1491 results =
1492 conn
1493 |> assign(:user, user)
1494 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1495 |> json_response(200)
1496
1497 result_ids = for result <- results, do: result["acct"]
1498
1499 assert user_three.nickname in result_ids
1500 end
1501
1502 test "search", %{conn: conn} do
1503 user = insert(:user)
1504 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1505 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1506
1507 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1508
1509 {:ok, _activity} =
1510 CommonAPI.post(user, %{
1511 "status" => "This is about 2hu, but private",
1512 "visibility" => "private"
1513 })
1514
1515 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1516
1517 conn =
1518 conn
1519 |> get("/api/v1/search", %{"q" => "2hu"})
1520
1521 assert results = json_response(conn, 200)
1522
1523 [account | _] = results["accounts"]
1524 assert account["id"] == to_string(user_three.id)
1525
1526 assert results["hashtags"] == []
1527
1528 [status] = results["statuses"]
1529 assert status["id"] == to_string(activity.id)
1530 end
1531
1532 test "search fetches remote statuses", %{conn: conn} do
1533 capture_log(fn ->
1534 conn =
1535 conn
1536 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1537
1538 assert results = json_response(conn, 200)
1539
1540 [status] = results["statuses"]
1541 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1542 end)
1543 end
1544
1545 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1546 {:ok, activity} =
1547 CommonAPI.post(insert(:user), %{
1548 "status" => "This is about 2hu, but private",
1549 "visibility" => "private"
1550 })
1551
1552 capture_log(fn ->
1553 conn =
1554 conn
1555 |> get("/api/v1/search", %{"q" => activity.data["object"]["id"]})
1556
1557 assert results = json_response(conn, 200)
1558
1559 [] = results["statuses"]
1560 end)
1561 end
1562
1563 test "search fetches remote accounts", %{conn: conn} do
1564 conn =
1565 conn
1566 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1567
1568 assert results = json_response(conn, 200)
1569 [account] = results["accounts"]
1570 assert account["acct"] == "shp@social.heldscal.la"
1571 end
1572
1573 test "returns the favorites of a user", %{conn: conn} do
1574 user = insert(:user)
1575 other_user = insert(:user)
1576
1577 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1578 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1579
1580 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1581
1582 first_conn =
1583 conn
1584 |> assign(:user, user)
1585 |> get("/api/v1/favourites")
1586
1587 assert [status] = json_response(first_conn, 200)
1588 assert status["id"] == to_string(activity.id)
1589
1590 assert [{"link", _link_header}] =
1591 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1592
1593 # Honours query params
1594 {:ok, second_activity} =
1595 CommonAPI.post(other_user, %{
1596 "status" =>
1597 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1598 })
1599
1600 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1601
1602 last_like = status["id"]
1603
1604 second_conn =
1605 conn
1606 |> assign(:user, user)
1607 |> get("/api/v1/favourites?since_id=#{last_like}")
1608
1609 assert [second_status] = json_response(second_conn, 200)
1610 assert second_status["id"] == to_string(second_activity.id)
1611
1612 third_conn =
1613 conn
1614 |> assign(:user, user)
1615 |> get("/api/v1/favourites?limit=0")
1616
1617 assert [] = json_response(third_conn, 200)
1618 end
1619
1620 describe "updating credentials" do
1621 test "updates the user's bio", %{conn: conn} do
1622 user = insert(:user)
1623 user2 = insert(:user)
1624
1625 conn =
1626 conn
1627 |> assign(:user, user)
1628 |> patch("/api/v1/accounts/update_credentials", %{
1629 "note" => "I drink #cofe with @#{user2.nickname}"
1630 })
1631
1632 assert user = json_response(conn, 200)
1633
1634 assert user["note"] ==
1635 ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a data-user=") <>
1636 user2.id <>
1637 ~s(" class="u-url mention" href=") <>
1638 user2.ap_id <> ~s(">@<span>) <> user2.nickname <> ~s(</span></a></span>)
1639 end
1640
1641 test "updates the user's locking status", %{conn: conn} do
1642 user = insert(:user)
1643
1644 conn =
1645 conn
1646 |> assign(:user, user)
1647 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1648
1649 assert user = json_response(conn, 200)
1650 assert user["locked"] == true
1651 end
1652
1653 test "updates the user's name", %{conn: conn} do
1654 user = insert(:user)
1655
1656 conn =
1657 conn
1658 |> assign(:user, user)
1659 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1660
1661 assert user = json_response(conn, 200)
1662 assert user["display_name"] == "markorepairs"
1663 end
1664
1665 test "updates the user's avatar", %{conn: conn} do
1666 user = insert(:user)
1667
1668 new_avatar = %Plug.Upload{
1669 content_type: "image/jpg",
1670 path: Path.absname("test/fixtures/image.jpg"),
1671 filename: "an_image.jpg"
1672 }
1673
1674 conn =
1675 conn
1676 |> assign(:user, user)
1677 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1678
1679 assert user_response = json_response(conn, 200)
1680 assert user_response["avatar"] != User.avatar_url(user)
1681 end
1682
1683 test "updates the user's banner", %{conn: conn} do
1684 user = insert(:user)
1685
1686 new_header = %Plug.Upload{
1687 content_type: "image/jpg",
1688 path: Path.absname("test/fixtures/image.jpg"),
1689 filename: "an_image.jpg"
1690 }
1691
1692 conn =
1693 conn
1694 |> assign(:user, user)
1695 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1696
1697 assert user_response = json_response(conn, 200)
1698 assert user_response["header"] != User.banner_url(user)
1699 end
1700
1701 test "requires 'write' permission", %{conn: conn} do
1702 token1 = insert(:oauth_token, scopes: ["read"])
1703 token2 = insert(:oauth_token, scopes: ["write", "follow"])
1704
1705 for token <- [token1, token2] do
1706 conn =
1707 conn
1708 |> put_req_header("authorization", "Bearer #{token.token}")
1709 |> patch("/api/v1/accounts/update_credentials", %{})
1710
1711 if token == token1 do
1712 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
1713 else
1714 assert json_response(conn, 200)
1715 end
1716 end
1717 end
1718 end
1719
1720 test "get instance information", %{conn: conn} do
1721 user = insert(:user, %{local: true})
1722
1723 user2 = insert(:user, %{local: true})
1724 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1725
1726 insert(:user, %{local: false, nickname: "u@peer1.com"})
1727 insert(:user, %{local: false, nickname: "u@peer2.com"})
1728
1729 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
1730
1731 # Stats should count users with missing or nil `info.deactivated` value
1732 user = Repo.get(User, user.id)
1733 info_change = Changeset.change(user.info, %{deactivated: nil})
1734
1735 {:ok, _user} =
1736 user
1737 |> Changeset.change()
1738 |> Changeset.put_embed(:info, info_change)
1739 |> User.update_and_set_cache()
1740
1741 Pleroma.Stats.update_stats()
1742
1743 conn = get(conn, "/api/v1/instance")
1744
1745 assert result = json_response(conn, 200)
1746
1747 stats = result["stats"]
1748
1749 assert stats
1750 assert stats["user_count"] == 1
1751 assert stats["status_count"] == 1
1752 assert stats["domain_count"] == 2
1753 end
1754
1755 test "get peers", %{conn: conn} do
1756 insert(:user, %{local: false, nickname: "u@peer1.com"})
1757 insert(:user, %{local: false, nickname: "u@peer2.com"})
1758
1759 Pleroma.Stats.update_stats()
1760
1761 conn = get(conn, "/api/v1/instance/peers")
1762
1763 assert result = json_response(conn, 200)
1764
1765 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1766 end
1767
1768 test "put settings", %{conn: conn} do
1769 user = insert(:user)
1770
1771 conn =
1772 conn
1773 |> assign(:user, user)
1774 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1775
1776 assert _result = json_response(conn, 200)
1777
1778 user = User.get_cached_by_ap_id(user.ap_id)
1779 assert user.info.settings == %{"programming" => "socks"}
1780 end
1781
1782 describe "pinned statuses" do
1783 setup do
1784 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1785
1786 user = insert(:user)
1787 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
1788
1789 [user: user, activity: activity]
1790 end
1791
1792 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
1793 {:ok, _} = CommonAPI.pin(activity.id, user)
1794
1795 result =
1796 conn
1797 |> assign(:user, user)
1798 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1799 |> json_response(200)
1800
1801 id_str = to_string(activity.id)
1802
1803 assert [%{"id" => ^id_str, "pinned" => true}] = result
1804 end
1805
1806 test "pin status", %{conn: conn, user: user, activity: activity} do
1807 id_str = to_string(activity.id)
1808
1809 assert %{"id" => ^id_str, "pinned" => true} =
1810 conn
1811 |> assign(:user, user)
1812 |> post("/api/v1/statuses/#{activity.id}/pin")
1813 |> json_response(200)
1814
1815 assert [%{"id" => ^id_str, "pinned" => true}] =
1816 conn
1817 |> assign(:user, user)
1818 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1819 |> json_response(200)
1820 end
1821
1822 test "unpin status", %{conn: conn, user: user, activity: activity} do
1823 {:ok, _} = CommonAPI.pin(activity.id, user)
1824
1825 id_str = to_string(activity.id)
1826 user = refresh_record(user)
1827
1828 assert %{"id" => ^id_str, "pinned" => false} =
1829 conn
1830 |> assign(:user, user)
1831 |> post("/api/v1/statuses/#{activity.id}/unpin")
1832 |> json_response(200)
1833
1834 assert [] =
1835 conn
1836 |> assign(:user, user)
1837 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1838 |> json_response(200)
1839 end
1840
1841 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
1842 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
1843
1844 id_str_one = to_string(activity_one.id)
1845
1846 assert %{"id" => ^id_str_one, "pinned" => true} =
1847 conn
1848 |> assign(:user, user)
1849 |> post("/api/v1/statuses/#{id_str_one}/pin")
1850 |> json_response(200)
1851
1852 user = refresh_record(user)
1853
1854 assert %{"error" => "You have already pinned the maximum number of statuses"} =
1855 conn
1856 |> assign(:user, user)
1857 |> post("/api/v1/statuses/#{activity_two.id}/pin")
1858 |> json_response(400)
1859 end
1860
1861 test "Status rich-media Card", %{conn: conn, user: user} do
1862 Pleroma.Config.put([:rich_media, :enabled], true)
1863 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
1864
1865 response =
1866 conn
1867 |> get("/api/v1/statuses/#{activity.id}/card")
1868 |> json_response(200)
1869
1870 assert response == %{
1871 "image" => "http://ia.media-imdb.com/images/rock.jpg",
1872 "provider_name" => "www.imdb.com",
1873 "provider_url" => "http://www.imdb.com",
1874 "title" => "The Rock",
1875 "type" => "link",
1876 "url" => "http://www.imdb.com/title/tt0117500/",
1877 "description" => nil,
1878 "pleroma" => %{
1879 "opengraph" => %{
1880 "image" => "http://ia.media-imdb.com/images/rock.jpg",
1881 "title" => "The Rock",
1882 "type" => "video.movie",
1883 "url" => "http://www.imdb.com/title/tt0117500/"
1884 }
1885 }
1886 }
1887
1888 # works with private posts
1889 {:ok, activity} =
1890 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
1891
1892 response_two =
1893 conn
1894 |> assign(:user, user)
1895 |> get("/api/v1/statuses/#{activity.id}/card")
1896 |> json_response(200)
1897
1898 assert response_two == response
1899
1900 Pleroma.Config.put([:rich_media, :enabled], false)
1901 end
1902 end
1903
1904 test "bookmarks" do
1905 user = insert(:user)
1906 for_user = insert(:user)
1907
1908 {:ok, activity1} =
1909 CommonAPI.post(user, %{
1910 "status" => "heweoo?"
1911 })
1912
1913 {:ok, activity2} =
1914 CommonAPI.post(user, %{
1915 "status" => "heweoo!"
1916 })
1917
1918 response1 =
1919 build_conn()
1920 |> assign(:user, for_user)
1921 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
1922
1923 assert json_response(response1, 200)["bookmarked"] == true
1924
1925 response2 =
1926 build_conn()
1927 |> assign(:user, for_user)
1928 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
1929
1930 assert json_response(response2, 200)["bookmarked"] == true
1931
1932 bookmarks =
1933 build_conn()
1934 |> assign(:user, for_user)
1935 |> get("/api/v1/bookmarks")
1936
1937 assert [json_response(response2, 200), json_response(response1, 200)] ==
1938 json_response(bookmarks, 200)
1939
1940 response1 =
1941 build_conn()
1942 |> assign(:user, for_user)
1943 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
1944
1945 assert json_response(response1, 200)["bookmarked"] == false
1946
1947 bookmarks =
1948 build_conn()
1949 |> assign(:user, for_user)
1950 |> get("/api/v1/bookmarks")
1951
1952 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
1953 end
1954
1955 describe "conversation muting" do
1956 setup do
1957 user = insert(:user)
1958 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
1959
1960 [user: user, activity: activity]
1961 end
1962
1963 test "mute conversation", %{conn: conn, user: user, activity: activity} do
1964 id_str = to_string(activity.id)
1965
1966 assert %{"id" => ^id_str, "muted" => true} =
1967 conn
1968 |> assign(:user, user)
1969 |> post("/api/v1/statuses/#{activity.id}/mute")
1970 |> json_response(200)
1971 end
1972
1973 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
1974 {:ok, _} = CommonAPI.add_mute(user, activity)
1975
1976 id_str = to_string(activity.id)
1977 user = refresh_record(user)
1978
1979 assert %{"id" => ^id_str, "muted" => false} =
1980 conn
1981 |> assign(:user, user)
1982 |> post("/api/v1/statuses/#{activity.id}/unmute")
1983 |> json_response(200)
1984 end
1985 end
1986
1987 test "flavours switching (Pleroma Extension)", %{conn: conn} do
1988 user = insert(:user)
1989
1990 get_old_flavour =
1991 conn
1992 |> assign(:user, user)
1993 |> get("/api/v1/pleroma/flavour")
1994
1995 assert "glitch" == json_response(get_old_flavour, 200)
1996
1997 set_flavour =
1998 conn
1999 |> assign(:user, user)
2000 |> post("/api/v1/pleroma/flavour/vanilla")
2001
2002 assert "vanilla" == json_response(set_flavour, 200)
2003
2004 get_new_flavour =
2005 conn
2006 |> assign(:user, user)
2007 |> post("/api/v1/pleroma/flavour/vanilla")
2008
2009 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2010 end
2011
2012 describe "reports" do
2013 setup do
2014 reporter = insert(:user)
2015 target_user = insert(:user)
2016
2017 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2018
2019 [reporter: reporter, target_user: target_user, activity: activity]
2020 end
2021
2022 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2023 assert %{"action_taken" => false, "id" => _} =
2024 conn
2025 |> assign(:user, reporter)
2026 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2027 |> json_response(200)
2028 end
2029
2030 test "submit a report with statuses and comment", %{
2031 conn: conn,
2032 reporter: reporter,
2033 target_user: target_user,
2034 activity: activity
2035 } do
2036 assert %{"action_taken" => false, "id" => _} =
2037 conn
2038 |> assign(:user, reporter)
2039 |> post("/api/v1/reports", %{
2040 "account_id" => target_user.id,
2041 "status_ids" => [activity.id],
2042 "comment" => "bad status!"
2043 })
2044 |> json_response(200)
2045 end
2046
2047 test "account_id is required", %{
2048 conn: conn,
2049 reporter: reporter,
2050 activity: activity
2051 } do
2052 assert %{"error" => "Valid `account_id` required"} =
2053 conn
2054 |> assign(:user, reporter)
2055 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2056 |> json_response(400)
2057 end
2058
2059 test "comment must be up to the size specified in the config", %{
2060 conn: conn,
2061 reporter: reporter,
2062 target_user: target_user
2063 } do
2064 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2065 comment = String.pad_trailing("a", max_size + 1, "a")
2066
2067 error = %{"error" => "Comment must be up to #{max_size} characters"}
2068
2069 assert ^error =
2070 conn
2071 |> assign(:user, reporter)
2072 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2073 |> json_response(400)
2074 end
2075 end
2076
2077 describe "link headers" do
2078 test "preserves parameters in link headers", %{conn: conn} do
2079 user = insert(:user)
2080 other_user = insert(:user)
2081
2082 {:ok, activity1} =
2083 CommonAPI.post(other_user, %{
2084 "status" => "hi @#{user.nickname}",
2085 "visibility" => "public"
2086 })
2087
2088 {:ok, activity2} =
2089 CommonAPI.post(other_user, %{
2090 "status" => "hi @#{user.nickname}",
2091 "visibility" => "public"
2092 })
2093
2094 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2095 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2096
2097 conn =
2098 conn
2099 |> assign(:user, user)
2100 |> get("/api/v1/notifications", %{media_only: true})
2101
2102 assert [link_header] = get_resp_header(conn, "link")
2103 assert link_header =~ ~r/media_only=true/
2104 assert link_header =~ ~r/since_id=#{notification2.id}/
2105 assert link_header =~ ~r/max_id=#{notification1.id}/
2106 end
2107 end
2108 end