aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexander Strizhakov <alex.strizhakov@gmail.com>2020-03-16 14:25:55 +0300
committerAlexander Strizhakov <alex.strizhakov@gmail.com>2020-03-16 14:25:55 +0300
commitf0651730bdf018b713e21ce718719c7781398362 (patch)
tree836e0fbcbb49f0ae78635a268e30013c0e94aea7 /lib
parent98ed0d1c4bd2db354154cc4a1d1e6530eb68f499 (diff)
parentc2527b8c63a4e35b121981efe2c39cc54c77648d (diff)
downloadpleroma-f0651730bdf018b713e21ce718719c7781398362.tar.gz
Merge branch 'develop' into gun
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/activity/ir/topics.ex2
-rw-r--r--lib/pleroma/earmark_renderer.ex256
-rw-r--r--lib/pleroma/plugs/ensure_authenticated_plug.ex19
-rw-r--r--lib/pleroma/plugs/federating_plug.ex18
-rw-r--r--lib/pleroma/plugs/rate_limiter/rate_limiter.ex27
-rw-r--r--lib/pleroma/plugs/remote_ip.ex7
-rw-r--r--lib/pleroma/plugs/static_fe_plug.ex5
-rw-r--r--lib/pleroma/plugs/uploaded_media.ex7
-rw-r--r--lib/pleroma/reverse_proxy/reverse_proxy.ex20
-rw-r--r--lib/pleroma/user.ex56
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex105
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex39
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex7
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex4
-rw-r--r--lib/pleroma/web/admin_api/views/account_view.ex4
-rw-r--r--lib/pleroma/web/common_api/utils.ex2
-rw-r--r--lib/pleroma/web/endpoint.ex2
-rw-r--r--lib/pleroma/web/feed/user_controller.ex7
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/auth_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex19
-rw-r--r--lib/pleroma/web/ostatus/ostatus_controller.ex10
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex33
-rw-r--r--lib/pleroma/web/router.ex6
-rw-r--r--lib/pleroma/web/static_fe/static_fe_controller.ex33
-rw-r--r--lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex2
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex2
-rw-r--r--lib/pleroma/workers/background_worker.ex4
27 files changed, 495 insertions, 203 deletions
diff --git a/lib/pleroma/activity/ir/topics.ex b/lib/pleroma/activity/ir/topics.ex
index 4acc1a3e0..9e65bedad 100644
--- a/lib/pleroma/activity/ir/topics.ex
+++ b/lib/pleroma/activity/ir/topics.ex
@@ -39,7 +39,7 @@ defmodule Pleroma.Activity.Ir.Topics do
end
end
- defp item_creation_tags(tags, %{data: %{"type" => "Create"}} = object, activity) do
+ defp item_creation_tags(tags, object, %{data: %{"type" => "Create"}} = activity) do
tags ++ hashtags_to_topics(object) ++ attachment_topics(object, activity)
end
diff --git a/lib/pleroma/earmark_renderer.ex b/lib/pleroma/earmark_renderer.ex
new file mode 100644
index 000000000..6211a3b4a
--- /dev/null
+++ b/lib/pleroma/earmark_renderer.ex
@@ -0,0 +1,256 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+#
+# This file is derived from Earmark, under the following copyright:
+# Copyright © 2014 Dave Thomas, The Pragmatic Programmers
+# SPDX-License-Identifier: Apache-2.0
+# Upstream: https://github.com/pragdave/earmark/blob/master/lib/earmark/html_renderer.ex
+defmodule Pleroma.EarmarkRenderer do
+ @moduledoc false
+
+ alias Earmark.Block
+ alias Earmark.Context
+ alias Earmark.HtmlRenderer
+ alias Earmark.Options
+
+ import Earmark.Inline, only: [convert: 3]
+ import Earmark.Helpers.HtmlHelpers
+ import Earmark.Message, only: [add_messages_from: 2, get_messages: 1, set_messages: 2]
+ import Earmark.Context, only: [append: 2, set_value: 2]
+ import Earmark.Options, only: [get_mapper: 1]
+
+ @doc false
+ def render(blocks, %Context{options: %Options{}} = context) do
+ messages = get_messages(context)
+
+ {contexts, html} =
+ get_mapper(context.options).(
+ blocks,
+ &render_block(&1, put_in(context.options.messages, []))
+ )
+ |> Enum.unzip()
+
+ all_messages =
+ contexts
+ |> Enum.reduce(messages, fn ctx, messages1 -> messages1 ++ get_messages(ctx) end)
+
+ {put_in(context.options.messages, all_messages), html |> IO.iodata_to_binary()}
+ end
+
+ #############
+ # Paragraph #
+ #############
+ defp render_block(%Block.Para{lnb: lnb, lines: lines, attrs: attrs}, context) do
+ lines = convert(lines, lnb, context)
+ add_attrs(lines, "<p>#{lines.value}</p>", attrs, [], lnb)
+ end
+
+ ########
+ # Html #
+ ########
+ defp render_block(%Block.Html{html: html}, context) do
+ {context, html}
+ end
+
+ defp render_block(%Block.HtmlComment{lines: lines}, context) do
+ {context, lines}
+ end
+
+ defp render_block(%Block.HtmlOneline{html: html}, context) do
+ {context, html}
+ end
+
+ #########
+ # Ruler #
+ #########
+ defp render_block(%Block.Ruler{lnb: lnb, attrs: attrs}, context) do
+ add_attrs(context, "<hr />", attrs, [], lnb)
+ end
+
+ ###########
+ # Heading #
+ ###########
+ defp render_block(
+ %Block.Heading{lnb: lnb, level: level, content: content, attrs: attrs},
+ context
+ ) do
+ converted = convert(content, lnb, context)
+ html = "<h#{level}>#{converted.value}</h#{level}>"
+ add_attrs(converted, html, attrs, [], lnb)
+ end
+
+ ##############
+ # Blockquote #
+ ##############
+
+ defp render_block(%Block.BlockQuote{lnb: lnb, blocks: blocks, attrs: attrs}, context) do
+ {context1, body} = render(blocks, context)
+ html = "<blockquote>#{body}</blockquote>"
+ add_attrs(context1, html, attrs, [], lnb)
+ end
+
+ #########
+ # Table #
+ #########
+
+ defp render_block(
+ %Block.Table{lnb: lnb, header: header, rows: rows, alignments: aligns, attrs: attrs},
+ context
+ ) do
+ {context1, html} = add_attrs(context, "<table>", attrs, [], lnb)
+ context2 = set_value(context1, html)
+
+ context3 =
+ if header do
+ append(add_trs(append(context2, "<thead>"), [header], "th", aligns, lnb), "</thead>")
+ else
+ # Maybe an error, needed append(context, html)
+ context2
+ end
+
+ context4 = append(add_trs(append(context3, "<tbody>"), rows, "td", aligns, lnb), "</tbody>")
+
+ {context4, [context4.value, "</table>"]}
+ end
+
+ ########
+ # Code #
+ ########
+
+ defp render_block(
+ %Block.Code{lnb: lnb, language: language, attrs: attrs} = block,
+ %Context{options: options} = context
+ ) do
+ class =
+ if language, do: ~s{ class="#{code_classes(language, options.code_class_prefix)}"}, else: ""
+
+ tag = ~s[<pre><code#{class}>]
+ lines = options.render_code.(block)
+ html = ~s[#{tag}#{lines}</code></pre>]
+ add_attrs(context, html, attrs, [], lnb)
+ end
+
+ #########
+ # Lists #
+ #########
+
+ defp render_block(
+ %Block.List{lnb: lnb, type: type, blocks: items, attrs: attrs, start: start},
+ context
+ ) do
+ {context1, content} = render(items, context)
+ html = "<#{type}#{start}>#{content}</#{type}>"
+ add_attrs(context1, html, attrs, [], lnb)
+ end
+
+ # format a single paragraph list item, and remove the para tags
+ defp render_block(
+ %Block.ListItem{lnb: lnb, blocks: blocks, spaced: false, attrs: attrs},
+ context
+ )
+ when length(blocks) == 1 do
+ {context1, content} = render(blocks, context)
+ content = Regex.replace(~r{</?p>}, content, "")
+ html = "<li>#{content}</li>"
+ add_attrs(context1, html, attrs, [], lnb)
+ end
+
+ # format a spaced list item
+ defp render_block(%Block.ListItem{lnb: lnb, blocks: blocks, attrs: attrs}, context) do
+ {context1, content} = render(blocks, context)
+ html = "<li>#{content}</li>"
+ add_attrs(context1, html, attrs, [], lnb)
+ end
+
+ ##################
+ # Footnote Block #
+ ##################
+
+ defp render_block(%Block.FnList{blocks: footnotes}, context) do
+ items =
+ Enum.map(footnotes, fn note ->
+ blocks = append_footnote_link(note)
+ %Block.ListItem{attrs: "#fn:#{note.number}", type: :ol, blocks: blocks}
+ end)
+
+ {context1, html} = render_block(%Block.List{type: :ol, blocks: items}, context)
+ {context1, Enum.join([~s[<div class="footnotes">], "<hr />", html, "</div>"])}
+ end
+
+ #######################################
+ # Isolated IALs are rendered as paras #
+ #######################################
+
+ defp render_block(%Block.Ial{verbatim: verbatim}, context) do
+ {context, "<p>{:#{verbatim}}</p>"}
+ end
+
+ ####################
+ # IDDef is ignored #
+ ####################
+
+ defp render_block(%Block.IdDef{}, context), do: {context, ""}
+
+ #####################################
+ # And here are the inline renderers #
+ #####################################
+
+ defdelegate br, to: HtmlRenderer
+ defdelegate codespan(text), to: HtmlRenderer
+ defdelegate em(text), to: HtmlRenderer
+ defdelegate strong(text), to: HtmlRenderer
+ defdelegate strikethrough(text), to: HtmlRenderer
+
+ defdelegate link(url, text), to: HtmlRenderer
+ defdelegate link(url, text, title), to: HtmlRenderer
+
+ defdelegate image(path, alt, title), to: HtmlRenderer
+
+ defdelegate footnote_link(ref, backref, number), to: HtmlRenderer
+
+ # Table rows
+ defp add_trs(context, rows, tag, aligns, lnb) do
+ numbered_rows =
+ rows
+ |> Enum.zip(Stream.iterate(lnb, &(&1 + 1)))
+
+ numbered_rows
+ |> Enum.reduce(context, fn {row, lnb}, ctx ->
+ append(add_tds(append(ctx, "<tr>"), row, tag, aligns, lnb), "</tr>")
+ end)
+ end
+
+ defp add_tds(context, row, tag, aligns, lnb) do
+ Enum.reduce(1..length(row), context, add_td_fn(row, tag, aligns, lnb))
+ end
+
+ defp add_td_fn(row, tag, aligns, lnb) do
+ fn n, ctx ->
+ style =
+ case Enum.at(aligns, n - 1, :default) do
+ :default -> ""
+ align -> " style=\"text-align: #{align}\""
+ end
+
+ col = Enum.at(row, n - 1)
+ converted = convert(col, lnb, set_messages(ctx, []))
+ append(add_messages_from(ctx, converted), "<#{tag}#{style}>#{converted.value}</#{tag}>")
+ end
+ end
+
+ ###############################
+ # Append Footnote Return Link #
+ ###############################
+
+ defdelegate append_footnote_link(note), to: HtmlRenderer
+ defdelegate append_footnote_link(note, fnlink), to: HtmlRenderer
+
+ defdelegate render_code(lines), to: HtmlRenderer
+
+ defp code_classes(language, prefix) do
+ ["" | String.split(prefix || "")]
+ |> Enum.map(fn pfx -> "#{pfx}#{language}" end)
+ |> Enum.join(" ")
+ end
+end
diff --git a/lib/pleroma/plugs/ensure_authenticated_plug.ex b/lib/pleroma/plugs/ensure_authenticated_plug.ex
index 6f9b840a9..054d2297f 100644
--- a/lib/pleroma/plugs/ensure_authenticated_plug.ex
+++ b/lib/pleroma/plugs/ensure_authenticated_plug.ex
@@ -15,9 +15,24 @@ defmodule Pleroma.Plugs.EnsureAuthenticatedPlug do
conn
end
- def call(conn, _) do
+ def call(conn, options) do
+ perform =
+ cond do
+ options[:if_func] -> options[:if_func].()
+ options[:unless_func] -> !options[:unless_func].()
+ true -> true
+ end
+
+ if perform do
+ fail(conn)
+ else
+ conn
+ end
+ end
+
+ def fail(conn) do
conn
|> render_error(:forbidden, "Invalid credentials.")
- |> halt
+ |> halt()
end
end
diff --git a/lib/pleroma/plugs/federating_plug.ex b/lib/pleroma/plugs/federating_plug.ex
index d3943586d..7d947339f 100644
--- a/lib/pleroma/plugs/federating_plug.ex
+++ b/lib/pleroma/plugs/federating_plug.ex
@@ -10,14 +10,20 @@ defmodule Pleroma.Web.FederatingPlug do
end
def call(conn, _opts) do
- if Pleroma.Config.get([:instance, :federating]) do
+ if federating?() do
conn
else
- conn
- |> put_status(404)
- |> Phoenix.Controller.put_view(Pleroma.Web.ErrorView)
- |> Phoenix.Controller.render("404.json")
- |> halt()
+ fail(conn)
end
end
+
+ def federating?, do: Pleroma.Config.get([:instance, :federating])
+
+ defp fail(conn) do
+ conn
+ |> put_status(404)
+ |> Phoenix.Controller.put_view(Pleroma.Web.ErrorView)
+ |> Phoenix.Controller.render("404.json")
+ |> halt()
+ end
end
diff --git a/lib/pleroma/plugs/rate_limiter/rate_limiter.ex b/lib/pleroma/plugs/rate_limiter/rate_limiter.ex
index c3f6351c8..1529da717 100644
--- a/lib/pleroma/plugs/rate_limiter/rate_limiter.ex
+++ b/lib/pleroma/plugs/rate_limiter/rate_limiter.ex
@@ -78,7 +78,7 @@ defmodule Pleroma.Plugs.RateLimiter do
end
def call(conn, plug_opts) do
- if disabled?() do
+ if disabled?(conn) do
handle_disabled(conn)
else
action_settings = action_settings(plug_opts)
@@ -87,9 +87,9 @@ defmodule Pleroma.Plugs.RateLimiter do
end
defp handle_disabled(conn) do
- if Config.get(:env) == :prod do
- Logger.warn("Rate limiter is disabled for localhost/socket")
- end
+ Logger.warn(
+ "Rate limiter disabled due to forwarded IP not being found. Please ensure your reverse proxy is providing the X-Forwarded-For header or disable the RemoteIP plug/rate limiter."
+ )
conn
end
@@ -109,16 +109,21 @@ defmodule Pleroma.Plugs.RateLimiter do
end
end
- def disabled? do
+ def disabled?(conn) do
localhost_or_socket =
- Config.get([Pleroma.Web.Endpoint, :http, :ip])
- |> Tuple.to_list()
- |> Enum.join(".")
- |> String.match?(~r/^local|^127.0.0.1/)
+ case Config.get([Pleroma.Web.Endpoint, :http, :ip]) do
+ {127, 0, 0, 1} -> true
+ {0, 0, 0, 0, 0, 0, 0, 1} -> true
+ {:local, _} -> true
+ _ -> false
+ end
- remote_ip_disabled = not Config.get([Pleroma.Plugs.RemoteIp, :enabled])
+ remote_ip_not_found =
+ if Map.has_key?(conn.assigns, :remote_ip_found),
+ do: !conn.assigns.remote_ip_found,
+ else: false
- localhost_or_socket and remote_ip_disabled
+ localhost_or_socket and remote_ip_not_found
end
@inspect_bucket_not_found {:error, :not_found}
diff --git a/lib/pleroma/plugs/remote_ip.ex b/lib/pleroma/plugs/remote_ip.ex
index 2eca4f8f6..0ac9050d0 100644
--- a/lib/pleroma/plugs/remote_ip.ex
+++ b/lib/pleroma/plugs/remote_ip.ex
@@ -7,6 +7,8 @@ defmodule Pleroma.Plugs.RemoteIp do
This is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.
"""
+ import Plug.Conn
+
@behaviour Plug
@headers ~w[
@@ -26,11 +28,12 @@ defmodule Pleroma.Plugs.RemoteIp do
def init(_), do: nil
- def call(conn, _) do
+ def call(%{remote_ip: original_remote_ip} = conn, _) do
config = Pleroma.Config.get(__MODULE__, [])
if Keyword.get(config, :enabled, false) do
- RemoteIp.call(conn, remote_ip_opts(config))
+ %{remote_ip: new_remote_ip} = conn = RemoteIp.call(conn, remote_ip_opts(config))
+ assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip)
else
conn
end
diff --git a/lib/pleroma/plugs/static_fe_plug.ex b/lib/pleroma/plugs/static_fe_plug.ex
index deebe4879..156e6788e 100644
--- a/lib/pleroma/plugs/static_fe_plug.ex
+++ b/lib/pleroma/plugs/static_fe_plug.ex
@@ -21,6 +21,9 @@ defmodule Pleroma.Plugs.StaticFEPlug do
defp enabled?, do: Pleroma.Config.get([:static_fe, :enabled], false)
defp accepts_html?(conn) do
- conn |> get_req_header("accept") |> List.first() |> String.contains?("text/html")
+ case get_req_header(conn, "accept") do
+ [accept | _] -> String.contains?(accept, "text/html")
+ _ -> false
+ end
end
end
diff --git a/lib/pleroma/plugs/uploaded_media.ex b/lib/pleroma/plugs/uploaded_media.ex
index f372829a2..36ff024a7 100644
--- a/lib/pleroma/plugs/uploaded_media.ex
+++ b/lib/pleroma/plugs/uploaded_media.ex
@@ -14,9 +14,14 @@ defmodule Pleroma.Plugs.UploadedMedia do
# no slashes
@path "media"
+ @default_cache_control_header "public, max-age=1209600"
+
def init(_opts) do
static_plug_opts =
- []
+ [
+ headers: %{"cache-control" => @default_cache_control_header},
+ cache_control_for_etags: @default_cache_control_header
+ ]
|> Keyword.put(:from, "__unconfigured_media_plug")
|> Keyword.put(:at, "/__unconfigured_media_plug")
|> Plug.Static.init()
diff --git a/lib/pleroma/reverse_proxy/reverse_proxy.ex b/lib/pleroma/reverse_proxy/reverse_proxy.ex
index 35b973b56..4bbeb493c 100644
--- a/lib/pleroma/reverse_proxy/reverse_proxy.ex
+++ b/lib/pleroma/reverse_proxy/reverse_proxy.ex
@@ -5,7 +5,7 @@
defmodule Pleroma.ReverseProxy do
@keep_req_headers ~w(accept user-agent accept-encoding cache-control if-modified-since) ++
~w(if-unmodified-since if-none-match if-range range)
- @resp_cache_headers ~w(etag date last-modified cache-control)
+ @resp_cache_headers ~w(etag date last-modified)
@keep_resp_headers @resp_cache_headers ++
~w(content-type content-disposition content-encoding content-range) ++
~w(accept-ranges vary)
@@ -32,9 +32,6 @@ defmodule Pleroma.ReverseProxy do
* request: `#{inspect(@keep_req_headers)}`
* response: `#{inspect(@keep_resp_headers)}`
- If no caching headers (`#{inspect(@resp_cache_headers)}`) are returned by upstream, `cache-control` will be
- set to `#{inspect(@default_cache_control_header)}`.
-
Options:
* `redirect_on_failure` (default `false`). Redirects the client to the real remote URL if there's any HTTP
@@ -291,16 +288,17 @@ defmodule Pleroma.ReverseProxy do
defp build_resp_cache_headers(headers, _opts) do
has_cache? = Enum.any?(headers, fn {k, _} -> k in @resp_cache_headers end)
- has_cache_control? = List.keymember?(headers, "cache-control", 0)
cond do
- has_cache? && has_cache_control? ->
- headers
-
has_cache? ->
- # There's caching header present but no cache-control -- we need to explicitely override it
- # to public as Plug defaults to "max-age=0, private, must-revalidate"
- List.keystore(headers, "cache-control", 0, {"cache-control", "public"})
+ # There's caching header present but no cache-control -- we need to set our own
+ # as Plug defaults to "max-age=0, private, must-revalidate"
+ List.keystore(
+ headers,
+ "cache-control",
+ 0,
+ {"cache-control", @default_cache_control_header}
+ )
true ->
List.keystore(
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 7531757f5..911dde6e2 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -16,6 +16,7 @@ defmodule Pleroma.User do
alias Pleroma.Conversation.Participation
alias Pleroma.Delivery
alias Pleroma.FollowingRelationship
+ alias Pleroma.HTML
alias Pleroma.Keys
alias Pleroma.Notification
alias Pleroma.Object
@@ -839,10 +840,6 @@ defmodule Pleroma.User do
_e ->
with [_nick, _domain] <- String.split(nickname, "@"),
{:ok, user} <- fetch_by_nickname(nickname) do
- if Pleroma.Config.get([:fetch_initial_posts, :enabled]) do
- fetch_initial_posts(user)
- end
-
{:ok, user}
else
_e -> {:error, "not found " <> nickname}
@@ -850,11 +847,6 @@ defmodule Pleroma.User do
end
end
- @doc "Fetch some posts when the user has just been federated with"
- def fetch_initial_posts(user) do
- BackgroundWorker.enqueue("fetch_initial_posts", %{"user_id" => user.id})
- end
-
@spec get_followers_query(User.t(), pos_integer() | nil) :: Ecto.Query.t()
def get_followers_query(%User{} = user, nil) do
User.Query.build(%{followers: user, deactivated: false})
@@ -1320,16 +1312,6 @@ defmodule Pleroma.User do
Repo.delete(user)
end
- def perform(:fetch_initial_posts, %User{} = user) do
- pages = Pleroma.Config.get!([:fetch_initial_posts, :pages])
-
- # Insert all the posts in reverse order, so they're in the right order on the timeline
- user.source_data["outbox"]
- |> Utils.fetch_ordered_collection(pages)
- |> Enum.reverse()
- |> Enum.each(&Pleroma.Web.Federator.incoming_ap_doc/1)
- end
-
def perform(:deactivate_async, user, status), do: deactivate(user, status)
@spec perform(atom(), User.t(), list()) :: list() | {:error, any()}
@@ -1458,18 +1440,7 @@ defmodule Pleroma.User do
if !is_nil(user) and !needs_update?(user) do
{:ok, user}
else
- # Whether to fetch initial posts for the user (if it's a new user & the fetching is enabled)
- should_fetch_initial = is_nil(user) and Pleroma.Config.get([:fetch_initial_posts, :enabled])
-
- resp = fetch_by_ap_id(ap_id)
-
- if should_fetch_initial do
- with {:ok, %User{} = user} <- resp do
- fetch_initial_posts(user)
- end
- end
-
- resp
+ fetch_by_ap_id(ap_id)
end
end
@@ -2062,4 +2033,27 @@ defmodule Pleroma.User do
|> validate_required([:invisible])
|> update_and_set_cache()
end
+
+ def sanitize_html(%User{} = user) do
+ sanitize_html(user, nil)
+ end
+
+ # User data that mastodon isn't filtering (treated as plaintext):
+ # - field name
+ # - display name
+ def sanitize_html(%User{} = user, filter) do
+ fields =
+ user
+ |> User.fields()
+ |> Enum.map(fn %{"name" => name, "value" => value} ->
+ %{
+ "name" => name,
+ "value" => HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
+ }
+ end)
+
+ user
+ |> Map.put(:bio, HTML.filter_tags(user.bio, filter))
+ |> Map.put(:fields, fields)
+ end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 779de0e4d..8b9eb4a2c 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
alias Pleroma.Delivery
alias Pleroma.Object
alias Pleroma.Object.Fetcher
+ alias Pleroma.Plugs.EnsureAuthenticatedPlug
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.InternalFetchActor
@@ -18,23 +19,37 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
alias Pleroma.Web.ActivityPub.UserView
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
+ alias Pleroma.Web.FederatingPlug
alias Pleroma.Web.Federator
require Logger
action_fallback(:errors)
+ @federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers]
+
+ plug(FederatingPlug when action in @federating_only_actions)
+
+ plug(
+ EnsureAuthenticatedPlug,
+ [unless_func: &FederatingPlug.federating?/0] when action not in @federating_only_actions
+ )
+
+ plug(
+ EnsureAuthenticatedPlug
+ when action in [:read_inbox, :update_outbox, :whoami, :upload_media, :following, :followers]
+ )
+
plug(
Pleroma.Plugs.Cache,
[query_params: false, tracking_fun: &__MODULE__.track_object_fetch/2]
when action in [:activity, :object]
)
- plug(Pleroma.Web.FederatingPlug when action in [:inbox, :relay])
plug(:set_requester_reachable when action in [:inbox])
plug(:relay_active? when action in [:relay])
- def relay_active?(conn, _) do
+ defp relay_active?(conn, _) do
if Pleroma.Config.get([:instance, :allow_relay]) do
conn
else
@@ -127,11 +142,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
# GET /relay/following
- def following(%{assigns: %{relay: true}} = conn, _params) do
- conn
- |> put_resp_content_type("application/activity+json")
- |> put_view(UserView)
- |> render("following.json", %{user: Relay.get_actor()})
+ def relay_following(conn, _params) do
+ with %{halted: false} = conn <- FederatingPlug.call(conn, []) do
+ conn
+ |> put_resp_content_type("application/activity+json")
+ |> put_view(UserView)
+ |> render("following.json", %{user: Relay.get_actor()})
+ end
end
def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
@@ -164,11 +181,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
# GET /relay/followers
- def followers(%{assigns: %{relay: true}} = conn, _params) do
- conn
- |> put_resp_content_type("application/activity+json")
- |> put_view(UserView)
- |> render("followers.json", %{user: Relay.get_actor()})
+ def relay_followers(conn, _params) do
+ with %{halted: false} = conn <- FederatingPlug.call(conn, []) do
+ conn
+ |> put_resp_content_type("application/activity+json")
+ |> put_view(UserView)
+ |> render("followers.json", %{user: Relay.get_actor()})
+ end
end
def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
@@ -200,13 +219,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
- def outbox(conn, %{"nickname" => nickname, "page" => page?} = params)
+ def outbox(
+ %{assigns: %{user: for_user}} = conn,
+ %{"nickname" => nickname, "page" => page?} = params
+ )
when page? in [true, "true"] do
with %User{} = user <- User.get_cached_by_nickname(nickname),
{:ok, user} <- User.ensure_keys_present(user) do
activities =
if params["max_id"] do
- ActivityPub.fetch_user_activities(user, nil, %{
+ ActivityPub.fetch_user_activities(user, for_user, %{
"max_id" => params["max_id"],
# This is a hack because postgres generates inefficient queries when filtering by
# 'Answer', poll votes will be hidden by the visibility filter in this case anyway
@@ -214,7 +236,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
"limit" => 10
})
else
- ActivityPub.fetch_user_activities(user, nil, %{
+ ActivityPub.fetch_user_activities(user, for_user, %{
"limit" => 10,
"include_poll_votes" => true
})
@@ -255,8 +277,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
json(conn, "ok")
end
- # only accept relayed Creates
- def inbox(conn, %{"type" => "Create"} = params) do
+ # POST /relay/inbox -or- POST /internal/fetch/inbox
+ def inbox(conn, params) do
+ if params["type"] == "Create" && FederatingPlug.federating?() do
+ post_inbox_relayed_create(conn, params)
+ else
+ post_inbox_fallback(conn, params)
+ end
+ end
+
+ defp post_inbox_relayed_create(conn, params) do
Logger.debug(
"Signature missing or not from author, relayed Create message, fetching object from source"
)
@@ -266,10 +296,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
json(conn, "ok")
end
- def inbox(conn, params) do
+ defp post_inbox_fallback(conn, params) do
headers = Enum.into(conn.req_headers, %{})
- if String.contains?(headers["signature"], params["actor"]) do
+ if headers["signature"] && params["actor"] &&
+ String.contains?(headers["signature"], params["actor"]) do
Logger.debug(
"Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
)
@@ -277,7 +308,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
Logger.debug(inspect(conn.req_headers))
end
- json(conn, dgettext("errors", "error"))
+ conn
+ |> put_status(:bad_request)
+ |> json(dgettext("errors", "error"))
end
defp represent_service_actor(%User{} = user, conn) do
@@ -311,10 +344,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> render("user.json", %{user: user})
end
- def whoami(_conn, _params), do: {:error, :not_found}
-
def read_inbox(
- %{assigns: %{user: %{nickname: nickname} = user}} = conn,
+ %{assigns: %{user: %User{nickname: nickname} = user}} = conn,
%{"nickname" => nickname, "page" => page?} = params
)
when page? in [true, "true"] do
@@ -337,7 +368,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
})
end
- def read_inbox(%{assigns: %{user: %{nickname: nickname} = user}} = conn, %{
+ def read_inbox(%{assigns: %{user: %User{nickname: nickname} = user}} = conn, %{
"nickname" => nickname
}) do
with {:ok, user} <- User.ensure_keys_present(user) do
@@ -348,15 +379,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
- def read_inbox(%{assigns: %{user: nil}} = conn, %{"nickname" => nickname}) do
- err = dgettext("errors", "can't read inbox of %{nickname}", nickname: nickname)
-
- conn
- |> put_status(:forbidden)
- |> json(err)
- end
-
- def read_inbox(%{assigns: %{user: %{nickname: as_nickname}}} = conn, %{
+ def read_inbox(%{assigns: %{user: %User{nickname: as_nickname}}} = conn, %{
"nickname" => nickname
}) do
err =
@@ -370,7 +393,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> json(err)
end
- def handle_user_activity(user, %{"type" => "Create"} = params) do
+ defp handle_user_activity(%User{} = user, %{"type" => "Create"} = params) do
object =
params["object"]
|> Map.merge(Map.take(params, ["to", "cc"]))
@@ -386,7 +409,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
})
end
- def handle_user_activity(user, %{"type" => "Delete"} = params) do
+ defp handle_user_activity(%User{} = user, %{"type" => "Delete"} = params) do
with %Object{} = object <- Object.normalize(params["object"]),
true <- user.is_moderator || user.ap_id == object.data["actor"],
{:ok, delete} <- ActivityPub.delete(object) do
@@ -396,7 +419,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
- def handle_user_activity(user, %{"type" => "Like"} = params) do
+ defp handle_user_activity(%User{} = user, %{"type" => "Like"} = params) do
with %Object{} = object <- Object.normalize(params["object"]),
{:ok, activity, _object} <- ActivityPub.like(user, object) do
{:ok, activity}
@@ -405,7 +428,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
- def handle_user_activity(_, _) do
+ defp handle_user_activity(_, _) do
{:error, dgettext("errors", "Unhandled activity type")}
end
@@ -434,7 +457,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
- def update_outbox(%{assigns: %{user: user}} = conn, %{"nickname" => nickname} = _) do
+ def update_outbox(%{assigns: %{user: %User{} = user}} = conn, %{"nickname" => nickname}) do
err =
dgettext("errors", "can't update outbox of %{nickname} as %{as_nickname}",
nickname: nickname,
@@ -446,13 +469,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> json(err)
end
- def errors(conn, {:error, :not_found}) do
+ defp errors(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
|> json(dgettext("errors", "Not found"))
end
- def errors(conn, _e) do
+ defp errors(conn, _e) do
conn
|> put_status(:internal_server_error)
|> json(dgettext("errors", "error"))
@@ -492,7 +515,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
- HTTP Code: 201 Created
- HTTP Body: ActivityPub object to be inserted into another's `attachment` field
"""
- def upload_media(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
+ def upload_media(%{assigns: %{user: %User{} = user}} = conn, %{"file" => file} = data) do
with {:ok, object} <-
ActivityPub.upload(
file,
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 2bc958670..15dd2ed45 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -784,45 +784,6 @@ defmodule Pleroma.Web.ActivityPub.Utils do
defp build_flag_object(_), do: []
- @doc """
- Fetches the OrderedCollection/OrderedCollectionPage from `from`, limiting the amount of pages fetched after
- the first one to `pages_left` pages.
- If the amount of pages is higher than the collection has, it returns whatever was there.
- """
- def fetch_ordered_collection(from, pages_left, acc \\ []) do
- with {:ok, response} <- Tesla.get(from),
- {:ok, collection} <- Jason.decode(response.body) do
- case collection["type"] do
- "OrderedCollection" ->
- # If we've encountered the OrderedCollection and not the page,
- # just call the same function on the page address
- fetch_ordered_collection(collection["first"], pages_left)
-
- "OrderedCollectionPage" ->
- if pages_left > 0 do
- # There are still more pages
- if Map.has_key?(collection, "next") do
- # There are still more pages, go deeper saving what we have into the accumulator
- fetch_ordered_collection(
- collection["next"],
- pages_left - 1,
- acc ++ collection["orderedItems"]
- )
- else
- # No more pages left, just return whatever we already have
- acc ++ collection["orderedItems"]
- end
- else
- # Got the amount of pages needed, add them all to the accumulator
- acc ++ collection["orderedItems"]
- end
-
- _ ->
- {:error, "Not an OrderedCollection or OrderedCollectionPage"}
- end
- end
- end
-
#### Report-related helpers
def get_reports(params, page, page_size) do
params =
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index c0358b678..bc21ac6c7 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -73,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
{:ok, _, public_key} = Keys.keys_from_pem(user.keys)
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
public_key = :public_key.pem_encode([public_key])
+ user = User.sanitize_html(user)
endpoints = render("endpoints.json", %{user: user})
@@ -81,12 +82,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
fields =
user
|> User.fields()
- |> Enum.map(fn %{"name" => name, "value" => value} ->
- %{
- "name" => Pleroma.HTML.strip_tags(name),
- "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
- }
- end)
|> Enum.map(&Map.put(&1, "type", "PropertyValue"))
%{
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 47b7d2da3..175260bc2 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -745,14 +745,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
end
end
- def list_statuses(%{assigns: %{user: admin}} = conn, params) do
+ def list_statuses(%{assigns: %{user: _admin}} = conn, params) do
godmode = params["godmode"] == "true" || params["godmode"] == true
local_only = params["local_only"] == "true" || params["local_only"] == true
with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
{page, page_size} = page_params(params)
activities =
- ActivityPub.fetch_statuses(admin, %{
+ ActivityPub.fetch_statuses(nil, %{
"godmode" => godmode,
"local_only" => local_only,
"limit" => page_size,
diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex
index 619390ef4..1e03849de 100644
--- a/lib/pleroma/web/admin_api/views/account_view.ex
+++ b/lib/pleroma/web/admin_api/views/account_view.ex
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.AdminAPI.AccountView do
use Pleroma.Web, :view
- alias Pleroma.HTML
alias Pleroma.User
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.MediaProxy
@@ -26,7 +25,8 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
def render("show.json", %{user: user}) do
avatar = User.avatar_url(user) |> MediaProxy.url()
- display_name = HTML.strip_tags(user.name || user.nickname)
+ display_name = Pleroma.HTML.strip_tags(user.name || user.nickname)
+ user = User.sanitize_html(user, FastSanitize.Sanitizer.StripTags)
%{
"id" => user.id,
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 348fdedf1..635e7cd38 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -331,7 +331,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
def format_input(text, "text/markdown", options) do
text
|> Formatter.mentions_escape(options)
- |> Earmark.as_html!()
+ |> Earmark.as_html!(%Earmark.Options{renderer: Pleroma.EarmarkRenderer})
|> Formatter.linkify(options)
|> Formatter.html_escape("text/html")
end
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
index 118c3ac6f..72cb3ee27 100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -12,7 +12,7 @@ defmodule Pleroma.Web.Endpoint do
plug(Pleroma.Plugs.HTTPSecurityPlug)
plug(Pleroma.Plugs.UploadedMedia)
- @static_cache_control "public max-age=86400 must-revalidate"
+ @static_cache_control "public, no-cache"
# InstanceStatic needs to be before Plug.Static to be able to override shipped-static files
# If you're adding new paths to `only:` you'll need to configure them in InstanceStatic as well
diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex
index 59aabb549..9ba602d9f 100644
--- a/lib/pleroma/web/feed/user_controller.ex
+++ b/lib/pleroma/web/feed/user_controller.ex
@@ -25,7 +25,12 @@ defmodule Pleroma.Web.Feed.UserController do
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
when format in ["json", "activity+json"] do
- ActivityPubController.call(conn, :user)
+ with %{halted: false} = conn <-
+ Pleroma.Plugs.EnsureAuthenticatedPlug.call(conn,
+ unless_func: &Pleroma.Web.FederatingPlug.federating?/0
+ ) do
+ ActivityPubController.call(conn, :user)
+ end
end
def feed_redirect(conn, %{"nickname" => nickname}) do
diff --git a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
index f165c9965..37b389382 100644
--- a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
@@ -86,6 +86,6 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
@spec get_or_make_app() :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
defp get_or_make_app do
%{client_name: @local_mastodon_name, redirect_uris: "."}
- |> App.get_or_make(["read", "write", "follow", "push"])
+ |> App.get_or_make(["read", "write", "follow", "push", "admin"])
end
end
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index 6dc191250..341dc2c91 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.MastodonAPI.AccountView do
use Pleroma.Web, :view
- alias Pleroma.HTML
alias Pleroma.User
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.AccountView
@@ -67,6 +66,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
end
defp do_render("show.json", %{user: user} = opts) do
+ user = User.sanitize_html(user, User.html_filter_policy(opts[:for]))
display_name = user.name || user.nickname
image = User.avatar_url(user) |> MediaProxy.url()
@@ -100,17 +100,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
}
end)
- fields =
- user
- |> User.fields()
- |> Enum.map(fn %{"name" => name, "value" => value} ->
- %{
- "name" => name,
- "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
- }
- end)
-
- bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
relationship = render("relationship.json", %{user: opts[:for], target: user})
%{
@@ -123,17 +112,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
followers_count: followers_count,
following_count: following_count,
statuses_count: user.note_count,
- note: bio || "",
+ note: user.bio || "",
url: User.profile_url(user),
avatar: image,
avatar_static: image,
header: header,
header_static: header,
emojis: emojis,
- fields: fields,
+ fields: user.fields,
bot: bot,
source: %{
- note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
+ note: Pleroma.HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
sensitive: false,
fields: user.raw_fields,
pleroma: %{
diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex
index c443c888c..6fd3cfce5 100644
--- a/lib/pleroma/web/ostatus/ostatus_controller.ex
+++ b/lib/pleroma/web/ostatus/ostatus_controller.ex
@@ -16,6 +16,10 @@ defmodule Pleroma.Web.OStatus.OStatusController do
alias Pleroma.Web.Metadata.PlayerView
alias Pleroma.Web.Router
+ plug(Pleroma.Plugs.EnsureAuthenticatedPlug,
+ unless_func: &Pleroma.Web.FederatingPlug.federating?/0
+ )
+
plug(
RateLimiter,
[name: :ap_routes, params: ["uuid"]] when action in [:object, :activity]
@@ -135,13 +139,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do
end
end
- def errors(conn, {:error, :not_found}) do
+ defp errors(conn, {:error, :not_found}) do
render_error(conn, :not_found, "Not found")
end
- def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
+ defp errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
- def errors(conn, _) do
+ defp errors(conn, _) do
render_error(conn, :internal_server_error, "Something went wrong")
end
end
diff --git a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
index 0e160bbfc..dae7f0f2f 100644
--- a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
@@ -101,6 +101,11 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
conn
|> put_view(ConversationView)
|> render("participation.json", %{participation: participation, for: user})
+ else
+ _error ->
+ conn
+ |> put_status(404)
+ |> json(%{"error" => "Unknown conversation id"})
end
end
@@ -108,9 +113,9 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
%{assigns: %{user: user}} = conn,
%{"id" => participation_id} = params
) do
- participation = Participation.get(participation_id, preload: [:conversation])
-
- if user.id == participation.user_id do
+ with %Participation{} = participation <-
+ Participation.get(participation_id, preload: [:conversation]),
+ true <- user.id == participation.user_id do
params =
params
|> Map.put("blocking_user", user)
@@ -126,6 +131,11 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|> add_link_headers(activities)
|> put_view(StatusView)
|> render("index.json", %{activities: activities, for: user, as: :activity})
+ else
+ _error ->
+ conn
+ |> put_status(404)
+ |> json(%{"error" => "Unknown conversation id"})
end
end
@@ -133,15 +143,22 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
%{assigns: %{user: user}} = conn,
%{"id" => participation_id, "recipients" => recipients}
) do
- participation =
- participation_id
- |> Participation.get()
-
- with true <- user.id == participation.user_id,
+ with %Participation{} = participation <- Participation.get(participation_id),
+ true <- user.id == participation.user_id,
{:ok, participation} <- Participation.set_recipients(participation, recipients) do
conn
|> put_view(ConversationView)
|> render("participation.json", %{participation: participation, for: user})
+ else
+ {:error, message} ->
+ conn
+ |> put_status(:bad_request)
+ |> json(%{"error" => message})
+
+ _error ->
+ conn
+ |> put_status(404)
+ |> json(%{"error" => "Unknown conversation id"})
end
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 980242c68..e4e3ee704 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -541,6 +541,7 @@ defmodule Pleroma.Web.Router do
get("/mailer/unsubscribe/:token", Mailer.SubscriptionController, :unsubscribe)
end
+ # Server to Server (S2S) AP interactions
pipeline :activitypub do
plug(:accepts, ["activity+json", "json"])
plug(Pleroma.Web.Plugs.HTTPSignaturePlug)
@@ -554,6 +555,7 @@ defmodule Pleroma.Web.Router do
get("/users/:nickname/outbox", ActivityPubController, :outbox)
end
+ # Client to Server (C2S) AP interactions
pipeline :activitypub_client do
plug(:accepts, ["activity+json", "json"])
plug(:fetch_session)
@@ -597,8 +599,8 @@ defmodule Pleroma.Web.Router do
post("/inbox", ActivityPubController, :inbox)
end
- get("/following", ActivityPubController, :following, assigns: %{relay: true})
- get("/followers", ActivityPubController, :followers, assigns: %{relay: true})
+ get("/following", ActivityPubController, :relay_following)
+ get("/followers", ActivityPubController, :relay_followers)
end
scope "/internal/fetch", Pleroma.Web.ActivityPub do
diff --git a/lib/pleroma/web/static_fe/static_fe_controller.ex b/lib/pleroma/web/static_fe/static_fe_controller.ex
index 5ac75f1c4..7f9464268 100644
--- a/lib/pleroma/web/static_fe/static_fe_controller.ex
+++ b/lib/pleroma/web/static_fe/static_fe_controller.ex
@@ -17,6 +17,10 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
plug(:put_view, Pleroma.Web.StaticFE.StaticFEView)
plug(:assign_id)
+ plug(Pleroma.Plugs.EnsureAuthenticatedPlug,
+ unless_func: &Pleroma.Web.FederatingPlug.federating?/0
+ )
+
@page_keys ["max_id", "min_id", "limit", "since_id", "order"]
defp get_title(%Object{data: %{"name" => name}}) when is_binary(name),
@@ -33,7 +37,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
|> render("error.html", %{message: message, meta: ""})
end
- def get_counts(%Activity{} = activity) do
+ defp get_counts(%Activity{} = activity) do
%Object{data: data} = Object.normalize(activity)
%{
@@ -43,9 +47,9 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
}
end
- def represent(%Activity{} = activity), do: represent(activity, false)
+ defp represent(%Activity{} = activity), do: represent(activity, false)
- def represent(%Activity{object: %Object{data: data}} = activity, selected) do
+ defp represent(%Activity{object: %Object{data: data}} = activity, selected) do
{:ok, user} = User.get_or_fetch(activity.object.data["actor"])
link =
@@ -54,10 +58,17 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
_ -> data["url"] || data["external_url"] || data["id"]
end
+ content =
+ if data["content"] do
+ Pleroma.HTML.filter_tags(data["content"])
+ else
+ nil
+ end
+
%{
- user: user,
+ user: User.sanitize_html(user),
title: get_title(activity.object),
- content: data["content"] || nil,
+ content: content,
attachment: data["attachment"],
link: link,
published: data["published"],
@@ -109,7 +120,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
next_page_id = List.last(timeline) && List.last(timeline).id
render(conn, "profile.html", %{
- user: user,
+ user: User.sanitize_html(user),
timeline: timeline,
prev_page_id: prev_page_id,
next_page_id: next_page_id,
@@ -147,17 +158,17 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
end
end
- def assign_id(%{path_info: ["notice", notice_id]} = conn, _opts),
+ defp assign_id(%{path_info: ["notice", notice_id]} = conn, _opts),
do: assign(conn, :notice_id, notice_id)
- def assign_id(%{path_info: ["users", user_id]} = conn, _opts),
+ defp assign_id(%{path_info: ["users", user_id]} = conn, _opts),
do: assign(conn, :username_or_id, user_id)
- def assign_id(%{path_info: ["objects", object_id]} = conn, _opts),
+ defp assign_id(%{path_info: ["objects", object_id]} = conn, _opts),
do: assign(conn, :object_id, object_id)
- def assign_id(%{path_info: ["activities", activity_id]} = conn, _opts),
+ defp assign_id(%{path_info: ["activities", activity_id]} = conn, _opts),
do: assign(conn, :activity_id, activity_id)
- def assign_id(conn, _opts), do: conn
+ defp assign_id(conn, _opts), do: conn
end
diff --git a/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex b/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex
index fbf31c7eb..89da760da 100644
--- a/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex
@@ -16,6 +16,8 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowController do
@status_types ["Article", "Event", "Note", "Video", "Page", "Question"]
+ plug(Pleroma.Web.FederatingPlug)
+
# Note: follower can submit the form (with password auth) not being signed in (having no token)
plug(
OAuthScopesPlug,
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index bca0e26eb..537f9f778 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -17,6 +17,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.WebFinger
+ plug(Pleroma.Web.FederatingPlug when action == :remote_subscribe)
+
plug(
OAuthScopesPlug,
%{scopes: ["follow", "write:follows"]}
diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex
index 598df6580..0f8ece2c4 100644
--- a/lib/pleroma/workers/background_worker.ex
+++ b/lib/pleroma/workers/background_worker.ex
@@ -10,10 +10,6 @@ defmodule Pleroma.Workers.BackgroundWorker do
use Pleroma.Workers.WorkerHelper, queue: "background"
@impl Oban.Worker
- def perform(%{"op" => "fetch_initial_posts", "user_id" => user_id}, _job) do
- user = User.get_cached_by_id(user_id)
- User.perform(:fetch_initial_posts, user)
- end
def perform(%{"op" => "deactivate_user", "user_id" => user_id, "status" => status}, _job) do
user = User.get_cached_by_id(user_id)