move to 2.5.5
[anni] / test / pleroma / web / o_status / o_status_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.OStatus.OStatusControllerTest do
6   use Pleroma.Web.ConnCase
7
8   import Pleroma.Factory
9
10   alias Pleroma.Object
11   alias Pleroma.User
12   alias Pleroma.Web.ActivityPub.ActivityPub
13   alias Pleroma.Web.CommonAPI
14   alias Pleroma.Web.Endpoint
15
16   require Pleroma.Constants
17
18   setup_all do
19     Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
20     :ok
21   end
22
23   setup do: clear_config([:static_fe, :enabled], false)
24
25   describe "Mastodon compatibility routes" do
26     setup %{conn: conn} do
27       conn = put_req_header(conn, "accept", "text/html")
28
29       {:ok, object} =
30         %{
31           "type" => "Note",
32           "content" => "hey",
33           "id" => Endpoint.url() <> "/users/raymoo/statuses/999999999",
34           "actor" => Endpoint.url() <> "/users/raymoo",
35           "to" => [Pleroma.Constants.as_public()]
36         }
37         |> Object.create()
38
39       {:ok, activity, _} =
40         %{
41           "id" => object.data["id"] <> "/activity",
42           "type" => "Create",
43           "object" => object.data["id"],
44           "actor" => object.data["actor"],
45           "to" => object.data["to"]
46         }
47         |> ActivityPub.persist(local: true)
48
49       %{conn: conn, activity: activity}
50     end
51
52     test "redirects to /notice/:id for html format", %{conn: conn, activity: activity} do
53       conn = get(conn, "/users/raymoo/statuses/999999999")
54       assert redirected_to(conn) == "/notice/#{activity.id}"
55     end
56
57     test "redirects to /notice/:id for html format for activity", %{
58       conn: conn,
59       activity: activity
60     } do
61       conn = get(conn, "/users/raymoo/statuses/999999999/activity")
62       assert redirected_to(conn) == "/notice/#{activity.id}"
63     end
64   end
65
66   # Note: see ActivityPubControllerTest for JSON format tests
67   describe "GET /objects/:uuid (text/html)" do
68     setup %{conn: conn} do
69       conn = put_req_header(conn, "accept", "text/html")
70       %{conn: conn}
71     end
72
73     test "redirects to /notice/id for html format", %{conn: conn} do
74       note_activity = insert(:note_activity)
75       object = Object.normalize(note_activity, fetch: false)
76       [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
77       url = "/objects/#{uuid}"
78
79       conn = get(conn, url)
80       assert redirected_to(conn) == "/notice/#{note_activity.id}"
81     end
82
83     test "404s on private objects", %{conn: conn} do
84       note_activity = insert(:direct_note_activity)
85       object = Object.normalize(note_activity, fetch: false)
86       [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
87
88       conn
89       |> get("/objects/#{uuid}")
90       |> response(404)
91     end
92
93     test "404s on non-existing objects", %{conn: conn} do
94       conn
95       |> get("/objects/123")
96       |> response(404)
97     end
98   end
99
100   # Note: see ActivityPubControllerTest for JSON format tests
101   describe "GET /activities/:uuid (text/html)" do
102     setup %{conn: conn} do
103       conn = put_req_header(conn, "accept", "text/html")
104       %{conn: conn}
105     end
106
107     test "redirects to /notice/id for html format", %{conn: conn} do
108       note_activity = insert(:note_activity)
109       [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
110
111       conn = get(conn, "/activities/#{uuid}")
112       assert redirected_to(conn) == "/notice/#{note_activity.id}"
113     end
114
115     test "404s on private activities", %{conn: conn} do
116       note_activity = insert(:direct_note_activity)
117       [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
118
119       conn
120       |> get("/activities/#{uuid}")
121       |> response(404)
122     end
123
124     test "404s on nonexistent activities", %{conn: conn} do
125       conn
126       |> get("/activities/123")
127       |> response(404)
128     end
129   end
130
131   describe "GET notice/2" do
132     test "redirects to a proper object URL when json requested and the object is local", %{
133       conn: conn
134     } do
135       note_activity = insert(:note_activity)
136       expected_redirect_url = Object.normalize(note_activity, fetch: false).data["id"]
137
138       redirect_url =
139         conn
140         |> put_req_header("accept", "application/activity+json")
141         |> get("/notice/#{note_activity.id}")
142         |> redirected_to()
143
144       assert redirect_url == expected_redirect_url
145     end
146
147     test "redirects to a proper object URL when json requested and the object is remote", %{
148       conn: conn
149     } do
150       note_activity = insert(:note_activity, local: false)
151       expected_redirect_url = Object.normalize(note_activity, fetch: false).data["id"]
152
153       redirect_url =
154         conn
155         |> put_req_header("accept", "application/activity+json")
156         |> get("/notice/#{note_activity.id}")
157         |> redirected_to()
158
159       assert redirect_url == expected_redirect_url
160     end
161
162     test "500s when actor not found", %{conn: conn} do
163       note_activity = insert(:note_activity)
164       user = User.get_cached_by_ap_id(note_activity.data["actor"])
165       User.invalidate_cache(user)
166       Pleroma.Repo.delete(user)
167
168       conn =
169         conn
170         |> get("/notice/#{note_activity.id}")
171
172       assert response(conn, 500) == ~S({"error":"Something went wrong"})
173     end
174
175     test "render html for redirect for html format", %{conn: conn} do
176       note_activity = insert(:note_activity)
177
178       resp =
179         conn
180         |> put_req_header("accept", "text/html")
181         |> get("/notice/#{note_activity.id}")
182         |> response(200)
183
184       assert resp =~
185                "<meta content=\"#{Pleroma.Web.Endpoint.url()}/notice/#{note_activity.id}\" property=\"og:url\">"
186
187       user = insert(:user)
188
189       {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
190
191       assert like_activity.data["type"] == "Like"
192
193       resp =
194         conn
195         |> put_req_header("accept", "text/html")
196         |> get("/notice/#{like_activity.id}")
197         |> response(200)
198
199       assert resp =~ "<!--server-generated-meta-->"
200     end
201
202     test "404s a private notice", %{conn: conn} do
203       note_activity = insert(:direct_note_activity)
204       url = "/notice/#{note_activity.id}"
205
206       conn =
207         conn
208         |> get(url)
209
210       assert response(conn, 404)
211     end
212
213     test "404s a non-existing notice", %{conn: conn} do
214       url = "/notice/123"
215
216       conn =
217         conn
218         |> get(url)
219
220       assert response(conn, 404)
221     end
222
223     test "does not require authentication on non-federating instances", %{
224       conn: conn
225     } do
226       clear_config([:instance, :federating], false)
227       note_activity = insert(:note_activity)
228
229       conn
230       |> put_req_header("accept", "text/html")
231       |> get("/notice/#{note_activity.id}")
232       |> response(200)
233     end
234   end
235
236   describe "GET /notice/:id/embed_player" do
237     setup do
238       note_activity = insert(:note_activity)
239       object = Pleroma.Object.normalize(note_activity, fetch: false)
240
241       object_data =
242         Map.put(object.data, "attachment", [
243           %{
244             "url" => [
245               %{
246                 "href" =>
247                   "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
248                 "mediaType" => "video/mp4",
249                 "type" => "Link"
250               }
251             ]
252           }
253         ])
254
255       object
256       |> Ecto.Changeset.change(data: object_data)
257       |> Pleroma.Repo.update()
258
259       %{note_activity: note_activity}
260     end
261
262     test "renders embed player", %{conn: conn, note_activity: note_activity} do
263       conn = get(conn, "/notice/#{note_activity.id}/embed_player")
264
265       assert Plug.Conn.get_resp_header(conn, "x-frame-options") == ["ALLOW"]
266
267       assert Plug.Conn.get_resp_header(
268                conn,
269                "content-security-policy"
270              ) == [
271                "default-src 'none';style-src 'self' 'unsafe-inline';img-src 'self' data: https:; media-src 'self' https:;"
272              ]
273
274       assert response(conn, 200) =~
275                "<video controls loop><source src=\"https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4\" type=\"video/mp4\">Your browser does not support video/mp4 playback.</video>"
276     end
277
278     test "404s when activity isn't create", %{conn: conn} do
279       note_activity = insert(:note_activity, data_attrs: %{"type" => "Like"})
280
281       assert conn
282              |> get("/notice/#{note_activity.id}/embed_player")
283              |> response(404)
284     end
285
286     test "404s when activity is direct message", %{conn: conn} do
287       note_activity = insert(:note_activity, data_attrs: %{"directMessage" => true})
288
289       assert conn
290              |> get("/notice/#{note_activity.id}/embed_player")
291              |> response(404)
292     end
293
294     test "404s when attachment is empty", %{conn: conn} do
295       note_activity = insert(:note_activity)
296       object = Pleroma.Object.normalize(note_activity, fetch: false)
297       object_data = Map.put(object.data, "attachment", [])
298
299       object
300       |> Ecto.Changeset.change(data: object_data)
301       |> Pleroma.Repo.update()
302
303       assert conn
304              |> get("/notice/#{note_activity.id}/embed_player")
305              |> response(404)
306     end
307
308     test "404s when attachment isn't audio or video", %{conn: conn} do
309       note_activity = insert(:note_activity)
310       object = Pleroma.Object.normalize(note_activity, fetch: false)
311
312       object_data =
313         Map.put(object.data, "attachment", [
314           %{
315             "url" => [
316               %{
317                 "href" => "https://peertube.moe/static/webseed/480.jpg",
318                 "mediaType" => "image/jpg",
319                 "type" => "Link"
320               }
321             ]
322           }
323         ])
324
325       object
326       |> Ecto.Changeset.change(data: object_data)
327       |> Pleroma.Repo.update()
328
329       conn
330       |> get("/notice/#{note_activity.id}/embed_player")
331       |> response(404)
332     end
333
334     test "does not require authentication on non-federating instances", %{
335       conn: conn,
336       note_activity: note_activity
337     } do
338       clear_config([:instance, :federating], false)
339
340       conn
341       |> put_req_header("accept", "text/html")
342       |> get("/notice/#{note_activity.id}/embed_player")
343       |> response(200)
344     end
345   end
346 end