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