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.UtilControllerTest do
6 use Pleroma.Web.ConnCase
10 alias Pleroma.Web.CommonAPI
11 import ExUnit.CaptureLog
12 import Pleroma.Factory
16 Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
20 clear_config([:instance])
21 clear_config([:frontend_configurations, :pleroma_fe])
22 clear_config([:user, :deny_follow_blocked])
24 describe "POST /api/pleroma/follow_import" do
25 test "it returns HTTP 200", %{conn: conn} do
31 |> assign(:user, user1)
32 |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"})
35 assert response == "job started"
38 test "it imports follow lists from file", %{conn: conn} do
44 read!: fn "follow_list.txt" ->
45 "Account address,Show boosts\n#{user2.ap_id},true"
47 {PleromaJobQueue, [:passthrough], []}
51 |> assign(:user, user1)
52 |> post("/api/pleroma/follow_import", %{"list" => %Plug.Upload{path: "follow_list.txt"}})
56 PleromaJobQueue.enqueue(
59 [:follow_import, user1, [user2.ap_id]]
63 assert response == "job started"
67 test "it imports new-style mastodon follow lists", %{conn: conn} do
73 |> assign(:user, user1)
74 |> post("/api/pleroma/follow_import", %{
75 "list" => "Account address,Show boosts\n#{user2.ap_id},true"
79 assert response == "job started"
82 test "requires 'follow' permission", %{conn: conn} do
83 token1 = insert(:oauth_token, scopes: ["read", "write"])
84 token2 = insert(:oauth_token, scopes: ["follow"])
85 another_user = insert(:user)
87 for token <- [token1, token2] do
90 |> put_req_header("authorization", "Bearer #{token.token}")
91 |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"})
94 assert %{"error" => "Insufficient permissions: follow."} == json_response(conn, 403)
96 assert json_response(conn, 200)
102 describe "POST /api/pleroma/blocks_import" do
103 test "it returns HTTP 200", %{conn: conn} do
104 user1 = insert(:user)
105 user2 = insert(:user)
109 |> assign(:user, user1)
110 |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"})
111 |> json_response(:ok)
113 assert response == "job started"
116 test "it imports blocks users from file", %{conn: conn} do
117 user1 = insert(:user)
118 user2 = insert(:user)
119 user3 = insert(:user)
122 {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end},
123 {PleromaJobQueue, [:passthrough], []}
127 |> assign(:user, user1)
128 |> post("/api/pleroma/blocks_import", %{"list" => %Plug.Upload{path: "blocks_list.txt"}})
129 |> json_response(:ok)
132 PleromaJobQueue.enqueue(
135 [:blocks_import, user1, [user2.ap_id, user3.ap_id]]
139 assert response == "job started"
144 describe "PUT /api/pleroma/notification_settings" do
145 test "it updates notification settings", %{conn: conn} do
149 |> assign(:user, user)
150 |> put("/api/pleroma/notification_settings", %{
151 "followers" => false,
154 |> json_response(:ok)
156 user = Repo.get(User, user.id)
159 "followers" => false,
161 "non_follows" => true,
162 "non_followers" => true
163 } == user.info.notification_settings
167 describe "GET /api/statusnet/config" do
168 test "it returns config in xml format", %{conn: conn} do
169 instance = Pleroma.Config.get(:instance)
173 |> put_req_header("accept", "application/xml")
174 |> get("/api/statusnet/config")
178 "<config>\n<site>\n<name>#{Keyword.get(instance, :name)}</name>\n<site>#{
179 Pleroma.Web.base_url()
180 }</site>\n<textlimit>#{Keyword.get(instance, :limit)}</textlimit>\n<closed>#{
181 !Keyword.get(instance, :registrations_open)
182 }</closed>\n</site>\n</config>\n"
185 test "it returns config in json format", %{conn: conn} do
186 instance = Pleroma.Config.get(:instance)
187 Pleroma.Config.put([:instance, :managed_config], true)
188 Pleroma.Config.put([:instance, :registrations_open], false)
189 Pleroma.Config.put([:instance, :invites_enabled], true)
190 Pleroma.Config.put([:instance, :public], false)
191 Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
195 |> put_req_header("accept", "application/json")
196 |> get("/api/statusnet/config")
197 |> json_response(:ok)
201 "accountActivationRequired" => "0",
203 "description" => Keyword.get(instance, :description),
204 "invitesEnabled" => "1",
205 "name" => Keyword.get(instance, :name),
206 "pleromafe" => %{"theme" => "asuka-hospital"},
208 "safeDMMentionsEnabled" => "0",
209 "server" => Pleroma.Web.base_url(),
210 "textlimit" => to_string(Keyword.get(instance, :limit)),
212 "avatarlimit" => to_string(Keyword.get(instance, :avatar_upload_limit)),
213 "backgroundlimit" => to_string(Keyword.get(instance, :background_upload_limit)),
214 "bannerlimit" => to_string(Keyword.get(instance, :banner_upload_limit)),
215 "uploadlimit" => to_string(Keyword.get(instance, :upload_limit))
217 "vapidPublicKey" => Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
221 assert response == expected_data
224 test "returns the state of safe_dm_mentions flag", %{conn: conn} do
225 Pleroma.Config.put([:instance, :safe_dm_mentions], true)
229 |> get("/api/statusnet/config.json")
230 |> json_response(:ok)
232 assert response["site"]["safeDMMentionsEnabled"] == "1"
234 Pleroma.Config.put([:instance, :safe_dm_mentions], false)
238 |> get("/api/statusnet/config.json")
239 |> json_response(:ok)
241 assert response["site"]["safeDMMentionsEnabled"] == "0"
244 test "it returns the managed config", %{conn: conn} do
245 Pleroma.Config.put([:instance, :managed_config], false)
246 Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
250 |> get("/api/statusnet/config.json")
251 |> json_response(:ok)
253 refute response["site"]["pleromafe"]
255 Pleroma.Config.put([:instance, :managed_config], true)
259 |> get("/api/statusnet/config.json")
260 |> json_response(:ok)
262 assert response["site"]["pleromafe"] == %{"theme" => "asuka-hospital"}
266 describe "GET /api/pleroma/frontend_configurations" do
267 test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} do
278 Pleroma.Config.put(:frontend_configurations, config)
282 |> get("/api/pleroma/frontend_configurations")
283 |> json_response(:ok)
285 assert response == Jason.encode!(config |> Enum.into(%{})) |> Jason.decode!()
289 describe "/api/pleroma/emoji" do
290 test "returns json with custom emoji with tags", %{conn: conn} do
293 |> get("/api/pleroma/emoji")
294 |> json_response(200)
296 assert Enum.all?(emoji, fn
302 is_binary(url) and is_list(tags)
307 describe "GET /ostatus_subscribe - remote_follow/2" do
308 test "adds status to pleroma instance if the `acct` is a status", %{conn: conn} do
312 "/ostatus_subscribe?acct=https://mastodon.social/users/emelie/statuses/101849165031453009"
315 assert redirected_to(conn) =~ "/notice/"
318 test "show follow account page if the `acct` is a account link", %{conn: conn} do
322 "/ostatus_subscribe?acct=https://mastodon.social/users/emelie"
325 assert html_response(response, 200) =~ "Log in to follow"
328 test "show follow page if the `acct` is a account link", %{conn: conn} do
333 |> assign(:user, user)
334 |> get("/ostatus_subscribe?acct=https://mastodon.social/users/emelie")
336 assert html_response(response, 200) =~ "Remote follow"
339 test "show follow page with error when user cannot fecth by `acct` link", %{conn: conn} do
342 assert capture_log(fn ->
345 |> assign(:user, user)
346 |> get("/ostatus_subscribe?acct=https://mastodon.social/users/not_found")
348 assert html_response(response, 200) =~ "Error fetching user"
349 end) =~ "Object has been deleted"
353 describe "POST /ostatus_subscribe - do_remote_follow/2 with assigned user " do
354 test "follows user", %{conn: conn} do
356 user2 = insert(:user)
360 |> assign(:user, user)
361 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
364 assert response =~ "Account followed!"
365 assert user2.follower_address in refresh_record(user).following
368 test "returns error when user is deactivated", %{conn: conn} do
369 user = insert(:user, info: %{deactivated: true})
370 user2 = insert(:user)
374 |> assign(:user, user)
375 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
378 assert response =~ "Error following account"
381 test "returns error when user is blocked", %{conn: conn} do
382 Pleroma.Config.put([:user, :deny_follow_blocked], true)
384 user2 = insert(:user)
386 {:ok, _user} = Pleroma.User.block(user2, user)
390 |> assign(:user, user)
391 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
394 assert response =~ "Error following account"
397 test "returns error when followee not found", %{conn: conn} do
402 |> assign(:user, user)
403 |> post("/ostatus_subscribe", %{"user" => %{"id" => "jimm"}})
406 assert response =~ "Error following account"
409 test "returns success result when user already in followers", %{conn: conn} do
411 user2 = insert(:user)
412 {:ok, _, _, _} = CommonAPI.follow(user, user2)
416 |> assign(:user, refresh_record(user))
417 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
420 assert response =~ "Account followed!"
424 describe "POST /ostatus_subscribe - do_remote_follow/2 without assigned user " do
425 test "follows", %{conn: conn} do
427 user2 = insert(:user)
431 |> post("/ostatus_subscribe", %{
432 "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
436 assert response =~ "Account followed!"
437 assert user2.follower_address in refresh_record(user).following
440 test "returns error when followee not found", %{conn: conn} do
445 |> post("/ostatus_subscribe", %{
446 "authorization" => %{"name" => user.nickname, "password" => "test", "id" => "jimm"}
450 assert response =~ "Error following account"
453 test "returns error when login invalid", %{conn: conn} do
458 |> post("/ostatus_subscribe", %{
459 "authorization" => %{"name" => "jimm", "password" => "test", "id" => user.id}
463 assert response =~ "Wrong username or password"
466 test "returns error when password invalid", %{conn: conn} do
468 user2 = insert(:user)
472 |> post("/ostatus_subscribe", %{
473 "authorization" => %{"name" => user.nickname, "password" => "42", "id" => user2.id}
477 assert response =~ "Wrong username or password"
480 test "returns error when user is blocked", %{conn: conn} do
481 Pleroma.Config.put([:user, :deny_follow_blocked], true)
483 user2 = insert(:user)
484 {:ok, _user} = Pleroma.User.block(user2, user)
488 |> post("/ostatus_subscribe", %{
489 "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
493 assert response =~ "Error following account"
497 describe "GET /api/pleroma/healthcheck" do
498 clear_config([:instance, :healthcheck])
500 test "returns 503 when healthcheck disabled", %{conn: conn} do
501 Pleroma.Config.put([:instance, :healthcheck], false)
505 |> get("/api/pleroma/healthcheck")
506 |> json_response(503)
508 assert response == %{}
511 test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do
512 Pleroma.Config.put([:instance, :healthcheck], true)
514 with_mock Pleroma.Healthcheck,
515 system_info: fn -> %Pleroma.Healthcheck{healthy: true} end do
518 |> get("/api/pleroma/healthcheck")
519 |> json_response(200)
531 test "returns 503 when healthcheck enabled and health is false", %{conn: conn} do
532 Pleroma.Config.put([:instance, :healthcheck], true)
534 with_mock Pleroma.Healthcheck,
535 system_info: fn -> %Pleroma.Healthcheck{healthy: false} end do
538 |> get("/api/pleroma/healthcheck")
539 |> json_response(503)
552 describe "POST /api/pleroma/disable_account" do
553 test "it returns HTTP 200", %{conn: conn} do
558 |> assign(:user, user)
559 |> post("/api/pleroma/disable_account", %{"password" => "test"})
560 |> json_response(:ok)
562 assert response == %{"status" => "success"}
564 user = User.get_cached_by_id(user.id)
566 assert user.info.deactivated == true
569 test "it returns returns when password invalid", %{conn: conn} do
574 |> assign(:user, user)
575 |> post("/api/pleroma/disable_account", %{"password" => "test1"})
576 |> json_response(:ok)
578 assert response == %{"error" => "Invalid password."}
579 user = User.get_cached_by_id(user.id)
581 refute user.info.deactivated
585 describe "GET /api/statusnet/version" do
586 test "it returns version in xml format", %{conn: conn} do
589 |> put_req_header("accept", "application/xml")
590 |> get("/api/statusnet/version")
593 assert response == "<version>#{Pleroma.Application.named_version()}</version>"
596 test "it returns version in json format", %{conn: conn} do
599 |> put_req_header("accept", "application/json")
600 |> get("/api/statusnet/version")
601 |> json_response(:ok)
603 assert response == "#{Pleroma.Application.named_version()}"
607 describe "POST /main/ostatus - remote_subscribe/2" do
608 test "renders subscribe form", %{conn: conn} do
613 |> post("/main/ostatus", %{"nickname" => user.nickname, "profile" => ""})
616 refute response =~ "Could not find user"
617 assert response =~ "Remotely follow #{user.nickname}"
620 test "renders subscribe form with error when user not found", %{conn: conn} do
623 |> post("/main/ostatus", %{"nickname" => "nickname", "profile" => ""})
626 assert response =~ "Could not find user"
627 refute response =~ "Remotely follow"
630 test "it redirect to webfinger url", %{conn: conn} do
632 user2 = insert(:user, ap_id: "shp@social.heldscal.la")
636 |> post("/main/ostatus", %{
637 "user" => %{"nickname" => user.nickname, "profile" => user2.ap_id}
640 assert redirected_to(conn) ==
641 "https://social.heldscal.la/main/ostatussub?profile=#{user.ap_id}"
644 test "it renders form with error when use not found", %{conn: conn} do
645 user2 = insert(:user, ap_id: "shp@social.heldscal.la")
649 |> post("/main/ostatus", %{"user" => %{"nickname" => "jimm", "profile" => user2.ap_id}})
652 assert response =~ "Something went wrong."
656 test "it returns new captcha", %{conn: conn} do
657 with_mock Pleroma.Captcha,
658 new: fn -> "test_captcha" end do
661 |> get("/api/pleroma/captcha")
664 assert resp == "\"test_captcha\""
665 assert called(Pleroma.Captcha.new())
669 defp with_credentials(conn, username, password) do
670 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
671 put_req_header(conn, "authorization", header_content)
674 defp valid_user(_context) do
679 describe "POST /api/pleroma/change_email" do
682 test "without credentials", %{conn: conn} do
683 conn = post(conn, "/api/pleroma/change_email")
684 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
687 test "with credentials and invalid password", %{conn: conn, user: current_user} do
690 |> with_credentials(current_user.nickname, "test")
691 |> post("/api/pleroma/change_email", %{
693 "email" => "test@test.com"
696 assert json_response(conn, 200) == %{"error" => "Invalid password."}
699 test "with credentials, valid password and invalid email", %{
705 |> with_credentials(current_user.nickname, "test")
706 |> post("/api/pleroma/change_email", %{
707 "password" => "test",
711 assert json_response(conn, 200) == %{"error" => "Email has invalid format."}
714 test "with credentials, valid password and no email", %{
720 |> with_credentials(current_user.nickname, "test")
721 |> post("/api/pleroma/change_email", %{
725 assert json_response(conn, 200) == %{"error" => "Email can't be blank."}
728 test "with credentials, valid password and blank email", %{
734 |> with_credentials(current_user.nickname, "test")
735 |> post("/api/pleroma/change_email", %{
736 "password" => "test",
740 assert json_response(conn, 200) == %{"error" => "Email can't be blank."}
743 test "with credentials, valid password and non unique email", %{
751 |> with_credentials(current_user.nickname, "test")
752 |> post("/api/pleroma/change_email", %{
753 "password" => "test",
754 "email" => user.email
757 assert json_response(conn, 200) == %{"error" => "Email has already been taken."}
760 test "with credentials, valid password and valid email", %{
766 |> with_credentials(current_user.nickname, "test")
767 |> post("/api/pleroma/change_email", %{
768 "password" => "test",
769 "email" => "cofe@foobar.com"
772 assert json_response(conn, 200) == %{"status" => "success"}