1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.TwitterAPI.ControllerTest do
6 use Pleroma.Web.ConnCase
10 alias Pleroma.Builders.ActivityBuilder
11 alias Pleroma.Builders.UserBuilder
12 alias Pleroma.Notification
15 alias Pleroma.Tests.ObanHelpers
17 alias Pleroma.Web.ActivityPub.ActivityPub
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.OAuth.Token
20 alias Pleroma.Web.TwitterAPI.ActivityView
21 alias Pleroma.Web.TwitterAPI.Controller
22 alias Pleroma.Web.TwitterAPI.NotificationView
23 alias Pleroma.Web.TwitterAPI.TwitterAPI
24 alias Pleroma.Web.TwitterAPI.UserView
27 import Pleroma.Factory
28 import Swoosh.TestAssertions
30 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
32 describe "POST /api/account/update_profile_banner" do
33 test "it updates the banner", %{conn: conn} do
37 |> assign(:user, user)
38 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
41 user = refresh_record(user)
42 assert user.info.banner["type"] == "Image"
45 test "profile banner can be reset", %{conn: conn} do
49 |> assign(:user, user)
50 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => ""})
53 user = refresh_record(user)
54 assert user.info.banner == %{}
58 describe "POST /api/qvitter/update_background_image" do
59 test "it updates the background", %{conn: conn} do
63 |> assign(:user, user)
64 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
67 user = refresh_record(user)
68 assert user.info.background["type"] == "Image"
71 test "background can be reset", %{conn: conn} do
75 |> assign(:user, user)
76 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => ""})
79 user = refresh_record(user)
80 assert user.info.background == %{}
84 describe "POST /api/account/verify_credentials" do
87 test "without valid credentials", %{conn: conn} do
88 conn = post(conn, "/api/account/verify_credentials.json")
89 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
92 test "with credentials", %{conn: conn, user: user} do
95 |> with_credentials(user.nickname, "test")
96 |> post("/api/account/verify_credentials.json")
100 UserView.render("show.json", %{user: user, token: response["token"], for: user})
104 describe "POST /statuses/update.json" do
107 test "without valid credentials", %{conn: conn} do
108 conn = post(conn, "/api/statuses/update.json")
109 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
112 test "with credentials", %{conn: conn, user: user} do
113 conn_with_creds = conn |> with_credentials(user.nickname, "test")
114 request_path = "/api/statuses/update.json"
117 "request" => request_path,
118 "error" => "Client must provide a 'status' parameter with a value."
123 |> post(request_path)
125 assert json_response(conn, 400) == error_response
129 |> post(request_path, %{status: ""})
131 assert json_response(conn, 400) == error_response
135 |> post(request_path, %{status: " "})
137 assert json_response(conn, 400) == error_response
139 # we post with visibility private in order to avoid triggering relay
142 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
144 assert json_response(conn, 200) ==
145 ActivityView.render("activity.json", %{
146 activity: Repo.one(Activity),
153 describe "GET /statuses/public_timeline.json" do
156 test "returns statuses", %{conn: conn} do
158 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
159 ActivityBuilder.insert_list(10, %{}, %{user: user})
160 since_id = List.last(activities).id
164 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
166 response = json_response(conn, 200)
168 assert length(response) == 10
171 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
172 Pleroma.Config.put([:instance, :public], false)
175 |> get("/api/statuses/public_timeline.json")
176 |> json_response(403)
178 Pleroma.Config.put([:instance, :public], true)
181 test "returns 200 to authenticated request when the instance is not public",
182 %{conn: conn, user: user} do
183 Pleroma.Config.put([:instance, :public], false)
186 |> with_credentials(user.nickname, "test")
187 |> get("/api/statuses/public_timeline.json")
188 |> json_response(200)
190 Pleroma.Config.put([:instance, :public], true)
193 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
195 |> get("/api/statuses/public_timeline.json")
196 |> json_response(200)
199 test "returns 200 to authenticated request when the instance is public",
200 %{conn: conn, user: user} do
202 |> with_credentials(user.nickname, "test")
203 |> get("/api/statuses/public_timeline.json")
204 |> json_response(200)
207 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
211 token = insert(:oauth_token, scopes: ["write"])
214 |> put_req_header("authorization", "Bearer #{token.token}")
215 |> get("/api/statuses/public_timeline.json")
216 |> json_response(200)
218 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
222 describe "GET /statuses/public_and_external_timeline.json" do
225 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
226 Pleroma.Config.put([:instance, :public], false)
229 |> get("/api/statuses/public_and_external_timeline.json")
230 |> json_response(403)
232 Pleroma.Config.put([:instance, :public], true)
235 test "returns 200 to authenticated request when the instance is not public",
236 %{conn: conn, user: user} do
237 Pleroma.Config.put([:instance, :public], false)
240 |> with_credentials(user.nickname, "test")
241 |> get("/api/statuses/public_and_external_timeline.json")
242 |> json_response(200)
244 Pleroma.Config.put([:instance, :public], true)
247 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
249 |> get("/api/statuses/public_and_external_timeline.json")
250 |> json_response(200)
253 test "returns 200 to authenticated request when the instance is public",
254 %{conn: conn, user: user} do
256 |> with_credentials(user.nickname, "test")
257 |> get("/api/statuses/public_and_external_timeline.json")
258 |> json_response(200)
262 describe "GET /statuses/show/:id.json" do
263 test "returns one status", %{conn: conn} do
265 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
266 actor = User.get_cached_by_ap_id(activity.data["actor"])
270 |> get("/api/statuses/show/#{activity.id}.json")
272 response = json_response(conn, 200)
274 assert response == ActivityView.render("activity.json", %{activity: activity, user: actor})
278 describe "GET /users/show.json" do
279 test "gets user with screen_name", %{conn: conn} do
284 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
286 response = json_response(conn, 200)
288 assert response["id"] == user.id
291 test "gets user with user_id", %{conn: conn} do
296 |> get("/api/users/show.json", %{"user_id" => user.id})
298 response = json_response(conn, 200)
300 assert response["id"] == user.id
303 test "gets a user for a logged in user", %{conn: conn} do
305 logged_in = insert(:user)
307 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
311 |> with_credentials(logged_in.nickname, "test")
312 |> get("/api/users/show.json", %{"user_id" => user.id})
314 response = json_response(conn, 200)
316 assert response["following"] == true
320 describe "GET /statusnet/conversation/:id.json" do
321 test "returns the statuses in the conversation", %{conn: conn} do
322 {:ok, _user} = UserBuilder.insert()
323 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
324 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
325 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
329 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
331 response = json_response(conn, 200)
333 assert length(response) == 2
337 describe "GET /statuses/friends_timeline.json" do
340 test "without valid credentials", %{conn: conn} do
341 conn = get(conn, "/api/statuses/friends_timeline.json")
342 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
345 test "with credentials", %{conn: conn, user: current_user} do
349 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
351 returned_activities =
352 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
354 other_user = insert(:user)
355 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
356 since_id = List.last(activities).id
359 Changeset.change(current_user, following: [User.ap_followers(user)])
364 |> with_credentials(current_user.nickname, "test")
365 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
367 response = json_response(conn, 200)
369 assert length(response) == 10
372 Enum.map(returned_activities, fn activity ->
373 ActivityView.render("activity.json", %{
375 user: User.get_cached_by_ap_id(activity.data["actor"]),
382 describe "GET /statuses/dm_timeline.json" do
383 test "it show direct messages", %{conn: conn} do
384 user_one = insert(:user)
385 user_two = insert(:user)
387 {:ok, user_two} = User.follow(user_two, user_one)
390 CommonAPI.post(user_one, %{
391 "status" => "Hi @#{user_two.nickname}!",
392 "visibility" => "direct"
396 CommonAPI.post(user_two, %{
397 "status" => "Hi @#{user_one.nickname}!",
398 "visibility" => "direct"
401 {:ok, _follower_only} =
402 CommonAPI.post(user_one, %{
403 "status" => "Hi @#{user_two.nickname}!",
404 "visibility" => "private"
407 # Only direct should be visible here
410 |> assign(:user, user_two)
411 |> get("/api/statuses/dm_timeline.json")
413 [status, status_two] = json_response(res_conn, 200)
414 assert status["id"] == direct_two.id
415 assert status_two["id"] == direct.id
418 test "doesn't include DMs from blocked users", %{conn: conn} do
419 blocker = insert(:user)
420 blocked = insert(:user)
422 {:ok, blocker} = User.block(blocker, blocked)
424 {:ok, _blocked_direct} =
425 CommonAPI.post(blocked, %{
426 "status" => "Hi @#{blocker.nickname}!",
427 "visibility" => "direct"
431 CommonAPI.post(user, %{
432 "status" => "Hi @#{blocker.nickname}!",
433 "visibility" => "direct"
438 |> assign(:user, blocker)
439 |> get("/api/statuses/dm_timeline.json")
441 [status] = json_response(res_conn, 200)
442 assert status["id"] == direct.id
446 describe "GET /statuses/mentions.json" do
449 test "without valid credentials", %{conn: conn} do
450 conn = get(conn, "/api/statuses/mentions.json")
451 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
454 test "with credentials", %{conn: conn, user: current_user} do
456 CommonAPI.post(current_user, %{
457 "status" => "why is tenshi eating a corndog so cute?",
458 "visibility" => "public"
463 |> with_credentials(current_user.nickname, "test")
464 |> get("/api/statuses/mentions.json")
466 response = json_response(conn, 200)
468 assert length(response) == 1
470 assert Enum.at(response, 0) ==
471 ActivityView.render("activity.json", %{
478 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
480 CommonAPI.post(current_user, %{
481 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
482 "visibility" => "direct"
487 |> with_credentials(current_user.nickname, "test")
488 |> get("/api/statuses/mentions.json")
490 response = json_response(conn, 200)
492 assert Enum.empty?(response)
496 describe "GET /api/qvitter/statuses/notifications.json" do
499 test "without valid credentials", %{conn: conn} do
500 conn = get(conn, "/api/qvitter/statuses/notifications.json")
501 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
504 test "with credentials", %{conn: conn, user: current_user} do
505 other_user = insert(:user)
508 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
512 |> with_credentials(current_user.nickname, "test")
513 |> get("/api/qvitter/statuses/notifications.json")
515 response = json_response(conn, 200)
517 assert length(response) == 1
520 NotificationView.render("notification.json", %{
521 notifications: Notification.for_user(current_user),
526 test "muted user", %{conn: conn, user: current_user} do
527 other_user = insert(:user)
529 {:ok, current_user} = User.mute(current_user, other_user)
532 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
536 |> with_credentials(current_user.nickname, "test")
537 |> get("/api/qvitter/statuses/notifications.json")
539 assert json_response(conn, 200) == []
542 test "muted user with with_muted parameter", %{conn: conn, user: current_user} do
543 other_user = insert(:user)
545 {:ok, current_user} = User.mute(current_user, other_user)
548 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
552 |> with_credentials(current_user.nickname, "test")
553 |> get("/api/qvitter/statuses/notifications.json", %{"with_muted" => "true"})
555 assert length(json_response(conn, 200)) == 1
559 describe "POST /api/qvitter/statuses/notifications/read" do
562 test "without valid credentials", %{conn: conn} do
563 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
564 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
567 test "with credentials, without any params", %{conn: conn, user: current_user} do
570 |> with_credentials(current_user.nickname, "test")
571 |> post("/api/qvitter/statuses/notifications/read")
573 assert json_response(conn, 400) == %{
574 "error" => "You need to specify latest_id",
575 "request" => "/api/qvitter/statuses/notifications/read"
579 test "with credentials, with params", %{conn: conn, user: current_user} do
580 other_user = insert(:user)
583 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
587 |> with_credentials(current_user.nickname, "test")
588 |> get("/api/qvitter/statuses/notifications.json")
590 [notification] = response = json_response(response_conn, 200)
592 assert length(response) == 1
594 assert notification["is_seen"] == 0
598 |> with_credentials(current_user.nickname, "test")
599 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
601 [notification] = response = json_response(response_conn, 200)
603 assert length(response) == 1
605 assert notification["is_seen"] == 1
609 describe "GET /statuses/user_timeline.json" do
612 test "without any params", %{conn: conn} do
613 conn = get(conn, "/api/statuses/user_timeline.json")
615 assert json_response(conn, 400) == %{
616 "error" => "You need to specify screen_name or user_id",
617 "request" => "/api/statuses/user_timeline.json"
621 test "with user_id", %{conn: conn} do
623 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
625 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
626 response = json_response(conn, 200)
627 assert length(response) == 1
629 assert Enum.at(response, 0) ==
630 ActivityView.render("activity.json", %{user: user, activity: activity})
633 test "with screen_name", %{conn: conn} do
635 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
637 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
638 response = json_response(conn, 200)
639 assert length(response) == 1
641 assert Enum.at(response, 0) ==
642 ActivityView.render("activity.json", %{user: user, activity: activity})
645 test "with credentials", %{conn: conn, user: current_user} do
646 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
650 |> with_credentials(current_user.nickname, "test")
651 |> get("/api/statuses/user_timeline.json")
653 response = json_response(conn, 200)
655 assert length(response) == 1
657 assert Enum.at(response, 0) ==
658 ActivityView.render("activity.json", %{
665 test "with credentials with user_id", %{conn: conn, user: current_user} do
667 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
671 |> with_credentials(current_user.nickname, "test")
672 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
674 response = json_response(conn, 200)
676 assert length(response) == 1
678 assert Enum.at(response, 0) ==
679 ActivityView.render("activity.json", %{user: user, activity: activity})
682 test "with credentials screen_name", %{conn: conn, user: current_user} do
684 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
688 |> with_credentials(current_user.nickname, "test")
689 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
691 response = json_response(conn, 200)
693 assert length(response) == 1
695 assert Enum.at(response, 0) ==
696 ActivityView.render("activity.json", %{user: user, activity: activity})
699 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
701 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
702 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
706 |> with_credentials(current_user.nickname, "test")
707 |> get("/api/statuses/user_timeline.json", %{
708 "user_id" => user.id,
709 "include_rts" => "false"
712 response = json_response(conn, 200)
714 assert length(response) == 1
716 assert Enum.at(response, 0) ==
717 ActivityView.render("activity.json", %{user: user, activity: activity})
721 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
723 response = json_response(conn, 200)
725 assert length(response) == 1
727 assert Enum.at(response, 0) ==
728 ActivityView.render("activity.json", %{user: user, activity: activity})
732 describe "POST /friendships/create.json" do
735 test "without valid credentials", %{conn: conn} do
736 conn = post(conn, "/api/friendships/create.json")
737 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
740 test "with credentials", %{conn: conn, user: current_user} do
741 followed = insert(:user)
745 |> with_credentials(current_user.nickname, "test")
746 |> post("/api/friendships/create.json", %{user_id: followed.id})
748 current_user = User.get_cached_by_id(current_user.id)
749 assert User.ap_followers(followed) in current_user.following
751 assert json_response(conn, 200) ==
752 UserView.render("show.json", %{user: followed, for: current_user})
755 test "for restricted account", %{conn: conn, user: current_user} do
756 followed = insert(:user, info: %User.Info{locked: true})
760 |> with_credentials(current_user.nickname, "test")
761 |> post("/api/friendships/create.json", %{user_id: followed.id})
763 current_user = User.get_cached_by_id(current_user.id)
764 followed = User.get_cached_by_id(followed.id)
766 refute User.ap_followers(followed) in current_user.following
768 assert json_response(conn, 200) ==
769 UserView.render("show.json", %{user: followed, for: current_user})
773 describe "POST /friendships/destroy.json" do
776 test "without valid credentials", %{conn: conn} do
777 conn = post(conn, "/api/friendships/destroy.json")
778 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
781 test "with credentials", %{conn: conn, user: current_user} do
782 followed = insert(:user)
784 {:ok, current_user} = User.follow(current_user, followed)
785 assert User.ap_followers(followed) in current_user.following
786 ActivityPub.follow(current_user, followed)
790 |> with_credentials(current_user.nickname, "test")
791 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
793 current_user = User.get_cached_by_id(current_user.id)
794 assert current_user.following == [current_user.ap_id]
796 assert json_response(conn, 200) ==
797 UserView.render("show.json", %{user: followed, for: current_user})
801 describe "POST /blocks/create.json" do
804 test "without valid credentials", %{conn: conn} do
805 conn = post(conn, "/api/blocks/create.json")
806 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
809 test "with credentials", %{conn: conn, user: current_user} do
810 blocked = insert(:user)
814 |> with_credentials(current_user.nickname, "test")
815 |> post("/api/blocks/create.json", %{user_id: blocked.id})
817 current_user = User.get_cached_by_id(current_user.id)
818 assert User.blocks?(current_user, blocked)
820 assert json_response(conn, 200) ==
821 UserView.render("show.json", %{user: blocked, for: current_user})
825 describe "POST /blocks/destroy.json" do
828 test "without valid credentials", %{conn: conn} do
829 conn = post(conn, "/api/blocks/destroy.json")
830 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
833 test "with credentials", %{conn: conn, user: current_user} do
834 blocked = insert(:user)
836 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
837 assert User.blocks?(current_user, blocked)
841 |> with_credentials(current_user.nickname, "test")
842 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
844 current_user = User.get_cached_by_id(current_user.id)
845 assert current_user.info.blocks == []
847 assert json_response(conn, 200) ==
848 UserView.render("show.json", %{user: blocked, for: current_user})
852 describe "GET /help/test.json" do
853 test "returns \"ok\"", %{conn: conn} do
854 conn = get(conn, "/api/help/test.json")
855 assert json_response(conn, 200) == "ok"
859 describe "POST /api/qvitter/update_avatar.json" do
862 test "without valid credentials", %{conn: conn} do
863 conn = post(conn, "/api/qvitter/update_avatar.json")
864 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
867 test "with credentials", %{conn: conn, user: current_user} do
868 avatar_image = File.read!("test/fixtures/avatar_data_uri")
872 |> with_credentials(current_user.nickname, "test")
873 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
875 current_user = User.get_cached_by_id(current_user.id)
876 assert is_map(current_user.avatar)
878 assert json_response(conn, 200) ==
879 UserView.render("show.json", %{user: current_user, for: current_user})
882 test "user avatar can be reset", %{conn: conn, user: current_user} do
885 |> with_credentials(current_user.nickname, "test")
886 |> post("/api/qvitter/update_avatar.json", %{img: ""})
888 current_user = User.get_cached_by_id(current_user.id)
889 assert current_user.avatar == nil
891 assert json_response(conn, 200) ==
892 UserView.render("show.json", %{user: current_user, for: current_user})
896 describe "GET /api/qvitter/mutes.json" do
899 test "unimplemented mutes without valid credentials", %{conn: conn} do
900 conn = get(conn, "/api/qvitter/mutes.json")
901 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
904 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
907 |> with_credentials(current_user.nickname, "test")
908 |> get("/api/qvitter/mutes.json")
909 |> json_response(200)
915 describe "POST /api/favorites/create/:id" do
918 test "without valid credentials", %{conn: conn} do
919 note_activity = insert(:note_activity)
920 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
921 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
924 test "with credentials", %{conn: conn, user: current_user} do
925 note_activity = insert(:note_activity)
929 |> with_credentials(current_user.nickname, "test")
930 |> post("/api/favorites/create/#{note_activity.id}.json")
932 assert json_response(conn, 200)
935 test "with credentials, invalid param", %{conn: conn, user: current_user} do
938 |> with_credentials(current_user.nickname, "test")
939 |> post("/api/favorites/create/wrong.json")
941 assert json_response(conn, 400)
944 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
947 |> with_credentials(current_user.nickname, "test")
948 |> post("/api/favorites/create/1.json")
950 assert json_response(conn, 400)
954 describe "POST /api/favorites/destroy/:id" do
957 test "without valid credentials", %{conn: conn} do
958 note_activity = insert(:note_activity)
959 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
960 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
963 test "with credentials", %{conn: conn, user: current_user} do
964 note_activity = insert(:note_activity)
965 object = Object.normalize(note_activity)
966 ActivityPub.like(current_user, object)
970 |> with_credentials(current_user.nickname, "test")
971 |> post("/api/favorites/destroy/#{note_activity.id}.json")
973 assert json_response(conn, 200)
977 describe "POST /api/statuses/retweet/:id" do
980 test "without valid credentials", %{conn: conn} do
981 note_activity = insert(:note_activity)
982 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
983 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
986 test "with credentials", %{conn: conn, user: current_user} do
987 note_activity = insert(:note_activity)
989 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
993 |> with_credentials(current_user.nickname, "test")
994 |> post(request_path)
996 activity = Activity.get_by_id(note_activity.id)
997 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
999 assert json_response(response, 200) ==
1000 ActivityView.render("activity.json", %{
1001 user: activity_user,
1008 describe "POST /api/statuses/unretweet/:id" do
1011 test "without valid credentials", %{conn: conn} do
1012 note_activity = insert(:note_activity)
1013 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
1014 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1017 test "with credentials", %{conn: conn, user: current_user} do
1018 note_activity = insert(:note_activity)
1020 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
1024 |> with_credentials(current_user.nickname, "test")
1025 |> post(request_path)
1027 request_path = String.replace(request_path, "retweet", "unretweet")
1031 |> with_credentials(current_user.nickname, "test")
1032 |> post(request_path)
1034 activity = Activity.get_by_id(note_activity.id)
1035 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
1037 assert json_response(response, 200) ==
1038 ActivityView.render("activity.json", %{
1039 user: activity_user,
1046 describe "POST /api/account/register" do
1047 test "it creates a new user", %{conn: conn} do
1049 "nickname" => "lain",
1050 "email" => "lain@wired.jp",
1051 "fullname" => "lain iwakura",
1052 "bio" => "close the world.",
1053 "password" => "bear",
1059 |> post("/api/account/register", data)
1061 user = json_response(conn, 200)
1063 fetched_user = User.get_cached_by_nickname("lain")
1064 assert user == UserView.render("show.json", %{user: fetched_user})
1067 test "it returns errors on a problem", %{conn: conn} do
1069 "email" => "lain@wired.jp",
1070 "fullname" => "lain iwakura",
1071 "bio" => "close the world.",
1072 "password" => "bear",
1078 |> post("/api/account/register", data)
1080 errors = json_response(conn, 400)
1082 assert is_binary(errors["error"])
1086 describe "POST /api/account/password_reset, with valid parameters" do
1087 setup %{conn: conn} do
1088 user = insert(:user)
1089 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1090 %{conn: conn, user: user}
1093 test "it returns 204", %{conn: conn} do
1094 assert json_response(conn, :no_content)
1097 test "it creates a PasswordResetToken record for user", %{user: user} do
1098 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1102 test "it sends an email to user", %{user: user} do
1103 ObanHelpers.perform_all()
1104 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1106 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1107 notify_email = Pleroma.Config.get([:instance, :notify_email])
1108 instance_name = Pleroma.Config.get([:instance, :name])
1111 from: {instance_name, notify_email},
1112 to: {user.name, user.email},
1113 html_body: email.html_body
1118 describe "POST /api/account/password_reset, with invalid parameters" do
1121 test "it returns 404 when user is not found", %{conn: conn, user: user} do
1122 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1123 assert conn.status == 404
1124 assert conn.resp_body == ""
1127 test "it returns 400 when user is not local", %{conn: conn, user: user} do
1128 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1129 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1130 assert conn.status == 400
1131 assert conn.resp_body == ""
1135 describe "GET /api/account/confirm_email/:id/:token" do
1137 user = insert(:user)
1138 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1142 |> Changeset.change()
1143 |> Changeset.put_embed(:info, info_change)
1146 assert user.info.confirmation_pending
1151 test "it redirects to root url", %{conn: conn, user: user} do
1152 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1154 assert 302 == conn.status
1157 test "it confirms the user account", %{conn: conn, user: user} do
1158 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1160 user = User.get_cached_by_id(user.id)
1162 refute user.info.confirmation_pending
1163 refute user.info.confirmation_token
1166 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1167 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1169 assert 500 == conn.status
1172 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1173 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1175 assert 500 == conn.status
1179 describe "POST /api/account/resend_confirmation_email" do
1181 setting = Pleroma.Config.get([:instance, :account_activation_required])
1184 Pleroma.Config.put([:instance, :account_activation_required], true)
1185 on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
1188 user = insert(:user)
1189 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1193 |> Changeset.change()
1194 |> Changeset.put_embed(:info, info_change)
1197 assert user.info.confirmation_pending
1202 test "it returns 204 No Content", %{conn: conn, user: user} do
1204 |> assign(:user, user)
1205 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1206 |> json_response(:no_content)
1209 test "it sends confirmation email", %{conn: conn, user: user} do
1211 |> assign(:user, user)
1212 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1214 ObanHelpers.perform_all()
1216 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
1217 notify_email = Pleroma.Config.get([:instance, :notify_email])
1218 instance_name = Pleroma.Config.get([:instance, :name])
1221 from: {instance_name, notify_email},
1222 to: {user.name, user.email},
1223 html_body: email.html_body
1228 describe "GET /api/externalprofile/show" do
1229 test "it returns the user", %{conn: conn} do
1230 user = insert(:user)
1231 other_user = insert(:user)
1235 |> assign(:user, user)
1236 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1238 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1242 describe "GET /api/statuses/followers" do
1243 test "it returns a user's followers", %{conn: conn} do
1244 user = insert(:user)
1245 follower_one = insert(:user)
1246 follower_two = insert(:user)
1247 _not_follower = insert(:user)
1249 {:ok, follower_one} = User.follow(follower_one, user)
1250 {:ok, follower_two} = User.follow(follower_two, user)
1254 |> assign(:user, user)
1255 |> get("/api/statuses/followers")
1257 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1258 result = json_response(conn, 200)
1259 assert Enum.sort(expected) == Enum.sort(result)
1262 test "it returns 20 followers per page", %{conn: conn} do
1263 user = insert(:user)
1264 followers = insert_list(21, :user)
1266 Enum.each(followers, fn follower ->
1267 User.follow(follower, user)
1272 |> assign(:user, user)
1273 |> get("/api/statuses/followers")
1275 result = json_response(res_conn, 200)
1276 assert length(result) == 20
1280 |> assign(:user, user)
1281 |> get("/api/statuses/followers?page=2")
1283 result = json_response(res_conn, 200)
1284 assert length(result) == 1
1287 test "it returns a given user's followers with user_id", %{conn: conn} do
1288 user = insert(:user)
1289 follower_one = insert(:user)
1290 follower_two = insert(:user)
1291 not_follower = insert(:user)
1293 {:ok, follower_one} = User.follow(follower_one, user)
1294 {:ok, follower_two} = User.follow(follower_two, user)
1298 |> assign(:user, not_follower)
1299 |> get("/api/statuses/followers", %{"user_id" => user.id})
1301 assert MapSet.equal?(
1302 MapSet.new(json_response(conn, 200)),
1304 UserView.render("index.json", %{
1305 users: [follower_one, follower_two],
1312 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1313 user = insert(:user, %{info: %{hide_followers: true}})
1314 follower_one = insert(:user)
1315 follower_two = insert(:user)
1316 not_follower = insert(:user)
1318 {:ok, _follower_one} = User.follow(follower_one, user)
1319 {:ok, _follower_two} = User.follow(follower_two, user)
1323 |> assign(:user, not_follower)
1324 |> get("/api/statuses/followers", %{"user_id" => user.id})
1325 |> json_response(200)
1327 assert [] == response
1330 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1334 user = insert(:user, %{info: %{hide_followers: true}})
1335 follower_one = insert(:user)
1336 follower_two = insert(:user)
1337 _not_follower = insert(:user)
1339 {:ok, _follower_one} = User.follow(follower_one, user)
1340 {:ok, _follower_two} = User.follow(follower_two, user)
1344 |> assign(:user, user)
1345 |> get("/api/statuses/followers", %{"user_id" => user.id})
1347 refute [] == json_response(conn, 200)
1351 describe "GET /api/statuses/blocks" do
1352 test "it returns the list of users blocked by requester", %{conn: conn} do
1353 user = insert(:user)
1354 other_user = insert(:user)
1356 {:ok, user} = User.block(user, other_user)
1360 |> assign(:user, user)
1361 |> get("/api/statuses/blocks")
1363 expected = UserView.render("index.json", %{users: [other_user], for: user})
1364 result = json_response(conn, 200)
1365 assert Enum.sort(expected) == Enum.sort(result)
1369 describe "GET /api/statuses/friends" do
1370 test "it returns the logged in user's friends", %{conn: conn} do
1371 user = insert(:user)
1372 followed_one = insert(:user)
1373 followed_two = insert(:user)
1374 _not_followed = insert(:user)
1376 {:ok, user} = User.follow(user, followed_one)
1377 {:ok, user} = User.follow(user, followed_two)
1381 |> assign(:user, user)
1382 |> get("/api/statuses/friends")
1384 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1385 result = json_response(conn, 200)
1386 assert Enum.sort(expected) == Enum.sort(result)
1389 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1390 user = insert(:user)
1391 followeds = insert_list(21, :user)
1394 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1395 User.follow(user, followed)
1400 |> assign(:user, user)
1401 |> get("/api/statuses/friends")
1403 result = json_response(res_conn, 200)
1404 assert length(result) == 20
1408 |> assign(:user, user)
1409 |> get("/api/statuses/friends", %{page: 2})
1411 result = json_response(res_conn, 200)
1412 assert length(result) == 1
1416 |> assign(:user, user)
1417 |> get("/api/statuses/friends", %{all: true})
1419 result = json_response(res_conn, 200)
1420 assert length(result) == 21
1423 test "it returns a given user's friends with user_id", %{conn: conn} do
1424 user = insert(:user)
1425 followed_one = insert(:user)
1426 followed_two = insert(:user)
1427 _not_followed = insert(:user)
1429 {:ok, user} = User.follow(user, followed_one)
1430 {:ok, user} = User.follow(user, followed_two)
1434 |> assign(:user, user)
1435 |> get("/api/statuses/friends", %{"user_id" => user.id})
1437 assert MapSet.equal?(
1438 MapSet.new(json_response(conn, 200)),
1440 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1445 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1446 user = insert(:user, %{info: %{hide_follows: true}})
1447 followed_one = insert(:user)
1448 followed_two = insert(:user)
1449 not_followed = insert(:user)
1451 {:ok, user} = User.follow(user, followed_one)
1452 {:ok, user} = User.follow(user, followed_two)
1456 |> assign(:user, not_followed)
1457 |> get("/api/statuses/friends", %{"user_id" => user.id})
1459 assert [] == json_response(conn, 200)
1462 test "it returns friends when hide_follows is set to true if the user themselves request it",
1466 user = insert(:user, %{info: %{hide_follows: true}})
1467 followed_one = insert(:user)
1468 followed_two = insert(:user)
1469 _not_followed = insert(:user)
1471 {:ok, _user} = User.follow(user, followed_one)
1472 {:ok, _user} = User.follow(user, followed_two)
1476 |> assign(:user, user)
1477 |> get("/api/statuses/friends", %{"user_id" => user.id})
1478 |> json_response(200)
1480 refute [] == response
1483 test "it returns a given user's friends with screen_name", %{conn: conn} do
1484 user = insert(:user)
1485 followed_one = insert(:user)
1486 followed_two = insert(:user)
1487 _not_followed = insert(:user)
1489 {:ok, user} = User.follow(user, followed_one)
1490 {:ok, user} = User.follow(user, followed_two)
1494 |> assign(:user, user)
1495 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1497 assert MapSet.equal?(
1498 MapSet.new(json_response(conn, 200)),
1500 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1506 describe "GET /friends/ids" do
1507 test "it returns a user's friends", %{conn: conn} do
1508 user = insert(:user)
1509 followed_one = insert(:user)
1510 followed_two = insert(:user)
1511 _not_followed = insert(:user)
1513 {:ok, user} = User.follow(user, followed_one)
1514 {:ok, user} = User.follow(user, followed_two)
1518 |> assign(:user, user)
1519 |> get("/api/friends/ids")
1521 expected = [followed_one.id, followed_two.id]
1523 assert MapSet.equal?(
1524 MapSet.new(Poison.decode!(json_response(conn, 200))),
1525 MapSet.new(expected)
1530 describe "POST /api/account/update_profile.json" do
1531 test "it updates a user's profile", %{conn: conn} do
1532 user = insert(:user)
1533 user2 = insert(:user)
1537 |> assign(:user, user)
1538 |> post("/api/account/update_profile.json", %{
1539 "name" => "new name",
1540 "description" => "hi @#{user2.nickname}"
1543 user = Repo.get!(User, user.id)
1544 assert user.name == "new name"
1547 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1549 }'>@<span>#{user2.nickname}</span></a></span>"
1551 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1554 test "it sets and un-sets hide_follows", %{conn: conn} do
1555 user = insert(:user)
1558 |> assign(:user, user)
1559 |> post("/api/account/update_profile.json", %{
1560 "hide_follows" => "true"
1563 user = Repo.get!(User, user.id)
1564 assert user.info.hide_follows == true
1568 |> assign(:user, user)
1569 |> post("/api/account/update_profile.json", %{
1570 "hide_follows" => "false"
1573 user = refresh_record(user)
1574 assert user.info.hide_follows == false
1575 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1578 test "it sets and un-sets hide_followers", %{conn: conn} do
1579 user = insert(:user)
1582 |> assign(:user, user)
1583 |> post("/api/account/update_profile.json", %{
1584 "hide_followers" => "true"
1587 user = Repo.get!(User, user.id)
1588 assert user.info.hide_followers == true
1592 |> assign(:user, user)
1593 |> post("/api/account/update_profile.json", %{
1594 "hide_followers" => "false"
1597 user = Repo.get!(User, user.id)
1598 assert user.info.hide_followers == false
1599 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1602 test "it sets and un-sets show_role", %{conn: conn} do
1603 user = insert(:user)
1606 |> assign(:user, user)
1607 |> post("/api/account/update_profile.json", %{
1608 "show_role" => "true"
1611 user = Repo.get!(User, user.id)
1612 assert user.info.show_role == true
1616 |> assign(:user, user)
1617 |> post("/api/account/update_profile.json", %{
1618 "show_role" => "false"
1621 user = Repo.get!(User, user.id)
1622 assert user.info.show_role == false
1623 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1626 test "it sets and un-sets skip_thread_containment", %{conn: conn} do
1627 user = insert(:user)
1631 |> assign(:user, user)
1632 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "true"})
1633 |> json_response(200)
1635 assert response["pleroma"]["skip_thread_containment"] == true
1636 user = refresh_record(user)
1637 assert user.info.skip_thread_containment
1641 |> assign(:user, user)
1642 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "false"})
1643 |> json_response(200)
1645 assert response["pleroma"]["skip_thread_containment"] == false
1646 refute refresh_record(user).info.skip_thread_containment
1649 test "it locks an account", %{conn: conn} do
1650 user = insert(:user)
1654 |> assign(:user, user)
1655 |> post("/api/account/update_profile.json", %{
1659 user = Repo.get!(User, user.id)
1660 assert user.info.locked == true
1662 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1665 test "it unlocks an account", %{conn: conn} do
1666 user = insert(:user)
1670 |> assign(:user, user)
1671 |> post("/api/account/update_profile.json", %{
1675 user = Repo.get!(User, user.id)
1676 assert user.info.locked == false
1678 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1681 # Broken before the change to class="emoji" and non-<img/> in the DB
1683 test "it formats emojos", %{conn: conn} do
1684 user = insert(:user)
1688 |> assign(:user, user)
1689 |> post("/api/account/update_profile.json", %{
1690 "bio" => "I love our :moominmamma:"
1693 assert response = json_response(conn, 200)
1696 "description" => "I love our :moominmamma:",
1697 "description_html" =>
1698 ~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
1704 |> get("/api/users/show.json?user_id=#{user.nickname}")
1706 assert response == json_response(conn, 200)
1710 defp valid_user(_context) do
1711 user = insert(:user)
1715 defp with_credentials(conn, username, password) do
1716 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1717 put_req_header(conn, "authorization", header_content)
1720 describe "GET /api/search.json" do
1721 test "it returns search results", %{conn: conn} do
1722 user = insert(:user)
1723 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1725 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1726 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1730 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1732 assert [status] = json_response(conn, 200)
1733 assert status["id"] == activity.id
1737 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1738 test "it returns the tags timeline", %{conn: conn} do
1739 user = insert(:user)
1740 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1742 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1743 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1747 |> get("/api/statusnet/tags/timeline/2hu.json")
1749 assert [status] = json_response(conn, 200)
1750 assert status["id"] == activity.id
1754 test "Convert newlines to <br> in bio", %{conn: conn} do
1755 user = insert(:user)
1759 |> assign(:user, user)
1760 |> post("/api/account/update_profile.json", %{
1761 "description" => "Hello,\r\nWorld! I\n am a test."
1764 user = Repo.get!(User, user.id)
1765 assert user.bio == "Hello,<br>World! I<br> am a test."
1768 describe "POST /api/pleroma/change_password" do
1771 test "without credentials", %{conn: conn} do
1772 conn = post(conn, "/api/pleroma/change_password")
1773 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1776 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1779 |> with_credentials(current_user.nickname, "test")
1780 |> post("/api/pleroma/change_password", %{
1782 "new_password" => "newpass",
1783 "new_password_confirmation" => "newpass"
1786 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1789 test "with credentials, valid password and new password and confirmation not matching", %{
1795 |> with_credentials(current_user.nickname, "test")
1796 |> post("/api/pleroma/change_password", %{
1797 "password" => "test",
1798 "new_password" => "newpass",
1799 "new_password_confirmation" => "notnewpass"
1802 assert json_response(conn, 200) == %{
1803 "error" => "New password does not match confirmation."
1807 test "with credentials, valid password and invalid new password", %{
1813 |> with_credentials(current_user.nickname, "test")
1814 |> post("/api/pleroma/change_password", %{
1815 "password" => "test",
1816 "new_password" => "",
1817 "new_password_confirmation" => ""
1820 assert json_response(conn, 200) == %{
1821 "error" => "New password can't be blank."
1825 test "with credentials, valid password and matching new password and confirmation", %{
1831 |> with_credentials(current_user.nickname, "test")
1832 |> post("/api/pleroma/change_password", %{
1833 "password" => "test",
1834 "new_password" => "newpass",
1835 "new_password_confirmation" => "newpass"
1838 assert json_response(conn, 200) == %{"status" => "success"}
1839 fetched_user = User.get_cached_by_id(current_user.id)
1840 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1844 describe "POST /api/pleroma/delete_account" do
1847 test "without credentials", %{conn: conn} do
1848 conn = post(conn, "/api/pleroma/delete_account")
1849 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1852 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1855 |> with_credentials(current_user.nickname, "test")
1856 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1858 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1861 test "with credentials and valid password", %{conn: conn, user: current_user} do
1864 |> with_credentials(current_user.nickname, "test")
1865 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1867 assert json_response(conn, 200) == %{"status" => "success"}
1868 # Wait a second for the started task to end
1873 describe "GET /api/pleroma/friend_requests" do
1874 test "it lists friend requests" do
1875 user = insert(:user)
1876 other_user = insert(:user)
1878 {:ok, _activity} = ActivityPub.follow(other_user, user)
1880 user = User.get_cached_by_id(user.id)
1881 other_user = User.get_cached_by_id(other_user.id)
1883 assert User.following?(other_user, user) == false
1887 |> assign(:user, user)
1888 |> get("/api/pleroma/friend_requests")
1890 assert [relationship] = json_response(conn, 200)
1891 assert other_user.id == relationship["id"]
1894 test "requires 'read' permission", %{conn: conn} do
1895 token1 = insert(:oauth_token, scopes: ["write"])
1896 token2 = insert(:oauth_token, scopes: ["read"])
1898 for token <- [token1, token2] do
1901 |> put_req_header("authorization", "Bearer #{token.token}")
1902 |> get("/api/pleroma/friend_requests")
1904 if token == token1 do
1905 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1907 assert json_response(conn, 200)
1913 describe "POST /api/pleroma/friendships/approve" do
1914 test "it approves a friend request" do
1915 user = insert(:user)
1916 other_user = insert(:user)
1918 {:ok, _activity} = ActivityPub.follow(other_user, user)
1920 user = User.get_cached_by_id(user.id)
1921 other_user = User.get_cached_by_id(other_user.id)
1923 assert User.following?(other_user, user) == false
1927 |> assign(:user, user)
1928 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1930 assert relationship = json_response(conn, 200)
1931 assert other_user.id == relationship["id"]
1932 assert relationship["follows_you"] == true
1936 describe "POST /api/pleroma/friendships/deny" do
1937 test "it denies a friend request" do
1938 user = insert(:user)
1939 other_user = insert(:user)
1941 {:ok, _activity} = ActivityPub.follow(other_user, user)
1943 user = User.get_cached_by_id(user.id)
1944 other_user = User.get_cached_by_id(other_user.id)
1946 assert User.following?(other_user, user) == false
1950 |> assign(:user, user)
1951 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1953 assert relationship = json_response(conn, 200)
1954 assert other_user.id == relationship["id"]
1955 assert relationship["follows_you"] == false
1959 describe "GET /api/pleroma/search_user" do
1960 test "it returns users, ordered by similarity", %{conn: conn} do
1961 user = insert(:user, %{name: "eal"})
1962 user_two = insert(:user, %{name: "eal me"})
1963 _user_three = insert(:user, %{name: "zzz"})
1967 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1968 |> json_response(200)
1970 assert length(resp) == 2
1971 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1975 describe "POST /api/media/upload" do
1977 Pleroma.DataCase.ensure_local_uploader(context)
1980 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1983 user = insert(:user)
1985 upload_filename = "test/fixtures/image_tmp.jpg"
1986 File.cp!("test/fixtures/image.jpg", upload_filename)
1988 file = %Plug.Upload{
1989 content_type: "image/jpg",
1990 path: Path.absname(upload_filename),
1991 filename: "image.jpg"
1996 |> assign(:user, user)
1997 |> put_req_header("content-type", "application/octet-stream")
1998 |> post("/api/media/upload", %{
2001 |> json_response(:ok)
2003 assert response["media_id"]
2004 object = Repo.get(Object, response["media_id"])
2006 assert object.data["actor"] == User.ap_id(user)
2010 describe "POST /api/media/metadata/create" do
2012 object = insert(:note)
2013 user = User.get_cached_by_ap_id(object.data["actor"])
2014 %{object: object, user: user}
2017 test "it returns :forbidden status on attempt to modify someone else's upload", %{
2021 initial_description = object.data["name"]
2022 another_user = insert(:user)
2025 |> assign(:user, another_user)
2026 |> post("/api/media/metadata/create", %{"media_id" => object.id})
2027 |> json_response(:forbidden)
2029 object = Repo.get(Object, object.id)
2030 assert object.data["name"] == initial_description
2033 test "it updates `data[name]` of referenced Object with provided value", %{
2038 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
2041 |> assign(:user, user)
2042 |> post("/api/media/metadata/create", %{
2043 "media_id" => object.id,
2044 "alt_text" => %{"text" => description}
2046 |> json_response(:no_content)
2048 object = Repo.get(Object, object.id)
2049 assert object.data["name"] == description
2053 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
2054 test "it returns a list of pinned statuses", %{conn: conn} do
2055 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2057 user = insert(:user, %{name: "egor"})
2058 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
2059 {:ok, _} = CommonAPI.pin(activity_id, user)
2063 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
2064 |> json_response(200)
2066 assert length(resp) == 1
2067 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
2071 describe "POST /api/statuses/pin/:id" do
2073 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2074 [user: insert(:user)]
2077 test "without valid credentials", %{conn: conn} do
2078 note_activity = insert(:note_activity)
2079 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
2080 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2083 test "with credentials", %{conn: conn, user: user} do
2084 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2086 request_path = "/api/statuses/pin/#{activity.id}.json"
2090 |> with_credentials(user.nickname, "test")
2091 |> post(request_path)
2093 user = refresh_record(user)
2095 assert json_response(response, 200) ==
2096 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2100 describe "POST /api/statuses/unpin/:id" do
2102 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2103 [user: insert(:user)]
2106 test "without valid credentials", %{conn: conn} do
2107 note_activity = insert(:note_activity)
2108 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2109 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2112 test "with credentials", %{conn: conn, user: user} do
2113 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2114 {:ok, activity} = CommonAPI.pin(activity.id, user)
2116 request_path = "/api/statuses/unpin/#{activity.id}.json"
2120 |> with_credentials(user.nickname, "test")
2121 |> post(request_path)
2123 user = refresh_record(user)
2125 assert json_response(response, 200) ==
2126 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2130 describe "GET /api/oauth_tokens" do
2132 token = insert(:oauth_token) |> Repo.preload(:user)
2137 test "renders list", %{token: token} do
2140 |> assign(:user, token.user)
2141 |> get("/api/oauth_tokens")
2144 json_response(response, 200)
2148 assert keys -- ["id", "app_name", "valid_until"] == []
2151 test "revoke token", %{token: token} do
2154 |> assign(:user, token.user)
2155 |> delete("/api/oauth_tokens/#{token.id}")
2157 tokens = Token.get_user_tokens(token.user)
2160 assert response.status == 201