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