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