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