Merge branch 'bugfix/pleroma-email-naming' into 'develop'
[akkoma] / test / web / twitter_api / twitter_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.TwitterAPI.ControllerTest do
6 use Pleroma.Web.ConnCase
7 alias Comeonin.Pbkdf2
8 alias Ecto.Changeset
9 alias Pleroma.Activity
10 alias Pleroma.Builders.ActivityBuilder
11 alias Pleroma.Builders.UserBuilder
12 alias Pleroma.Notification
13 alias Pleroma.Object
14 alias Pleroma.Repo
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ActivityPub
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.OAuth.Token
19 alias Pleroma.Web.TwitterAPI.ActivityView
20 alias Pleroma.Web.TwitterAPI.Controller
21 alias Pleroma.Web.TwitterAPI.NotificationView
22 alias Pleroma.Web.TwitterAPI.TwitterAPI
23 alias Pleroma.Web.TwitterAPI.UserView
24
25 import Pleroma.Factory
26 import Mock
27
28 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
29
30 describe "POST /api/account/update_profile_banner" do
31 test "it updates the banner", %{conn: conn} do
32 user = insert(:user)
33
34 conn
35 |> assign(:user, user)
36 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
37 |> json_response(200)
38
39 user = refresh_record(user)
40 assert user.info.banner["type"] == "Image"
41 end
42 end
43
44 describe "POST /api/qvitter/update_background_image" do
45 test "it updates the background", %{conn: conn} do
46 user = insert(:user)
47
48 conn
49 |> assign(:user, user)
50 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
51 |> json_response(200)
52
53 user = refresh_record(user)
54 assert user.info.background["type"] == "Image"
55 end
56 end
57
58 describe "POST /api/account/verify_credentials" do
59 setup [:valid_user]
60
61 test "without valid credentials", %{conn: conn} do
62 conn = post(conn, "/api/account/verify_credentials.json")
63 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
64 end
65
66 test "with credentials", %{conn: conn, user: user} do
67 response =
68 conn
69 |> with_credentials(user.nickname, "test")
70 |> post("/api/account/verify_credentials.json")
71 |> json_response(200)
72
73 assert response ==
74 UserView.render("show.json", %{user: user, token: response["token"], for: user})
75 end
76 end
77
78 describe "POST /statuses/update.json" do
79 setup [:valid_user]
80
81 test "without valid credentials", %{conn: conn} do
82 conn = post(conn, "/api/statuses/update.json")
83 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
84 end
85
86 test "with credentials", %{conn: conn, user: user} do
87 conn_with_creds = conn |> with_credentials(user.nickname, "test")
88 request_path = "/api/statuses/update.json"
89
90 error_response = %{
91 "request" => request_path,
92 "error" => "Client must provide a 'status' parameter with a value."
93 }
94
95 conn =
96 conn_with_creds
97 |> post(request_path)
98
99 assert json_response(conn, 400) == error_response
100
101 conn =
102 conn_with_creds
103 |> post(request_path, %{status: ""})
104
105 assert json_response(conn, 400) == error_response
106
107 conn =
108 conn_with_creds
109 |> post(request_path, %{status: " "})
110
111 assert json_response(conn, 400) == error_response
112
113 # we post with visibility private in order to avoid triggering relay
114 conn =
115 conn_with_creds
116 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
117
118 assert json_response(conn, 200) ==
119 ActivityView.render("activity.json", %{
120 activity: Repo.one(Activity),
121 user: user,
122 for: user
123 })
124 end
125 end
126
127 describe "GET /statuses/public_timeline.json" do
128 setup [:valid_user]
129
130 test "returns statuses", %{conn: conn} do
131 user = insert(:user)
132 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
133 ActivityBuilder.insert_list(10, %{}, %{user: user})
134 since_id = List.last(activities).id
135
136 conn =
137 conn
138 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
139
140 response = json_response(conn, 200)
141
142 assert length(response) == 10
143 end
144
145 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
146 instance =
147 Application.get_env(:pleroma, :instance)
148 |> Keyword.put(:public, false)
149
150 Application.put_env(:pleroma, :instance, instance)
151
152 conn
153 |> get("/api/statuses/public_timeline.json")
154 |> json_response(403)
155
156 instance =
157 Application.get_env(:pleroma, :instance)
158 |> Keyword.put(:public, true)
159
160 Application.put_env(:pleroma, :instance, instance)
161 end
162
163 test "returns 200 to authenticated request when the instance is not public",
164 %{conn: conn, user: user} do
165 instance =
166 Application.get_env(:pleroma, :instance)
167 |> Keyword.put(:public, false)
168
169 Application.put_env(:pleroma, :instance, instance)
170
171 conn
172 |> with_credentials(user.nickname, "test")
173 |> get("/api/statuses/public_timeline.json")
174 |> json_response(200)
175
176 instance =
177 Application.get_env(:pleroma, :instance)
178 |> Keyword.put(:public, true)
179
180 Application.put_env(:pleroma, :instance, instance)
181 end
182
183 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
184 conn
185 |> get("/api/statuses/public_timeline.json")
186 |> json_response(200)
187 end
188
189 test "returns 200 to authenticated request when the instance is public",
190 %{conn: conn, user: user} do
191 conn
192 |> with_credentials(user.nickname, "test")
193 |> get("/api/statuses/public_timeline.json")
194 |> json_response(200)
195 end
196
197 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
198 Controller,
199 [:passthrough],
200 [] do
201 token = insert(:oauth_token, scopes: ["write"])
202
203 build_conn()
204 |> put_req_header("authorization", "Bearer #{token.token}")
205 |> get("/api/statuses/public_timeline.json")
206 |> json_response(200)
207
208 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
209 end
210 end
211
212 describe "GET /statuses/public_and_external_timeline.json" do
213 setup [:valid_user]
214
215 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
216 instance =
217 Application.get_env(:pleroma, :instance)
218 |> Keyword.put(:public, false)
219
220 Application.put_env(:pleroma, :instance, instance)
221
222 conn
223 |> get("/api/statuses/public_and_external_timeline.json")
224 |> json_response(403)
225
226 instance =
227 Application.get_env(:pleroma, :instance)
228 |> Keyword.put(:public, true)
229
230 Application.put_env(:pleroma, :instance, instance)
231 end
232
233 test "returns 200 to authenticated request when the instance is not public",
234 %{conn: conn, user: user} do
235 instance =
236 Application.get_env(:pleroma, :instance)
237 |> Keyword.put(:public, false)
238
239 Application.put_env(:pleroma, :instance, instance)
240
241 conn
242 |> with_credentials(user.nickname, "test")
243 |> get("/api/statuses/public_and_external_timeline.json")
244 |> json_response(200)
245
246 instance =
247 Application.get_env(:pleroma, :instance)
248 |> Keyword.put(:public, true)
249
250 Application.put_env(:pleroma, :instance, instance)
251 end
252
253 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
254 conn
255 |> get("/api/statuses/public_and_external_timeline.json")
256 |> json_response(200)
257 end
258
259 test "returns 200 to authenticated request when the instance is public",
260 %{conn: conn, user: user} do
261 conn
262 |> with_credentials(user.nickname, "test")
263 |> get("/api/statuses/public_and_external_timeline.json")
264 |> json_response(200)
265 end
266 end
267
268 describe "GET /statuses/show/:id.json" do
269 test "returns one status", %{conn: conn} do
270 user = insert(:user)
271 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
272 actor = Repo.get_by!(User, ap_id: activity.data["actor"])
273
274 conn =
275 conn
276 |> get("/api/statuses/show/#{activity.id}.json")
277
278 response = json_response(conn, 200)
279
280 assert response == ActivityView.render("activity.json", %{activity: activity, user: actor})
281 end
282 end
283
284 describe "GET /users/show.json" do
285 test "gets user with screen_name", %{conn: conn} do
286 user = insert(:user)
287
288 conn =
289 conn
290 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
291
292 response = json_response(conn, 200)
293
294 assert response["id"] == user.id
295 end
296
297 test "gets user with user_id", %{conn: conn} do
298 user = insert(:user)
299
300 conn =
301 conn
302 |> get("/api/users/show.json", %{"user_id" => user.id})
303
304 response = json_response(conn, 200)
305
306 assert response["id"] == user.id
307 end
308
309 test "gets a user for a logged in user", %{conn: conn} do
310 user = insert(:user)
311 logged_in = insert(:user)
312
313 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
314
315 conn =
316 conn
317 |> with_credentials(logged_in.nickname, "test")
318 |> get("/api/users/show.json", %{"user_id" => user.id})
319
320 response = json_response(conn, 200)
321
322 assert response["following"] == true
323 end
324 end
325
326 describe "GET /statusnet/conversation/:id.json" do
327 test "returns the statuses in the conversation", %{conn: conn} do
328 {:ok, _user} = UserBuilder.insert()
329 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
330 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
331 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
332
333 conn =
334 conn
335 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
336
337 response = json_response(conn, 200)
338
339 assert length(response) == 2
340 end
341 end
342
343 describe "GET /statuses/friends_timeline.json" do
344 setup [:valid_user]
345
346 test "without valid credentials", %{conn: conn} do
347 conn = get(conn, "/api/statuses/friends_timeline.json")
348 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
349 end
350
351 test "with credentials", %{conn: conn, user: current_user} do
352 user = insert(:user)
353
354 activities =
355 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
356
357 returned_activities =
358 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
359
360 other_user = insert(:user)
361 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
362 since_id = List.last(activities).id
363
364 current_user =
365 Changeset.change(current_user, following: [User.ap_followers(user)])
366 |> Repo.update!()
367
368 conn =
369 conn
370 |> with_credentials(current_user.nickname, "test")
371 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
372
373 response = json_response(conn, 200)
374
375 assert length(response) == 10
376
377 assert response ==
378 Enum.map(returned_activities, fn activity ->
379 ActivityView.render("activity.json", %{
380 activity: activity,
381 user: User.get_cached_by_ap_id(activity.data["actor"]),
382 for: current_user
383 })
384 end)
385 end
386 end
387
388 describe "GET /statuses/dm_timeline.json" do
389 test "it show direct messages", %{conn: conn} do
390 user_one = insert(:user)
391 user_two = insert(:user)
392
393 {:ok, user_two} = User.follow(user_two, user_one)
394
395 {:ok, direct} =
396 CommonAPI.post(user_one, %{
397 "status" => "Hi @#{user_two.nickname}!",
398 "visibility" => "direct"
399 })
400
401 {:ok, direct_two} =
402 CommonAPI.post(user_two, %{
403 "status" => "Hi @#{user_one.nickname}!",
404 "visibility" => "direct"
405 })
406
407 {:ok, _follower_only} =
408 CommonAPI.post(user_one, %{
409 "status" => "Hi @#{user_two.nickname}!",
410 "visibility" => "private"
411 })
412
413 # Only direct should be visible here
414 res_conn =
415 conn
416 |> assign(:user, user_two)
417 |> get("/api/statuses/dm_timeline.json")
418
419 [status, status_two] = json_response(res_conn, 200)
420 assert status["id"] == direct_two.id
421 assert status_two["id"] == direct.id
422 end
423
424 test "doesn't include DMs from blocked users", %{conn: conn} do
425 blocker = insert(:user)
426 blocked = insert(:user)
427 user = insert(:user)
428 {:ok, blocker} = User.block(blocker, blocked)
429
430 {:ok, _blocked_direct} =
431 CommonAPI.post(blocked, %{
432 "status" => "Hi @#{blocker.nickname}!",
433 "visibility" => "direct"
434 })
435
436 {:ok, direct} =
437 CommonAPI.post(user, %{
438 "status" => "Hi @#{blocker.nickname}!",
439 "visibility" => "direct"
440 })
441
442 res_conn =
443 conn
444 |> assign(:user, blocker)
445 |> get("/api/statuses/dm_timeline.json")
446
447 [status] = json_response(res_conn, 200)
448 assert status["id"] == direct.id
449 end
450 end
451
452 describe "GET /statuses/mentions.json" do
453 setup [:valid_user]
454
455 test "without valid credentials", %{conn: conn} do
456 conn = get(conn, "/api/statuses/mentions.json")
457 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
458 end
459
460 test "with credentials", %{conn: conn, user: current_user} do
461 {:ok, activity} =
462 CommonAPI.post(current_user, %{
463 "status" => "why is tenshi eating a corndog so cute?",
464 "visibility" => "public"
465 })
466
467 conn =
468 conn
469 |> with_credentials(current_user.nickname, "test")
470 |> get("/api/statuses/mentions.json")
471
472 response = json_response(conn, 200)
473
474 assert length(response) == 1
475
476 assert Enum.at(response, 0) ==
477 ActivityView.render("activity.json", %{
478 user: current_user,
479 for: current_user,
480 activity: activity
481 })
482 end
483
484 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
485 {:ok, _activity} =
486 CommonAPI.post(current_user, %{
487 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
488 "visibility" => "direct"
489 })
490
491 conn =
492 conn
493 |> with_credentials(current_user.nickname, "test")
494 |> get("/api/statuses/mentions.json")
495
496 response = json_response(conn, 200)
497
498 assert Enum.empty?(response)
499 end
500 end
501
502 describe "GET /api/qvitter/statuses/notifications.json" do
503 setup [:valid_user]
504
505 test "without valid credentials", %{conn: conn} do
506 conn = get(conn, "/api/qvitter/statuses/notifications.json")
507 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
508 end
509
510 test "with credentials", %{conn: conn, user: current_user} do
511 other_user = insert(:user)
512
513 {:ok, _activity} =
514 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
515
516 conn =
517 conn
518 |> with_credentials(current_user.nickname, "test")
519 |> get("/api/qvitter/statuses/notifications.json")
520
521 response = json_response(conn, 200)
522
523 assert length(response) == 1
524
525 assert response ==
526 NotificationView.render("notification.json", %{
527 notifications: Notification.for_user(current_user),
528 for: current_user
529 })
530 end
531 end
532
533 describe "POST /api/qvitter/statuses/notifications/read" do
534 setup [:valid_user]
535
536 test "without valid credentials", %{conn: conn} do
537 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
538 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
539 end
540
541 test "with credentials, without any params", %{conn: conn, user: current_user} do
542 conn =
543 conn
544 |> with_credentials(current_user.nickname, "test")
545 |> post("/api/qvitter/statuses/notifications/read")
546
547 assert json_response(conn, 400) == %{
548 "error" => "You need to specify latest_id",
549 "request" => "/api/qvitter/statuses/notifications/read"
550 }
551 end
552
553 test "with credentials, with params", %{conn: conn, user: current_user} do
554 other_user = insert(:user)
555
556 {:ok, _activity} =
557 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
558
559 response_conn =
560 conn
561 |> with_credentials(current_user.nickname, "test")
562 |> get("/api/qvitter/statuses/notifications.json")
563
564 [notification] = response = json_response(response_conn, 200)
565
566 assert length(response) == 1
567
568 assert notification["is_seen"] == 0
569
570 response_conn =
571 conn
572 |> with_credentials(current_user.nickname, "test")
573 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
574
575 [notification] = response = json_response(response_conn, 200)
576
577 assert length(response) == 1
578
579 assert notification["is_seen"] == 1
580 end
581 end
582
583 describe "GET /statuses/user_timeline.json" do
584 setup [:valid_user]
585
586 test "without any params", %{conn: conn} do
587 conn = get(conn, "/api/statuses/user_timeline.json")
588
589 assert json_response(conn, 400) == %{
590 "error" => "You need to specify screen_name or user_id",
591 "request" => "/api/statuses/user_timeline.json"
592 }
593 end
594
595 test "with user_id", %{conn: conn} do
596 user = insert(:user)
597 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
598
599 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
600 response = json_response(conn, 200)
601 assert length(response) == 1
602
603 assert Enum.at(response, 0) ==
604 ActivityView.render("activity.json", %{user: user, activity: activity})
605 end
606
607 test "with screen_name", %{conn: conn} do
608 user = insert(:user)
609 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
610
611 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
612 response = json_response(conn, 200)
613 assert length(response) == 1
614
615 assert Enum.at(response, 0) ==
616 ActivityView.render("activity.json", %{user: user, activity: activity})
617 end
618
619 test "with credentials", %{conn: conn, user: current_user} do
620 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
621
622 conn =
623 conn
624 |> with_credentials(current_user.nickname, "test")
625 |> get("/api/statuses/user_timeline.json")
626
627 response = json_response(conn, 200)
628
629 assert length(response) == 1
630
631 assert Enum.at(response, 0) ==
632 ActivityView.render("activity.json", %{
633 user: current_user,
634 for: current_user,
635 activity: activity
636 })
637 end
638
639 test "with credentials with user_id", %{conn: conn, user: current_user} do
640 user = insert(:user)
641 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
642
643 conn =
644 conn
645 |> with_credentials(current_user.nickname, "test")
646 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
647
648 response = json_response(conn, 200)
649
650 assert length(response) == 1
651
652 assert Enum.at(response, 0) ==
653 ActivityView.render("activity.json", %{user: user, activity: activity})
654 end
655
656 test "with credentials screen_name", %{conn: conn, user: current_user} do
657 user = insert(:user)
658 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
659
660 conn =
661 conn
662 |> with_credentials(current_user.nickname, "test")
663 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
664
665 response = json_response(conn, 200)
666
667 assert length(response) == 1
668
669 assert Enum.at(response, 0) ==
670 ActivityView.render("activity.json", %{user: user, activity: activity})
671 end
672
673 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
674 user = insert(:user)
675 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
676 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
677
678 conn =
679 conn
680 |> with_credentials(current_user.nickname, "test")
681 |> get("/api/statuses/user_timeline.json", %{
682 "user_id" => user.id,
683 "include_rts" => "false"
684 })
685
686 response = json_response(conn, 200)
687
688 assert length(response) == 1
689
690 assert Enum.at(response, 0) ==
691 ActivityView.render("activity.json", %{user: user, activity: activity})
692
693 conn =
694 conn
695 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
696
697 response = json_response(conn, 200)
698
699 assert length(response) == 1
700
701 assert Enum.at(response, 0) ==
702 ActivityView.render("activity.json", %{user: user, activity: activity})
703 end
704 end
705
706 describe "POST /friendships/create.json" do
707 setup [:valid_user]
708
709 test "without valid credentials", %{conn: conn} do
710 conn = post(conn, "/api/friendships/create.json")
711 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
712 end
713
714 test "with credentials", %{conn: conn, user: current_user} do
715 followed = insert(:user)
716
717 conn =
718 conn
719 |> with_credentials(current_user.nickname, "test")
720 |> post("/api/friendships/create.json", %{user_id: followed.id})
721
722 current_user = User.get_by_id(current_user.id)
723 assert User.ap_followers(followed) in current_user.following
724
725 assert json_response(conn, 200) ==
726 UserView.render("show.json", %{user: followed, for: current_user})
727 end
728
729 test "for restricted account", %{conn: conn, user: current_user} do
730 followed = insert(:user, info: %User.Info{locked: true})
731
732 conn =
733 conn
734 |> with_credentials(current_user.nickname, "test")
735 |> post("/api/friendships/create.json", %{user_id: followed.id})
736
737 current_user = User.get_by_id(current_user.id)
738 followed = User.get_by_id(followed.id)
739
740 refute User.ap_followers(followed) in current_user.following
741
742 assert json_response(conn, 200) ==
743 UserView.render("show.json", %{user: followed, for: current_user})
744 end
745 end
746
747 describe "POST /friendships/destroy.json" do
748 setup [:valid_user]
749
750 test "without valid credentials", %{conn: conn} do
751 conn = post(conn, "/api/friendships/destroy.json")
752 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
753 end
754
755 test "with credentials", %{conn: conn, user: current_user} do
756 followed = insert(:user)
757
758 {:ok, current_user} = User.follow(current_user, followed)
759 assert User.ap_followers(followed) in current_user.following
760 ActivityPub.follow(current_user, followed)
761
762 conn =
763 conn
764 |> with_credentials(current_user.nickname, "test")
765 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
766
767 current_user = User.get_by_id(current_user.id)
768 assert current_user.following == [current_user.ap_id]
769
770 assert json_response(conn, 200) ==
771 UserView.render("show.json", %{user: followed, for: current_user})
772 end
773 end
774
775 describe "POST /blocks/create.json" do
776 setup [:valid_user]
777
778 test "without valid credentials", %{conn: conn} do
779 conn = post(conn, "/api/blocks/create.json")
780 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
781 end
782
783 test "with credentials", %{conn: conn, user: current_user} do
784 blocked = insert(:user)
785
786 conn =
787 conn
788 |> with_credentials(current_user.nickname, "test")
789 |> post("/api/blocks/create.json", %{user_id: blocked.id})
790
791 current_user = User.get_by_id(current_user.id)
792 assert User.blocks?(current_user, blocked)
793
794 assert json_response(conn, 200) ==
795 UserView.render("show.json", %{user: blocked, for: current_user})
796 end
797 end
798
799 describe "POST /blocks/destroy.json" do
800 setup [:valid_user]
801
802 test "without valid credentials", %{conn: conn} do
803 conn = post(conn, "/api/blocks/destroy.json")
804 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
805 end
806
807 test "with credentials", %{conn: conn, user: current_user} do
808 blocked = insert(:user)
809
810 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
811 assert User.blocks?(current_user, blocked)
812
813 conn =
814 conn
815 |> with_credentials(current_user.nickname, "test")
816 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
817
818 current_user = User.get_by_id(current_user.id)
819 assert current_user.info.blocks == []
820
821 assert json_response(conn, 200) ==
822 UserView.render("show.json", %{user: blocked, for: current_user})
823 end
824 end
825
826 describe "GET /help/test.json" do
827 test "returns \"ok\"", %{conn: conn} do
828 conn = get(conn, "/api/help/test.json")
829 assert json_response(conn, 200) == "ok"
830 end
831 end
832
833 describe "POST /api/qvitter/update_avatar.json" do
834 setup [:valid_user]
835
836 test "without valid credentials", %{conn: conn} do
837 conn = post(conn, "/api/qvitter/update_avatar.json")
838 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
839 end
840
841 test "with credentials", %{conn: conn, user: current_user} do
842 avatar_image = File.read!("test/fixtures/avatar_data_uri")
843
844 conn =
845 conn
846 |> with_credentials(current_user.nickname, "test")
847 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
848
849 current_user = User.get_by_id(current_user.id)
850 assert is_map(current_user.avatar)
851
852 assert json_response(conn, 200) ==
853 UserView.render("show.json", %{user: current_user, for: current_user})
854 end
855 end
856
857 describe "GET /api/qvitter/mutes.json" do
858 setup [:valid_user]
859
860 test "unimplemented mutes without valid credentials", %{conn: conn} do
861 conn = get(conn, "/api/qvitter/mutes.json")
862 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
863 end
864
865 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
866 response =
867 conn
868 |> with_credentials(current_user.nickname, "test")
869 |> get("/api/qvitter/mutes.json")
870 |> json_response(200)
871
872 assert [] = response
873 end
874 end
875
876 describe "POST /api/favorites/create/:id" do
877 setup [:valid_user]
878
879 test "without valid credentials", %{conn: conn} do
880 note_activity = insert(:note_activity)
881 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
882 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
883 end
884
885 test "with credentials", %{conn: conn, user: current_user} do
886 note_activity = insert(:note_activity)
887
888 conn =
889 conn
890 |> with_credentials(current_user.nickname, "test")
891 |> post("/api/favorites/create/#{note_activity.id}.json")
892
893 assert json_response(conn, 200)
894 end
895
896 test "with credentials, invalid param", %{conn: conn, user: current_user} do
897 conn =
898 conn
899 |> with_credentials(current_user.nickname, "test")
900 |> post("/api/favorites/create/wrong.json")
901
902 assert json_response(conn, 400)
903 end
904
905 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
906 conn =
907 conn
908 |> with_credentials(current_user.nickname, "test")
909 |> post("/api/favorites/create/1.json")
910
911 assert json_response(conn, 400)
912 end
913 end
914
915 describe "POST /api/favorites/destroy/:id" do
916 setup [:valid_user]
917
918 test "without valid credentials", %{conn: conn} do
919 note_activity = insert(:note_activity)
920 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
921 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
922 end
923
924 test "with credentials", %{conn: conn, user: current_user} do
925 note_activity = insert(:note_activity)
926 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
927 ActivityPub.like(current_user, object)
928
929 conn =
930 conn
931 |> with_credentials(current_user.nickname, "test")
932 |> post("/api/favorites/destroy/#{note_activity.id}.json")
933
934 assert json_response(conn, 200)
935 end
936 end
937
938 describe "POST /api/statuses/retweet/:id" do
939 setup [:valid_user]
940
941 test "without valid credentials", %{conn: conn} do
942 note_activity = insert(:note_activity)
943 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
944 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
945 end
946
947 test "with credentials", %{conn: conn, user: current_user} do
948 note_activity = insert(:note_activity)
949
950 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
951
952 response =
953 conn
954 |> with_credentials(current_user.nickname, "test")
955 |> post(request_path)
956
957 activity = Activity.get_by_id(note_activity.id)
958 activity_user = User.get_by_ap_id(note_activity.data["actor"])
959
960 assert json_response(response, 200) ==
961 ActivityView.render("activity.json", %{
962 user: activity_user,
963 for: current_user,
964 activity: activity
965 })
966 end
967 end
968
969 describe "POST /api/statuses/unretweet/:id" do
970 setup [:valid_user]
971
972 test "without valid credentials", %{conn: conn} do
973 note_activity = insert(:note_activity)
974 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
975 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
976 end
977
978 test "with credentials", %{conn: conn, user: current_user} do
979 note_activity = insert(:note_activity)
980
981 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
982
983 _response =
984 conn
985 |> with_credentials(current_user.nickname, "test")
986 |> post(request_path)
987
988 request_path = String.replace(request_path, "retweet", "unretweet")
989
990 response =
991 conn
992 |> with_credentials(current_user.nickname, "test")
993 |> post(request_path)
994
995 activity = Activity.get_by_id(note_activity.id)
996 activity_user = User.get_by_ap_id(note_activity.data["actor"])
997
998 assert json_response(response, 200) ==
999 ActivityView.render("activity.json", %{
1000 user: activity_user,
1001 for: current_user,
1002 activity: activity
1003 })
1004 end
1005 end
1006
1007 describe "POST /api/account/register" do
1008 test "it creates a new user", %{conn: conn} do
1009 data = %{
1010 "nickname" => "lain",
1011 "email" => "lain@wired.jp",
1012 "fullname" => "lain iwakura",
1013 "bio" => "close the world.",
1014 "password" => "bear",
1015 "confirm" => "bear"
1016 }
1017
1018 conn =
1019 conn
1020 |> post("/api/account/register", data)
1021
1022 user = json_response(conn, 200)
1023
1024 fetched_user = User.get_by_nickname("lain")
1025 assert user == UserView.render("show.json", %{user: fetched_user})
1026 end
1027
1028 test "it returns errors on a problem", %{conn: conn} do
1029 data = %{
1030 "email" => "lain@wired.jp",
1031 "fullname" => "lain iwakura",
1032 "bio" => "close the world.",
1033 "password" => "bear",
1034 "confirm" => "bear"
1035 }
1036
1037 conn =
1038 conn
1039 |> post("/api/account/register", data)
1040
1041 errors = json_response(conn, 400)
1042
1043 assert is_binary(errors["error"])
1044 end
1045 end
1046
1047 describe "POST /api/account/password_reset, with valid parameters" do
1048 setup %{conn: conn} do
1049 user = insert(:user)
1050 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1051 %{conn: conn, user: user}
1052 end
1053
1054 test "it returns 204", %{conn: conn} do
1055 assert json_response(conn, :no_content)
1056 end
1057
1058 test "it creates a PasswordResetToken record for user", %{user: user} do
1059 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1060 assert token_record
1061 end
1062
1063 test "it sends an email to user", %{user: user} do
1064 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1065
1066 Swoosh.TestAssertions.assert_email_sent(
1067 Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
1068 )
1069 end
1070 end
1071
1072 describe "POST /api/account/password_reset, with invalid parameters" do
1073 setup [:valid_user]
1074
1075 test "it returns 500 when user is not found", %{conn: conn, user: user} do
1076 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1077 assert json_response(conn, :internal_server_error)
1078 end
1079
1080 test "it returns 500 when user is not local", %{conn: conn, user: user} do
1081 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1082 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1083 assert json_response(conn, :internal_server_error)
1084 end
1085 end
1086
1087 describe "GET /api/account/confirm_email/:id/:token" do
1088 setup do
1089 user = insert(:user)
1090 info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
1091
1092 {:ok, user} =
1093 user
1094 |> Changeset.change()
1095 |> Changeset.put_embed(:info, info_change)
1096 |> Repo.update()
1097
1098 assert user.info.confirmation_pending
1099
1100 [user: user]
1101 end
1102
1103 test "it redirects to root url", %{conn: conn, user: user} do
1104 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1105
1106 assert 302 == conn.status
1107 end
1108
1109 test "it confirms the user account", %{conn: conn, user: user} do
1110 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1111
1112 user = User.get_by_id(user.id)
1113
1114 refute user.info.confirmation_pending
1115 refute user.info.confirmation_token
1116 end
1117
1118 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1119 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1120
1121 assert 500 == conn.status
1122 end
1123
1124 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1125 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1126
1127 assert 500 == conn.status
1128 end
1129 end
1130
1131 describe "POST /api/account/resend_confirmation_email" do
1132 setup do
1133 setting = Pleroma.Config.get([:instance, :account_activation_required])
1134
1135 unless setting do
1136 Pleroma.Config.put([:instance, :account_activation_required], true)
1137 on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
1138 end
1139
1140 user = insert(:user)
1141 info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
1142
1143 {:ok, user} =
1144 user
1145 |> Changeset.change()
1146 |> Changeset.put_embed(:info, info_change)
1147 |> Repo.update()
1148
1149 assert user.info.confirmation_pending
1150
1151 [user: user]
1152 end
1153
1154 test "it returns 204 No Content", %{conn: conn, user: user} do
1155 conn
1156 |> assign(:user, user)
1157 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1158 |> json_response(:no_content)
1159 end
1160
1161 test "it sends confirmation email", %{conn: conn, user: user} do
1162 conn
1163 |> assign(:user, user)
1164 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1165
1166 Swoosh.TestAssertions.assert_email_sent(
1167 Pleroma.Emails.UserEmail.account_confirmation_email(user)
1168 )
1169 end
1170 end
1171
1172 describe "GET /api/externalprofile/show" do
1173 test "it returns the user", %{conn: conn} do
1174 user = insert(:user)
1175 other_user = insert(:user)
1176
1177 conn =
1178 conn
1179 |> assign(:user, user)
1180 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1181
1182 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1183 end
1184 end
1185
1186 describe "GET /api/statuses/followers" do
1187 test "it returns a user's followers", %{conn: conn} do
1188 user = insert(:user)
1189 follower_one = insert(:user)
1190 follower_two = insert(:user)
1191 _not_follower = insert(:user)
1192
1193 {:ok, follower_one} = User.follow(follower_one, user)
1194 {:ok, follower_two} = User.follow(follower_two, user)
1195
1196 conn =
1197 conn
1198 |> assign(:user, user)
1199 |> get("/api/statuses/followers")
1200
1201 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1202 result = json_response(conn, 200)
1203 assert Enum.sort(expected) == Enum.sort(result)
1204 end
1205
1206 test "it returns 20 followers per page", %{conn: conn} do
1207 user = insert(:user)
1208 followers = insert_list(21, :user)
1209
1210 Enum.each(followers, fn follower ->
1211 User.follow(follower, user)
1212 end)
1213
1214 res_conn =
1215 conn
1216 |> assign(:user, user)
1217 |> get("/api/statuses/followers")
1218
1219 result = json_response(res_conn, 200)
1220 assert length(result) == 20
1221
1222 res_conn =
1223 conn
1224 |> assign(:user, user)
1225 |> get("/api/statuses/followers?page=2")
1226
1227 result = json_response(res_conn, 200)
1228 assert length(result) == 1
1229 end
1230
1231 test "it returns a given user's followers with user_id", %{conn: conn} do
1232 user = insert(:user)
1233 follower_one = insert(:user)
1234 follower_two = insert(:user)
1235 not_follower = insert(:user)
1236
1237 {:ok, follower_one} = User.follow(follower_one, user)
1238 {:ok, follower_two} = User.follow(follower_two, user)
1239
1240 conn =
1241 conn
1242 |> assign(:user, not_follower)
1243 |> get("/api/statuses/followers", %{"user_id" => user.id})
1244
1245 assert MapSet.equal?(
1246 MapSet.new(json_response(conn, 200)),
1247 MapSet.new(
1248 UserView.render("index.json", %{
1249 users: [follower_one, follower_two],
1250 for: not_follower
1251 })
1252 )
1253 )
1254 end
1255
1256 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1257 user = insert(:user, %{info: %{hide_followers: true}})
1258 follower_one = insert(:user)
1259 follower_two = insert(:user)
1260 not_follower = insert(:user)
1261
1262 {:ok, _follower_one} = User.follow(follower_one, user)
1263 {:ok, _follower_two} = User.follow(follower_two, user)
1264
1265 response =
1266 conn
1267 |> assign(:user, not_follower)
1268 |> get("/api/statuses/followers", %{"user_id" => user.id})
1269 |> json_response(200)
1270
1271 assert [] == response
1272 end
1273
1274 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1275 %{
1276 conn: conn
1277 } do
1278 user = insert(:user, %{info: %{hide_followers: true}})
1279 follower_one = insert(:user)
1280 follower_two = insert(:user)
1281 _not_follower = insert(:user)
1282
1283 {:ok, _follower_one} = User.follow(follower_one, user)
1284 {:ok, _follower_two} = User.follow(follower_two, user)
1285
1286 conn =
1287 conn
1288 |> assign(:user, user)
1289 |> get("/api/statuses/followers", %{"user_id" => user.id})
1290
1291 refute [] == json_response(conn, 200)
1292 end
1293 end
1294
1295 describe "GET /api/statuses/blocks" do
1296 test "it returns the list of users blocked by requester", %{conn: conn} do
1297 user = insert(:user)
1298 other_user = insert(:user)
1299
1300 {:ok, user} = User.block(user, other_user)
1301
1302 conn =
1303 conn
1304 |> assign(:user, user)
1305 |> get("/api/statuses/blocks")
1306
1307 expected = UserView.render("index.json", %{users: [other_user], for: user})
1308 result = json_response(conn, 200)
1309 assert Enum.sort(expected) == Enum.sort(result)
1310 end
1311 end
1312
1313 describe "GET /api/statuses/friends" do
1314 test "it returns the logged in user's friends", %{conn: conn} do
1315 user = insert(:user)
1316 followed_one = insert(:user)
1317 followed_two = insert(:user)
1318 _not_followed = insert(:user)
1319
1320 {:ok, user} = User.follow(user, followed_one)
1321 {:ok, user} = User.follow(user, followed_two)
1322
1323 conn =
1324 conn
1325 |> assign(:user, user)
1326 |> get("/api/statuses/friends")
1327
1328 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1329 result = json_response(conn, 200)
1330 assert Enum.sort(expected) == Enum.sort(result)
1331 end
1332
1333 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1334 user = insert(:user)
1335 followeds = insert_list(21, :user)
1336
1337 {:ok, user} =
1338 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1339 User.follow(user, followed)
1340 end)
1341
1342 res_conn =
1343 conn
1344 |> assign(:user, user)
1345 |> get("/api/statuses/friends")
1346
1347 result = json_response(res_conn, 200)
1348 assert length(result) == 20
1349
1350 res_conn =
1351 conn
1352 |> assign(:user, user)
1353 |> get("/api/statuses/friends", %{page: 2})
1354
1355 result = json_response(res_conn, 200)
1356 assert length(result) == 1
1357
1358 res_conn =
1359 conn
1360 |> assign(:user, user)
1361 |> get("/api/statuses/friends", %{all: true})
1362
1363 result = json_response(res_conn, 200)
1364 assert length(result) == 21
1365 end
1366
1367 test "it returns a given user's friends with user_id", %{conn: conn} do
1368 user = insert(:user)
1369 followed_one = insert(:user)
1370 followed_two = insert(:user)
1371 _not_followed = insert(:user)
1372
1373 {:ok, user} = User.follow(user, followed_one)
1374 {:ok, user} = User.follow(user, followed_two)
1375
1376 conn =
1377 conn
1378 |> assign(:user, user)
1379 |> get("/api/statuses/friends", %{"user_id" => user.id})
1380
1381 assert MapSet.equal?(
1382 MapSet.new(json_response(conn, 200)),
1383 MapSet.new(
1384 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1385 )
1386 )
1387 end
1388
1389 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1390 user = insert(:user, %{info: %{hide_follows: true}})
1391 followed_one = insert(:user)
1392 followed_two = insert(:user)
1393 not_followed = insert(:user)
1394
1395 {:ok, user} = User.follow(user, followed_one)
1396 {:ok, user} = User.follow(user, followed_two)
1397
1398 conn =
1399 conn
1400 |> assign(:user, not_followed)
1401 |> get("/api/statuses/friends", %{"user_id" => user.id})
1402
1403 assert [] == json_response(conn, 200)
1404 end
1405
1406 test "it returns friends when hide_follows is set to true if the user themselves request it",
1407 %{
1408 conn: conn
1409 } do
1410 user = insert(:user, %{info: %{hide_follows: true}})
1411 followed_one = insert(:user)
1412 followed_two = insert(:user)
1413 _not_followed = insert(:user)
1414
1415 {:ok, _user} = User.follow(user, followed_one)
1416 {:ok, _user} = User.follow(user, followed_two)
1417
1418 response =
1419 conn
1420 |> assign(:user, user)
1421 |> get("/api/statuses/friends", %{"user_id" => user.id})
1422 |> json_response(200)
1423
1424 refute [] == response
1425 end
1426
1427 test "it returns a given user's friends with screen_name", %{conn: conn} do
1428 user = insert(:user)
1429 followed_one = insert(:user)
1430 followed_two = insert(:user)
1431 _not_followed = insert(:user)
1432
1433 {:ok, user} = User.follow(user, followed_one)
1434 {:ok, user} = User.follow(user, followed_two)
1435
1436 conn =
1437 conn
1438 |> assign(:user, user)
1439 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1440
1441 assert MapSet.equal?(
1442 MapSet.new(json_response(conn, 200)),
1443 MapSet.new(
1444 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1445 )
1446 )
1447 end
1448 end
1449
1450 describe "GET /friends/ids" do
1451 test "it returns a user's friends", %{conn: conn} do
1452 user = insert(:user)
1453 followed_one = insert(:user)
1454 followed_two = insert(:user)
1455 _not_followed = insert(:user)
1456
1457 {:ok, user} = User.follow(user, followed_one)
1458 {:ok, user} = User.follow(user, followed_two)
1459
1460 conn =
1461 conn
1462 |> assign(:user, user)
1463 |> get("/api/friends/ids")
1464
1465 expected = [followed_one.id, followed_two.id]
1466
1467 assert MapSet.equal?(
1468 MapSet.new(Poison.decode!(json_response(conn, 200))),
1469 MapSet.new(expected)
1470 )
1471 end
1472 end
1473
1474 describe "POST /api/account/update_profile.json" do
1475 test "it updates a user's profile", %{conn: conn} do
1476 user = insert(:user)
1477 user2 = insert(:user)
1478
1479 conn =
1480 conn
1481 |> assign(:user, user)
1482 |> post("/api/account/update_profile.json", %{
1483 "name" => "new name",
1484 "description" => "hi @#{user2.nickname}"
1485 })
1486
1487 user = Repo.get!(User, user.id)
1488 assert user.name == "new name"
1489
1490 assert user.bio ==
1491 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1492 user2.ap_id
1493 }'>@<span>#{user2.nickname}</span></a></span>"
1494
1495 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1496 end
1497
1498 test "it sets and un-sets hide_follows", %{conn: conn} do
1499 user = insert(:user)
1500
1501 conn
1502 |> assign(:user, user)
1503 |> post("/api/account/update_profile.json", %{
1504 "hide_follows" => "true"
1505 })
1506
1507 user = Repo.get!(User, user.id)
1508 assert user.info.hide_follows == true
1509
1510 conn =
1511 conn
1512 |> assign(:user, user)
1513 |> post("/api/account/update_profile.json", %{
1514 "hide_follows" => "false"
1515 })
1516
1517 user = Repo.get!(User, user.id)
1518 assert user.info.hide_follows == false
1519 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1520 end
1521
1522 test "it sets and un-sets hide_followers", %{conn: conn} do
1523 user = insert(:user)
1524
1525 conn
1526 |> assign(:user, user)
1527 |> post("/api/account/update_profile.json", %{
1528 "hide_followers" => "true"
1529 })
1530
1531 user = Repo.get!(User, user.id)
1532 assert user.info.hide_followers == true
1533
1534 conn =
1535 conn
1536 |> assign(:user, user)
1537 |> post("/api/account/update_profile.json", %{
1538 "hide_followers" => "false"
1539 })
1540
1541 user = Repo.get!(User, user.id)
1542 assert user.info.hide_followers == false
1543 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1544 end
1545
1546 test "it sets and un-sets show_role", %{conn: conn} do
1547 user = insert(:user)
1548
1549 conn
1550 |> assign(:user, user)
1551 |> post("/api/account/update_profile.json", %{
1552 "show_role" => "true"
1553 })
1554
1555 user = Repo.get!(User, user.id)
1556 assert user.info.show_role == true
1557
1558 conn =
1559 conn
1560 |> assign(:user, user)
1561 |> post("/api/account/update_profile.json", %{
1562 "show_role" => "false"
1563 })
1564
1565 user = Repo.get!(User, user.id)
1566 assert user.info.show_role == false
1567 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1568 end
1569
1570 test "it locks an account", %{conn: conn} do
1571 user = insert(:user)
1572
1573 conn =
1574 conn
1575 |> assign(:user, user)
1576 |> post("/api/account/update_profile.json", %{
1577 "locked" => "true"
1578 })
1579
1580 user = Repo.get!(User, user.id)
1581 assert user.info.locked == true
1582
1583 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1584 end
1585
1586 test "it unlocks an account", %{conn: conn} do
1587 user = insert(:user)
1588
1589 conn =
1590 conn
1591 |> assign(:user, user)
1592 |> post("/api/account/update_profile.json", %{
1593 "locked" => "false"
1594 })
1595
1596 user = Repo.get!(User, user.id)
1597 assert user.info.locked == false
1598
1599 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1600 end
1601 end
1602
1603 defp valid_user(_context) do
1604 user = insert(:user)
1605 [user: user]
1606 end
1607
1608 defp with_credentials(conn, username, password) do
1609 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1610 put_req_header(conn, "authorization", header_content)
1611 end
1612
1613 describe "GET /api/search.json" do
1614 test "it returns search results", %{conn: conn} do
1615 user = insert(:user)
1616 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1617
1618 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1619 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1620
1621 conn =
1622 conn
1623 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1624
1625 assert [status] = json_response(conn, 200)
1626 assert status["id"] == activity.id
1627 end
1628 end
1629
1630 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1631 test "it returns the tags timeline", %{conn: conn} do
1632 user = insert(:user)
1633 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1634
1635 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1636 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1637
1638 conn =
1639 conn
1640 |> get("/api/statusnet/tags/timeline/2hu.json")
1641
1642 assert [status] = json_response(conn, 200)
1643 assert status["id"] == activity.id
1644 end
1645 end
1646
1647 test "Convert newlines to <br> in bio", %{conn: conn} do
1648 user = insert(:user)
1649
1650 _conn =
1651 conn
1652 |> assign(:user, user)
1653 |> post("/api/account/update_profile.json", %{
1654 "description" => "Hello,\r\nWorld! I\n am a test."
1655 })
1656
1657 user = Repo.get!(User, user.id)
1658 assert user.bio == "Hello,<br>World! I<br> am a test."
1659 end
1660
1661 describe "POST /api/pleroma/change_password" do
1662 setup [:valid_user]
1663
1664 test "without credentials", %{conn: conn} do
1665 conn = post(conn, "/api/pleroma/change_password")
1666 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1667 end
1668
1669 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1670 conn =
1671 conn
1672 |> with_credentials(current_user.nickname, "test")
1673 |> post("/api/pleroma/change_password", %{
1674 "password" => "hi",
1675 "new_password" => "newpass",
1676 "new_password_confirmation" => "newpass"
1677 })
1678
1679 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1680 end
1681
1682 test "with credentials, valid password and new password and confirmation not matching", %{
1683 conn: conn,
1684 user: current_user
1685 } do
1686 conn =
1687 conn
1688 |> with_credentials(current_user.nickname, "test")
1689 |> post("/api/pleroma/change_password", %{
1690 "password" => "test",
1691 "new_password" => "newpass",
1692 "new_password_confirmation" => "notnewpass"
1693 })
1694
1695 assert json_response(conn, 200) == %{
1696 "error" => "New password does not match confirmation."
1697 }
1698 end
1699
1700 test "with credentials, valid password and invalid new password", %{
1701 conn: conn,
1702 user: current_user
1703 } do
1704 conn =
1705 conn
1706 |> with_credentials(current_user.nickname, "test")
1707 |> post("/api/pleroma/change_password", %{
1708 "password" => "test",
1709 "new_password" => "",
1710 "new_password_confirmation" => ""
1711 })
1712
1713 assert json_response(conn, 200) == %{
1714 "error" => "New password can't be blank."
1715 }
1716 end
1717
1718 test "with credentials, valid password and matching new password and confirmation", %{
1719 conn: conn,
1720 user: current_user
1721 } do
1722 conn =
1723 conn
1724 |> with_credentials(current_user.nickname, "test")
1725 |> post("/api/pleroma/change_password", %{
1726 "password" => "test",
1727 "new_password" => "newpass",
1728 "new_password_confirmation" => "newpass"
1729 })
1730
1731 assert json_response(conn, 200) == %{"status" => "success"}
1732 fetched_user = User.get_by_id(current_user.id)
1733 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1734 end
1735 end
1736
1737 describe "POST /api/pleroma/delete_account" do
1738 setup [:valid_user]
1739
1740 test "without credentials", %{conn: conn} do
1741 conn = post(conn, "/api/pleroma/delete_account")
1742 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1743 end
1744
1745 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1746 conn =
1747 conn
1748 |> with_credentials(current_user.nickname, "test")
1749 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1750
1751 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1752 end
1753
1754 test "with credentials and valid password", %{conn: conn, user: current_user} do
1755 conn =
1756 conn
1757 |> with_credentials(current_user.nickname, "test")
1758 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1759
1760 assert json_response(conn, 200) == %{"status" => "success"}
1761 # Wait a second for the started task to end
1762 :timer.sleep(1000)
1763 end
1764 end
1765
1766 describe "GET /api/pleroma/friend_requests" do
1767 test "it lists friend requests" do
1768 user = insert(:user)
1769 other_user = insert(:user)
1770
1771 {:ok, _activity} = ActivityPub.follow(other_user, user)
1772
1773 user = User.get_by_id(user.id)
1774 other_user = User.get_by_id(other_user.id)
1775
1776 assert User.following?(other_user, user) == false
1777
1778 conn =
1779 build_conn()
1780 |> assign(:user, user)
1781 |> get("/api/pleroma/friend_requests")
1782
1783 assert [relationship] = json_response(conn, 200)
1784 assert other_user.id == relationship["id"]
1785 end
1786
1787 test "requires 'read' permission", %{conn: conn} do
1788 token1 = insert(:oauth_token, scopes: ["write"])
1789 token2 = insert(:oauth_token, scopes: ["read"])
1790
1791 for token <- [token1, token2] do
1792 conn =
1793 conn
1794 |> put_req_header("authorization", "Bearer #{token.token}")
1795 |> get("/api/pleroma/friend_requests")
1796
1797 if token == token1 do
1798 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1799 else
1800 assert json_response(conn, 200)
1801 end
1802 end
1803 end
1804 end
1805
1806 describe "POST /api/pleroma/friendships/approve" do
1807 test "it approves a friend request" do
1808 user = insert(:user)
1809 other_user = insert(:user)
1810
1811 {:ok, _activity} = ActivityPub.follow(other_user, user)
1812
1813 user = User.get_by_id(user.id)
1814 other_user = User.get_by_id(other_user.id)
1815
1816 assert User.following?(other_user, user) == false
1817
1818 conn =
1819 build_conn()
1820 |> assign(:user, user)
1821 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1822
1823 assert relationship = json_response(conn, 200)
1824 assert other_user.id == relationship["id"]
1825 assert relationship["follows_you"] == true
1826 end
1827 end
1828
1829 describe "POST /api/pleroma/friendships/deny" do
1830 test "it denies a friend request" do
1831 user = insert(:user)
1832 other_user = insert(:user)
1833
1834 {:ok, _activity} = ActivityPub.follow(other_user, user)
1835
1836 user = User.get_by_id(user.id)
1837 other_user = User.get_by_id(other_user.id)
1838
1839 assert User.following?(other_user, user) == false
1840
1841 conn =
1842 build_conn()
1843 |> assign(:user, user)
1844 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1845
1846 assert relationship = json_response(conn, 200)
1847 assert other_user.id == relationship["id"]
1848 assert relationship["follows_you"] == false
1849 end
1850 end
1851
1852 describe "GET /api/pleroma/search_user" do
1853 test "it returns users, ordered by similarity", %{conn: conn} do
1854 user = insert(:user, %{name: "eal"})
1855 user_two = insert(:user, %{name: "eal me"})
1856 _user_three = insert(:user, %{name: "zzz"})
1857
1858 resp =
1859 conn
1860 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1861 |> json_response(200)
1862
1863 assert length(resp) == 2
1864 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1865 end
1866 end
1867
1868 describe "POST /api/media/upload" do
1869 setup context do
1870 Pleroma.DataCase.ensure_local_uploader(context)
1871 end
1872
1873 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1874 conn: conn
1875 } do
1876 user = insert(:user)
1877
1878 upload_filename = "test/fixtures/image_tmp.jpg"
1879 File.cp!("test/fixtures/image.jpg", upload_filename)
1880
1881 file = %Plug.Upload{
1882 content_type: "image/jpg",
1883 path: Path.absname(upload_filename),
1884 filename: "image.jpg"
1885 }
1886
1887 response =
1888 conn
1889 |> assign(:user, user)
1890 |> put_req_header("content-type", "application/octet-stream")
1891 |> post("/api/media/upload", %{
1892 "media" => file
1893 })
1894 |> json_response(:ok)
1895
1896 assert response["media_id"]
1897 object = Repo.get(Object, response["media_id"])
1898 assert object
1899 assert object.data["actor"] == User.ap_id(user)
1900 end
1901 end
1902
1903 describe "POST /api/media/metadata/create" do
1904 setup do
1905 object = insert(:note)
1906 user = User.get_by_ap_id(object.data["actor"])
1907 %{object: object, user: user}
1908 end
1909
1910 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1911 conn: conn,
1912 object: object
1913 } do
1914 initial_description = object.data["name"]
1915 another_user = insert(:user)
1916
1917 conn
1918 |> assign(:user, another_user)
1919 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1920 |> json_response(:forbidden)
1921
1922 object = Repo.get(Object, object.id)
1923 assert object.data["name"] == initial_description
1924 end
1925
1926 test "it updates `data[name]` of referenced Object with provided value", %{
1927 conn: conn,
1928 object: object,
1929 user: user
1930 } do
1931 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1932
1933 conn
1934 |> assign(:user, user)
1935 |> post("/api/media/metadata/create", %{
1936 "media_id" => object.id,
1937 "alt_text" => %{"text" => description}
1938 })
1939 |> json_response(:no_content)
1940
1941 object = Repo.get(Object, object.id)
1942 assert object.data["name"] == description
1943 end
1944 end
1945
1946 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
1947 test "it returns a list of pinned statuses", %{conn: conn} do
1948 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1949
1950 user = insert(:user, %{name: "egor"})
1951 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
1952 {:ok, _} = CommonAPI.pin(activity_id, user)
1953
1954 resp =
1955 conn
1956 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
1957 |> json_response(200)
1958
1959 assert length(resp) == 1
1960 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
1961 end
1962 end
1963
1964 describe "POST /api/statuses/pin/:id" do
1965 setup do
1966 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1967 [user: insert(:user)]
1968 end
1969
1970 test "without valid credentials", %{conn: conn} do
1971 note_activity = insert(:note_activity)
1972 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
1973 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1974 end
1975
1976 test "with credentials", %{conn: conn, user: user} do
1977 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
1978
1979 request_path = "/api/statuses/pin/#{activity.id}.json"
1980
1981 response =
1982 conn
1983 |> with_credentials(user.nickname, "test")
1984 |> post(request_path)
1985
1986 user = refresh_record(user)
1987
1988 assert json_response(response, 200) ==
1989 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
1990 end
1991 end
1992
1993 describe "POST /api/statuses/unpin/:id" do
1994 setup do
1995 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1996 [user: insert(:user)]
1997 end
1998
1999 test "without valid credentials", %{conn: conn} do
2000 note_activity = insert(:note_activity)
2001 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2002 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2003 end
2004
2005 test "with credentials", %{conn: conn, user: user} do
2006 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2007 {:ok, activity} = CommonAPI.pin(activity.id, user)
2008
2009 request_path = "/api/statuses/unpin/#{activity.id}.json"
2010
2011 response =
2012 conn
2013 |> with_credentials(user.nickname, "test")
2014 |> post(request_path)
2015
2016 user = refresh_record(user)
2017
2018 assert json_response(response, 200) ==
2019 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2020 end
2021 end
2022
2023 describe "GET /api/oauth_tokens" do
2024 setup do
2025 token = insert(:oauth_token) |> Repo.preload(:user)
2026
2027 %{token: token}
2028 end
2029
2030 test "renders list", %{token: token} do
2031 response =
2032 build_conn()
2033 |> assign(:user, token.user)
2034 |> get("/api/oauth_tokens")
2035
2036 keys =
2037 json_response(response, 200)
2038 |> hd()
2039 |> Map.keys()
2040
2041 assert keys -- ["id", "app_name", "valid_until"] == []
2042 end
2043
2044 test "revoke token", %{token: token} do
2045 response =
2046 build_conn()
2047 |> assign(:user, token.user)
2048 |> delete("/api/oauth_tokens/#{token.id}")
2049
2050 tokens = Token.get_user_tokens(token.user)
2051
2052 assert tokens == []
2053 assert response.status == 201
2054 end
2055 end
2056 end