f6285853a16d7a5db189fdcd48eac676f53cbc38
[akkoma] / test / pleroma / 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_one} = 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/jpeg",
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
440 test "muted reactions", %{user: user, conn: conn} do
441 user2 = insert(:user)
442 User.mute(user, user2)
443 {:ok, activity} = CommonAPI.post(user, %{status: "."})
444 {:ok, _} = CommonAPI.react_with_emoji(activity.id, user2, "🎅")
445
446 result =
447 conn
448 |> get("/api/v1/accounts/#{user.id}/statuses")
449 |> json_response_and_validate_schema(200)
450
451 assert [
452 %{
453 "pleroma" => %{
454 "emoji_reactions" => []
455 }
456 }
457 ] = result
458
459 result =
460 conn
461 |> get("/api/v1/accounts/#{user.id}/statuses?with_muted=true")
462 |> json_response_and_validate_schema(200)
463
464 assert [
465 %{
466 "pleroma" => %{
467 "emoji_reactions" => [%{"count" => 1, "me" => false, "name" => "🎅"}]
468 }
469 }
470 ] = result
471 end
472 end
473
474 defp local_and_remote_activities(%{local: local, remote: remote}) do
475 insert(:note_activity, user: local)
476 insert(:note_activity, user: remote, local: false)
477
478 :ok
479 end
480
481 describe "statuses with restrict unauthenticated profiles for local and remote" do
482 setup do: local_and_remote_users()
483 setup :local_and_remote_activities
484
485 setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
486
487 setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
488
489 test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
490 assert %{"error" => "This API requires an authenticated user"} ==
491 conn
492 |> get("/api/v1/accounts/#{local.id}/statuses")
493 |> json_response_and_validate_schema(:unauthorized)
494
495 assert %{"error" => "This API requires an authenticated user"} ==
496 conn
497 |> get("/api/v1/accounts/#{remote.id}/statuses")
498 |> json_response_and_validate_schema(:unauthorized)
499 end
500
501 test "if user is authenticated", %{local: local, remote: remote} do
502 %{conn: conn} = oauth_access(["read"])
503
504 res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
505 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
506
507 res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
508 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
509 end
510 end
511
512 describe "statuses with restrict unauthenticated profiles for local" do
513 setup do: local_and_remote_users()
514 setup :local_and_remote_activities
515
516 setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
517
518 test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
519 assert %{"error" => "This API requires an authenticated user"} ==
520 conn
521 |> get("/api/v1/accounts/#{local.id}/statuses")
522 |> json_response_and_validate_schema(:unauthorized)
523
524 res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
525 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
526 end
527
528 test "if user is authenticated", %{local: local, remote: remote} do
529 %{conn: conn} = oauth_access(["read"])
530
531 res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
532 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
533
534 res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
535 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
536 end
537 end
538
539 describe "statuses with restrict unauthenticated profiles for remote" do
540 setup do: local_and_remote_users()
541 setup :local_and_remote_activities
542
543 setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
544
545 test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
546 res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
547 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
548
549 assert %{"error" => "This API requires an authenticated user"} ==
550 conn
551 |> get("/api/v1/accounts/#{remote.id}/statuses")
552 |> json_response_and_validate_schema(:unauthorized)
553 end
554
555 test "if user is authenticated", %{local: local, remote: remote} do
556 %{conn: conn} = oauth_access(["read"])
557
558 res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
559 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
560
561 res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
562 assert length(json_response_and_validate_schema(res_conn, 200)) == 1
563 end
564 end
565
566 describe "followers" do
567 setup do: oauth_access(["read:accounts"])
568
569 test "getting followers", %{user: user, conn: conn} do
570 other_user = insert(:user)
571 {:ok, %{id: user_id}, other_user} = User.follow(user, other_user)
572
573 conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
574
575 assert [%{"id" => ^user_id}] = json_response_and_validate_schema(conn, 200)
576 end
577
578 test "getting followers, hide_followers", %{user: user, conn: conn} do
579 other_user = insert(:user, hide_followers: true)
580 {:ok, _user, _other_user} = User.follow(user, other_user)
581
582 conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
583
584 assert [] == json_response_and_validate_schema(conn, 200)
585 end
586
587 test "getting followers, hide_followers, same user requesting" do
588 user = insert(:user)
589 other_user = insert(:user, hide_followers: true)
590 {:ok, _user, _other_user} = User.follow(user, other_user)
591
592 conn =
593 build_conn()
594 |> assign(:user, other_user)
595 |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
596 |> get("/api/v1/accounts/#{other_user.id}/followers")
597
598 refute [] == json_response_and_validate_schema(conn, 200)
599 end
600
601 test "getting followers, pagination", %{user: user, conn: conn} do
602 {:ok, %User{id: follower1_id}, _user} = :user |> insert() |> User.follow(user)
603 {:ok, %User{id: follower2_id}, _user} = :user |> insert() |> User.follow(user)
604 {:ok, %User{id: follower3_id}, _user} = :user |> insert() |> User.follow(user)
605
606 assert [%{"id" => ^follower3_id}, %{"id" => ^follower2_id}] =
607 conn
608 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1_id}")
609 |> json_response_and_validate_schema(200)
610
611 assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
612 conn
613 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")
614 |> json_response_and_validate_schema(200)
615
616 assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
617 conn
618 |> get(
619 "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{
620 follower3_id
621 }"
622 )
623 |> json_response_and_validate_schema(200)
624
625 res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")
626
627 assert [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200)
628
629 assert [link_header] = get_resp_header(res_conn, "link")
630 assert link_header =~ ~r/min_id=#{follower2_id}/
631 assert link_header =~ ~r/max_id=#{follower2_id}/
632 end
633 end
634
635 describe "following" do
636 setup do: oauth_access(["read:accounts"])
637
638 test "getting following", %{user: user, conn: conn} do
639 other_user = insert(:user)
640 {:ok, user, other_user} = User.follow(user, other_user)
641
642 conn = get(conn, "/api/v1/accounts/#{user.id}/following")
643
644 assert [%{"id" => id}] = json_response_and_validate_schema(conn, 200)
645 assert id == to_string(other_user.id)
646 end
647
648 test "getting following, hide_follows, other user requesting" do
649 user = insert(:user, hide_follows: true)
650 other_user = insert(:user)
651 {:ok, user, other_user} = User.follow(user, other_user)
652
653 conn =
654 build_conn()
655 |> assign(:user, other_user)
656 |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
657 |> get("/api/v1/accounts/#{user.id}/following")
658
659 assert [] == json_response_and_validate_schema(conn, 200)
660 end
661
662 test "getting following, hide_follows, same user requesting" do
663 user = insert(:user, hide_follows: true)
664 other_user = insert(:user)
665 {:ok, user, _other_user} = User.follow(user, other_user)
666
667 conn =
668 build_conn()
669 |> assign(:user, user)
670 |> assign(:token, insert(:oauth_token, user: user, scopes: ["read:accounts"]))
671 |> get("/api/v1/accounts/#{user.id}/following")
672
673 refute [] == json_response_and_validate_schema(conn, 200)
674 end
675
676 test "getting following, pagination", %{user: user, conn: conn} do
677 following1 = insert(:user)
678 following2 = insert(:user)
679 following3 = insert(:user)
680 {:ok, _, _} = User.follow(user, following1)
681 {:ok, _, _} = User.follow(user, following2)
682 {:ok, _, _} = User.follow(user, following3)
683
684 res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
685
686 assert [%{"id" => id3}, %{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
687 assert id3 == following3.id
688 assert id2 == following2.id
689
690 res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
691
692 assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
693 assert id2 == following2.id
694 assert id1 == following1.id
695
696 res_conn =
697 get(
698 conn,
699 "/api/v1/accounts/#{user.id}/following?id=#{user.id}&limit=20&max_id=#{following3.id}"
700 )
701
702 assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
703 assert id2 == following2.id
704 assert id1 == following1.id
705
706 res_conn =
707 get(conn, "/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
708
709 assert [%{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
710 assert id2 == following2.id
711
712 assert [link_header] = get_resp_header(res_conn, "link")
713 assert link_header =~ ~r/min_id=#{following2.id}/
714 assert link_header =~ ~r/max_id=#{following2.id}/
715 end
716 end
717
718 describe "follow/unfollow" do
719 setup do: oauth_access(["follow"])
720
721 test "following / unfollowing a user", %{conn: conn} do
722 %{id: other_user_id, nickname: other_user_nickname} = insert(:user)
723
724 assert %{"id" => _id, "following" => true} =
725 conn
726 |> post("/api/v1/accounts/#{other_user_id}/follow")
727 |> json_response_and_validate_schema(200)
728
729 assert %{"id" => _id, "following" => false} =
730 conn
731 |> post("/api/v1/accounts/#{other_user_id}/unfollow")
732 |> json_response_and_validate_schema(200)
733
734 assert %{"id" => ^other_user_id} =
735 conn
736 |> put_req_header("content-type", "application/json")
737 |> post("/api/v1/follows", %{"uri" => other_user_nickname})
738 |> json_response_and_validate_schema(200)
739 end
740
741 test "cancelling follow request", %{conn: conn} do
742 %{id: other_user_id} = insert(:user, %{is_locked: true})
743
744 assert %{"id" => ^other_user_id, "following" => false, "requested" => true} =
745 conn
746 |> post("/api/v1/accounts/#{other_user_id}/follow")
747 |> json_response_and_validate_schema(:ok)
748
749 assert %{"id" => ^other_user_id, "following" => false, "requested" => false} =
750 conn
751 |> post("/api/v1/accounts/#{other_user_id}/unfollow")
752 |> json_response_and_validate_schema(:ok)
753 end
754
755 test "following without reblogs" do
756 %{conn: conn} = oauth_access(["follow", "read:statuses"])
757 followed = insert(:user)
758 other_user = insert(:user)
759
760 ret_conn =
761 conn
762 |> put_req_header("content-type", "application/json")
763 |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
764
765 assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200)
766
767 {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
768 {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
769
770 assert [] ==
771 conn
772 |> get("/api/v1/timelines/home")
773 |> json_response(200)
774
775 assert %{"showing_reblogs" => true} =
776 conn
777 |> put_req_header("content-type", "application/json")
778 |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: true})
779 |> json_response_and_validate_schema(200)
780
781 assert [%{"id" => ^reblog_id}] =
782 conn
783 |> get("/api/v1/timelines/home")
784 |> json_response(200)
785 end
786
787 test "following with reblogs" do
788 %{conn: conn} = oauth_access(["follow", "read:statuses"])
789 followed = insert(:user)
790 other_user = insert(:user)
791
792 ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow")
793
794 assert %{"showing_reblogs" => true} = json_response_and_validate_schema(ret_conn, 200)
795
796 {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
797 {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
798
799 assert [%{"id" => ^reblog_id}] =
800 conn
801 |> get("/api/v1/timelines/home")
802 |> json_response(200)
803
804 assert %{"showing_reblogs" => false} =
805 conn
806 |> put_req_header("content-type", "application/json")
807 |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
808 |> json_response_and_validate_schema(200)
809
810 assert [] ==
811 conn
812 |> get("/api/v1/timelines/home")
813 |> json_response(200)
814 end
815
816 test "following / unfollowing errors", %{user: user, conn: conn} do
817 # self follow
818 conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
819
820 assert %{"error" => "Can not follow yourself"} =
821 json_response_and_validate_schema(conn_res, 400)
822
823 # self unfollow
824 user = User.get_cached_by_id(user.id)
825 conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
826
827 assert %{"error" => "Can not unfollow yourself"} =
828 json_response_and_validate_schema(conn_res, 400)
829
830 # self follow via uri
831 user = User.get_cached_by_id(user.id)
832
833 assert %{"error" => "Can not follow yourself"} =
834 conn
835 |> put_req_header("content-type", "multipart/form-data")
836 |> post("/api/v1/follows", %{"uri" => user.nickname})
837 |> json_response_and_validate_schema(400)
838
839 # follow non existing user
840 conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
841 assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
842
843 # follow non existing user via uri
844 conn_res =
845 conn
846 |> put_req_header("content-type", "multipart/form-data")
847 |> post("/api/v1/follows", %{"uri" => "doesntexist"})
848
849 assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
850
851 # unfollow non existing user
852 conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
853 assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
854 end
855 end
856
857 describe "mute/unmute" do
858 setup do: oauth_access(["write:mutes"])
859
860 test "with notifications", %{conn: conn} do
861 other_user = insert(:user)
862
863 assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
864 conn
865 |> post("/api/v1/accounts/#{other_user.id}/mute")
866 |> json_response_and_validate_schema(200)
867
868 conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
869
870 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
871 json_response_and_validate_schema(conn, 200)
872 end
873
874 test "without notifications", %{conn: conn} do
875 other_user = insert(:user)
876
877 ret_conn =
878 conn
879 |> put_req_header("content-type", "multipart/form-data")
880 |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
881
882 assert %{"id" => _id, "muting" => true, "muting_notifications" => false} =
883 json_response_and_validate_schema(ret_conn, 200)
884
885 conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
886
887 assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
888 json_response_and_validate_schema(conn, 200)
889 end
890 end
891
892 describe "pinned statuses" do
893 setup do
894 user = insert(:user)
895 {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"})
896 %{conn: conn} = oauth_access(["read:statuses"], user: user)
897
898 [conn: conn, user: user, activity: activity]
899 end
900
901 test "returns pinned statuses", %{conn: conn, user: user, activity: %{id: activity_id}} do
902 {:ok, _} = CommonAPI.pin(activity_id, user)
903
904 assert [%{"id" => ^activity_id, "pinned" => true}] =
905 conn
906 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
907 |> json_response_and_validate_schema(200)
908 end
909 end
910
911 test "blocking / unblocking a user" do
912 %{conn: conn} = oauth_access(["follow"])
913 other_user = insert(:user)
914
915 ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/block")
916
917 assert %{"id" => _id, "blocking" => true} = json_response_and_validate_schema(ret_conn, 200)
918
919 conn = post(conn, "/api/v1/accounts/#{other_user.id}/unblock")
920
921 assert %{"id" => _id, "blocking" => false} = json_response_and_validate_schema(conn, 200)
922 end
923
924 describe "create account by app" do
925 setup do
926 valid_params = %{
927 username: "lain",
928 email: "lain@example.org",
929 password: "PlzDontHackLain",
930 agreement: true
931 }
932
933 [valid_params: valid_params]
934 end
935
936 test "registers and logs in without :account_activation_required / :account_approval_required",
937 %{conn: conn} do
938 clear_config([:instance, :account_activation_required], false)
939 clear_config([:instance, :account_approval_required], false)
940
941 conn =
942 conn
943 |> put_req_header("content-type", "application/json")
944 |> post("/api/v1/apps", %{
945 client_name: "client_name",
946 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
947 scopes: "read, write, follow"
948 })
949
950 assert %{
951 "client_id" => client_id,
952 "client_secret" => client_secret,
953 "id" => _,
954 "name" => "client_name",
955 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
956 "vapid_key" => _,
957 "website" => nil
958 } = json_response_and_validate_schema(conn, 200)
959
960 conn =
961 post(conn, "/oauth/token", %{
962 grant_type: "client_credentials",
963 client_id: client_id,
964 client_secret: client_secret
965 })
966
967 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
968 json_response(conn, 200)
969
970 assert token
971 token_from_db = Repo.get_by(Token, token: token)
972 assert token_from_db
973 assert refresh
974 assert scope == "read write follow"
975
976 clear_config([User, :email_blacklist], ["example.org"])
977
978 params = %{
979 username: "lain",
980 email: "lain@example.org",
981 password: "PlzDontHackLain",
982 bio: "Test Bio",
983 agreement: true
984 }
985
986 conn =
987 build_conn()
988 |> put_req_header("content-type", "multipart/form-data")
989 |> put_req_header("authorization", "Bearer " <> token)
990 |> post("/api/v1/accounts", params)
991
992 assert %{"error" => "{\"email\":[\"Invalid email\"]}"} =
993 json_response_and_validate_schema(conn, 400)
994
995 Pleroma.Config.put([User, :email_blacklist], [])
996
997 conn =
998 build_conn()
999 |> put_req_header("content-type", "multipart/form-data")
1000 |> put_req_header("authorization", "Bearer " <> token)
1001 |> post("/api/v1/accounts", params)
1002
1003 %{
1004 "access_token" => token,
1005 "created_at" => _created_at,
1006 "scope" => ^scope,
1007 "token_type" => "Bearer"
1008 } = json_response_and_validate_schema(conn, 200)
1009
1010 token_from_db = Repo.get_by(Token, token: token)
1011 assert token_from_db
1012 user = Repo.preload(token_from_db, :user).user
1013
1014 assert user
1015 refute user.confirmation_pending
1016 refute user.approval_pending
1017 end
1018
1019 test "registers but does not log in with :account_activation_required", %{conn: conn} do
1020 clear_config([:instance, :account_activation_required], true)
1021 clear_config([:instance, :account_approval_required], false)
1022
1023 conn =
1024 conn
1025 |> put_req_header("content-type", "application/json")
1026 |> post("/api/v1/apps", %{
1027 client_name: "client_name",
1028 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
1029 scopes: "read, write, follow"
1030 })
1031
1032 assert %{
1033 "client_id" => client_id,
1034 "client_secret" => client_secret,
1035 "id" => _,
1036 "name" => "client_name",
1037 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
1038 "vapid_key" => _,
1039 "website" => nil
1040 } = json_response_and_validate_schema(conn, 200)
1041
1042 conn =
1043 post(conn, "/oauth/token", %{
1044 grant_type: "client_credentials",
1045 client_id: client_id,
1046 client_secret: client_secret
1047 })
1048
1049 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
1050 json_response(conn, 200)
1051
1052 assert token
1053 token_from_db = Repo.get_by(Token, token: token)
1054 assert token_from_db
1055 assert refresh
1056 assert scope == "read write follow"
1057
1058 conn =
1059 build_conn()
1060 |> put_req_header("content-type", "multipart/form-data")
1061 |> put_req_header("authorization", "Bearer " <> token)
1062 |> post("/api/v1/accounts", %{
1063 username: "lain",
1064 email: "lain@example.org",
1065 password: "PlzDontHackLain",
1066 bio: "Test Bio",
1067 agreement: true
1068 })
1069
1070 response = json_response_and_validate_schema(conn, 200)
1071 assert %{"identifier" => "missing_confirmed_email"} = response
1072 refute response["access_token"]
1073 refute response["token_type"]
1074
1075 user = Repo.get_by(User, email: "lain@example.org")
1076 assert user.confirmation_pending
1077 end
1078
1079 test "registers but does not log in with :account_approval_required", %{conn: conn} do
1080 clear_config([:instance, :account_approval_required], true)
1081 clear_config([:instance, :account_activation_required], false)
1082
1083 conn =
1084 conn
1085 |> put_req_header("content-type", "application/json")
1086 |> post("/api/v1/apps", %{
1087 client_name: "client_name",
1088 redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
1089 scopes: "read, write, follow"
1090 })
1091
1092 assert %{
1093 "client_id" => client_id,
1094 "client_secret" => client_secret,
1095 "id" => _,
1096 "name" => "client_name",
1097 "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
1098 "vapid_key" => _,
1099 "website" => nil
1100 } = json_response_and_validate_schema(conn, 200)
1101
1102 conn =
1103 post(conn, "/oauth/token", %{
1104 grant_type: "client_credentials",
1105 client_id: client_id,
1106 client_secret: client_secret
1107 })
1108
1109 assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
1110 json_response(conn, 200)
1111
1112 assert token
1113 token_from_db = Repo.get_by(Token, token: token)
1114 assert token_from_db
1115 assert refresh
1116 assert scope == "read write follow"
1117
1118 conn =
1119 build_conn()
1120 |> put_req_header("content-type", "multipart/form-data")
1121 |> put_req_header("authorization", "Bearer " <> token)
1122 |> post("/api/v1/accounts", %{
1123 username: "lain",
1124 email: "lain@example.org",
1125 password: "PlzDontHackLain",
1126 bio: "Test Bio",
1127 agreement: true,
1128 reason: "I'm a cool dude, bro"
1129 })
1130
1131 response = json_response_and_validate_schema(conn, 200)
1132 assert %{"identifier" => "awaiting_approval"} = response
1133 refute response["access_token"]
1134 refute response["token_type"]
1135
1136 user = Repo.get_by(User, email: "lain@example.org")
1137
1138 assert user.approval_pending
1139 assert user.registration_reason == "I'm a cool dude, bro"
1140 end
1141
1142 test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
1143 _user = insert(:user, email: "lain@example.org")
1144 app_token = insert(:oauth_token, user: nil)
1145
1146 res =
1147 conn
1148 |> put_req_header("authorization", "Bearer " <> app_token.token)
1149 |> put_req_header("content-type", "application/json")
1150 |> post("/api/v1/accounts", valid_params)
1151
1152 assert json_response_and_validate_schema(res, 400) == %{
1153 "error" => "{\"email\":[\"has already been taken\"]}"
1154 }
1155 end
1156
1157 test "returns bad_request if missing required params", %{
1158 conn: conn,
1159 valid_params: valid_params
1160 } do
1161 app_token = insert(:oauth_token, user: nil)
1162
1163 conn =
1164 conn
1165 |> put_req_header("authorization", "Bearer " <> app_token.token)
1166 |> put_req_header("content-type", "application/json")
1167
1168 res = post(conn, "/api/v1/accounts", valid_params)
1169 assert json_response_and_validate_schema(res, 200)
1170
1171 [{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
1172 |> Stream.zip(Map.delete(valid_params, :email))
1173 |> Enum.each(fn {ip, {attr, _}} ->
1174 res =
1175 conn
1176 |> Map.put(:remote_ip, ip)
1177 |> post("/api/v1/accounts", Map.delete(valid_params, attr))
1178 |> json_response_and_validate_schema(400)
1179
1180 assert res == %{
1181 "error" => "Missing field: #{attr}.",
1182 "errors" => [
1183 %{
1184 "message" => "Missing field: #{attr}",
1185 "source" => %{"pointer" => "/#{attr}"},
1186 "title" => "Invalid value"
1187 }
1188 ]
1189 }
1190 end)
1191 end
1192
1193 test "returns bad_request if missing email params when :account_activation_required is enabled",
1194 %{conn: conn, valid_params: valid_params} do
1195 clear_config([:instance, :account_activation_required], true)
1196
1197 app_token = insert(:oauth_token, user: nil)
1198
1199 conn =
1200 conn
1201 |> put_req_header("authorization", "Bearer " <> app_token.token)
1202 |> put_req_header("content-type", "application/json")
1203
1204 res =
1205 conn
1206 |> Map.put(:remote_ip, {127, 0, 0, 5})
1207 |> post("/api/v1/accounts", Map.delete(valid_params, :email))
1208
1209 assert json_response_and_validate_schema(res, 400) ==
1210 %{"error" => "Missing parameter: email"}
1211
1212 res =
1213 conn
1214 |> Map.put(:remote_ip, {127, 0, 0, 6})
1215 |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
1216
1217 assert json_response_and_validate_schema(res, 400) == %{
1218 "error" => "{\"email\":[\"can't be blank\"]}"
1219 }
1220 end
1221
1222 test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
1223 app_token = insert(:oauth_token, user: nil)
1224 conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
1225
1226 res =
1227 conn
1228 |> put_req_header("content-type", "application/json")
1229 |> Map.put(:remote_ip, {127, 0, 0, 7})
1230 |> post("/api/v1/accounts", Map.delete(valid_params, :email))
1231
1232 assert json_response_and_validate_schema(res, 200)
1233 end
1234
1235 test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
1236 app_token = insert(:oauth_token, user: nil)
1237 conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
1238
1239 res =
1240 conn
1241 |> put_req_header("content-type", "application/json")
1242 |> Map.put(:remote_ip, {127, 0, 0, 8})
1243 |> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
1244
1245 assert json_response_and_validate_schema(res, 200)
1246 end
1247
1248 test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
1249 res =
1250 conn
1251 |> put_req_header("authorization", "Bearer " <> "invalid-token")
1252 |> put_req_header("content-type", "multipart/form-data")
1253 |> post("/api/v1/accounts", valid_params)
1254
1255 assert json_response_and_validate_schema(res, 403) == %{"error" => "Invalid credentials"}
1256 end
1257
1258 test "registration from trusted app" do
1259 clear_config([Pleroma.Captcha, :enabled], true)
1260 app = insert(:oauth_app, trusted: true, scopes: ["read", "write", "follow", "push"])
1261
1262 conn =
1263 build_conn()
1264 |> post("/oauth/token", %{
1265 "grant_type" => "client_credentials",
1266 "client_id" => app.client_id,
1267 "client_secret" => app.client_secret
1268 })
1269
1270 assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200)
1271
1272 response =
1273 build_conn()
1274 |> Plug.Conn.put_req_header("authorization", "Bearer " <> token)
1275 |> put_req_header("content-type", "multipart/form-data")
1276 |> post("/api/v1/accounts", %{
1277 nickname: "nickanme",
1278 agreement: true,
1279 email: "email@example.com",
1280 fullname: "Lain",
1281 username: "Lain",
1282 password: "some_password",
1283 confirm: "some_password"
1284 })
1285 |> json_response_and_validate_schema(200)
1286
1287 assert %{
1288 "access_token" => access_token,
1289 "created_at" => _,
1290 "scope" => "read write follow push",
1291 "token_type" => "Bearer"
1292 } = response
1293
1294 response =
1295 build_conn()
1296 |> Plug.Conn.put_req_header("authorization", "Bearer " <> access_token)
1297 |> get("/api/v1/accounts/verify_credentials")
1298 |> json_response_and_validate_schema(200)
1299
1300 assert %{
1301 "acct" => "Lain",
1302 "bot" => false,
1303 "display_name" => "Lain",
1304 "follow_requests_count" => 0,
1305 "followers_count" => 0,
1306 "following_count" => 0,
1307 "locked" => false,
1308 "note" => "",
1309 "source" => %{
1310 "fields" => [],
1311 "note" => "",
1312 "pleroma" => %{
1313 "actor_type" => "Person",
1314 "discoverable" => false,
1315 "no_rich_text" => false,
1316 "show_role" => true
1317 },
1318 "privacy" => "public",
1319 "sensitive" => false
1320 },
1321 "statuses_count" => 0,
1322 "username" => "Lain"
1323 } = response
1324 end
1325 end
1326
1327 describe "create account by app / rate limit" do
1328 setup do: clear_config([:rate_limit, :app_account_creation], {10_000, 2})
1329
1330 test "respects rate limit setting", %{conn: conn} do
1331 app_token = insert(:oauth_token, user: nil)
1332
1333 conn =
1334 conn
1335 |> put_req_header("authorization", "Bearer " <> app_token.token)
1336 |> Map.put(:remote_ip, {15, 15, 15, 15})
1337 |> put_req_header("content-type", "multipart/form-data")
1338
1339 for i <- 1..2 do
1340 conn =
1341 conn
1342 |> post("/api/v1/accounts", %{
1343 username: "#{i}lain",
1344 email: "#{i}lain@example.org",
1345 password: "PlzDontHackLain",
1346 agreement: true
1347 })
1348
1349 %{
1350 "access_token" => token,
1351 "created_at" => _created_at,
1352 "scope" => _scope,
1353 "token_type" => "Bearer"
1354 } = json_response_and_validate_schema(conn, 200)
1355
1356 token_from_db = Repo.get_by(Token, token: token)
1357 assert token_from_db
1358 token_from_db = Repo.preload(token_from_db, :user)
1359 assert token_from_db.user
1360 end
1361
1362 conn =
1363 post(conn, "/api/v1/accounts", %{
1364 username: "6lain",
1365 email: "6lain@example.org",
1366 password: "PlzDontHackLain",
1367 agreement: true
1368 })
1369
1370 assert json_response_and_validate_schema(conn, :too_many_requests) == %{
1371 "error" => "Throttled"
1372 }
1373 end
1374 end
1375
1376 describe "create account with enabled captcha" do
1377 setup %{conn: conn} do
1378 app_token = insert(:oauth_token, user: nil)
1379
1380 conn =
1381 conn
1382 |> put_req_header("authorization", "Bearer " <> app_token.token)
1383 |> put_req_header("content-type", "multipart/form-data")
1384
1385 [conn: conn]
1386 end
1387
1388 setup do: clear_config([Pleroma.Captcha, :enabled], true)
1389
1390 test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
1391 %{token: token, answer_data: answer_data} = Pleroma.Captcha.new()
1392
1393 params = %{
1394 username: "lain",
1395 email: "lain@example.org",
1396 password: "PlzDontHackLain",
1397 agreement: true,
1398 captcha_solution: Pleroma.Captcha.Mock.solution(),
1399 captcha_token: token,
1400 captcha_answer_data: answer_data
1401 }
1402
1403 assert %{
1404 "access_token" => access_token,
1405 "created_at" => _,
1406 "scope" => "read",
1407 "token_type" => "Bearer"
1408 } =
1409 conn
1410 |> post("/api/v1/accounts", params)
1411 |> json_response_and_validate_schema(:ok)
1412
1413 assert Token |> Repo.get_by(token: access_token) |> Repo.preload(:user) |> Map.get(:user)
1414 end
1415
1416 test "returns 400 if any captcha field is not provided", %{conn: conn} do
1417 captcha_fields = [:captcha_solution, :captcha_token, :captcha_answer_data]
1418
1419 valid_params = %{
1420 username: "lain",
1421 email: "lain@example.org",
1422 password: "PlzDontHackLain",
1423 agreement: true,
1424 captcha_solution: "xx",
1425 captcha_token: "xx",
1426 captcha_answer_data: "xx"
1427 }
1428
1429 for field <- captcha_fields do
1430 expected = %{
1431 "error" => "{\"captcha\":[\"Invalid CAPTCHA (Missing parameter: #{field})\"]}"
1432 }
1433
1434 assert expected ==
1435 conn
1436 |> post("/api/v1/accounts", Map.delete(valid_params, field))
1437 |> json_response_and_validate_schema(:bad_request)
1438 end
1439 end
1440
1441 test "returns an error if captcha is invalid", %{conn: conn} do
1442 params = %{
1443 username: "lain",
1444 email: "lain@example.org",
1445 password: "PlzDontHackLain",
1446 agreement: true,
1447 captcha_solution: "cofe",
1448 captcha_token: "cofe",
1449 captcha_answer_data: "cofe"
1450 }
1451
1452 assert %{"error" => "{\"captcha\":[\"Invalid answer data\"]}"} ==
1453 conn
1454 |> post("/api/v1/accounts", params)
1455 |> json_response_and_validate_schema(:bad_request)
1456 end
1457 end
1458
1459 describe "GET /api/v1/accounts/:id/lists - account_lists" do
1460 test "returns lists to which the account belongs" do
1461 %{user: user, conn: conn} = oauth_access(["read:lists"])
1462 other_user = insert(:user)
1463 assert {:ok, %Pleroma.List{id: _list_id} = list} = Pleroma.List.create("Test List", user)
1464 {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
1465
1466 assert [%{"id" => _list_id, "title" => "Test List"}] =
1467 conn
1468 |> get("/api/v1/accounts/#{other_user.id}/lists")
1469 |> json_response_and_validate_schema(200)
1470 end
1471 end
1472
1473 describe "verify_credentials" do
1474 test "verify_credentials" do
1475 %{user: user, conn: conn} = oauth_access(["read:accounts"])
1476
1477 [notification | _] =
1478 insert_list(7, :notification, user: user, activity: insert(:note_activity))
1479
1480 Pleroma.Notification.set_read_up_to(user, notification.id)
1481 conn = get(conn, "/api/v1/accounts/verify_credentials")
1482
1483 response = json_response_and_validate_schema(conn, 200)
1484
1485 assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
1486 assert response["pleroma"]["chat_token"]
1487 assert response["pleroma"]["unread_notifications_count"] == 6
1488 assert id == to_string(user.id)
1489 end
1490
1491 test "verify_credentials default scope unlisted" do
1492 user = insert(:user, default_scope: "unlisted")
1493 %{conn: conn} = oauth_access(["read:accounts"], user: user)
1494
1495 conn = get(conn, "/api/v1/accounts/verify_credentials")
1496
1497 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} =
1498 json_response_and_validate_schema(conn, 200)
1499
1500 assert id == to_string(user.id)
1501 end
1502
1503 test "locked accounts" do
1504 user = insert(:user, default_scope: "private")
1505 %{conn: conn} = oauth_access(["read:accounts"], user: user)
1506
1507 conn = get(conn, "/api/v1/accounts/verify_credentials")
1508
1509 assert %{"id" => id, "source" => %{"privacy" => "private"}} =
1510 json_response_and_validate_schema(conn, 200)
1511
1512 assert id == to_string(user.id)
1513 end
1514 end
1515
1516 describe "user relationships" do
1517 setup do: oauth_access(["read:follows"])
1518
1519 test "returns the relationships for the current user", %{user: user, conn: conn} do
1520 %{id: other_user_id} = other_user = insert(:user)
1521 {:ok, _user, _other_user} = User.follow(user, other_user)
1522
1523 assert [%{"id" => ^other_user_id}] =
1524 conn
1525 |> get("/api/v1/accounts/relationships?id=#{other_user.id}")
1526 |> json_response_and_validate_schema(200)
1527
1528 assert [%{"id" => ^other_user_id}] =
1529 conn
1530 |> get("/api/v1/accounts/relationships?id[]=#{other_user.id}")
1531 |> json_response_and_validate_schema(200)
1532 end
1533
1534 test "returns an empty list on a bad request", %{conn: conn} do
1535 conn = get(conn, "/api/v1/accounts/relationships", %{})
1536
1537 assert [] = json_response_and_validate_schema(conn, 200)
1538 end
1539 end
1540
1541 test "getting a list of mutes" do
1542 %{user: user, conn: conn} = oauth_access(["read:mutes"])
1543 %{id: id1} = other_user1 = insert(:user)
1544 %{id: id2} = other_user2 = insert(:user)
1545 %{id: id3} = other_user3 = insert(:user)
1546
1547 {:ok, _user_relationships} = User.mute(user, other_user1)
1548 {:ok, _user_relationships} = User.mute(user, other_user2)
1549 {:ok, _user_relationships} = User.mute(user, other_user3)
1550
1551 result =
1552 conn
1553 |> assign(:user, user)
1554 |> get("/api/v1/mutes")
1555 |> json_response_and_validate_schema(200)
1556
1557 assert [id1, id2, id3] == Enum.map(result, & &1["id"])
1558
1559 result =
1560 conn
1561 |> assign(:user, user)
1562 |> get("/api/v1/mutes?limit=1")
1563 |> json_response_and_validate_schema(200)
1564
1565 assert [%{"id" => ^id1}] = result
1566
1567 result =
1568 conn
1569 |> assign(:user, user)
1570 |> get("/api/v1/mutes?since_id=#{id1}")
1571 |> json_response_and_validate_schema(200)
1572
1573 assert [%{"id" => ^id2}, %{"id" => ^id3}] = result
1574
1575 result =
1576 conn
1577 |> assign(:user, user)
1578 |> get("/api/v1/mutes?since_id=#{id1}&max_id=#{id3}")
1579 |> json_response_and_validate_schema(200)
1580
1581 assert [%{"id" => ^id2}] = result
1582
1583 result =
1584 conn
1585 |> assign(:user, user)
1586 |> get("/api/v1/mutes?since_id=#{id1}&limit=1")
1587 |> json_response_and_validate_schema(200)
1588
1589 assert [%{"id" => ^id2}] = result
1590 end
1591
1592 test "getting a list of blocks" do
1593 %{user: user, conn: conn} = oauth_access(["read:blocks"])
1594 %{id: id1} = other_user1 = insert(:user)
1595 %{id: id2} = other_user2 = insert(:user)
1596 %{id: id3} = other_user3 = insert(:user)
1597
1598 {:ok, _user_relationship} = User.block(user, other_user1)
1599 {:ok, _user_relationship} = User.block(user, other_user3)
1600 {:ok, _user_relationship} = User.block(user, other_user2)
1601
1602 result =
1603 conn
1604 |> assign(:user, user)
1605 |> get("/api/v1/blocks")
1606 |> json_response_and_validate_schema(200)
1607
1608 assert [id1, id2, id3] == Enum.map(result, & &1["id"])
1609
1610 result =
1611 conn
1612 |> assign(:user, user)
1613 |> get("/api/v1/blocks?limit=1")
1614 |> json_response_and_validate_schema(200)
1615
1616 assert [%{"id" => ^id1}] = result
1617
1618 result =
1619 conn
1620 |> assign(:user, user)
1621 |> get("/api/v1/blocks?since_id=#{id1}")
1622 |> json_response_and_validate_schema(200)
1623
1624 assert [%{"id" => ^id2}, %{"id" => ^id3}] = result
1625
1626 result =
1627 conn
1628 |> assign(:user, user)
1629 |> get("/api/v1/blocks?since_id=#{id1}&max_id=#{id3}")
1630 |> json_response_and_validate_schema(200)
1631
1632 assert [%{"id" => ^id2}] = result
1633
1634 result =
1635 conn
1636 |> assign(:user, user)
1637 |> get("/api/v1/blocks?since_id=#{id1}&limit=1")
1638 |> json_response_and_validate_schema(200)
1639
1640 assert [%{"id" => ^id2}] = result
1641 end
1642 end