Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

779 lines
22KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
  5. use Pleroma.Web.ConnCase
  6. use Oban.Testing, repo: Pleroma.Repo
  7. alias Pleroma.Repo
  8. alias Pleroma.Tests.ObanHelpers
  9. alias Pleroma.User
  10. alias Pleroma.Web.CommonAPI
  11. import ExUnit.CaptureLog
  12. import Pleroma.Factory
  13. import Mock
  14. setup do
  15. Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
  16. :ok
  17. end
  18. clear_config([:instance])
  19. clear_config([:frontend_configurations, :pleroma_fe])
  20. clear_config([:user, :deny_follow_blocked])
  21. describe "POST /api/pleroma/follow_import" do
  22. test "it returns HTTP 200", %{conn: conn} do
  23. user1 = insert(:user)
  24. user2 = insert(:user)
  25. response =
  26. conn
  27. |> assign(:user, user1)
  28. |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"})
  29. |> json_response(:ok)
  30. assert response == "job started"
  31. end
  32. test "it imports follow lists from file", %{conn: conn} do
  33. user1 = insert(:user)
  34. user2 = insert(:user)
  35. with_mocks([
  36. {File, [],
  37. read!: fn "follow_list.txt" ->
  38. "Account address,Show boosts\n#{user2.ap_id},true"
  39. end}
  40. ]) do
  41. response =
  42. conn
  43. |> assign(:user, user1)
  44. |> post("/api/pleroma/follow_import", %{"list" => %Plug.Upload{path: "follow_list.txt"}})
  45. |> json_response(:ok)
  46. assert response == "job started"
  47. assert ObanHelpers.member?(
  48. %{
  49. "op" => "follow_import",
  50. "follower_id" => user1.id,
  51. "followed_identifiers" => [user2.ap_id]
  52. },
  53. all_enqueued(worker: Pleroma.Workers.BackgroundWorker)
  54. )
  55. end
  56. end
  57. test "it imports new-style mastodon follow lists", %{conn: conn} do
  58. user1 = insert(:user)
  59. user2 = insert(:user)
  60. response =
  61. conn
  62. |> assign(:user, user1)
  63. |> post("/api/pleroma/follow_import", %{
  64. "list" => "Account address,Show boosts\n#{user2.ap_id},true"
  65. })
  66. |> json_response(:ok)
  67. assert response == "job started"
  68. end
  69. test "requires 'follow' permission", %{conn: conn} do
  70. token1 = insert(:oauth_token, scopes: ["read", "write"])
  71. token2 = insert(:oauth_token, scopes: ["follow"])
  72. another_user = insert(:user)
  73. for token <- [token1, token2] do
  74. conn =
  75. conn
  76. |> put_req_header("authorization", "Bearer #{token.token}")
  77. |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"})
  78. if token == token1 do
  79. assert %{"error" => "Insufficient permissions: follow."} == json_response(conn, 403)
  80. else
  81. assert json_response(conn, 200)
  82. end
  83. end
  84. end
  85. end
  86. describe "POST /api/pleroma/blocks_import" do
  87. test "it returns HTTP 200", %{conn: conn} do
  88. user1 = insert(:user)
  89. user2 = insert(:user)
  90. response =
  91. conn
  92. |> assign(:user, user1)
  93. |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"})
  94. |> json_response(:ok)
  95. assert response == "job started"
  96. end
  97. test "it imports blocks users from file", %{conn: conn} do
  98. user1 = insert(:user)
  99. user2 = insert(:user)
  100. user3 = insert(:user)
  101. with_mocks([
  102. {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end}
  103. ]) do
  104. response =
  105. conn
  106. |> assign(:user, user1)
  107. |> post("/api/pleroma/blocks_import", %{"list" => %Plug.Upload{path: "blocks_list.txt"}})
  108. |> json_response(:ok)
  109. assert response == "job started"
  110. assert ObanHelpers.member?(
  111. %{
  112. "op" => "blocks_import",
  113. "blocker_id" => user1.id,
  114. "blocked_identifiers" => [user2.ap_id, user3.ap_id]
  115. },
  116. all_enqueued(worker: Pleroma.Workers.BackgroundWorker)
  117. )
  118. end
  119. end
  120. end
  121. describe "PUT /api/pleroma/notification_settings" do
  122. test "it updates notification settings", %{conn: conn} do
  123. user = insert(:user)
  124. conn
  125. |> assign(:user, user)
  126. |> put("/api/pleroma/notification_settings", %{
  127. "followers" => false,
  128. "bar" => 1
  129. })
  130. |> json_response(:ok)
  131. user = Repo.get(User, user.id)
  132. assert %{
  133. "followers" => false,
  134. "follows" => true,
  135. "non_follows" => true,
  136. "non_followers" => true
  137. } == user.info.notification_settings
  138. end
  139. end
  140. describe "GET /api/statusnet/config" do
  141. test "it returns config in xml format", %{conn: conn} do
  142. instance = Pleroma.Config.get(:instance)
  143. response =
  144. conn
  145. |> put_req_header("accept", "application/xml")
  146. |> get("/api/statusnet/config")
  147. |> response(:ok)
  148. assert response ==
  149. "<config>\n<site>\n<name>#{Keyword.get(instance, :name)}</name>\n<site>#{
  150. Pleroma.Web.base_url()
  151. }</site>\n<textlimit>#{Keyword.get(instance, :limit)}</textlimit>\n<closed>#{
  152. !Keyword.get(instance, :registrations_open)
  153. }</closed>\n</site>\n</config>\n"
  154. end
  155. test "it returns config in json format", %{conn: conn} do
  156. instance = Pleroma.Config.get(:instance)
  157. Pleroma.Config.put([:instance, :managed_config], true)
  158. Pleroma.Config.put([:instance, :registrations_open], false)
  159. Pleroma.Config.put([:instance, :invites_enabled], true)
  160. Pleroma.Config.put([:instance, :public], false)
  161. Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
  162. response =
  163. conn
  164. |> put_req_header("accept", "application/json")
  165. |> get("/api/statusnet/config")
  166. |> json_response(:ok)
  167. expected_data = %{
  168. "site" => %{
  169. "accountActivationRequired" => "0",
  170. "closed" => "1",
  171. "description" => Keyword.get(instance, :description),
  172. "invitesEnabled" => "1",
  173. "name" => Keyword.get(instance, :name),
  174. "pleromafe" => %{"theme" => "asuka-hospital"},
  175. "private" => "1",
  176. "safeDMMentionsEnabled" => "0",
  177. "server" => Pleroma.Web.base_url(),
  178. "textlimit" => to_string(Keyword.get(instance, :limit)),
  179. "uploadlimit" => %{
  180. "avatarlimit" => to_string(Keyword.get(instance, :avatar_upload_limit)),
  181. "backgroundlimit" => to_string(Keyword.get(instance, :background_upload_limit)),
  182. "bannerlimit" => to_string(Keyword.get(instance, :banner_upload_limit)),
  183. "uploadlimit" => to_string(Keyword.get(instance, :upload_limit))
  184. },
  185. "vapidPublicKey" => Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
  186. }
  187. }
  188. assert response == expected_data
  189. end
  190. test "returns the state of safe_dm_mentions flag", %{conn: conn} do
  191. Pleroma.Config.put([:instance, :safe_dm_mentions], true)
  192. response =
  193. conn
  194. |> get("/api/statusnet/config.json")
  195. |> json_response(:ok)
  196. assert response["site"]["safeDMMentionsEnabled"] == "1"
  197. Pleroma.Config.put([:instance, :safe_dm_mentions], false)
  198. response =
  199. conn
  200. |> get("/api/statusnet/config.json")
  201. |> json_response(:ok)
  202. assert response["site"]["safeDMMentionsEnabled"] == "0"
  203. end
  204. test "it returns the managed config", %{conn: conn} do
  205. Pleroma.Config.put([:instance, :managed_config], false)
  206. Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
  207. response =
  208. conn
  209. |> get("/api/statusnet/config.json")
  210. |> json_response(:ok)
  211. refute response["site"]["pleromafe"]
  212. Pleroma.Config.put([:instance, :managed_config], true)
  213. response =
  214. conn
  215. |> get("/api/statusnet/config.json")
  216. |> json_response(:ok)
  217. assert response["site"]["pleromafe"] == %{"theme" => "asuka-hospital"}
  218. end
  219. end
  220. describe "GET /api/pleroma/frontend_configurations" do
  221. test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} do
  222. config = [
  223. frontend_a: %{
  224. x: 1,
  225. y: 2
  226. },
  227. frontend_b: %{
  228. z: 3
  229. }
  230. ]
  231. Pleroma.Config.put(:frontend_configurations, config)
  232. response =
  233. conn
  234. |> get("/api/pleroma/frontend_configurations")
  235. |> json_response(:ok)
  236. assert response == Jason.encode!(config |> Enum.into(%{})) |> Jason.decode!()
  237. end
  238. end
  239. describe "/api/pleroma/emoji" do
  240. test "returns json with custom emoji with tags", %{conn: conn} do
  241. emoji =
  242. conn
  243. |> get("/api/pleroma/emoji")
  244. |> json_response(200)
  245. assert Enum.all?(emoji, fn
  246. {_key,
  247. %{
  248. "image_url" => url,
  249. "tags" => tags
  250. }} ->
  251. is_binary(url) and is_list(tags)
  252. end)
  253. end
  254. end
  255. describe "GET /ostatus_subscribe - remote_follow/2" do
  256. test "adds status to pleroma instance if the `acct` is a status", %{conn: conn} do
  257. conn =
  258. get(
  259. conn,
  260. "/ostatus_subscribe?acct=https://mastodon.social/users/emelie/statuses/101849165031453009"
  261. )
  262. assert redirected_to(conn) =~ "/notice/"
  263. end
  264. test "show follow account page if the `acct` is a account link", %{conn: conn} do
  265. response =
  266. get(
  267. conn,
  268. "/ostatus_subscribe?acct=https://mastodon.social/users/emelie"
  269. )
  270. assert html_response(response, 200) =~ "Log in to follow"
  271. end
  272. test "show follow page if the `acct` is a account link", %{conn: conn} do
  273. user = insert(:user)
  274. response =
  275. conn
  276. |> assign(:user, user)
  277. |> get("/ostatus_subscribe?acct=https://mastodon.social/users/emelie")
  278. assert html_response(response, 200) =~ "Remote follow"
  279. end
  280. test "show follow page with error when user cannot fecth by `acct` link", %{conn: conn} do
  281. user = insert(:user)
  282. assert capture_log(fn ->
  283. response =
  284. conn
  285. |> assign(:user, user)
  286. |> get("/ostatus_subscribe?acct=https://mastodon.social/users/not_found")
  287. assert html_response(response, 200) =~ "Error fetching user"
  288. end) =~ "Object has been deleted"
  289. end
  290. end
  291. describe "POST /ostatus_subscribe - do_remote_follow/2 with assigned user " do
  292. test "follows user", %{conn: conn} do
  293. user = insert(:user)
  294. user2 = insert(:user)
  295. response =
  296. conn
  297. |> assign(:user, user)
  298. |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
  299. |> response(200)
  300. assert response =~ "Account followed!"
  301. assert user2.follower_address in refresh_record(user).following
  302. end
  303. test "returns error when user is deactivated", %{conn: conn} do
  304. user = insert(:user, info: %{deactivated: true})
  305. user2 = insert(:user)
  306. response =
  307. conn
  308. |> assign(:user, user)
  309. |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
  310. |> response(200)
  311. assert response =~ "Error following account"
  312. end
  313. test "returns error when user is blocked", %{conn: conn} do
  314. Pleroma.Config.put([:user, :deny_follow_blocked], true)
  315. user = insert(:user)
  316. user2 = insert(:user)
  317. {:ok, _user} = Pleroma.User.block(user2, user)
  318. response =
  319. conn
  320. |> assign(:user, user)
  321. |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
  322. |> response(200)
  323. assert response =~ "Error following account"
  324. end
  325. test "returns error when followee not found", %{conn: conn} do
  326. user = insert(:user)
  327. response =
  328. conn
  329. |> assign(:user, user)
  330. |> post("/ostatus_subscribe", %{"user" => %{"id" => "jimm"}})
  331. |> response(200)
  332. assert response =~ "Error following account"
  333. end
  334. test "returns success result when user already in followers", %{conn: conn} do
  335. user = insert(:user)
  336. user2 = insert(:user)
  337. {:ok, _, _, _} = CommonAPI.follow(user, user2)
  338. response =
  339. conn
  340. |> assign(:user, refresh_record(user))
  341. |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
  342. |> response(200)
  343. assert response =~ "Account followed!"
  344. end
  345. end
  346. describe "POST /ostatus_subscribe - do_remote_follow/2 without assigned user " do
  347. test "follows", %{conn: conn} do
  348. user = insert(:user)
  349. user2 = insert(:user)
  350. response =
  351. conn
  352. |> post("/ostatus_subscribe", %{
  353. "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
  354. })
  355. |> response(200)
  356. assert response =~ "Account followed!"
  357. assert user2.follower_address in refresh_record(user).following
  358. end
  359. test "returns error when followee not found", %{conn: conn} do
  360. user = insert(:user)
  361. response =
  362. conn
  363. |> post("/ostatus_subscribe", %{
  364. "authorization" => %{"name" => user.nickname, "password" => "test", "id" => "jimm"}
  365. })
  366. |> response(200)
  367. assert response =~ "Error following account"
  368. end
  369. test "returns error when login invalid", %{conn: conn} do
  370. user = insert(:user)
  371. response =
  372. conn
  373. |> post("/ostatus_subscribe", %{
  374. "authorization" => %{"name" => "jimm", "password" => "test", "id" => user.id}
  375. })
  376. |> response(200)
  377. assert response =~ "Wrong username or password"
  378. end
  379. test "returns error when password invalid", %{conn: conn} do
  380. user = insert(:user)
  381. user2 = insert(:user)
  382. response =
  383. conn
  384. |> post("/ostatus_subscribe", %{
  385. "authorization" => %{"name" => user.nickname, "password" => "42", "id" => user2.id}
  386. })
  387. |> response(200)
  388. assert response =~ "Wrong username or password"
  389. end
  390. test "returns error when user is blocked", %{conn: conn} do
  391. Pleroma.Config.put([:user, :deny_follow_blocked], true)
  392. user = insert(:user)
  393. user2 = insert(:user)
  394. {:ok, _user} = Pleroma.User.block(user2, user)
  395. response =
  396. conn
  397. |> post("/ostatus_subscribe", %{
  398. "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
  399. })
  400. |> response(200)
  401. assert response =~ "Error following account"
  402. end
  403. end
  404. describe "GET /api/pleroma/healthcheck" do
  405. clear_config([:instance, :healthcheck])
  406. test "returns 503 when healthcheck disabled", %{conn: conn} do
  407. Pleroma.Config.put([:instance, :healthcheck], false)
  408. response =
  409. conn
  410. |> get("/api/pleroma/healthcheck")
  411. |> json_response(503)
  412. assert response == %{}
  413. end
  414. test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do
  415. Pleroma.Config.put([:instance, :healthcheck], true)
  416. with_mock Pleroma.Healthcheck,
  417. system_info: fn -> %Pleroma.Healthcheck{healthy: true} end do
  418. response =
  419. conn
  420. |> get("/api/pleroma/healthcheck")
  421. |> json_response(200)
  422. assert %{
  423. "active" => _,
  424. "healthy" => true,
  425. "idle" => _,
  426. "memory_used" => _,
  427. "pool_size" => _
  428. } = response
  429. end
  430. end
  431. test "returns 503 when healthcheck enabled and health is false", %{conn: conn} do
  432. Pleroma.Config.put([:instance, :healthcheck], true)
  433. with_mock Pleroma.Healthcheck,
  434. system_info: fn -> %Pleroma.Healthcheck{healthy: false} end do
  435. response =
  436. conn
  437. |> get("/api/pleroma/healthcheck")
  438. |> json_response(503)
  439. assert %{
  440. "active" => _,
  441. "healthy" => false,
  442. "idle" => _,
  443. "memory_used" => _,
  444. "pool_size" => _
  445. } = response
  446. end
  447. end
  448. end
  449. describe "POST /api/pleroma/disable_account" do
  450. test "it returns HTTP 200", %{conn: conn} do
  451. user = insert(:user)
  452. response =
  453. conn
  454. |> assign(:user, user)
  455. |> post("/api/pleroma/disable_account", %{"password" => "test"})
  456. |> json_response(:ok)
  457. assert response == %{"status" => "success"}
  458. ObanHelpers.perform_all()
  459. user = User.get_cached_by_id(user.id)
  460. assert user.info.deactivated == true
  461. end
  462. test "it returns returns when password invalid", %{conn: conn} do
  463. user = insert(:user)
  464. response =
  465. conn
  466. |> assign(:user, user)
  467. |> post("/api/pleroma/disable_account", %{"password" => "test1"})
  468. |> json_response(:ok)
  469. assert response == %{"error" => "Invalid password."}
  470. user = User.get_cached_by_id(user.id)
  471. refute user.info.deactivated
  472. end
  473. end
  474. describe "GET /api/statusnet/version" do
  475. test "it returns version in xml format", %{conn: conn} do
  476. response =
  477. conn
  478. |> put_req_header("accept", "application/xml")
  479. |> get("/api/statusnet/version")
  480. |> response(:ok)
  481. assert response == "<version>#{Pleroma.Application.named_version()}</version>"
  482. end
  483. test "it returns version in json format", %{conn: conn} do
  484. response =
  485. conn
  486. |> put_req_header("accept", "application/json")
  487. |> get("/api/statusnet/version")
  488. |> json_response(:ok)
  489. assert response == "#{Pleroma.Application.named_version()}"
  490. end
  491. end
  492. describe "POST /main/ostatus - remote_subscribe/2" do
  493. test "renders subscribe form", %{conn: conn} do
  494. user = insert(:user)
  495. response =
  496. conn
  497. |> post("/main/ostatus", %{"nickname" => user.nickname, "profile" => ""})
  498. |> response(:ok)
  499. refute response =~ "Could not find user"
  500. assert response =~ "Remotely follow #{user.nickname}"
  501. end
  502. test "renders subscribe form with error when user not found", %{conn: conn} do
  503. response =
  504. conn
  505. |> post("/main/ostatus", %{"nickname" => "nickname", "profile" => ""})
  506. |> response(:ok)
  507. assert response =~ "Could not find user"
  508. refute response =~ "Remotely follow"
  509. end
  510. test "it redirect to webfinger url", %{conn: conn} do
  511. user = insert(:user)
  512. user2 = insert(:user, ap_id: "shp@social.heldscal.la")
  513. conn =
  514. conn
  515. |> post("/main/ostatus", %{
  516. "user" => %{"nickname" => user.nickname, "profile" => user2.ap_id}
  517. })
  518. assert redirected_to(conn) ==
  519. "https://social.heldscal.la/main/ostatussub?profile=#{user.ap_id}"
  520. end
  521. test "it renders form with error when use not found", %{conn: conn} do
  522. user2 = insert(:user, ap_id: "shp@social.heldscal.la")
  523. response =
  524. conn
  525. |> post("/main/ostatus", %{"user" => %{"nickname" => "jimm", "profile" => user2.ap_id}})
  526. |> response(:ok)
  527. assert response =~ "Something went wrong."
  528. end
  529. end
  530. test "it returns new captcha", %{conn: conn} do
  531. with_mock Pleroma.Captcha,
  532. new: fn -> "test_captcha" end do
  533. resp =
  534. conn
  535. |> get("/api/pleroma/captcha")
  536. |> response(200)
  537. assert resp == "\"test_captcha\""
  538. assert called(Pleroma.Captcha.new())
  539. end
  540. end
  541. defp with_credentials(conn, username, password) do
  542. header_content = "Basic " <> Base.encode64("#{username}:#{password}")
  543. put_req_header(conn, "authorization", header_content)
  544. end
  545. defp valid_user(_context) do
  546. user = insert(:user)
  547. [user: user]
  548. end
  549. describe "POST /api/pleroma/change_email" do
  550. setup [:valid_user]
  551. test "without credentials", %{conn: conn} do
  552. conn = post(conn, "/api/pleroma/change_email")
  553. assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
  554. end
  555. test "with credentials and invalid password", %{conn: conn, user: current_user} do
  556. conn =
  557. conn
  558. |> with_credentials(current_user.nickname, "test")
  559. |> post("/api/pleroma/change_email", %{
  560. "password" => "hi",
  561. "email" => "test@test.com"
  562. })
  563. assert json_response(conn, 200) == %{"error" => "Invalid password."}
  564. end
  565. test "with credentials, valid password and invalid email", %{
  566. conn: conn,
  567. user: current_user
  568. } do
  569. conn =
  570. conn
  571. |> with_credentials(current_user.nickname, "test")
  572. |> post("/api/pleroma/change_email", %{
  573. "password" => "test",
  574. "email" => "foobar"
  575. })
  576. assert json_response(conn, 200) == %{"error" => "Email has invalid format."}
  577. end
  578. test "with credentials, valid password and no email", %{
  579. conn: conn,
  580. user: current_user
  581. } do
  582. conn =
  583. conn
  584. |> with_credentials(current_user.nickname, "test")
  585. |> post("/api/pleroma/change_email", %{
  586. "password" => "test"
  587. })
  588. assert json_response(conn, 200) == %{"error" => "Email can't be blank."}
  589. end
  590. test "with credentials, valid password and blank email", %{
  591. conn: conn,
  592. user: current_user
  593. } do
  594. conn =
  595. conn
  596. |> with_credentials(current_user.nickname, "test")
  597. |> post("/api/pleroma/change_email", %{
  598. "password" => "test",
  599. "email" => ""
  600. })
  601. assert json_response(conn, 200) == %{"error" => "Email can't be blank."}
  602. end
  603. test "with credentials, valid password and non unique email", %{
  604. conn: conn,
  605. user: current_user
  606. } do
  607. user = insert(:user)
  608. conn =
  609. conn
  610. |> with_credentials(current_user.nickname, "test")
  611. |> post("/api/pleroma/change_email", %{
  612. "password" => "test",
  613. "email" => user.email
  614. })
  615. assert json_response(conn, 200) == %{"error" => "Email has already been taken."}
  616. end
  617. test "with credentials, valid password and valid email", %{
  618. conn: conn,
  619. user: current_user
  620. } do
  621. conn =
  622. conn
  623. |> with_credentials(current_user.nickname, "test")
  624. |> post("/api/pleroma/change_email", %{
  625. "password" => "test",
  626. "email" => "cofe@foobar.com"
  627. })
  628. assert json_response(conn, 200) == %{"status" => "success"}
  629. end
  630. end
  631. end