logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

account_controller_test.exs (53804B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
  5. use Pleroma.Web.ConnCase
  6. alias Pleroma.Repo
  7. alias Pleroma.User
  8. alias Pleroma.Web.ActivityPub.ActivityPub
  9. alias Pleroma.Web.ActivityPub.InternalFetchActor
  10. alias Pleroma.Web.CommonAPI
  11. alias Pleroma.Web.OAuth.Token
  12. import Pleroma.Factory
  13. describe "account fetching" do
  14. test "works by id" do
  15. %User{id: user_id} = insert(:user)
  16. assert %{"id" => ^user_id} =
  17. build_conn()
  18. |> get("/api/v1/accounts/#{user_id}")
  19. |> json_response_and_validate_schema(200)
  20. assert %{"error" => "Can't find user"} =
  21. build_conn()
  22. |> get("/api/v1/accounts/-1")
  23. |> json_response_and_validate_schema(404)
  24. end
  25. test "works by nickname" do
  26. user = insert(:user)
  27. assert %{"id" => user_id} =
  28. build_conn()
  29. |> get("/api/v1/accounts/#{user.nickname}")
  30. |> json_response_and_validate_schema(200)
  31. end
  32. test "works by nickname for remote users" do
  33. clear_config([:instance, :limit_to_local_content], false)
  34. user = insert(:user, nickname: "user@example.com", local: false)
  35. assert %{"id" => user_id} =
  36. build_conn()
  37. |> get("/api/v1/accounts/#{user.nickname}")
  38. |> json_response_and_validate_schema(200)
  39. end
  40. test "respects limit_to_local_content == :all for remote user nicknames" do
  41. clear_config([:instance, :limit_to_local_content], :all)
  42. user = insert(:user, nickname: "user@example.com", local: false)
  43. assert build_conn()
  44. |> get("/api/v1/accounts/#{user.nickname}")
  45. |> json_response_and_validate_schema(404)
  46. end
  47. test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
  48. clear_config([:instance, :limit_to_local_content], :unauthenticated)
  49. user = insert(:user, nickname: "user@example.com", local: false)
  50. reading_user = insert(:user)
  51. conn =
  52. build_conn()
  53. |> get("/api/v1/accounts/#{user.nickname}")
  54. assert json_response_and_validate_schema(conn, 404)
  55. conn =
  56. build_conn()
  57. |> assign(:user, reading_user)
  58. |> assign(:token, insert(:oauth_token, user: reading_user, scopes: ["read:accounts"]))
  59. |> get("/api/v1/accounts/#{user.nickname}")
  60. assert %{"id" => id} = json_response_and_validate_schema(conn, 200)
  61. assert id == user.id
  62. end
  63. test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
  64. # Need to set an old-style integer ID to reproduce the problem
  65. # (these are no longer assigned to new accounts but were preserved
  66. # for existing accounts during the migration to flakeIDs)
  67. user_one = insert(:user, %{id: 1212})
  68. user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
  69. acc_one =
  70. conn
  71. |> get("/api/v1/accounts/#{user_one.id}")
  72. |> json_response_and_validate_schema(:ok)
  73. acc_two =
  74. conn
  75. |> get("/api/v1/accounts/#{user_two.nickname}")
  76. |> json_response_and_validate_schema(:ok)
  77. acc_three =
  78. conn
  79. |> get("/api/v1/accounts/#{user_two.id}")
  80. |> json_response_and_validate_schema(:ok)
  81. refute acc_one == acc_two
  82. assert acc_two == acc_three
  83. end
  84. test "returns 404 when user is invisible", %{conn: conn} do
  85. user = insert(:user, %{invisible: true})
  86. assert %{"error" => "Can't find user"} =
  87. conn
  88. |> get("/api/v1/accounts/#{user.nickname}")
  89. |> json_response_and_validate_schema(404)
  90. end
  91. test "returns 404 for internal.fetch actor", %{conn: conn} do
  92. %User{nickname: "internal.fetch"} = InternalFetchActor.get_actor()
  93. assert %{"error" => "Can't find user"} =
  94. conn
  95. |> get("/api/v1/accounts/internal.fetch")
  96. |> json_response_and_validate_schema(404)
  97. end
  98. test "returns 404 for deactivated user", %{conn: conn} do
  99. user = insert(:user, deactivated: true)
  100. assert %{"error" => "Can't find user"} =
  101. conn
  102. |> get("/api/v1/accounts/#{user.id}")
  103. |> json_response_and_validate_schema(:not_found)
  104. end
  105. end
  106. defp local_and_remote_users do
  107. local = insert(:user)
  108. remote = insert(:user, local: false)
  109. {:ok, local: local, remote: remote}
  110. end
  111. describe "user fetching with restrict unauthenticated profiles for local and remote" do
  112. setup do: local_and_remote_users()
  113. setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
  114. setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
  115. test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
  116. assert %{"error" => "This API requires an authenticated user"} ==
  117. conn
  118. |> get("/api/v1/accounts/#{local.id}")
  119. |> json_response_and_validate_schema(:unauthorized)
  120. assert %{"error" => "This API requires an authenticated user"} ==
  121. conn
  122. |> get("/api/v1/accounts/#{remote.id}")
  123. |> json_response_and_validate_schema(:unauthorized)
  124. end
  125. test "if user is authenticated", %{local: local, remote: remote} do
  126. %{conn: conn} = oauth_access(["read"])
  127. res_conn = get(conn, "/api/v1/accounts/#{local.id}")
  128. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  129. res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
  130. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  131. end
  132. end
  133. describe "user fetching with restrict unauthenticated profiles for local" do
  134. setup do: local_and_remote_users()
  135. setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
  136. test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
  137. res_conn = get(conn, "/api/v1/accounts/#{local.id}")
  138. assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
  139. "error" => "This API requires an authenticated user"
  140. }
  141. res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
  142. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  143. end
  144. test "if user is authenticated", %{local: local, remote: remote} do
  145. %{conn: conn} = oauth_access(["read"])
  146. res_conn = get(conn, "/api/v1/accounts/#{local.id}")
  147. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  148. res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
  149. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  150. end
  151. end
  152. describe "user fetching with restrict unauthenticated profiles for remote" do
  153. setup do: local_and_remote_users()
  154. setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
  155. test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
  156. res_conn = get(conn, "/api/v1/accounts/#{local.id}")
  157. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  158. res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
  159. assert json_response_and_validate_schema(res_conn, :unauthorized) == %{
  160. "error" => "This API requires an authenticated user"
  161. }
  162. end
  163. test "if user is authenticated", %{local: local, remote: remote} do
  164. %{conn: conn} = oauth_access(["read"])
  165. res_conn = get(conn, "/api/v1/accounts/#{local.id}")
  166. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  167. res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
  168. assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
  169. end
  170. end
  171. describe "user timelines" do
  172. setup do: oauth_access(["read:statuses"])
  173. test "works with announces that are just addressed to public", %{conn: conn} do
  174. user = insert(:user, ap_id: "https://honktest/u/test", local: false)
  175. other_user = insert(:user)
  176. {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"})
  177. {:ok, announce, _} =
  178. %{
  179. "@context" => "https://www.w3.org/ns/activitystreams",
  180. "actor" => "https://honktest/u/test",
  181. "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx",
  182. "object" => post.data["object"],
  183. "published" => "2019-06-25T19:33:58Z",
  184. "to" => ["https://www.w3.org/ns/activitystreams#Public"],
  185. "type" => "Announce"
  186. }
  187. |> ActivityPub.persist(local: false)
  188. assert resp =
  189. conn
  190. |> get("/api/v1/accounts/#{user.id}/statuses")
  191. |> json_response_and_validate_schema(200)
  192. assert [%{"id" => id}] = resp
  193. assert id == announce.id
  194. end
  195. test "deactivated user", %{conn: conn} do
  196. user = insert(:user, deactivated: true)
  197. assert %{"error" => "Can't find user"} ==
  198. conn
  199. |> get("/api/v1/accounts/#{user.id}/statuses")
  200. |> json_response_and_validate_schema(:not_found)
  201. end
  202. test "returns 404 when user is invisible", %{conn: conn} do
  203. user = insert(:user, %{invisible: true})
  204. assert %{"error" => "Can't find user"} =
  205. conn
  206. |> get("/api/v1/accounts/#{user.id}")
  207. |> json_response_and_validate_schema(404)
  208. end
  209. test "respects blocks", %{user: user_one, conn: conn} do
  210. user_two = insert(:user)
  211. user_three = insert(:user)
  212. User.block(user_one, user_two)
  213. {:ok, activity} = CommonAPI.post(user_two, %{status: "User one sux0rz"})
  214. {:ok, repeat} = CommonAPI.repeat(activity.id, user_three)
  215. assert resp =
  216. conn
  217. |> get("/api/v1/accounts/#{user_two.id}/statuses")
  218. |> json_response_and_validate_schema(200)
  219. assert [%{"id" => id}] = resp
  220. assert id == activity.id
  221. # Even a blocked user will deliver the full user timeline, there would be
  222. # no point in looking at a blocked users timeline otherwise
  223. assert resp =
  224. conn
  225. |> get("/api/v1/accounts/#{user_two.id}/statuses")
  226. |> json_response_and_validate_schema(200)
  227. assert [%{"id" => id}] = resp
  228. assert id == activity.id
  229. # Third user's timeline includes the repeat when viewed by unauthenticated user
  230. resp =
  231. build_conn()
  232. |> get("/api/v1/accounts/#{user_three.id}/statuses")
  233. |> json_response_and_validate_schema(200)
  234. assert [%{"id" => id}] = resp
  235. assert id == repeat.id
  236. # When viewing a third user's timeline, the blocked users' statuses will NOT be shown
  237. resp = get(conn, "/api/v1/accounts/#{user_three.id}/statuses")
  238. assert [] == json_response_and_validate_schema(resp, 200)
  239. end
  240. test "gets users statuses", %{conn: conn} do
  241. user_one = insert(:user)
  242. user_two = insert(:user)
  243. user_three = insert(:user)
  244. {:ok, _user_three} = User.follow(user_three, user_one)
  245. {:ok, activity} = CommonAPI.post(user_one, %{status: "HI!!!"})
  246. {:ok, direct_activity} =
  247. CommonAPI.post(user_one, %{
  248. status: "Hi, @#{user_two.nickname}.",
  249. visibility: "direct"
  250. })
  251. {:ok, private_activity} =
  252. CommonAPI.post(user_one, %{status: "private", visibility: "private"})
  253. # TODO!!!
  254. resp =
  255. conn
  256. |> get("/api/v1/accounts/#{user_one.id}/statuses")
  257. |> json_response_and_validate_schema(200)
  258. assert [%{"id" => id}] = resp
  259. assert id == to_string(activity.id)
  260. resp =
  261. conn
  262. |> assign(:user, user_two)
  263. |> assign(:token, insert(:oauth_token, user: user_two, scopes: ["read:statuses"]))
  264. |> get("/api/v1/accounts/#{user_one.id}/statuses")
  265. |> json_response_and_validate_schema(200)
  266. assert [%{"id" => id_one}, %{"id" => id_two}] = resp
  267. assert id_one == to_string(direct_activity.id)
  268. assert id_two == to_string(activity.id)
  269. resp =
  270. conn
  271. |> assign(:user, user_three)
  272. |> assign(:token, insert(:oauth_token, user: user_three, scopes: ["read:statuses"]))
  273. |> get("/api/v1/accounts/#{user_one.id}/statuses")
  274. |> json_response_and_validate_schema(200)
  275. assert [%{"id" => id_one}, %{"id" => id_two}] = resp
  276. assert id_one == to_string(private_activity.id)
  277. assert id_two == to_string(activity.id)
  278. end
  279. test "unimplemented pinned statuses feature", %{conn: conn} do
  280. note = insert(:note_activity)
  281. user = User.get_cached_by_ap_id(note.data["actor"])
  282. conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?pinned=true")
  283. assert json_response_and_validate_schema(conn, 200) == []
  284. end
  285. test "gets an users media, excludes reblogs", %{conn: conn} do
  286. note = insert(:note_activity)
  287. user = User.get_cached_by_ap_id(note.data["actor"])
  288. other_user = insert(:user)
  289. file = %Plug.Upload{
  290. content_type: "image/jpg",
  291. path: Path.absname("test/fixtures/image.jpg"),
  292. filename: "an_image.jpg"
  293. }
  294. {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
  295. {:ok, %{id: image_post_id}} = CommonAPI.post(user, %{status: "cofe", media_ids: [media_id]})
  296. {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: other_user.ap_id)
  297. {:ok, %{id: other_image_post_id}} =
  298. CommonAPI.post(other_user, %{status: "cofe2", media_ids: [media_id]})
  299. {:ok, _announce} = CommonAPI.repeat(other_image_post_id, user)
  300. conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?only_media=true")
  301. assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
  302. conn = get(build_conn(), "/api/v1/accounts/#{user.id}/statuses?only_media=1")
  303. assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
  304. end
  305. test "gets a user's statuses without reblogs", %{user: user, conn: conn} do
  306. {:ok, %{id: post_id}} = CommonAPI.post(user, %{status: "HI!!!"})
  307. {:ok, _} = CommonAPI.repeat(post_id, user)
  308. conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=true")
  309. assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
  310. conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=1")
  311. assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
  312. end
  313. test "filters user's statuses by a hashtag", %{user: user, conn: conn} do
  314. {:ok, %{id: post_id}} = CommonAPI.post(user, %{status: "#hashtag"})
  315. {:ok, _post} = CommonAPI.post(user, %{status: "hashtag"})
  316. conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?tagged=hashtag")
  317. assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
  318. end
  319. test "the user views their own timelines and excludes direct messages", %{
  320. user: user,
  321. conn: conn
  322. } do
  323. {:ok, %{id: public_activity_id}} =
  324. CommonAPI.post(user, %{status: ".", visibility: "public"})
  325. {:ok, _direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
  326. conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct")
  327. assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200)
  328. end
  329. end
  330. defp local_and_remote_activities(%{local: local, remote: remote}) do
  331. insert(:note_activity, user: local)
  332. insert(:note_activity, user: remote, local: false)
  333. :ok
  334. end
  335. describe "statuses with restrict unauthenticated profiles for local and remote" do
  336. setup do: local_and_remote_users()
  337. setup :local_and_remote_activities
  338. setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
  339. setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
  340. test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
  341. assert %{"error" => "This API requires an authenticated user"} ==
  342. conn
  343. |> get("/api/v1/accounts/#{local.id}/statuses")
  344. |> json_response_and_validate_schema(:unauthorized)
  345. assert %{"error" => "This API requires an authenticated user"} ==
  346. conn
  347. |> get("/api/v1/accounts/#{remote.id}/statuses")
  348. |> json_response_and_validate_schema(:unauthorized)
  349. end
  350. test "if user is authenticated", %{local: local, remote: remote} do
  351. %{conn: conn} = oauth_access(["read"])
  352. res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
  353. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  354. res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
  355. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  356. end
  357. end
  358. describe "statuses with restrict unauthenticated profiles for local" do
  359. setup do: local_and_remote_users()
  360. setup :local_and_remote_activities
  361. setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
  362. test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
  363. assert %{"error" => "This API requires an authenticated user"} ==
  364. conn
  365. |> get("/api/v1/accounts/#{local.id}/statuses")
  366. |> json_response_and_validate_schema(:unauthorized)
  367. res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
  368. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  369. end
  370. test "if user is authenticated", %{local: local, remote: remote} do
  371. %{conn: conn} = oauth_access(["read"])
  372. res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
  373. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  374. res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
  375. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  376. end
  377. end
  378. describe "statuses with restrict unauthenticated profiles for remote" do
  379. setup do: local_and_remote_users()
  380. setup :local_and_remote_activities
  381. setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
  382. test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
  383. res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
  384. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  385. assert %{"error" => "This API requires an authenticated user"} ==
  386. conn
  387. |> get("/api/v1/accounts/#{remote.id}/statuses")
  388. |> json_response_and_validate_schema(:unauthorized)
  389. end
  390. test "if user is authenticated", %{local: local, remote: remote} do
  391. %{conn: conn} = oauth_access(["read"])
  392. res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
  393. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  394. res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
  395. assert length(json_response_and_validate_schema(res_conn, 200)) == 1
  396. end
  397. end
  398. describe "followers" do
  399. setup do: oauth_access(["read:accounts"])
  400. test "getting followers", %{user: user, conn: conn} do
  401. other_user = insert(:user)
  402. {:ok, %{id: user_id}} = User.follow(user, other_user)
  403. conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
  404. assert [%{"id" => ^user_id}] = json_response_and_validate_schema(conn, 200)
  405. end
  406. test "getting followers, hide_followers", %{user: user, conn: conn} do
  407. other_user = insert(:user, hide_followers: true)
  408. {:ok, _user} = User.follow(user, other_user)
  409. conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
  410. assert [] == json_response_and_validate_schema(conn, 200)
  411. end
  412. test "getting followers, hide_followers, same user requesting" do
  413. user = insert(:user)
  414. other_user = insert(:user, hide_followers: true)
  415. {:ok, _user} = User.follow(user, other_user)
  416. conn =
  417. build_conn()
  418. |> assign(:user, other_user)
  419. |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
  420. |> get("/api/v1/accounts/#{other_user.id}/followers")
  421. refute [] == json_response_and_validate_schema(conn, 200)
  422. end
  423. test "getting followers, pagination", %{user: user, conn: conn} do
  424. {:ok, %User{id: follower1_id}} = :user |> insert() |> User.follow(user)
  425. {:ok, %User{id: follower2_id}} = :user |> insert() |> User.follow(user)
  426. {:ok, %User{id: follower3_id}} = :user |> insert() |> User.follow(user)
  427. assert [%{"id" => ^follower3_id}, %{"id" => ^follower2_id}] =
  428. conn
  429. |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1_id}")
  430. |> json_response_and_validate_schema(200)
  431. assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
  432. conn
  433. |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")
  434. |> json_response_and_validate_schema(200)
  435. assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
  436. conn
  437. |> get(
  438. "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{
  439. follower3_id
  440. }"
  441. )
  442. |> json_response_and_validate_schema(200)
  443. res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")
  444. assert [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200)
  445. assert [link_header] = get_resp_header(res_conn, "link")
  446. assert link_header =~ ~r/min_id=#{follower2_id}/
  447. assert link_header =~ ~r/max_id=#{follower2_id}/
  448. end
  449. end
  450. describe "following" do
  451. setup do: oauth_access(["read:accounts"])
  452. test "getting following", %{user: user, conn: conn} do
  453. other_user = insert(:user)
  454. {:ok, user} = User.follow(user, other_user)
  455. conn = get(conn, "/api/v1/accounts/#{user.id}/following")
  456. assert [%{"id" => id}] = json_response_and_validate_schema(conn, 200)
  457. assert id == to_string(other_user.id)
  458. end
  459. test "getting following, hide_follows, other user requesting" do
  460. user = insert(:user, hide_follows: true)
  461. other_user = insert(:user)
  462. {:ok, user} = User.follow(user, other_user)
  463. conn =
  464. build_conn()
  465. |> assign(:user, other_user)
  466. |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
  467. |> get("/api/v1/accounts/#{user.id}/following")
  468. assert [] == json_response_and_validate_schema(conn, 200)
  469. end
  470. test "getting following, hide_follows, same user requesting" do
  471. user = insert(:user, hide_follows: true)
  472. other_user = insert(:user)
  473. {:ok, user} = User.follow(user, other_user)
  474. conn =
  475. build_conn()
  476. |> assign(:user, user)
  477. |> assign(:token, insert(:oauth_token, user: user, scopes: ["read:accounts"]))
  478. |> get("/api/v1/accounts/#{user.id}/following")
  479. refute [] == json_response_and_validate_schema(conn, 200)
  480. end
  481. test "getting following, pagination", %{user: user, conn: conn} do
  482. following1 = insert(:user)
  483. following2 = insert(:user)
  484. following3 = insert(:user)
  485. {:ok, _} = User.follow(user, following1)
  486. {:ok, _} = User.follow(user, following2)
  487. {:ok, _} = User.follow(user, following3)
  488. res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
  489. assert [%{"id" => id3}, %{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
  490. assert id3 == following3.id
  491. assert id2 == following2.id
  492. res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
  493. assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
  494. assert id2 == following2.id
  495. assert id1 == following1.id
  496. res_conn =
  497. get(
  498. conn,
  499. "/api/v1/accounts/#{user.id}/following?id=#{user.id}&limit=20&max_id=#{following3.id}"
  500. )
  501. assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
  502. assert id2 == following2.id
  503. assert id1 == following1.id
  504. res_conn =
  505. get(conn, "/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
  506. assert [%{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
  507. assert id2 == following2.id
  508. assert [link_header] = get_resp_header(res_conn, "link")
  509. assert link_header =~ ~r/min_id=#{following2.id}/
  510. assert link_header =~ ~r/max_id=#{following2.id}/
  511. end
  512. end
  513. describe "follow/unfollow" do
  514. setup do: oauth_access(["follow"])
  515. test "following / unfollowing a user", %{conn: conn} do
  516. %{id: other_user_id, nickname: other_user_nickname} = insert(:user)
  517. assert %{"id" => _id, "following" => true} =
  518. conn
  519. |> post("/api/v1/accounts/#{other_user_id}/follow")
  520. |> json_response_and_validate_schema(200)
  521. assert %{"id" => _id, "following" => false} =
  522. conn
  523. |> post("/api/v1/accounts/#{other_user_id}/unfollow")
  524. |> json_response_and_validate_schema(200)
  525. assert %{"id" => ^other_user_id} =
  526. conn
  527. |> put_req_header("content-type", "application/json")
  528. |> post("/api/v1/follows", %{"uri" => other_user_nickname})
  529. |> json_response_and_validate_schema(200)
  530. end
  531. test "cancelling follow request", %{conn: conn} do
  532. %{id: other_user_id} = insert(:user, %{locked: true})
  533. assert %{"id" => ^other_user_id, "following" => false, "requested" => true} =
  534. conn
  535. |> post("/api/v1/accounts/#{other_user_id}/follow")
  536. |> json_response_and_validate_schema(:ok)
  537. assert %{"id" => ^other_user_id, "following" => false, "requested" => false} =
  538. conn
  539. |> post("/api/v1/accounts/#{other_user_id}/unfollow")
  540. |> json_response_and_validate_schema(:ok)
  541. end
  542. test "following without reblogs" do
  543. %{conn: conn} = oauth_access(["follow", "read:statuses"])
  544. followed = insert(:user)
  545. other_user = insert(:user)
  546. ret_conn =
  547. conn
  548. |> put_req_header("content-type", "application/json")
  549. |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
  550. assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200)
  551. {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
  552. {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
  553. assert [] ==
  554. conn
  555. |> get("/api/v1/timelines/home")
  556. |> json_response(200)
  557. assert %{"showing_reblogs" => true} =
  558. conn
  559. |> put_req_header("content-type", "application/json")
  560. |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: true})
  561. |> json_response_and_validate_schema(200)
  562. assert [%{"id" => ^reblog_id}] =
  563. conn
  564. |> get("/api/v1/timelines/home")
  565. |> json_response(200)
  566. end
  567. test "following with reblogs" do
  568. %{conn: conn} = oauth_access(["follow", "read:statuses"])
  569. followed = insert(:user)
  570. other_user = insert(:user)
  571. ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow")
  572. assert %{"showing_reblogs" => true} = json_response_and_validate_schema(ret_conn, 200)
  573. {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
  574. {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
  575. assert [%{"id" => ^reblog_id}] =
  576. conn
  577. |> get("/api/v1/timelines/home")
  578. |> json_response(200)
  579. assert %{"showing_reblogs" => false} =
  580. conn
  581. |> put_req_header("content-type", "application/json")
  582. |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
  583. |> json_response_and_validate_schema(200)
  584. assert [] ==
  585. conn
  586. |> get("/api/v1/timelines/home")
  587. |> json_response(200)
  588. end
  589. test "following / unfollowing errors", %{user: user, conn: conn} do
  590. # self follow
  591. conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
  592. assert %{"error" => "Can not follow yourself"} =
  593. json_response_and_validate_schema(conn_res, 400)
  594. # self unfollow
  595. user = User.get_cached_by_id(user.id)
  596. conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
  597. assert %{"error" => "Can not unfollow yourself"} =
  598. json_response_and_validate_schema(conn_res, 400)
  599. # self follow via uri
  600. user = User.get_cached_by_id(user.id)
  601. assert %{"error" => "Can not follow yourself"} =
  602. conn
  603. |> put_req_header("content-type", "multipart/form-data")
  604. |> post("/api/v1/follows", %{"uri" => user.nickname})
  605. |> json_response_and_validate_schema(400)
  606. # follow non existing user
  607. conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
  608. assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
  609. # follow non existing user via uri
  610. conn_res =
  611. conn
  612. |> put_req_header("content-type", "multipart/form-data")
  613. |> post("/api/v1/follows", %{"uri" => "doesntexist"})
  614. assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
  615. # unfollow non existing user
  616. conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
  617. assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
  618. end
  619. end
  620. describe "mute/unmute" do
  621. setup do: oauth_access(["write:mutes"])
  622. test "with notifications", %{conn: conn} do
  623. other_user = insert(:user)
  624. assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
  625. conn
  626. |> post("/api/v1/accounts/#{other_user.id}/mute")
  627. |> json_response_and_validate_schema(200)
  628. conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
  629. assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
  630. json_response_and_validate_schema(conn, 200)
  631. end
  632. test "without notifications", %{conn: conn} do
  633. other_user = insert(:user)
  634. ret_conn =
  635. conn
  636. |> put_req_header("content-type", "multipart/form-data")
  637. |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
  638. assert %{"id" => _id, "muting" => true, "muting_notifications" => false} =
  639. json_response_and_validate_schema(ret_conn, 200)
  640. conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
  641. assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
  642. json_response_and_validate_schema(conn, 200)
  643. end
  644. end
  645. describe "pinned statuses" do
  646. setup do
  647. user = insert(:user)
  648. {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"})
  649. %{conn: conn} = oauth_access(["read:statuses"], user: user)
  650. [conn: conn, user: user, activity: activity]
  651. end
  652. test "returns pinned statuses", %{conn: conn, user: user, activity: %{id: activity_id}} do
  653. {:ok, _} = CommonAPI.pin(activity_id, user)
  654. assert [%{"id" => ^activity_id, "pinned" => true}] =
  655. conn
  656. |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
  657. |> json_response_and_validate_schema(200)
  658. end
  659. end
  660. test "blocking / unblocking a user" do
  661. %{conn: conn} = oauth_access(["follow"])
  662. other_user = insert(:user)
  663. ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/block")
  664. assert %{"id" => _id, "blocking" => true} = json_response_and_validate_schema(ret_conn, 200)
  665. conn = post(conn, "/api/v1/accounts/#{other_user.id}/unblock")
  666. assert %{"id" => _id, "blocking" => false} = json_response_and_validate_schema(conn, 200)
  667. end
  668. describe "create account by app" do
  669. setup do
  670. valid_params = %{
  671. username: "lain",
  672. email: "lain@example.org",
  673. password: "PlzDontHackLain",
  674. agreement: true
  675. }
  676. [valid_params: valid_params]
  677. end
  678. test "registers and logs in without :account_activation_required / :account_approval_required",
  679. %{conn: conn} do
  680. clear_config([:instance, :account_activation_required], false)
  681. clear_config([:instance, :account_approval_required], false)
  682. conn =
  683. conn
  684. |> put_req_header("content-type", "application/json")
  685. |> post("/api/v1/apps", %{
  686. client_name: "client_name",
  687. redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
  688. scopes: "read, write, follow"
  689. })
  690. assert %{
  691. "client_id" => client_id,
  692. "client_secret" => client_secret,
  693. "id" => _,
  694. "name" => "client_name",
  695. "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
  696. "vapid_key" => _,
  697. "website" => nil
  698. } = json_response_and_validate_schema(conn, 200)
  699. conn =
  700. post(conn, "/oauth/token", %{
  701. grant_type: "client_credentials",
  702. client_id: client_id,
  703. client_secret: client_secret
  704. })
  705. assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
  706. json_response(conn, 200)
  707. assert token
  708. token_from_db = Repo.get_by(Token, token: token)
  709. assert token_from_db
  710. assert refresh
  711. assert scope == "read write follow"
  712. clear_config([User, :email_blacklist], ["example.org"])
  713. params = %{
  714. username: "lain",
  715. email: "lain@example.org",
  716. password: "PlzDontHackLain",
  717. bio: "Test Bio",
  718. agreement: true
  719. }
  720. conn =
  721. build_conn()
  722. |> put_req_header("content-type", "multipart/form-data")
  723. |> put_req_header("authorization", "Bearer " <> token)
  724. |> post("/api/v1/accounts", params)
  725. assert %{"error" => "{\"email\":[\"Invalid email\"]}"} =
  726. json_response_and_validate_schema(conn, 400)
  727. Pleroma.Config.put([User, :email_blacklist], [])
  728. conn =
  729. build_conn()
  730. |> put_req_header("content-type", "multipart/form-data")
  731. |> put_req_header("authorization", "Bearer " <> token)
  732. |> post("/api/v1/accounts", params)
  733. %{
  734. "access_token" => token,
  735. "created_at" => _created_at,
  736. "scope" => ^scope,
  737. "token_type" => "Bearer"
  738. } = json_response_and_validate_schema(conn, 200)
  739. token_from_db = Repo.get_by(Token, token: token)
  740. assert token_from_db
  741. user = Repo.preload(token_from_db, :user).user
  742. assert user
  743. refute user.confirmation_pending
  744. refute user.approval_pending
  745. end
  746. test "registers but does not log in with :account_activation_required", %{conn: conn} do
  747. clear_config([:instance, :account_activation_required], true)
  748. clear_config([:instance, :account_approval_required], false)
  749. conn =
  750. conn
  751. |> put_req_header("content-type", "application/json")
  752. |> post("/api/v1/apps", %{
  753. client_name: "client_name",
  754. redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
  755. scopes: "read, write, follow"
  756. })
  757. assert %{
  758. "client_id" => client_id,
  759. "client_secret" => client_secret,
  760. "id" => _,
  761. "name" => "client_name",
  762. "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
  763. "vapid_key" => _,
  764. "website" => nil
  765. } = json_response_and_validate_schema(conn, 200)
  766. conn =
  767. post(conn, "/oauth/token", %{
  768. grant_type: "client_credentials",
  769. client_id: client_id,
  770. client_secret: client_secret
  771. })
  772. assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
  773. json_response(conn, 200)
  774. assert token
  775. token_from_db = Repo.get_by(Token, token: token)
  776. assert token_from_db
  777. assert refresh
  778. assert scope == "read write follow"
  779. conn =
  780. build_conn()
  781. |> put_req_header("content-type", "multipart/form-data")
  782. |> put_req_header("authorization", "Bearer " <> token)
  783. |> post("/api/v1/accounts", %{
  784. username: "lain",
  785. email: "lain@example.org",
  786. password: "PlzDontHackLain",
  787. bio: "Test Bio",
  788. agreement: true
  789. })
  790. response = json_response_and_validate_schema(conn, 200)
  791. assert %{"identifier" => "missing_confirmed_email"} = response
  792. refute response["access_token"]
  793. refute response["token_type"]
  794. user = Repo.get_by(User, email: "lain@example.org")
  795. assert user.confirmation_pending
  796. end
  797. test "registers but does not log in with :account_approval_required", %{conn: conn} do
  798. clear_config([:instance, :account_approval_required], true)
  799. clear_config([:instance, :account_activation_required], false)
  800. conn =
  801. conn
  802. |> put_req_header("content-type", "application/json")
  803. |> post("/api/v1/apps", %{
  804. client_name: "client_name",
  805. redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
  806. scopes: "read, write, follow"
  807. })
  808. assert %{
  809. "client_id" => client_id,
  810. "client_secret" => client_secret,
  811. "id" => _,
  812. "name" => "client_name",
  813. "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
  814. "vapid_key" => _,
  815. "website" => nil
  816. } = json_response_and_validate_schema(conn, 200)
  817. conn =
  818. post(conn, "/oauth/token", %{
  819. grant_type: "client_credentials",
  820. client_id: client_id,
  821. client_secret: client_secret
  822. })
  823. assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
  824. json_response(conn, 200)
  825. assert token
  826. token_from_db = Repo.get_by(Token, token: token)
  827. assert token_from_db
  828. assert refresh
  829. assert scope == "read write follow"
  830. conn =
  831. build_conn()
  832. |> put_req_header("content-type", "multipart/form-data")
  833. |> put_req_header("authorization", "Bearer " <> token)
  834. |> post("/api/v1/accounts", %{
  835. username: "lain",
  836. email: "lain@example.org",
  837. password: "PlzDontHackLain",
  838. bio: "Test Bio",
  839. agreement: true,
  840. reason: "I'm a cool dude, bro"
  841. })
  842. response = json_response_and_validate_schema(conn, 200)
  843. assert %{"identifier" => "awaiting_approval"} = response
  844. refute response["access_token"]
  845. refute response["token_type"]
  846. user = Repo.get_by(User, email: "lain@example.org")
  847. assert user.approval_pending
  848. assert user.registration_reason == "I'm a cool dude, bro"
  849. end
  850. test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
  851. _user = insert(:user, email: "lain@example.org")
  852. app_token = insert(:oauth_token, user: nil)
  853. res =
  854. conn
  855. |> put_req_header("authorization", "Bearer " <> app_token.token)
  856. |> put_req_header("content-type", "application/json")
  857. |> post("/api/v1/accounts", valid_params)
  858. assert json_response_and_validate_schema(res, 400) == %{
  859. "error" => "{\"email\":[\"has already been taken\"]}"
  860. }
  861. end
  862. test "returns bad_request if missing required params", %{
  863. conn: conn,
  864. valid_params: valid_params
  865. } do
  866. app_token = insert(:oauth_token, user: nil)
  867. conn =
  868. conn
  869. |> put_req_header("authorization", "Bearer " <> app_token.token)
  870. |> put_req_header("content-type", "application/json")
  871. res = post(conn, "/api/v1/accounts", valid_params)
  872. assert json_response_and_validate_schema(res, 200)
  873. [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
  874. |> Stream.zip(Map.delete(valid_params, :email))
  875. |> Enum.each(fn {ip, {attr, _}} ->
  876. res =
  877. conn
  878. |> Map.put(:remote_ip, ip)
  879. |> post("/api/v1/accounts", Map.delete(valid_params, attr))
  880. |> json_response_and_validate_schema(400)
  881. assert res == %{
  882. "error" => "Missing field: #{attr}.",
  883. "errors" => [
  884. %{
  885. "message" => "Missing field: #{attr}",
  886. "source" => %{"pointer" => "/#{attr}"},
  887. "title" => "Invalid value"
  888. }
  889. ]
  890. }
  891. end)
  892. end
  893. test "returns bad_request if missing email params when :account_activation_required is enabled",
  894. %{conn: conn, valid_params: valid_params} do
  895. clear_config([:instance, :account_activation_required], true)
  896. app_token = insert(:oauth_token, user: nil)
  897. conn =
  898. conn
  899. |> put_req_header("authorization", "Bearer " <> app_token.token)
  900. |> put_req_header("content-type", "application/json")
  901. res =
  902. conn
  903. |> Map.put(:remote_ip, {127, 0, 0, 5})
  904. |> post("/api/v1/accounts", Map.delete(valid_params, :email))
  905. assert json_response_and_validate_schema(res, 400) ==
  906. %{"error" => "Missing parameter: email"}
  907. res =
  908. conn
  909. |> Map.put(:remote_ip, {127, 0, 0, 6})
  910. |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
  911. assert json_response_and_validate_schema(res, 400) == %{
  912. "error" => "{\"email\":[\"can't be blank\"]}"
  913. }
  914. end
  915. test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
  916. app_token = insert(:oauth_token, user: nil)
  917. conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
  918. res =
  919. conn
  920. |> put_req_header("content-type", "application/json")
  921. |> Map.put(:remote_ip, {127, 0, 0, 7})
  922. |> post("/api/v1/accounts", Map.delete(valid_params, :email))
  923. assert json_response_and_validate_schema(res, 200)
  924. end
  925. test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
  926. app_token = insert(:oauth_token, user: nil)
  927. conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
  928. res =
  929. conn
  930. |> put_req_header("content-type", "application/json")
  931. |> Map.put(:remote_ip, {127, 0, 0, 8})
  932. |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
  933. assert json_response_and_validate_schema(res, 200)
  934. end
  935. test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
  936. res =
  937. conn
  938. |> put_req_header("authorization", "Bearer " <> "invalid-token")
  939. |> put_req_header("content-type", "multipart/form-data")
  940. |> post("/api/v1/accounts", valid_params)
  941. assert json_response_and_validate_schema(res, 403) == %{"error" => "Invalid credentials"}
  942. end
  943. test "registration from trusted app" do
  944. clear_config([Pleroma.Captcha, :enabled], true)
  945. app = insert(:oauth_app, trusted: true, scopes: ["read", "write", "follow", "push"])
  946. conn =
  947. build_conn()
  948. |> post("/oauth/token", %{
  949. "grant_type" => "client_credentials",
  950. "client_id" => app.client_id,
  951. "client_secret" => app.client_secret
  952. })
  953. assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200)
  954. response =
  955. build_conn()
  956. |> Plug.Conn.put_req_header("authorization", "Bearer " <> token)
  957. |> put_req_header("content-type", "multipart/form-data")
  958. |> post("/api/v1/accounts", %{
  959. nickname: "nickanme",
  960. agreement: true,
  961. email: "email@example.com",
  962. fullname: "Lain",
  963. username: "Lain",
  964. password: "some_password",
  965. confirm: "some_password"
  966. })
  967. |> json_response_and_validate_schema(200)
  968. assert %{
  969. "access_token" => access_token,
  970. "created_at" => _,
  971. "scope" => "read write follow push",
  972. "token_type" => "Bearer"
  973. } = response
  974. response =
  975. build_conn()
  976. |> Plug.Conn.put_req_header("authorization", "Bearer " <> access_token)
  977. |> get("/api/v1/accounts/verify_credentials")
  978. |> json_response_and_validate_schema(200)
  979. assert %{
  980. "acct" => "Lain",
  981. "bot" => false,
  982. "display_name" => "Lain",
  983. "follow_requests_count" => 0,
  984. "followers_count" => 0,
  985. "following_count" => 0,
  986. "locked" => false,
  987. "note" => "",
  988. "source" => %{
  989. "fields" => [],
  990. "note" => "",
  991. "pleroma" => %{
  992. "actor_type" => "Person",
  993. "discoverable" => false,
  994. "no_rich_text" => false,
  995. "show_role" => true
  996. },
  997. "privacy" => "public",
  998. "sensitive" => false
  999. },
  1000. "statuses_count" => 0,
  1001. "username" => "Lain"
  1002. } = response
  1003. end
  1004. end
  1005. describe "create account by app / rate limit" do
  1006. setup do: clear_config([:rate_limit, :app_account_creation], {10_000, 2})
  1007. test "respects rate limit setting", %{conn: conn} do
  1008. app_token = insert(:oauth_token, user: nil)
  1009. conn =
  1010. conn
  1011. |> put_req_header("authorization", "Bearer " <> app_token.token)
  1012. |> Map.put(:remote_ip, {15, 15, 15, 15})
  1013. |> put_req_header("content-type", "multipart/form-data")
  1014. for i <- 1..2 do
  1015. conn =
  1016. conn
  1017. |> post("/api/v1/accounts", %{
  1018. username: "#{i}lain",
  1019. email: "#{i}lain@example.org",
  1020. password: "PlzDontHackLain",
  1021. agreement: true
  1022. })
  1023. %{
  1024. "access_token" => token,
  1025. "created_at" => _created_at,
  1026. "scope" => _scope,
  1027. "token_type" => "Bearer"
  1028. } = json_response_and_validate_schema(conn, 200)
  1029. token_from_db = Repo.get_by(Token, token: token)
  1030. assert token_from_db
  1031. token_from_db = Repo.preload(token_from_db, :user)
  1032. assert token_from_db.user
  1033. end
  1034. conn =
  1035. post(conn, "/api/v1/accounts", %{
  1036. username: "6lain",
  1037. email: "6lain@example.org",
  1038. password: "PlzDontHackLain",
  1039. agreement: true
  1040. })
  1041. assert json_response_and_validate_schema(conn, :too_many_requests) == %{
  1042. "error" => "Throttled"
  1043. }
  1044. end
  1045. end
  1046. describe "create account with enabled captcha" do
  1047. setup %{conn: conn} do
  1048. app_token = insert(:oauth_token, user: nil)
  1049. conn =
  1050. conn
  1051. |> put_req_header("authorization", "Bearer " <> app_token.token)
  1052. |> put_req_header("content-type", "multipart/form-data")
  1053. [conn: conn]
  1054. end
  1055. setup do: clear_config([Pleroma.Captcha, :enabled], true)
  1056. test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
  1057. %{token: token, answer_data: answer_data} = Pleroma.Captcha.new()
  1058. params = %{
  1059. username: "lain",
  1060. email: "lain@example.org",
  1061. password: "PlzDontHackLain",
  1062. agreement: true,
  1063. captcha_solution: Pleroma.Captcha.Mock.solution(),
  1064. captcha_token: token,
  1065. captcha_answer_data: answer_data
  1066. }
  1067. assert %{
  1068. "access_token" => access_token,
  1069. "created_at" => _,
  1070. "scope" => "read",
  1071. "token_type" => "Bearer"
  1072. } =
  1073. conn
  1074. |> post("/api/v1/accounts", params)
  1075. |> json_response_and_validate_schema(:ok)
  1076. assert Token |> Repo.get_by(token: access_token) |> Repo.preload(:user) |> Map.get(:user)
  1077. Cachex.del(:used_captcha_cache, token)
  1078. end
  1079. test "returns 400 if any captcha field is not provided", %{conn: conn} do
  1080. captcha_fields = [:captcha_solution, :captcha_token, :captcha_answer_data]
  1081. valid_params = %{
  1082. username: "lain",
  1083. email: "lain@example.org",
  1084. password: "PlzDontHackLain",
  1085. agreement: true,
  1086. captcha_solution: "xx",
  1087. captcha_token: "xx",
  1088. captcha_answer_data: "xx"
  1089. }
  1090. for field <- captcha_fields do
  1091. expected = %{
  1092. "error" => "{\"captcha\":[\"Invalid CAPTCHA (Missing parameter: #{field})\"]}"
  1093. }
  1094. assert expected ==
  1095. conn
  1096. |> post("/api/v1/accounts", Map.delete(valid_params, field))
  1097. |> json_response_and_validate_schema(:bad_request)
  1098. end
  1099. end
  1100. test "returns an error if captcha is invalid", %{conn: conn} do
  1101. params = %{
  1102. username: "lain",
  1103. email: "lain@example.org",
  1104. password: "PlzDontHackLain",
  1105. agreement: true,
  1106. captcha_solution: "cofe",
  1107. captcha_token: "cofe",
  1108. captcha_answer_data: "cofe"
  1109. }
  1110. assert %{"error" => "{\"captcha\":[\"Invalid answer data\"]}"} ==
  1111. conn
  1112. |> post("/api/v1/accounts", params)
  1113. |> json_response_and_validate_schema(:bad_request)
  1114. end
  1115. end
  1116. describe "GET /api/v1/accounts/:id/lists - account_lists" do
  1117. test "returns lists to which the account belongs" do
  1118. %{user: user, conn: conn} = oauth_access(["read:lists"])
  1119. other_user = insert(:user)
  1120. assert {:ok, %Pleroma.List{id: list_id} = list} = Pleroma.List.create("Test List", user)
  1121. {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
  1122. assert [%{"id" => list_id, "title" => "Test List"}] =
  1123. conn
  1124. |> get("/api/v1/accounts/#{other_user.id}/lists")
  1125. |> json_response_and_validate_schema(200)
  1126. end
  1127. end
  1128. describe "verify_credentials" do
  1129. test "verify_credentials" do
  1130. %{user: user, conn: conn} = oauth_access(["read:accounts"])
  1131. [notification | _] =
  1132. insert_list(7, :notification, user: user, activity: insert(:note_activity))
  1133. Pleroma.Notification.set_read_up_to(user, notification.id)
  1134. conn = get(conn, "/api/v1/accounts/verify_credentials")
  1135. response = json_response_and_validate_schema(conn, 200)
  1136. assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
  1137. assert response["pleroma"]["chat_token"]
  1138. assert response["pleroma"]["unread_notifications_count"] == 6
  1139. assert id == to_string(user.id)
  1140. end
  1141. test "verify_credentials default scope unlisted" do
  1142. user = insert(:user, default_scope: "unlisted")
  1143. %{conn: conn} = oauth_access(["read:accounts"], user: user)
  1144. conn = get(conn, "/api/v1/accounts/verify_credentials")
  1145. assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} =
  1146. json_response_and_validate_schema(conn, 200)
  1147. assert id == to_string(user.id)
  1148. end
  1149. test "locked accounts" do
  1150. user = insert(:user, default_scope: "private")
  1151. %{conn: conn} = oauth_access(["read:accounts"], user: user)
  1152. conn = get(conn, "/api/v1/accounts/verify_credentials")
  1153. assert %{"id" => id, "source" => %{"privacy" => "private"}} =
  1154. json_response_and_validate_schema(conn, 200)
  1155. assert id == to_string(user.id)
  1156. end
  1157. end
  1158. describe "user relationships" do
  1159. setup do: oauth_access(["read:follows"])
  1160. test "returns the relationships for the current user", %{user: user, conn: conn} do
  1161. %{id: other_user_id} = other_user = insert(:user)
  1162. {:ok, _user} = User.follow(user, other_user)
  1163. assert [%{"id" => ^other_user_id}] =
  1164. conn
  1165. |> get("/api/v1/accounts/relationships?id=#{other_user.id}")
  1166. |> json_response_and_validate_schema(200)
  1167. assert [%{"id" => ^other_user_id}] =
  1168. conn
  1169. |> get("/api/v1/accounts/relationships?id[]=#{other_user.id}")
  1170. |> json_response_and_validate_schema(200)
  1171. end
  1172. test "returns an empty list on a bad request", %{conn: conn} do
  1173. conn = get(conn, "/api/v1/accounts/relationships", %{})
  1174. assert [] = json_response_and_validate_schema(conn, 200)
  1175. end
  1176. end
  1177. test "getting a list of mutes" do
  1178. %{user: user, conn: conn} = oauth_access(["read:mutes"])
  1179. other_user = insert(:user)
  1180. {:ok, _user_relationships} = User.mute(user, other_user)
  1181. conn = get(conn, "/api/v1/mutes")
  1182. other_user_id = to_string(other_user.id)
  1183. assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
  1184. end
  1185. test "getting a list of blocks" do
  1186. %{user: user, conn: conn} = oauth_access(["read:blocks"])
  1187. other_user = insert(:user)
  1188. {:ok, _user_relationship} = User.block(user, other_user)
  1189. conn =
  1190. conn
  1191. |> assign(:user, user)
  1192. |> get("/api/v1/blocks")
  1193. other_user_id = to_string(other_user.id)
  1194. assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
  1195. end
  1196. end