Extract RSS Feed functionality from OStatus
[akkoma] / test / web / ostatus / ostatus_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.OStatus.OStatusControllerTest do
6 use Pleroma.Web.ConnCase
7
8 import ExUnit.CaptureLog
9 import Pleroma.Factory
10
11 alias Pleroma.Object
12 alias Pleroma.User
13 alias Pleroma.Web.CommonAPI
14 alias Pleroma.Web.OStatus.ActivityRepresenter
15
16 setup_all do
17 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
18 :ok
19 end
20
21 clear_config_all([:instance, :federating]) do
22 Pleroma.Config.put([:instance, :federating], true)
23 end
24
25 describe "salmon_incoming" do
26 test "decodes a salmon", %{conn: conn} do
27 user = insert(:user)
28 salmon = File.read!("test/fixtures/salmon.xml")
29
30 assert capture_log(fn ->
31 conn =
32 conn
33 |> put_req_header("content-type", "application/atom+xml")
34 |> post("/users/#{user.nickname}/salmon", salmon)
35
36 assert response(conn, 200)
37 end) =~ "[error]"
38 end
39
40 test "decodes a salmon with a changed magic key", %{conn: conn} do
41 user = insert(:user)
42 salmon = File.read!("test/fixtures/salmon.xml")
43
44 assert capture_log(fn ->
45 conn =
46 conn
47 |> put_req_header("content-type", "application/atom+xml")
48 |> post("/users/#{user.nickname}/salmon", salmon)
49
50 assert response(conn, 200)
51 end) =~ "[error]"
52
53 # Wrong key
54 info = %{
55 magic_key:
56 "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
57 }
58
59 # Set a wrong magic-key for a user so it has to refetch
60 "http://gs.example.org:4040/index.php/user/1"
61 |> User.get_cached_by_ap_id()
62 |> User.update_info(&User.Info.remote_user_creation(&1, info))
63
64 assert capture_log(fn ->
65 conn =
66 build_conn()
67 |> put_req_header("content-type", "application/atom+xml")
68 |> post("/users/#{user.nickname}/salmon", salmon)
69
70 assert response(conn, 200)
71 end) =~ "[error]"
72 end
73 end
74
75 describe "GET object/2" do
76 test "gets an object", %{conn: conn} do
77 note_activity = insert(:note_activity)
78 object = Object.normalize(note_activity)
79 user = User.get_cached_by_ap_id(note_activity.data["actor"])
80 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
81 url = "/objects/#{uuid}"
82
83 conn =
84 conn
85 |> put_req_header("accept", "application/xml")
86 |> get(url)
87
88 expected =
89 ActivityRepresenter.to_simple_form(note_activity, user, true)
90 |> ActivityRepresenter.wrap_with_entry()
91 |> :xmerl.export_simple(:xmerl_xml)
92 |> to_string
93
94 assert response(conn, 200) == expected
95 end
96
97 test "redirects to /notice/id for html format", %{conn: conn} do
98 note_activity = insert(:note_activity)
99 object = Object.normalize(note_activity)
100 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
101 url = "/objects/#{uuid}"
102
103 conn =
104 conn
105 |> put_req_header("accept", "text/html")
106 |> get(url)
107
108 assert redirected_to(conn) == "/notice/#{note_activity.id}"
109 end
110
111 test "500s when user not found", %{conn: conn} do
112 note_activity = insert(:note_activity)
113 object = Object.normalize(note_activity)
114 user = User.get_cached_by_ap_id(note_activity.data["actor"])
115 User.invalidate_cache(user)
116 Pleroma.Repo.delete(user)
117 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
118 url = "/objects/#{uuid}"
119
120 conn =
121 conn
122 |> put_req_header("accept", "application/xml")
123 |> get(url)
124
125 assert response(conn, 500) == ~S({"error":"Something went wrong"})
126 end
127
128 test "404s on private objects", %{conn: conn} do
129 note_activity = insert(:direct_note_activity)
130 object = Object.normalize(note_activity)
131 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
132
133 conn
134 |> get("/objects/#{uuid}")
135 |> response(404)
136 end
137
138 test "404s on nonexisting objects", %{conn: conn} do
139 conn
140 |> get("/objects/123")
141 |> response(404)
142 end
143 end
144
145 describe "GET activity/2" do
146 test "gets an activity in xml format", %{conn: conn} do
147 note_activity = insert(:note_activity)
148 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
149
150 conn
151 |> put_req_header("accept", "application/xml")
152 |> get("/activities/#{uuid}")
153 |> response(200)
154 end
155
156 test "redirects to /notice/id for html format", %{conn: conn} do
157 note_activity = insert(:note_activity)
158 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
159
160 conn =
161 conn
162 |> put_req_header("accept", "text/html")
163 |> get("/activities/#{uuid}")
164
165 assert redirected_to(conn) == "/notice/#{note_activity.id}"
166 end
167
168 test "505s when user not found", %{conn: conn} do
169 note_activity = insert(:note_activity)
170 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
171 user = User.get_cached_by_ap_id(note_activity.data["actor"])
172 User.invalidate_cache(user)
173 Pleroma.Repo.delete(user)
174
175 conn =
176 conn
177 |> put_req_header("accept", "text/html")
178 |> get("/activities/#{uuid}")
179
180 assert response(conn, 500) == ~S({"error":"Something went wrong"})
181 end
182
183 test "404s on deleted objects", %{conn: conn} do
184 note_activity = insert(:note_activity)
185 object = Object.normalize(note_activity)
186 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
187
188 conn
189 |> put_req_header("accept", "application/xml")
190 |> get("/objects/#{uuid}")
191 |> response(200)
192
193 Object.delete(object)
194
195 conn
196 |> put_req_header("accept", "application/xml")
197 |> get("/objects/#{uuid}")
198 |> response(404)
199 end
200
201 test "404s on private activities", %{conn: conn} do
202 note_activity = insert(:direct_note_activity)
203 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
204
205 conn
206 |> get("/activities/#{uuid}")
207 |> response(404)
208 end
209
210 test "404s on nonexistent activities", %{conn: conn} do
211 conn
212 |> get("/activities/123")
213 |> response(404)
214 end
215
216 test "gets an activity in AS2 format", %{conn: conn} do
217 note_activity = insert(:note_activity)
218 [_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
219 url = "/activities/#{uuid}"
220
221 conn =
222 conn
223 |> put_req_header("accept", "application/activity+json")
224 |> get(url)
225
226 assert json_response(conn, 200)
227 end
228 end
229
230 describe "GET notice/2" do
231 test "gets a notice in xml format", %{conn: conn} do
232 note_activity = insert(:note_activity)
233
234 conn
235 |> get("/notice/#{note_activity.id}")
236 |> response(200)
237 end
238
239 test "gets a notice in AS2 format", %{conn: conn} do
240 note_activity = insert(:note_activity)
241
242 conn
243 |> put_req_header("accept", "application/activity+json")
244 |> get("/notice/#{note_activity.id}")
245 |> json_response(200)
246 end
247
248 test "500s when actor not found", %{conn: conn} do
249 note_activity = insert(:note_activity)
250 user = User.get_cached_by_ap_id(note_activity.data["actor"])
251 User.invalidate_cache(user)
252 Pleroma.Repo.delete(user)
253
254 conn =
255 conn
256 |> get("/notice/#{note_activity.id}")
257
258 assert response(conn, 500) == ~S({"error":"Something went wrong"})
259 end
260
261 test "only gets a notice in AS2 format for Create messages", %{conn: conn} do
262 note_activity = insert(:note_activity)
263 url = "/notice/#{note_activity.id}"
264
265 conn =
266 conn
267 |> put_req_header("accept", "application/activity+json")
268 |> get(url)
269
270 assert json_response(conn, 200)
271
272 user = insert(:user)
273
274 {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
275 url = "/notice/#{like_activity.id}"
276
277 assert like_activity.data["type"] == "Like"
278
279 conn =
280 build_conn()
281 |> put_req_header("accept", "application/activity+json")
282 |> get(url)
283
284 assert response(conn, 404)
285 end
286
287 test "render html for redirect for html format", %{conn: conn} do
288 note_activity = insert(:note_activity)
289
290 resp =
291 conn
292 |> put_req_header("accept", "text/html")
293 |> get("/notice/#{note_activity.id}")
294 |> response(200)
295
296 assert resp =~
297 "<meta content=\"#{Pleroma.Web.base_url()}/notice/#{note_activity.id}\" property=\"og:url\">"
298
299 user = insert(:user)
300
301 {:ok, like_activity, _} = CommonAPI.favorite(note_activity.id, user)
302
303 assert like_activity.data["type"] == "Like"
304
305 resp =
306 conn
307 |> put_req_header("accept", "text/html")
308 |> get("/notice/#{like_activity.id}")
309 |> response(200)
310
311 assert resp =~ "<!--server-generated-meta-->"
312 end
313
314 test "404s a private notice", %{conn: conn} do
315 note_activity = insert(:direct_note_activity)
316 url = "/notice/#{note_activity.id}"
317
318 conn =
319 conn
320 |> get(url)
321
322 assert response(conn, 404)
323 end
324
325 test "404s a nonexisting notice", %{conn: conn} do
326 url = "/notice/123"
327
328 conn =
329 conn
330 |> get(url)
331
332 assert response(conn, 404)
333 end
334 end
335
336 describe "GET /notice/:id/embed_player" do
337 test "render embed player", %{conn: conn} do
338 note_activity = insert(:note_activity)
339 object = Pleroma.Object.normalize(note_activity)
340
341 object_data =
342 Map.put(object.data, "attachment", [
343 %{
344 "url" => [
345 %{
346 "href" =>
347 "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4",
348 "mediaType" => "video/mp4",
349 "type" => "Link"
350 }
351 ]
352 }
353 ])
354
355 object
356 |> Ecto.Changeset.change(data: object_data)
357 |> Pleroma.Repo.update()
358
359 conn =
360 conn
361 |> get("/notice/#{note_activity.id}/embed_player")
362
363 assert Plug.Conn.get_resp_header(conn, "x-frame-options") == ["ALLOW"]
364
365 assert Plug.Conn.get_resp_header(
366 conn,
367 "content-security-policy"
368 ) == [
369 "default-src 'none';style-src 'self' 'unsafe-inline';img-src 'self' data: https:; media-src 'self' https:;"
370 ]
371
372 assert response(conn, 200) =~
373 "<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>"
374 end
375
376 test "404s when activity isn't create", %{conn: conn} do
377 note_activity = insert(:note_activity, data_attrs: %{"type" => "Like"})
378
379 assert conn
380 |> get("/notice/#{note_activity.id}/embed_player")
381 |> response(404)
382 end
383
384 test "404s when activity is direct message", %{conn: conn} do
385 note_activity = insert(:note_activity, data_attrs: %{"directMessage" => true})
386
387 assert conn
388 |> get("/notice/#{note_activity.id}/embed_player")
389 |> response(404)
390 end
391
392 test "404s when attachment is empty", %{conn: conn} do
393 note_activity = insert(:note_activity)
394 object = Pleroma.Object.normalize(note_activity)
395 object_data = Map.put(object.data, "attachment", [])
396
397 object
398 |> Ecto.Changeset.change(data: object_data)
399 |> Pleroma.Repo.update()
400
401 assert conn
402 |> get("/notice/#{note_activity.id}/embed_player")
403 |> response(404)
404 end
405
406 test "404s when attachment isn't audio or video", %{conn: conn} do
407 note_activity = insert(:note_activity)
408 object = Pleroma.Object.normalize(note_activity)
409
410 object_data =
411 Map.put(object.data, "attachment", [
412 %{
413 "url" => [
414 %{
415 "href" => "https://peertube.moe/static/webseed/480.jpg",
416 "mediaType" => "image/jpg",
417 "type" => "Link"
418 }
419 ]
420 }
421 ])
422
423 object
424 |> Ecto.Changeset.change(data: object_data)
425 |> Pleroma.Repo.update()
426
427 assert conn
428 |> get("/notice/#{note_activity.id}/embed_player")
429 |> response(404)
430 end
431 end
432 end