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