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