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