Merge commit '07fed0fda2473fc4e1e3b01e863217391fd2902f'; commit 'e3173a279dad89dfce6eae89368ad3ba180c0490'; commit '21787546c01069d1d1d8261f0bc37d13a73122a9'; commit 'fda34591cefad94277385311c6391d1ca2adb36c'; commit '0ada3fe823a3c2e6c5835431bdacfbdb8b3d02a7'; commit '32d263cb905dd7fffd43a4955295af0b2b378537'; commit 'c9e4200ed2167772294fceb4f282979b5ea04981'; commit '3ff9c5e2a67ab83c2abdb14cd246dea059079e75'; commit 'fa543a936124abee524f9a103c17d2601176dcd4'; commit 'c23b81e399d5be6fc30f4acb1d757d5eb291d8e1' into cycles-phase-1

This commit is contained in:
Alex Gleason 2021-05-30 12:58:24 -05:00
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
32 changed files with 213 additions and 131 deletions

View file

@ -54,6 +54,10 @@
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
# Reduce recompilation time
# https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects
config :phoenix, :plug_init_mode, :runtime
if File.exists?("./config/dev.secret.exs") do if File.exists?("./config/dev.secret.exs") do
import_config "dev.secret.exs" import_config "dev.secret.exs"
else else

View file

@ -133,6 +133,10 @@
ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock, ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock,
logger: Pleroma.LoggerMock logger: Pleroma.LoggerMock
# Reduce recompilation time
# https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects
config :phoenix, :plug_init_mode, :runtime
if File.exists?("./config/test.secret.exs") do if File.exists?("./config/test.secret.exs") do
import_config "test.secret.exs" import_config "test.secret.exs"
else else

View file

@ -0,0 +1,45 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Activity.HTML do
alias Pleroma.HTML
alias Pleroma.Object
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def get_cached_scrubbed_html_for_activity(
content,
scrubbers,
activity,
key \\ "",
callback \\ fn x -> x end
) do
key = "#{key}#{generate_scrubber_signature(scrubbers)}|#{activity.id}"
@cachex.fetch!(:scrubber_cache, key, fn _key ->
object = Object.normalize(activity, fetch: false)
HTML.ensure_scrubbed_html(content, scrubbers, object.data["fake"] || false, callback)
end)
end
def get_cached_stripped_html_for_activity(content, activity, key) do
get_cached_scrubbed_html_for_activity(
content,
FastSanitize.Sanitizer.StripTags,
activity,
key,
&HtmlEntities.decode/1
)
end
defp generate_scrubber_signature(scrubber) when is_atom(scrubber) do
generate_scrubber_signature([scrubber])
end
defp generate_scrubber_signature(scrubbers) do
Enum.reduce(scrubbers, "", fn scrubber, signature ->
"#{signature}#{to_string(scrubber)}"
end)
end
end

View file

@ -3,7 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Config.Loader do defmodule Pleroma.Config.Loader do
@reject_keys [ defp reject_keys,
do: [
Pleroma.Repo, Pleroma.Repo,
Pleroma.Web.Endpoint, Pleroma.Web.Endpoint,
:env, :env,
@ -12,7 +13,8 @@ defmodule Pleroma.Config.Loader do
:swarm :swarm
] ]
@reject_groups [ defp reject_groups,
do: [
:postgrex, :postgrex,
:tesla :tesla
] ]
@ -52,7 +54,7 @@ defp filter(configs) do
@spec filter_group(atom(), keyword()) :: keyword() @spec filter_group(atom(), keyword()) :: keyword()
def filter_group(group, configs) do def filter_group(group, configs) do
Enum.reject(configs[group], fn {key, _v} -> Enum.reject(configs[group], fn {key, _v} ->
key in @reject_keys or group in @reject_groups or key in reject_keys() or group in reject_groups() or
(group == :phoenix and key == :serve_endpoints) (group == :phoenix and key == :serve_endpoints)
end) end)
end end

View file

@ -13,7 +13,8 @@ defmodule Pleroma.Config.TransferTask do
@type env() :: :test | :benchmark | :dev | :prod @type env() :: :test | :benchmark | :dev | :prod
@reboot_time_keys [ defp reboot_time_keys,
do: [
{:pleroma, :hackney_pools}, {:pleroma, :hackney_pools},
{:pleroma, :chat}, {:pleroma, :chat},
{:pleroma, Oban}, {:pleroma, Oban},
@ -24,7 +25,8 @@ defmodule Pleroma.Config.TransferTask do
{:pleroma, :connections_pool} {:pleroma, :connections_pool}
] ]
@reboot_time_subkeys [ defp reboot_time_subkeys,
do: [
{:pleroma, Pleroma.Captcha, [:seconds_valid]}, {:pleroma, Pleroma.Captcha, [:seconds_valid]},
{:pleroma, Pleroma.Upload, [:proxy_remote]}, {:pleroma, Pleroma.Upload, [:proxy_remote]},
{:pleroma, :instance, [:upload_limit]}, {:pleroma, :instance, [:upload_limit]},
@ -165,12 +167,12 @@ def pleroma_need_restart?(group, key, value) do
end end
defp group_and_key_need_reboot?(group, key) do defp group_and_key_need_reboot?(group, key) do
Enum.any?(@reboot_time_keys, fn {g, k} -> g == group and k == key end) Enum.any?(reboot_time_keys(), fn {g, k} -> g == group and k == key end)
end end
defp group_and_subkey_need_reboot?(group, key, value) do defp group_and_subkey_need_reboot?(group, key, value) do
Keyword.keyword?(value) and Keyword.keyword?(value) and
Enum.any?(@reboot_time_subkeys, fn {g, k, subkeys} -> Enum.any?(reboot_time_subkeys(), fn {g, k, subkeys} ->
g == group and k == key and g == group and k == key and
Enum.any?(Keyword.keys(value), &(&1 in subkeys)) Enum.any?(Keyword.keys(value), &(&1 in subkeys))
end) end)

View file

@ -11,9 +11,7 @@ defmodule Pleroma.Gun do
@callback await(pid(), reference()) :: {:response, :fin, 200, []} @callback await(pid(), reference()) :: {:response, :fin, 200, []}
@callback set_owner(pid(), pid()) :: :ok @callback set_owner(pid(), pid()) :: :ok
@api Pleroma.Config.get([Pleroma.Gun], Pleroma.Gun.API) defp api, do: Pleroma.Config.get([Pleroma.Gun], Pleroma.Gun.API)
defp api, do: @api
def open(host, port, opts), do: api().open(host, port, opts) def open(host, port, opts), do: api().open(host, port, opts)

View file

@ -5,11 +5,11 @@
defmodule Pleroma.Gun.ConnectionPool.Reclaimer do defmodule Pleroma.Gun.ConnectionPool.Reclaimer do
use GenServer, restart: :temporary use GenServer, restart: :temporary
@registry Pleroma.Gun.ConnectionPool defp registry, do: Pleroma.Gun.ConnectionPool
def start_monitor do def start_monitor do
pid = pid =
case :gen_server.start(__MODULE__, [], name: {:via, Registry, {@registry, "reclaimer"}}) do case :gen_server.start(__MODULE__, [], name: {:via, Registry, {registry(), "reclaimer"}}) do
{:ok, pid} -> {:ok, pid} ->
pid pid
@ -46,7 +46,7 @@ def handle_continue(:reclaim, _) do
# {worker_pid, crf, last_reference} end) # {worker_pid, crf, last_reference} end)
unused_conns = unused_conns =
Registry.select( Registry.select(
@registry, registry(),
[ [
{{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}], [{{:"$1", :"$3", :"$4"}}]} {{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}], [{{:"$1", :"$3", :"$4"}}]}
] ]

View file

@ -6,10 +6,10 @@ defmodule Pleroma.Gun.ConnectionPool.Worker do
alias Pleroma.Gun alias Pleroma.Gun
use GenServer, restart: :temporary use GenServer, restart: :temporary
@registry Pleroma.Gun.ConnectionPool defp registry, do: Pleroma.Gun.ConnectionPool
def start_link([key | _] = opts) do def start_link([key | _] = opts) do
GenServer.start_link(__MODULE__, opts, name: {:via, Registry, {@registry, key}}) GenServer.start_link(__MODULE__, opts, name: {:via, Registry, {registry(), key}})
end end
@impl true @impl true
@ -24,7 +24,7 @@ def handle_continue({:connect, [key, uri, opts, client_pid]}, _) do
time = :erlang.monotonic_time(:millisecond) time = :erlang.monotonic_time(:millisecond)
{_, _} = {_, _} =
Registry.update_value(@registry, key, fn _ -> Registry.update_value(registry(), key, fn _ ->
{conn_pid, [client_pid], 1, time} {conn_pid, [client_pid], 1, time}
end) end)
@ -65,7 +65,7 @@ def handle_call(:add_client, {client_pid, _}, %{key: key, protocol: protocol} =
time = :erlang.monotonic_time(:millisecond) time = :erlang.monotonic_time(:millisecond)
{{conn_pid, used_by, _, _}, _} = {{conn_pid, used_by, _, _}, _} =
Registry.update_value(@registry, key, fn {conn_pid, used_by, crf, last_reference} -> Registry.update_value(registry(), key, fn {conn_pid, used_by, crf, last_reference} ->
{conn_pid, [client_pid | used_by], crf(time - last_reference, crf), time} {conn_pid, [client_pid | used_by], crf(time - last_reference, crf), time}
end) end)
@ -92,7 +92,7 @@ def handle_call(:add_client, {client_pid, _}, %{key: key, protocol: protocol} =
@impl true @impl true
def handle_call(:remove_client, {client_pid, _}, %{key: key} = state) do def handle_call(:remove_client, {client_pid, _}, %{key: key} = state) do
{{_conn_pid, used_by, _crf, _last_reference}, _} = {{_conn_pid, used_by, _crf, _last_reference}, _} =
Registry.update_value(@registry, key, fn {conn_pid, used_by, crf, last_reference} -> Registry.update_value(registry(), key, fn {conn_pid, used_by, crf, last_reference} ->
{conn_pid, List.delete(used_by, client_pid), crf, last_reference} {conn_pid, List.delete(used_by, client_pid), crf, last_reference}
end) end)

View file

@ -49,31 +49,6 @@ def filter_tags(html, scrubber) do
def filter_tags(html), do: filter_tags(html, nil) def filter_tags(html), do: filter_tags(html, nil)
def strip_tags(html), do: filter_tags(html, FastSanitize.Sanitizer.StripTags) def strip_tags(html), do: filter_tags(html, FastSanitize.Sanitizer.StripTags)
def get_cached_scrubbed_html_for_activity(
content,
scrubbers,
activity,
key \\ "",
callback \\ fn x -> x end
) do
key = "#{key}#{generate_scrubber_signature(scrubbers)}|#{activity.id}"
@cachex.fetch!(:scrubber_cache, key, fn _key ->
object = Pleroma.Object.normalize(activity, fetch: false)
ensure_scrubbed_html(content, scrubbers, object.data["fake"] || false, callback)
end)
end
def get_cached_stripped_html_for_activity(content, activity, key) do
get_cached_scrubbed_html_for_activity(
content,
FastSanitize.Sanitizer.StripTags,
activity,
key,
&HtmlEntities.decode/1
)
end
def ensure_scrubbed_html( def ensure_scrubbed_html(
content, content,
scrubbers, scrubbers,
@ -92,16 +67,6 @@ def ensure_scrubbed_html(
end end
end end
defp generate_scrubber_signature(scrubber) when is_atom(scrubber) do
generate_scrubber_signature([scrubber])
end
defp generate_scrubber_signature(scrubbers) do
Enum.reduce(scrubbers, "", fn scrubber, signature ->
"#{signature}#{to_string(scrubber)}"
end)
end
def extract_first_external_url_from_object(%{data: %{"content" => content}} = object) def extract_first_external_url_from_object(%{data: %{"content" => content}} = object)
when is_binary(content) do when is_binary(content) do
unless object.data["fake"] do unless object.data["fake"] do

View file

@ -54,8 +54,8 @@ def pool_timeout(pool) do
Config.get([:pools, pool, :recv_timeout], default) Config.get([:pools, pool, :recv_timeout], default)
end end
@prefix Pleroma.Gun.ConnectionPool
def limiter_setup do def limiter_setup do
prefix = Pleroma.Gun.ConnectionPool
wait = Config.get([:connections_pool, :connection_acquisition_wait]) wait = Config.get([:connections_pool, :connection_acquisition_wait])
retries = Config.get([:connections_pool, :connection_acquisition_retries]) retries = Config.get([:connections_pool, :connection_acquisition_retries])
@ -66,7 +66,7 @@ def limiter_setup do
max_waiting = Keyword.get(opts, :max_waiting, 10) max_waiting = Keyword.get(opts, :max_waiting, 10)
result = result =
ConcurrentLimiter.new(:"#{@prefix}.#{name}", max_running, max_waiting, ConcurrentLimiter.new(:"#{prefix}.#{name}", max_running, max_waiting,
wait: wait, wait: wait,
max_retries: retries max_retries: retries
) )

View file

@ -235,16 +235,4 @@ defmacro __using__(which) when is_atom(which) do
def base_url do def base_url do
Pleroma.Web.Endpoint.url() Pleroma.Web.Endpoint.url()
end end
# TODO: Change to Phoenix.Router.routes/1 for Phoenix 1.6.0+
def get_api_routes do
Pleroma.Web.Router.__routes__()
|> Enum.reject(fn r -> r.plug == Pleroma.Web.Fallback.RedirectController end)
|> Enum.map(fn r ->
r.path
|> String.split("/", trim: true)
|> List.first()
end)
|> Enum.uniq()
end
end end

View file

@ -7,26 +7,23 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub
alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.SideEffects
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
@side_effects Config.get([:pipeline, :side_effects], SideEffects) defp side_effects, do: Config.get([:pipeline, :side_effects], SideEffects)
@federator Config.get([:pipeline, :federator], Federator) defp federator, do: Config.get([:pipeline, :federator], Federator)
@object_validator Config.get([:pipeline, :object_validator], ObjectValidator) defp object_validator, do: Config.get([:pipeline, :object_validator], ObjectValidator)
@mrf Config.get([:pipeline, :mrf], MRF) defp mrf, do: Config.get([:pipeline, :mrf], MRF)
@activity_pub Config.get([:pipeline, :activity_pub], ActivityPub) defp activity_pub, do: Config.get([:pipeline, :activity_pub], ActivityPub)
@config Config.get([:pipeline, :config], Config) defp config, do: Config.get([:pipeline, :config], Config)
@spec common_pipeline(map(), keyword()) :: @spec common_pipeline(map(), keyword()) ::
{:ok, Activity.t() | Object.t(), keyword()} | {:error, any()} {:ok, Activity.t() | Object.t(), keyword()} | {:error, any()}
def common_pipeline(object, meta) do def common_pipeline(object, meta) do
case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do
{:ok, {:ok, activity, meta}} -> {:ok, {:ok, activity, meta}} ->
@side_effects.handle_after_transaction(meta) side_effects().handle_after_transaction(meta)
{:ok, activity, meta} {:ok, activity, meta}
{:ok, value} -> {:ok, value} ->
@ -42,13 +39,13 @@ def common_pipeline(object, meta) do
def do_common_pipeline(object, meta) do def do_common_pipeline(object, meta) do
with {_, {:ok, validated_object, meta}} <- with {_, {:ok, validated_object, meta}} <-
{:validate_object, @object_validator.validate(object, meta)}, {:validate_object, object_validator().validate(object, meta)},
{_, {:ok, mrfd_object, meta}} <- {_, {:ok, mrfd_object, meta}} <-
{:mrf_object, @mrf.pipeline_filter(validated_object, meta)}, {:mrf_object, mrf().pipeline_filter(validated_object, meta)},
{_, {:ok, activity, meta}} <- {_, {:ok, activity, meta}} <-
{:persist_object, @activity_pub.persist(mrfd_object, meta)}, {:persist_object, activity_pub().persist(mrfd_object, meta)},
{_, {:ok, activity, meta}} <- {_, {:ok, activity, meta}} <-
{:execute_side_effects, @side_effects.handle(activity, meta)}, {:execute_side_effects, side_effects().handle(activity, meta)},
{_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do {_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do
{:ok, activity, meta} {:ok, activity, meta}
else else
@ -61,7 +58,7 @@ defp maybe_federate(%Object{}, _), do: {:ok, :not_federated}
defp maybe_federate(%Activity{} = activity, meta) do defp maybe_federate(%Activity{} = activity, meta) do
with {:ok, local} <- Keyword.fetch(meta, :local) do with {:ok, local} <- Keyword.fetch(meta, :local) do
do_not_federate = meta[:do_not_federate] || !@config.get([:instance, :federating]) do_not_federate = meta[:do_not_federate] || !config().get([:instance, :federating])
if !do_not_federate and local and not Visibility.is_local_public?(activity) do if !do_not_federate and local and not Visibility.is_local_public?(activity) do
activity = activity =
@ -71,7 +68,7 @@ defp maybe_federate(%Activity{} = activity, meta) do
activity activity
end end
@federator.publish(activity) federator().publish(activity)
{:ok, :federated} {:ok, :federated}
else else
{:ok, :not_federated} {:ok, :not_federated}

View file

@ -13,7 +13,6 @@ defmodule Pleroma.Web.AdminAPI.OAuthAppController do
require Logger require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:put_view, Pleroma.Web.MastodonAPI.AppView)
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.OAuthAppView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.AppView.render(view, opts)
end

View file

@ -9,7 +9,6 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:assign_follower when action != :index) plug(:assign_follower when action != :index)

View file

@ -13,7 +13,6 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController) action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:create, :create2]) plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:create, :create2])
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
plug(OAuthScopesPlug, %{scopes: ["read:media"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["read:media"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action != :show) plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action != :show)

View file

@ -37,8 +37,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
when action in [:public, :hashtag] when action in [:public, :hashtag]
) )
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TimelineOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TimelineOperation
# GET /api/v1/timelines/home # GET /api/v1/timelines/home

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.FollowRequestView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.AccountView.render(view, opts)
end

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.MediaView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.StatusView.render(view, opts)
end

View file

@ -254,7 +254,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
content_html = content_html =
content content
|> HTML.get_cached_scrubbed_html_for_activity( |> Activity.HTML.get_cached_scrubbed_html_for_activity(
User.html_filter_policy(opts[:for]), User.html_filter_policy(opts[:for]),
activity, activity,
"mastoapi:content" "mastoapi:content"
@ -262,7 +262,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
content_plaintext = content_plaintext =
content content
|> HTML.get_cached_stripped_html_for_activity( |> Activity.HTML.get_cached_stripped_html_for_activity(
activity, activity,
"mastoapi:content" "mastoapi:content"
) )

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.TimelineView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.StatusView.render(view, opts)
end

View file

@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Metadata.Utils do defmodule Pleroma.Web.Metadata.Utils do
alias Pleroma.Activity
alias Pleroma.Emoji alias Pleroma.Emoji
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.HTML alias Pleroma.HTML
@ -13,7 +14,7 @@ def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do
# html content comes from DB already encoded, decode first and scrub after # html content comes from DB already encoded, decode first and scrub after
|> HtmlEntities.decode() |> HtmlEntities.decode()
|> String.replace(~r/<br\s?\/?>/, " ") |> String.replace(~r/<br\s?\/?>/, " ")
|> HTML.get_cached_stripped_html_for_activity(object, "metadata") |> Activity.HTML.get_cached_stripped_html_for_activity(object, "metadata")
|> Emoji.Formatter.demojify() |> Emoji.Formatter.demojify()
|> HtmlEntities.decode() |> HtmlEntities.decode()
|> Formatter.truncate() |> Formatter.truncate()

View file

@ -47,7 +47,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
plug(RateLimiter, [name: :account_confirmation_resend] when action == :confirmation_resend) plug(RateLimiter, [name: :account_confirmation_resend] when action == :confirmation_resend)
plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe]) plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation

View file

@ -13,7 +13,6 @@ defmodule Pleroma.Web.PleromaAPI.ConversationController do
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:put_view, Pleroma.Web.MastodonAPI.ConversationView)
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:show, :statuses]) plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:show, :statuses])
plug( plug(

View file

@ -14,8 +14,6 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
%{scopes: ["write:notifications"]} when action == :mark_as_read %{scopes: ["write:notifications"]} when action == :mark_as_read
) )
plug(:put_view, Pleroma.Web.MastodonAPI.NotificationView)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaNotificationOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaNotificationOperation
def mark_as_read(%{assigns: %{user: user}, body_params: %{id: notification_id}} = conn, _) do def mark_as_read(%{assigns: %{user: user}, body_params: %{id: notification_id}} = conn, _) do

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.AccountView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.AccountView.render(view, opts)
end

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.ConversationView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.ConversationView.render(view, opts)
end

View file

@ -0,0 +1,10 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.NotificationView do
use Pleroma.Web, :view
alias Pleroma.Web.MastodonAPI
def render(view, opts), do: MastodonAPI.NotificationView.render(view, opts)
end

View file

@ -10,7 +10,7 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do
""" """
@behaviour Plug @behaviour Plug
@api_routes Pleroma.Web.get_api_routes() @api_routes Pleroma.Web.Router.get_api_routes()
def file_path(path, frontend_type \\ :primary) do def file_path(path, frontend_type \\ :primary) do
if configuration = Pleroma.Config.get([:frontends, frontend_type]) do if configuration = Pleroma.Config.get([:frontends, frontend_type]) do

View file

@ -140,6 +140,10 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug) plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug)
end end
pipeline :static_fe do
plug(Pleroma.Web.Plugs.StaticFEPlug)
end
scope "/api/v1/pleroma", Pleroma.Web.TwitterAPI do scope "/api/v1/pleroma", Pleroma.Web.TwitterAPI do
pipe_through(:pleroma_api) pipe_through(:pleroma_api)
@ -631,7 +635,7 @@ defmodule Pleroma.Web.Router do
scope "/", Pleroma.Web do scope "/", Pleroma.Web do
# Note: html format is supported only if static FE is enabled # Note: html format is supported only if static FE is enabled
# Note: http signature is only considered for json requests (no auth for non-json requests) # Note: http signature is only considered for json requests (no auth for non-json requests)
pipe_through([:accepts_html_json, :http_signature, Pleroma.Web.Plugs.StaticFEPlug]) pipe_through([:accepts_html_json, :http_signature, :static_fe])
get("/objects/:uuid", OStatus.OStatusController, :object) get("/objects/:uuid", OStatus.OStatusController, :object)
get("/activities/:uuid", OStatus.OStatusController, :activity) get("/activities/:uuid", OStatus.OStatusController, :activity)
@ -645,7 +649,7 @@ defmodule Pleroma.Web.Router do
scope "/", Pleroma.Web do scope "/", Pleroma.Web do
# Note: html format is supported only if static FE is enabled # Note: html format is supported only if static FE is enabled
# Note: http signature is only considered for json requests (no auth for non-json requests) # Note: http signature is only considered for json requests (no auth for non-json requests)
pipe_through([:accepts_html_xml_json, :http_signature, Pleroma.Web.Plugs.StaticFEPlug]) pipe_through([:accepts_html_xml_json, :http_signature, :static_fe])
# Note: returns user _profile_ for json requests, redirects to user _feed_ for non-json ones # Note: returns user _profile_ for json requests, redirects to user _feed_ for non-json ones
get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed) get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed)
@ -653,7 +657,7 @@ defmodule Pleroma.Web.Router do
scope "/", Pleroma.Web do scope "/", Pleroma.Web do
# Note: html format is supported only if static FE is enabled # Note: html format is supported only if static FE is enabled
pipe_through([:accepts_html_xml, Pleroma.Web.Plugs.StaticFEPlug]) pipe_through([:accepts_html_xml, :static_fe])
get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed) get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed)
end end
@ -764,11 +768,11 @@ defmodule Pleroma.Web.Router do
get("/embed/:id", EmbedController, :show) get("/embed/:id", EmbedController, :show)
end end
scope "/proxy/", Pleroma.Web.MediaProxy do scope "/proxy/", Pleroma.Web do
get("/preview/:sig/:url", MediaProxyController, :preview) get("/preview/:sig/:url", MediaProxy.MediaProxyController, :preview)
get("/preview/:sig/:url/:filename", MediaProxyController, :preview) get("/preview/:sig/:url/:filename", MediaProxy.MediaProxyController, :preview)
get("/:sig/:url", MediaProxyController, :remote) get("/:sig/:url", MediaProxy.MediaProxyController, :remote)
get("/:sig/:url/:filename", MediaProxyController, :remote) get("/:sig/:url/:filename", MediaProxy.MediaProxyController, :remote)
end end
if Pleroma.Config.get(:env) == :dev do if Pleroma.Config.get(:env) == :dev do
@ -821,4 +825,16 @@ defmodule Pleroma.Web.Router do
options("/*path", RedirectController, :empty) options("/*path", RedirectController, :empty)
end end
# TODO: Change to Phoenix.Router.routes/1 for Phoenix 1.6.0+
def get_api_routes do
__MODULE__.__routes__()
|> Enum.reject(fn r -> r.plug == Pleroma.Web.Fallback.RedirectController end)
|> Enum.map(fn r ->
r.path
|> String.split("/", trim: true)
|> List.first()
end)
|> Enum.uniq()
end
end end

View file

@ -14,7 +14,6 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
alias Pleroma.Web.Router.Helpers alias Pleroma.Web.Router.Helpers
plug(:put_layout, :static_fe) plug(:put_layout, :static_fe)
plug(:put_view, Pleroma.Web.StaticFE.StaticFEView)
plug(:assign_id) plug(:assign_id)
@page_keys ["max_id", "min_id", "limit", "since_id", "order"] @page_keys ["max_id", "min_id", "limit", "since_id", "order"]

View file

@ -103,6 +103,6 @@ test "api routes are detected correctly" do
"check_password" "check_password"
] ]
assert expected_routes == Pleroma.Web.get_api_routes() assert expected_routes == Pleroma.Web.Router.get_api_routes()
end end
end end