60ade00d2c59ddeac91866a3212359a3608d2128
[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.Config
11 alias Pleroma.Notification
12 alias Pleroma.Object
13 alias Pleroma.Repo
14 alias Pleroma.ScheduledActivity
15 alias Pleroma.Tests.ObanHelpers
16 alias Pleroma.User
17 alias Pleroma.Web.ActivityPub.ActivityPub
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.MastodonAPI.FilterView
20 alias Pleroma.Web.OAuth.App
21 alias Pleroma.Web.OAuth.Token
22 alias Pleroma.Web.Push
23
24 import ExUnit.CaptureLog
25 import Pleroma.Factory
26 import Swoosh.TestAssertions
27 import Tesla.Mock
28
29 @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
30
31 setup do
32 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
33 :ok
34 end
35
36 clear_config([:instance, :public])
37 clear_config([:rich_media, :enabled])
38
39 test "Conversations", %{conn: conn} do
40 user_one = insert(:user)
41 user_two = insert(:user)
42 user_three = insert(:user)
43
44 {:ok, user_two} = User.follow(user_two, user_one)
45
46 {:ok, direct} =
47 CommonAPI.post(user_one, %{
48 "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!",
49 "visibility" => "direct"
50 })
51
52 {:ok, _follower_only} =
53 CommonAPI.post(user_one, %{
54 "status" => "Hi @#{user_two.nickname}!",
55 "visibility" => "private"
56 })
57
58 res_conn =
59 conn
60 |> assign(:user, user_one)
61 |> get("/api/v1/conversations")
62
63 assert response = json_response(res_conn, 200)
64
65 assert [
66 %{
67 "id" => res_id,
68 "accounts" => res_accounts,
69 "last_status" => res_last_status,
70 "unread" => unread
71 }
72 ] = response
73
74 account_ids = Enum.map(res_accounts, & &1["id"])
75 assert length(res_accounts) == 2
76 assert user_two.id in account_ids
77 assert user_three.id in account_ids
78 assert is_binary(res_id)
79 assert unread == true
80 assert res_last_status["id"] == direct.id
81
82 # Apparently undocumented API endpoint
83 res_conn =
84 conn
85 |> assign(:user, user_one)
86 |> post("/api/v1/conversations/#{res_id}/read")
87
88 assert response = json_response(res_conn, 200)
89 assert length(response["accounts"]) == 2
90 assert response["last_status"]["id"] == direct.id
91 assert response["unread"] == false
92
93 # (vanilla) Mastodon frontend behaviour
94 res_conn =
95 conn
96 |> assign(:user, user_one)
97 |> get("/api/v1/statuses/#{res_last_status["id"]}/context")
98
99 assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
100 end
101
102 test "verify_credentials", %{conn: conn} do
103 user = insert(:user)
104
105 conn =
106 conn
107 |> assign(:user, user)
108 |> get("/api/v1/accounts/verify_credentials")
109
110 response = json_response(conn, 200)
111
112 assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
113 assert response["pleroma"]["chat_token"]
114 assert id == to_string(user.id)
115 end
116
117 test "verify_credentials default scope unlisted", %{conn: conn} do
118 user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}})
119
120 conn =
121 conn
122 |> assign(:user, user)
123 |> get("/api/v1/accounts/verify_credentials")
124
125 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
126 assert id == to_string(user.id)
127 end
128
129 test "apps/verify_credentials", %{conn: conn} do
130 token = insert(:oauth_token)
131
132 conn =
133 conn
134 |> assign(:user, token.user)
135 |> assign(:token, token)
136 |> get("/api/v1/apps/verify_credentials")
137
138 app = Repo.preload(token, :app).app
139
140 expected = %{
141 "name" => app.client_name,
142 "website" => app.website,
143 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
144 }
145
146 assert expected == json_response(conn, 200)
147 end
148
149 test "user avatar can be set", %{conn: conn} do
150 user = insert(:user)
151 avatar_image = File.read!("test/fixtures/avatar_data_uri")
152
153 conn =
154 conn
155 |> assign(:user, user)
156 |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
157
158 user = refresh_record(user)
159
160 assert %{
161 "name" => _,
162 "type" => _,
163 "url" => [
164 %{
165 "href" => _,
166 "mediaType" => _,
167 "type" => _
168 }
169 ]
170 } = user.avatar
171
172 assert %{"url" => _} = json_response(conn, 200)
173 end
174
175 test "user avatar can be reset", %{conn: conn} do
176 user = insert(:user)
177
178 conn =
179 conn
180 |> assign(:user, user)
181 |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
182
183 user = User.get_cached_by_id(user.id)
184
185 assert user.avatar == nil
186
187 assert %{"url" => nil} = json_response(conn, 200)
188 end
189
190 test "can set profile banner", %{conn: conn} do
191 user = insert(:user)
192
193 conn =
194 conn
195 |> assign(:user, user)
196 |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
197
198 user = refresh_record(user)
199 assert user.info.banner["type"] == "Image"
200
201 assert %{"url" => _} = json_response(conn, 200)
202 end
203
204 test "can reset profile banner", %{conn: conn} do
205 user = insert(:user)
206
207 conn =
208 conn
209 |> assign(:user, user)
210 |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
211
212 user = refresh_record(user)
213 assert user.info.banner == %{}
214
215 assert %{"url" => nil} = json_response(conn, 200)
216 end
217
218 test "background image can be set", %{conn: conn} do
219 user = insert(:user)
220
221 conn =
222 conn
223 |> assign(:user, user)
224 |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
225
226 user = refresh_record(user)
227 assert user.info.background["type"] == "Image"
228 assert %{"url" => _} = json_response(conn, 200)
229 end
230
231 test "background image can be reset", %{conn: conn} do
232 user = insert(:user)
233
234 conn =
235 conn
236 |> assign(:user, user)
237 |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
238
239 user = refresh_record(user)
240 assert user.info.background == %{}
241 assert %{"url" => nil} = json_response(conn, 200)
242 end
243
244 test "creates an oauth app", %{conn: conn} do
245 user = insert(:user)
246 app_attrs = build(:oauth_app)
247
248 conn =
249 conn
250 |> assign(:user, user)
251 |> post("/api/v1/apps", %{
252 client_name: app_attrs.client_name,
253 redirect_uris: app_attrs.redirect_uris
254 })
255
256 [app] = Repo.all(App)
257
258 expected = %{
259 "name" => app.client_name,
260 "website" => app.website,
261 "client_id" => app.client_id,
262 "client_secret" => app.client_secret,
263 "id" => app.id |> to_string(),
264 "redirect_uri" => app.redirect_uris,
265 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
266 }
267
268 assert expected == json_response(conn, 200)
269 end
270
271 describe "filters" do
272 test "creating a filter", %{conn: conn} do
273 user = insert(:user)
274
275 filter = %Pleroma.Filter{
276 phrase: "knights",
277 context: ["home"]
278 }
279
280 conn =
281 conn
282 |> assign(:user, user)
283 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
284
285 assert response = json_response(conn, 200)
286 assert response["phrase"] == filter.phrase
287 assert response["context"] == filter.context
288 assert response["irreversible"] == false
289 assert response["id"] != nil
290 assert response["id"] != ""
291 end
292
293 test "fetching a list of filters", %{conn: conn} do
294 user = insert(:user)
295
296 query_one = %Pleroma.Filter{
297 user_id: user.id,
298 filter_id: 1,
299 phrase: "knights",
300 context: ["home"]
301 }
302
303 query_two = %Pleroma.Filter{
304 user_id: user.id,
305 filter_id: 2,
306 phrase: "who",
307 context: ["home"]
308 }
309
310 {:ok, filter_one} = Pleroma.Filter.create(query_one)
311 {:ok, filter_two} = Pleroma.Filter.create(query_two)
312
313 response =
314 conn
315 |> assign(:user, user)
316 |> get("/api/v1/filters")
317 |> json_response(200)
318
319 assert response ==
320 render_json(
321 FilterView,
322 "filters.json",
323 filters: [filter_two, filter_one]
324 )
325 end
326
327 test "get a filter", %{conn: conn} do
328 user = insert(:user)
329
330 query = %Pleroma.Filter{
331 user_id: user.id,
332 filter_id: 2,
333 phrase: "knight",
334 context: ["home"]
335 }
336
337 {:ok, filter} = Pleroma.Filter.create(query)
338
339 conn =
340 conn
341 |> assign(:user, user)
342 |> get("/api/v1/filters/#{filter.filter_id}")
343
344 assert _response = json_response(conn, 200)
345 end
346
347 test "update a filter", %{conn: conn} do
348 user = insert(:user)
349
350 query = %Pleroma.Filter{
351 user_id: user.id,
352 filter_id: 2,
353 phrase: "knight",
354 context: ["home"]
355 }
356
357 {:ok, _filter} = Pleroma.Filter.create(query)
358
359 new = %Pleroma.Filter{
360 phrase: "nii",
361 context: ["home"]
362 }
363
364 conn =
365 conn
366 |> assign(:user, user)
367 |> put("/api/v1/filters/#{query.filter_id}", %{
368 phrase: new.phrase,
369 context: new.context
370 })
371
372 assert response = json_response(conn, 200)
373 assert response["phrase"] == new.phrase
374 assert response["context"] == new.context
375 end
376
377 test "delete a filter", %{conn: conn} do
378 user = insert(:user)
379
380 query = %Pleroma.Filter{
381 user_id: user.id,
382 filter_id: 2,
383 phrase: "knight",
384 context: ["home"]
385 }
386
387 {:ok, filter} = Pleroma.Filter.create(query)
388
389 conn =
390 conn
391 |> assign(:user, user)
392 |> delete("/api/v1/filters/#{filter.filter_id}")
393
394 assert response = json_response(conn, 200)
395 assert response == %{}
396 end
397 end
398
399 describe "user timelines" do
400 test "gets a users statuses", %{conn: conn} do
401 user_one = insert(:user)
402 user_two = insert(:user)
403 user_three = insert(:user)
404
405 {:ok, user_three} = User.follow(user_three, user_one)
406
407 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
408
409 {:ok, direct_activity} =
410 CommonAPI.post(user_one, %{
411 "status" => "Hi, @#{user_two.nickname}.",
412 "visibility" => "direct"
413 })
414
415 {:ok, private_activity} =
416 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
417
418 resp =
419 conn
420 |> get("/api/v1/accounts/#{user_one.id}/statuses")
421
422 assert [%{"id" => id}] = json_response(resp, 200)
423 assert id == to_string(activity.id)
424
425 resp =
426 conn
427 |> assign(:user, user_two)
428 |> get("/api/v1/accounts/#{user_one.id}/statuses")
429
430 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
431 assert id_one == to_string(direct_activity.id)
432 assert id_two == to_string(activity.id)
433
434 resp =
435 conn
436 |> assign(:user, user_three)
437 |> get("/api/v1/accounts/#{user_one.id}/statuses")
438
439 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
440 assert id_one == to_string(private_activity.id)
441 assert id_two == to_string(activity.id)
442 end
443
444 test "unimplemented pinned statuses feature", %{conn: conn} do
445 note = insert(:note_activity)
446 user = User.get_cached_by_ap_id(note.data["actor"])
447
448 conn =
449 conn
450 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
451
452 assert json_response(conn, 200) == []
453 end
454
455 test "gets an users media", %{conn: conn} do
456 note = insert(:note_activity)
457 user = User.get_cached_by_ap_id(note.data["actor"])
458
459 file = %Plug.Upload{
460 content_type: "image/jpg",
461 path: Path.absname("test/fixtures/image.jpg"),
462 filename: "an_image.jpg"
463 }
464
465 {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
466
467 {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
468
469 conn =
470 conn
471 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
472
473 assert [%{"id" => id}] = json_response(conn, 200)
474 assert id == to_string(image_post.id)
475
476 conn =
477 build_conn()
478 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
479
480 assert [%{"id" => id}] = json_response(conn, 200)
481 assert id == to_string(image_post.id)
482 end
483
484 test "gets a user's statuses without reblogs", %{conn: conn} do
485 user = insert(:user)
486 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
487 {:ok, _, _} = CommonAPI.repeat(post.id, user)
488
489 conn =
490 conn
491 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
492
493 assert [%{"id" => id}] = json_response(conn, 200)
494 assert id == to_string(post.id)
495
496 conn =
497 conn
498 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
499
500 assert [%{"id" => id}] = json_response(conn, 200)
501 assert id == to_string(post.id)
502 end
503
504 test "filters user's statuses by a hashtag", %{conn: conn} do
505 user = insert(:user)
506 {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
507 {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
508
509 conn =
510 conn
511 |> get("/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
512
513 assert [%{"id" => id}] = json_response(conn, 200)
514 assert id == to_string(post.id)
515 end
516 end
517
518 describe "user relationships" do
519 test "returns the relationships for the current user", %{conn: conn} do
520 user = insert(:user)
521 other_user = insert(:user)
522 {:ok, user} = User.follow(user, other_user)
523
524 conn =
525 conn
526 |> assign(:user, user)
527 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
528
529 assert [relationship] = json_response(conn, 200)
530
531 assert to_string(other_user.id) == relationship["id"]
532 end
533 end
534
535 describe "media upload" do
536 setup do
537 user = insert(:user)
538
539 conn =
540 build_conn()
541 |> assign(:user, user)
542
543 image = %Plug.Upload{
544 content_type: "image/jpg",
545 path: Path.absname("test/fixtures/image.jpg"),
546 filename: "an_image.jpg"
547 }
548
549 [conn: conn, image: image]
550 end
551
552 clear_config([:media_proxy])
553 clear_config([Pleroma.Upload])
554
555 test "returns uploaded image", %{conn: conn, image: image} do
556 desc = "Description of the image"
557
558 media =
559 conn
560 |> post("/api/v1/media", %{"file" => image, "description" => desc})
561 |> json_response(:ok)
562
563 assert media["type"] == "image"
564 assert media["description"] == desc
565 assert media["id"]
566
567 object = Repo.get(Object, media["id"])
568 assert object.data["actor"] == User.ap_id(conn.assigns[:user])
569 end
570 end
571
572 describe "locked accounts" do
573 test "verify_credentials", %{conn: conn} do
574 user = insert(:user, %{info: %User.Info{default_scope: "private"}})
575
576 conn =
577 conn
578 |> assign(:user, user)
579 |> get("/api/v1/accounts/verify_credentials")
580
581 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
582 assert id == to_string(user.id)
583 end
584 end
585
586 describe "account fetching" do
587 test "works by id" do
588 user = insert(:user)
589
590 conn =
591 build_conn()
592 |> get("/api/v1/accounts/#{user.id}")
593
594 assert %{"id" => id} = json_response(conn, 200)
595 assert id == to_string(user.id)
596
597 conn =
598 build_conn()
599 |> get("/api/v1/accounts/-1")
600
601 assert %{"error" => "Can't find user"} = json_response(conn, 404)
602 end
603
604 test "works by nickname" do
605 user = insert(:user)
606
607 conn =
608 build_conn()
609 |> get("/api/v1/accounts/#{user.nickname}")
610
611 assert %{"id" => id} = json_response(conn, 200)
612 assert id == user.id
613 end
614
615 test "works by nickname for remote users" do
616 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
617 Pleroma.Config.put([:instance, :limit_to_local_content], false)
618 user = insert(:user, nickname: "user@example.com", local: false)
619
620 conn =
621 build_conn()
622 |> get("/api/v1/accounts/#{user.nickname}")
623
624 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
625 assert %{"id" => id} = json_response(conn, 200)
626 assert id == user.id
627 end
628
629 test "respects limit_to_local_content == :all for remote user nicknames" do
630 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
631 Pleroma.Config.put([:instance, :limit_to_local_content], :all)
632
633 user = insert(:user, nickname: "user@example.com", local: false)
634
635 conn =
636 build_conn()
637 |> get("/api/v1/accounts/#{user.nickname}")
638
639 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
640 assert json_response(conn, 404)
641 end
642
643 test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
644 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
645 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
646
647 user = insert(:user, nickname: "user@example.com", local: false)
648 reading_user = insert(:user)
649
650 conn =
651 build_conn()
652 |> get("/api/v1/accounts/#{user.nickname}")
653
654 assert json_response(conn, 404)
655
656 conn =
657 build_conn()
658 |> assign(:user, reading_user)
659 |> get("/api/v1/accounts/#{user.nickname}")
660
661 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
662 assert %{"id" => id} = json_response(conn, 200)
663 assert id == user.id
664 end
665 end
666
667 test "mascot upload", %{conn: conn} do
668 user = insert(:user)
669
670 non_image_file = %Plug.Upload{
671 content_type: "audio/mpeg",
672 path: Path.absname("test/fixtures/sound.mp3"),
673 filename: "sound.mp3"
674 }
675
676 conn =
677 conn
678 |> assign(:user, user)
679 |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
680
681 assert json_response(conn, 415)
682
683 file = %Plug.Upload{
684 content_type: "image/jpg",
685 path: Path.absname("test/fixtures/image.jpg"),
686 filename: "an_image.jpg"
687 }
688
689 conn =
690 build_conn()
691 |> assign(:user, user)
692 |> put("/api/v1/pleroma/mascot", %{"file" => file})
693
694 assert %{"id" => _, "type" => image} = json_response(conn, 200)
695 end
696
697 test "mascot retrieving", %{conn: conn} do
698 user = insert(:user)
699 # When user hasn't set a mascot, we should just get pleroma tan back
700 conn =
701 conn
702 |> assign(:user, user)
703 |> get("/api/v1/pleroma/mascot")
704
705 assert %{"url" => url} = json_response(conn, 200)
706 assert url =~ "pleroma-fox-tan-smol"
707
708 # When a user sets their mascot, we should get that back
709 file = %Plug.Upload{
710 content_type: "image/jpg",
711 path: Path.absname("test/fixtures/image.jpg"),
712 filename: "an_image.jpg"
713 }
714
715 conn =
716 build_conn()
717 |> assign(:user, user)
718 |> put("/api/v1/pleroma/mascot", %{"file" => file})
719
720 assert json_response(conn, 200)
721
722 user = User.get_cached_by_id(user.id)
723
724 conn =
725 build_conn()
726 |> assign(:user, user)
727 |> get("/api/v1/pleroma/mascot")
728
729 assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
730 assert url =~ "an_image"
731 end
732
733 test "getting followers", %{conn: conn} do
734 user = insert(:user)
735 other_user = insert(:user)
736 {:ok, user} = User.follow(user, other_user)
737
738 conn =
739 conn
740 |> get("/api/v1/accounts/#{other_user.id}/followers")
741
742 assert [%{"id" => id}] = json_response(conn, 200)
743 assert id == to_string(user.id)
744 end
745
746 test "getting followers, hide_followers", %{conn: conn} do
747 user = insert(:user)
748 other_user = insert(:user, %{info: %{hide_followers: true}})
749 {:ok, _user} = User.follow(user, other_user)
750
751 conn =
752 conn
753 |> get("/api/v1/accounts/#{other_user.id}/followers")
754
755 assert [] == json_response(conn, 200)
756 end
757
758 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
759 user = insert(:user)
760 other_user = insert(:user, %{info: %{hide_followers: true}})
761 {:ok, _user} = User.follow(user, other_user)
762
763 conn =
764 conn
765 |> assign(:user, other_user)
766 |> get("/api/v1/accounts/#{other_user.id}/followers")
767
768 refute [] == json_response(conn, 200)
769 end
770
771 test "getting followers, pagination", %{conn: conn} do
772 user = insert(:user)
773 follower1 = insert(:user)
774 follower2 = insert(:user)
775 follower3 = insert(:user)
776 {:ok, _} = User.follow(follower1, user)
777 {:ok, _} = User.follow(follower2, user)
778 {:ok, _} = User.follow(follower3, user)
779
780 conn =
781 conn
782 |> assign(:user, user)
783
784 res_conn =
785 conn
786 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
787
788 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
789 assert id3 == follower3.id
790 assert id2 == follower2.id
791
792 res_conn =
793 conn
794 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
795
796 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
797 assert id2 == follower2.id
798 assert id1 == follower1.id
799
800 res_conn =
801 conn
802 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
803
804 assert [%{"id" => id2}] = json_response(res_conn, 200)
805 assert id2 == follower2.id
806
807 assert [link_header] = get_resp_header(res_conn, "link")
808 assert link_header =~ ~r/min_id=#{follower2.id}/
809 assert link_header =~ ~r/max_id=#{follower2.id}/
810 end
811
812 test "getting following", %{conn: conn} do
813 user = insert(:user)
814 other_user = insert(:user)
815 {:ok, user} = User.follow(user, other_user)
816
817 conn =
818 conn
819 |> get("/api/v1/accounts/#{user.id}/following")
820
821 assert [%{"id" => id}] = json_response(conn, 200)
822 assert id == to_string(other_user.id)
823 end
824
825 test "getting following, hide_follows", %{conn: conn} do
826 user = insert(:user, %{info: %{hide_follows: true}})
827 other_user = insert(:user)
828 {:ok, user} = User.follow(user, other_user)
829
830 conn =
831 conn
832 |> get("/api/v1/accounts/#{user.id}/following")
833
834 assert [] == json_response(conn, 200)
835 end
836
837 test "getting following, hide_follows, same user requesting", %{conn: conn} do
838 user = insert(:user, %{info: %{hide_follows: true}})
839 other_user = insert(:user)
840 {:ok, user} = User.follow(user, other_user)
841
842 conn =
843 conn
844 |> assign(:user, user)
845 |> get("/api/v1/accounts/#{user.id}/following")
846
847 refute [] == json_response(conn, 200)
848 end
849
850 test "getting following, pagination", %{conn: conn} do
851 user = insert(:user)
852 following1 = insert(:user)
853 following2 = insert(:user)
854 following3 = insert(:user)
855 {:ok, _} = User.follow(user, following1)
856 {:ok, _} = User.follow(user, following2)
857 {:ok, _} = User.follow(user, following3)
858
859 conn =
860 conn
861 |> assign(:user, user)
862
863 res_conn =
864 conn
865 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
866
867 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
868 assert id3 == following3.id
869 assert id2 == following2.id
870
871 res_conn =
872 conn
873 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
874
875 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
876 assert id2 == following2.id
877 assert id1 == following1.id
878
879 res_conn =
880 conn
881 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
882
883 assert [%{"id" => id2}] = json_response(res_conn, 200)
884 assert id2 == following2.id
885
886 assert [link_header] = get_resp_header(res_conn, "link")
887 assert link_header =~ ~r/min_id=#{following2.id}/
888 assert link_header =~ ~r/max_id=#{following2.id}/
889 end
890
891 test "following / unfollowing a user", %{conn: conn} do
892 user = insert(:user)
893 other_user = insert(:user)
894
895 conn =
896 conn
897 |> assign(:user, user)
898 |> post("/api/v1/accounts/#{other_user.id}/follow")
899
900 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
901
902 user = User.get_cached_by_id(user.id)
903
904 conn =
905 build_conn()
906 |> assign(:user, user)
907 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
908
909 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
910
911 user = User.get_cached_by_id(user.id)
912
913 conn =
914 build_conn()
915 |> assign(:user, user)
916 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
917
918 assert %{"id" => id} = json_response(conn, 200)
919 assert id == to_string(other_user.id)
920 end
921
922 test "following without reblogs" do
923 follower = insert(:user)
924 followed = insert(:user)
925 other_user = insert(:user)
926
927 conn =
928 build_conn()
929 |> assign(:user, follower)
930 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
931
932 assert %{"showing_reblogs" => false} = json_response(conn, 200)
933
934 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
935 {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
936
937 conn =
938 build_conn()
939 |> assign(:user, User.get_cached_by_id(follower.id))
940 |> get("/api/v1/timelines/home")
941
942 assert [] == json_response(conn, 200)
943
944 conn =
945 build_conn()
946 |> assign(:user, follower)
947 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
948
949 assert %{"showing_reblogs" => true} = json_response(conn, 200)
950
951 conn =
952 build_conn()
953 |> assign(:user, User.get_cached_by_id(follower.id))
954 |> get("/api/v1/timelines/home")
955
956 expected_activity_id = reblog.id
957 assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
958 end
959
960 test "following / unfollowing errors" do
961 user = insert(:user)
962
963 conn =
964 build_conn()
965 |> assign(:user, user)
966
967 # self follow
968 conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
969 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
970
971 # self unfollow
972 user = User.get_cached_by_id(user.id)
973 conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
974 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
975
976 # self follow via uri
977 user = User.get_cached_by_id(user.id)
978 conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
979 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
980
981 # follow non existing user
982 conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
983 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
984
985 # follow non existing user via uri
986 conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
987 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
988
989 # unfollow non existing user
990 conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
991 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
992 end
993
994 describe "mute/unmute" do
995 test "with notifications", %{conn: conn} do
996 user = insert(:user)
997 other_user = insert(:user)
998
999 conn =
1000 conn
1001 |> assign(:user, user)
1002 |> post("/api/v1/accounts/#{other_user.id}/mute")
1003
1004 response = json_response(conn, 200)
1005
1006 assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
1007 user = User.get_cached_by_id(user.id)
1008
1009 conn =
1010 build_conn()
1011 |> assign(:user, user)
1012 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1013
1014 response = json_response(conn, 200)
1015 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
1016 end
1017
1018 test "without notifications", %{conn: conn} do
1019 user = insert(:user)
1020 other_user = insert(:user)
1021
1022 conn =
1023 conn
1024 |> assign(:user, user)
1025 |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
1026
1027 response = json_response(conn, 200)
1028
1029 assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
1030 user = User.get_cached_by_id(user.id)
1031
1032 conn =
1033 build_conn()
1034 |> assign(:user, user)
1035 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1036
1037 response = json_response(conn, 200)
1038 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
1039 end
1040 end
1041
1042 test "subscribing / unsubscribing to a user", %{conn: conn} do
1043 user = insert(:user)
1044 subscription_target = insert(:user)
1045
1046 conn =
1047 conn
1048 |> assign(:user, user)
1049 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
1050
1051 assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
1052
1053 conn =
1054 build_conn()
1055 |> assign(:user, user)
1056 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
1057
1058 assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
1059 end
1060
1061 test "getting a list of mutes", %{conn: conn} do
1062 user = insert(:user)
1063 other_user = insert(:user)
1064
1065 {:ok, user} = User.mute(user, other_user)
1066
1067 conn =
1068 conn
1069 |> assign(:user, user)
1070 |> get("/api/v1/mutes")
1071
1072 other_user_id = to_string(other_user.id)
1073 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1074 end
1075
1076 test "blocking / unblocking a user", %{conn: conn} do
1077 user = insert(:user)
1078 other_user = insert(:user)
1079
1080 conn =
1081 conn
1082 |> assign(:user, user)
1083 |> post("/api/v1/accounts/#{other_user.id}/block")
1084
1085 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1086
1087 user = User.get_cached_by_id(user.id)
1088
1089 conn =
1090 build_conn()
1091 |> assign(:user, user)
1092 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1093
1094 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1095 end
1096
1097 test "getting a list of blocks", %{conn: conn} do
1098 user = insert(:user)
1099 other_user = insert(:user)
1100
1101 {:ok, user} = User.block(user, other_user)
1102
1103 conn =
1104 conn
1105 |> assign(:user, user)
1106 |> get("/api/v1/blocks")
1107
1108 other_user_id = to_string(other_user.id)
1109 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1110 end
1111
1112 test "blocking / unblocking a domain", %{conn: conn} do
1113 user = insert(:user)
1114 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1115
1116 conn =
1117 conn
1118 |> assign(:user, user)
1119 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1120
1121 assert %{} = json_response(conn, 200)
1122 user = User.get_cached_by_ap_id(user.ap_id)
1123 assert User.blocks?(user, other_user)
1124
1125 conn =
1126 build_conn()
1127 |> assign(:user, user)
1128 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1129
1130 assert %{} = json_response(conn, 200)
1131 user = User.get_cached_by_ap_id(user.ap_id)
1132 refute User.blocks?(user, other_user)
1133 end
1134
1135 test "getting a list of domain blocks", %{conn: conn} do
1136 user = insert(:user)
1137
1138 {:ok, user} = User.block_domain(user, "bad.site")
1139 {:ok, user} = User.block_domain(user, "even.worse.site")
1140
1141 conn =
1142 conn
1143 |> assign(:user, user)
1144 |> get("/api/v1/domain_blocks")
1145
1146 domain_blocks = json_response(conn, 200)
1147
1148 assert "bad.site" in domain_blocks
1149 assert "even.worse.site" in domain_blocks
1150 end
1151
1152 test "unimplemented follow_requests, blocks, domain blocks" do
1153 user = insert(:user)
1154
1155 ["blocks", "domain_blocks", "follow_requests"]
1156 |> Enum.each(fn endpoint ->
1157 conn =
1158 build_conn()
1159 |> assign(:user, user)
1160 |> get("/api/v1/#{endpoint}")
1161
1162 assert [] = json_response(conn, 200)
1163 end)
1164 end
1165
1166 test "returns the favorites of a user", %{conn: conn} do
1167 user = insert(:user)
1168 other_user = insert(:user)
1169
1170 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1171 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1172
1173 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1174
1175 first_conn =
1176 conn
1177 |> assign(:user, user)
1178 |> get("/api/v1/favourites")
1179
1180 assert [status] = json_response(first_conn, 200)
1181 assert status["id"] == to_string(activity.id)
1182
1183 assert [{"link", _link_header}] =
1184 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1185
1186 # Honours query params
1187 {:ok, second_activity} =
1188 CommonAPI.post(other_user, %{
1189 "status" =>
1190 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1191 })
1192
1193 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1194
1195 last_like = status["id"]
1196
1197 second_conn =
1198 conn
1199 |> assign(:user, user)
1200 |> get("/api/v1/favourites?since_id=#{last_like}")
1201
1202 assert [second_status] = json_response(second_conn, 200)
1203 assert second_status["id"] == to_string(second_activity.id)
1204
1205 third_conn =
1206 conn
1207 |> assign(:user, user)
1208 |> get("/api/v1/favourites?limit=0")
1209
1210 assert [] = json_response(third_conn, 200)
1211 end
1212
1213 describe "getting favorites timeline of specified user" do
1214 setup do
1215 [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
1216 [current_user: current_user, user: user]
1217 end
1218
1219 test "returns list of statuses favorited by specified user", %{
1220 conn: conn,
1221 current_user: current_user,
1222 user: user
1223 } do
1224 [activity | _] = insert_pair(:note_activity)
1225 CommonAPI.favorite(activity.id, user)
1226
1227 response =
1228 conn
1229 |> assign(:user, current_user)
1230 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1231 |> json_response(:ok)
1232
1233 [like] = response
1234
1235 assert length(response) == 1
1236 assert like["id"] == activity.id
1237 end
1238
1239 test "returns favorites for specified user_id when user is not logged in", %{
1240 conn: conn,
1241 user: user
1242 } do
1243 activity = insert(:note_activity)
1244 CommonAPI.favorite(activity.id, user)
1245
1246 response =
1247 conn
1248 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1249 |> json_response(:ok)
1250
1251 assert length(response) == 1
1252 end
1253
1254 test "returns favorited DM only when user is logged in and he is one of recipients", %{
1255 conn: conn,
1256 current_user: current_user,
1257 user: user
1258 } do
1259 {:ok, direct} =
1260 CommonAPI.post(current_user, %{
1261 "status" => "Hi @#{user.nickname}!",
1262 "visibility" => "direct"
1263 })
1264
1265 CommonAPI.favorite(direct.id, user)
1266
1267 response =
1268 conn
1269 |> assign(:user, current_user)
1270 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1271 |> json_response(:ok)
1272
1273 assert length(response) == 1
1274
1275 anonymous_response =
1276 conn
1277 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1278 |> json_response(:ok)
1279
1280 assert Enum.empty?(anonymous_response)
1281 end
1282
1283 test "does not return others' favorited DM when user is not one of recipients", %{
1284 conn: conn,
1285 current_user: current_user,
1286 user: user
1287 } do
1288 user_two = insert(:user)
1289
1290 {:ok, direct} =
1291 CommonAPI.post(user_two, %{
1292 "status" => "Hi @#{user.nickname}!",
1293 "visibility" => "direct"
1294 })
1295
1296 CommonAPI.favorite(direct.id, user)
1297
1298 response =
1299 conn
1300 |> assign(:user, current_user)
1301 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1302 |> json_response(:ok)
1303
1304 assert Enum.empty?(response)
1305 end
1306
1307 test "paginates favorites using since_id and max_id", %{
1308 conn: conn,
1309 current_user: current_user,
1310 user: user
1311 } do
1312 activities = insert_list(10, :note_activity)
1313
1314 Enum.each(activities, fn activity ->
1315 CommonAPI.favorite(activity.id, user)
1316 end)
1317
1318 third_activity = Enum.at(activities, 2)
1319 seventh_activity = Enum.at(activities, 6)
1320
1321 response =
1322 conn
1323 |> assign(:user, current_user)
1324 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
1325 since_id: third_activity.id,
1326 max_id: seventh_activity.id
1327 })
1328 |> json_response(:ok)
1329
1330 assert length(response) == 3
1331 refute third_activity in response
1332 refute seventh_activity in response
1333 end
1334
1335 test "limits favorites using limit parameter", %{
1336 conn: conn,
1337 current_user: current_user,
1338 user: user
1339 } do
1340 7
1341 |> insert_list(:note_activity)
1342 |> Enum.each(fn activity ->
1343 CommonAPI.favorite(activity.id, user)
1344 end)
1345
1346 response =
1347 conn
1348 |> assign(:user, current_user)
1349 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
1350 |> json_response(:ok)
1351
1352 assert length(response) == 3
1353 end
1354
1355 test "returns empty response when user does not have any favorited statuses", %{
1356 conn: conn,
1357 current_user: current_user,
1358 user: user
1359 } do
1360 response =
1361 conn
1362 |> assign(:user, current_user)
1363 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1364 |> json_response(:ok)
1365
1366 assert Enum.empty?(response)
1367 end
1368
1369 test "returns 404 error when specified user is not exist", %{conn: conn} do
1370 conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
1371
1372 assert json_response(conn, 404) == %{"error" => "Record not found"}
1373 end
1374
1375 test "returns 403 error when user has hidden own favorites", %{
1376 conn: conn,
1377 current_user: current_user
1378 } do
1379 user = insert(:user, %{info: %{hide_favorites: true}})
1380 activity = insert(:note_activity)
1381 CommonAPI.favorite(activity.id, user)
1382
1383 conn =
1384 conn
1385 |> assign(:user, current_user)
1386 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1387
1388 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
1389 end
1390
1391 test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
1392 user = insert(:user)
1393 activity = insert(:note_activity)
1394 CommonAPI.favorite(activity.id, user)
1395
1396 conn =
1397 conn
1398 |> assign(:user, current_user)
1399 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1400
1401 assert user.info.hide_favorites
1402 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
1403 end
1404 end
1405
1406 test "get instance information", %{conn: conn} do
1407 conn = get(conn, "/api/v1/instance")
1408 assert result = json_response(conn, 200)
1409
1410 email = Config.get([:instance, :email])
1411 # Note: not checking for "max_toot_chars" since it's optional
1412 assert %{
1413 "uri" => _,
1414 "title" => _,
1415 "description" => _,
1416 "version" => _,
1417 "email" => from_config_email,
1418 "urls" => %{
1419 "streaming_api" => _
1420 },
1421 "stats" => _,
1422 "thumbnail" => _,
1423 "languages" => _,
1424 "registrations" => _,
1425 "poll_limits" => _
1426 } = result
1427
1428 assert email == from_config_email
1429 end
1430
1431 test "get instance stats", %{conn: conn} do
1432 user = insert(:user, %{local: true})
1433
1434 user2 = insert(:user, %{local: true})
1435 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1436
1437 insert(:user, %{local: false, nickname: "u@peer1.com"})
1438 insert(:user, %{local: false, nickname: "u@peer2.com"})
1439
1440 {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"})
1441
1442 # Stats should count users with missing or nil `info.deactivated` value
1443
1444 {:ok, _user} =
1445 user.id
1446 |> User.get_cached_by_id()
1447 |> User.update_info(&Changeset.change(&1, %{deactivated: nil}))
1448
1449 Pleroma.Stats.force_update()
1450
1451 conn = get(conn, "/api/v1/instance")
1452
1453 assert result = json_response(conn, 200)
1454
1455 stats = result["stats"]
1456
1457 assert stats
1458 assert stats["user_count"] == 1
1459 assert stats["status_count"] == 1
1460 assert stats["domain_count"] == 2
1461 end
1462
1463 test "get peers", %{conn: conn} do
1464 insert(:user, %{local: false, nickname: "u@peer1.com"})
1465 insert(:user, %{local: false, nickname: "u@peer2.com"})
1466
1467 Pleroma.Stats.force_update()
1468
1469 conn = get(conn, "/api/v1/instance/peers")
1470
1471 assert result = json_response(conn, 200)
1472
1473 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1474 end
1475
1476 test "put settings", %{conn: conn} do
1477 user = insert(:user)
1478
1479 conn =
1480 conn
1481 |> assign(:user, user)
1482 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1483
1484 assert _result = json_response(conn, 200)
1485
1486 user = User.get_cached_by_ap_id(user.ap_id)
1487 assert user.info.settings == %{"programming" => "socks"}
1488 end
1489
1490 describe "pinned statuses" do
1491 setup do
1492 user = insert(:user)
1493 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
1494
1495 [user: user, activity: activity]
1496 end
1497
1498 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
1499 {:ok, _} = CommonAPI.pin(activity.id, user)
1500
1501 result =
1502 conn
1503 |> assign(:user, user)
1504 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1505 |> json_response(200)
1506
1507 id_str = to_string(activity.id)
1508
1509 assert [%{"id" => ^id_str, "pinned" => true}] = result
1510 end
1511 end
1512
1513 describe "reports" do
1514 setup do
1515 reporter = insert(:user)
1516 target_user = insert(:user)
1517
1518 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
1519
1520 [reporter: reporter, target_user: target_user, activity: activity]
1521 end
1522
1523 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
1524 assert %{"action_taken" => false, "id" => _} =
1525 conn
1526 |> assign(:user, reporter)
1527 |> post("/api/v1/reports", %{"account_id" => target_user.id})
1528 |> json_response(200)
1529 end
1530
1531 test "submit a report with statuses and comment", %{
1532 conn: conn,
1533 reporter: reporter,
1534 target_user: target_user,
1535 activity: activity
1536 } do
1537 assert %{"action_taken" => false, "id" => _} =
1538 conn
1539 |> assign(:user, reporter)
1540 |> post("/api/v1/reports", %{
1541 "account_id" => target_user.id,
1542 "status_ids" => [activity.id],
1543 "comment" => "bad status!",
1544 "forward" => "false"
1545 })
1546 |> json_response(200)
1547 end
1548
1549 test "account_id is required", %{
1550 conn: conn,
1551 reporter: reporter,
1552 activity: activity
1553 } do
1554 assert %{"error" => "Valid `account_id` required"} =
1555 conn
1556 |> assign(:user, reporter)
1557 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
1558 |> json_response(400)
1559 end
1560
1561 test "comment must be up to the size specified in the config", %{
1562 conn: conn,
1563 reporter: reporter,
1564 target_user: target_user
1565 } do
1566 max_size = Config.get([:instance, :max_report_comment_size], 1000)
1567 comment = String.pad_trailing("a", max_size + 1, "a")
1568
1569 error = %{"error" => "Comment must be up to #{max_size} characters"}
1570
1571 assert ^error =
1572 conn
1573 |> assign(:user, reporter)
1574 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
1575 |> json_response(400)
1576 end
1577
1578 test "returns error when account is not exist", %{
1579 conn: conn,
1580 reporter: reporter,
1581 activity: activity
1582 } do
1583 conn =
1584 conn
1585 |> assign(:user, reporter)
1586 |> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
1587
1588 assert json_response(conn, 400) == %{"error" => "Account not found"}
1589 end
1590 end
1591
1592 describe "link headers" do
1593 test "preserves parameters in link headers", %{conn: conn} do
1594 user = insert(:user)
1595 other_user = insert(:user)
1596
1597 {:ok, activity1} =
1598 CommonAPI.post(other_user, %{
1599 "status" => "hi @#{user.nickname}",
1600 "visibility" => "public"
1601 })
1602
1603 {:ok, activity2} =
1604 CommonAPI.post(other_user, %{
1605 "status" => "hi @#{user.nickname}",
1606 "visibility" => "public"
1607 })
1608
1609 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
1610 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
1611
1612 conn =
1613 conn
1614 |> assign(:user, user)
1615 |> get("/api/v1/notifications", %{media_only: true})
1616
1617 assert [link_header] = get_resp_header(conn, "link")
1618 assert link_header =~ ~r/media_only=true/
1619 assert link_header =~ ~r/min_id=#{notification2.id}/
1620 assert link_header =~ ~r/max_id=#{notification1.id}/
1621 end
1622 end
1623
1624 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
1625 # Need to set an old-style integer ID to reproduce the problem
1626 # (these are no longer assigned to new accounts but were preserved
1627 # for existing accounts during the migration to flakeIDs)
1628 user_one = insert(:user, %{id: 1212})
1629 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
1630
1631 resp_one =
1632 conn
1633 |> get("/api/v1/accounts/#{user_one.id}")
1634
1635 resp_two =
1636 conn
1637 |> get("/api/v1/accounts/#{user_two.nickname}")
1638
1639 resp_three =
1640 conn
1641 |> get("/api/v1/accounts/#{user_two.id}")
1642
1643 acc_one = json_response(resp_one, 200)
1644 acc_two = json_response(resp_two, 200)
1645 acc_three = json_response(resp_three, 200)
1646 refute acc_one == acc_two
1647 assert acc_two == acc_three
1648 end
1649
1650 describe "custom emoji" do
1651 test "with tags", %{conn: conn} do
1652 [emoji | _body] =
1653 conn
1654 |> get("/api/v1/custom_emojis")
1655 |> json_response(200)
1656
1657 assert Map.has_key?(emoji, "shortcode")
1658 assert Map.has_key?(emoji, "static_url")
1659 assert Map.has_key?(emoji, "tags")
1660 assert is_list(emoji["tags"])
1661 assert Map.has_key?(emoji, "category")
1662 assert Map.has_key?(emoji, "url")
1663 assert Map.has_key?(emoji, "visible_in_picker")
1664 end
1665 end
1666
1667 describe "index/2 redirections" do
1668 setup %{conn: conn} do
1669 session_opts = [
1670 store: :cookie,
1671 key: "_test",
1672 signing_salt: "cooldude"
1673 ]
1674
1675 conn =
1676 conn
1677 |> Plug.Session.call(Plug.Session.init(session_opts))
1678 |> fetch_session()
1679
1680 test_path = "/web/statuses/test"
1681 %{conn: conn, path: test_path}
1682 end
1683
1684 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
1685 conn = get(conn, path)
1686
1687 assert conn.status == 302
1688 assert redirected_to(conn) == "/web/login"
1689 end
1690
1691 test "redirects not logged-in users to the login page on private instances", %{
1692 conn: conn,
1693 path: path
1694 } do
1695 Config.put([:instance, :public], false)
1696
1697 conn = get(conn, path)
1698
1699 assert conn.status == 302
1700 assert redirected_to(conn) == "/web/login"
1701 end
1702
1703 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
1704 token = insert(:oauth_token)
1705
1706 conn =
1707 conn
1708 |> assign(:user, token.user)
1709 |> put_session(:oauth_token, token.token)
1710 |> get(path)
1711
1712 assert conn.status == 200
1713 end
1714
1715 test "saves referer path to session", %{conn: conn, path: path} do
1716 conn = get(conn, path)
1717 return_to = Plug.Conn.get_session(conn, :return_to)
1718
1719 assert return_to == path
1720 end
1721
1722 test "redirects to the saved path after log in", %{conn: conn, path: path} do
1723 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
1724 auth = insert(:oauth_authorization, app: app)
1725
1726 conn =
1727 conn
1728 |> put_session(:return_to, path)
1729 |> get("/web/login", %{code: auth.token})
1730
1731 assert conn.status == 302
1732 assert redirected_to(conn) == path
1733 end
1734
1735 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
1736 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
1737 auth = insert(:oauth_authorization, app: app)
1738
1739 conn = get(conn, "/web/login", %{code: auth.token})
1740
1741 assert conn.status == 302
1742 assert redirected_to(conn) == "/web/getting-started"
1743 end
1744 end
1745
1746 describe "scheduled activities" do
1747 test "creates a scheduled activity", %{conn: conn} do
1748 user = insert(:user)
1749 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
1750
1751 conn =
1752 conn
1753 |> assign(:user, user)
1754 |> post("/api/v1/statuses", %{
1755 "status" => "scheduled",
1756 "scheduled_at" => scheduled_at
1757 })
1758
1759 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
1760 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
1761 assert [] == Repo.all(Activity)
1762 end
1763
1764 test "creates a scheduled activity with a media attachment", %{conn: conn} do
1765 user = insert(:user)
1766 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
1767
1768 file = %Plug.Upload{
1769 content_type: "image/jpg",
1770 path: Path.absname("test/fixtures/image.jpg"),
1771 filename: "an_image.jpg"
1772 }
1773
1774 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
1775
1776 conn =
1777 conn
1778 |> assign(:user, user)
1779 |> post("/api/v1/statuses", %{
1780 "media_ids" => [to_string(upload.id)],
1781 "status" => "scheduled",
1782 "scheduled_at" => scheduled_at
1783 })
1784
1785 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
1786 assert %{"type" => "image"} = media_attachment
1787 end
1788
1789 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
1790 %{conn: conn} do
1791 user = insert(:user)
1792
1793 scheduled_at =
1794 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
1795
1796 conn =
1797 conn
1798 |> assign(:user, user)
1799 |> post("/api/v1/statuses", %{
1800 "status" => "not scheduled",
1801 "scheduled_at" => scheduled_at
1802 })
1803
1804 assert %{"content" => "not scheduled"} = json_response(conn, 200)
1805 assert [] == Repo.all(ScheduledActivity)
1806 end
1807
1808 test "returns error when daily user limit is exceeded", %{conn: conn} do
1809 user = insert(:user)
1810
1811 today =
1812 NaiveDateTime.utc_now()
1813 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
1814 |> NaiveDateTime.to_iso8601()
1815
1816 attrs = %{params: %{}, scheduled_at: today}
1817 {:ok, _} = ScheduledActivity.create(user, attrs)
1818 {:ok, _} = ScheduledActivity.create(user, attrs)
1819
1820 conn =
1821 conn
1822 |> assign(:user, user)
1823 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
1824
1825 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
1826 end
1827
1828 test "returns error when total user limit is exceeded", %{conn: conn} do
1829 user = insert(:user)
1830
1831 today =
1832 NaiveDateTime.utc_now()
1833 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
1834 |> NaiveDateTime.to_iso8601()
1835
1836 tomorrow =
1837 NaiveDateTime.utc_now()
1838 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
1839 |> NaiveDateTime.to_iso8601()
1840
1841 attrs = %{params: %{}, scheduled_at: today}
1842 {:ok, _} = ScheduledActivity.create(user, attrs)
1843 {:ok, _} = ScheduledActivity.create(user, attrs)
1844 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
1845
1846 conn =
1847 conn
1848 |> assign(:user, user)
1849 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
1850
1851 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
1852 end
1853
1854 test "shows scheduled activities", %{conn: conn} do
1855 user = insert(:user)
1856 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
1857 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
1858 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
1859 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
1860
1861 conn =
1862 conn
1863 |> assign(:user, user)
1864
1865 # min_id
1866 conn_res =
1867 conn
1868 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
1869
1870 result = json_response(conn_res, 200)
1871 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
1872
1873 # since_id
1874 conn_res =
1875 conn
1876 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
1877
1878 result = json_response(conn_res, 200)
1879 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
1880
1881 # max_id
1882 conn_res =
1883 conn
1884 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
1885
1886 result = json_response(conn_res, 200)
1887 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
1888 end
1889
1890 test "shows a scheduled activity", %{conn: conn} do
1891 user = insert(:user)
1892 scheduled_activity = insert(:scheduled_activity, user: user)
1893
1894 res_conn =
1895 conn
1896 |> assign(:user, user)
1897 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
1898
1899 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
1900 assert scheduled_activity_id == scheduled_activity.id |> to_string()
1901
1902 res_conn =
1903 conn
1904 |> assign(:user, user)
1905 |> get("/api/v1/scheduled_statuses/404")
1906
1907 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
1908 end
1909
1910 test "updates a scheduled activity", %{conn: conn} do
1911 user = insert(:user)
1912 scheduled_activity = insert(:scheduled_activity, user: user)
1913
1914 new_scheduled_at =
1915 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
1916
1917 res_conn =
1918 conn
1919 |> assign(:user, user)
1920 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
1921 scheduled_at: new_scheduled_at
1922 })
1923
1924 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
1925 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
1926
1927 res_conn =
1928 conn
1929 |> assign(:user, user)
1930 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
1931
1932 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
1933 end
1934
1935 test "deletes a scheduled activity", %{conn: conn} do
1936 user = insert(:user)
1937 scheduled_activity = insert(:scheduled_activity, user: user)
1938
1939 res_conn =
1940 conn
1941 |> assign(:user, user)
1942 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
1943
1944 assert %{} = json_response(res_conn, 200)
1945 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
1946
1947 res_conn =
1948 conn
1949 |> assign(:user, user)
1950 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
1951
1952 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
1953 end
1954 end
1955
1956 describe "create account by app" do
1957 test "Account registration via Application", %{conn: conn} do
1958 conn =
1959 conn
1960 |> post("/api/v1/apps", %{
1961 client_name: "client_name",
1962 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
1963 scopes: "read, write, follow"
1964 })
1965
1966 %{
1967 "client_id" => client_id,
1968 "client_secret" => client_secret,
1969 "id" => _,
1970 "name" => "client_name",
1971 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
1972 "vapid_key" => _,
1973 "website" => nil
1974 } = json_response(conn, 200)
1975
1976 conn =
1977 conn
1978 |> post("/oauth/token", %{
1979 grant_type: "client_credentials",
1980 client_id: client_id,
1981 client_secret: client_secret
1982 })
1983
1984 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
1985 json_response(conn, 200)
1986
1987 assert token
1988 token_from_db = Repo.get_by(Token, token: token)
1989 assert token_from_db
1990 assert refresh
1991 assert scope == "read write follow"
1992
1993 conn =
1994 build_conn()
1995 |> put_req_header("authorization", "Bearer " <> token)
1996 |> post("/api/v1/accounts", %{
1997 username: "lain",
1998 email: "lain@example.org",
1999 password: "PlzDontHackLain",
2000 agreement: true
2001 })
2002
2003 %{
2004 "access_token" => token,
2005 "created_at" => _created_at,
2006 "scope" => _scope,
2007 "token_type" => "Bearer"
2008 } = json_response(conn, 200)
2009
2010 token_from_db = Repo.get_by(Token, token: token)
2011 assert token_from_db
2012 token_from_db = Repo.preload(token_from_db, :user)
2013 assert token_from_db.user
2014
2015 assert token_from_db.user.info.confirmation_pending
2016 end
2017
2018 test "rate limit", %{conn: conn} do
2019 app_token = insert(:oauth_token, user: nil)
2020
2021 conn =
2022 put_req_header(conn, "authorization", "Bearer " <> app_token.token)
2023 |> Map.put(:remote_ip, {15, 15, 15, 15})
2024
2025 for i <- 1..5 do
2026 conn =
2027 conn
2028 |> post("/api/v1/accounts", %{
2029 username: "#{i}lain",
2030 email: "#{i}lain@example.org",
2031 password: "PlzDontHackLain",
2032 agreement: true
2033 })
2034
2035 %{
2036 "access_token" => token,
2037 "created_at" => _created_at,
2038 "scope" => _scope,
2039 "token_type" => "Bearer"
2040 } = json_response(conn, 200)
2041
2042 token_from_db = Repo.get_by(Token, token: token)
2043 assert token_from_db
2044 token_from_db = Repo.preload(token_from_db, :user)
2045 assert token_from_db.user
2046
2047 assert token_from_db.user.info.confirmation_pending
2048 end
2049
2050 conn =
2051 conn
2052 |> post("/api/v1/accounts", %{
2053 username: "6lain",
2054 email: "6lain@example.org",
2055 password: "PlzDontHackLain",
2056 agreement: true
2057 })
2058
2059 assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
2060 end
2061 end
2062
2063 describe "GET /api/v1/polls/:id" do
2064 test "returns poll entity for object id", %{conn: conn} do
2065 user = insert(:user)
2066
2067 {:ok, activity} =
2068 CommonAPI.post(user, %{
2069 "status" => "Pleroma does",
2070 "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}
2071 })
2072
2073 object = Object.normalize(activity)
2074
2075 conn =
2076 conn
2077 |> assign(:user, user)
2078 |> get("/api/v1/polls/#{object.id}")
2079
2080 response = json_response(conn, 200)
2081 id = to_string(object.id)
2082 assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
2083 end
2084
2085 test "does not expose polls for private statuses", %{conn: conn} do
2086 user = insert(:user)
2087 other_user = insert(:user)
2088
2089 {:ok, activity} =
2090 CommonAPI.post(user, %{
2091 "status" => "Pleroma does",
2092 "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20},
2093 "visibility" => "private"
2094 })
2095
2096 object = Object.normalize(activity)
2097
2098 conn =
2099 conn
2100 |> assign(:user, other_user)
2101 |> get("/api/v1/polls/#{object.id}")
2102
2103 assert json_response(conn, 404)
2104 end
2105 end
2106
2107 describe "POST /api/v1/polls/:id/votes" do
2108 test "votes are added to the poll", %{conn: conn} do
2109 user = insert(:user)
2110 other_user = insert(:user)
2111
2112 {:ok, activity} =
2113 CommonAPI.post(user, %{
2114 "status" => "A very delicious sandwich",
2115 "poll" => %{
2116 "options" => ["Lettuce", "Grilled Bacon", "Tomato"],
2117 "expires_in" => 20,
2118 "multiple" => true
2119 }
2120 })
2121
2122 object = Object.normalize(activity)
2123
2124 conn =
2125 conn
2126 |> assign(:user, other_user)
2127 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
2128
2129 assert json_response(conn, 200)
2130 object = Object.get_by_id(object.id)
2131
2132 assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
2133 total_items == 1
2134 end)
2135 end
2136
2137 test "author can't vote", %{conn: conn} do
2138 user = insert(:user)
2139
2140 {:ok, activity} =
2141 CommonAPI.post(user, %{
2142 "status" => "Am I cute?",
2143 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
2144 })
2145
2146 object = Object.normalize(activity)
2147
2148 assert conn
2149 |> assign(:user, user)
2150 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
2151 |> json_response(422) == %{"error" => "Poll's author can't vote"}
2152
2153 object = Object.get_by_id(object.id)
2154
2155 refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
2156 end
2157
2158 test "does not allow multiple choices on a single-choice question", %{conn: conn} do
2159 user = insert(:user)
2160 other_user = insert(:user)
2161
2162 {:ok, activity} =
2163 CommonAPI.post(user, %{
2164 "status" => "The glass is",
2165 "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20}
2166 })
2167
2168 object = Object.normalize(activity)
2169
2170 assert conn
2171 |> assign(:user, other_user)
2172 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
2173 |> json_response(422) == %{"error" => "Too many choices"}
2174
2175 object = Object.get_by_id(object.id)
2176
2177 refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
2178 total_items == 1
2179 end)
2180 end
2181
2182 test "does not allow choice index to be greater than options count", %{conn: conn} do
2183 user = insert(:user)
2184 other_user = insert(:user)
2185
2186 {:ok, activity} =
2187 CommonAPI.post(user, %{
2188 "status" => "Am I cute?",
2189 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
2190 })
2191
2192 object = Object.normalize(activity)
2193
2194 conn =
2195 conn
2196 |> assign(:user, other_user)
2197 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
2198
2199 assert json_response(conn, 422) == %{"error" => "Invalid indices"}
2200 end
2201
2202 test "returns 404 error when object is not exist", %{conn: conn} do
2203 user = insert(:user)
2204
2205 conn =
2206 conn
2207 |> assign(:user, user)
2208 |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
2209
2210 assert json_response(conn, 404) == %{"error" => "Record not found"}
2211 end
2212
2213 test "returns 404 when poll is private and not available for user", %{conn: conn} do
2214 user = insert(:user)
2215 other_user = insert(:user)
2216
2217 {:ok, activity} =
2218 CommonAPI.post(user, %{
2219 "status" => "Am I cute?",
2220 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20},
2221 "visibility" => "private"
2222 })
2223
2224 object = Object.normalize(activity)
2225
2226 conn =
2227 conn
2228 |> assign(:user, other_user)
2229 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
2230
2231 assert json_response(conn, 404) == %{"error" => "Record not found"}
2232 end
2233 end
2234
2235 describe "POST /auth/password, with valid parameters" do
2236 setup %{conn: conn} do
2237 user = insert(:user)
2238 conn = post(conn, "/auth/password?email=#{user.email}")
2239 %{conn: conn, user: user}
2240 end
2241
2242 test "it returns 204", %{conn: conn} do
2243 assert json_response(conn, :no_content)
2244 end
2245
2246 test "it creates a PasswordResetToken record for user", %{user: user} do
2247 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
2248 assert token_record
2249 end
2250
2251 test "it sends an email to user", %{user: user} do
2252 ObanHelpers.perform_all()
2253 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
2254
2255 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
2256 notify_email = Config.get([:instance, :notify_email])
2257 instance_name = Config.get([:instance, :name])
2258
2259 assert_email_sent(
2260 from: {instance_name, notify_email},
2261 to: {user.name, user.email},
2262 html_body: email.html_body
2263 )
2264 end
2265 end
2266
2267 describe "POST /auth/password, with invalid parameters" do
2268 setup do
2269 user = insert(:user)
2270 {:ok, user: user}
2271 end
2272
2273 test "it returns 404 when user is not found", %{conn: conn, user: user} do
2274 conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
2275 assert conn.status == 404
2276 assert conn.resp_body == ""
2277 end
2278
2279 test "it returns 400 when user is not local", %{conn: conn, user: user} do
2280 {:ok, user} = Repo.update(Changeset.change(user, local: false))
2281 conn = post(conn, "/auth/password?email=#{user.email}")
2282 assert conn.status == 400
2283 assert conn.resp_body == ""
2284 end
2285 end
2286
2287 describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
2288 setup do
2289 {:ok, user} =
2290 insert(:user)
2291 |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
2292 |> Repo.update()
2293
2294 assert user.info.confirmation_pending
2295
2296 [user: user]
2297 end
2298
2299 clear_config([:instance, :account_activation_required]) do
2300 Config.put([:instance, :account_activation_required], true)
2301 end
2302
2303 test "resend account confirmation email", %{conn: conn, user: user} do
2304 conn
2305 |> assign(:user, user)
2306 |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
2307 |> json_response(:no_content)
2308
2309 ObanHelpers.perform_all()
2310
2311 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
2312 notify_email = Config.get([:instance, :notify_email])
2313 instance_name = Config.get([:instance, :name])
2314
2315 assert_email_sent(
2316 from: {instance_name, notify_email},
2317 to: {user.name, user.email},
2318 html_body: email.html_body
2319 )
2320 end
2321 end
2322
2323 describe "GET /api/v1/suggestions" do
2324 setup do
2325 user = insert(:user)
2326 other_user = insert(:user)
2327 host = Config.get([Pleroma.Web.Endpoint, :url, :host])
2328 url500 = "http://test500?#{host}&#{user.nickname}"
2329 url200 = "http://test200?#{host}&#{user.nickname}"
2330
2331 mock(fn
2332 %{method: :get, url: ^url500} ->
2333 %Tesla.Env{status: 500, body: "bad request"}
2334
2335 %{method: :get, url: ^url200} ->
2336 %Tesla.Env{
2337 status: 200,
2338 body:
2339 ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
2340 other_user.ap_id
2341 }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
2342 }
2343 end)
2344
2345 [user: user, other_user: other_user]
2346 end
2347
2348 clear_config(:suggestions)
2349
2350 test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
2351 Config.put([:suggestions, :enabled], false)
2352
2353 res =
2354 conn
2355 |> assign(:user, user)
2356 |> get("/api/v1/suggestions")
2357 |> json_response(200)
2358
2359 assert res == []
2360 end
2361
2362 test "returns error", %{conn: conn, user: user} do
2363 Config.put([:suggestions, :enabled], true)
2364 Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
2365
2366 assert capture_log(fn ->
2367 res =
2368 conn
2369 |> assign(:user, user)
2370 |> get("/api/v1/suggestions")
2371 |> json_response(500)
2372
2373 assert res == "Something went wrong"
2374 end) =~ "Could not retrieve suggestions"
2375 end
2376
2377 test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
2378 Config.put([:suggestions, :enabled], true)
2379 Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}")
2380
2381 res =
2382 conn
2383 |> assign(:user, user)
2384 |> get("/api/v1/suggestions")
2385 |> json_response(200)
2386
2387 assert res == [
2388 %{
2389 "acct" => "yj455",
2390 "avatar" => "https://social.heldscal.la/avatar/201.jpeg",
2391 "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg",
2392 "id" => 0
2393 },
2394 %{
2395 "acct" => other_user.ap_id,
2396 "avatar" => "https://social.heldscal.la/avatar/202.jpeg",
2397 "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg",
2398 "id" => other_user.id
2399 }
2400 ]
2401 end
2402 end
2403 end