diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/application.ex | 18 | ||||
| -rw-r--r-- | lib/pleroma/config.ex | 41 | ||||
| -rw-r--r-- | lib/pleroma/upload/filter/exiftool.ex | 12 | ||||
| -rw-r--r-- | lib/pleroma/upload/filter/mogrifun.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/upload/filter/mogrify.ex | 12 | ||||
| -rw-r--r-- | lib/pleroma/user.ex | 11 | ||||
| -rw-r--r-- | lib/pleroma/utils.ex | 15 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex | 4 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/object_validators/common_validations.ex | 13 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/views/filter_view.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/oauth/oauth_controller.ex | 7 | ||||
| -rw-r--r-- | lib/pleroma/web/rich_media/helpers.ex | 21 | ||||
| -rw-r--r-- | lib/pleroma/web/rich_media/parser.ex | 20 | ||||
| -rw-r--r-- | lib/pleroma/web/rich_media/parsers/oembed_parser.ex | 2 | ||||
| -rw-r--r-- | lib/pleroma/web/templates/layout/app.html.eex | 2 | 
15 files changed, 142 insertions, 49 deletions
| diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 0ffb55358..c0b5db9f1 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -47,6 +47,7 @@ defmodule Pleroma.Application do      Pleroma.ApplicationRequirements.verify!()      setup_instrumenters()      load_custom_modules() +    check_system_commands()      Pleroma.Docs.JSON.compile()      adapter = Application.get_env(:tesla, :adapter) @@ -249,4 +250,21 @@ defmodule Pleroma.Application do    end    defp http_children(_, _), do: [] + +  defp check_system_commands do +    filters = Config.get([Pleroma.Upload, :filters]) + +    check_filter = fn filter, command_required -> +      with true <- filter in filters, +           false <- Pleroma.Utils.command_available?(command_required) do +        Logger.error( +          "#{filter} is specified in list of Pleroma.Upload filters, but the #{command_required} command is not found" +        ) +      end +    end + +    check_filter.(Pleroma.Upload.Filters.Exiftool, "exiftool") +    check_filter.(Pleroma.Upload.Filters.Mogrify, "mogrify") +    check_filter.(Pleroma.Upload.Filters.Mogrifun, "mogrify") +  end  end diff --git a/lib/pleroma/config.ex b/lib/pleroma/config.ex index cc80deff5..a8329cc1e 100644 --- a/lib/pleroma/config.ex +++ b/lib/pleroma/config.ex @@ -11,12 +11,10 @@ defmodule Pleroma.Config do    def get([key], default), do: get(key, default) -  def get([parent_key | keys], default) do -    case :pleroma -         |> Application.get_env(parent_key) -         |> get_in(keys) do -      nil -> default -      any -> any +  def get([_ | _] = path, default) do +    case fetch(path) do +      {:ok, value} -> value +      :error -> default      end    end @@ -34,6 +32,24 @@ defmodule Pleroma.Config do      end    end +  def fetch(key) when is_atom(key), do: fetch([key]) + +  def fetch([root_key | keys]) do +    Enum.reduce_while(keys, Application.fetch_env(:pleroma, root_key), fn +      key, {:ok, config} when is_map(config) or is_list(config) -> +        case Access.fetch(config, key) do +          :error -> +            {:halt, :error} + +          value -> +            {:cont, value} +        end + +      _key, _config -> +        {:halt, :error} +    end) +  end +    def put([key], value), do: put(key, value)    def put([parent_key | keys], value) do @@ -50,12 +66,15 @@ defmodule Pleroma.Config do    def delete([key]), do: delete(key) -  def delete([parent_key | keys]) do -    {_, parent} = -      Application.get_env(:pleroma, parent_key) -      |> get_and_update_in(keys, fn _ -> :pop end) +  def delete([parent_key | keys] = path) do +    with {:ok, _} <- fetch(path) do +      {_, parent} = +        parent_key +        |> get() +        |> get_and_update_in(keys, fn _ -> :pop end) -    Application.put_env(:pleroma, parent_key, parent) +      Application.put_env(:pleroma, parent_key, parent) +    end    end    def delete(key) do diff --git a/lib/pleroma/upload/filter/exiftool.ex b/lib/pleroma/upload/filter/exiftool.ex index c7fb6aefa..ea8798fe3 100644 --- a/lib/pleroma/upload/filter/exiftool.ex +++ b/lib/pleroma/upload/filter/exiftool.ex @@ -9,9 +9,17 @@ defmodule Pleroma.Upload.Filter.Exiftool do    """    @behaviour Pleroma.Upload.Filter +  @spec filter(Pleroma.Upload.t()) :: :ok | {:error, String.t()}    def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do -    System.cmd("exiftool", ["-overwrite_original", "-gps:all=", file], parallelism: true) -    :ok +    try do +      case System.cmd("exiftool", ["-overwrite_original", "-gps:all=", file], parallelism: true) do +        {_response, 0} -> :ok +        {error, 1} -> {:error, error} +      end +    rescue +      _e in ErlangError -> +        {:error, "exiftool command not found"} +    end    end    def filter(_), do: :ok diff --git a/lib/pleroma/upload/filter/mogrifun.ex b/lib/pleroma/upload/filter/mogrifun.ex index 7d95577a4..a8503ac24 100644 --- a/lib/pleroma/upload/filter/mogrifun.ex +++ b/lib/pleroma/upload/filter/mogrifun.ex @@ -34,10 +34,15 @@ defmodule Pleroma.Upload.Filter.Mogrifun do      [{"fill", "yellow"}, {"tint", "40"}]    ] +  @spec filter(Pleroma.Upload.t()) :: :ok | {:error, String.t()}    def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do -    Filter.Mogrify.do_filter(file, [Enum.random(@filters)]) - -    :ok +    try do +      Filter.Mogrify.do_filter(file, [Enum.random(@filters)]) +      :ok +    rescue +      _e in ErlangError -> +        {:error, "mogrify command not found"} +    end    end    def filter(_), do: :ok diff --git a/lib/pleroma/upload/filter/mogrify.ex b/lib/pleroma/upload/filter/mogrify.ex index 2eb758006..7a45add5a 100644 --- a/lib/pleroma/upload/filter/mogrify.ex +++ b/lib/pleroma/upload/filter/mogrify.ex @@ -8,11 +8,15 @@ defmodule Pleroma.Upload.Filter.Mogrify do    @type conversion :: action :: String.t() | {action :: String.t(), opts :: String.t()}    @type conversions :: conversion() | [conversion()] +  @spec filter(Pleroma.Upload.t()) :: :ok | {:error, String.t()}    def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do -    filters = Pleroma.Config.get!([__MODULE__, :args]) - -    do_filter(file, filters) -    :ok +    try do +      do_filter(file, Pleroma.Config.get!([__MODULE__, :args])) +      :ok +    rescue +      _e in ErlangError -> +        {:error, "mogrify command not found"} +    end    end    def filter(_), do: :ok diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 0c1fab223..09e606b37 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -676,10 +676,19 @@ defmodule Pleroma.User do      |> validate_required([:name, :nickname, :password, :password_confirmation])      |> validate_confirmation(:password)      |> unique_constraint(:email) +    |> validate_format(:email, @email_regex) +    |> validate_change(:email, fn :email, email -> +      valid? = +        Config.get([User, :email_blacklist]) +        |> Enum.all?(fn blacklisted_domain -> +          !String.ends_with?(email, ["@" <> blacklisted_domain, "." <> blacklisted_domain]) +        end) + +      if valid?, do: [], else: [email: "Invalid email"] +    end)      |> unique_constraint(:nickname)      |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))      |> validate_format(:nickname, local_nickname_regex()) -    |> validate_format(:email, @email_regex)      |> validate_length(:bio, max: bio_limit)      |> validate_length(:name, min: 1, max: name_limit)      |> validate_length(:registration_reason, max: reason_limit) diff --git a/lib/pleroma/utils.ex b/lib/pleroma/utils.ex index 6b8e3accf..21d1159be 100644 --- a/lib/pleroma/utils.ex +++ b/lib/pleroma/utils.ex @@ -9,4 +9,19 @@ defmodule Pleroma.Utils do      |> Enum.map(&Path.join(dir, &1))      |> Kernel.ParallelCompiler.compile()    end + +  @doc """ +  POSIX-compliant check if command is available in the system + +  ## Examples +      iex> command_available?("git") +      true +      iex> command_available?("wrongcmd") +      false + +  """ +  @spec command_available?(String.t()) :: boolean() +  def command_available?(command) do +    match?({_output, 0}, System.cmd("sh", ["-c", "command -v #{command}"])) +  end  end diff --git a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex index 8e47f1e02..7b4c78e0f 100644 --- a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex @@ -21,8 +21,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do    @impl true    def describe, do: {:ok, %{}} -  defp local?(%{"id" => id}) do -    String.starts_with?(id, Pleroma.Web.Endpoint.url()) +  defp local?(%{"actor" => actor}) do +    String.starts_with?(actor, Pleroma.Web.Endpoint.url())    end    defp note?(activity) do diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex index aeef31945..bd46f8034 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex @@ -34,10 +34,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do      cng      |> validate_change(field_name, fn field_name, actor -> -      if User.get_cached_by_ap_id(actor) do -        [] -      else -        [{field_name, "can't find user"}] +      case User.get_cached_by_ap_id(actor) do +        %User{deactivated: true} -> +          [{field_name, "user is deactivated"}] + +        %User{} -> +          [] + +        _ -> +          [{field_name, "can't find user"}]        end      end)    end diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex index aeff646f5..c37f624e0 100644 --- a/lib/pleroma/web/mastodon_api/views/filter_view.ex +++ b/lib/pleroma/web/mastodon_api/views/filter_view.ex @@ -25,7 +25,7 @@ defmodule Pleroma.Web.MastodonAPI.FilterView do        context: filter.context,        expires_at: expires_at,        irreversible: filter.hide, -      whole_word: false +      whole_word: filter.whole_word      }    end  end diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index f29b3cb57..dd00600ea 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -76,6 +76,13 @@ defmodule Pleroma.Web.OAuth.OAuthController do      available_scopes = (app && app.scopes) || []      scopes = Scopes.fetch_scopes(params, available_scopes) +    scopes = +      if scopes == [] do +        available_scopes +      else +        scopes +      end +      # Note: `params` might differ from `conn.params`; use `@params` not `@conn.params` in template      render(conn, Authenticator.auth_template(), %{        response_type: params["response_type"], diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex index 5c7daf1a5..6210f2c5a 100644 --- a/lib/pleroma/web/rich_media/helpers.ex +++ b/lib/pleroma/web/rich_media/helpers.ex @@ -9,6 +9,11 @@ defmodule Pleroma.Web.RichMedia.Helpers do    alias Pleroma.Object    alias Pleroma.Web.RichMedia.Parser +  @rich_media_options [ +    pool: :media, +    max_body: 2_000_000 +  ] +    @spec validate_page_url(URI.t() | binary()) :: :ok | :error    defp validate_page_url(page_url) when is_binary(page_url) do      validate_tld = Pleroma.Config.get([Pleroma.Formatter, :validate_tld]) @@ -77,4 +82,20 @@ defmodule Pleroma.Web.RichMedia.Helpers do      fetch_data_for_activity(activity)      :ok    end + +  def rich_media_get(url) do +    headers = [{"user-agent", Pleroma.Application.user_agent() <> "; Bot"}] + +    options = +      if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do +        Keyword.merge(@rich_media_options, +          recv_timeout: 2_000, +          with_body: true +        ) +      else +        @rich_media_options +      end + +    Pleroma.HTTP.get(url, headers, options) +  end  end diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index c8a767935..ca592833f 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -3,11 +3,6 @@  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.RichMedia.Parser do -  @options [ -    pool: :media, -    max_body: 2_000_000 -  ] -    defp parsers do      Pleroma.Config.get([:rich_media, :parsers])    end @@ -75,21 +70,8 @@ defmodule Pleroma.Web.RichMedia.Parser do    end    defp parse_url(url) do -    opts = -      if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do -        Keyword.merge(@options, -          recv_timeout: 2_000, -          with_body: true -        ) -      else -        @options -      end -      try do -      rich_media_agent = Pleroma.Application.user_agent() <> "; Bot" - -      {:ok, %Tesla.Env{body: html}} = -        Pleroma.HTTP.get(url, [{"user-agent", rich_media_agent}], adapter: opts) +      {:ok, %Tesla.Env{body: html}} = Pleroma.Web.RichMedia.Helpers.rich_media_get(url)        html        |> parse_html() diff --git a/lib/pleroma/web/rich_media/parsers/oembed_parser.ex b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex index 6bdeac89c..1fe6729c3 100644 --- a/lib/pleroma/web/rich_media/parsers/oembed_parser.ex +++ b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex @@ -22,7 +22,7 @@ defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do    end    defp get_oembed_data(url) do -    with {:ok, %Tesla.Env{body: json}} <- Pleroma.HTTP.get(url, [], adapter: [pool: :media]) do +    with {:ok, %Tesla.Env{body: json}} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url) do        Jason.decode(json)      end    end diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex index 5836ec1e0..51603fe0c 100644 --- a/lib/pleroma/web/templates/layout/app.html.eex +++ b/lib/pleroma/web/templates/layout/app.html.eex @@ -37,7 +37,7 @@        }        a { -        color: color: #d8a070; +        color: #d8a070;          text-decoration: none;        } | 
