diff --git a/config/config.exs b/config/config.exs index d911236fd..f117bea40 100644 --- a/config/config.exs +++ b/config/config.exs @@ -23,7 +23,7 @@ config :mobilizon, :instance, # Federation is to be activated with Mobilizon 1.0.0-beta.2 federating: false, remote_limit: 100_000, - upload_limit: 16_000_000, + upload_limit: 10_000_000, avatar_upload_limit: 2_000_000, banner_upload_limit: 4_000_000, email_from: System.get_env("MOBILIZON_INSTANCE_EMAIL") || "noreply@localhost", @@ -44,7 +44,10 @@ config :mobilizon, MobilizonWeb.Endpoint, # Upload configuration config :mobilizon, MobilizonWeb.Upload, uploader: MobilizonWeb.Uploaders.Local, - filters: [MobilizonWeb.Upload.Filter.Dedupe], + filters: [ + MobilizonWeb.Upload.Filter.Dedupe, + MobilizonWeb.Upload.Filter.Optimize + ], link_name: true, proxy_remote: false, proxy_opts: [ diff --git a/js/src/components/PictureUpload.vue b/js/src/components/PictureUpload.vue index ff36df43e..80ad8bee9 100644 --- a/js/src/components/PictureUpload.vue +++ b/js/src/components/PictureUpload.vue @@ -53,7 +53,7 @@ import { Component, Model, Prop, Vue, Watch } from 'vue-property-decorator'; @Component export default class PictureUpload extends Vue { @Model('change', { type: File }) readonly pictureFile!: File; - @Prop({ type: String, required: false, default: 'image/png,image/jpeg' }) accept; + @Prop({ type: String, required: false, default: 'image/gif,image/png,image/jpeg,image/webp' }) accept; // @ts-ignore @Prop({ type: String, required: false, default() { return this.$t('Avatar'); } }) textFallback!: string; diff --git a/lib/mobilizon_web/endpoint.ex b/lib/mobilizon_web/endpoint.ex index 82327333b..1ff261e7a 100644 --- a/lib/mobilizon_web/endpoint.ex +++ b/lib/mobilizon_web/endpoint.ex @@ -41,7 +41,7 @@ defmodule MobilizonWeb.Endpoint do plug( Plug.Parsers, - parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser], + parsers: [:urlencoded, {:multipart, length: 10_000_000}, :json, Absinthe.Plug.Parser], pass: ["*/*"], json_decoder: Jason ) diff --git a/lib/mobilizon_web/upload.ex b/lib/mobilizon_web/upload.ex index 6c32f2898..67c982034 100644 --- a/lib/mobilizon_web/upload.ex +++ b/lib/mobilizon_web/upload.ex @@ -166,7 +166,7 @@ defmodule MobilizonWeb.Upload do defp check_file_size(_, _), do: :ok - @picture_content_types ["image/png", "image/jpg", "image/jpeg", "image/webp"] + @picture_content_types ["image/gif", "image/png", "image/jpg", "image/jpeg", "image/webp"] # Return whether the upload is a picture or not defp get_type(content_type) do if content_type in @picture_content_types do diff --git a/lib/mobilizon_web/upload/filter/optimize.ex b/lib/mobilizon_web/upload/filter/optimize.ex new file mode 100644 index 000000000..487c81496 --- /dev/null +++ b/lib/mobilizon_web/upload/filter/optimize.ex @@ -0,0 +1,41 @@ +defmodule MobilizonWeb.Upload.Filter.Optimize do + @moduledoc """ + Handle picture optimizations + """ + + @behaviour MobilizonWeb.Upload.Filter + + alias Mobilizon.Config + + @default_optimizers [ + JpegOptim, + PngQuant, + Optipng, + Svgo, + Gifsicle, + Cwebp + ] + + def filter(%MobilizonWeb.Upload{tempfile: file, content_type: "image" <> _}) do + optimizers = Config.get([__MODULE__, :optimizers], @default_optimizers) + + case ExOptimizer.optimize(file, deps: optimizers) do + {:ok, res} -> + :ok + + {:error, err} -> + require Logger + + Logger.warn( + "Unable to optimize file #{file}. The return from the process was #{inspect(err)}" + ) + + :ok + + err -> + err + end + end + + def filter(_), do: :ok +end diff --git a/mix.exs b/mix.exs index a9a9fd081..f4a2bdff1 100644 --- a/mix.exs +++ b/mix.exs @@ -98,6 +98,7 @@ defmodule Mobilizon.Mixfile do ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"}, {:html_sanitize_ex, "~> 1.3.0"}, {:ex_cldr_dates_times, "~> 2.0"}, + {:ex_optimizer, "~> 0.1"}, # Dev and test dependencies {:phoenix_live_reload, "~> 1.2", only: [:dev, :e2e]}, {:ex_machina, "~> 2.3", only: [:dev, :test]}, diff --git a/mix.lock b/mix.lock index d7876d788..33b2eb293 100644 --- a/mix.lock +++ b/mix.lock @@ -42,12 +42,14 @@ "ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "ex_ical": {:hex, :ex_ical, "0.2.0", "4b928b554614704016cc0c9ee226eb854da9327a1cc460457621ceacb1ac29a6", [:mix], [{:timex, "~> 3.1", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm"}, "ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"}, + "ex_optimizer": {:hex, :ex_optimizer, "0.1.0", "1d12f7ea289092a38a794b84bd2f42c1e0621cb307c0f3e6a7df620839af2937", [:mix], [{:file_info, "~> 0.0.4", [hex: :file_info, repo: "hexpm", optional: false]}], "hexpm"}, "ex_unit_notifier": {:hex, :ex_unit_notifier, "0.1.4", "36a2dcab829f506e01bf17816590680dd1474407926d43e64c1263e627c364b8", [:mix], [], "hexpm"}, "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm"}, "excoveralls": {:hex, :excoveralls, "0.11.2", "0c6f2c8db7683b0caa9d490fb8125709c54580b4255ffa7ad35f3264b075a643", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exgravatar": {:hex, :exgravatar, "2.0.1", "66d595c7d63dd6bbac442c5542a724375ae29144059c6fe093e61553850aace4", [:mix], [], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "exvcr": {:hex, :exvcr, "0.10.4", "ba7ff59af5625c0bad41909b7a94599523c09bbefba5e1d85fb7643889965204", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, + "file_info": {:hex, :file_info, "0.0.4", "2e0e77f211e833f38ead22cb29ce53761d457d80b3ffe0ffe0eb93880b0963b2", [:mix], [{:mimetype_parser, "~> 0.1.2", [hex: :mimetype_parser, repo: "hexpm", optional: false]}], "hexpm"}, "file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"}, "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm"}, "geo": {:hex, :geo, "3.3.2", "30c7b458bcb0ab1ca73a997b26d22c68643d9ffe1726e475e0759499b6024cff", [:mix], [], "hexpm"}, @@ -76,6 +78,7 @@ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, + "mimetype_parser": {:hex, :mimetype_parser, "0.1.3", "628ac9fe56aa7edcedb534d68397dd66674ab82493c8ebe39acb9a19b666099d", [:mix], [], "hexpm"}, "mix_test_watch": {:hex, :mix_test_watch, "0.9.0", "c72132a6071261893518fa08e121e911c9358713f62794a90c95db59042af375", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm"}, "mmdb2_decoder": {:hex, :mmdb2_decoder, "1.1.0", "2e2347521bb3bf6b81b9ee58d3be2199cb68ea42dcbafcd0d8eb40214d2844cf", [:mix], [], "hexpm"}, "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},