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