Merge remote-tracking branch 'upstream/develop' into restrict-origin
[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 clear_config([User, :email_blacklist], ["example.org"])
944
945 params = %{
946 username: "lain",
947 email: "lain@example.org",
948 password: "PlzDontHackLain",
949 bio: "Test Bio",
950 agreement: true
951 }
952
953 conn =
954 build_conn()
955 |> put_req_header("content-type", "multipart/form-data")
956 |> put_req_header("authorization", "Bearer " <> token)
957 |> post("/api/v1/accounts", params)
958
959 assert %{"error" => "{\"email\":[\"Invalid email\"]}"} =
960 json_response_and_validate_schema(conn, 400)
961
962 Pleroma.Config.put([User, :email_blacklist], [])
963
964 conn =
965 build_conn()
966 |> put_req_header("content-type", "multipart/form-data")
967 |> put_req_header("authorization", "Bearer " <> token)
968 |> post("/api/v1/accounts", params)
969
970 %{
971 "access_token" => token,
972 "created_at" => _created_at,
973 "scope" => ^scope,
974 "token_type" => "Bearer"
975 } = json_response_and_validate_schema(conn, 200)
976
977 token_from_db = Repo.get_by(Token, token: token)
978 assert token_from_db
979 user = Repo.preload(token_from_db, :user).user
980
981 assert user
982 refute user.confirmation_pending
983 refute user.approval_pending
984 end
985
986 test "registers but does not log in with :account_activation_required", %{conn: conn} do
987 clear_config([:instance, :account_activation_required], true)
988 clear_config([:instance, :account_approval_required], false)
989
990 conn =
991 conn
992 |> put_req_header("content-type", "application/json")
993 |> post("/api/v1/apps", %{
994 client_name: "client_name",
995 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
996 scopes: "read, write, follow"
997 })
998
999 assert %{
1000 "client_id" => client_id,
1001 "client_secret" => client_secret,
1002 "id" => _,
1003 "name" => "client_name",
1004 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
1005 "vapid_key" => _,
1006 "website" => nil
1007 } = json_response_and_validate_schema(conn, 200)
1008
1009 conn =
1010 post(conn, "/oauth/token", %{
1011 grant_type: "client_credentials",
1012 client_id: client_id,
1013 client_secret: client_secret
1014 })
1015
1016 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
1017 json_response(conn, 200)
1018
1019 assert token
1020 token_from_db = Repo.get_by(Token, token: token)
1021 assert token_from_db
1022 assert refresh
1023 assert scope == "read write follow"
1024
1025 conn =
1026 build_conn()
1027 |> put_req_header("content-type", "multipart/form-data")
1028 |> put_req_header("authorization", "Bearer " <> token)
1029 |> post("/api/v1/accounts", %{
1030 username: "lain",
1031 email: "lain@example.org",
1032 password: "PlzDontHackLain",
1033 bio: "Test Bio",
1034 agreement: true
1035 })
1036
1037 response = json_response_and_validate_schema(conn, 200)
1038 assert %{"identifier" => "missing_confirmed_email"} = response
1039 refute response["access_token"]
1040 refute response["token_type"]
1041
1042 user = Repo.get_by(User, email: "lain@example.org")
1043 assert user.confirmation_pending
1044 end
1045
1046 test "registers but does not log in with :account_approval_required", %{conn: conn} do
1047 clear_config([:instance, :account_approval_required], true)
1048 clear_config([:instance, :account_activation_required], false)
1049
1050 conn =
1051 conn
1052 |> put_req_header("content-type", "application/json")
1053 |> post("/api/v1/apps", %{
1054 client_name: "client_name",
1055 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
1056 scopes: "read, write, follow"
1057 })
1058
1059 assert %{
1060 "client_id" => client_id,
1061 "client_secret" => client_secret,
1062 "id" => _,
1063 "name" => "client_name",
1064 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
1065 "vapid_key" => _,
1066 "website" => nil
1067 } = json_response_and_validate_schema(conn, 200)
1068
1069 conn =
1070 post(conn, "/oauth/token", %{
1071 grant_type: "client_credentials",
1072 client_id: client_id,
1073 client_secret: client_secret
1074 })
1075
1076 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
1077 json_response(conn, 200)
1078
1079 assert token
1080 token_from_db = Repo.get_by(Token, token: token)
1081 assert token_from_db
1082 assert refresh
1083 assert scope == "read write follow"
1084
1085 conn =
1086 build_conn()
1087 |> put_req_header("content-type", "multipart/form-data")
1088 |> put_req_header("authorization", "Bearer " <> token)
1089 |> post("/api/v1/accounts", %{
1090 username: "lain",
1091 email: "lain@example.org",
1092 password: "PlzDontHackLain",
1093 bio: "Test Bio",
1094 agreement: true,
1095 reason: "I'm a cool dude, bro"
1096 })
1097
1098 response = json_response_and_validate_schema(conn, 200)
1099 assert %{"identifier" => "awaiting_approval"} = response
1100 refute response["access_token"]
1101 refute response["token_type"]
1102
1103 user = Repo.get_by(User, email: "lain@example.org")
1104
1105 assert user.approval_pending
1106 assert user.registration_reason == "I'm a cool dude, bro"
1107 end
1108
1109 test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
1110 _user = insert(:user, email: "lain@example.org")
1111 app_token = insert(:oauth_token, user: nil)
1112
1113 res =
1114 conn
1115 |> put_req_header("authorization", "Bearer " <> app_token.token)
1116 |> put_req_header("content-type", "application/json")
1117 |> post("/api/v1/accounts", valid_params)
1118
1119 assert json_response_and_validate_schema(res, 400) == %{
1120 "error" => "{\"email\":[\"has already been taken\"]}"
1121 }
1122 end
1123
1124 test "returns bad_request if missing required params", %{
1125 conn: conn,
1126 valid_params: valid_params
1127 } do
1128 app_token = insert(:oauth_token, user: nil)
1129
1130 conn =
1131 conn
1132 |> put_req_header("authorization", "Bearer " <> app_token.token)
1133 |> put_req_header("content-type", "application/json")
1134
1135 res = post(conn, "/api/v1/accounts", valid_params)
1136 assert json_response_and_validate_schema(res, 200)
1137
1138 [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
1139 |> Stream.zip(Map.delete(valid_params, :email))
1140 |> Enum.each(fn {ip, {attr, _}} ->
1141 res =
1142 conn
1143 |> Map.put(:remote_ip, ip)
1144 |> post("/api/v1/accounts", Map.delete(valid_params, attr))
1145 |> json_response_and_validate_schema(400)
1146
1147 assert res == %{
1148 "error" => "Missing field: #{attr}.",
1149 "errors" => [
1150 %{
1151 "message" => "Missing field: #{attr}",
1152 "source" => %{"pointer" => "/#{attr}"},
1153 "title" => "Invalid value"
1154 }
1155 ]
1156 }
1157 end)
1158 end
1159
1160 test "returns bad_request if missing email params when :account_activation_required is enabled",
1161 %{conn: conn, valid_params: valid_params} do
1162 clear_config([:instance, :account_activation_required], true)
1163
1164 app_token = insert(:oauth_token, user: nil)
1165
1166 conn =
1167 conn
1168 |> put_req_header("authorization", "Bearer " <> app_token.token)
1169 |> put_req_header("content-type", "application/json")
1170
1171 res =
1172 conn
1173 |> Map.put(:remote_ip, {127, 0, 0, 5})
1174 |> post("/api/v1/accounts", Map.delete(valid_params, :email))
1175
1176 assert json_response_and_validate_schema(res, 400) ==
1177 %{"error" => "Missing parameter: email"}
1178
1179 res =
1180 conn
1181 |> Map.put(:remote_ip, {127, 0, 0, 6})
1182 |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
1183
1184 assert json_response_and_validate_schema(res, 400) == %{
1185 "error" => "{\"email\":[\"can't be blank\"]}"
1186 }
1187 end
1188
1189 test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
1190 app_token = insert(:oauth_token, user: nil)
1191 conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
1192
1193 res =
1194 conn
1195 |> put_req_header("content-type", "application/json")
1196 |> Map.put(:remote_ip, {127, 0, 0, 7})
1197 |> post("/api/v1/accounts", Map.delete(valid_params, :email))
1198
1199 assert json_response_and_validate_schema(res, 200)
1200 end
1201
1202 test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
1203 app_token = insert(:oauth_token, user: nil)
1204 conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
1205
1206 res =
1207 conn
1208 |> put_req_header("content-type", "application/json")
1209 |> Map.put(:remote_ip, {127, 0, 0, 8})
1210 |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
1211
1212 assert json_response_and_validate_schema(res, 200)
1213 end
1214
1215 test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
1216 res =
1217 conn
1218 |> put_req_header("authorization", "Bearer " <> "invalid-token")
1219 |> put_req_header("content-type", "multipart/form-data")
1220 |> post("/api/v1/accounts", valid_params)
1221
1222 assert json_response_and_validate_schema(res, 403) == %{"error" => "Invalid credentials"}
1223 end
1224
1225 test "registration from trusted app" do
1226 clear_config([Pleroma.Captcha, :enabled], true)
1227 app = insert(:oauth_app, trusted: true, scopes: ["read", "write", "follow", "push"])
1228
1229 conn =
1230 build_conn()
1231 |> post("/oauth/token", %{
1232 "grant_type" => "client_credentials",
1233 "client_id" => app.client_id,
1234 "client_secret" => app.client_secret
1235 })
1236
1237 assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200)
1238
1239 response =
1240 build_conn()
1241 |> Plug.Conn.put_req_header("authorization", "Bearer " <> token)
1242 |> put_req_header("content-type", "multipart/form-data")
1243 |> post("/api/v1/accounts", %{
1244 nickname: "nickanme",
1245 agreement: true,
1246 email: "email@example.com",
1247 fullname: "Lain",
1248 username: "Lain",
1249 password: "some_password",
1250 confirm: "some_password"
1251 })
1252 |> json_response_and_validate_schema(200)
1253
1254 assert %{
1255 "access_token" => access_token,
1256 "created_at" => _,
1257 "scope" => "read write follow push",
1258 "token_type" => "Bearer"
1259 } = response
1260
1261 response =
1262 build_conn()
1263 |> Plug.Conn.put_req_header("authorization", "Bearer " <> access_token)
1264 |> get("/api/v1/accounts/verify_credentials")
1265 |> json_response_and_validate_schema(200)
1266
1267 assert %{
1268 "acct" => "Lain",
1269 "bot" => false,
1270 "display_name" => "Lain",
1271 "follow_requests_count" => 0,
1272 "followers_count" => 0,
1273 "following_count" => 0,
1274 "locked" => false,
1275 "note" => "",
1276 "source" => %{
1277 "fields" => [],
1278 "note" => "",
1279 "pleroma" => %{
1280 "actor_type" => "Person",
1281 "discoverable" => false,
1282 "no_rich_text" => false,
1283 "show_role" => true
1284 },
1285 "privacy" => "public",
1286 "sensitive" => false
1287 },
1288 "statuses_count" => 0,
1289 "username" => "Lain"
1290 } = response
1291 end
1292 end
1293
1294 describe "create account by app / rate limit" do
1295 setup do: clear_config([:rate_limit, :app_account_creation], {10_000, 2})
1296
1297 test "respects rate limit setting", %{conn: conn} do
1298 app_token = insert(:oauth_token, user: nil)
1299
1300 conn =
1301 conn
1302 |> put_req_header("authorization", "Bearer " <> app_token.token)
1303 |> Map.put(:remote_ip, {15, 15, 15, 15})
1304 |> put_req_header("content-type", "multipart/form-data")
1305
1306 for i <- 1..2 do
1307 conn =
1308 conn
1309 |> post("/api/v1/accounts", %{
1310 username: "#{i}lain",
1311 email: "#{i}lain@example.org",
1312 password: "PlzDontHackLain",
1313 agreement: true
1314 })
1315
1316 %{
1317 "access_token" => token,
1318 "created_at" => _created_at,
1319 "scope" => _scope,
1320 "token_type" => "Bearer"
1321 } = json_response_and_validate_schema(conn, 200)
1322
1323 token_from_db = Repo.get_by(Token, token: token)
1324 assert token_from_db
1325 token_from_db = Repo.preload(token_from_db, :user)
1326 assert token_from_db.user
1327 end
1328
1329 conn =
1330 post(conn, "/api/v1/accounts", %{
1331 username: "6lain",
1332 email: "6lain@example.org",
1333 password: "PlzDontHackLain",
1334 agreement: true
1335 })
1336
1337 assert json_response_and_validate_schema(conn, :too_many_requests) == %{
1338 "error" => "Throttled"
1339 }
1340 end
1341 end
1342
1343 describe "create account with enabled captcha" do
1344 setup %{conn: conn} do
1345 app_token = insert(:oauth_token, user: nil)
1346
1347 conn =
1348 conn
1349 |> put_req_header("authorization", "Bearer " <> app_token.token)
1350 |> put_req_header("content-type", "multipart/form-data")
1351
1352 [conn: conn]
1353 end
1354
1355 setup do: clear_config([Pleroma.Captcha, :enabled], true)
1356
1357 test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
1358 %{token: token, answer_data: answer_data} = Pleroma.Captcha.new()
1359
1360 params = %{
1361 username: "lain",
1362 email: "lain@example.org",
1363 password: "PlzDontHackLain",
1364 agreement: true,
1365 captcha_solution: Pleroma.Captcha.Mock.solution(),
1366 captcha_token: token,
1367 captcha_answer_data: answer_data
1368 }
1369
1370 assert %{
1371 "access_token" => access_token,
1372 "created_at" => _,
1373 "scope" => "read",
1374 "token_type" => "Bearer"
1375 } =
1376 conn
1377 |> post("/api/v1/accounts", params)
1378 |> json_response_and_validate_schema(:ok)
1379
1380 assert Token |> Repo.get_by(token: access_token) |> Repo.preload(:user) |> Map.get(:user)
1381
1382 Cachex.del(:used_captcha_cache, token)
1383 end
1384
1385 test "returns 400 if any captcha field is not provided", %{conn: conn} do
1386 captcha_fields = [:captcha_solution, :captcha_token, :captcha_answer_data]
1387
1388 valid_params = %{
1389 username: "lain",
1390 email: "lain@example.org",
1391 password: "PlzDontHackLain",
1392 agreement: true,
1393 captcha_solution: "xx",
1394 captcha_token: "xx",
1395 captcha_answer_data: "xx"
1396 }
1397
1398 for field <- captcha_fields do
1399 expected = %{
1400 "error" => "{\"captcha\":[\"Invalid CAPTCHA (Missing parameter: #{field})\"]}"
1401 }
1402
1403 assert expected ==
1404 conn
1405 |> post("/api/v1/accounts", Map.delete(valid_params, field))
1406 |> json_response_and_validate_schema(:bad_request)
1407 end
1408 end
1409
1410 test "returns an error if captcha is invalid", %{conn: conn} do
1411 params = %{
1412 username: "lain",
1413 email: "lain@example.org",
1414 password: "PlzDontHackLain",
1415 agreement: true,
1416 captcha_solution: "cofe",
1417 captcha_token: "cofe",
1418 captcha_answer_data: "cofe"
1419 }
1420
1421 assert %{"error" => "{\"captcha\":[\"Invalid answer data\"]}"} ==
1422 conn
1423 |> post("/api/v1/accounts", params)
1424 |> json_response_and_validate_schema(:bad_request)
1425 end
1426 end
1427
1428 describe "GET /api/v1/accounts/:id/lists - account_lists" do
1429 test "returns lists to which the account belongs" do
1430 %{user: user, conn: conn} = oauth_access(["read:lists"])
1431 other_user = insert(:user)
1432 assert {:ok, %Pleroma.List{id: list_id} = list} = Pleroma.List.create("Test List", user)
1433 {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
1434
1435 assert [%{"id" => list_id, "title" => "Test List"}] =
1436 conn
1437 |> get("/api/v1/accounts/#{other_user.id}/lists")
1438 |> json_response_and_validate_schema(200)
1439 end
1440 end
1441
1442 describe "verify_credentials" do
1443 test "verify_credentials" do
1444 %{user: user, conn: conn} = oauth_access(["read:accounts"])
1445
1446 [notification | _] =
1447 insert_list(7, :notification, user: user, activity: insert(:note_activity))
1448
1449 Pleroma.Notification.set_read_up_to(user, notification.id)
1450 conn = get(conn, "/api/v1/accounts/verify_credentials")
1451
1452 response = json_response_and_validate_schema(conn, 200)
1453
1454 assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
1455 assert response["pleroma"]["chat_token"]
1456 assert response["pleroma"]["unread_notifications_count"] == 6
1457 assert id == to_string(user.id)
1458 end
1459
1460 test "verify_credentials default scope unlisted" do
1461 user = insert(:user, default_scope: "unlisted")
1462 %{conn: conn} = oauth_access(["read:accounts"], user: user)
1463
1464 conn = get(conn, "/api/v1/accounts/verify_credentials")
1465
1466 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} =
1467 json_response_and_validate_schema(conn, 200)
1468
1469 assert id == to_string(user.id)
1470 end
1471
1472 test "locked accounts" do
1473 user = insert(:user, default_scope: "private")
1474 %{conn: conn} = oauth_access(["read:accounts"], user: user)
1475
1476 conn = get(conn, "/api/v1/accounts/verify_credentials")
1477
1478 assert %{"id" => id, "source" => %{"privacy" => "private"}} =
1479 json_response_and_validate_schema(conn, 200)
1480
1481 assert id == to_string(user.id)
1482 end
1483 end
1484
1485 describe "user relationships" do
1486 setup do: oauth_access(["read:follows"])
1487
1488 test "returns the relationships for the current user", %{user: user, conn: conn} do
1489 %{id: other_user_id} = other_user = insert(:user)
1490 {:ok, _user} = User.follow(user, other_user)
1491
1492 assert [%{"id" => ^other_user_id}] =
1493 conn
1494 |> get("/api/v1/accounts/relationships?id=#{other_user.id}")
1495 |> json_response_and_validate_schema(200)
1496
1497 assert [%{"id" => ^other_user_id}] =
1498 conn
1499 |> get("/api/v1/accounts/relationships?id[]=#{other_user.id}")
1500 |> json_response_and_validate_schema(200)
1501 end
1502
1503 test "returns an empty list on a bad request", %{conn: conn} do
1504 conn = get(conn, "/api/v1/accounts/relationships", %{})
1505
1506 assert [] = json_response_and_validate_schema(conn, 200)
1507 end
1508 end
1509
1510 test "getting a list of mutes" do
1511 %{user: user, conn: conn} = oauth_access(["read:mutes"])
1512 other_user = insert(:user)
1513
1514 {:ok, _user_relationships} = User.mute(user, other_user)
1515
1516 conn = get(conn, "/api/v1/mutes")
1517
1518 other_user_id = to_string(other_user.id)
1519 assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
1520 end
1521
1522 test "getting a list of blocks" do
1523 %{user: user, conn: conn} = oauth_access(["read:blocks"])
1524 other_user = insert(:user)
1525
1526 {:ok, _user_relationship} = User.block(user, other_user)
1527
1528 conn =
1529 conn
1530 |> assign(:user, user)
1531 |> get("/api/v1/blocks")
1532
1533 other_user_id = to_string(other_user.id)
1534 assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
1535 end
1536 end