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