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