total rebase
[anni] / test / pleroma / web / mastodon_api / controllers / media_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.MastodonAPI.MediaControllerTest do
6   use Pleroma.Web.ConnCase
7
8   import ExUnit.CaptureLog
9   import Mox
10
11   alias Pleroma.Object
12   alias Pleroma.UnstubbedConfigMock, as: ConfigMock
13   alias Pleroma.User
14   alias Pleroma.Web.ActivityPub.ActivityPub
15
16   describe "Upload media" do
17     setup do: oauth_access(["write:media"])
18
19     setup do
20       ConfigMock
21       |> stub_with(Pleroma.Test.StaticConfig)
22
23       image = %Plug.Upload{
24         content_type: "image/jpeg",
25         path: Path.absname("test/fixtures/image.jpg"),
26         filename: "an_image.jpg"
27       }
28
29       [image: image]
30     end
31
32     setup do: clear_config([:media_proxy])
33     setup do: clear_config([Pleroma.Upload])
34
35     test "/api/v1/media", %{conn: conn, image: image} do
36       desc = "Description of the image"
37
38       media =
39         conn
40         |> put_req_header("content-type", "multipart/form-data")
41         |> post("/api/v1/media", %{"file" => image, "description" => desc})
42         |> json_response_and_validate_schema(:ok)
43
44       assert media["type"] == "image"
45       assert media["description"] == desc
46       assert media["id"]
47
48       object = Object.get_by_id(media["id"])
49       assert object.data["actor"] == User.ap_id(conn.assigns[:user])
50     end
51
52     test "/api/v2/media", %{conn: conn, user: user, image: image} do
53       desc = "Description of the image"
54
55       response =
56         conn
57         |> put_req_header("content-type", "multipart/form-data")
58         |> post("/api/v2/media", %{"file" => image, "description" => desc})
59         |> json_response_and_validate_schema(202)
60
61       assert media_id = response["id"]
62
63       %{conn: conn} = oauth_access(["read:media"], user: user)
64
65       media =
66         conn
67         |> get("/api/v1/media/#{media_id}")
68         |> json_response_and_validate_schema(200)
69
70       assert media["type"] == "image"
71       assert media["description"] == desc
72       assert media["id"]
73
74       object = Object.get_by_id(media["id"])
75       assert object.data["actor"] == user.ap_id
76     end
77
78     test "/api/v2/media, upload_limit", %{conn: conn, user: user} do
79       desc = "Description of the binary"
80
81       upload_limit = Config.get([:instance, :upload_limit]) * 8 + 8
82
83       assert :ok ==
84                File.write(Path.absname("test/tmp/large_binary.data"), <<0::size(upload_limit)>>)
85
86       large_binary = %Plug.Upload{
87         content_type: nil,
88         path: Path.absname("test/tmp/large_binary.data"),
89         filename: "large_binary.data"
90       }
91
92       assert capture_log(fn ->
93                assert %{"error" => "file_too_large"} =
94                         conn
95                         |> put_req_header("content-type", "multipart/form-data")
96                         |> post("/api/v2/media", %{
97                           "file" => large_binary,
98                           "description" => desc
99                         })
100                         |> json_response_and_validate_schema(400)
101              end) =~
102                "[error] Elixir.Pleroma.Upload store (using Pleroma.Uploaders.Local) failed: :file_too_large"
103
104       clear_config([:instance, :upload_limit], upload_limit)
105
106       assert response =
107                conn
108                |> put_req_header("content-type", "multipart/form-data")
109                |> post("/api/v2/media", %{
110                  "file" => large_binary,
111                  "description" => desc
112                })
113                |> json_response_and_validate_schema(202)
114
115       assert media_id = response["id"]
116
117       %{conn: conn} = oauth_access(["read:media"], user: user)
118
119       media =
120         conn
121         |> get("/api/v1/media/#{media_id}")
122         |> json_response_and_validate_schema(200)
123
124       assert media["type"] == "unknown"
125       assert media["description"] == desc
126       assert media["id"]
127
128       assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
129     end
130
131     test "Do not allow nested filename", %{conn: conn, image: image} do
132       image = %Plug.Upload{
133         image
134         | filename: "../../../../../nested/file.jpg"
135       }
136
137       desc = "Description of the image"
138
139       media =
140         conn
141         |> put_req_header("content-type", "multipart/form-data")
142         |> post("/api/v1/media", %{"file" => image, "description" => desc})
143         |> json_response_and_validate_schema(:ok)
144
145       refute Regex.match?(~r"/nested/", media["url"])
146     end
147   end
148
149   describe "Update media description" do
150     setup do: oauth_access(["write:media"])
151
152     setup %{user: actor} do
153       ConfigMock
154       |> stub_with(Pleroma.Test.StaticConfig)
155
156       file = %Plug.Upload{
157         content_type: "image/jpeg",
158         path: Path.absname("test/fixtures/image.jpg"),
159         filename: "an_image.jpg"
160       }
161
162       {:ok, %Object{} = object} =
163         ActivityPub.upload(
164           file,
165           actor: User.ap_id(actor),
166           description: "test-m"
167         )
168
169       [object: object]
170     end
171
172     test "/api/v1/media/:id good request", %{conn: conn, object: object} do
173       media =
174         conn
175         |> put_req_header("content-type", "multipart/form-data")
176         |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
177         |> json_response_and_validate_schema(:ok)
178
179       assert media["description"] == "test-media"
180       assert refresh_record(object).data["name"] == "test-media"
181     end
182   end
183
184   describe "Get media by id (/api/v1/media/:id)" do
185     setup do: oauth_access(["read:media"])
186
187     setup %{user: actor} do
188       ConfigMock
189       |> stub_with(Pleroma.Test.StaticConfig)
190
191       file = %Plug.Upload{
192         content_type: "image/jpeg",
193         path: Path.absname("test/fixtures/image.jpg"),
194         filename: "an_image.jpg"
195       }
196
197       {:ok, %Object{} = object} =
198         ActivityPub.upload(
199           file,
200           actor: User.ap_id(actor),
201           description: "test-media"
202         )
203
204       [object: object]
205     end
206
207     test "it returns media object when requested by owner", %{conn: conn, object: object} do
208       media =
209         conn
210         |> get("/api/v1/media/#{object.id}")
211         |> json_response_and_validate_schema(:ok)
212
213       assert media["description"] == "test-media"
214       assert media["type"] == "image"
215       assert media["id"]
216     end
217
218     test "it returns 403 if media object requested by non-owner", %{object: object, user: user} do
219       %{conn: conn, user: other_user} = oauth_access(["read:media"])
220
221       assert object.data["actor"] == user.ap_id
222       refute user.id == other_user.id
223
224       conn
225       |> get("/api/v1/media/#{object.id}")
226       |> json_response_and_validate_schema(403)
227     end
228   end
229 end