4119d1dd8142b03ffe996f3c072b67b66e27bba9
[akkoma] / test / web / twitter_api / twitter_api_controller_test.exs
1 defmodule Pleroma.Web.TwitterAPI.ControllerTest do
2 use Pleroma.Web.ConnCase
3 alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
4 alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
5 alias Pleroma.{Repo, Activity, User, Object, Notification}
6 alias Pleroma.Web.ActivityPub.ActivityPub
7 alias Pleroma.Web.TwitterAPI.UserView
8 alias Pleroma.Web.TwitterAPI.NotificationView
9 alias Pleroma.Web.CommonAPI
10 alias Pleroma.Web.TwitterAPI.TwitterAPI
11 alias Comeonin.Pbkdf2
12
13 import Pleroma.Factory
14
15 describe "POST /api/account/update_profile_banner" do
16 test "it updates the banner", %{conn: conn} do
17 user = insert(:user)
18
19 new_banner =
20 "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
21
22 response =
23 conn
24 |> assign(:user, user)
25 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => new_banner})
26 |> json_response(200)
27
28 user = Repo.get(User, user.id)
29 assert user.info.banner["type"] == "Image"
30 end
31 end
32
33 describe "POST /api/qvitter/update_background_image" do
34 test "it updates the background", %{conn: conn} do
35 user = insert(:user)
36
37 new_bg =
38 "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
39
40 response =
41 conn
42 |> assign(:user, user)
43 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => new_bg})
44 |> json_response(200)
45
46 user = Repo.get(User, user.id)
47 assert user.info.background["type"] == "Image"
48 end
49 end
50
51 describe "POST /api/account/verify_credentials" do
52 setup [:valid_user]
53
54 test "without valid credentials", %{conn: conn} do
55 conn = post(conn, "/api/account/verify_credentials.json")
56 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
57 end
58
59 test "with credentials", %{conn: conn, user: user} do
60 conn =
61 conn
62 |> with_credentials(user.nickname, "test")
63 |> post("/api/account/verify_credentials.json")
64
65 assert response = json_response(conn, 200)
66 assert response == UserView.render("show.json", %{user: user, token: response["token"]})
67 end
68 end
69
70 describe "POST /statuses/update.json" do
71 setup [:valid_user]
72
73 test "without valid credentials", %{conn: conn} do
74 conn = post(conn, "/api/statuses/update.json")
75 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
76 end
77
78 test "with credentials", %{conn: conn, user: user} do
79 conn_with_creds = conn |> with_credentials(user.nickname, "test")
80 request_path = "/api/statuses/update.json"
81
82 error_response = %{
83 "request" => request_path,
84 "error" => "Client must provide a 'status' parameter with a value."
85 }
86
87 conn = conn_with_creds |> post(request_path)
88 assert json_response(conn, 400) == error_response
89
90 conn = conn_with_creds |> post(request_path, %{status: ""})
91 assert json_response(conn, 400) == error_response
92
93 conn = conn_with_creds |> post(request_path, %{status: " "})
94 assert json_response(conn, 400) == error_response
95
96 # we post with visibility private in order to avoid triggering relay
97 conn = conn_with_creds |> post(request_path, %{status: "Nice meme.", visibility: "private"})
98
99 assert json_response(conn, 200) ==
100 ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
101 end
102 end
103
104 describe "GET /statuses/public_timeline.json" do
105 test "returns statuses", %{conn: conn} do
106 user = insert(:user)
107 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
108 ActivityBuilder.insert_list(10, %{}, %{user: user})
109 since_id = List.last(activities).id
110
111 conn =
112 conn
113 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
114
115 response = json_response(conn, 200)
116
117 assert length(response) == 10
118 end
119
120 test "returns 403 to unauthenticated request when the instance is not public" do
121 instance =
122 Application.get_env(:pleroma, :instance)
123 |> Keyword.put(:public, false)
124
125 Application.put_env(:pleroma, :instance, instance)
126
127 conn
128 |> get("/api/statuses/public_timeline.json")
129 |> json_response(403)
130
131 instance =
132 Application.get_env(:pleroma, :instance)
133 |> Keyword.put(:public, true)
134
135 Application.put_env(:pleroma, :instance, instance)
136 end
137
138 test "returns 200 to unauthenticated request when the instance is public" do
139 conn
140 |> get("/api/statuses/public_timeline.json")
141 |> json_response(200)
142 end
143 end
144
145 describe "GET /statuses/public_and_external_timeline.json" do
146 test "returns 403 to unauthenticated request when the instance is not public" 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_and_external_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 unauthenticated request when the instance is public" do
165 conn
166 |> get("/api/statuses/public_and_external_timeline.json")
167 |> json_response(200)
168 end
169 end
170
171 describe "GET /statuses/show/:id.json" do
172 test "returns one status", %{conn: conn} do
173 user = insert(:user)
174 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
175 actor = Repo.get_by!(User, ap_id: activity.data["actor"])
176
177 conn =
178 conn
179 |> get("/api/statuses/show/#{activity.id}.json")
180
181 response = json_response(conn, 200)
182
183 assert response == ActivityRepresenter.to_map(activity, %{user: actor})
184 end
185 end
186
187 describe "GET /users/show.json" do
188 test "gets user with screen_name", %{conn: conn} do
189 user = insert(:user)
190
191 conn =
192 conn
193 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
194
195 response = json_response(conn, 200)
196
197 assert response["id"] == user.id
198 end
199
200 test "gets user with user_id", %{conn: conn} do
201 user = insert(:user)
202
203 conn =
204 conn
205 |> get("/api/users/show.json", %{"user_id" => user.id})
206
207 response = json_response(conn, 200)
208
209 assert response["id"] == user.id
210 end
211
212 test "gets a user for a logged in user", %{conn: conn} do
213 user = insert(:user)
214 logged_in = insert(:user)
215
216 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
217
218 conn =
219 conn
220 |> with_credentials(logged_in.nickname, "test")
221 |> get("/api/users/show.json", %{"user_id" => user.id})
222
223 response = json_response(conn, 200)
224
225 assert response["following"] == true
226 end
227 end
228
229 describe "GET /statusnet/conversation/:id.json" do
230 test "returns the statuses in the conversation", %{conn: conn} do
231 {:ok, _user} = UserBuilder.insert()
232 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
233 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
234 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
235
236 conn =
237 conn
238 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
239
240 response = json_response(conn, 200)
241
242 assert length(response) == 2
243 end
244 end
245
246 describe "GET /statuses/friends_timeline.json" do
247 setup [:valid_user]
248
249 test "without valid credentials", %{conn: conn} do
250 conn = get(conn, "/api/statuses/friends_timeline.json")
251 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
252 end
253
254 test "with credentials", %{conn: conn, user: current_user} do
255 user = insert(:user)
256
257 activities =
258 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
259
260 returned_activities =
261 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
262
263 other_user = insert(:user)
264 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
265 since_id = List.last(activities).id
266
267 current_user =
268 Ecto.Changeset.change(current_user, following: [User.ap_followers(user)])
269 |> Repo.update!()
270
271 conn =
272 conn
273 |> with_credentials(current_user.nickname, "test")
274 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
275
276 response = json_response(conn, 200)
277
278 assert length(response) == 10
279
280 assert response ==
281 Enum.map(returned_activities, fn activity ->
282 ActivityRepresenter.to_map(activity, %{
283 user: User.get_cached_by_ap_id(activity.data["actor"]),
284 for: current_user
285 })
286 end)
287 end
288 end
289
290 describe "GET /statuses/dm_timeline.json" do
291 test "it show direct messages", %{conn: conn} do
292 user_one = insert(:user)
293 user_two = insert(:user)
294
295 {:ok, user_two} = User.follow(user_two, user_one)
296
297 {:ok, direct} =
298 CommonAPI.post(user_one, %{
299 "status" => "Hi @#{user_two.nickname}!",
300 "visibility" => "direct"
301 })
302
303 {:ok, direct_two} =
304 CommonAPI.post(user_two, %{
305 "status" => "Hi @#{user_one.nickname}!",
306 "visibility" => "direct"
307 })
308
309 {:ok, _follower_only} =
310 CommonAPI.post(user_one, %{
311 "status" => "Hi @#{user_two.nickname}!",
312 "visibility" => "private"
313 })
314
315 # Only direct should be visible here
316 res_conn =
317 conn
318 |> assign(:user, user_two)
319 |> get("/api/statuses/dm_timeline.json")
320
321 [status, status_two] = json_response(res_conn, 200)
322 assert status["id"] == direct_two.id
323 assert status_two["id"] == direct.id
324 end
325 end
326
327 describe "GET /statuses/mentions.json" do
328 setup [:valid_user]
329
330 test "without valid credentials", %{conn: conn} do
331 conn = get(conn, "/api/statuses/mentions.json")
332 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
333 end
334
335 test "with credentials", %{conn: conn, user: current_user} do
336 {:ok, activity} =
337 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
338
339 conn =
340 conn
341 |> with_credentials(current_user.nickname, "test")
342 |> get("/api/statuses/mentions.json")
343
344 response = json_response(conn, 200)
345
346 assert length(response) == 1
347
348 assert Enum.at(response, 0) ==
349 ActivityRepresenter.to_map(activity, %{
350 user: current_user,
351 mentioned: [current_user]
352 })
353 end
354 end
355
356 describe "GET /api/qvitter/statuses/notifications.json" do
357 setup [:valid_user]
358
359 test "without valid credentials", %{conn: conn} do
360 conn = get(conn, "/api/qvitter/statuses/notifications.json")
361 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
362 end
363
364 test "with credentials", %{conn: conn, user: current_user} do
365 other_user = insert(:user)
366
367 {:ok, _activity} =
368 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
369
370 conn =
371 conn
372 |> with_credentials(current_user.nickname, "test")
373 |> get("/api/qvitter/statuses/notifications.json")
374
375 response = json_response(conn, 200)
376
377 assert length(response) == 1
378
379 assert response ==
380 NotificationView.render("notification.json", %{
381 notifications: Notification.for_user(current_user),
382 for: current_user
383 })
384 end
385 end
386
387 describe "POST /api/qvitter/statuses/notifications/read" do
388 setup [:valid_user]
389
390 test "without valid credentials", %{conn: conn} do
391 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
392 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
393 end
394
395 test "with credentials, without any params", %{conn: conn, user: current_user} do
396 conn =
397 conn
398 |> with_credentials(current_user.nickname, "test")
399 |> post("/api/qvitter/statuses/notifications/read")
400
401 assert json_response(conn, 400) == %{
402 "error" => "You need to specify latest_id",
403 "request" => "/api/qvitter/statuses/notifications/read"
404 }
405 end
406
407 test "with credentials, with params", %{conn: conn, user: current_user} do
408 other_user = insert(:user)
409
410 {:ok, _activity} =
411 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
412
413 response_conn =
414 conn
415 |> with_credentials(current_user.nickname, "test")
416 |> get("/api/qvitter/statuses/notifications.json")
417
418 [notification] = response = json_response(response_conn, 200)
419
420 assert length(response) == 1
421
422 assert notification["is_seen"] == 0
423
424 response_conn =
425 conn
426 |> with_credentials(current_user.nickname, "test")
427 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
428
429 [notification] = response = json_response(response_conn, 200)
430
431 assert length(response) == 1
432
433 assert notification["is_seen"] == 1
434 end
435 end
436
437 describe "GET /statuses/user_timeline.json" do
438 setup [:valid_user]
439
440 test "without any params", %{conn: conn} do
441 conn = get(conn, "/api/statuses/user_timeline.json")
442
443 assert json_response(conn, 400) == %{
444 "error" => "You need to specify screen_name or user_id",
445 "request" => "/api/statuses/user_timeline.json"
446 }
447 end
448
449 test "with user_id", %{conn: conn} do
450 user = insert(:user)
451 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
452
453 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
454 response = json_response(conn, 200)
455 assert length(response) == 1
456 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
457 end
458
459 test "with screen_name", %{conn: conn} do
460 user = insert(:user)
461 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
462
463 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
464 response = json_response(conn, 200)
465 assert length(response) == 1
466 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
467 end
468
469 test "with credentials", %{conn: conn, user: current_user} do
470 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
471
472 conn =
473 conn
474 |> with_credentials(current_user.nickname, "test")
475 |> get("/api/statuses/user_timeline.json")
476
477 response = json_response(conn, 200)
478
479 assert length(response) == 1
480 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
481 end
482
483 test "with credentials with user_id", %{conn: conn, user: current_user} do
484 user = insert(:user)
485 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
486
487 conn =
488 conn
489 |> with_credentials(current_user.nickname, "test")
490 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
491
492 response = json_response(conn, 200)
493
494 assert length(response) == 1
495 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
496 end
497
498 test "with credentials screen_name", %{conn: conn, user: current_user} do
499 user = insert(:user)
500 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
501
502 conn =
503 conn
504 |> with_credentials(current_user.nickname, "test")
505 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
506
507 response = json_response(conn, 200)
508
509 assert length(response) == 1
510 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
511 end
512 end
513
514 describe "POST /friendships/create.json" do
515 setup [:valid_user]
516
517 test "without valid credentials", %{conn: conn} do
518 conn = post(conn, "/api/friendships/create.json")
519 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
520 end
521
522 test "with credentials", %{conn: conn, user: current_user} do
523 followed = insert(:user)
524
525 conn =
526 conn
527 |> with_credentials(current_user.nickname, "test")
528 |> post("/api/friendships/create.json", %{user_id: followed.id})
529
530 current_user = Repo.get(User, current_user.id)
531 assert User.ap_followers(followed) in current_user.following
532
533 assert json_response(conn, 200) ==
534 UserView.render("show.json", %{user: followed, for: current_user})
535 end
536 end
537
538 describe "POST /friendships/destroy.json" do
539 setup [:valid_user]
540
541 test "without valid credentials", %{conn: conn} do
542 conn = post(conn, "/api/friendships/destroy.json")
543 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
544 end
545
546 test "with credentials", %{conn: conn, user: current_user} do
547 followed = insert(:user)
548
549 {:ok, current_user} = User.follow(current_user, followed)
550 assert User.ap_followers(followed) in current_user.following
551 ActivityPub.follow(current_user, followed)
552
553 conn =
554 conn
555 |> with_credentials(current_user.nickname, "test")
556 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
557
558 current_user = Repo.get(User, current_user.id)
559 assert current_user.following == [current_user.ap_id]
560
561 assert json_response(conn, 200) ==
562 UserView.render("show.json", %{user: followed, for: current_user})
563 end
564 end
565
566 describe "POST /blocks/create.json" do
567 setup [:valid_user]
568
569 test "without valid credentials", %{conn: conn} do
570 conn = post(conn, "/api/blocks/create.json")
571 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
572 end
573
574 test "with credentials", %{conn: conn, user: current_user} do
575 blocked = insert(:user)
576
577 conn =
578 conn
579 |> with_credentials(current_user.nickname, "test")
580 |> post("/api/blocks/create.json", %{user_id: blocked.id})
581
582 current_user = Repo.get(User, current_user.id)
583 assert User.blocks?(current_user, blocked)
584
585 assert json_response(conn, 200) ==
586 UserView.render("show.json", %{user: blocked, for: current_user})
587 end
588 end
589
590 describe "POST /blocks/destroy.json" do
591 setup [:valid_user]
592
593 test "without valid credentials", %{conn: conn} do
594 conn = post(conn, "/api/blocks/destroy.json")
595 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
596 end
597
598 test "with credentials", %{conn: conn, user: current_user} do
599 blocked = insert(:user)
600
601 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
602 assert User.blocks?(current_user, blocked)
603
604 conn =
605 conn
606 |> with_credentials(current_user.nickname, "test")
607 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
608
609 current_user = Repo.get(User, current_user.id)
610 assert current_user.info.blocks == []
611
612 assert json_response(conn, 200) ==
613 UserView.render("show.json", %{user: blocked, for: current_user})
614 end
615 end
616
617 describe "GET /help/test.json" do
618 test "returns \"ok\"", %{conn: conn} do
619 conn = get(conn, "/api/help/test.json")
620 assert json_response(conn, 200) == "ok"
621 end
622 end
623
624 describe "POST /api/qvitter/update_avatar.json" do
625 setup [:valid_user]
626
627 test "without valid credentials", %{conn: conn} do
628 conn = post(conn, "/api/qvitter/update_avatar.json")
629 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
630 end
631
632 test "with credentials", %{conn: conn, user: current_user} do
633 avatar_image = File.read!("test/fixtures/avatar_data_uri")
634
635 conn =
636 conn
637 |> with_credentials(current_user.nickname, "test")
638 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
639
640 current_user = Repo.get(User, current_user.id)
641 assert is_map(current_user.avatar)
642
643 assert json_response(conn, 200) ==
644 UserView.render("show.json", %{user: current_user, for: current_user})
645 end
646 end
647
648 describe "GET /api/qvitter/mutes.json" do
649 setup [:valid_user]
650
651 test "unimplemented mutes without valid credentials", %{conn: conn} do
652 conn = get(conn, "/api/qvitter/mutes.json")
653 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
654 end
655
656 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
657 conn =
658 conn
659 |> with_credentials(current_user.nickname, "test")
660 |> get("/api/qvitter/mutes.json")
661
662 current_user = Repo.get(User, current_user.id)
663
664 assert [] = json_response(conn, 200)
665 end
666 end
667
668 describe "POST /api/favorites/create/:id" do
669 setup [:valid_user]
670
671 test "without valid credentials", %{conn: conn} do
672 note_activity = insert(:note_activity)
673 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
674 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
675 end
676
677 test "with credentials", %{conn: conn, user: current_user} do
678 note_activity = insert(:note_activity)
679
680 conn =
681 conn
682 |> with_credentials(current_user.nickname, "test")
683 |> post("/api/favorites/create/#{note_activity.id}.json")
684
685 assert json_response(conn, 200)
686 end
687
688 test "with credentials, invalid param", %{conn: conn, user: current_user} do
689 conn =
690 conn
691 |> with_credentials(current_user.nickname, "test")
692 |> post("/api/favorites/create/wrong.json")
693
694 assert json_response(conn, 400)
695 end
696
697 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
698 conn =
699 conn
700 |> with_credentials(current_user.nickname, "test")
701 |> post("/api/favorites/create/1.json")
702
703 assert json_response(conn, 500)
704 end
705 end
706
707 describe "POST /api/favorites/destroy/:id" do
708 setup [:valid_user]
709
710 test "without valid credentials", %{conn: conn} do
711 note_activity = insert(:note_activity)
712 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
713 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
714 end
715
716 test "with credentials", %{conn: conn, user: current_user} do
717 note_activity = insert(:note_activity)
718 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
719 ActivityPub.like(current_user, object)
720
721 conn =
722 conn
723 |> with_credentials(current_user.nickname, "test")
724 |> post("/api/favorites/destroy/#{note_activity.id}.json")
725
726 assert json_response(conn, 200)
727 end
728 end
729
730 describe "POST /api/statuses/retweet/:id" do
731 setup [:valid_user]
732
733 test "without valid credentials", %{conn: conn} do
734 note_activity = insert(:note_activity)
735 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
736 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
737 end
738
739 test "with credentials", %{conn: conn, user: current_user} do
740 note_activity = insert(:note_activity)
741
742 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
743
744 response =
745 conn
746 |> with_credentials(current_user.nickname, "test")
747 |> post(request_path)
748
749 activity = Repo.get(Activity, note_activity.id)
750 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
751
752 assert json_response(response, 200) ==
753 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
754 end
755 end
756
757 describe "POST /api/statuses/unretweet/:id" do
758 setup [:valid_user]
759
760 test "without valid credentials", %{conn: conn} do
761 note_activity = insert(:note_activity)
762 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
763 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
764 end
765
766 test "with credentials", %{conn: conn, user: current_user} do
767 note_activity = insert(:note_activity)
768
769 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
770
771 _response =
772 conn
773 |> with_credentials(current_user.nickname, "test")
774 |> post(request_path)
775
776 request_path = String.replace(request_path, "retweet", "unretweet")
777
778 response =
779 conn
780 |> with_credentials(current_user.nickname, "test")
781 |> post(request_path)
782
783 activity = Repo.get(Activity, note_activity.id)
784 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
785
786 assert json_response(response, 200) ==
787 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
788 end
789 end
790
791 describe "POST /api/account/register" do
792 test "it creates a new user", %{conn: conn} do
793 data = %{
794 "nickname" => "lain",
795 "email" => "lain@wired.jp",
796 "fullname" => "lain iwakura",
797 "bio" => "close the world.",
798 "password" => "bear",
799 "confirm" => "bear"
800 }
801
802 conn =
803 conn
804 |> post("/api/account/register", data)
805
806 user = json_response(conn, 200)
807
808 fetched_user = Repo.get_by(User, nickname: "lain")
809 assert user == UserView.render("show.json", %{user: fetched_user})
810 end
811
812 test "it returns errors on a problem", %{conn: conn} do
813 data = %{
814 "email" => "lain@wired.jp",
815 "fullname" => "lain iwakura",
816 "bio" => "close the world.",
817 "password" => "bear",
818 "confirm" => "bear"
819 }
820
821 conn =
822 conn
823 |> post("/api/account/register", data)
824
825 errors = json_response(conn, 400)
826
827 assert is_binary(errors["error"])
828 end
829 end
830
831 describe "GET /api/externalprofile/show" do
832 test "it returns the user", %{conn: conn} do
833 user = insert(:user)
834 other_user = insert(:user)
835
836 conn =
837 conn
838 |> assign(:user, user)
839 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
840
841 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
842 end
843 end
844
845 describe "GET /api/statuses/followers" do
846 test "it returns a user's followers", %{conn: conn} do
847 user = insert(:user)
848 follower_one = insert(:user)
849 follower_two = insert(:user)
850 _not_follower = insert(:user)
851
852 {:ok, follower_one} = User.follow(follower_one, user)
853 {:ok, follower_two} = User.follow(follower_two, user)
854
855 conn =
856 conn
857 |> assign(:user, user)
858 |> get("/api/statuses/followers")
859
860 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
861 result = json_response(conn, 200)
862 assert Enum.sort(expected) == Enum.sort(result)
863 end
864
865 test "it returns a given user's followers with user_id", %{conn: conn} do
866 user = insert(:user)
867 follower_one = insert(:user)
868 follower_two = insert(:user)
869 not_follower = insert(:user)
870
871 {:ok, follower_one} = User.follow(follower_one, user)
872 {:ok, follower_two} = User.follow(follower_two, user)
873
874 conn =
875 conn
876 |> assign(:user, not_follower)
877 |> get("/api/statuses/followers", %{"user_id" => user.id})
878
879 assert MapSet.equal?(
880 MapSet.new(json_response(conn, 200)),
881 MapSet.new(
882 UserView.render("index.json", %{
883 users: [follower_one, follower_two],
884 for: not_follower
885 })
886 )
887 )
888 end
889
890 test "it returns empty for a hidden network", %{conn: conn} do
891 user = insert(:user, %{info: %{hide_network: true}})
892 follower_one = insert(:user)
893 follower_two = insert(:user)
894 not_follower = insert(:user)
895
896 {:ok, follower_one} = User.follow(follower_one, user)
897 {:ok, follower_two} = User.follow(follower_two, user)
898
899 conn =
900 conn
901 |> assign(:user, not_follower)
902 |> get("/api/statuses/followers", %{"user_id" => user.id})
903
904 assert [] == json_response(conn, 200)
905 end
906
907 test "it returns the followers for a hidden network if requested by the user themselves", %{
908 conn: conn
909 } do
910 user = insert(:user, %{info: %{hide_network: true}})
911 follower_one = insert(:user)
912 follower_two = insert(:user)
913 not_follower = insert(:user)
914
915 {:ok, follower_one} = User.follow(follower_one, user)
916 {:ok, follower_two} = User.follow(follower_two, user)
917
918 conn =
919 conn
920 |> assign(:user, user)
921 |> get("/api/statuses/followers", %{"user_id" => user.id})
922
923 refute [] == json_response(conn, 200)
924 end
925 end
926
927 describe "GET /api/statuses/friends" do
928 test "it returns the logged in user's friends", %{conn: conn} do
929 user = insert(:user)
930 followed_one = insert(:user)
931 followed_two = insert(:user)
932 _not_followed = insert(:user)
933
934 {:ok, user} = User.follow(user, followed_one)
935 {:ok, user} = User.follow(user, followed_two)
936
937 conn =
938 conn
939 |> assign(:user, user)
940 |> get("/api/statuses/friends")
941
942 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
943 result = json_response(conn, 200)
944 assert Enum.sort(expected) == Enum.sort(result)
945 end
946
947 test "it returns a given user's friends with user_id", %{conn: conn} do
948 user = insert(:user)
949 followed_one = insert(:user)
950 followed_two = insert(:user)
951 _not_followed = insert(:user)
952
953 {:ok, user} = User.follow(user, followed_one)
954 {:ok, user} = User.follow(user, followed_two)
955
956 conn =
957 conn
958 |> assign(:user, user)
959 |> get("/api/statuses/friends", %{"user_id" => user.id})
960
961 assert MapSet.equal?(
962 MapSet.new(json_response(conn, 200)),
963 MapSet.new(
964 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
965 )
966 )
967 end
968
969 test "it returns empty for a hidden network", %{conn: conn} do
970 user = insert(:user, %{info: %{hide_network: true}})
971 followed_one = insert(:user)
972 followed_two = insert(:user)
973 not_followed = insert(:user)
974
975 {:ok, user} = User.follow(user, followed_one)
976 {:ok, user} = User.follow(user, followed_two)
977
978 conn =
979 conn
980 |> assign(:user, not_followed)
981 |> get("/api/statuses/friends", %{"user_id" => user.id})
982
983 assert [] == json_response(conn, 200)
984 end
985
986 test "it returns friends for a hidden network if the user themselves request it", %{
987 conn: conn
988 } do
989 user = insert(:user, %{info: %{hide_network: true}})
990 followed_one = insert(:user)
991 followed_two = insert(:user)
992 not_followed = insert(:user)
993
994 {:ok, user} = User.follow(user, followed_one)
995 {:ok, user} = User.follow(user, followed_two)
996
997 conn =
998 conn
999 |> assign(:user, user)
1000 |> get("/api/statuses/friends", %{"user_id" => user.id})
1001
1002 refute [] == json_response(conn, 200)
1003 end
1004
1005 test "it returns a given user's friends with screen_name", %{conn: conn} do
1006 user = insert(:user)
1007 followed_one = insert(:user)
1008 followed_two = insert(:user)
1009 _not_followed = insert(:user)
1010
1011 {:ok, user} = User.follow(user, followed_one)
1012 {:ok, user} = User.follow(user, followed_two)
1013
1014 conn =
1015 conn
1016 |> assign(:user, user)
1017 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1018
1019 assert MapSet.equal?(
1020 MapSet.new(json_response(conn, 200)),
1021 MapSet.new(
1022 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1023 )
1024 )
1025 end
1026 end
1027
1028 describe "GET /friends/ids" do
1029 test "it returns a user's friends", %{conn: conn} do
1030 user = insert(:user)
1031 followed_one = insert(:user)
1032 followed_two = insert(:user)
1033 _not_followed = insert(:user)
1034
1035 {:ok, user} = User.follow(user, followed_one)
1036 {:ok, user} = User.follow(user, followed_two)
1037
1038 conn =
1039 conn
1040 |> assign(:user, user)
1041 |> get("/api/friends/ids")
1042
1043 expected = [followed_one.id, followed_two.id]
1044
1045 assert MapSet.equal?(
1046 MapSet.new(Poison.decode!(json_response(conn, 200))),
1047 MapSet.new(expected)
1048 )
1049 end
1050 end
1051
1052 describe "POST /api/account/update_profile.json" do
1053 test "it updates a user's profile", %{conn: conn} do
1054 user = insert(:user)
1055 user2 = insert(:user)
1056
1057 conn =
1058 conn
1059 |> assign(:user, user)
1060 |> post("/api/account/update_profile.json", %{
1061 "name" => "new name",
1062 "description" => "hi @#{user2.nickname}"
1063 })
1064
1065 user = Repo.get!(User, user.id)
1066 assert user.name == "new name"
1067
1068 assert user.bio ==
1069 "hi <span><a data-user='#{user2.id}' class='mention' href='#{user2.ap_id}'>@<span>#{
1070 user2.nickname
1071 }</span></a></span>"
1072
1073 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1074 end
1075
1076 test "it sets and un-sets hide_network", %{conn: conn} do
1077 user = insert(:user)
1078
1079 conn
1080 |> assign(:user, user)
1081 |> post("/api/account/update_profile.json", %{
1082 "hide_network" => "true"
1083 })
1084
1085 user = Repo.get!(User, user.id)
1086 assert user.info.hide_network == true
1087
1088 conn =
1089 conn
1090 |> assign(:user, user)
1091 |> post("/api/account/update_profile.json", %{
1092 "hide_network" => "false"
1093 })
1094
1095 user = Repo.get!(User, user.id)
1096 assert user.info.hide_network == false
1097 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1098 end
1099
1100 test "it locks an account", %{conn: conn} do
1101 user = insert(:user)
1102
1103 conn =
1104 conn
1105 |> assign(:user, user)
1106 |> post("/api/account/update_profile.json", %{
1107 "locked" => "true"
1108 })
1109
1110 user = Repo.get!(User, user.id)
1111 assert user.info.locked == true
1112
1113 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1114 end
1115
1116 test "it unlocks an account", %{conn: conn} do
1117 user = insert(:user)
1118
1119 conn =
1120 conn
1121 |> assign(:user, user)
1122 |> post("/api/account/update_profile.json", %{
1123 "locked" => "false"
1124 })
1125
1126 user = Repo.get!(User, user.id)
1127 assert user.info.locked == false
1128
1129 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1130 end
1131 end
1132
1133 defp valid_user(_context) do
1134 user = insert(:user)
1135 [user: user]
1136 end
1137
1138 defp with_credentials(conn, username, password) do
1139 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1140 put_req_header(conn, "authorization", header_content)
1141 end
1142
1143 describe "GET /api/search.json" do
1144 test "it returns search results", %{conn: conn} do
1145 user = insert(:user)
1146 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1147
1148 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1149 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1150
1151 conn =
1152 conn
1153 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1154
1155 assert [status] = json_response(conn, 200)
1156 assert status["id"] == activity.id
1157 end
1158 end
1159
1160 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1161 test "it returns the tags timeline", %{conn: conn} do
1162 user = insert(:user)
1163 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1164
1165 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1166 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1167
1168 conn =
1169 conn
1170 |> get("/api/statusnet/tags/timeline/2hu.json")
1171
1172 assert [status] = json_response(conn, 200)
1173 assert status["id"] == activity.id
1174 end
1175 end
1176
1177 test "Convert newlines to <br> in bio", %{conn: conn} do
1178 user = insert(:user)
1179
1180 _conn =
1181 conn
1182 |> assign(:user, user)
1183 |> post("/api/account/update_profile.json", %{
1184 "description" => "Hello,\r\nWorld! I\n am a test."
1185 })
1186
1187 user = Repo.get!(User, user.id)
1188 assert user.bio == "Hello,<br>World! I<br> am a test."
1189 end
1190
1191 describe "POST /api/pleroma/change_password" do
1192 setup [:valid_user]
1193
1194 test "without credentials", %{conn: conn} do
1195 conn = post(conn, "/api/pleroma/change_password")
1196 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1197 end
1198
1199 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1200 conn =
1201 conn
1202 |> with_credentials(current_user.nickname, "test")
1203 |> post("/api/pleroma/change_password", %{
1204 "password" => "hi",
1205 "new_password" => "newpass",
1206 "new_password_confirmation" => "newpass"
1207 })
1208
1209 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1210 end
1211
1212 test "with credentials, valid password and new password and confirmation not matching", %{
1213 conn: conn,
1214 user: current_user
1215 } do
1216 conn =
1217 conn
1218 |> with_credentials(current_user.nickname, "test")
1219 |> post("/api/pleroma/change_password", %{
1220 "password" => "test",
1221 "new_password" => "newpass",
1222 "new_password_confirmation" => "notnewpass"
1223 })
1224
1225 assert json_response(conn, 200) == %{
1226 "error" => "New password does not match confirmation."
1227 }
1228 end
1229
1230 test "with credentials, valid password and invalid new password", %{
1231 conn: conn,
1232 user: current_user
1233 } do
1234 conn =
1235 conn
1236 |> with_credentials(current_user.nickname, "test")
1237 |> post("/api/pleroma/change_password", %{
1238 "password" => "test",
1239 "new_password" => "",
1240 "new_password_confirmation" => ""
1241 })
1242
1243 assert json_response(conn, 200) == %{
1244 "error" => "New password can't be blank."
1245 }
1246 end
1247
1248 test "with credentials, valid password and matching new password and confirmation", %{
1249 conn: conn,
1250 user: current_user
1251 } do
1252 conn =
1253 conn
1254 |> with_credentials(current_user.nickname, "test")
1255 |> post("/api/pleroma/change_password", %{
1256 "password" => "test",
1257 "new_password" => "newpass",
1258 "new_password_confirmation" => "newpass"
1259 })
1260
1261 assert json_response(conn, 200) == %{"status" => "success"}
1262 fetched_user = Repo.get(User, current_user.id)
1263 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1264 end
1265 end
1266
1267 describe "POST /api/pleroma/delete_account" do
1268 setup [:valid_user]
1269
1270 test "without credentials", %{conn: conn} do
1271 conn = post(conn, "/api/pleroma/delete_account")
1272 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1273 end
1274
1275 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1276 conn =
1277 conn
1278 |> with_credentials(current_user.nickname, "test")
1279 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1280
1281 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1282 end
1283
1284 test "with credentials and valid password", %{conn: conn, user: current_user} do
1285 conn =
1286 conn
1287 |> with_credentials(current_user.nickname, "test")
1288 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1289
1290 assert json_response(conn, 200) == %{"status" => "success"}
1291 # Wait a second for the started task to end
1292 :timer.sleep(1000)
1293 end
1294 end
1295
1296 describe "GET /api/pleroma/friend_requests" do
1297 test "it lists friend requests" do
1298 user = insert(:user)
1299 other_user = insert(:user)
1300
1301 {:ok, _activity} = ActivityPub.follow(other_user, user)
1302
1303 user = Repo.get(User, user.id)
1304 other_user = Repo.get(User, other_user.id)
1305
1306 assert User.following?(other_user, user) == false
1307
1308 conn =
1309 build_conn()
1310 |> assign(:user, user)
1311 |> get("/api/pleroma/friend_requests")
1312
1313 assert [relationship] = json_response(conn, 200)
1314 assert other_user.id == relationship["id"]
1315 end
1316 end
1317
1318 describe "POST /api/pleroma/friendships/approve" do
1319 test "it approves a friend request" do
1320 user = insert(:user)
1321 other_user = insert(:user)
1322
1323 {:ok, _activity} = ActivityPub.follow(other_user, user)
1324
1325 user = Repo.get(User, user.id)
1326 other_user = Repo.get(User, other_user.id)
1327
1328 assert User.following?(other_user, user) == false
1329
1330 conn =
1331 build_conn()
1332 |> assign(:user, user)
1333 |> post("/api/pleroma/friendships/approve", %{"user_id" => to_string(other_user.id)})
1334
1335 assert relationship = json_response(conn, 200)
1336 assert other_user.id == relationship["id"]
1337 assert relationship["follows_you"] == true
1338 end
1339 end
1340
1341 describe "POST /api/pleroma/friendships/deny" do
1342 test "it denies a friend request" do
1343 user = insert(:user)
1344 other_user = insert(:user)
1345
1346 {:ok, _activity} = ActivityPub.follow(other_user, user)
1347
1348 user = Repo.get(User, user.id)
1349 other_user = Repo.get(User, other_user.id)
1350
1351 assert User.following?(other_user, user) == false
1352
1353 conn =
1354 build_conn()
1355 |> assign(:user, user)
1356 |> post("/api/pleroma/friendships/deny", %{"user_id" => to_string(other_user.id)})
1357
1358 assert relationship = json_response(conn, 200)
1359 assert other_user.id == relationship["id"]
1360 assert relationship["follows_you"] == false
1361 end
1362 end
1363
1364 describe "GET /api/pleroma/search_user" do
1365 test "it returns users, ordered by similarity", %{conn: conn} do
1366 user = insert(:user, %{name: "eal"})
1367 user_two = insert(:user, %{name: "ean"})
1368 user_three = insert(:user, %{name: "ebn"})
1369
1370 resp =
1371 conn
1372 |> get(twitter_api_search__path(conn, :search_user), query: "eal")
1373 |> json_response(200)
1374
1375 assert length(resp) == 3
1376 assert [user.id, user_two.id, user_three.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1377 end
1378 end
1379
1380 describe "POST /api/media/upload" do
1381 setup context do
1382 Pleroma.DataCase.ensure_local_uploader(context)
1383 end
1384
1385 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1386 conn: conn
1387 } do
1388 user = insert(:user)
1389
1390 upload_filename = "test/fixtures/image_tmp.jpg"
1391 File.cp!("test/fixtures/image.jpg", upload_filename)
1392
1393 file = %Plug.Upload{
1394 content_type: "image/jpg",
1395 path: Path.absname(upload_filename),
1396 filename: "image.jpg"
1397 }
1398
1399 response =
1400 conn
1401 |> assign(:user, user)
1402 |> put_req_header("content-type", "application/octet-stream")
1403 |> post("/api/media/upload", %{
1404 "media" => file
1405 })
1406 |> json_response(:ok)
1407
1408 assert response["media_id"]
1409 object = Repo.get(Object, response["media_id"])
1410 assert object
1411 assert object.data["actor"] == User.ap_id(user)
1412 end
1413 end
1414
1415 describe "POST /api/media/metadata/create" do
1416 setup do
1417 object = insert(:note)
1418 user = User.get_by_ap_id(object.data["actor"])
1419 %{object: object, user: user}
1420 end
1421
1422 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1423 conn: conn,
1424 object: object
1425 } do
1426 initial_description = object.data["name"]
1427 another_user = insert(:user)
1428
1429 conn
1430 |> assign(:user, another_user)
1431 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1432 |> json_response(:forbidden)
1433
1434 object = Repo.get(Object, object.id)
1435 assert object.data["name"] == initial_description
1436 end
1437
1438 test "it updates `data[name]` of referenced Object with provided value", %{
1439 conn: conn,
1440 object: object,
1441 user: user
1442 } do
1443 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1444
1445 conn
1446 |> assign(:user, user)
1447 |> post("/api/media/metadata/create", %{
1448 "media_id" => object.id,
1449 "alt_text" => %{"text" => description}
1450 })
1451 |> json_response(:no_content)
1452
1453 object = Repo.get(Object, object.id)
1454 assert object.data["name"] == description
1455 end
1456 end
1457 end