diff --git a/changelog.d/docs-otp-install-links.fix b/changelog.d/docs-otp-install-links.fix new file mode 100644 index 000000000..28d504bc0 --- /dev/null +++ b/changelog.d/docs-otp-install-links.fix @@ -0,0 +1 @@ +Docs: Fixed OTP install links in documentation, broke up wall of install commands into smaller chunks, fixed sudo commands execution diff --git a/changelog.d/grouped-notifs-embed.skip b/changelog.d/grouped-notifs-embed.skip new file mode 100644 index 000000000..e69de29bb diff --git a/changelog.d/mediaproxy-content-type.fix b/changelog.d/mediaproxy-content-type.fix deleted file mode 100644 index f36dd6283..000000000 --- a/changelog.d/mediaproxy-content-type.fix +++ /dev/null @@ -1 +0,0 @@ -Detect image content types for extensionless MediaProxy responses. diff --git a/changelog.d/oban-reindexer.add b/changelog.d/oban-reindexer.add new file mode 100644 index 000000000..5b56d9482 --- /dev/null +++ b/changelog.d/oban-reindexer.add @@ -0,0 +1 @@ +Oban: Enabled the Reindexer plugin to reduce oban_jobs index DB bloat diff --git a/changelog.d/syslog-fix-otp.skip b/changelog.d/syslog-fix-otp.skip new file mode 100644 index 000000000..e69de29bb diff --git a/changelog.d/syslog-pc.fix b/changelog.d/syslog-pc.fix new file mode 100644 index 000000000..3f08cec47 --- /dev/null +++ b/changelog.d/syslog-pc.fix @@ -0,0 +1 @@ +Fix intermittent failure to compile syslog package diff --git a/config/config.exs b/config/config.exs index d4a70450f..e2c110689 100644 --- a/config/config.exs +++ b/config/config.exs @@ -607,7 +607,11 @@ config :pleroma, Oban, search_indexing: [limit: 10, paused: true], slow: 5 ], - plugins: [Oban.Plugins.Lazarus, {Oban.Plugins.Pruner, max_age: 900}], + plugins: [ + Oban.Plugins.Lazarus, + {Oban.Plugins.Pruner, max_age: 900}, + {Oban.Plugins.Reindexer, schedule: "@weekly"} + ], crontab: [ {"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker}, {"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}, diff --git a/docs/installation/migrating_from_source_otp_en.md b/docs/installation/migrating_from_source_otp_en.md index 798862566..450d33804 100644 --- a/docs/installation/migrating_from_source_otp_en.md +++ b/docs/installation/migrating_from_source_otp_en.md @@ -76,35 +76,51 @@ $EDITOR /etc/pleroma/config.exs ``` ## Installing the release Before proceeding, get the flavour from [Detecting flavour](otp_en.md#detecting-flavour) section in OTP installation guide. + + +Delete all files in pleroma user's directory: ```sh -# Delete all files in pleroma user's directory rm -r ~pleroma/* +``` -# Set the flavour environment variable to the string you got in Detecting flavour section. -# For example if the flavour is `amd64-musl` the command will be +Set the flavour environment variable to the string you got in Detecting flavour section. +For example if the flavour is `amd64-musl` the command will be: + +```sh export FLAVOUR="amd64-musl" +``` -# Clone the release build into a temporary directory and unpack it -# Replace `stable` with `unstable` if you want to run the unstable branch -sudo -Hu pleroma " -curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip -unzip /tmp/pleroma.zip -d /tmp/ -" +Clone the release build into a temporary directory and unpack it. +Replace `stable` with `develop`, if you want to run the develop branch. -# Move the release to the home directory and delete temporary files -sudo -Hu pleroma " -mv /tmp/release/* ~pleroma/ -rmdir /tmp/release -rm /tmp/pleroma.zip -" +```sh +sudo -Hu pleroma curl "https://git.pleroma.social/api/packages/pleroma/generic/pleroma-otp-stable-$FLAVOUR/latest/pleroma.zip" -o /tmp/pleroma.zip +sudo -Hu pleroma unzip /tmp/pleroma.zip -d /tmp/ +``` -# Start the instance to verify that everything is working as expected +Move the release to the home directory and delete temporary files: + +```sh +sudo -Hu pleroma mv /tmp/release/* ~pleroma/ +sudo -Hu pleroma rmdir /tmp/release +sudo -Hu pleroma rm /tmp/pleroma.zip +``` + +Start the instance to verify that everything is working as expected: + +```sh sudo -Hu pleroma "./bin/pleroma daemon" +``` -# Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly +Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly: + +```sh sleep 20 && curl http://localhost:4000/api/v1/instance +``` -# Stop the instance +Stop the instance: + +```sh sudo -Hu pleroma "./bin/pleroma stop" ``` diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md index 5fc1db21e..0f296a9f6 100644 --- a/docs/installation/otp_en.md +++ b/docs/installation/otp_en.md @@ -130,60 +130,90 @@ Restart PostgreSQL to apply configuration changes: ``` ### Installing Pleroma +Create a Pleroma user: + ```sh -# Create a Pleroma user adduser --system --shell /bin/false --home /opt/pleroma pleroma +``` -# Set the flavour environment variable to the string you got in Detecting flavour section. -# For example if the flavour is `amd64-musl` the command will be +Set the flavour environment variable to the string you got in Detecting flavour section. For example if the flavour is `amd64-musl` the command will be: + +```sh export FLAVOUR="amd64-musl" +``` -# Clone the release build into a temporary directory and unpack it -sudo -Hu pleroma " -curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip -unzip /tmp/pleroma.zip -d /tmp/ -" +Clone the release build into a temporary directory and unpack it: -# Move the release to the home directory and delete temporary files -sudo -Hu pleroma " -mv /tmp/release/* /opt/pleroma -rmdir /tmp/release -rm /tmp/pleroma.zip -" -# Create uploads directory and set proper permissions (skip if planning to use a remote uploader) -# Note: It does not have to be `/var/lib/pleroma/uploads`, the config generator will ask about the upload directory later +```sh +sudo -Hu pleroma curl "https://git.pleroma.social/api/packages/pleroma/generic/pleroma-otp-stable-$FLAVOUR/latest/pleroma.zip" -o /tmp/pleroma.zip +sudo -Hu pleroma unzip /tmp/pleroma.zip -d /tmp/ +``` +Move the release to the home directory and delete temporary files: + +```sh +sudo -Hu pleroma mv /tmp/release/* /opt/pleroma +sudo -Hu pleroma rmdir /tmp/release +sudo -Hu pleroma rm /tmp/pleroma.zip +``` + +Create uploads directory and set proper permissions (skip if planning to use a remote uploader). +Note: It does not have to be `/var/lib/pleroma/uploads`, the config generator will ask about the upload directory later. + +```sh mkdir -p /var/lib/pleroma/uploads chown -R pleroma /var/lib/pleroma +``` -# Create custom public files directory (custom emojis, frontend bundle overrides, robots.txt, etc.) -# Note: It does not have to be `/var/lib/pleroma/static`, the config generator will ask about the custom public files directory later +Create custom public files directory (custom emojis, frontend bundle overrides, robots.txt, etc.) +Note: It does not have to be `/var/lib/pleroma/static`, the config generator will ask about the custom public files directory later. + +```sh mkdir -p /var/lib/pleroma/static chown -R pleroma /var/lib/pleroma +``` -# Create a config directory +Create a config directory: + +```sh mkdir -p /etc/pleroma chown -R pleroma /etc/pleroma +``` -# Run the config generator +Run the config generator: + +```sh sudo -Hu pleroma "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql" +``` -# Create the postgres database +Create the postgres database and schema: + +```sh sudo -u postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql" - -# Create the database schema sudo -Hu pleroma "./bin/pleroma_ctl migrate" +``` -# If you have installed RUM indexes uncommend and run -# sudo -Hu pleroma "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/" +(Optional) If you have installed RUM indexes: -# Start the instance to verify that everything is working as expected +```sh +sudo -Hu pleroma "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/" +``` + +Start the instance to verify that everything is working as expected: + +```sh sudo -Hu pleroma "./bin/pleroma daemon" +``` -# Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly +Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly: + +```sh sleep 20 && curl http://localhost:4000/api/v1/instance +``` -# Stop the instance +Stop the instance: + +```sh sudo -Hu pleroma "./bin/pleroma stop" ``` diff --git a/lib/pleroma/reverse_proxy.ex b/lib/pleroma/reverse_proxy.ex index 12e48eadd..ee20303a3 100644 --- a/lib/pleroma/reverse_proxy.ex +++ b/lib/pleroma/reverse_proxy.ex @@ -17,7 +17,6 @@ defmodule Pleroma.ReverseProxy do @max_read_duration :timer.seconds(30) @max_body_length :infinity @failed_request_ttl :timer.seconds(60) - @sniff_bytes 8 * 1024 @methods ~w(GET HEAD) @allowed_mime_types Pleroma.Config.get([Pleroma.Upload, :allowed_mime_types], []) @@ -70,12 +69,7 @@ defmodule Pleroma.ReverseProxy do * `inline_content_types`: * `true` will not alter `content-disposition` (up to the upstream), * `false` will add `content-disposition: attachment` to any request, - * a list of whitelisted content types for which `content-disposition: inline` - is always set (overriding any upstream header) so the media can be embedded - in pages; the filename is derived from the content type - - * `sniff_content_type` (default `false`): detects an image MIME type from the first - response chunk when the upstream type is missing or `application/octet-stream`. + * a list of whitelisted content types * `req_headers`, `resp_headers` additional headers. @@ -112,7 +106,6 @@ defmodule Pleroma.ReverseProxy do | {:req_headers, [{String.t(), String.t()}]} | {:resp_headers, [{String.t(), String.t()}]} | {:inline_content_types, boolean() | list(String.t())} - | {:sniff_content_type, boolean()} | {:redirect_on_failure, boolean()} @spec call(Plug.Conn.t(), String.t(), list(option())) :: Plug.Conn.t() @@ -228,30 +221,11 @@ defmodule Pleroma.ReverseProxy do defp response(conn, client, url, status, headers, opts) do Logger.debug("#{__MODULE__} #{status} #{url} #{inspect(headers)}") - case maybe_prefetch_for_content_type(headers, client, opts) do - {_headers, client, {:error, {:upstream, error}}} -> - Logger.warning( - "#{__MODULE__} request to #{url} failed before streaming: #{inspect(error)}" - ) - - client().close(client) - track_failed_url(url, error, opts) - - conn - |> error_or_redirect(url, 500, "Request failed", opts) - |> halt() - - {headers, client, prefetched} -> - stream_response(conn, client, url, status, headers, opts, prefetched) - end - end - - defp stream_response(conn, client, url, status, headers, opts, prefetched) do result = conn |> put_resp_headers(build_resp_headers(headers, opts)) |> send_chunked(status) - |> chunk_reply(client, opts, prefetched) + |> chunk_reply(client, opts) case result do {:ok, conn} -> @@ -272,29 +246,18 @@ defmodule Pleroma.ReverseProxy do end end - defp chunk_reply(conn, client, opts, :none) do + defp chunk_reply(conn, client, opts) do chunk_reply(conn, client, opts, 0, 0) end - defp chunk_reply(conn, _client, _opts, :done), do: {:ok, conn} - defp chunk_reply(conn, _client, _opts, {:error, error}), do: {:error, error, conn} - - defp chunk_reply(conn, client, opts, {:ok, data, duration}) do - with :ok <- - body_size_constraint( - byte_size(data), - Keyword.get(opts, :max_body_length, @max_body_length) - ), - {:ok, conn} <- write_chunk(conn, data) do - chunk_reply(conn, client, opts, byte_size(data), duration) - else - {:error, {:downstream, error}} -> {:error, {:downstream, error}, conn} - {:error, error} -> {:error, {:upstream, error}, conn} - end - end - defp chunk_reply(conn, client, opts, sent_so_far, duration) do - with {:ok, data, client, duration} <- read_chunk(client, duration, opts), + with {:ok, duration} <- + check_read_duration( + duration, + Keyword.get(opts, :max_read_duration, @max_read_duration) + ), + {:ok, data, client} <- client().stream_body(client), + {:ok, duration} <- increase_read_duration(duration), sent_so_far = sent_so_far + byte_size(data), :ok <- body_size_constraint( @@ -310,24 +273,6 @@ defmodule Pleroma.ReverseProxy do end end - defp read_chunk(client, duration, opts) do - result = - with {:ok, timer} <- - check_read_duration( - duration, - Keyword.get(opts, :max_read_duration, @max_read_duration) - ), - {:ok, data, client} <- client().stream_body(client), - {:ok, duration} <- increase_read_duration(timer) do - {:ok, data, client, duration} - end - - case result do - {:error, error} -> {:error, {:upstream, error}} - result -> result - end - end - defp write_chunk(conn, data) do case chunk(conn, data) do {:error, error} -> {:error, {:downstream, error}} @@ -335,54 +280,6 @@ defmodule Pleroma.ReverseProxy do end end - defp maybe_prefetch_for_content_type(headers, client, opts) do - if Keyword.get(opts, :sniff_content_type, false) and generic_content_type?(headers) do - case read_chunk(client, 0, opts) do - {:ok, data, client, duration} -> - {maybe_put_image_content_type(headers, data), client, {:ok, data, duration}} - - :done -> - {headers, client, :done} - - {:error, error} -> - {headers, client, {:error, error}} - end - else - {headers, client, :none} - end - end - - defp generic_content_type?(headers) do - headers - |> get_content_type() - |> String.trim() - |> String.downcase() - |> then(&(&1 in ["", "application/octet-stream"])) - end - - defp maybe_put_image_content_type(headers, data) do - with false <- data == "", - {:ok, %{mime_type: "image/" <> _ = content_type}} <- - Majic.perform({:bytes, binary_part(data, 0, min(byte_size(data), @sniff_bytes))}, - pool: Pleroma.MajicPool - ) do - [ - {"content-type", content_type} - | Enum.reject(headers, fn {key, _} -> key == "content-type" end) - ] - else - _ -> headers - end - rescue - error -> - Logger.debug("#{__MODULE__}: content-type sniffing failed: #{Exception.message(error)}") - headers - catch - kind, reason -> - Logger.debug("#{__MODULE__}: content-type sniffing failed: #{kind}: #{inspect(reason)}") - headers - end - defp head_response(conn, url, code, headers, opts) do Logger.debug("#{__MODULE__} #{code} #{url} #{inspect(headers)}") @@ -430,33 +327,16 @@ defmodule Pleroma.ReverseProxy do |> build_req_range_or_encoding_header(opts) |> build_req_user_agent_header(opts) |> merge_headers(Keyword.get(opts, :req_headers, [])) - |> maybe_force_identity_encoding(opts) - end - - defp merge_headers(headers, extra_headers) do - Enum.reduce(extra_headers, headers, fn {key, value}, headers -> - List.keystore(headers, String.downcase(key), 0, {String.downcase(key), value}) - end) - end - - defp maybe_force_identity_encoding(headers, opts) do - if Keyword.get(opts, :sniff_content_type, false) do - List.keystore(headers, "accept-encoding", 0, {"accept-encoding", "identity"}) - else - headers - end end # Disable content-encoding if any @range_headers are requested (see #1823). defp build_req_range_or_encoding_header(headers, _opts) do range? = Enum.any?(headers, fn {header, _} -> Enum.member?(@range_headers, header) end) - cond do - range? && List.keymember?(headers, "accept-encoding", 0) -> - List.keydelete(headers, "accept-encoding", 0) - - true -> - headers + if range? && List.keymember?(headers, "accept-encoding", 0) do + List.keydelete(headers, "accept-encoding", 0) + else + headers end end @@ -479,6 +359,12 @@ defmodule Pleroma.ReverseProxy do |> ensure_no_transform() end + defp merge_headers(headers, extra_headers) do + Enum.reduce(extra_headers, headers, fn {key, value}, headers -> + List.keystore(headers, String.downcase(key), 0, {String.downcase(key), value}) + end) + end + defp ensure_no_transform(headers) do {_, cache_control} = List.keyfind(headers, "cache-control", 0, {"cache-control", @default_cache_control_header}) @@ -568,20 +454,7 @@ defmodule Pleroma.ReverseProxy do replace_header(headers, "content-disposition", disposition) else - if opt == true do - headers - else - name = inline_filename(content_type) - - disposition = - if name do - "inline; filename=\"#{name}\"" - else - "inline" - end - - replace_header(headers, "content-disposition", disposition) - end + headers end end @@ -589,13 +462,6 @@ defmodule Pleroma.ReverseProxy do [{key, value} | Enum.reject(headers, fn {header, _} -> header == key end)] end - defp inline_filename(content_type) do - case MIME.extensions(content_type) do - [ext | _] when ext != "" -> "inline.#{ext}" - _ -> nil - end - end - defp header_length_constraint(headers, limit) do lengths = for {"content-length", value} <- headers, @@ -640,9 +506,7 @@ defmodule Pleroma.ReverseProxy do end end - defp check_read_duration(_, _), do: {:ok, :no_duration_limit} - - defp increase_read_duration(:no_duration_limit), do: {:ok, :no_duration_limit} + defp check_read_duration(_, _), do: {:ok, :no_duration_limit, :no_duration_limit} defp increase_read_duration({previous_duration, started}) when is_integer(previous_duration) and is_integer(started) do diff --git a/lib/pleroma/web/api_spec/operations/notification_operation.ex b/lib/pleroma/web/api_spec/operations/notification_operation.ex index 6c8f7d5e9..740f7645d 100644 --- a/lib/pleroma/web/api_spec/operations/notification_operation.ex +++ b/lib/pleroma/web/api_spec/operations/notification_operation.ex @@ -8,6 +8,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do alias Pleroma.Web.ApiSpec.Schemas.Account alias Pleroma.Web.ApiSpec.Schemas.ApiError alias Pleroma.Web.ApiSpec.Schemas.BooleanLike + alias Pleroma.Web.ApiSpec.Schemas.ChatMessage alias Pleroma.Web.ApiSpec.Schemas.Status alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope @@ -304,7 +305,25 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do page_max_id: %Schema{type: :string, nullable: true}, latest_page_notification_at: %Schema{type: :string, format: :"date-time", nullable: true}, sample_account_ids: %Schema{type: :array, items: %Schema{type: :string}}, - status_id: %Schema{type: :string, nullable: true} + status_id: %Schema{type: :string, nullable: true}, + target_id: %Schema{ + type: :string, + description: "ID of the target account for a move notification" + }, + emoji: %Schema{ + type: :string, + description: "Emoji used for an emoji reaction notification" + }, + emoji_url: %Schema{ + type: :string, + nullable: true, + description: "URL of the custom emoji used for an emoji reaction notification" + }, + chat_message: ChatMessage, + report: %Schema{ + type: :object, + description: "Report embedded in a report notification" + } }, required: [ :group_key, diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex index 33d4b2924..eadfac4a0 100644 --- a/lib/pleroma/web/mastodon_api/views/notification_view.ex +++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex @@ -101,13 +101,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do |> Enum.filter(& &1) |> Enum.uniq_by(& &1[:id]) - actors = + accounts = notification_groups |> List.flatten() - |> notification_actors() + |> notification_accounts() %{ - accounts: AccountView.render("index.json", %{users: actors, for: reading_user}), + accounts: AccountView.render("index.json", %{users: accounts, for: reading_user}), statuses: statuses, notification_groups: Enum.map( @@ -191,7 +191,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do defp render_group( [%Notification{} = notification | _] = notifications, - _reading_user, + reading_user, grouped_types, notification_group_counts, notification_group_bounds, @@ -237,13 +237,49 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do response end - if status_activity do - Map.put(response, :status_id, to_string(status_activity.id)) - else - response + response = + if status_activity do + Map.put(response, :status_id, to_string(status_activity.id)) + else + response + end + + put_group_details(response, notification, reading_user) + end + + defp put_group_details(response, %Notification{type: "move", activity: activity}, _reading_user) do + case User.get_cached_by_ap_id(activity.data["target"]) do + %User{id: id} -> Map.put(response, :target_id, to_string(id)) + _ -> response end end + defp put_group_details( + response, + %Notification{type: "pleroma:emoji_reaction", activity: activity}, + _reading_user + ) do + put_emoji(response, activity) + end + + defp put_group_details( + response, + %Notification{type: "pleroma:chat_mention", activity: activity}, + reading_user + ) do + put_chat_message(response, activity, reading_user, %{}) + end + + defp put_group_details( + response, + %Notification{type: "pleroma:report", activity: activity}, + _reading_user + ) do + put_report(response, activity) + end + + defp put_group_details(response, _notification, _reading_user), do: response + defp status_activity_for_group([%Notification{} = notification | _], grouped_types) do status_activity_for(notification, grouped_types) end @@ -287,6 +323,19 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do |> Enum.uniq_by(& &1.id) end + defp notification_accounts(notifications) do + move_targets = + notifications + |> Enum.filter(&(&1.type == "move")) + |> Enum.map(&User.get_cached_by_ap_id(&1.activity.data["target"])) + |> Enum.filter(& &1) + + notifications + |> notification_actors() + |> Kernel.++(move_targets) + |> Enum.uniq_by(& &1.id) + end + defp put_emoji(response, activity) do response |> Map.put(:emoji, activity.data["content"]) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 356e8fce5..4625be47c 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -631,7 +631,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do String.contains?(media_type, "image") -> "image" String.contains?(media_type, "video") -> "video" String.contains?(media_type, "audio") -> "audio" - attachment["type"] == "Image" -> "image" true -> "unknown" end diff --git a/lib/pleroma/web/media_proxy/media_proxy_controller.ex b/lib/pleroma/web/media_proxy/media_proxy_controller.ex index 93f692008..a0aafc32e 100644 --- a/lib/pleroma/web/media_proxy/media_proxy_controller.ex +++ b/lib/pleroma/web/media_proxy/media_proxy_controller.ex @@ -208,7 +208,6 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do defp media_proxy_opts do Config.get([:media_proxy, :proxy_opts], []) - |> Keyword.put_new(:sniff_content_type, true) end defp sandbox(conn, _params) do diff --git a/mix.exs b/mix.exs index 4f82b1f53..140aafb98 100644 --- a/mix.exs +++ b/mix.exs @@ -172,6 +172,14 @@ defmodule Pleroma.Mixfile do {:gen_smtp, "~> 0.15"}, {:mua, "~> 0.2.4"}, {:mail, "~> 0.3.1"}, + # Fixes intermittent failure to compile due to an old pc version, + # upstream hasn't made a release with the fix yet. + # https://github.com/Vagabond/erlang-syslog/pull/44 + {:syslog, + git: "https://github.com/Vagabond/erlang-syslog", + ref: "614a1fde7a8654bee2815b599bbdaae1bb0323b5", + override: true, + runtime: false}, {:ex_syslogger, "~> 1.5"}, {:floki, "~> 0.38"}, {:timex, "~> 3.7"}, diff --git a/mix.lock b/mix.lock index a4db3f68d..bca6f777b 100644 --- a/mix.lock +++ b/mix.lock @@ -139,7 +139,7 @@ "statistex": {:hex, :statistex, "1.1.0", "7fec1eb2f580a0d2c1a05ed27396a084ab064a40cfc84246dbfb0c72a5c761e5", [:mix], [], "hexpm", "f5950ea26ad43246ba2cce54324ac394a4e7408fdcf98b8e230f503a0cba9cf5"}, "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, "swoosh": {:hex, :swoosh, "1.16.12", "cbb24ad512f2f7f24c7a469661c188a00a8c2cd64e0ab54acd1520f132092dfd", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0e262df1ae510d59eeaaa3db42189a2aa1b3746f73771eb2616fc3f7ee63cc20"}, - "syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"}, + "syslog": {:git, "https://github.com/Vagabond/erlang-syslog", "614a1fde7a8654bee2815b599bbdaae1bb0323b5", [ref: "614a1fde7a8654bee2815b599bbdaae1bb0323b5"]}, "table_rex": {:hex, :table_rex, "4.1.0", "fbaa8b1ce154c9772012bf445bfb86b587430fb96f3b12022d3f35ee4a68c918", [:mix], [], "hexpm", "95932701df195d43bc2d1c6531178fc8338aa8f38c80f098504d529c43bc2601"}, "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"}, diff --git a/test/pleroma/reverse_proxy_test.exs b/test/pleroma/reverse_proxy_test.exs index bf0a809c4..156b7d7ed 100644 --- a/test/pleroma/reverse_proxy_test.exs +++ b/test/pleroma/reverse_proxy_test.exs @@ -579,56 +579,6 @@ defmodule Pleroma.ReverseProxyTest do assert Conn.get_resp_header(conn, "content-type") == ["application/octet-stream"] end - test "sniffs and preserves an image body with a generic content type", %{conn: conn} do - body = File.read!("test/fixtures/image.jpg") - - ClientMock - |> expect(:request, fn :get, "/extensionless", headers, _, _ -> - assert {"accept-encoding", "identity"} in headers - {:ok, 200, [{"content-type", "application/octet-stream"}], %{body: body}} - end) - |> expect(:stream_body, fn %{body: ^body} = client -> - {:ok, body, Map.delete(client, :body)} - end) - |> expect(:stream_body, fn %{} -> :done end) - - conn = - ReverseProxy.call(conn, "/extensionless", - sniff_content_type: true, - max_read_duration: :infinity, - req_headers: [{"accept-encoding", "gzip"}] - ) - - assert conn.resp_body == body - assert Conn.get_resp_header(conn, "content-type") == ["image/jpeg"] - - assert Conn.get_resp_header(conn, "content-disposition") == [ - "inline; filename=\"inline.jpg\"" - ] - end - - test "redirects a content sniffing failure before committing the response", %{conn: conn} do - url = "https://example.com/extensionless" - - ClientMock - |> expect(:request, fn :get, ^url, _, _, _ -> - {:ok, 200, [{"content-type", "application/octet-stream"}], %{url: url}} - end) - |> expect(:stream_body, fn _ -> {:error, :closed} end) - |> expect(:close, fn _ -> :ok end) - - conn = - ReverseProxy.call(conn, url, - sniff_content_type: true, - redirect_on_failure: true - ) - - assert conn.status == 302 - assert Conn.get_resp_header(conn, "location") == [url] - assert conn.state == :sent - assert Cachex.get(:failed_proxy_url_cache, url) == {:ok, true} - end - test "preserves a generic content type for a non-image body", %{conn: conn} do body = "not an image" @@ -823,24 +773,6 @@ defmodule Pleroma.ReverseProxyTest do conn = ReverseProxy.call(conn, "/disposition") assert {"content-type", "image/gif"} in conn.resp_headers - assert {"content-disposition", "inline; filename=\"inline.gif\""} in conn.resp_headers - end - - test "forces inline for inline content types overriding upstream attachment", %{ - conn: conn - } do - disposition_headers_mock([ - {"content-type", "image/png"}, - {"content-disposition", "attachment; filename=\"filename.png\""}, - {"content-disposition", "attachment; filename=\"duplicate.png\""}, - {"content-length", "0"} - ]) - - conn = ReverseProxy.call(conn, "/disposition") - - [disposition] = Conn.get_resp_header(conn, "content-disposition") - assert String.starts_with?(disposition, "inline") - refute String.starts_with?(disposition, "attachment") end test "with content-disposition header", %{conn: conn} do @@ -853,50 +785,6 @@ defmodule Pleroma.ReverseProxyTest do assert {"content-disposition", "attachment; filename=\"filename.jpg\""} in conn.resp_headers end - - test "with inline_content_types: true leaves upstream headers untouched", %{ - conn: conn - } do - # opt == true: the proxy must not synthesise or rewrite content-disposition. - disposition_headers_mock([ - {"content-type", "image/png"}, - {"content-disposition", "attachment; filename=\"upstream.png\""}, - {"content-length", "0"} - ]) - - conn = ReverseProxy.call(conn, "/disposition", inline_content_types: true) - - assert {"content-disposition", "attachment; filename=\"upstream.png\""} in conn.resp_headers - end - - test "forces bare inline for a whitelisted type with no MIME extension", %{ - conn: conn - } do - # image/x-foo-bar has no entry in MIME's database, so inline_filename/1 - # returns nil and the disposition should be the bare token "inline". - disposition_headers_mock([ - {"content-type", "image/x-foo-bar"}, - {"content-length", "0"} - ]) - - conn = ReverseProxy.call(conn, "/disposition", inline_content_types: ["image/x-foo-bar"]) - - [disposition] = Conn.get_resp_header(conn, "content-disposition") - assert disposition == "inline" - end - - test "serves modern browser image types inline", %{conn: conn} do - disposition_headers_mock([ - {"content-type", "image/webp"}, - {"content-length", "0"} - ]) - - conn = ReverseProxy.call(conn, "/disposition") - - assert Conn.get_resp_header(conn, "content-disposition") == [ - "inline; filename=\"inline.webp\"" - ] - end end describe "content-type sanitisation" do diff --git a/test/pleroma/web/mastodon_api/views/notification_view_test.exs b/test/pleroma/web/mastodon_api/views/notification_view_test.exs index 2d0801589..e6fb31e28 100644 --- a/test/pleroma/web/mastodon_api/views/notification_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/notification_view_test.exs @@ -65,6 +65,15 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], recipient, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{ + notifications: [notification], + for: recipient + }) + + assert [group] = grouped.notification_groups + assert group.chat_message == expected.chat_message end test "Mention notification" do @@ -182,6 +191,16 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], follower, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{ + notifications: [notification], + for: follower + }) + + assert [group] = grouped.notification_groups + assert group.target_id == new_user.id + assert Enum.any?(grouped.accounts, &(&1.id == new_user.id)) end test "EmojiReact notification" do @@ -210,6 +229,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], user, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{notifications: [notification], for: user}) + + assert [group] = grouped.notification_groups + assert group.emoji == expected.emoji + assert group.emoji_url == expected.emoji_url end test "EmojiReact custom emoji notification" do @@ -295,6 +321,15 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do } test_notifications_rendering([notification], moderator_user, [expected]) + + grouped = + NotificationView.render("grouped_index.json", %{ + notifications: [notification], + for: moderator_user + }) + + assert [group] = grouped.notification_groups + assert group.report == expected.report end test "Edit notification" do diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs index 73adb196a..f7b815ed7 100644 --- a/test/pleroma/web/mastodon_api/views/status_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/status_view_test.exs @@ -668,23 +668,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do assert expected == StatusView.render("attachment.json", %{attachment: object}) assert_schema(expected, "Attachment", api_spec) end - - test "uses the ActivityStreams image type when the MIME type is generic" do - object = %{ - "type" => "Image", - "url" => [ - %{ - "mediaType" => "application/octet-stream", - "href" => "https://example.com/extensionless" - } - ] - } - - attachment = StatusView.render("attachment.json", %{attachment: object}) - - assert attachment.type == "image" - assert attachment.pleroma.mime_type == "application/octet-stream" - end end test "put the url advertised in the Activity in to the url attribute" do diff --git a/test/pleroma/web/media_proxy/media_proxy_controller_test.exs b/test/pleroma/web/media_proxy/media_proxy_controller_test.exs index 800159c21..f7e52483c 100644 --- a/test/pleroma/web/media_proxy/media_proxy_controller_test.exs +++ b/test/pleroma/web/media_proxy/media_proxy_controller_test.exs @@ -71,10 +71,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do test "it performs ReverseProxy.call with valid signature", %{conn: conn, url: url} do with_mock Pleroma.ReverseProxy, - call: fn _conn, _url, opts -> - assert opts[:sniff_content_type] - %Conn{status: :success} - end do + call: fn _conn, _url, _opts -> %Conn{status: :success} end do assert %Conn{status: :success} = get(conn, url) end end