total rebase
[anni] / test / pleroma / upload_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.UploadTest do
6   use Pleroma.DataCase
7
8   import ExUnit.CaptureLog
9   import Mox
10
11   alias Pleroma.UnstubbedConfigMock, as: ConfigMock
12   alias Pleroma.Upload
13   alias Pleroma.Uploaders.Uploader
14
15   setup do
16     ConfigMock
17     |> stub_with(Pleroma.Test.StaticConfig)
18
19     :ok
20   end
21
22   @upload_file %Plug.Upload{
23     content_type: "image/jpeg",
24     path: Path.absname("test/fixtures/image_tmp.jpg"),
25     filename: "image.jpg"
26   }
27
28   defmodule TestUploaderBase do
29     def put_file(%{path: path} = _upload, module_name) do
30       task_pid =
31         Task.async(fn ->
32           :timer.sleep(10)
33
34           {Uploader, path}
35           |> :global.whereis_name()
36           |> send({Uploader, self(), {:test}, %{}})
37
38           assert_receive {Uploader, {:test}}, 4_000
39         end)
40
41       Agent.start(fn -> task_pid end, name: module_name)
42
43       :wait_callback
44     end
45   end
46
47   describe "Tried storing a file when http callback response success result" do
48     defmodule TestUploaderSuccess do
49       def http_callback(conn, _params),
50         do: {:ok, conn, {:file, "post-process-file.jpg"}}
51
52       def put_file(upload), do: TestUploaderBase.put_file(upload, __MODULE__)
53     end
54
55     setup do: [uploader: TestUploaderSuccess]
56     setup [:ensure_local_uploader]
57
58     test "it returns file" do
59       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
60
61       assert {:ok, result} = Upload.store(@upload_file)
62
63       assert result ==
64                %{
65                  "id" => result["id"],
66                  "name" => "image.jpg",
67                  "type" => "Document",
68                  "mediaType" => "image/jpeg",
69                  "url" => [
70                    %{
71                      "href" => "http://localhost:4001/media/post-process-file.jpg",
72                      "mediaType" => "image/jpeg",
73                      "type" => "Link"
74                    }
75                  ]
76                }
77
78       Task.await(Agent.get(TestUploaderSuccess, fn task_pid -> task_pid end))
79     end
80   end
81
82   describe "Tried storing a file when http callback response error" do
83     defmodule TestUploaderError do
84       def http_callback(conn, _params), do: {:error, conn, "Errors"}
85
86       def put_file(upload), do: TestUploaderBase.put_file(upload, __MODULE__)
87     end
88
89     setup do: [uploader: TestUploaderError]
90     setup [:ensure_local_uploader]
91
92     test "it returns error" do
93       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
94
95       assert capture_log(fn ->
96                assert Upload.store(@upload_file) == {:error, "Errors"}
97                Task.await(Agent.get(TestUploaderError, fn task_pid -> task_pid end))
98              end) =~
99                "[error] Elixir.Pleroma.Upload store (using Pleroma.UploadTest.TestUploaderError) failed: \"Errors\""
100     end
101   end
102
103   describe "Tried storing a file when http callback doesn't response by timeout" do
104     defmodule(TestUploader, do: def(put_file(_upload), do: :wait_callback))
105     setup do: [uploader: TestUploader]
106     setup [:ensure_local_uploader]
107
108     test "it returns error" do
109       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
110
111       assert capture_log(fn ->
112                assert Upload.store(@upload_file) == {:error, "Uploader callback timeout"}
113              end) =~
114                "[error] Elixir.Pleroma.Upload store (using Pleroma.UploadTest.TestUploader) failed: \"Uploader callback timeout\""
115     end
116   end
117
118   describe "Storing a file with the Local uploader" do
119     setup [:ensure_local_uploader]
120
121     test "does not allow descriptions longer than the post limit" do
122       clear_config([:instance, :description_limit], 2)
123       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
124
125       file = %Plug.Upload{
126         content_type: "image/jpeg",
127         path: Path.absname("test/fixtures/image_tmp.jpg"),
128         filename: "image.jpg"
129       }
130
131       {:error, :description_too_long} = Upload.store(file, description: "123")
132     end
133
134     test "returns a media url" do
135       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
136
137       file = %Plug.Upload{
138         content_type: "image/jpeg",
139         path: Path.absname("test/fixtures/image_tmp.jpg"),
140         filename: "image.jpg"
141       }
142
143       {:ok, data} = Upload.store(file)
144
145       assert %{"url" => [%{"href" => url}]} = data
146
147       assert String.starts_with?(url, Pleroma.Upload.base_url())
148     end
149
150     test "copies the file to the configured folder with deduping" do
151       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
152
153       file = %Plug.Upload{
154         content_type: "image/jpeg",
155         path: Path.absname("test/fixtures/image_tmp.jpg"),
156         filename: "an [image.jpg"
157       }
158
159       {:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.Dedupe])
160
161       assert List.first(data["url"])["href"] ==
162                Pleroma.Upload.base_url() <>
163                  "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
164     end
165
166     test "copies the file to the configured folder without deduping" do
167       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
168
169       file = %Plug.Upload{
170         content_type: "image/jpeg",
171         path: Path.absname("test/fixtures/image_tmp.jpg"),
172         filename: "an [image.jpg"
173       }
174
175       {:ok, data} = Upload.store(file)
176       assert data["name"] == "an [image.jpg"
177     end
178
179     test "fixes incorrect content type when base64 is given" do
180       params = %{
181         img: "data:image/png;base64,#{Base.encode64(File.read!("test/fixtures/image.jpg"))}"
182       }
183
184       {:ok, data} = Upload.store(params)
185       assert hd(data["url"])["mediaType"] == "image/jpeg"
186     end
187
188     test "adds extension when base64 is given" do
189       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
190
191       params = %{
192         img: "data:image/png;base64,#{Base.encode64(File.read!("test/fixtures/image.jpg"))}"
193       }
194
195       {:ok, data} = Upload.store(params)
196       assert String.ends_with?(data["name"], ".jpg")
197     end
198
199     test "copies the file to the configured folder with anonymizing filename" do
200       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
201
202       file = %Plug.Upload{
203         content_type: "image/jpeg",
204         path: Path.absname("test/fixtures/image_tmp.jpg"),
205         filename: "an [image.jpg"
206       }
207
208       {:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.AnonymizeFilename])
209
210       refute data["name"] == "an [image.jpg"
211     end
212
213     test "escapes invalid characters in url" do
214       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
215
216       file = %Plug.Upload{
217         content_type: "image/jpeg",
218         path: Path.absname("test/fixtures/image_tmp.jpg"),
219         filename: "an… image.jpg"
220       }
221
222       {:ok, data} = Upload.store(file)
223       [attachment_url | _] = data["url"]
224
225       assert Path.basename(attachment_url["href"]) == "an%E2%80%A6%20image.jpg"
226     end
227
228     test "escapes reserved uri characters" do
229       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
230
231       file = %Plug.Upload{
232         content_type: "image/jpeg",
233         path: Path.absname("test/fixtures/image_tmp.jpg"),
234         filename: ":?#[]@!$&\\'()*+,;=.jpg"
235       }
236
237       {:ok, data} = Upload.store(file)
238       [attachment_url | _] = data["url"]
239
240       assert Path.basename(attachment_url["href"]) ==
241                "%3A%3F%23%5B%5D%40%21%24%26%5C%27%28%29%2A%2B%2C%3B%3D.jpg"
242     end
243   end
244
245   describe "Setting a custom base_url for uploaded media" do
246     setup do: clear_config([Pleroma.Upload, :base_url], "https://cache.pleroma.social")
247
248     # This seems to be backwards. Skipped for that reason
249     @tag skip: true
250     test "returns a media url with configured base_url" do
251       base_url = Pleroma.Config.get([Pleroma.Upload, :base_url])
252
253       File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
254
255       file = %Plug.Upload{
256         content_type: "image/jpeg",
257         path: Path.absname("test/fixtures/image_tmp.jpg"),
258         filename: "image.jpg"
259       }
260
261       {:ok, data} = Upload.store(file, base_url: base_url)
262
263       assert %{"url" => [%{"href" => url}]} = data
264
265       refute String.starts_with?(url, base_url <> "/media/")
266     end
267   end
268 end