diff options
| -rw-r--r-- | lib/mix/tasks/pleroma/instance.ex | 15 | ||||
| -rw-r--r-- | lib/pleroma/emoji/pack.ex | 62 | ||||
| -rw-r--r-- | lib/pleroma/utils.ex | 16 | ||||
| -rw-r--r-- | lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex | 3 | ||||
| -rw-r--r-- | lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex | 6 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/account_view.ex | 16 | ||||
| -rw-r--r-- | lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex | 37 | ||||
| -rw-r--r-- | lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex | 63 | ||||
| -rw-r--r-- | priv/gettext/en/LC_MESSAGES/posix_errors.po | 141 | ||||
| -rw-r--r-- | priv/gettext/posix_errors.pot | 149 | ||||
| -rw-r--r-- | priv/gettext/zh_Hans/LC_MESSAGES/errors.po | 128 | ||||
| -rw-r--r-- | test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs | 26 | ||||
| -rw-r--r-- | test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs | 59 | 
13 files changed, 586 insertions, 135 deletions
| diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index ac8688424..853c4eaa2 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -161,12 +161,21 @@ defmodule Mix.Tasks.Pleroma.Instance do          )          |> Path.expand() +      {strip_uploads_message, strip_uploads_default} = +        if Pleroma.Utils.command_available?("exiftool") do +          {"Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as installed. (y/n)", +           "y"} +        else +          {"Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as not installed, please install it if you answer yes. (y/n)", +           "n"} +        end +        strip_uploads =          get_option(            options,            :strip_uploads, -          "Do you want to strip location (GPS) data from uploaded images? (y/n)", -          "y" +          strip_uploads_message, +          strip_uploads_default          ) === "y"        anonymize_uploads = @@ -253,7 +262,7 @@ defmodule Mix.Tasks.Pleroma.Instance do      else        shell_error(          "The task would have overwritten the following files:\n" <> -          (Enum.map(paths, &"- #{&1}\n") |> Enum.join("")) <> +          (Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <>            "Rerun with `--force` to overwrite them."        )      end diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index ca58e5432..f768af19f 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -22,14 +22,14 @@ defmodule Pleroma.Emoji.Pack do    alias Pleroma.Emoji    alias Pleroma.Emoji.Pack +  alias Pleroma.Utils    @spec create(String.t()) :: {:ok, t()} | {:error, File.posix()} | {:error, :empty_values}    def create(name) do      with :ok <- validate_not_empty([name]),           dir <- Path.join(emoji_path(), name),           :ok <- File.mkdir(dir) do -      %__MODULE__{pack_file: Path.join(dir, "pack.json")} -      |> save_pack() +      save_pack(%__MODULE__{pack_file: Path.join(dir, "pack.json")})      end    end @@ -62,10 +62,9 @@ defmodule Pleroma.Emoji.Pack do    @spec delete(String.t()) ::            {:ok, [binary()]} | {:error, File.posix(), binary()} | {:error, :empty_values}    def delete(name) do -    with :ok <- validate_not_empty([name]) do -      emoji_path() -      |> Path.join(name) -      |> File.rm_rf() +    with :ok <- validate_not_empty([name]), +         pack_path <- Path.join(emoji_path(), name) do +      File.rm_rf(pack_path)      end    end @@ -94,7 +93,7 @@ defmodule Pleroma.Emoji.Pack do    def add_file(%Pack{} = pack, _, _, %Plug.Upload{content_type: "application/zip"} = file) do      with {:ok, zip_files} <- :zip.table(to_charlist(file.path)),           [_ | _] = emojies <- unpack_zip_emojies(zip_files), -         {:ok, tmp_dir} <- Pleroma.Utils.tmp_dir("emoji") do +         {:ok, tmp_dir} <- Utils.tmp_dir("emoji") do        try do          {:ok, _emoji_files} =            :zip.unzip( @@ -282,18 +281,21 @@ defmodule Pleroma.Emoji.Pack do      end    end -  @spec load_pack(String.t()) :: {:ok, t()} | {:error, :not_found} +  @spec load_pack(String.t()) :: {:ok, t()} | {:error, :file.posix()}    def load_pack(name) do      pack_file = Path.join([emoji_path(), name, "pack.json"]) -    if File.exists?(pack_file) do +    with {:ok, _} <- File.stat(pack_file), +         {:ok, pack_data} <- File.read(pack_file) do        pack = -        pack_file -        |> File.read!() -        |> from_json() -        |> Map.put(:pack_file, pack_file) -        |> Map.put(:path, Path.dirname(pack_file)) -        |> Map.put(:name, name) +        from_json( +          pack_data, +          %{ +            pack_file: pack_file, +            path: Path.dirname(pack_file), +            name: name +          } +        )        files_count =          pack.files @@ -301,8 +303,6 @@ defmodule Pleroma.Emoji.Pack do          |> length()        {:ok, Map.put(pack, :files_count, files_count)} -    else -      {:error, :not_found}      end    end @@ -434,10 +434,17 @@ defmodule Pleroma.Emoji.Pack do      end    end -  defp from_json(json) do +  defp from_json(json, attrs) do      map = Jason.decode!(json) -    struct(__MODULE__, %{files: map["files"], pack: map["pack"]}) +    pack_attrs = +      attrs +      |> Map.merge(%{ +        files: map["files"], +        pack: map["pack"] +      }) + +    struct(__MODULE__, pack_attrs)    end    defp validate_shareable_packs_available(uri) do @@ -491,10 +498,10 @@ defmodule Pleroma.Emoji.Pack do    end    defp create_subdirs(file_path) do -    if String.contains?(file_path, "/") do -      file_path -      |> Path.dirname() -      |> File.mkdir_p!() +    with true <- String.contains?(file_path, "/"), +         path <- Path.dirname(file_path), +         false <- File.exists?(path) do +      File.mkdir_p!(path)      end    end @@ -518,10 +525,15 @@ defmodule Pleroma.Emoji.Pack do    defp get_filename(pack, shortcode) do      with %{^shortcode => filename} when is_binary(filename) <- pack.files, -         true <- pack.path |> Path.join(filename) |> File.exists?() do +         file_path <- Path.join(pack.path, filename), +         {:ok, _} <- File.stat(file_path) do        {:ok, filename}      else -      _ -> {:error, :doesnt_exist} +      {:error, _} = error -> +        error + +      _ -> +        {:error, :doesnt_exist}      end    end diff --git a/lib/pleroma/utils.ex b/lib/pleroma/utils.ex index e95766223..fa75a8c99 100644 --- a/lib/pleroma/utils.ex +++ b/lib/pleroma/utils.ex @@ -3,6 +3,14 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Utils do +  @posix_error_codes ~w( +    eacces eagain ebadf ebadmsg ebusy edeadlk edeadlock edquot eexist efault +    efbig eftype eintr einval eio eisdir eloop emfile emlink emultihop +    enametoolong enfile enobufs enodev enolck enolink enoent enomem enospc +    enosr enostr enosys enotblk enotdir enotsup enxio eopnotsupp eoverflow +    eperm epipe erange erofs espipe esrch estale etxtbsy exdev +  )a +    def compile_dir(dir) when is_binary(dir) do      dir      |> File.ls!() @@ -44,4 +52,12 @@ defmodule Pleroma.Utils do        error -> error      end    end + +  @spec posix_error_message(atom()) :: binary() +  def posix_error_message(code) when code in @posix_error_codes do +    error_message = Gettext.dgettext(Pleroma.Web.Gettext, "posix_errors", "#{code}") +    "(POSIX error: #{error_message})" +  end + +  def posix_error_message(_), do: ""  end diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex index a56641426..747f17e7f 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex @@ -27,7 +27,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do          422 => Operation.response("Unprocessable Entity", "application/json", ApiError),          404 => Operation.response("Not Found", "application/json", ApiError),          400 => Operation.response("Bad Request", "application/json", ApiError), -        409 => Operation.response("Conflict", "application/json", ApiError) +        409 => Operation.response("Conflict", "application/json", ApiError), +        500 => Operation.response("Error", "application/json", ApiError)        }      }    end diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex index 79f52dcb3..e576ccbad 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex @@ -169,7 +169,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do        responses: %{          200 => ok_response(),          400 => Operation.response("Bad Request", "application/json", ApiError), -        404 => Operation.response("Not Found", "application/json", ApiError) +        404 => Operation.response("Not Found", "application/json", ApiError), +        500 => Operation.response("Error", "application/json", ApiError)        }      }    end @@ -184,7 +185,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do        parameters: [name_param()],        responses: %{          200 => Operation.response("Metadata", "application/json", metadata()), -        400 => Operation.response("Bad Request", "application/json", ApiError) +        400 => Operation.response("Bad Request", "application/json", ApiError), +        500 => Operation.response("Error", "application/json", ApiError)        }      }    end diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 3158d09ed..026ae9458 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -187,18 +187,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do      header_static = User.banner_url(user) |> MediaProxy.preview_url(static: true)      following_count = -      if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do -        user.following_count || 0 -      else -        0 -      end +      if !user.hide_follows_count or !user.hide_follows or opts[:for] == user, +        do: user.following_count, +        else: 0      followers_count = -      if !user.hide_followers_count or !user.hide_followers or opts[:for] == user do -        user.follower_count || 0 -      else -        0 -      end +      if !user.hide_followers_count or !user.hide_followers or opts[:for] == user, +        do: user.follower_count, +        else: 0      bot = user.actor_type == "Service" diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex index 428c97de6..c15980ff0 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex @@ -42,7 +42,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do          |> json(%{error: "pack name, shortcode or filename cannot be empty"})        {:error, _} = error -> -        handle_error(conn, error, %{pack_name: pack_name}) +        handle_error(conn, error, %{ +          pack_name: pack_name, +          message: "Unexpected error occurred while adding file to pack." +        })      end    end @@ -69,7 +72,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do          |> json(%{error: "new_shortcode or new_filename cannot be empty"})        {:error, _} = error -> -        handle_error(conn, error, %{pack_name: pack_name, code: shortcode}) +        handle_error(conn, error, %{ +          pack_name: pack_name, +          code: shortcode, +          message: "Unexpected error occurred while updating." +        })      end    end @@ -84,7 +91,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do          |> json(%{error: "pack name or shortcode cannot be empty"})        {:error, _} = error -> -        handle_error(conn, error, %{pack_name: pack_name, code: shortcode}) +        handle_error(conn, error, %{ +          pack_name: pack_name, +          code: shortcode, +          message: "Unexpected error occurred while deleting emoji file." +        })      end    end @@ -94,18 +105,24 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do      |> json(%{error: "Emoji \"#{emoji_code}\" does not exist"})    end -  defp handle_error(conn, {:error, :not_found}, %{pack_name: pack_name}) do +  defp handle_error(conn, {:error, :enoent}, %{pack_name: pack_name}) do      conn      |> put_status(:not_found)      |> json(%{error: "pack \"#{pack_name}\" is not found"})    end -  defp handle_error(conn, {:error, _}, _) do -    render_error( -      conn, -      :internal_server_error, -      "Unexpected error occurred while adding file to pack." -    ) +  defp handle_error(conn, {:error, error}, opts) do +    message = +      [ +        Map.get(opts, :message, "Unexpected error occurred."), +        Pleroma.Utils.posix_error_message(error) +      ] +      |> Enum.join(" ") +      |> String.trim() + +    conn +    |> put_status(:internal_server_error) +    |> json(%{error: message})    end    defp get_filename(%Plug.Upload{filename: filename}), do: filename diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex index a9accc5af..bc4c8d840 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex @@ -71,7 +71,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do      with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do        json(conn, pack)      else -      {:error, :not_found} -> +      {:error, :enoent} ->          conn          |> put_status(:not_found)          |> json(%{error: "Pack #{name} does not exist"}) @@ -80,6 +80,17 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do          conn          |> put_status(:bad_request)          |> json(%{error: "pack name cannot be empty"}) + +      {:error, error} -> +        error_message = +          add_posix_error( +            "Failed to get the contents of the `#{name}` pack.", +            error +          ) + +        conn +        |> put_status(:internal_server_error) +        |> json(%{error: error_message})      end    end @@ -95,7 +106,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do              "Pack #{name} cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"          }) -      {:error, :not_found} -> +      {:error, :enoent} ->          conn          |> put_status(:not_found)          |> json(%{error: "Pack #{name} does not exist"}) @@ -116,10 +127,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do          |> put_status(:internal_server_error)          |> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"}) -      {:error, e} -> +      {:error, error} ->          conn          |> put_status(:internal_server_error) -        |> json(%{error: e}) +        |> json(%{error: error})      end    end @@ -139,12 +150,16 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do          |> put_status(:bad_request)          |> json(%{error: "pack name cannot be empty"}) -      {:error, _} -> -        render_error( -          conn, -          :internal_server_error, -          "Unexpected error occurred while creating pack." -        ) +      {:error, error} -> +        error_message = +          add_posix_error( +            "Unexpected error occurred while creating pack.", +            error +          ) + +        conn +        |> put_status(:internal_server_error) +        |> json(%{error: error_message})      end    end @@ -164,10 +179,12 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do          |> put_status(:bad_request)          |> json(%{error: "pack name cannot be empty"}) -      {:error, _, _} -> +      {:error, error, _} -> +        error_message = add_posix_error("Couldn't delete the `#{name}` pack", error) +          conn          |> put_status(:internal_server_error) -        |> json(%{error: "Couldn't delete the pack #{name}"}) +        |> json(%{error: error_message})      end    end @@ -180,12 +197,16 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do          |> put_status(:bad_request)          |> json(%{error: "The fallback archive does not have all files specified in pack.json"}) -      {:error, _} -> -        render_error( -          conn, -          :internal_server_error, -          "Unexpected error occurred while updating pack metadata." -        ) +      {:error, error} -> +        error_message = +          add_posix_error( +            "Unexpected error occurred while updating pack metadata.", +            error +          ) + +        conn +        |> put_status(:internal_server_error) +        |> json(%{error: error_message})      end    end @@ -204,4 +225,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do          |> json(%{error: "Error accessing emoji pack directory"})      end    end + +  defp add_posix_error(msg, error) do +    [msg, Pleroma.Utils.posix_error_message(error)] +    |> Enum.join(" ") +    |> String.trim() +  end  end diff --git a/priv/gettext/en/LC_MESSAGES/posix_errors.po b/priv/gettext/en/LC_MESSAGES/posix_errors.po new file mode 100644 index 000000000..4d8fbf1d3 --- /dev/null +++ b/priv/gettext/en/LC_MESSAGES/posix_errors.po @@ -0,0 +1,141 @@ +## This file is a PO Template file. +msgid "eperm" +msgstr "Operation not permitted" + +msgid "eacces" +msgstr "Permission denied" + +msgid "eagain" +msgstr "Resource temporarily unavailable" +   +msgid "ebadf" +msgstr "Bad file descriptor" +   +msgid "ebadmsg" +msgstr "Bad message" +   +msgid "ebusy" +msgstr "Device or resource busy" +   +msgid "edeadlk" +msgstr "Resource deadlock avoided" +   +msgid "edeadlock" +msgstr "Resource deadlock avoided" +   +msgid "edquot" +msgstr "Disk quota exceeded" +   +msgid "eexist" +msgstr "File exists" +   +msgid "efault" +msgstr "Bad address" +   +msgid "efbig" +msgstr "File is too large" +   +msgid "eftype" +msgstr "Inappropriate file type or format" +   +msgid "eintr" +msgstr "Interrupted system call" +   +msgid "einval" +msgstr "Invalid argument" +   +msgid "eio" +msgstr "Input/output error" +   +msgid "eisdir" +msgstr "Illegal operation on a directory" +   +msgid "eloop" +msgstr "Too many levels of symbolic links" +   +msgid "emfile" +msgstr "Too many open files" +   +msgid "emlink" +msgstr "Too many links" +   +msgid "emultihop" +msgstr "Multihop attempted" +   +msgid "enametoolong" +msgstr "File name is too long" +   +msgid "enfile" +msgstr "Too many open files in system" +   +msgid "enobufs" +msgstr "No buffer space available" +   +msgid "enodev" +msgstr "No such device" +   +msgid "enolck" +msgstr "No locks available" +   +msgid "enolink" +msgstr "Link has been severed" +   +msgid "enoent" +msgstr "No such file or directory" +   +msgid "enomem" +msgstr "Cannot allocate memory" +   +msgid "enospc" +msgstr "No space left on device" +   +msgid "enosr" +msgstr "Out of streams resources" +   +msgid "enostr" +msgstr "Device is not a stream" +   +msgid "enosys" +msgstr "Function not implemented" +   +msgid "enotblk" +msgstr "Block device required" +   +msgid "enotdir" +msgstr "Not a directory" +   +msgid "enotsup" +msgstr "Operation not supported" +   +msgid "enxio" +msgstr "No such device or address" +   +msgid "eopnotsupp" +msgstr "Operation not supported" +   +msgid "eoverflow" +msgstr "Value too large for defined data type" +   +msgid "epipe" +msgstr "Broken pipe" +   +msgid "erange" +msgstr "Numerical result out of range" +   +msgid "erofs" +msgstr "Read-only file system" +   +msgid "espipe" +msgstr "Illegal seek" +   +msgid "esrch" +msgstr "No such process" +   +msgid "estale" +msgstr "Stale file handle" +   +msgid "etxtbsy" +msgstr "Text file busy" +   +msgid "exdev" +msgstr "Invalid cross-device link" diff --git a/priv/gettext/posix_errors.pot b/priv/gettext/posix_errors.pot new file mode 100644 index 000000000..c9f593944 --- /dev/null +++ b/priv/gettext/posix_errors.pot @@ -0,0 +1,149 @@ +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. +msgid "eperm" +msgstr "" + +msgid "eacces" +msgstr "" + +msgid "eagain" +msgstr "" +   +msgid "ebadf" +msgstr "" +   +msgid "ebadmsg" +msgstr "" +   +msgid "ebusy" +msgstr "" +   +msgid "edeadlk" +msgstr "" +   +msgid "edeadlock" +msgstr "" +   +msgid "edquot" +msgstr "" +   +msgid "eexist" +msgstr "" +   +msgid "efault" +msgstr "" +   +msgid "efbig" +msgstr "" +   +msgid "eftype" +msgstr "" +   +msgid "eintr" +msgstr "" +   +msgid "einval" +msgstr "" +   +msgid "eio" +msgstr "" +   +msgid "eisdir" +msgstr "" +   +msgid "eloop" +msgstr "" +   +msgid "emfile" +msgstr "" +   +msgid "emlink" +msgstr "" +   +msgid "emultihop" +msgstr "" +   +msgid "enametoolong" +msgstr "" +   +msgid "enfile" +msgstr "" +   +msgid "enobufs" +msgstr "" +   +msgid "enodev" +msgstr "" +   +msgid "enolck" +msgstr "" +   +msgid "enolink" +msgstr "" +   +msgid "enoent" +msgstr "" +   +msgid "enomem" +msgstr "" +   +msgid "enospc" +msgstr "" +   +msgid "enosr" +msgstr "" +   +msgid "enostr" +msgstr "" +   +msgid "enosys" +msgstr "" +   +msgid "enotblk" +msgstr "" +   +msgid "enotdir" +msgstr "" +   +msgid "enotsup" +msgstr "" +   +msgid "enxio" +msgstr "" +   +msgid "eopnotsupp" +msgstr "" +   +msgid "eoverflow" +msgstr "" +   +msgid "epipe" +msgstr "" +   +msgid "erange" +msgstr "" +   +msgid "erofs" +msgstr "" +   +msgid "espipe" +msgstr "" +   +msgid "esrch" +msgstr "" +   +msgid "estale" +msgstr "" +   +msgid "etxtbsy" +msgstr "" +   +msgid "exdev" +msgstr "" diff --git a/priv/gettext/zh_Hans/LC_MESSAGES/errors.po b/priv/gettext/zh_Hans/LC_MESSAGES/errors.po index 8b24d4a86..ecf1dab6b 100644 --- a/priv/gettext/zh_Hans/LC_MESSAGES/errors.po +++ b/priv/gettext/zh_Hans/LC_MESSAGES/errors.po @@ -3,7 +3,7 @@ msgstr ""  "Project-Id-Version: PACKAGE VERSION\n"  "Report-Msgid-Bugs-To: \n"  "POT-Creation-Date: 2020-09-20 13:18+0000\n" -"PO-Revision-Date: 2020-10-22 18:25+0000\n" +"PO-Revision-Date: 2020-12-14 06:00+0000\n"  "Last-Translator: shironeko <shironeko@tesaguri.club>\n"  "Language-Team: Chinese (Simplified) <https://translate.pleroma.social/"  "projects/pleroma/pleroma/zh_Hans/>\n" @@ -146,9 +146,9 @@ msgid "Cannot post an empty status without attachments"  msgstr "无法发送空白且不包含附件的状态"  #: lib/pleroma/web/common_api/utils.ex:511 -#, elixir-format +#, elixir-format, fuzzy  msgid "Comment must be up to %{max_size} characters" -msgstr "" +msgstr "评论最多可使用 %{max_size} 字符"  #: lib/pleroma/config/config_db.ex:191  #, elixir-format @@ -250,21 +250,21 @@ msgstr "没有该对话"  #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388  #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 -#, elixir-format +#, elixir-format, fuzzy  msgid "No such permission_group" -msgstr "" +msgstr "没有该权限组"  #: lib/pleroma/plugs/uploaded_media.ex:84  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11  #: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143  #, elixir-format  msgid "Not found" -msgstr "" +msgstr "未找到"  #: lib/pleroma/web/common_api/common_api.ex:331  #, elixir-format  msgid "Poll's author can't vote" -msgstr "" +msgstr "投票的发起者不能投票"  #: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20  #: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49 @@ -272,39 +272,39 @@ msgstr ""  #: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71  #, elixir-format  msgid "Record not found" -msgstr "" +msgstr "未找到该记录"  #: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35  #: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36  #: lib/pleroma/web/ostatus/ostatus_controller.ex:149  #, elixir-format  msgid "Something went wrong" -msgstr "" +msgstr "发生了一些错误"  #: lib/pleroma/web/common_api/activity_draft.ex:107  #, elixir-format  msgid "The message visibility must be direct" -msgstr "" +msgstr "该消息必须为私信"  #: lib/pleroma/web/common_api/utils.ex:573  #, elixir-format  msgid "The status is over the character limit" -msgstr "" +msgstr "状态超过了字符数限制"  #: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31  #, elixir-format  msgid "This resource requires authentication." -msgstr "" +msgstr "该资源需要认证。"  #: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 -#, elixir-format +#, elixir-format, fuzzy  msgid "Throttled" -msgstr "" +msgstr "节流了"  #: lib/pleroma/web/common_api/common_api.ex:356  #, elixir-format  msgid "Too many choices" -msgstr "" +msgstr "太多选项"  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443  #, elixir-format @@ -314,101 +314,101 @@ msgstr ""  #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485  #, elixir-format  msgid "You can't revoke your own admin status." -msgstr "" +msgstr "您不能撤消自己的管理员权限。"  #: lib/pleroma/web/oauth/oauth_controller.ex:221  #: lib/pleroma/web/oauth/oauth_controller.ex:308  #, elixir-format  msgid "Your account is currently disabled" -msgstr "" +msgstr "您的账户已被禁用"  #: lib/pleroma/web/oauth/oauth_controller.ex:183  #: lib/pleroma/web/oauth/oauth_controller.ex:331  #, elixir-format  msgid "Your login is missing a confirmed e-mail address" -msgstr "" +msgstr "您的账户缺少已认证的 e-mail 地址"  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390  #, elixir-format  msgid "can't read inbox of %{nickname} as %{as_nickname}" -msgstr "" +msgstr "无法以 %{as_nickname} 读取 %{nickname} 的收件箱"  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473  #, elixir-format  msgid "can't update outbox of %{nickname} as %{as_nickname}" -msgstr "" +msgstr "无法以 %{as_nickname} 更新 %{nickname} 的出件箱"  #: lib/pleroma/web/common_api/common_api.ex:471  #, elixir-format  msgid "conversation is already muted" -msgstr "" +msgstr "对话已经被静音"  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:314  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:492  #, elixir-format  msgid "error" -msgstr "" +msgstr "错误"  #: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32  #, elixir-format  msgid "mascots can only be images" -msgstr "" +msgstr "吉祥物只能是图片"  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62  #, elixir-format  msgid "not found" -msgstr "" +msgstr "未找到"  #: lib/pleroma/web/oauth/oauth_controller.ex:394  #, elixir-format  msgid "Bad OAuth request." -msgstr "" +msgstr "错误的 OAuth 请求。"  #: lib/pleroma/web/twitter_api/twitter_api.ex:115  #, elixir-format  msgid "CAPTCHA already used" -msgstr "" +msgstr "验证码已被使用"  #: lib/pleroma/web/twitter_api/twitter_api.ex:112  #, elixir-format  msgid "CAPTCHA expired" -msgstr "" +msgstr "验证码已过期"  #: lib/pleroma/plugs/uploaded_media.ex:57  #, elixir-format  msgid "Failed" -msgstr "" +msgstr "失败"  #: lib/pleroma/web/oauth/oauth_controller.ex:410 -#, elixir-format +#, elixir-format, fuzzy  msgid "Failed to authenticate: %{message}." -msgstr "" +msgstr "认证失败:%{message}。"  #: lib/pleroma/web/oauth/oauth_controller.ex:441  #, elixir-format  msgid "Failed to set up user account." -msgstr "" +msgstr "建立用户帐号失败。"  #: lib/pleroma/plugs/oauth_scopes_plug.ex:38  #, elixir-format  msgid "Insufficient permissions: %{permissions}." -msgstr "" +msgstr "权限不足:%{permissions}。"  #: lib/pleroma/plugs/uploaded_media.ex:104  #, elixir-format  msgid "Internal Error" -msgstr "" +msgstr "内部错误"  #: lib/pleroma/web/oauth/fallback_controller.ex:22  #: lib/pleroma/web/oauth/fallback_controller.ex:29  #, elixir-format  msgid "Invalid Username/Password" -msgstr "" +msgstr "无效的用户名/密码"  #: lib/pleroma/web/twitter_api/twitter_api.ex:118 -#, elixir-format +#, elixir-format, fuzzy  msgid "Invalid answer data" -msgstr "" +msgstr "无效的回答数据"  #: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33  #, elixir-format @@ -418,12 +418,12 @@ msgstr ""  #: lib/pleroma/web/oauth/oauth_controller.ex:172  #, elixir-format  msgid "This action is outside the authorized scopes" -msgstr "" +msgstr "此操作在许可范围以外"  #: lib/pleroma/web/oauth/fallback_controller.ex:14  #, elixir-format  msgid "Unknown error, please check the details and try again." -msgstr "" +msgstr "未知错误,请检查并重试。"  #: lib/pleroma/web/oauth/oauth_controller.ex:119  #: lib/pleroma/web/oauth/oauth_controller.ex:158 @@ -434,53 +434,53 @@ msgstr ""  #: lib/pleroma/web/oauth/oauth_controller.ex:390  #, elixir-format  msgid "Unsupported OAuth provider: %{provider}." -msgstr "" +msgstr "不支持的 OAuth 提供者:%{provider}。"  #: lib/pleroma/uploaders/uploader.ex:72 -#, elixir-format +#, elixir-format, fuzzy  msgid "Uploader callback timeout" -msgstr "" +msgstr "上传回复超时"  #: lib/pleroma/web/uploader_controller.ex:23  #, elixir-format  msgid "bad request" -msgstr "" +msgstr "错误的请求"  #: lib/pleroma/web/twitter_api/twitter_api.ex:103  #, elixir-format  msgid "CAPTCHA Error" -msgstr "" +msgstr "验证码错误"  #: lib/pleroma/web/common_api/common_api.ex:290 -#, elixir-format +#, elixir-format, fuzzy  msgid "Could not add reaction emoji" -msgstr "" +msgstr "无法添加表情反应"  #: lib/pleroma/web/common_api/common_api.ex:301  #, elixir-format  msgid "Could not remove reaction emoji" -msgstr "" +msgstr "无法移除表情反应"  #: lib/pleroma/web/twitter_api/twitter_api.ex:129  #, elixir-format  msgid "Invalid CAPTCHA (Missing parameter: %{name})" -msgstr "" +msgstr "无效的验证码(缺少参数:%{name})"  #: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92  #, elixir-format  msgid "List not found" -msgstr "" +msgstr "未找到列表"  #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123  #, elixir-format  msgid "Missing parameter: %{name}" -msgstr "" +msgstr "缺少参数:%{name}"  #: lib/pleroma/web/oauth/oauth_controller.ex:210  #: lib/pleroma/web/oauth/oauth_controller.ex:321  #, elixir-format  msgid "Password reset is required" -msgstr "" +msgstr "需要重置密码"  #: lib/pleroma/tests/auth_test_controller.ex:9  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6 @@ -520,61 +520,61 @@ msgid "Security violation: OAuth scopes check was neither handled nor explicitly  msgstr ""  #: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 -#, elixir-format +#, elixir-format, fuzzy  msgid "Two-factor authentication enabled, you must use a access token." -msgstr "" +msgstr "已启用两因素验证,您需要使用访问令牌。"  #: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210  #, elixir-format  msgid "Unexpected error occurred while adding file to pack." -msgstr "" +msgstr "向表情包添加文件时发生了没有预料到的错误。"  #: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138  #, elixir-format  msgid "Unexpected error occurred while creating pack." -msgstr "" +msgstr "创建表情包时发生了没有预料到的错误。"  #: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278  #, elixir-format  msgid "Unexpected error occurred while removing file from pack." -msgstr "" +msgstr "从表情包移除文件时发生了没有预料到的错误。"  #: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250  #, elixir-format  msgid "Unexpected error occurred while updating file in pack." -msgstr "" +msgstr "更新表情包内的文件时发生了没有预料到的错误。"  #: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179  #, elixir-format  msgid "Unexpected error occurred while updating pack metadata." -msgstr "" +msgstr "更新表情包元数据时发生了没有预料到的错误。"  #: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 -#, elixir-format +#, elixir-format, fuzzy  msgid "Web push subscription is disabled on this Pleroma instance" -msgstr "" +msgstr "此 Pleroma 实例禁用了网页推送订阅"  #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451  #, elixir-format  msgid "You can't revoke your own admin/moderator status." -msgstr "" +msgstr "您不能撤消自己的管理员权限。"  #: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126  #, elixir-format  msgid "authorization required for timeline view" -msgstr "" +msgstr "浏览时间线需要认证"  #: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24  #, elixir-format  msgid "Access denied" -msgstr "" +msgstr "拒绝访问"  #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282  #, elixir-format  msgid "This API requires an authenticated user" -msgstr "" +msgstr "此 API 需要已认证的用户"  #: lib/pleroma/plugs/user_is_admin_plug.ex:21  #, elixir-format  msgid "User is not an admin." -msgstr "" +msgstr "该用户不是管理员。" diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs index 82de86ee3..6fbdaec7a 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs @@ -5,6 +5,7 @@  defmodule Pleroma.Web.PleromaAPI.EmojiFileControllerTest do    use Pleroma.Web.ConnCase +  import Mock    import Tesla.Mock    import Pleroma.Factory @@ -200,6 +201,31 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileControllerTest do               }      end +    test "returns an error on add file when file system is not writable", %{ +      admin_conn: admin_conn +    } do +      pack_file = Path.join([@emoji_path, "not_loaded", "pack.json"]) + +      with_mocks([ +        {File, [:passthrough], [stat: fn ^pack_file -> {:error, :eacces} end]} +      ]) do +        assert admin_conn +               |> put_req_header("content-type", "multipart/form-data") +               |> post("/api/pleroma/emoji/packs/files?name=not_loaded", %{ +                 shortcode: "blank3", +                 filename: "dir/blank.png", +                 file: %Plug.Upload{ +                   filename: "blank.png", +                   path: "#{@emoji_path}/test_pack/blank.png" +                 } +               }) +               |> json_response_and_validate_schema(500) == %{ +                 "error" => +                   "Unexpected error occurred while adding file to pack. (POSIX error: Permission denied)" +               } +      end +    end +      test "remove file with not loaded pack", %{admin_conn: admin_conn} do        assert admin_conn               |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=blank3") diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs index 3445f0ca0..d9385389b 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -3,8 +3,9 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do -  use Pleroma.Web.ConnCase +  use Pleroma.Web.ConnCase, async: false +  import Mock    import Tesla.Mock    import Pleroma.Factory @@ -346,7 +347,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      end    end -  describe "PATCH /api/pleroma/emoji/pack?name=:name" do +  describe "PATCH/update /api/pleroma/emoji/pack?name=:name" do      setup do        pack_file = "#{@emoji_path}/test_pack/pack.json"        original_content = File.read!(pack_file) @@ -365,6 +366,20 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do         }}      end +    test "returns error when file system not writable", %{admin_conn: conn} = ctx do +      with_mocks([ +        {File, [:passthrough], [stat: fn _ -> {:error, :eacces} end]} +      ]) do +        assert conn +               |> put_req_header("content-type", "multipart/form-data") +               |> patch( +                 "/api/pleroma/emoji/pack?name=test_pack", +                 %{"metadata" => ctx[:new_data]} +               ) +               |> json_response_and_validate_schema(500) +      end +    end +      test "for a pack without a fallback source", ctx do        assert ctx[:admin_conn]               |> put_req_header("content-type", "multipart/form-data") @@ -424,6 +439,46 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do    end    describe "POST/DELETE /api/pleroma/emoji/pack?name=:name" do +    test "returns an error on creates pack when file system not writable", %{ +      admin_conn: admin_conn +    } do +      path_pack = Path.join(@emoji_path, "test_pack") + +      with_mocks([ +        {File, [:passthrough], [mkdir: fn ^path_pack -> {:error, :eacces} end]} +      ]) do +        assert admin_conn +               |> post("/api/pleroma/emoji/pack?name=test_pack") +               |> json_response_and_validate_schema(500) == %{ +                 "error" => +                   "Unexpected error occurred while creating pack. (POSIX error: Permission denied)" +               } +      end +    end + +    test "returns an error on deletes pack when the file system is not writable", %{ +      admin_conn: admin_conn +    } do +      path_pack = Path.join(@emoji_path, "test_emoji_pack") + +      try do +        {:ok, _pack} = Pleroma.Emoji.Pack.create("test_emoji_pack") + +        with_mocks([ +          {File, [:passthrough], [rm_rf: fn ^path_pack -> {:error, :eacces, path_pack} end]} +        ]) do +          assert admin_conn +                 |> delete("/api/pleroma/emoji/pack?name=test_emoji_pack") +                 |> json_response_and_validate_schema(500) == %{ +                   "error" => +                     "Couldn't delete the `test_emoji_pack` pack (POSIX error: Permission denied)" +                 } +        end +      after +        File.rm_rf(path_pack) +      end +    end +      test "creating and deleting a pack", %{admin_conn: admin_conn} do        assert admin_conn               |> post("/api/pleroma/emoji/pack?name=test_created") | 
