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
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.OAuth.Token
19 alias Pleroma.Web.TwitterAPI.ActivityView
20 alias Pleroma.Web.TwitterAPI.Controller
21 alias Pleroma.Web.TwitterAPI.NotificationView
22 alias Pleroma.Web.TwitterAPI.TwitterAPI
23 alias Pleroma.Web.TwitterAPI.UserView
26 import Pleroma.Factory
27 import Swoosh.TestAssertions
29 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
31 describe "POST /api/account/update_profile_banner" do
32 test "it updates the banner", %{conn: conn} do
36 |> assign(:user, user)
37 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
40 user = refresh_record(user)
41 assert user.info.banner["type"] == "Image"
44 test "profile banner can be reset", %{conn: conn} do
48 |> assign(:user, user)
49 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => ""})
52 user = refresh_record(user)
53 assert user.info.banner == %{}
57 describe "POST /api/qvitter/update_background_image" do
58 test "it updates the background", %{conn: conn} do
62 |> assign(:user, user)
63 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
66 user = refresh_record(user)
67 assert user.info.background["type"] == "Image"
70 test "background can be reset", %{conn: conn} do
74 |> assign(:user, user)
75 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => ""})
78 user = refresh_record(user)
79 assert user.info.background == %{}
83 describe "POST /api/account/verify_credentials" do
86 test "without valid credentials", %{conn: conn} do
87 conn = post(conn, "/api/account/verify_credentials.json")
88 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
91 test "with credentials", %{conn: conn, user: user} do
94 |> with_credentials(user.nickname, "test")
95 |> post("/api/account/verify_credentials.json")
99 UserView.render("show.json", %{user: user, token: response["token"], for: user})
103 describe "POST /statuses/update.json" do
106 test "without valid credentials", %{conn: conn} do
107 conn = post(conn, "/api/statuses/update.json")
108 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
111 test "with credentials", %{conn: conn, user: user} do
112 conn_with_creds = conn |> with_credentials(user.nickname, "test")
113 request_path = "/api/statuses/update.json"
116 "request" => request_path,
117 "error" => "Client must provide a 'status' parameter with a value."
122 |> post(request_path)
124 assert json_response(conn, 400) == error_response
128 |> post(request_path, %{status: ""})
130 assert json_response(conn, 400) == error_response
134 |> post(request_path, %{status: " "})
136 assert json_response(conn, 400) == error_response
138 # we post with visibility private in order to avoid triggering relay
141 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
143 assert json_response(conn, 200) ==
144 ActivityView.render("activity.json", %{
145 activity: Repo.one(Activity),
152 describe "GET /statuses/public_timeline.json" do
155 test "returns statuses", %{conn: conn} do
157 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
158 ActivityBuilder.insert_list(10, %{}, %{user: user})
159 since_id = List.last(activities).id
163 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
165 response = json_response(conn, 200)
167 assert length(response) == 10
170 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
171 Pleroma.Config.put([:instance, :public], false)
174 |> get("/api/statuses/public_timeline.json")
175 |> json_response(403)
177 Pleroma.Config.put([:instance, :public], true)
180 test "returns 200 to authenticated request when the instance is not public",
181 %{conn: conn, user: user} do
182 Pleroma.Config.put([:instance, :public], false)
185 |> with_credentials(user.nickname, "test")
186 |> get("/api/statuses/public_timeline.json")
187 |> json_response(200)
189 Pleroma.Config.put([:instance, :public], true)
192 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
194 |> get("/api/statuses/public_timeline.json")
195 |> json_response(200)
198 test "returns 200 to authenticated request when the instance is public",
199 %{conn: conn, user: user} do
201 |> with_credentials(user.nickname, "test")
202 |> get("/api/statuses/public_timeline.json")
203 |> json_response(200)
206 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
210 token = insert(:oauth_token, scopes: ["write"])
213 |> put_req_header("authorization", "Bearer #{token.token}")
214 |> get("/api/statuses/public_timeline.json")
215 |> json_response(200)
217 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
221 describe "GET /statuses/public_and_external_timeline.json" do
224 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
225 Pleroma.Config.put([:instance, :public], false)
228 |> get("/api/statuses/public_and_external_timeline.json")
229 |> json_response(403)
231 Pleroma.Config.put([:instance, :public], true)
234 test "returns 200 to authenticated request when the instance is not public",
235 %{conn: conn, user: user} do
236 Pleroma.Config.put([:instance, :public], false)
239 |> with_credentials(user.nickname, "test")
240 |> get("/api/statuses/public_and_external_timeline.json")
241 |> json_response(200)
243 Pleroma.Config.put([:instance, :public], true)
246 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
248 |> get("/api/statuses/public_and_external_timeline.json")
249 |> json_response(200)
252 test "returns 200 to authenticated request when the instance is public",
253 %{conn: conn, user: user} do
255 |> with_credentials(user.nickname, "test")
256 |> get("/api/statuses/public_and_external_timeline.json")
257 |> json_response(200)
261 describe "GET /statuses/show/:id.json" do
262 test "returns one status", %{conn: conn} do
264 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
265 actor = User.get_cached_by_ap_id(activity.data["actor"])
269 |> get("/api/statuses/show/#{activity.id}.json")
271 response = json_response(conn, 200)
273 assert response == ActivityView.render("activity.json", %{activity: activity, user: actor})
277 describe "GET /users/show.json" do
278 test "gets user with screen_name", %{conn: conn} do
283 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
285 response = json_response(conn, 200)
287 assert response["id"] == user.id
290 test "gets user with user_id", %{conn: conn} do
295 |> get("/api/users/show.json", %{"user_id" => user.id})
297 response = json_response(conn, 200)
299 assert response["id"] == user.id
302 test "gets a user for a logged in user", %{conn: conn} do
304 logged_in = insert(:user)
306 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
310 |> with_credentials(logged_in.nickname, "test")
311 |> get("/api/users/show.json", %{"user_id" => user.id})
313 response = json_response(conn, 200)
315 assert response["following"] == true
319 describe "GET /statusnet/conversation/:id.json" do
320 test "returns the statuses in the conversation", %{conn: conn} do
321 {:ok, _user} = UserBuilder.insert()
322 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
323 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
324 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
328 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
330 response = json_response(conn, 200)
332 assert length(response) == 2
336 describe "GET /statuses/friends_timeline.json" do
339 test "without valid credentials", %{conn: conn} do
340 conn = get(conn, "/api/statuses/friends_timeline.json")
341 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
344 test "with credentials", %{conn: conn, user: current_user} do
348 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
350 returned_activities =
351 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
353 other_user = insert(:user)
354 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
355 since_id = List.last(activities).id
358 Changeset.change(current_user, following: [User.ap_followers(user)])
363 |> with_credentials(current_user.nickname, "test")
364 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
366 response = json_response(conn, 200)
368 assert length(response) == 10
371 Enum.map(returned_activities, fn activity ->
372 ActivityView.render("activity.json", %{
374 user: User.get_cached_by_ap_id(activity.data["actor"]),
381 describe "GET /statuses/dm_timeline.json" do
382 test "it show direct messages", %{conn: conn} do
383 user_one = insert(:user)
384 user_two = insert(:user)
386 {:ok, user_two} = User.follow(user_two, user_one)
389 CommonAPI.post(user_one, %{
390 "status" => "Hi @#{user_two.nickname}!",
391 "visibility" => "direct"
395 CommonAPI.post(user_two, %{
396 "status" => "Hi @#{user_one.nickname}!",
397 "visibility" => "direct"
400 {:ok, _follower_only} =
401 CommonAPI.post(user_one, %{
402 "status" => "Hi @#{user_two.nickname}!",
403 "visibility" => "private"
406 # Only direct should be visible here
409 |> assign(:user, user_two)
410 |> get("/api/statuses/dm_timeline.json")
412 [status, status_two] = json_response(res_conn, 200)
413 assert status["id"] == direct_two.id
414 assert status_two["id"] == direct.id
417 test "doesn't include DMs from blocked users", %{conn: conn} do
418 blocker = insert(:user)
419 blocked = insert(:user)
421 {:ok, blocker} = User.block(blocker, blocked)
423 {:ok, _blocked_direct} =
424 CommonAPI.post(blocked, %{
425 "status" => "Hi @#{blocker.nickname}!",
426 "visibility" => "direct"
430 CommonAPI.post(user, %{
431 "status" => "Hi @#{blocker.nickname}!",
432 "visibility" => "direct"
437 |> assign(:user, blocker)
438 |> get("/api/statuses/dm_timeline.json")
440 [status] = json_response(res_conn, 200)
441 assert status["id"] == direct.id
445 describe "GET /statuses/mentions.json" do
448 test "without valid credentials", %{conn: conn} do
449 conn = get(conn, "/api/statuses/mentions.json")
450 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
453 test "with credentials", %{conn: conn, user: current_user} do
455 CommonAPI.post(current_user, %{
456 "status" => "why is tenshi eating a corndog so cute?",
457 "visibility" => "public"
462 |> with_credentials(current_user.nickname, "test")
463 |> get("/api/statuses/mentions.json")
465 response = json_response(conn, 200)
467 assert length(response) == 1
469 assert Enum.at(response, 0) ==
470 ActivityView.render("activity.json", %{
477 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
479 CommonAPI.post(current_user, %{
480 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
481 "visibility" => "direct"
486 |> with_credentials(current_user.nickname, "test")
487 |> get("/api/statuses/mentions.json")
489 response = json_response(conn, 200)
491 assert Enum.empty?(response)
495 describe "GET /api/qvitter/statuses/notifications.json" do
498 test "without valid credentials", %{conn: conn} do
499 conn = get(conn, "/api/qvitter/statuses/notifications.json")
500 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
503 test "with credentials", %{conn: conn, user: current_user} do
504 other_user = insert(:user)
507 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
511 |> with_credentials(current_user.nickname, "test")
512 |> get("/api/qvitter/statuses/notifications.json")
514 response = json_response(conn, 200)
516 assert length(response) == 1
519 NotificationView.render("notification.json", %{
520 notifications: Notification.for_user(current_user),
526 describe "POST /api/qvitter/statuses/notifications/read" do
529 test "without valid credentials", %{conn: conn} do
530 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
531 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
534 test "with credentials, without any params", %{conn: conn, user: current_user} do
537 |> with_credentials(current_user.nickname, "test")
538 |> post("/api/qvitter/statuses/notifications/read")
540 assert json_response(conn, 400) == %{
541 "error" => "You need to specify latest_id",
542 "request" => "/api/qvitter/statuses/notifications/read"
546 test "with credentials, with params", %{conn: conn, user: current_user} do
547 other_user = insert(:user)
550 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
554 |> with_credentials(current_user.nickname, "test")
555 |> get("/api/qvitter/statuses/notifications.json")
557 [notification] = response = json_response(response_conn, 200)
559 assert length(response) == 1
561 assert notification["is_seen"] == 0
565 |> with_credentials(current_user.nickname, "test")
566 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
568 [notification] = response = json_response(response_conn, 200)
570 assert length(response) == 1
572 assert notification["is_seen"] == 1
576 describe "GET /statuses/user_timeline.json" do
579 test "without any params", %{conn: conn} do
580 conn = get(conn, "/api/statuses/user_timeline.json")
582 assert json_response(conn, 400) == %{
583 "error" => "You need to specify screen_name or user_id",
584 "request" => "/api/statuses/user_timeline.json"
588 test "with user_id", %{conn: conn} do
590 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
592 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
593 response = json_response(conn, 200)
594 assert length(response) == 1
596 assert Enum.at(response, 0) ==
597 ActivityView.render("activity.json", %{user: user, activity: activity})
600 test "with screen_name", %{conn: conn} do
602 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
604 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
605 response = json_response(conn, 200)
606 assert length(response) == 1
608 assert Enum.at(response, 0) ==
609 ActivityView.render("activity.json", %{user: user, activity: activity})
612 test "with credentials", %{conn: conn, user: current_user} do
613 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
617 |> with_credentials(current_user.nickname, "test")
618 |> get("/api/statuses/user_timeline.json")
620 response = json_response(conn, 200)
622 assert length(response) == 1
624 assert Enum.at(response, 0) ==
625 ActivityView.render("activity.json", %{
632 test "with credentials with user_id", %{conn: conn, user: current_user} do
634 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
638 |> with_credentials(current_user.nickname, "test")
639 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
641 response = json_response(conn, 200)
643 assert length(response) == 1
645 assert Enum.at(response, 0) ==
646 ActivityView.render("activity.json", %{user: user, activity: activity})
649 test "with credentials screen_name", %{conn: conn, user: current_user} do
651 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
655 |> with_credentials(current_user.nickname, "test")
656 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
658 response = json_response(conn, 200)
660 assert length(response) == 1
662 assert Enum.at(response, 0) ==
663 ActivityView.render("activity.json", %{user: user, activity: activity})
666 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
668 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
669 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
673 |> with_credentials(current_user.nickname, "test")
674 |> get("/api/statuses/user_timeline.json", %{
675 "user_id" => user.id,
676 "include_rts" => "false"
679 response = json_response(conn, 200)
681 assert length(response) == 1
683 assert Enum.at(response, 0) ==
684 ActivityView.render("activity.json", %{user: user, activity: activity})
688 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
690 response = json_response(conn, 200)
692 assert length(response) == 1
694 assert Enum.at(response, 0) ==
695 ActivityView.render("activity.json", %{user: user, activity: activity})
699 describe "POST /friendships/create.json" do
702 test "without valid credentials", %{conn: conn} do
703 conn = post(conn, "/api/friendships/create.json")
704 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
707 test "with credentials", %{conn: conn, user: current_user} do
708 followed = insert(:user)
712 |> with_credentials(current_user.nickname, "test")
713 |> post("/api/friendships/create.json", %{user_id: followed.id})
715 current_user = User.get_cached_by_id(current_user.id)
716 assert User.ap_followers(followed) in current_user.following
718 assert json_response(conn, 200) ==
719 UserView.render("show.json", %{user: followed, for: current_user})
722 test "for restricted account", %{conn: conn, user: current_user} do
723 followed = insert(:user, info: %User.Info{locked: true})
727 |> with_credentials(current_user.nickname, "test")
728 |> post("/api/friendships/create.json", %{user_id: followed.id})
730 current_user = User.get_cached_by_id(current_user.id)
731 followed = User.get_cached_by_id(followed.id)
733 refute User.ap_followers(followed) in current_user.following
735 assert json_response(conn, 200) ==
736 UserView.render("show.json", %{user: followed, for: current_user})
740 describe "POST /friendships/destroy.json" do
743 test "without valid credentials", %{conn: conn} do
744 conn = post(conn, "/api/friendships/destroy.json")
745 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
748 test "with credentials", %{conn: conn, user: current_user} do
749 followed = insert(:user)
751 {:ok, current_user} = User.follow(current_user, followed)
752 assert User.ap_followers(followed) in current_user.following
753 ActivityPub.follow(current_user, followed)
757 |> with_credentials(current_user.nickname, "test")
758 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
760 current_user = User.get_cached_by_id(current_user.id)
761 assert current_user.following == [current_user.ap_id]
763 assert json_response(conn, 200) ==
764 UserView.render("show.json", %{user: followed, for: current_user})
768 describe "POST /blocks/create.json" do
771 test "without valid credentials", %{conn: conn} do
772 conn = post(conn, "/api/blocks/create.json")
773 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
776 test "with credentials", %{conn: conn, user: current_user} do
777 blocked = insert(:user)
781 |> with_credentials(current_user.nickname, "test")
782 |> post("/api/blocks/create.json", %{user_id: blocked.id})
784 current_user = User.get_cached_by_id(current_user.id)
785 assert User.blocks?(current_user, blocked)
787 assert json_response(conn, 200) ==
788 UserView.render("show.json", %{user: blocked, for: current_user})
792 describe "POST /blocks/destroy.json" do
795 test "without valid credentials", %{conn: conn} do
796 conn = post(conn, "/api/blocks/destroy.json")
797 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
800 test "with credentials", %{conn: conn, user: current_user} do
801 blocked = insert(:user)
803 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
804 assert User.blocks?(current_user, blocked)
808 |> with_credentials(current_user.nickname, "test")
809 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
811 current_user = User.get_cached_by_id(current_user.id)
812 assert current_user.info.blocks == []
814 assert json_response(conn, 200) ==
815 UserView.render("show.json", %{user: blocked, for: current_user})
819 describe "GET /help/test.json" do
820 test "returns \"ok\"", %{conn: conn} do
821 conn = get(conn, "/api/help/test.json")
822 assert json_response(conn, 200) == "ok"
826 describe "POST /api/qvitter/update_avatar.json" do
829 test "without valid credentials", %{conn: conn} do
830 conn = post(conn, "/api/qvitter/update_avatar.json")
831 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
834 test "with credentials", %{conn: conn, user: current_user} do
835 avatar_image = File.read!("test/fixtures/avatar_data_uri")
839 |> with_credentials(current_user.nickname, "test")
840 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
842 current_user = User.get_cached_by_id(current_user.id)
843 assert is_map(current_user.avatar)
845 assert json_response(conn, 200) ==
846 UserView.render("show.json", %{user: current_user, for: current_user})
849 test "user avatar can be reset", %{conn: conn, user: current_user} do
852 |> with_credentials(current_user.nickname, "test")
853 |> post("/api/qvitter/update_avatar.json", %{img: ""})
855 current_user = User.get_cached_by_id(current_user.id)
856 assert current_user.avatar == nil
858 assert json_response(conn, 200) ==
859 UserView.render("show.json", %{user: current_user, for: current_user})
863 describe "GET /api/qvitter/mutes.json" do
866 test "unimplemented mutes without valid credentials", %{conn: conn} do
867 conn = get(conn, "/api/qvitter/mutes.json")
868 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
871 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
874 |> with_credentials(current_user.nickname, "test")
875 |> get("/api/qvitter/mutes.json")
876 |> json_response(200)
882 describe "POST /api/favorites/create/:id" do
885 test "without valid credentials", %{conn: conn} do
886 note_activity = insert(:note_activity)
887 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
888 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
891 test "with credentials", %{conn: conn, user: current_user} do
892 note_activity = insert(:note_activity)
896 |> with_credentials(current_user.nickname, "test")
897 |> post("/api/favorites/create/#{note_activity.id}.json")
899 assert json_response(conn, 200)
902 test "with credentials, invalid param", %{conn: conn, user: current_user} do
905 |> with_credentials(current_user.nickname, "test")
906 |> post("/api/favorites/create/wrong.json")
908 assert json_response(conn, 400)
911 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
914 |> with_credentials(current_user.nickname, "test")
915 |> post("/api/favorites/create/1.json")
917 assert json_response(conn, 400)
921 describe "POST /api/favorites/destroy/:id" do
924 test "without valid credentials", %{conn: conn} do
925 note_activity = insert(:note_activity)
926 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
927 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
930 test "with credentials", %{conn: conn, user: current_user} do
931 note_activity = insert(:note_activity)
932 object = Object.normalize(note_activity)
933 ActivityPub.like(current_user, object)
937 |> with_credentials(current_user.nickname, "test")
938 |> post("/api/favorites/destroy/#{note_activity.id}.json")
940 assert json_response(conn, 200)
944 describe "POST /api/statuses/retweet/:id" do
947 test "without valid credentials", %{conn: conn} do
948 note_activity = insert(:note_activity)
949 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
950 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
953 test "with credentials", %{conn: conn, user: current_user} do
954 note_activity = insert(:note_activity)
956 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
960 |> with_credentials(current_user.nickname, "test")
961 |> post(request_path)
963 activity = Activity.get_by_id(note_activity.id)
964 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
966 assert json_response(response, 200) ==
967 ActivityView.render("activity.json", %{
975 describe "POST /api/statuses/unretweet/:id" do
978 test "without valid credentials", %{conn: conn} do
979 note_activity = insert(:note_activity)
980 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
981 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
984 test "with credentials", %{conn: conn, user: current_user} do
985 note_activity = insert(:note_activity)
987 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
991 |> with_credentials(current_user.nickname, "test")
992 |> post(request_path)
994 request_path = String.replace(request_path, "retweet", "unretweet")
998 |> with_credentials(current_user.nickname, "test")
999 |> post(request_path)
1001 activity = Activity.get_by_id(note_activity.id)
1002 activity_user = User.get_cached_by_ap_id(note_activity.data["actor"])
1004 assert json_response(response, 200) ==
1005 ActivityView.render("activity.json", %{
1006 user: activity_user,
1013 describe "POST /api/account/register" do
1014 test "it creates a new user", %{conn: conn} do
1016 "nickname" => "lain",
1017 "email" => "lain@wired.jp",
1018 "fullname" => "lain iwakura",
1019 "bio" => "close the world.",
1020 "password" => "bear",
1026 |> post("/api/account/register", data)
1028 user = json_response(conn, 200)
1030 fetched_user = User.get_cached_by_nickname("lain")
1031 assert user == UserView.render("show.json", %{user: fetched_user})
1034 test "it returns errors on a problem", %{conn: conn} do
1036 "email" => "lain@wired.jp",
1037 "fullname" => "lain iwakura",
1038 "bio" => "close the world.",
1039 "password" => "bear",
1045 |> post("/api/account/register", data)
1047 errors = json_response(conn, 400)
1049 assert is_binary(errors["error"])
1053 describe "POST /api/account/password_reset, with valid parameters" do
1054 setup %{conn: conn} do
1055 user = insert(:user)
1056 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1057 %{conn: conn, user: user}
1060 test "it returns 204", %{conn: conn} do
1061 assert json_response(conn, :no_content)
1064 test "it creates a PasswordResetToken record for user", %{user: user} do
1065 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1069 test "it sends an email to user", %{user: user} do
1070 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1072 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1073 notify_email = Pleroma.Config.get([:instance, :notify_email])
1074 instance_name = Pleroma.Config.get([:instance, :name])
1077 from: {instance_name, notify_email},
1078 to: {user.name, user.email},
1079 html_body: email.html_body
1084 describe "POST /api/account/password_reset, with invalid parameters" do
1087 test "it returns 500 when user is not found", %{conn: conn, user: user} do
1088 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1089 assert json_response(conn, :internal_server_error)
1092 test "it returns 500 when user is not local", %{conn: conn, user: user} do
1093 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1094 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1095 assert json_response(conn, :internal_server_error)
1099 describe "GET /api/account/confirm_email/:id/:token" do
1101 user = insert(:user)
1102 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1106 |> Changeset.change()
1107 |> Changeset.put_embed(:info, info_change)
1110 assert user.info.confirmation_pending
1115 test "it redirects to root url", %{conn: conn, user: user} do
1116 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1118 assert 302 == conn.status
1121 test "it confirms the user account", %{conn: conn, user: user} do
1122 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1124 user = User.get_cached_by_id(user.id)
1126 refute user.info.confirmation_pending
1127 refute user.info.confirmation_token
1130 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1131 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1133 assert 500 == conn.status
1136 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1137 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1139 assert 500 == conn.status
1143 describe "POST /api/account/resend_confirmation_email" do
1145 setting = Pleroma.Config.get([:instance, :account_activation_required])
1148 Pleroma.Config.put([:instance, :account_activation_required], true)
1149 on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
1152 user = insert(:user)
1153 info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
1157 |> Changeset.change()
1158 |> Changeset.put_embed(:info, info_change)
1161 assert user.info.confirmation_pending
1166 test "it returns 204 No Content", %{conn: conn, user: user} do
1168 |> assign(:user, user)
1169 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1170 |> json_response(:no_content)
1173 test "it sends confirmation email", %{conn: conn, user: user} do
1175 |> assign(:user, user)
1176 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1178 email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
1179 notify_email = Pleroma.Config.get([:instance, :notify_email])
1180 instance_name = Pleroma.Config.get([:instance, :name])
1183 from: {instance_name, notify_email},
1184 to: {user.name, user.email},
1185 html_body: email.html_body
1190 describe "GET /api/externalprofile/show" do
1191 test "it returns the user", %{conn: conn} do
1192 user = insert(:user)
1193 other_user = insert(:user)
1197 |> assign(:user, user)
1198 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1200 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1204 describe "GET /api/statuses/followers" do
1205 test "it returns a user's followers", %{conn: conn} do
1206 user = insert(:user)
1207 follower_one = insert(:user)
1208 follower_two = insert(:user)
1209 _not_follower = insert(:user)
1211 {:ok, follower_one} = User.follow(follower_one, user)
1212 {:ok, follower_two} = User.follow(follower_two, user)
1216 |> assign(:user, user)
1217 |> get("/api/statuses/followers")
1219 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1220 result = json_response(conn, 200)
1221 assert Enum.sort(expected) == Enum.sort(result)
1224 test "it returns 20 followers per page", %{conn: conn} do
1225 user = insert(:user)
1226 followers = insert_list(21, :user)
1228 Enum.each(followers, fn follower ->
1229 User.follow(follower, user)
1234 |> assign(:user, user)
1235 |> get("/api/statuses/followers")
1237 result = json_response(res_conn, 200)
1238 assert length(result) == 20
1242 |> assign(:user, user)
1243 |> get("/api/statuses/followers?page=2")
1245 result = json_response(res_conn, 200)
1246 assert length(result) == 1
1249 test "it returns a given user's followers with user_id", %{conn: conn} do
1250 user = insert(:user)
1251 follower_one = insert(:user)
1252 follower_two = insert(:user)
1253 not_follower = insert(:user)
1255 {:ok, follower_one} = User.follow(follower_one, user)
1256 {:ok, follower_two} = User.follow(follower_two, user)
1260 |> assign(:user, not_follower)
1261 |> get("/api/statuses/followers", %{"user_id" => user.id})
1263 assert MapSet.equal?(
1264 MapSet.new(json_response(conn, 200)),
1266 UserView.render("index.json", %{
1267 users: [follower_one, follower_two],
1274 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1275 user = insert(:user, %{info: %{hide_followers: true}})
1276 follower_one = insert(:user)
1277 follower_two = insert(:user)
1278 not_follower = insert(:user)
1280 {:ok, _follower_one} = User.follow(follower_one, user)
1281 {:ok, _follower_two} = User.follow(follower_two, user)
1285 |> assign(:user, not_follower)
1286 |> get("/api/statuses/followers", %{"user_id" => user.id})
1287 |> json_response(200)
1289 assert [] == response
1292 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1296 user = insert(:user, %{info: %{hide_followers: true}})
1297 follower_one = insert(:user)
1298 follower_two = insert(:user)
1299 _not_follower = insert(:user)
1301 {:ok, _follower_one} = User.follow(follower_one, user)
1302 {:ok, _follower_two} = User.follow(follower_two, user)
1306 |> assign(:user, user)
1307 |> get("/api/statuses/followers", %{"user_id" => user.id})
1309 refute [] == json_response(conn, 200)
1313 describe "GET /api/statuses/blocks" do
1314 test "it returns the list of users blocked by requester", %{conn: conn} do
1315 user = insert(:user)
1316 other_user = insert(:user)
1318 {:ok, user} = User.block(user, other_user)
1322 |> assign(:user, user)
1323 |> get("/api/statuses/blocks")
1325 expected = UserView.render("index.json", %{users: [other_user], for: user})
1326 result = json_response(conn, 200)
1327 assert Enum.sort(expected) == Enum.sort(result)
1331 describe "GET /api/statuses/friends" do
1332 test "it returns the logged in user's friends", %{conn: conn} do
1333 user = insert(:user)
1334 followed_one = insert(:user)
1335 followed_two = insert(:user)
1336 _not_followed = insert(:user)
1338 {:ok, user} = User.follow(user, followed_one)
1339 {:ok, user} = User.follow(user, followed_two)
1343 |> assign(:user, user)
1344 |> get("/api/statuses/friends")
1346 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1347 result = json_response(conn, 200)
1348 assert Enum.sort(expected) == Enum.sort(result)
1351 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1352 user = insert(:user)
1353 followeds = insert_list(21, :user)
1356 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1357 User.follow(user, followed)
1362 |> assign(:user, user)
1363 |> get("/api/statuses/friends")
1365 result = json_response(res_conn, 200)
1366 assert length(result) == 20
1370 |> assign(:user, user)
1371 |> get("/api/statuses/friends", %{page: 2})
1373 result = json_response(res_conn, 200)
1374 assert length(result) == 1
1378 |> assign(:user, user)
1379 |> get("/api/statuses/friends", %{all: true})
1381 result = json_response(res_conn, 200)
1382 assert length(result) == 21
1385 test "it returns a given user's friends with user_id", %{conn: conn} do
1386 user = insert(:user)
1387 followed_one = insert(:user)
1388 followed_two = insert(:user)
1389 _not_followed = insert(:user)
1391 {:ok, user} = User.follow(user, followed_one)
1392 {:ok, user} = User.follow(user, followed_two)
1396 |> assign(:user, user)
1397 |> get("/api/statuses/friends", %{"user_id" => user.id})
1399 assert MapSet.equal?(
1400 MapSet.new(json_response(conn, 200)),
1402 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1407 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1408 user = insert(:user, %{info: %{hide_follows: true}})
1409 followed_one = insert(:user)
1410 followed_two = insert(:user)
1411 not_followed = insert(:user)
1413 {:ok, user} = User.follow(user, followed_one)
1414 {:ok, user} = User.follow(user, followed_two)
1418 |> assign(:user, not_followed)
1419 |> get("/api/statuses/friends", %{"user_id" => user.id})
1421 assert [] == json_response(conn, 200)
1424 test "it returns friends when hide_follows is set to true if the user themselves request it",
1428 user = insert(:user, %{info: %{hide_follows: true}})
1429 followed_one = insert(:user)
1430 followed_two = insert(:user)
1431 _not_followed = insert(:user)
1433 {:ok, _user} = User.follow(user, followed_one)
1434 {:ok, _user} = User.follow(user, followed_two)
1438 |> assign(:user, user)
1439 |> get("/api/statuses/friends", %{"user_id" => user.id})
1440 |> json_response(200)
1442 refute [] == response
1445 test "it returns a given user's friends with screen_name", %{conn: conn} do
1446 user = insert(:user)
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, user)
1457 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1459 assert MapSet.equal?(
1460 MapSet.new(json_response(conn, 200)),
1462 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1468 describe "GET /friends/ids" do
1469 test "it returns a user's friends", %{conn: conn} do
1470 user = insert(:user)
1471 followed_one = insert(:user)
1472 followed_two = insert(:user)
1473 _not_followed = insert(:user)
1475 {:ok, user} = User.follow(user, followed_one)
1476 {:ok, user} = User.follow(user, followed_two)
1480 |> assign(:user, user)
1481 |> get("/api/friends/ids")
1483 expected = [followed_one.id, followed_two.id]
1485 assert MapSet.equal?(
1486 MapSet.new(Poison.decode!(json_response(conn, 200))),
1487 MapSet.new(expected)
1492 describe "POST /api/account/update_profile.json" do
1493 test "it updates a user's profile", %{conn: conn} do
1494 user = insert(:user)
1495 user2 = insert(:user)
1499 |> assign(:user, user)
1500 |> post("/api/account/update_profile.json", %{
1501 "name" => "new name",
1502 "description" => "hi @#{user2.nickname}"
1505 user = Repo.get!(User, user.id)
1506 assert user.name == "new name"
1509 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1511 }'>@<span>#{user2.nickname}</span></a></span>"
1513 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1516 test "it sets and un-sets hide_follows", %{conn: conn} do
1517 user = insert(:user)
1520 |> assign(:user, user)
1521 |> post("/api/account/update_profile.json", %{
1522 "hide_follows" => "true"
1525 user = Repo.get!(User, user.id)
1526 assert user.info.hide_follows == true
1530 |> assign(:user, user)
1531 |> post("/api/account/update_profile.json", %{
1532 "hide_follows" => "false"
1535 user = refresh_record(user)
1536 assert user.info.hide_follows == false
1537 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1540 test "it sets and un-sets hide_followers", %{conn: conn} do
1541 user = insert(:user)
1544 |> assign(:user, user)
1545 |> post("/api/account/update_profile.json", %{
1546 "hide_followers" => "true"
1549 user = Repo.get!(User, user.id)
1550 assert user.info.hide_followers == true
1554 |> assign(:user, user)
1555 |> post("/api/account/update_profile.json", %{
1556 "hide_followers" => "false"
1559 user = Repo.get!(User, user.id)
1560 assert user.info.hide_followers == false
1561 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1564 test "it sets and un-sets show_role", %{conn: conn} do
1565 user = insert(:user)
1568 |> assign(:user, user)
1569 |> post("/api/account/update_profile.json", %{
1570 "show_role" => "true"
1573 user = Repo.get!(User, user.id)
1574 assert user.info.show_role == true
1578 |> assign(:user, user)
1579 |> post("/api/account/update_profile.json", %{
1580 "show_role" => "false"
1583 user = Repo.get!(User, user.id)
1584 assert user.info.show_role == false
1585 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1588 test "it sets and un-sets skip_thread_containment", %{conn: conn} do
1589 user = insert(:user)
1593 |> assign(:user, user)
1594 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "true"})
1595 |> json_response(200)
1597 assert response["pleroma"]["skip_thread_containment"] == true
1598 user = refresh_record(user)
1599 assert user.info.skip_thread_containment
1603 |> assign(:user, user)
1604 |> post("/api/account/update_profile.json", %{"skip_thread_containment" => "false"})
1605 |> json_response(200)
1607 assert response["pleroma"]["skip_thread_containment"] == false
1608 refute refresh_record(user).info.skip_thread_containment
1611 test "it locks an account", %{conn: conn} do
1612 user = insert(:user)
1616 |> assign(:user, user)
1617 |> post("/api/account/update_profile.json", %{
1621 user = Repo.get!(User, user.id)
1622 assert user.info.locked == true
1624 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1627 test "it unlocks an account", %{conn: conn} do
1628 user = insert(:user)
1632 |> assign(:user, user)
1633 |> post("/api/account/update_profile.json", %{
1637 user = Repo.get!(User, user.id)
1638 assert user.info.locked == false
1640 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1643 # Broken before the change to class="emoji" and non-<img/> in the DB
1645 test "it formats emojos", %{conn: conn} do
1646 user = insert(:user)
1650 |> assign(:user, user)
1651 |> post("/api/account/update_profile.json", %{
1652 "bio" => "I love our :moominmamma:"
1655 assert response = json_response(conn, 200)
1658 "description" => "I love our :moominmamma:",
1659 "description_html" =>
1660 ~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
1666 |> get("/api/users/show.json?user_id=#{user.nickname}")
1668 assert response == json_response(conn, 200)
1672 defp valid_user(_context) do
1673 user = insert(:user)
1677 defp with_credentials(conn, username, password) do
1678 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1679 put_req_header(conn, "authorization", header_content)
1682 describe "GET /api/search.json" do
1683 test "it returns search results", %{conn: conn} do
1684 user = insert(:user)
1685 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1687 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1688 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1692 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1694 assert [status] = json_response(conn, 200)
1695 assert status["id"] == activity.id
1699 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1700 test "it returns the tags timeline", %{conn: conn} do
1701 user = insert(:user)
1702 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1704 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1705 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1709 |> get("/api/statusnet/tags/timeline/2hu.json")
1711 assert [status] = json_response(conn, 200)
1712 assert status["id"] == activity.id
1716 test "Convert newlines to <br> in bio", %{conn: conn} do
1717 user = insert(:user)
1721 |> assign(:user, user)
1722 |> post("/api/account/update_profile.json", %{
1723 "description" => "Hello,\r\nWorld! I\n am a test."
1726 user = Repo.get!(User, user.id)
1727 assert user.bio == "Hello,<br>World! I<br> am a test."
1730 describe "POST /api/pleroma/change_password" do
1733 test "without credentials", %{conn: conn} do
1734 conn = post(conn, "/api/pleroma/change_password")
1735 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1738 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1741 |> with_credentials(current_user.nickname, "test")
1742 |> post("/api/pleroma/change_password", %{
1744 "new_password" => "newpass",
1745 "new_password_confirmation" => "newpass"
1748 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1751 test "with credentials, valid password and new password and confirmation not matching", %{
1757 |> with_credentials(current_user.nickname, "test")
1758 |> post("/api/pleroma/change_password", %{
1759 "password" => "test",
1760 "new_password" => "newpass",
1761 "new_password_confirmation" => "notnewpass"
1764 assert json_response(conn, 200) == %{
1765 "error" => "New password does not match confirmation."
1769 test "with credentials, valid password and invalid new password", %{
1775 |> with_credentials(current_user.nickname, "test")
1776 |> post("/api/pleroma/change_password", %{
1777 "password" => "test",
1778 "new_password" => "",
1779 "new_password_confirmation" => ""
1782 assert json_response(conn, 200) == %{
1783 "error" => "New password can't be blank."
1787 test "with credentials, valid password and matching new password and confirmation", %{
1793 |> with_credentials(current_user.nickname, "test")
1794 |> post("/api/pleroma/change_password", %{
1795 "password" => "test",
1796 "new_password" => "newpass",
1797 "new_password_confirmation" => "newpass"
1800 assert json_response(conn, 200) == %{"status" => "success"}
1801 fetched_user = User.get_cached_by_id(current_user.id)
1802 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1806 describe "POST /api/pleroma/delete_account" do
1809 test "without credentials", %{conn: conn} do
1810 conn = post(conn, "/api/pleroma/delete_account")
1811 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1814 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1817 |> with_credentials(current_user.nickname, "test")
1818 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1820 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1823 test "with credentials and valid password", %{conn: conn, user: current_user} do
1826 |> with_credentials(current_user.nickname, "test")
1827 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1829 assert json_response(conn, 200) == %{"status" => "success"}
1830 # Wait a second for the started task to end
1835 describe "GET /api/pleroma/friend_requests" do
1836 test "it lists friend requests" do
1837 user = insert(:user)
1838 other_user = insert(:user)
1840 {:ok, _activity} = ActivityPub.follow(other_user, user)
1842 user = User.get_cached_by_id(user.id)
1843 other_user = User.get_cached_by_id(other_user.id)
1845 assert User.following?(other_user, user) == false
1849 |> assign(:user, user)
1850 |> get("/api/pleroma/friend_requests")
1852 assert [relationship] = json_response(conn, 200)
1853 assert other_user.id == relationship["id"]
1856 test "requires 'read' permission", %{conn: conn} do
1857 token1 = insert(:oauth_token, scopes: ["write"])
1858 token2 = insert(:oauth_token, scopes: ["read"])
1860 for token <- [token1, token2] do
1863 |> put_req_header("authorization", "Bearer #{token.token}")
1864 |> get("/api/pleroma/friend_requests")
1866 if token == token1 do
1867 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1869 assert json_response(conn, 200)
1875 describe "POST /api/pleroma/friendships/approve" do
1876 test "it approves a friend request" do
1877 user = insert(:user)
1878 other_user = insert(:user)
1880 {:ok, _activity} = ActivityPub.follow(other_user, user)
1882 user = User.get_cached_by_id(user.id)
1883 other_user = User.get_cached_by_id(other_user.id)
1885 assert User.following?(other_user, user) == false
1889 |> assign(:user, user)
1890 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1892 assert relationship = json_response(conn, 200)
1893 assert other_user.id == relationship["id"]
1894 assert relationship["follows_you"] == true
1898 describe "POST /api/pleroma/friendships/deny" do
1899 test "it denies a friend request" do
1900 user = insert(:user)
1901 other_user = insert(:user)
1903 {:ok, _activity} = ActivityPub.follow(other_user, user)
1905 user = User.get_cached_by_id(user.id)
1906 other_user = User.get_cached_by_id(other_user.id)
1908 assert User.following?(other_user, user) == false
1912 |> assign(:user, user)
1913 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1915 assert relationship = json_response(conn, 200)
1916 assert other_user.id == relationship["id"]
1917 assert relationship["follows_you"] == false
1921 describe "GET /api/pleroma/search_user" do
1922 test "it returns users, ordered by similarity", %{conn: conn} do
1923 user = insert(:user, %{name: "eal"})
1924 user_two = insert(:user, %{name: "eal me"})
1925 _user_three = insert(:user, %{name: "zzz"})
1929 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1930 |> json_response(200)
1932 assert length(resp) == 2
1933 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1937 describe "POST /api/media/upload" do
1939 Pleroma.DataCase.ensure_local_uploader(context)
1942 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1945 user = insert(:user)
1947 upload_filename = "test/fixtures/image_tmp.jpg"
1948 File.cp!("test/fixtures/image.jpg", upload_filename)
1950 file = %Plug.Upload{
1951 content_type: "image/jpg",
1952 path: Path.absname(upload_filename),
1953 filename: "image.jpg"
1958 |> assign(:user, user)
1959 |> put_req_header("content-type", "application/octet-stream")
1960 |> post("/api/media/upload", %{
1963 |> json_response(:ok)
1965 assert response["media_id"]
1966 object = Repo.get(Object, response["media_id"])
1968 assert object.data["actor"] == User.ap_id(user)
1972 describe "POST /api/media/metadata/create" do
1974 object = insert(:note)
1975 user = User.get_cached_by_ap_id(object.data["actor"])
1976 %{object: object, user: user}
1979 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1983 initial_description = object.data["name"]
1984 another_user = insert(:user)
1987 |> assign(:user, another_user)
1988 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1989 |> json_response(:forbidden)
1991 object = Repo.get(Object, object.id)
1992 assert object.data["name"] == initial_description
1995 test "it updates `data[name]` of referenced Object with provided value", %{
2000 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
2003 |> assign(:user, user)
2004 |> post("/api/media/metadata/create", %{
2005 "media_id" => object.id,
2006 "alt_text" => %{"text" => description}
2008 |> json_response(:no_content)
2010 object = Repo.get(Object, object.id)
2011 assert object.data["name"] == description
2015 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
2016 test "it returns a list of pinned statuses", %{conn: conn} do
2017 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2019 user = insert(:user, %{name: "egor"})
2020 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
2021 {:ok, _} = CommonAPI.pin(activity_id, user)
2025 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
2026 |> json_response(200)
2028 assert length(resp) == 1
2029 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
2033 describe "POST /api/statuses/pin/:id" do
2035 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2036 [user: insert(:user)]
2039 test "without valid credentials", %{conn: conn} do
2040 note_activity = insert(:note_activity)
2041 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
2042 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2045 test "with credentials", %{conn: conn, user: user} do
2046 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2048 request_path = "/api/statuses/pin/#{activity.id}.json"
2052 |> with_credentials(user.nickname, "test")
2053 |> post(request_path)
2055 user = refresh_record(user)
2057 assert json_response(response, 200) ==
2058 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2062 describe "POST /api/statuses/unpin/:id" do
2064 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2065 [user: insert(:user)]
2068 test "without valid credentials", %{conn: conn} do
2069 note_activity = insert(:note_activity)
2070 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2071 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2074 test "with credentials", %{conn: conn, user: user} do
2075 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2076 {:ok, activity} = CommonAPI.pin(activity.id, user)
2078 request_path = "/api/statuses/unpin/#{activity.id}.json"
2082 |> with_credentials(user.nickname, "test")
2083 |> post(request_path)
2085 user = refresh_record(user)
2087 assert json_response(response, 200) ==
2088 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2092 describe "GET /api/oauth_tokens" do
2094 token = insert(:oauth_token) |> Repo.preload(:user)
2099 test "renders list", %{token: token} do
2102 |> assign(:user, token.user)
2103 |> get("/api/oauth_tokens")
2106 json_response(response, 200)
2110 assert keys -- ["id", "app_name", "valid_until"] == []
2113 test "revoke token", %{token: token} do
2116 |> assign(:user, token.user)
2117 |> delete("/api/oauth_tokens/#{token.id}")
2119 tokens = Token.get_user_tokens(token.user)
2122 assert response.status == 201