Merge remote-tracking branch 'upstream/develop' into admin-create-users
[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 = Repo.get!(User, user.id)
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 locks an account", %{conn: conn} do
1552 user = insert(:user)
1553
1554 conn =
1555 conn
1556 |> assign(:user, user)
1557 |> post("/api/account/update_profile.json", %{
1558 "locked" => "true"
1559 })
1560
1561 user = Repo.get!(User, user.id)
1562 assert user.info.locked == true
1563
1564 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1565 end
1566
1567 test "it unlocks an account", %{conn: conn} do
1568 user = insert(:user)
1569
1570 conn =
1571 conn
1572 |> assign(:user, user)
1573 |> post("/api/account/update_profile.json", %{
1574 "locked" => "false"
1575 })
1576
1577 user = Repo.get!(User, user.id)
1578 assert user.info.locked == false
1579
1580 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1581 end
1582
1583 # Broken before the change to class="emoji" and non-<img/> in the DB
1584 @tag :skip
1585 test "it formats emojos", %{conn: conn} do
1586 user = insert(:user)
1587
1588 conn =
1589 conn
1590 |> assign(:user, user)
1591 |> post("/api/account/update_profile.json", %{
1592 "bio" => "I love our :moominmamma:​"
1593 })
1594
1595 assert response = json_response(conn, 200)
1596
1597 assert %{
1598 "description" => "I love our :moominmamma:",
1599 "description_html" =>
1600 ~s{I love our <img class="emoji" alt="moominmamma" title="moominmamma" src="} <>
1601 _
1602 } = response
1603
1604 conn =
1605 conn
1606 |> get("/api/users/show.json?user_id=#{user.nickname}")
1607
1608 assert response == json_response(conn, 200)
1609 end
1610 end
1611
1612 defp valid_user(_context) do
1613 user = insert(:user)
1614 [user: user]
1615 end
1616
1617 defp with_credentials(conn, username, password) do
1618 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1619 put_req_header(conn, "authorization", header_content)
1620 end
1621
1622 describe "GET /api/search.json" do
1623 test "it returns search results", %{conn: conn} do
1624 user = insert(:user)
1625 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1626
1627 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1628 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1629
1630 conn =
1631 conn
1632 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1633
1634 assert [status] = json_response(conn, 200)
1635 assert status["id"] == activity.id
1636 end
1637 end
1638
1639 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1640 test "it returns the tags timeline", %{conn: conn} do
1641 user = insert(:user)
1642 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1643
1644 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1645 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1646
1647 conn =
1648 conn
1649 |> get("/api/statusnet/tags/timeline/2hu.json")
1650
1651 assert [status] = json_response(conn, 200)
1652 assert status["id"] == activity.id
1653 end
1654 end
1655
1656 test "Convert newlines to <br> in bio", %{conn: conn} do
1657 user = insert(:user)
1658
1659 _conn =
1660 conn
1661 |> assign(:user, user)
1662 |> post("/api/account/update_profile.json", %{
1663 "description" => "Hello,\r\nWorld! I\n am a test."
1664 })
1665
1666 user = Repo.get!(User, user.id)
1667 assert user.bio == "Hello,<br>World! I<br> am a test."
1668 end
1669
1670 describe "POST /api/pleroma/change_password" do
1671 setup [:valid_user]
1672
1673 test "without credentials", %{conn: conn} do
1674 conn = post(conn, "/api/pleroma/change_password")
1675 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1676 end
1677
1678 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1679 conn =
1680 conn
1681 |> with_credentials(current_user.nickname, "test")
1682 |> post("/api/pleroma/change_password", %{
1683 "password" => "hi",
1684 "new_password" => "newpass",
1685 "new_password_confirmation" => "newpass"
1686 })
1687
1688 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1689 end
1690
1691 test "with credentials, valid password and new password and confirmation not matching", %{
1692 conn: conn,
1693 user: current_user
1694 } do
1695 conn =
1696 conn
1697 |> with_credentials(current_user.nickname, "test")
1698 |> post("/api/pleroma/change_password", %{
1699 "password" => "test",
1700 "new_password" => "newpass",
1701 "new_password_confirmation" => "notnewpass"
1702 })
1703
1704 assert json_response(conn, 200) == %{
1705 "error" => "New password does not match confirmation."
1706 }
1707 end
1708
1709 test "with credentials, valid password and invalid new password", %{
1710 conn: conn,
1711 user: current_user
1712 } do
1713 conn =
1714 conn
1715 |> with_credentials(current_user.nickname, "test")
1716 |> post("/api/pleroma/change_password", %{
1717 "password" => "test",
1718 "new_password" => "",
1719 "new_password_confirmation" => ""
1720 })
1721
1722 assert json_response(conn, 200) == %{
1723 "error" => "New password can't be blank."
1724 }
1725 end
1726
1727 test "with credentials, valid password and matching new password and confirmation", %{
1728 conn: conn,
1729 user: current_user
1730 } do
1731 conn =
1732 conn
1733 |> with_credentials(current_user.nickname, "test")
1734 |> post("/api/pleroma/change_password", %{
1735 "password" => "test",
1736 "new_password" => "newpass",
1737 "new_password_confirmation" => "newpass"
1738 })
1739
1740 assert json_response(conn, 200) == %{"status" => "success"}
1741 fetched_user = User.get_cached_by_id(current_user.id)
1742 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1743 end
1744 end
1745
1746 describe "POST /api/pleroma/delete_account" do
1747 setup [:valid_user]
1748
1749 test "without credentials", %{conn: conn} do
1750 conn = post(conn, "/api/pleroma/delete_account")
1751 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1752 end
1753
1754 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1755 conn =
1756 conn
1757 |> with_credentials(current_user.nickname, "test")
1758 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1759
1760 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1761 end
1762
1763 test "with credentials and valid password", %{conn: conn, user: current_user} do
1764 conn =
1765 conn
1766 |> with_credentials(current_user.nickname, "test")
1767 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1768
1769 assert json_response(conn, 200) == %{"status" => "success"}
1770 # Wait a second for the started task to end
1771 :timer.sleep(1000)
1772 end
1773 end
1774
1775 describe "GET /api/pleroma/friend_requests" do
1776 test "it lists friend requests" do
1777 user = insert(:user)
1778 other_user = insert(:user)
1779
1780 {:ok, _activity} = ActivityPub.follow(other_user, user)
1781
1782 user = User.get_cached_by_id(user.id)
1783 other_user = User.get_cached_by_id(other_user.id)
1784
1785 assert User.following?(other_user, user) == false
1786
1787 conn =
1788 build_conn()
1789 |> assign(:user, user)
1790 |> get("/api/pleroma/friend_requests")
1791
1792 assert [relationship] = json_response(conn, 200)
1793 assert other_user.id == relationship["id"]
1794 end
1795
1796 test "requires 'read' permission", %{conn: conn} do
1797 token1 = insert(:oauth_token, scopes: ["write"])
1798 token2 = insert(:oauth_token, scopes: ["read"])
1799
1800 for token <- [token1, token2] do
1801 conn =
1802 conn
1803 |> put_req_header("authorization", "Bearer #{token.token}")
1804 |> get("/api/pleroma/friend_requests")
1805
1806 if token == token1 do
1807 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1808 else
1809 assert json_response(conn, 200)
1810 end
1811 end
1812 end
1813 end
1814
1815 describe "POST /api/pleroma/friendships/approve" do
1816 test "it approves a friend request" do
1817 user = insert(:user)
1818 other_user = insert(:user)
1819
1820 {:ok, _activity} = ActivityPub.follow(other_user, user)
1821
1822 user = User.get_cached_by_id(user.id)
1823 other_user = User.get_cached_by_id(other_user.id)
1824
1825 assert User.following?(other_user, user) == false
1826
1827 conn =
1828 build_conn()
1829 |> assign(:user, user)
1830 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1831
1832 assert relationship = json_response(conn, 200)
1833 assert other_user.id == relationship["id"]
1834 assert relationship["follows_you"] == true
1835 end
1836 end
1837
1838 describe "POST /api/pleroma/friendships/deny" do
1839 test "it denies 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/deny", %{"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"] == false
1858 end
1859 end
1860
1861 describe "GET /api/pleroma/search_user" do
1862 test "it returns users, ordered by similarity", %{conn: conn} do
1863 user = insert(:user, %{name: "eal"})
1864 user_two = insert(:user, %{name: "eal me"})
1865 _user_three = insert(:user, %{name: "zzz"})
1866
1867 resp =
1868 conn
1869 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1870 |> json_response(200)
1871
1872 assert length(resp) == 2
1873 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1874 end
1875 end
1876
1877 describe "POST /api/media/upload" do
1878 setup context do
1879 Pleroma.DataCase.ensure_local_uploader(context)
1880 end
1881
1882 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1883 conn: conn
1884 } do
1885 user = insert(:user)
1886
1887 upload_filename = "test/fixtures/image_tmp.jpg"
1888 File.cp!("test/fixtures/image.jpg", upload_filename)
1889
1890 file = %Plug.Upload{
1891 content_type: "image/jpg",
1892 path: Path.absname(upload_filename),
1893 filename: "image.jpg"
1894 }
1895
1896 response =
1897 conn
1898 |> assign(:user, user)
1899 |> put_req_header("content-type", "application/octet-stream")
1900 |> post("/api/media/upload", %{
1901 "media" => file
1902 })
1903 |> json_response(:ok)
1904
1905 assert response["media_id"]
1906 object = Repo.get(Object, response["media_id"])
1907 assert object
1908 assert object.data["actor"] == User.ap_id(user)
1909 end
1910 end
1911
1912 describe "POST /api/media/metadata/create" do
1913 setup do
1914 object = insert(:note)
1915 user = User.get_cached_by_ap_id(object.data["actor"])
1916 %{object: object, user: user}
1917 end
1918
1919 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1920 conn: conn,
1921 object: object
1922 } do
1923 initial_description = object.data["name"]
1924 another_user = insert(:user)
1925
1926 conn
1927 |> assign(:user, another_user)
1928 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1929 |> json_response(:forbidden)
1930
1931 object = Repo.get(Object, object.id)
1932 assert object.data["name"] == initial_description
1933 end
1934
1935 test "it updates `data[name]` of referenced Object with provided value", %{
1936 conn: conn,
1937 object: object,
1938 user: user
1939 } do
1940 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1941
1942 conn
1943 |> assign(:user, user)
1944 |> post("/api/media/metadata/create", %{
1945 "media_id" => object.id,
1946 "alt_text" => %{"text" => description}
1947 })
1948 |> json_response(:no_content)
1949
1950 object = Repo.get(Object, object.id)
1951 assert object.data["name"] == description
1952 end
1953 end
1954
1955 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
1956 test "it returns a list of pinned statuses", %{conn: conn} do
1957 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1958
1959 user = insert(:user, %{name: "egor"})
1960 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
1961 {:ok, _} = CommonAPI.pin(activity_id, user)
1962
1963 resp =
1964 conn
1965 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
1966 |> json_response(200)
1967
1968 assert length(resp) == 1
1969 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
1970 end
1971 end
1972
1973 describe "POST /api/statuses/pin/:id" do
1974 setup do
1975 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1976 [user: insert(:user)]
1977 end
1978
1979 test "without valid credentials", %{conn: conn} do
1980 note_activity = insert(:note_activity)
1981 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
1982 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1983 end
1984
1985 test "with credentials", %{conn: conn, user: user} do
1986 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
1987
1988 request_path = "/api/statuses/pin/#{activity.id}.json"
1989
1990 response =
1991 conn
1992 |> with_credentials(user.nickname, "test")
1993 |> post(request_path)
1994
1995 user = refresh_record(user)
1996
1997 assert json_response(response, 200) ==
1998 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
1999 end
2000 end
2001
2002 describe "POST /api/statuses/unpin/:id" do
2003 setup do
2004 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2005 [user: insert(:user)]
2006 end
2007
2008 test "without valid credentials", %{conn: conn} do
2009 note_activity = insert(:note_activity)
2010 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
2011 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
2012 end
2013
2014 test "with credentials", %{conn: conn, user: user} do
2015 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
2016 {:ok, activity} = CommonAPI.pin(activity.id, user)
2017
2018 request_path = "/api/statuses/unpin/#{activity.id}.json"
2019
2020 response =
2021 conn
2022 |> with_credentials(user.nickname, "test")
2023 |> post(request_path)
2024
2025 user = refresh_record(user)
2026
2027 assert json_response(response, 200) ==
2028 ActivityView.render("activity.json", %{user: user, for: user, activity: activity})
2029 end
2030 end
2031
2032 describe "GET /api/oauth_tokens" do
2033 setup do
2034 token = insert(:oauth_token) |> Repo.preload(:user)
2035
2036 %{token: token}
2037 end
2038
2039 test "renders list", %{token: token} do
2040 response =
2041 build_conn()
2042 |> assign(:user, token.user)
2043 |> get("/api/oauth_tokens")
2044
2045 keys =
2046 json_response(response, 200)
2047 |> hd()
2048 |> Map.keys()
2049
2050 assert keys -- ["id", "app_name", "valid_until"] == []
2051 end
2052
2053 test "revoke token", %{token: token} do
2054 response =
2055 build_conn()
2056 |> assign(:user, token.user)
2057 |> delete("/api/oauth_tokens/#{token.id}")
2058
2059 tokens = Token.get_user_tokens(token.user)
2060
2061 assert tokens == []
2062 assert response.status == 201
2063 end
2064 end
2065 end