added error messages for posix error code

This commit is contained in:
Maksim Pechnikov 2020-11-13 15:13:14 +03:00
parent 74179e6ac3
commit 1830b6aae5
6 changed files with 412 additions and 49 deletions

View file

@ -22,14 +22,14 @@ defmodule Pleroma.Emoji.Pack do
alias Pleroma.Emoji alias Pleroma.Emoji
alias Pleroma.Emoji.Pack alias Pleroma.Emoji.Pack
alias Pleroma.Utils
@spec create(String.t()) :: {:ok, t()} | {:error, File.posix()} | {:error, :empty_values} @spec create(String.t()) :: {:ok, t()} | {:error, File.posix()} | {:error, :empty_values}
def create(name) do def create(name) do
with :ok <- validate_not_empty([name]), with :ok <- validate_not_empty([name]),
dir <- Path.join(emoji_path(), name), dir <- Path.join(emoji_path(), name),
:ok <- File.mkdir(dir) do :ok <- File.mkdir(dir) do
%__MODULE__{pack_file: Path.join(dir, "pack.json")} save_pack(%__MODULE__{pack_file: Path.join(dir, "pack.json")})
|> save_pack()
end end
end end
@ -94,7 +94,7 @@ defp unpack_zip_emojies(zip_files) do
def add_file(%Pack{} = pack, _, _, %Plug.Upload{content_type: "application/zip"} = file) do def add_file(%Pack{} = pack, _, _, %Plug.Upload{content_type: "application/zip"} = file) do
with {:ok, zip_files} <- :zip.table(to_charlist(file.path)), with {:ok, zip_files} <- :zip.table(to_charlist(file.path)),
[_ | _] = emojies <- unpack_zip_emojies(zip_files), [_ | _] = 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 try do
{:ok, _emoji_files} = {:ok, _emoji_files} =
:zip.unzip( :zip.unzip(
@ -282,18 +282,21 @@ def update_metadata(name, data) do
end end
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 def load_pack(name) do
pack_file = Path.join([emoji_path(), name, "pack.json"]) 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 =
pack_file from_json(
|> File.read!() pack_data,
|> from_json() %{
|> Map.put(:pack_file, pack_file) pack_file: pack_file,
|> Map.put(:path, Path.dirname(pack_file)) path: Path.dirname(pack_file),
|> Map.put(:name, name) name: name
}
)
files_count = files_count =
pack.files pack.files
@ -301,8 +304,6 @@ def load_pack(name) do
|> length() |> length()
{:ok, Map.put(pack, :files_count, files_count)} {:ok, Map.put(pack, :files_count, files_count)}
else
{:error, :not_found}
end end
end end
@ -434,10 +435,17 @@ defp save_pack(pack) do
end end
end end
defp from_json(json) do defp from_json(json, attrs) do
map = Jason.decode!(json) 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 end
defp validate_shareable_packs_available(uri) do defp validate_shareable_packs_available(uri) do
@ -491,10 +499,10 @@ defp rename_file(pack, filename, new_filename) do
end end
defp create_subdirs(file_path) do defp create_subdirs(file_path) do
if String.contains?(file_path, "/") do with true <- String.contains?(file_path, "/"),
file_path path <- Path.dirname(file_path),
|> Path.dirname() false <- File.exists?(path) do
|> File.mkdir_p!() File.mkdir_p!(path)
end end
end end
@ -518,10 +526,15 @@ defp remove_dir_if_empty(emoji, filename) do
defp get_filename(pack, shortcode) do defp get_filename(pack, shortcode) do
with %{^shortcode => filename} when is_binary(filename) <- pack.files, 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} {:ok, filename}
else else
_ -> {:error, :doesnt_exist} {:error, _} = error ->
error
_ ->
{:error, :doesnt_exist}
end end
end end

View file

@ -3,6 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Utils do 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 def compile_dir(dir) when is_binary(dir) do
dir dir
|> File.ls!() |> File.ls!()
@ -44,4 +52,12 @@ def tmp_dir(prefix \\ "") do
error -> error error -> error
end end
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 end

View file

@ -42,7 +42,10 @@ def create(%{body_params: params} = conn, %{name: pack_name}) do
|> json(%{error: "pack name, shortcode or filename cannot be empty"}) |> json(%{error: "pack name, shortcode or filename cannot be empty"})
{:error, _} = error -> {: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
end end
@ -69,7 +72,11 @@ def update(%{body_params: %{shortcode: shortcode} = params} = conn, %{name: pack
|> json(%{error: "new_shortcode or new_filename cannot be empty"}) |> json(%{error: "new_shortcode or new_filename cannot be empty"})
{:error, _} = error -> {: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
end end
@ -84,7 +91,11 @@ def delete(conn, %{name: pack_name, shortcode: shortcode}) do
|> json(%{error: "pack name or shortcode cannot be empty"}) |> json(%{error: "pack name or shortcode cannot be empty"})
{:error, _} = error -> {: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
end end
@ -94,18 +105,24 @@ defp handle_error(conn, {:error, :doesnt_exist}, %{code: emoji_code}) do
|> json(%{error: "Emoji \"#{emoji_code}\" does not exist"}) |> json(%{error: "Emoji \"#{emoji_code}\" does not exist"})
end 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 conn
|> put_status(:not_found) |> put_status(:not_found)
|> json(%{error: "pack \"#{pack_name}\" is not found"}) |> json(%{error: "pack \"#{pack_name}\" is not found"})
end end
defp handle_error(conn, {:error, _}, _) do defp handle_error(conn, {:error, error}, opts) do
render_error( message =
conn, [
:internal_server_error, Map.get(opts, :message, "Unexpected error occurred."),
"Unexpected error occurred while adding file to pack." Pleroma.Utils.posix_error_message(error)
) ]
|> Enum.join(" ")
|> String.trim()
conn
|> put_status(:internal_server_error)
|> json(%{error: message})
end end
defp get_filename(%Plug.Upload{filename: filename}), do: filename defp get_filename(%Plug.Upload{filename: filename}), do: filename

View file

@ -71,7 +71,7 @@ def show(conn, %{name: name, page: page, page_size: page_size}) do
with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do
json(conn, pack) json(conn, pack)
else else
{:error, :not_found} -> {:error, :enoent} ->
conn conn
|> put_status(:not_found) |> put_status(:not_found)
|> json(%{error: "Pack #{name} does not exist"}) |> json(%{error: "Pack #{name} does not exist"})
@ -80,6 +80,17 @@ def show(conn, %{name: name, page: page, page_size: page_size}) do
conn conn
|> put_status(:bad_request) |> put_status(:bad_request)
|> json(%{error: "pack name cannot be empty"}) |> 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
end end
@ -95,7 +106,7 @@ def archive(conn, %{name: name}) do
"Pack #{name} cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing" "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 conn
|> put_status(:not_found) |> put_status(:not_found)
|> json(%{error: "Pack #{name} does not exist"}) |> json(%{error: "Pack #{name} does not exist"})
@ -116,10 +127,10 @@ def download(%{body_params: %{url: url, name: name} = params} = conn, _) do
|> put_status(:internal_server_error) |> put_status(:internal_server_error)
|> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"}) |> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"})
{:error, e} -> {:error, error} ->
conn conn
|> put_status(:internal_server_error) |> put_status(:internal_server_error)
|> json(%{error: e}) |> json(%{error: error})
end end
end end
@ -139,12 +150,16 @@ def create(conn, %{name: name}) do
|> put_status(:bad_request) |> put_status(:bad_request)
|> json(%{error: "pack name cannot be empty"}) |> json(%{error: "pack name cannot be empty"})
{:error, _} -> {:error, error} ->
render_error( error_message =
conn, add_posix_error(
:internal_server_error, "Unexpected error occurred while creating pack.",
"Unexpected error occurred while creating pack." error
) )
conn
|> put_status(:internal_server_error)
|> json(%{error: error_message})
end end
end end
@ -164,10 +179,12 @@ def delete(conn, %{name: name}) do
|> put_status(:bad_request) |> put_status(:bad_request)
|> json(%{error: "pack name cannot be empty"}) |> json(%{error: "pack name cannot be empty"})
{:error, _, _} -> {:error, error, _} ->
error_message = add_posix_error("Couldn't delete the pack #{name}", error)
conn conn
|> put_status(:internal_server_error) |> put_status(:internal_server_error)
|> json(%{error: "Couldn't delete the pack #{name}"}) |> json(%{error: error_message})
end end
end end
@ -180,12 +197,16 @@ def update(%{body_params: %{metadata: metadata}} = conn, %{name: name}) do
|> put_status(:bad_request) |> put_status(:bad_request)
|> json(%{error: "The fallback archive does not have all files specified in pack.json"}) |> json(%{error: "The fallback archive does not have all files specified in pack.json"})
{:error, _} -> {:error, error} ->
render_error( error_message =
conn, add_posix_error(
:internal_server_error, "Unexpected error occurred while updating pack metadata.",
"Unexpected error occurred while updating pack metadata." error
) )
conn
|> put_status(:internal_server_error)
|> json(%{error: error_message})
end end
end end
@ -204,4 +225,10 @@ def import_from_filesystem(conn, _params) do
|> json(%{error: "Error accessing emoji pack directory"}) |> json(%{error: "Error accessing emoji pack directory"})
end end
end end
defp add_posix_error(msg, error) do
[msg, Pleroma.Utils.posix_error_message(error)]
|> Enum.join(" ")
|> String.trim()
end
end end

View file

@ -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 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 "Is 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 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 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"

View file

@ -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 ""