Merge branch 'refactor/status-controller' into 'develop'
[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 "/api/v1/follow_requests works" do
574 user = insert(:user, %{info: %User.Info{locked: true}})
575 other_user = insert(:user)
576
577 {:ok, _activity} = ActivityPub.follow(other_user, user)
578
579 user = User.get_cached_by_id(user.id)
580 other_user = User.get_cached_by_id(other_user.id)
581
582 assert User.following?(other_user, user) == false
583
584 conn =
585 build_conn()
586 |> assign(:user, user)
587 |> get("/api/v1/follow_requests")
588
589 assert [relationship] = json_response(conn, 200)
590 assert to_string(other_user.id) == relationship["id"]
591 end
592
593 test "/api/v1/follow_requests/:id/authorize works" do
594 user = insert(:user, %{info: %User.Info{locked: true}})
595 other_user = insert(:user)
596
597 {:ok, _activity} = ActivityPub.follow(other_user, user)
598
599 user = User.get_cached_by_id(user.id)
600 other_user = User.get_cached_by_id(other_user.id)
601
602 assert User.following?(other_user, user) == false
603
604 conn =
605 build_conn()
606 |> assign(:user, user)
607 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
608
609 assert relationship = json_response(conn, 200)
610 assert to_string(other_user.id) == relationship["id"]
611
612 user = User.get_cached_by_id(user.id)
613 other_user = User.get_cached_by_id(other_user.id)
614
615 assert User.following?(other_user, user) == true
616 end
617
618 test "verify_credentials", %{conn: conn} do
619 user = insert(:user, %{info: %User.Info{default_scope: "private"}})
620
621 conn =
622 conn
623 |> assign(:user, user)
624 |> get("/api/v1/accounts/verify_credentials")
625
626 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
627 assert id == to_string(user.id)
628 end
629
630 test "/api/v1/follow_requests/:id/reject works" do
631 user = insert(:user, %{info: %User.Info{locked: true}})
632 other_user = insert(:user)
633
634 {:ok, _activity} = ActivityPub.follow(other_user, user)
635
636 user = User.get_cached_by_id(user.id)
637
638 conn =
639 build_conn()
640 |> assign(:user, user)
641 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
642
643 assert relationship = json_response(conn, 200)
644 assert to_string(other_user.id) == relationship["id"]
645
646 user = User.get_cached_by_id(user.id)
647 other_user = User.get_cached_by_id(other_user.id)
648
649 assert User.following?(other_user, user) == false
650 end
651 end
652
653 describe "account fetching" do
654 test "works by id" do
655 user = insert(:user)
656
657 conn =
658 build_conn()
659 |> get("/api/v1/accounts/#{user.id}")
660
661 assert %{"id" => id} = json_response(conn, 200)
662 assert id == to_string(user.id)
663
664 conn =
665 build_conn()
666 |> get("/api/v1/accounts/-1")
667
668 assert %{"error" => "Can't find user"} = json_response(conn, 404)
669 end
670
671 test "works by nickname" do
672 user = insert(:user)
673
674 conn =
675 build_conn()
676 |> get("/api/v1/accounts/#{user.nickname}")
677
678 assert %{"id" => id} = json_response(conn, 200)
679 assert id == user.id
680 end
681
682 test "works by nickname for remote users" do
683 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
684 Pleroma.Config.put([:instance, :limit_to_local_content], false)
685 user = insert(:user, nickname: "user@example.com", local: false)
686
687 conn =
688 build_conn()
689 |> get("/api/v1/accounts/#{user.nickname}")
690
691 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
692 assert %{"id" => id} = json_response(conn, 200)
693 assert id == user.id
694 end
695
696 test "respects limit_to_local_content == :all for remote user nicknames" do
697 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
698 Pleroma.Config.put([:instance, :limit_to_local_content], :all)
699
700 user = insert(:user, nickname: "user@example.com", local: false)
701
702 conn =
703 build_conn()
704 |> get("/api/v1/accounts/#{user.nickname}")
705
706 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
707 assert json_response(conn, 404)
708 end
709
710 test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
711 limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
712 Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
713
714 user = insert(:user, nickname: "user@example.com", local: false)
715 reading_user = insert(:user)
716
717 conn =
718 build_conn()
719 |> get("/api/v1/accounts/#{user.nickname}")
720
721 assert json_response(conn, 404)
722
723 conn =
724 build_conn()
725 |> assign(:user, reading_user)
726 |> get("/api/v1/accounts/#{user.nickname}")
727
728 Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
729 assert %{"id" => id} = json_response(conn, 200)
730 assert id == user.id
731 end
732 end
733
734 test "mascot upload", %{conn: conn} do
735 user = insert(:user)
736
737 non_image_file = %Plug.Upload{
738 content_type: "audio/mpeg",
739 path: Path.absname("test/fixtures/sound.mp3"),
740 filename: "sound.mp3"
741 }
742
743 conn =
744 conn
745 |> assign(:user, user)
746 |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
747
748 assert json_response(conn, 415)
749
750 file = %Plug.Upload{
751 content_type: "image/jpg",
752 path: Path.absname("test/fixtures/image.jpg"),
753 filename: "an_image.jpg"
754 }
755
756 conn =
757 build_conn()
758 |> assign(:user, user)
759 |> put("/api/v1/pleroma/mascot", %{"file" => file})
760
761 assert %{"id" => _, "type" => image} = json_response(conn, 200)
762 end
763
764 test "mascot retrieving", %{conn: conn} do
765 user = insert(:user)
766 # When user hasn't set a mascot, we should just get pleroma tan back
767 conn =
768 conn
769 |> assign(:user, user)
770 |> get("/api/v1/pleroma/mascot")
771
772 assert %{"url" => url} = json_response(conn, 200)
773 assert url =~ "pleroma-fox-tan-smol"
774
775 # When a user sets their mascot, we should get that back
776 file = %Plug.Upload{
777 content_type: "image/jpg",
778 path: Path.absname("test/fixtures/image.jpg"),
779 filename: "an_image.jpg"
780 }
781
782 conn =
783 build_conn()
784 |> assign(:user, user)
785 |> put("/api/v1/pleroma/mascot", %{"file" => file})
786
787 assert json_response(conn, 200)
788
789 user = User.get_cached_by_id(user.id)
790
791 conn =
792 build_conn()
793 |> assign(:user, user)
794 |> get("/api/v1/pleroma/mascot")
795
796 assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
797 assert url =~ "an_image"
798 end
799
800 test "getting followers", %{conn: conn} do
801 user = insert(:user)
802 other_user = insert(:user)
803 {:ok, user} = User.follow(user, other_user)
804
805 conn =
806 conn
807 |> get("/api/v1/accounts/#{other_user.id}/followers")
808
809 assert [%{"id" => id}] = json_response(conn, 200)
810 assert id == to_string(user.id)
811 end
812
813 test "getting followers, hide_followers", %{conn: conn} do
814 user = insert(:user)
815 other_user = insert(:user, %{info: %{hide_followers: true}})
816 {:ok, _user} = User.follow(user, other_user)
817
818 conn =
819 conn
820 |> get("/api/v1/accounts/#{other_user.id}/followers")
821
822 assert [] == json_response(conn, 200)
823 end
824
825 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
826 user = insert(:user)
827 other_user = insert(:user, %{info: %{hide_followers: true}})
828 {:ok, _user} = User.follow(user, other_user)
829
830 conn =
831 conn
832 |> assign(:user, other_user)
833 |> get("/api/v1/accounts/#{other_user.id}/followers")
834
835 refute [] == json_response(conn, 200)
836 end
837
838 test "getting followers, pagination", %{conn: conn} do
839 user = insert(:user)
840 follower1 = insert(:user)
841 follower2 = insert(:user)
842 follower3 = insert(:user)
843 {:ok, _} = User.follow(follower1, user)
844 {:ok, _} = User.follow(follower2, user)
845 {:ok, _} = User.follow(follower3, user)
846
847 conn =
848 conn
849 |> assign(:user, user)
850
851 res_conn =
852 conn
853 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
854
855 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
856 assert id3 == follower3.id
857 assert id2 == follower2.id
858
859 res_conn =
860 conn
861 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
862
863 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
864 assert id2 == follower2.id
865 assert id1 == follower1.id
866
867 res_conn =
868 conn
869 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
870
871 assert [%{"id" => id2}] = json_response(res_conn, 200)
872 assert id2 == follower2.id
873
874 assert [link_header] = get_resp_header(res_conn, "link")
875 assert link_header =~ ~r/min_id=#{follower2.id}/
876 assert link_header =~ ~r/max_id=#{follower2.id}/
877 end
878
879 test "getting following", %{conn: conn} do
880 user = insert(:user)
881 other_user = insert(:user)
882 {:ok, user} = User.follow(user, other_user)
883
884 conn =
885 conn
886 |> get("/api/v1/accounts/#{user.id}/following")
887
888 assert [%{"id" => id}] = json_response(conn, 200)
889 assert id == to_string(other_user.id)
890 end
891
892 test "getting following, hide_follows", %{conn: conn} do
893 user = insert(:user, %{info: %{hide_follows: true}})
894 other_user = insert(:user)
895 {:ok, user} = User.follow(user, other_user)
896
897 conn =
898 conn
899 |> get("/api/v1/accounts/#{user.id}/following")
900
901 assert [] == json_response(conn, 200)
902 end
903
904 test "getting following, hide_follows, same user requesting", %{conn: conn} do
905 user = insert(:user, %{info: %{hide_follows: true}})
906 other_user = insert(:user)
907 {:ok, user} = User.follow(user, other_user)
908
909 conn =
910 conn
911 |> assign(:user, user)
912 |> get("/api/v1/accounts/#{user.id}/following")
913
914 refute [] == json_response(conn, 200)
915 end
916
917 test "getting following, pagination", %{conn: conn} do
918 user = insert(:user)
919 following1 = insert(:user)
920 following2 = insert(:user)
921 following3 = insert(:user)
922 {:ok, _} = User.follow(user, following1)
923 {:ok, _} = User.follow(user, following2)
924 {:ok, _} = User.follow(user, following3)
925
926 conn =
927 conn
928 |> assign(:user, user)
929
930 res_conn =
931 conn
932 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
933
934 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
935 assert id3 == following3.id
936 assert id2 == following2.id
937
938 res_conn =
939 conn
940 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
941
942 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
943 assert id2 == following2.id
944 assert id1 == following1.id
945
946 res_conn =
947 conn
948 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
949
950 assert [%{"id" => id2}] = json_response(res_conn, 200)
951 assert id2 == following2.id
952
953 assert [link_header] = get_resp_header(res_conn, "link")
954 assert link_header =~ ~r/min_id=#{following2.id}/
955 assert link_header =~ ~r/max_id=#{following2.id}/
956 end
957
958 test "following / unfollowing a user", %{conn: conn} do
959 user = insert(:user)
960 other_user = insert(:user)
961
962 conn =
963 conn
964 |> assign(:user, user)
965 |> post("/api/v1/accounts/#{other_user.id}/follow")
966
967 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
968
969 user = User.get_cached_by_id(user.id)
970
971 conn =
972 build_conn()
973 |> assign(:user, user)
974 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
975
976 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
977
978 user = User.get_cached_by_id(user.id)
979
980 conn =
981 build_conn()
982 |> assign(:user, user)
983 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
984
985 assert %{"id" => id} = json_response(conn, 200)
986 assert id == to_string(other_user.id)
987 end
988
989 test "following without reblogs" do
990 follower = insert(:user)
991 followed = insert(:user)
992 other_user = insert(:user)
993
994 conn =
995 build_conn()
996 |> assign(:user, follower)
997 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
998
999 assert %{"showing_reblogs" => false} = json_response(conn, 200)
1000
1001 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
1002 {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
1003
1004 conn =
1005 build_conn()
1006 |> assign(:user, User.get_cached_by_id(follower.id))
1007 |> get("/api/v1/timelines/home")
1008
1009 assert [] == json_response(conn, 200)
1010
1011 conn =
1012 build_conn()
1013 |> assign(:user, follower)
1014 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
1015
1016 assert %{"showing_reblogs" => true} = json_response(conn, 200)
1017
1018 conn =
1019 build_conn()
1020 |> assign(:user, User.get_cached_by_id(follower.id))
1021 |> get("/api/v1/timelines/home")
1022
1023 expected_activity_id = reblog.id
1024 assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
1025 end
1026
1027 test "following / unfollowing errors" do
1028 user = insert(:user)
1029
1030 conn =
1031 build_conn()
1032 |> assign(:user, user)
1033
1034 # self follow
1035 conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
1036 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1037
1038 # self unfollow
1039 user = User.get_cached_by_id(user.id)
1040 conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
1041 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1042
1043 # self follow via uri
1044 user = User.get_cached_by_id(user.id)
1045 conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
1046 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1047
1048 # follow non existing user
1049 conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
1050 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1051
1052 # follow non existing user via uri
1053 conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
1054 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1055
1056 # unfollow non existing user
1057 conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
1058 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1059 end
1060
1061 describe "mute/unmute" do
1062 test "with notifications", %{conn: conn} do
1063 user = insert(:user)
1064 other_user = insert(:user)
1065
1066 conn =
1067 conn
1068 |> assign(:user, user)
1069 |> post("/api/v1/accounts/#{other_user.id}/mute")
1070
1071 response = json_response(conn, 200)
1072
1073 assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
1074 user = User.get_cached_by_id(user.id)
1075
1076 conn =
1077 build_conn()
1078 |> assign(:user, user)
1079 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1080
1081 response = json_response(conn, 200)
1082 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
1083 end
1084
1085 test "without notifications", %{conn: conn} do
1086 user = insert(:user)
1087 other_user = insert(:user)
1088
1089 conn =
1090 conn
1091 |> assign(:user, user)
1092 |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
1093
1094 response = json_response(conn, 200)
1095
1096 assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
1097 user = User.get_cached_by_id(user.id)
1098
1099 conn =
1100 build_conn()
1101 |> assign(:user, user)
1102 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1103
1104 response = json_response(conn, 200)
1105 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
1106 end
1107 end
1108
1109 test "subscribing / unsubscribing to a user", %{conn: conn} do
1110 user = insert(:user)
1111 subscription_target = insert(:user)
1112
1113 conn =
1114 conn
1115 |> assign(:user, user)
1116 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
1117
1118 assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
1119
1120 conn =
1121 build_conn()
1122 |> assign(:user, user)
1123 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
1124
1125 assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
1126 end
1127
1128 test "getting a list of mutes", %{conn: conn} do
1129 user = insert(:user)
1130 other_user = insert(:user)
1131
1132 {:ok, user} = User.mute(user, other_user)
1133
1134 conn =
1135 conn
1136 |> assign(:user, user)
1137 |> get("/api/v1/mutes")
1138
1139 other_user_id = to_string(other_user.id)
1140 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1141 end
1142
1143 test "blocking / unblocking a user", %{conn: conn} do
1144 user = insert(:user)
1145 other_user = insert(:user)
1146
1147 conn =
1148 conn
1149 |> assign(:user, user)
1150 |> post("/api/v1/accounts/#{other_user.id}/block")
1151
1152 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1153
1154 user = User.get_cached_by_id(user.id)
1155
1156 conn =
1157 build_conn()
1158 |> assign(:user, user)
1159 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1160
1161 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1162 end
1163
1164 test "getting a list of blocks", %{conn: conn} do
1165 user = insert(:user)
1166 other_user = insert(:user)
1167
1168 {:ok, user} = User.block(user, other_user)
1169
1170 conn =
1171 conn
1172 |> assign(:user, user)
1173 |> get("/api/v1/blocks")
1174
1175 other_user_id = to_string(other_user.id)
1176 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1177 end
1178
1179 test "blocking / unblocking a domain", %{conn: conn} do
1180 user = insert(:user)
1181 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1182
1183 conn =
1184 conn
1185 |> assign(:user, user)
1186 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1187
1188 assert %{} = json_response(conn, 200)
1189 user = User.get_cached_by_ap_id(user.ap_id)
1190 assert User.blocks?(user, other_user)
1191
1192 conn =
1193 build_conn()
1194 |> assign(:user, user)
1195 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1196
1197 assert %{} = json_response(conn, 200)
1198 user = User.get_cached_by_ap_id(user.ap_id)
1199 refute User.blocks?(user, other_user)
1200 end
1201
1202 test "getting a list of domain blocks", %{conn: conn} do
1203 user = insert(:user)
1204
1205 {:ok, user} = User.block_domain(user, "bad.site")
1206 {:ok, user} = User.block_domain(user, "even.worse.site")
1207
1208 conn =
1209 conn
1210 |> assign(:user, user)
1211 |> get("/api/v1/domain_blocks")
1212
1213 domain_blocks = json_response(conn, 200)
1214
1215 assert "bad.site" in domain_blocks
1216 assert "even.worse.site" in domain_blocks
1217 end
1218
1219 test "unimplemented follow_requests, blocks, domain blocks" do
1220 user = insert(:user)
1221
1222 ["blocks", "domain_blocks", "follow_requests"]
1223 |> Enum.each(fn endpoint ->
1224 conn =
1225 build_conn()
1226 |> assign(:user, user)
1227 |> get("/api/v1/#{endpoint}")
1228
1229 assert [] = json_response(conn, 200)
1230 end)
1231 end
1232
1233 test "returns the favorites of a user", %{conn: conn} do
1234 user = insert(:user)
1235 other_user = insert(:user)
1236
1237 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1238 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1239
1240 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1241
1242 first_conn =
1243 conn
1244 |> assign(:user, user)
1245 |> get("/api/v1/favourites")
1246
1247 assert [status] = json_response(first_conn, 200)
1248 assert status["id"] == to_string(activity.id)
1249
1250 assert [{"link", _link_header}] =
1251 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1252
1253 # Honours query params
1254 {:ok, second_activity} =
1255 CommonAPI.post(other_user, %{
1256 "status" =>
1257 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1258 })
1259
1260 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1261
1262 last_like = status["id"]
1263
1264 second_conn =
1265 conn
1266 |> assign(:user, user)
1267 |> get("/api/v1/favourites?since_id=#{last_like}")
1268
1269 assert [second_status] = json_response(second_conn, 200)
1270 assert second_status["id"] == to_string(second_activity.id)
1271
1272 third_conn =
1273 conn
1274 |> assign(:user, user)
1275 |> get("/api/v1/favourites?limit=0")
1276
1277 assert [] = json_response(third_conn, 200)
1278 end
1279
1280 describe "getting favorites timeline of specified user" do
1281 setup do
1282 [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
1283 [current_user: current_user, user: user]
1284 end
1285
1286 test "returns list of statuses favorited by specified user", %{
1287 conn: conn,
1288 current_user: current_user,
1289 user: user
1290 } do
1291 [activity | _] = insert_pair(:note_activity)
1292 CommonAPI.favorite(activity.id, user)
1293
1294 response =
1295 conn
1296 |> assign(:user, current_user)
1297 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1298 |> json_response(:ok)
1299
1300 [like] = response
1301
1302 assert length(response) == 1
1303 assert like["id"] == activity.id
1304 end
1305
1306 test "returns favorites for specified user_id when user is not logged in", %{
1307 conn: conn,
1308 user: user
1309 } do
1310 activity = insert(:note_activity)
1311 CommonAPI.favorite(activity.id, user)
1312
1313 response =
1314 conn
1315 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1316 |> json_response(:ok)
1317
1318 assert length(response) == 1
1319 end
1320
1321 test "returns favorited DM only when user is logged in and he is one of recipients", %{
1322 conn: conn,
1323 current_user: current_user,
1324 user: user
1325 } do
1326 {:ok, direct} =
1327 CommonAPI.post(current_user, %{
1328 "status" => "Hi @#{user.nickname}!",
1329 "visibility" => "direct"
1330 })
1331
1332 CommonAPI.favorite(direct.id, user)
1333
1334 response =
1335 conn
1336 |> assign(:user, current_user)
1337 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1338 |> json_response(:ok)
1339
1340 assert length(response) == 1
1341
1342 anonymous_response =
1343 conn
1344 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1345 |> json_response(:ok)
1346
1347 assert Enum.empty?(anonymous_response)
1348 end
1349
1350 test "does not return others' favorited DM when user is not one of recipients", %{
1351 conn: conn,
1352 current_user: current_user,
1353 user: user
1354 } do
1355 user_two = insert(:user)
1356
1357 {:ok, direct} =
1358 CommonAPI.post(user_two, %{
1359 "status" => "Hi @#{user.nickname}!",
1360 "visibility" => "direct"
1361 })
1362
1363 CommonAPI.favorite(direct.id, user)
1364
1365 response =
1366 conn
1367 |> assign(:user, current_user)
1368 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1369 |> json_response(:ok)
1370
1371 assert Enum.empty?(response)
1372 end
1373
1374 test "paginates favorites using since_id and max_id", %{
1375 conn: conn,
1376 current_user: current_user,
1377 user: user
1378 } do
1379 activities = insert_list(10, :note_activity)
1380
1381 Enum.each(activities, fn activity ->
1382 CommonAPI.favorite(activity.id, user)
1383 end)
1384
1385 third_activity = Enum.at(activities, 2)
1386 seventh_activity = Enum.at(activities, 6)
1387
1388 response =
1389 conn
1390 |> assign(:user, current_user)
1391 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
1392 since_id: third_activity.id,
1393 max_id: seventh_activity.id
1394 })
1395 |> json_response(:ok)
1396
1397 assert length(response) == 3
1398 refute third_activity in response
1399 refute seventh_activity in response
1400 end
1401
1402 test "limits favorites using limit parameter", %{
1403 conn: conn,
1404 current_user: current_user,
1405 user: user
1406 } do
1407 7
1408 |> insert_list(:note_activity)
1409 |> Enum.each(fn activity ->
1410 CommonAPI.favorite(activity.id, user)
1411 end)
1412
1413 response =
1414 conn
1415 |> assign(:user, current_user)
1416 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
1417 |> json_response(:ok)
1418
1419 assert length(response) == 3
1420 end
1421
1422 test "returns empty response when user does not have any favorited statuses", %{
1423 conn: conn,
1424 current_user: current_user,
1425 user: user
1426 } do
1427 response =
1428 conn
1429 |> assign(:user, current_user)
1430 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1431 |> json_response(:ok)
1432
1433 assert Enum.empty?(response)
1434 end
1435
1436 test "returns 404 error when specified user is not exist", %{conn: conn} do
1437 conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
1438
1439 assert json_response(conn, 404) == %{"error" => "Record not found"}
1440 end
1441
1442 test "returns 403 error when user has hidden own favorites", %{
1443 conn: conn,
1444 current_user: current_user
1445 } do
1446 user = insert(:user, %{info: %{hide_favorites: true}})
1447 activity = insert(:note_activity)
1448 CommonAPI.favorite(activity.id, user)
1449
1450 conn =
1451 conn
1452 |> assign(:user, current_user)
1453 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1454
1455 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
1456 end
1457
1458 test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
1459 user = insert(:user)
1460 activity = insert(:note_activity)
1461 CommonAPI.favorite(activity.id, user)
1462
1463 conn =
1464 conn
1465 |> assign(:user, current_user)
1466 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
1467
1468 assert user.info.hide_favorites
1469 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
1470 end
1471 end
1472
1473 test "get instance information", %{conn: conn} do
1474 conn = get(conn, "/api/v1/instance")
1475 assert result = json_response(conn, 200)
1476
1477 email = Config.get([:instance, :email])
1478 # Note: not checking for "max_toot_chars" since it's optional
1479 assert %{
1480 "uri" => _,
1481 "title" => _,
1482 "description" => _,
1483 "version" => _,
1484 "email" => from_config_email,
1485 "urls" => %{
1486 "streaming_api" => _
1487 },
1488 "stats" => _,
1489 "thumbnail" => _,
1490 "languages" => _,
1491 "registrations" => _,
1492 "poll_limits" => _
1493 } = result
1494
1495 assert email == from_config_email
1496 end
1497
1498 test "get instance stats", %{conn: conn} do
1499 user = insert(:user, %{local: true})
1500
1501 user2 = insert(:user, %{local: true})
1502 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
1503
1504 insert(:user, %{local: false, nickname: "u@peer1.com"})
1505 insert(:user, %{local: false, nickname: "u@peer2.com"})
1506
1507 {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"})
1508
1509 # Stats should count users with missing or nil `info.deactivated` value
1510
1511 {:ok, _user} =
1512 user.id
1513 |> User.get_cached_by_id()
1514 |> User.update_info(&Changeset.change(&1, %{deactivated: nil}))
1515
1516 Pleroma.Stats.force_update()
1517
1518 conn = get(conn, "/api/v1/instance")
1519
1520 assert result = json_response(conn, 200)
1521
1522 stats = result["stats"]
1523
1524 assert stats
1525 assert stats["user_count"] == 1
1526 assert stats["status_count"] == 1
1527 assert stats["domain_count"] == 2
1528 end
1529
1530 test "get peers", %{conn: conn} do
1531 insert(:user, %{local: false, nickname: "u@peer1.com"})
1532 insert(:user, %{local: false, nickname: "u@peer2.com"})
1533
1534 Pleroma.Stats.force_update()
1535
1536 conn = get(conn, "/api/v1/instance/peers")
1537
1538 assert result = json_response(conn, 200)
1539
1540 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
1541 end
1542
1543 test "put settings", %{conn: conn} do
1544 user = insert(:user)
1545
1546 conn =
1547 conn
1548 |> assign(:user, user)
1549 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
1550
1551 assert _result = json_response(conn, 200)
1552
1553 user = User.get_cached_by_ap_id(user.ap_id)
1554 assert user.info.settings == %{"programming" => "socks"}
1555 end
1556
1557 describe "pinned statuses" do
1558 setup do
1559 user = insert(:user)
1560 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
1561
1562 [user: user, activity: activity]
1563 end
1564
1565 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
1566 {:ok, _} = CommonAPI.pin(activity.id, user)
1567
1568 result =
1569 conn
1570 |> assign(:user, user)
1571 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1572 |> json_response(200)
1573
1574 id_str = to_string(activity.id)
1575
1576 assert [%{"id" => ^id_str, "pinned" => true}] = result
1577 end
1578 end
1579
1580 describe "reports" do
1581 setup do
1582 reporter = insert(:user)
1583 target_user = insert(:user)
1584
1585 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
1586
1587 [reporter: reporter, target_user: target_user, activity: activity]
1588 end
1589
1590 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
1591 assert %{"action_taken" => false, "id" => _} =
1592 conn
1593 |> assign(:user, reporter)
1594 |> post("/api/v1/reports", %{"account_id" => target_user.id})
1595 |> json_response(200)
1596 end
1597
1598 test "submit a report with statuses and comment", %{
1599 conn: conn,
1600 reporter: reporter,
1601 target_user: target_user,
1602 activity: activity
1603 } do
1604 assert %{"action_taken" => false, "id" => _} =
1605 conn
1606 |> assign(:user, reporter)
1607 |> post("/api/v1/reports", %{
1608 "account_id" => target_user.id,
1609 "status_ids" => [activity.id],
1610 "comment" => "bad status!",
1611 "forward" => "false"
1612 })
1613 |> json_response(200)
1614 end
1615
1616 test "account_id is required", %{
1617 conn: conn,
1618 reporter: reporter,
1619 activity: activity
1620 } do
1621 assert %{"error" => "Valid `account_id` required"} =
1622 conn
1623 |> assign(:user, reporter)
1624 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
1625 |> json_response(400)
1626 end
1627
1628 test "comment must be up to the size specified in the config", %{
1629 conn: conn,
1630 reporter: reporter,
1631 target_user: target_user
1632 } do
1633 max_size = Config.get([:instance, :max_report_comment_size], 1000)
1634 comment = String.pad_trailing("a", max_size + 1, "a")
1635
1636 error = %{"error" => "Comment must be up to #{max_size} characters"}
1637
1638 assert ^error =
1639 conn
1640 |> assign(:user, reporter)
1641 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
1642 |> json_response(400)
1643 end
1644
1645 test "returns error when account is not exist", %{
1646 conn: conn,
1647 reporter: reporter,
1648 activity: activity
1649 } do
1650 conn =
1651 conn
1652 |> assign(:user, reporter)
1653 |> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"})
1654
1655 assert json_response(conn, 400) == %{"error" => "Account not found"}
1656 end
1657 end
1658
1659 describe "link headers" do
1660 test "preserves parameters in link headers", %{conn: conn} do
1661 user = insert(:user)
1662 other_user = insert(:user)
1663
1664 {:ok, activity1} =
1665 CommonAPI.post(other_user, %{
1666 "status" => "hi @#{user.nickname}",
1667 "visibility" => "public"
1668 })
1669
1670 {:ok, activity2} =
1671 CommonAPI.post(other_user, %{
1672 "status" => "hi @#{user.nickname}",
1673 "visibility" => "public"
1674 })
1675
1676 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
1677 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
1678
1679 conn =
1680 conn
1681 |> assign(:user, user)
1682 |> get("/api/v1/notifications", %{media_only: true})
1683
1684 assert [link_header] = get_resp_header(conn, "link")
1685 assert link_header =~ ~r/media_only=true/
1686 assert link_header =~ ~r/min_id=#{notification2.id}/
1687 assert link_header =~ ~r/max_id=#{notification1.id}/
1688 end
1689 end
1690
1691 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
1692 # Need to set an old-style integer ID to reproduce the problem
1693 # (these are no longer assigned to new accounts but were preserved
1694 # for existing accounts during the migration to flakeIDs)
1695 user_one = insert(:user, %{id: 1212})
1696 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
1697
1698 resp_one =
1699 conn
1700 |> get("/api/v1/accounts/#{user_one.id}")
1701
1702 resp_two =
1703 conn
1704 |> get("/api/v1/accounts/#{user_two.nickname}")
1705
1706 resp_three =
1707 conn
1708 |> get("/api/v1/accounts/#{user_two.id}")
1709
1710 acc_one = json_response(resp_one, 200)
1711 acc_two = json_response(resp_two, 200)
1712 acc_three = json_response(resp_three, 200)
1713 refute acc_one == acc_two
1714 assert acc_two == acc_three
1715 end
1716
1717 describe "custom emoji" do
1718 test "with tags", %{conn: conn} do
1719 [emoji | _body] =
1720 conn
1721 |> get("/api/v1/custom_emojis")
1722 |> json_response(200)
1723
1724 assert Map.has_key?(emoji, "shortcode")
1725 assert Map.has_key?(emoji, "static_url")
1726 assert Map.has_key?(emoji, "tags")
1727 assert is_list(emoji["tags"])
1728 assert Map.has_key?(emoji, "category")
1729 assert Map.has_key?(emoji, "url")
1730 assert Map.has_key?(emoji, "visible_in_picker")
1731 end
1732 end
1733
1734 describe "index/2 redirections" do
1735 setup %{conn: conn} do
1736 session_opts = [
1737 store: :cookie,
1738 key: "_test",
1739 signing_salt: "cooldude"
1740 ]
1741
1742 conn =
1743 conn
1744 |> Plug.Session.call(Plug.Session.init(session_opts))
1745 |> fetch_session()
1746
1747 test_path = "/web/statuses/test"
1748 %{conn: conn, path: test_path}
1749 end
1750
1751 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
1752 conn = get(conn, path)
1753
1754 assert conn.status == 302
1755 assert redirected_to(conn) == "/web/login"
1756 end
1757
1758 test "redirects not logged-in users to the login page on private instances", %{
1759 conn: conn,
1760 path: path
1761 } do
1762 Config.put([:instance, :public], false)
1763
1764 conn = get(conn, path)
1765
1766 assert conn.status == 302
1767 assert redirected_to(conn) == "/web/login"
1768 end
1769
1770 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
1771 token = insert(:oauth_token)
1772
1773 conn =
1774 conn
1775 |> assign(:user, token.user)
1776 |> put_session(:oauth_token, token.token)
1777 |> get(path)
1778
1779 assert conn.status == 200
1780 end
1781
1782 test "saves referer path to session", %{conn: conn, path: path} do
1783 conn = get(conn, path)
1784 return_to = Plug.Conn.get_session(conn, :return_to)
1785
1786 assert return_to == path
1787 end
1788
1789 test "redirects to the saved path after log in", %{conn: conn, path: path} do
1790 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
1791 auth = insert(:oauth_authorization, app: app)
1792
1793 conn =
1794 conn
1795 |> put_session(:return_to, path)
1796 |> get("/web/login", %{code: auth.token})
1797
1798 assert conn.status == 302
1799 assert redirected_to(conn) == path
1800 end
1801
1802 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
1803 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
1804 auth = insert(:oauth_authorization, app: app)
1805
1806 conn = get(conn, "/web/login", %{code: auth.token})
1807
1808 assert conn.status == 302
1809 assert redirected_to(conn) == "/web/getting-started"
1810 end
1811 end
1812
1813 describe "scheduled activities" do
1814 test "creates a scheduled activity", %{conn: conn} do
1815 user = insert(:user)
1816 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
1817
1818 conn =
1819 conn
1820 |> assign(:user, user)
1821 |> post("/api/v1/statuses", %{
1822 "status" => "scheduled",
1823 "scheduled_at" => scheduled_at
1824 })
1825
1826 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
1827 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
1828 assert [] == Repo.all(Activity)
1829 end
1830
1831 test "creates a scheduled activity with a media attachment", %{conn: conn} do
1832 user = insert(:user)
1833 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
1834
1835 file = %Plug.Upload{
1836 content_type: "image/jpg",
1837 path: Path.absname("test/fixtures/image.jpg"),
1838 filename: "an_image.jpg"
1839 }
1840
1841 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
1842
1843 conn =
1844 conn
1845 |> assign(:user, user)
1846 |> post("/api/v1/statuses", %{
1847 "media_ids" => [to_string(upload.id)],
1848 "status" => "scheduled",
1849 "scheduled_at" => scheduled_at
1850 })
1851
1852 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
1853 assert %{"type" => "image"} = media_attachment
1854 end
1855
1856 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
1857 %{conn: conn} do
1858 user = insert(:user)
1859
1860 scheduled_at =
1861 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
1862
1863 conn =
1864 conn
1865 |> assign(:user, user)
1866 |> post("/api/v1/statuses", %{
1867 "status" => "not scheduled",
1868 "scheduled_at" => scheduled_at
1869 })
1870
1871 assert %{"content" => "not scheduled"} = json_response(conn, 200)
1872 assert [] == Repo.all(ScheduledActivity)
1873 end
1874
1875 test "returns error when daily user limit is exceeded", %{conn: conn} do
1876 user = insert(:user)
1877
1878 today =
1879 NaiveDateTime.utc_now()
1880 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
1881 |> NaiveDateTime.to_iso8601()
1882
1883 attrs = %{params: %{}, scheduled_at: today}
1884 {:ok, _} = ScheduledActivity.create(user, attrs)
1885 {:ok, _} = ScheduledActivity.create(user, attrs)
1886
1887 conn =
1888 conn
1889 |> assign(:user, user)
1890 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
1891
1892 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
1893 end
1894
1895 test "returns error when total user limit is exceeded", %{conn: conn} do
1896 user = insert(:user)
1897
1898 today =
1899 NaiveDateTime.utc_now()
1900 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
1901 |> NaiveDateTime.to_iso8601()
1902
1903 tomorrow =
1904 NaiveDateTime.utc_now()
1905 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
1906 |> NaiveDateTime.to_iso8601()
1907
1908 attrs = %{params: %{}, scheduled_at: today}
1909 {:ok, _} = ScheduledActivity.create(user, attrs)
1910 {:ok, _} = ScheduledActivity.create(user, attrs)
1911 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
1912
1913 conn =
1914 conn
1915 |> assign(:user, user)
1916 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
1917
1918 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
1919 end
1920
1921 test "shows scheduled activities", %{conn: conn} do
1922 user = insert(:user)
1923 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
1924 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
1925 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
1926 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
1927
1928 conn =
1929 conn
1930 |> assign(:user, user)
1931
1932 # min_id
1933 conn_res =
1934 conn
1935 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
1936
1937 result = json_response(conn_res, 200)
1938 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
1939
1940 # since_id
1941 conn_res =
1942 conn
1943 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
1944
1945 result = json_response(conn_res, 200)
1946 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
1947
1948 # max_id
1949 conn_res =
1950 conn
1951 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
1952
1953 result = json_response(conn_res, 200)
1954 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
1955 end
1956
1957 test "shows a scheduled activity", %{conn: conn} do
1958 user = insert(:user)
1959 scheduled_activity = insert(:scheduled_activity, user: user)
1960
1961 res_conn =
1962 conn
1963 |> assign(:user, user)
1964 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
1965
1966 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
1967 assert scheduled_activity_id == scheduled_activity.id |> to_string()
1968
1969 res_conn =
1970 conn
1971 |> assign(:user, user)
1972 |> get("/api/v1/scheduled_statuses/404")
1973
1974 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
1975 end
1976
1977 test "updates a scheduled activity", %{conn: conn} do
1978 user = insert(:user)
1979 scheduled_activity = insert(:scheduled_activity, user: user)
1980
1981 new_scheduled_at =
1982 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
1983
1984 res_conn =
1985 conn
1986 |> assign(:user, user)
1987 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
1988 scheduled_at: new_scheduled_at
1989 })
1990
1991 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
1992 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
1993
1994 res_conn =
1995 conn
1996 |> assign(:user, user)
1997 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
1998
1999 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2000 end
2001
2002 test "deletes a scheduled activity", %{conn: conn} do
2003 user = insert(:user)
2004 scheduled_activity = insert(:scheduled_activity, user: user)
2005
2006 res_conn =
2007 conn
2008 |> assign(:user, user)
2009 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2010
2011 assert %{} = json_response(res_conn, 200)
2012 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
2013
2014 res_conn =
2015 conn
2016 |> assign(:user, user)
2017 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
2018
2019 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
2020 end
2021 end
2022
2023 describe "create account by app" do
2024 test "Account registration via Application", %{conn: conn} do
2025 conn =
2026 conn
2027 |> post("/api/v1/apps", %{
2028 client_name: "client_name",
2029 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
2030 scopes: "read, write, follow"
2031 })
2032
2033 %{
2034 "client_id" => client_id,
2035 "client_secret" => client_secret,
2036 "id" => _,
2037 "name" => "client_name",
2038 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
2039 "vapid_key" => _,
2040 "website" => nil
2041 } = json_response(conn, 200)
2042
2043 conn =
2044 conn
2045 |> post("/oauth/token", %{
2046 grant_type: "client_credentials",
2047 client_id: client_id,
2048 client_secret: client_secret
2049 })
2050
2051 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
2052 json_response(conn, 200)
2053
2054 assert token
2055 token_from_db = Repo.get_by(Token, token: token)
2056 assert token_from_db
2057 assert refresh
2058 assert scope == "read write follow"
2059
2060 conn =
2061 build_conn()
2062 |> put_req_header("authorization", "Bearer " <> token)
2063 |> post("/api/v1/accounts", %{
2064 username: "lain",
2065 email: "lain@example.org",
2066 password: "PlzDontHackLain",
2067 agreement: true
2068 })
2069
2070 %{
2071 "access_token" => token,
2072 "created_at" => _created_at,
2073 "scope" => _scope,
2074 "token_type" => "Bearer"
2075 } = json_response(conn, 200)
2076
2077 token_from_db = Repo.get_by(Token, token: token)
2078 assert token_from_db
2079 token_from_db = Repo.preload(token_from_db, :user)
2080 assert token_from_db.user
2081
2082 assert token_from_db.user.info.confirmation_pending
2083 end
2084
2085 test "rate limit", %{conn: conn} do
2086 app_token = insert(:oauth_token, user: nil)
2087
2088 conn =
2089 put_req_header(conn, "authorization", "Bearer " <> app_token.token)
2090 |> Map.put(:remote_ip, {15, 15, 15, 15})
2091
2092 for i <- 1..5 do
2093 conn =
2094 conn
2095 |> post("/api/v1/accounts", %{
2096 username: "#{i}lain",
2097 email: "#{i}lain@example.org",
2098 password: "PlzDontHackLain",
2099 agreement: true
2100 })
2101
2102 %{
2103 "access_token" => token,
2104 "created_at" => _created_at,
2105 "scope" => _scope,
2106 "token_type" => "Bearer"
2107 } = json_response(conn, 200)
2108
2109 token_from_db = Repo.get_by(Token, token: token)
2110 assert token_from_db
2111 token_from_db = Repo.preload(token_from_db, :user)
2112 assert token_from_db.user
2113
2114 assert token_from_db.user.info.confirmation_pending
2115 end
2116
2117 conn =
2118 conn
2119 |> post("/api/v1/accounts", %{
2120 username: "6lain",
2121 email: "6lain@example.org",
2122 password: "PlzDontHackLain",
2123 agreement: true
2124 })
2125
2126 assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
2127 end
2128 end
2129
2130 describe "GET /api/v1/polls/:id" do
2131 test "returns poll entity for object id", %{conn: conn} do
2132 user = insert(:user)
2133
2134 {:ok, activity} =
2135 CommonAPI.post(user, %{
2136 "status" => "Pleroma does",
2137 "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}
2138 })
2139
2140 object = Object.normalize(activity)
2141
2142 conn =
2143 conn
2144 |> assign(:user, user)
2145 |> get("/api/v1/polls/#{object.id}")
2146
2147 response = json_response(conn, 200)
2148 id = to_string(object.id)
2149 assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
2150 end
2151
2152 test "does not expose polls for private statuses", %{conn: conn} do
2153 user = insert(:user)
2154 other_user = insert(:user)
2155
2156 {:ok, activity} =
2157 CommonAPI.post(user, %{
2158 "status" => "Pleroma does",
2159 "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20},
2160 "visibility" => "private"
2161 })
2162
2163 object = Object.normalize(activity)
2164
2165 conn =
2166 conn
2167 |> assign(:user, other_user)
2168 |> get("/api/v1/polls/#{object.id}")
2169
2170 assert json_response(conn, 404)
2171 end
2172 end
2173
2174 describe "POST /api/v1/polls/:id/votes" do
2175 test "votes are added to the poll", %{conn: conn} do
2176 user = insert(:user)
2177 other_user = insert(:user)
2178
2179 {:ok, activity} =
2180 CommonAPI.post(user, %{
2181 "status" => "A very delicious sandwich",
2182 "poll" => %{
2183 "options" => ["Lettuce", "Grilled Bacon", "Tomato"],
2184 "expires_in" => 20,
2185 "multiple" => true
2186 }
2187 })
2188
2189 object = Object.normalize(activity)
2190
2191 conn =
2192 conn
2193 |> assign(:user, other_user)
2194 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
2195
2196 assert json_response(conn, 200)
2197 object = Object.get_by_id(object.id)
2198
2199 assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
2200 total_items == 1
2201 end)
2202 end
2203
2204 test "author can't vote", %{conn: conn} do
2205 user = insert(:user)
2206
2207 {:ok, activity} =
2208 CommonAPI.post(user, %{
2209 "status" => "Am I cute?",
2210 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
2211 })
2212
2213 object = Object.normalize(activity)
2214
2215 assert conn
2216 |> assign(:user, user)
2217 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
2218 |> json_response(422) == %{"error" => "Poll's author can't vote"}
2219
2220 object = Object.get_by_id(object.id)
2221
2222 refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
2223 end
2224
2225 test "does not allow multiple choices on a single-choice question", %{conn: conn} do
2226 user = insert(:user)
2227 other_user = insert(:user)
2228
2229 {:ok, activity} =
2230 CommonAPI.post(user, %{
2231 "status" => "The glass is",
2232 "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20}
2233 })
2234
2235 object = Object.normalize(activity)
2236
2237 assert conn
2238 |> assign(:user, other_user)
2239 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
2240 |> json_response(422) == %{"error" => "Too many choices"}
2241
2242 object = Object.get_by_id(object.id)
2243
2244 refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
2245 total_items == 1
2246 end)
2247 end
2248
2249 test "does not allow choice index to be greater than options count", %{conn: conn} do
2250 user = insert(:user)
2251 other_user = insert(:user)
2252
2253 {:ok, activity} =
2254 CommonAPI.post(user, %{
2255 "status" => "Am I cute?",
2256 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
2257 })
2258
2259 object = Object.normalize(activity)
2260
2261 conn =
2262 conn
2263 |> assign(:user, other_user)
2264 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
2265
2266 assert json_response(conn, 422) == %{"error" => "Invalid indices"}
2267 end
2268
2269 test "returns 404 error when object is not exist", %{conn: conn} do
2270 user = insert(:user)
2271
2272 conn =
2273 conn
2274 |> assign(:user, user)
2275 |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
2276
2277 assert json_response(conn, 404) == %{"error" => "Record not found"}
2278 end
2279
2280 test "returns 404 when poll is private and not available for user", %{conn: conn} do
2281 user = insert(:user)
2282 other_user = insert(:user)
2283
2284 {:ok, activity} =
2285 CommonAPI.post(user, %{
2286 "status" => "Am I cute?",
2287 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20},
2288 "visibility" => "private"
2289 })
2290
2291 object = Object.normalize(activity)
2292
2293 conn =
2294 conn
2295 |> assign(:user, other_user)
2296 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
2297
2298 assert json_response(conn, 404) == %{"error" => "Record not found"}
2299 end
2300 end
2301
2302 describe "POST /auth/password, with valid parameters" do
2303 setup %{conn: conn} do
2304 user = insert(:user)
2305 conn = post(conn, "/auth/password?email=#{user.email}")
2306 %{conn: conn, user: user}
2307 end
2308
2309 test "it returns 204", %{conn: conn} do
2310 assert json_response(conn, :no_content)
2311 end
2312
2313 test "it creates a PasswordResetToken record for user", %{user: user} do
2314 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
2315 assert token_record
2316 end
2317
2318 test "it sends an email to user", %{user: user} do
2319 ObanHelpers.perform_all()
2320 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
2321
2322 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
2323 notify_email = Config.get([:instance, :notify_email])
2324 instance_name = Config.get([:instance, :name])
2325
2326 assert_email_sent(
2327 from: {instance_name, notify_email},
2328 to: {user.name, user.email},
2329 html_body: email.html_body
2330 )
2331 end
2332 end
2333
2334 describe "POST /auth/password, with invalid parameters" do
2335 setup do
2336 user = insert(:user)
2337 {:ok, user: user}
2338 end
2339
2340 test "it returns 404 when user is not found", %{conn: conn, user: user} do
2341 conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
2342 assert conn.status == 404
2343 assert conn.resp_body == ""
2344 end
2345
2346 test "it returns 400 when user is not local", %{conn: conn, user: user} do
2347 {:ok, user} = Repo.update(Changeset.change(user, local: false))
2348 conn = post(conn, "/auth/password?email=#{user.email}")
2349 assert conn.status == 400
2350 assert conn.resp_body == ""
2351 end
2352 end
2353
2354 describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
2355 setup do
2356 {:ok, user} =
2357 insert(:user)
2358 |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
2359 |> Repo.update()
2360
2361 assert user.info.confirmation_pending
2362
2363 [user: user]
2364 end
2365
2366 clear_config([:instance, :account_activation_required]) do
2367 Config.put([:instance, :account_activation_required], true)
2368 end
2369
2370 test "resend account confirmation email", %{conn: conn, user: user} do
2371 conn
2372 |> assign(:user, user)
2373 |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
2374 |> json_response(:no_content)
2375
2376 ObanHelpers.perform_all()
2377
2378 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
2379 notify_email = Config.get([:instance, :notify_email])
2380 instance_name = Config.get([:instance, :name])
2381
2382 assert_email_sent(
2383 from: {instance_name, notify_email},
2384 to: {user.name, user.email},
2385 html_body: email.html_body
2386 )
2387 end
2388 end
2389
2390 describe "GET /api/v1/suggestions" do
2391 setup do
2392 user = insert(:user)
2393 other_user = insert(:user)
2394 host = Config.get([Pleroma.Web.Endpoint, :url, :host])
2395 url500 = "http://test500?#{host}&#{user.nickname}"
2396 url200 = "http://test200?#{host}&#{user.nickname}"
2397
2398 mock(fn
2399 %{method: :get, url: ^url500} ->
2400 %Tesla.Env{status: 500, body: "bad request"}
2401
2402 %{method: :get, url: ^url200} ->
2403 %Tesla.Env{
2404 status: 200,
2405 body:
2406 ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
2407 other_user.ap_id
2408 }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
2409 }
2410 end)
2411
2412 [user: user, other_user: other_user]
2413 end
2414
2415 clear_config(:suggestions)
2416
2417 test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
2418 Config.put([:suggestions, :enabled], false)
2419
2420 res =
2421 conn
2422 |> assign(:user, user)
2423 |> get("/api/v1/suggestions")
2424 |> json_response(200)
2425
2426 assert res == []
2427 end
2428
2429 test "returns error", %{conn: conn, user: user} do
2430 Config.put([:suggestions, :enabled], true)
2431 Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
2432
2433 assert capture_log(fn ->
2434 res =
2435 conn
2436 |> assign(:user, user)
2437 |> get("/api/v1/suggestions")
2438 |> json_response(500)
2439
2440 assert res == "Something went wrong"
2441 end) =~ "Could not retrieve suggestions"
2442 end
2443
2444 test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
2445 Config.put([:suggestions, :enabled], true)
2446 Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}")
2447
2448 res =
2449 conn
2450 |> assign(:user, user)
2451 |> get("/api/v1/suggestions")
2452 |> json_response(200)
2453
2454 assert res == [
2455 %{
2456 "acct" => "yj455",
2457 "avatar" => "https://social.heldscal.la/avatar/201.jpeg",
2458 "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg",
2459 "id" => 0
2460 },
2461 %{
2462 "acct" => other_user.ap_id,
2463 "avatar" => "https://social.heldscal.la/avatar/202.jpeg",
2464 "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg",
2465 "id" => other_user.id
2466 }
2467 ]
2468 end
2469 end
2470 end