Merge remote-tracking branch 'upstream/develop' into neckbeard

This commit is contained in:
Your New SJW Waifu 2024-02-06 11:36:27 -06:00
commit 78f816b822
121 changed files with 1153 additions and 564 deletions

6
.dialyzer_ignore.exs Normal file
View File

@ -0,0 +1,6 @@
[
{"lib/cachex.ex", "Unknown type: Spec.cache/0."},
{"lib/pleroma/web/plugs/rate_limiter.ex", "The pattern can never match the type {:commit, _} | {:ignore, _}."},
{"lib/pleroma/web/plugs/rate_limiter.ex", "Function get_scale/2 will never be called."},
{"lib/pleroma/web/plugs/rate_limiter.ex", "Function initialize_buckets!/1 will never be called."}
]

View File

View File

View File

View File

View File

@ -0,0 +1 @@
Mastodon API /api/v1/directory: Fix listing directory contents when not authenticated

View File

@ -0,0 +1 @@
Rich Media Preview cache eviction when the activity is updated.

View File

@ -1,4 +1,4 @@
FROM elixir:1.12.3 FROM elixir:1.15.7-otp-25
# Single RUN statement, otherwise intermediate images are created # Single RUN statement, otherwise intermediate images are created
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run # https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run

View File

@ -111,7 +111,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
{:ok, _} = {:ok, _} =
:zip.unzip(binary_archive, :zip.unzip(binary_archive,
cwd: pack_path, cwd: String.to_charlist(pack_path),
file_list: files_to_unzip file_list: files_to_unzip
) )

View File

@ -28,7 +28,7 @@ defmodule Pleroma.Activity.HTML do
end end
end end
defp add_cache_key_for(activity_id, additional_key) do def add_cache_key_for(activity_id, additional_key) do
current = get_cache_keys_for(activity_id) current = get_cache_keys_for(activity_id)
unless additional_key in current do unless additional_key in current do

View File

@ -256,7 +256,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
move_namespace_and_warn(@mrf_config_map, warning_preface) move_namespace_and_warn(@mrf_config_map, warning_preface)
end end
@spec move_namespace_and_warn([config_map()], String.t()) :: :ok | nil @spec move_namespace_and_warn([config_map()], String.t()) :: :ok | :error
def move_namespace_and_warn(config_map, warning_preface) do def move_namespace_and_warn(config_map, warning_preface) do
warning = warning =
Enum.reduce(config_map, "", fn Enum.reduce(config_map, "", fn
@ -279,7 +279,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
end end
end end
@spec check_media_proxy_whitelist_config() :: :ok | nil @spec check_media_proxy_whitelist_config() :: :ok | :error
def check_media_proxy_whitelist_config do def check_media_proxy_whitelist_config do
whitelist = Config.get([:media_proxy, :whitelist]) whitelist = Config.get([:media_proxy, :whitelist])
@ -340,7 +340,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
end end
end end
@spec check_activity_expiration_config() :: :ok | nil @spec check_activity_expiration_config() :: :ok | :error
def check_activity_expiration_config do def check_activity_expiration_config do
warning_preface = """ warning_preface = """
!!!DEPRECATION WARNING!!! !!!DEPRECATION WARNING!!!
@ -356,7 +356,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
) )
end end
@spec check_remote_ip_plug_name() :: :ok | nil @spec check_remote_ip_plug_name() :: :ok | :error
def check_remote_ip_plug_name do def check_remote_ip_plug_name do
warning_preface = """ warning_preface = """
!!!DEPRECATION WARNING!!! !!!DEPRECATION WARNING!!!
@ -372,7 +372,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
) )
end end
@spec check_uploaders_s3_public_endpoint() :: :ok | nil @spec check_uploaders_s3_public_endpoint() :: :ok | :error
def check_uploaders_s3_public_endpoint do def check_uploaders_s3_public_endpoint do
s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3]) s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3])
@ -393,7 +393,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
end end
end end
@spec check_old_chat_shoutbox() :: :ok | nil @spec check_old_chat_shoutbox() :: :ok | :error
def check_old_chat_shoutbox do def check_old_chat_shoutbox do
instance_config = Pleroma.Config.get([:instance]) instance_config = Pleroma.Config.get([:instance])
chat_config = Pleroma.Config.get([:chat]) || [] chat_config = Pleroma.Config.get([:chat]) || []

View File

@ -57,7 +57,7 @@ defmodule Pleroma.Conversation do
3. Bump all relevant participations to 'unread' 3. Bump all relevant participations to 'unread'
""" """
def create_or_bump_for(activity, opts \\ []) do def create_or_bump_for(activity, opts \\ []) do
with true <- Pleroma.Web.ActivityPub.Visibility.is_direct?(activity), with true <- Pleroma.Web.ActivityPub.Visibility.direct?(activity),
"Create" <- activity.data["type"], "Create" <- activity.data["type"],
%Object{} = object <- Object.normalize(activity, fetch: false), %Object{} = object <- Object.normalize(activity, fetch: false),
true <- object.data["type"] in ["Note", "Question"], true <- object.data["type"] in ["Note", "Question"],

View File

@ -51,12 +51,12 @@ defmodule Pleroma.Emoji do
end end
@doc "Returns the path of the emoji `name`." @doc "Returns the path of the emoji `name`."
@spec get(String.t()) :: String.t() | nil @spec get(String.t()) :: Pleroma.Emoji.t() | nil
def get(name) do def get(name) do
name = maybe_strip_name(name) name = maybe_strip_name(name)
case :ets.lookup(@ets, name) do case :ets.lookup(@ets, name) do
[{_, path}] -> path [{_, emoji}] -> emoji
_ -> nil _ -> nil
end end
end end
@ -138,23 +138,23 @@ defmodule Pleroma.Emoji do
emojis = emojis ++ regional_indicators emojis = emojis ++ regional_indicators
for emoji <- emojis do for emoji <- emojis do
def is_unicode_emoji?(unquote(emoji)), do: true def unicode?(unquote(emoji)), do: true
end end
def is_unicode_emoji?(_), do: false def unicode?(_), do: false
@emoji_regex ~r/:[A-Za-z0-9_-]+(@.+)?:/ @emoji_regex ~r/:[A-Za-z0-9_-]+(@.+)?:/
def is_custom_emoji?(s) when is_binary(s), do: Regex.match?(@emoji_regex, s) def custom?(s) when is_binary(s), do: Regex.match?(@emoji_regex, s)
def is_custom_emoji?(_), do: false def custom?(_), do: false
def maybe_strip_name(name) when is_binary(name), do: String.trim(name, ":") def maybe_strip_name(name) when is_binary(name), do: String.trim(name, ":")
def maybe_strip_name(name), do: name def maybe_strip_name(name), do: name
def maybe_quote(name) when is_binary(name) do def maybe_quote(name) when is_binary(name) do
if is_unicode_emoji?(name) do if unicode?(name) do
name name
else else
if String.starts_with?(name, ":") do if String.starts_with?(name, ":") do

View File

@ -100,7 +100,7 @@ defmodule Pleroma.Emoji.Pack do
{:ok, _emoji_files} = {:ok, _emoji_files} =
:zip.unzip( :zip.unzip(
to_charlist(file.path), to_charlist(file.path),
[{:file_list, Enum.map(emojies, & &1[:path])}, {:cwd, tmp_dir}] [{:file_list, Enum.map(emojies, & &1[:path])}, {:cwd, String.to_charlist(tmp_dir)}]
) )
{_, updated_pack} = {_, updated_pack} =

View File

@ -216,9 +216,6 @@ defmodule Pleroma.Filter do
:re -> :re ->
~r/\b#{phrases}\b/i ~r/\b#{phrases}\b/i
_ ->
nil
end end
end end

View File

@ -114,7 +114,7 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
def response("/notices/" <> id) do def response("/notices/" <> id) do
with %Activity{} = activity <- Activity.get_by_id(id), with %Activity{} = activity <- Activity.get_by_id(id),
true <- Visibility.is_public?(activity) do true <- Visibility.public?(activity) do
activities = activities =
ActivityPub.fetch_activities_for_context(activity.data["context"]) ActivityPub.fetch_activities_for_context(activity.data["context"])
|> render_activities |> render_activities

View File

@ -9,7 +9,7 @@ defmodule Pleroma.Gun.ConnectionPool.Reclaimer do
def start_monitor do def start_monitor do
pid = pid =
case :gen_server.start(__MODULE__, [], name: {:via, Registry, {registry(), "reclaimer"}}) do case GenServer.start_link(__MODULE__, [], name: {:via, Registry, {registry(), "reclaimer"}}) do
{:ok, pid} -> {:ok, pid} ->
pid pid

View File

@ -126,9 +126,15 @@ defmodule Pleroma.Helpers.QtFastStart do
<<pos::integer-big-size(unquote(size)), rest::bits>>, <<pos::integer-big-size(unquote(size)), rest::bits>>,
acc acc
) do ) do
rewrite_entries(unquote(size), offset, rest, [ rewrite_entries(
acc | <<pos + offset::integer-big-size(unquote(size))>> unquote(size),
]) offset,
rest,
acc ++
[
<<pos + offset::integer-big-size(unquote(size))>>
]
)
end end
end end

View File

@ -6,8 +6,6 @@ defmodule Pleroma.HTML do
# Scrubbers are compiled on boot so they can be configured in OTP releases # Scrubbers are compiled on boot so they can be configured in OTP releases
# @on_load :compile_scrubbers # @on_load :compile_scrubbers
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def compile_scrubbers do def compile_scrubbers do
dir = Path.join(:code.priv_dir(:pleroma), "scrubbers") dir = Path.join(:code.priv_dir(:pleroma), "scrubbers")
@ -67,27 +65,20 @@ defmodule Pleroma.HTML do
end end
end end
def extract_first_external_url_from_object(%{data: %{"content" => content}} = object) @spec extract_first_external_url_from_object(Pleroma.Object.t()) ::
{:ok, String.t()} | {:error, :no_content}
def extract_first_external_url_from_object(%{data: %{"content" => content}})
when is_binary(content) do when is_binary(content) do
unless object.data["fake"] do url =
key = "URL|#{object.id}" content
|> Floki.parse_fragment!()
|> Floki.find("a:not(.mention,.hashtag,.attachment,[rel~=\"tag\"])")
|> Enum.take(1)
|> Floki.attribute("href")
|> Enum.at(0)
@cachex.fetch!(:scrubber_cache, key, fn _key -> {:ok, url}
{:commit, {:ok, extract_first_external_url(content)}}
end)
else
{:ok, extract_first_external_url(content)}
end
end end
def extract_first_external_url_from_object(_), do: {:error, :no_content} def extract_first_external_url_from_object(_), do: {:error, :no_content}
def extract_first_external_url(content) do
content
|> Floki.parse_fragment!()
|> Floki.find("a:not(.mention,.hashtag,.attachment,[rel~=\"tag\"])")
|> Enum.take(1)
|> Floki.attribute("href")
|> Enum.at(0)
end
end end

View File

@ -54,12 +54,12 @@ defmodule Pleroma.HTTP.RequestBuilder do
@doc """ @doc """
Add optional parameters to the request Add optional parameters to the request
""" """
@spec add_param(Request.t(), atom(), atom(), any()) :: Request.t() @spec add_param(Request.t(), atom(), atom() | String.t(), any()) :: Request.t()
def add_param(request, :query, :query, values), do: %{request | query: values} def add_param(request, :query, :query, values), do: %{request | query: values}
def add_param(request, :body, :body, value), do: %{request | body: value} def add_param(request, :body, :body, value), do: %{request | body: value}
def add_param(request, :body, key, value) do def add_param(request, :body, key, value) when is_binary(key) do
request request
|> Map.put(:body, Multipart.new()) |> Map.put(:body, Multipart.new())
|> Map.update!( |> Map.update!(

View File

@ -77,7 +77,7 @@ defmodule Pleroma.MFA do
{:ok, codes} {:ok, codes}
else else
{:error, msg} -> {:error, msg} ->
%{error: msg} {:error, msg}
end end
end end

View File

@ -14,6 +14,7 @@ defmodule Pleroma.MFA.TOTP do
@doc """ @doc """
https://github.com/google/google-authenticator/wiki/Key-Uri-Format https://github.com/google/google-authenticator/wiki/Key-Uri-Format
""" """
@spec provisioning_uri(String.t(), String.t(), list()) :: String.t()
def provisioning_uri(secret, label, opts \\ []) do def provisioning_uri(secret, label, opts \\ []) do
query = query =
%{ %{
@ -27,7 +28,7 @@ defmodule Pleroma.MFA.TOTP do
|> URI.encode_query() |> URI.encode_query()
%URI{scheme: "otpauth", host: "totp", path: "/" <> label, query: query} %URI{scheme: "otpauth", host: "totp", path: "/" <> label, query: query}
|> URI.to_string() |> to_string()
end end
defp default_period, do: Config.get(@config_ns ++ [:period]) defp default_period, do: Config.get(@config_ns ++ [:period])

View File

@ -121,7 +121,7 @@ defmodule Pleroma.ModerationLog do
defp prepare_log_data(attrs), do: attrs defp prepare_log_data(attrs), do: attrs
@spec insert_log(log_params()) :: {:ok, ModerationLog} | {:error, any} @spec insert_log(log_params()) :: {:ok, ModerationLog.t()} | {:error, any}
def insert_log(%{actor: %User{}, subject: subjects, permission: permission} = attrs) do def insert_log(%{actor: %User{}, subject: subjects, permission: permission} = attrs) do
data = data =
attrs attrs
@ -248,7 +248,8 @@ defmodule Pleroma.ModerationLog do
|> insert_log_entry_with_message() |> insert_log_entry_with_message()
end end
@spec insert_log_entry_with_message(ModerationLog) :: {:ok, ModerationLog} | {:error, any} @spec insert_log_entry_with_message(ModerationLog.t()) ::
{:ok, ModerationLog.t()} | {:error, any}
defp insert_log_entry_with_message(entry) do defp insert_log_entry_with_message(entry) do
entry.data["message"] entry.data["message"]
|> put_in(get_log_entry_message(entry)) |> put_in(get_log_entry_message(entry))

View File

@ -242,17 +242,17 @@ defmodule Pleroma.Object do
{:ok, _} <- invalid_object_cache(object) do {:ok, _} <- invalid_object_cache(object) do
cleanup_attachments( cleanup_attachments(
Config.get([:instance, :cleanup_attachments]), Config.get([:instance, :cleanup_attachments]),
%{"object" => object} object
) )
{:ok, object, deleted_activity} {:ok, object, deleted_activity}
end end
end end
@spec cleanup_attachments(boolean(), %{required(:object) => map()}) :: @spec cleanup_attachments(boolean(), Object.t()) ::
{:ok, Oban.Job.t() | nil} {:ok, Oban.Job.t() | nil}
def cleanup_attachments(true, %{"object" => _} = params) do def cleanup_attachments(true, %Object{} = object) do
AttachmentsCleanupWorker.enqueue("cleanup_attachments", params) AttachmentsCleanupWorker.enqueue("cleanup_attachments", %{"object" => object})
end end
def cleanup_attachments(_, _), do: {:ok, nil} def cleanup_attachments(_, _), do: {:ok, nil}

View File

@ -61,15 +61,16 @@ defmodule Pleroma.Pagination do
|> Repo.all() |> Repo.all()
end end
@spec paginate(Ecto.Query.t(), map(), type(), atom() | nil) :: [Ecto.Schema.t()] @spec paginate_list(list(), keyword()) :: list()
def paginate(query, options, method \\ :keyset, table_binding \\ nil) def paginate_list(list, options) do
def paginate(list, options, _method, _table_binding) when is_list(list) do
offset = options[:offset] || 0 offset = options[:offset] || 0
limit = options[:limit] || 0 limit = options[:limit] || 0
Enum.slice(list, offset, limit) Enum.slice(list, offset, limit)
end end
@spec paginate(Ecto.Query.t(), map(), type(), atom() | nil) :: [Ecto.Schema.t()]
def paginate(query, options, method \\ :keyset, table_binding \\ nil)
def paginate(query, options, :keyset, table_binding) do def paginate(query, options, :keyset, table_binding) do
query query
|> restrict(:min_id, options, table_binding) |> restrict(:min_id, options, table_binding)

View File

@ -84,13 +84,13 @@ defmodule Pleroma.ReverseProxy do
{:max_read_duration, non_neg_integer() | :infinity} {:max_read_duration, non_neg_integer() | :infinity}
| {:max_body_length, non_neg_integer() | :infinity} | {:max_body_length, non_neg_integer() | :infinity}
| {:failed_request_ttl, non_neg_integer() | :infinity} | {:failed_request_ttl, non_neg_integer() | :infinity}
| {:http, []} | {:http, keyword()}
| {:req_headers, [{String.t(), String.t()}]} | {:req_headers, [{String.t(), String.t()}]}
| {:resp_headers, [{String.t(), String.t()}]} | {:resp_headers, [{String.t(), String.t()}]}
| {:inline_content_types, boolean() | [String.t()]} | {:inline_content_types, boolean() | list(String.t())}
| {:redirect_on_failure, boolean()} | {:redirect_on_failure, boolean()}
@spec call(Plug.Conn.t(), url :: String.t(), [option()]) :: Plug.Conn.t() @spec call(Plug.Conn.t(), String.t(), list(option())) :: Plug.Conn.t()
def call(_conn, _url, _opts \\ []) def call(_conn, _url, _opts \\ [])
def call(conn = %{method: method}, url, opts) when method in @methods do def call(conn = %{method: method}, url, opts) when method in @methods do
@ -388,8 +388,6 @@ defmodule Pleroma.ReverseProxy do
defp body_size_constraint(_, _), do: :ok defp body_size_constraint(_, _), do: :ok
defp check_read_duration(nil = _duration, max), do: check_read_duration(@max_read_duration, max)
defp check_read_duration(duration, max) defp check_read_duration(duration, max)
when is_integer(duration) and is_integer(max) and max > 0 do when is_integer(duration) and is_integer(max) and max > 0 do
if duration > max do if duration > max do
@ -407,10 +405,6 @@ defmodule Pleroma.ReverseProxy do
{:ok, previous_duration + duration} {:ok, previous_duration + duration}
end end
defp increase_read_duration(_) do
{:ok, :no_duration_limit, :no_duration_limit}
end
defp client, do: Pleroma.ReverseProxy.Client.Wrapper defp client, do: Pleroma.ReverseProxy.Client.Wrapper
defp track_failed_url(url, error, opts) do defp track_failed_url(url, error, opts) do

View File

@ -20,5 +20,5 @@ defmodule Pleroma.Search.SearchBackend do
is what contains the actual content and there is no need for filtering when removing is what contains the actual content and there is no need for filtering when removing
from index. from index.
""" """
@callback remove_from_index(object :: Pleroma.Object.t()) :: {:ok, any()} | {:error, any()} @callback remove_from_index(object :: Pleroma.Object.t()) :: :ok | {:error, any()}
end end

View File

@ -27,7 +27,7 @@ defmodule Pleroma.Signature do
_ -> _ ->
case Pleroma.Web.WebFinger.finger(maybe_ap_id) do case Pleroma.Web.WebFinger.finger(maybe_ap_id) do
%{"ap_id" => ap_id} -> {:ok, ap_id} {:ok, %{"ap_id" => ap_id}} -> {:ok, ap_id}
_ -> {:error, maybe_ap_id} _ -> {:error, maybe_ap_id}
end end
end end

View File

@ -51,6 +51,7 @@ defmodule Pleroma.Upload do
| {:size_limit, nil | non_neg_integer()} | {:size_limit, nil | non_neg_integer()}
| {:uploader, module()} | {:uploader, module()}
| {:filters, [module()]} | {:filters, [module()]}
| {:actor, String.t()}
@type t :: %__MODULE__{ @type t :: %__MODULE__{
id: String.t(), id: String.t(),
@ -175,7 +176,7 @@ defmodule Pleroma.Upload do
defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do
parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data) parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data)
data = Base.decode64!(parsed["data"], ignore: :whitespace) data = Base.decode64!(parsed["data"], ignore: :whitespace)
hash = Base.encode16(:crypto.hash(:sha256, data), lower: true) hash = Base.encode16(:crypto.hash(:sha256, data), case: :upper)
with :ok <- check_binary_size(data, opts.size_limit), with :ok <- check_binary_size(data, opts.size_limit),
tmp_path <- tempfile_for_image(data), tmp_path <- tempfile_for_image(data),

View File

@ -1787,7 +1787,10 @@ defmodule Pleroma.User do
@spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} @spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def set_activation(users, status) when is_list(users) do def set_activation(users, status) when is_list(users) do
Repo.transaction(fn -> Repo.transaction(fn ->
for user <- users, do: set_activation(user, status) for user <- users do
{:ok, user} = set_activation(user, status)
user
end
end) end)
end end
@ -2404,9 +2407,9 @@ defmodule Pleroma.User do
defp put_password_hash(changeset), do: changeset defp put_password_hash(changeset), do: changeset
def is_internal_user?(%User{nickname: nil}), do: true def internal?(%User{nickname: nil}), do: true
def is_internal_user?(%User{local: true, nickname: "internal." <> _}), do: true def internal?(%User{local: true, nickname: "internal." <> _}), do: true
def is_internal_user?(_), do: false def internal?(_), do: false
# A hack because user delete activities have a fake id for whatever reason # A hack because user delete activities have a fake id for whatever reason
# TODO: Get rid of this # TODO: Get rid of this
@ -2556,9 +2559,9 @@ defmodule Pleroma.User do
cast(user, params, [:is_confirmed, :confirmation_token]) cast(user, params, [:is_confirmed, :confirmation_token])
end end
@spec approval_changeset(User.t(), keyword()) :: Ecto.Changeset.t() @spec approval_changeset(Ecto.Changeset.t(), keyword()) :: Ecto.Changeset.t()
def approval_changeset(user, set_approval: approved?) do def approval_changeset(changeset, set_approval: approved?) do
cast(user, %{is_approved: approved?}, [:is_approved]) cast(changeset, %{is_approved: approved?}, [:is_approved])
end end
@spec add_pinned_object_id(User.t(), String.t()) :: {:ok, User.t()} | {:error, term()} @spec add_pinned_object_id(User.t(), String.t()) :: {:ok, User.t()} | {:error, term()}

View File

@ -74,22 +74,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp check_remote_limit(_), do: true defp check_remote_limit(_), do: true
def increase_note_count_if_public(actor, object) do def increase_note_count_if_public(actor, object) do
if is_public?(object), do: User.increase_note_count(actor), else: {:ok, actor} if public?(object), do: User.increase_note_count(actor), else: {:ok, actor}
end end
def decrease_note_count_if_public(actor, object) do def decrease_note_count_if_public(actor, object) do
if is_public?(object), do: User.decrease_note_count(actor), else: {:ok, actor} if public?(object), do: User.decrease_note_count(actor), else: {:ok, actor}
end end
def update_last_status_at_if_public(actor, object) do def update_last_status_at_if_public(actor, object) do
if is_public?(object), do: User.update_last_status_at(actor), else: {:ok, actor} if public?(object), do: User.update_last_status_at(actor), else: {:ok, actor}
end end
defp increase_replies_count_if_reply(%{ defp increase_replies_count_if_reply(%{
"object" => %{"inReplyTo" => reply_ap_id} = object, "object" => %{"inReplyTo" => reply_ap_id} = object,
"type" => "Create" "type" => "Create"
}) do }) do
if is_public?(object) do if public?(object) do
Object.increase_replies_count(reply_ap_id) Object.increase_replies_count(reply_ap_id)
end end
end end
@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
"object" => %{"quoteUrl" => quote_ap_id} = object, "object" => %{"quoteUrl" => quote_ap_id} = object,
"type" => "Create" "type" => "Create"
}) do }) do
if is_public?(object) do if public?(object) do
Object.increase_quotes_count(quote_ap_id) Object.increase_quotes_count(quote_ap_id)
end end
end end

View File

@ -132,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
def emoji_react(actor, object, emoji) do def emoji_react(actor, object, emoji) do
with {:ok, data, meta} <- object_action(actor, object) do with {:ok, data, meta} <- object_action(actor, object) do
data = data =
if Emoji.is_unicode_emoji?(emoji) do if Emoji.unicode?(emoji) do
unicode_emoji_react(object, data, emoji) unicode_emoji_react(object, data, emoji)
else else
custom_emoji_react(object, data, emoji) custom_emoji_react(object, data, emoji)
@ -348,7 +348,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
actor.ap_id == Relay.ap_id() -> actor.ap_id == Relay.ap_id() ->
[actor.follower_address] [actor.follower_address]
public? and Visibility.is_local_public?(object) -> public? and Visibility.local_public?(object) ->
[actor.follower_address, object.data["actor"], Utils.as_local_public()] [actor.follower_address, object.data["actor"], Utils.as_local_public()]
public? -> public? ->
@ -376,7 +376,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
# Address the actor of the object, and our actor's follower collection if the post is public. # Address the actor of the object, and our actor's follower collection if the post is public.
to = to =
if Visibility.is_public?(object) do if Visibility.public?(object) do
[actor.follower_address, object.data["actor"]] [actor.follower_address, object.data["actor"]]
else else
[object.data["actor"]] [object.data["actor"]]

View File

@ -10,9 +10,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
@impl true @impl true
def filter(%{"actor" => actor} = object) do def filter(%{"actor" => actor} = object) do
with true <- is_local?(actor), with true <- local?(actor),
true <- is_eligible_type?(object), true <- eligible_type?(object),
true <- is_note?(object), true <- note?(object),
false <- has_attachment?(object), false <- has_attachment?(object),
true <- only_mentions?(object) do true <- only_mentions?(object) do
{:reject, "[NoEmptyPolicy]"} {:reject, "[NoEmptyPolicy]"}
@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
def filter(object), do: {:ok, object} def filter(object), do: {:ok, object}
defp is_local?(actor) do defp local?(actor) do
if actor |> String.starts_with?("#{Endpoint.url()}") do if actor |> String.starts_with?("#{Endpoint.url()}") do
true true
else else
@ -59,11 +59,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
defp only_mentions?(_), do: false defp only_mentions?(_), do: false
defp is_note?(%{"object" => %{"type" => "Note"}}), do: true defp note?(%{"object" => %{"type" => "Note"}}), do: true
defp is_note?(_), do: false defp note?(_), do: false
defp is_eligible_type?(%{"type" => type}) when type in ["Create", "Update"], do: true defp eligible_type?(%{"type" => type}) when type in ["Create", "Update"], do: true
defp is_eligible_type?(_), do: false defp eligible_type?(_), do: false
@impl true @impl true
def describe, do: {:ok, %{}} def describe, do: {:ok, %{}}

View File

@ -28,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
tags = object["tag"] || [] tags = object["tag"] || []
if Enum.any?(tags, fn tag -> if Enum.any?(tags, fn tag ->
CommonFixes.is_object_link_tag(tag) and tag["href"] == quote_url CommonFixes.object_link_tag?(tag) and tag["href"] == quote_url
end) do end) do
object object
else else

View File

@ -173,6 +173,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
{:object_validation, e} -> {:object_validation, e} ->
e e
{:error, %Ecto.Changeset{} = e} ->
{:error, e}
end end
end end

View File

@ -82,7 +82,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
object when is_binary(object) <- get_field(cng, :object), object when is_binary(object) <- get_field(cng, :object),
%User{} = actor <- User.get_cached_by_ap_id(actor), %User{} = actor <- User.get_cached_by_ap_id(actor),
%Object{} = object <- Object.get_cached_by_ap_id(object), %Object{} = object <- Object.get_cached_by_ap_id(object),
false <- Visibility.is_public?(object) do false <- Visibility.public?(object) do
same_actor = object.data["actor"] == actor.ap_id same_actor = object.data["actor"] == actor.ap_id
recipients = get_field(cng, :to) ++ get_field(cng, :cc) recipients = get_field(cng, :to) ++ get_field(cng, :cc)
local_public = Utils.as_local_public() local_public = Utils.as_local_public()

View File

@ -99,7 +99,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
end end
def fix_quote_url(%{"tag" => [_ | _] = tags} = data) do def fix_quote_url(%{"tag" => [_ | _] = tags} = data) do
tag = Enum.find(tags, &is_object_link_tag/1) tag = Enum.find(tags, &object_link_tag?/1)
if not is_nil(tag) do if not is_nil(tag) do
data data
@ -112,7 +112,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
def fix_quote_url(data), do: data def fix_quote_url(data), do: data
# https://codeberg.org/fediverse/fep/src/branch/main/fep/e232/fep-e232.md # https://codeberg.org/fediverse/fep/src/branch/main/fep/e232/fep-e232.md
def is_object_link_tag(%{ def object_link_tag?(%{
"type" => "Link", "type" => "Link",
"mediaType" => media_type, "mediaType" => media_type,
"href" => href "href" => href
@ -121,5 +121,5 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
true true
end end
def is_object_link_tag(_), do: false def object_link_tag?(_), do: false
end end

View File

@ -74,10 +74,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
new_emoji = Pleroma.Emoji.fully_qualify_emoji(emoji) new_emoji = Pleroma.Emoji.fully_qualify_emoji(emoji)
cond do cond do
Pleroma.Emoji.is_unicode_emoji?(emoji) -> Pleroma.Emoji.unicode?(emoji) ->
data data
Pleroma.Emoji.is_unicode_emoji?(new_emoji) -> Pleroma.Emoji.unicode?(new_emoji) ->
data |> Map.put("content", new_emoji) data |> Map.put("content", new_emoji)
true -> true ->
@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
defp validate_emoji(cng) do defp validate_emoji(cng) do
content = get_field(cng, :content) content = get_field(cng, :content)
if Emoji.is_unicode_emoji?(content) || Emoji.is_custom_emoji?(content) do if Emoji.unicode?(content) || Emoji.custom?(content) do
cng cng
else else
cng cng
@ -101,7 +101,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
defp maybe_validate_tag_presence(cng) do defp maybe_validate_tag_presence(cng) do
content = get_field(cng, :content) content = get_field(cng, :content)
if Emoji.is_unicode_emoji?(content) do if Emoji.unicode?(content) do
cng cng
else else
tag = get_field(cng, :tag) tag = get_field(cng, :tag)

View File

@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.Pipeline 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.local_public?(activity) do
activity = activity =
if object = Keyword.get(meta, :object_data) do if object = Keyword.get(meta, :object_data) do
%{activity | data: Map.put(activity.data, "object", object)} %{activity | data: Map.put(activity.data, "object", object)}

View File

@ -66,7 +66,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
@doc """ @doc """
Determine if an activity can be represented by running it through Transmogrifier. Determine if an activity can be represented by running it through Transmogrifier.
""" """
def is_representable?(%Activity{} = activity) do def representable?(%Activity{} = activity) do
with {:ok, _data} <- Transmogrifier.prepare_outgoing(activity.data) do with {:ok, _data} <- Transmogrifier.prepare_outgoing(activity.data) do
true true
else else
@ -246,7 +246,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity) def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
when is_list(bcc) and bcc != [] do when is_list(bcc) and bcc != [] do
public = is_public?(activity) public = public?(activity)
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data) {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
[priority_recipients, recipients] = recipients(actor, activity) [priority_recipients, recipients] = recipients(actor, activity)
@ -291,7 +291,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
# Publishes an activity to all relevant peers. # Publishes an activity to all relevant peers.
def publish(%User{} = actor, %Activity{} = activity) do def publish(%User{} = actor, %Activity{} = activity) do
public = is_public?(activity) public = public?(activity)
if public && Config.get([:instance, :allow_relay]) do if public && Config.get([:instance, :allow_relay]) do
Logger.debug(fn -> "Relaying #{activity.data["id"]} out" end) Logger.debug(fn -> "Relaying #{activity.data["id"]} out" end)

View File

@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
@spec publish(any()) :: {:ok, Activity.t()} | {:error, any()} @spec publish(any()) :: {:ok, Activity.t()} | {:error, any()}
def publish(%Activity{data: %{"type" => "Create"}} = activity) do def publish(%Activity{data: %{"type" => "Create"}} = activity) do
with %User{} = user <- get_actor(), with %User{} = user <- get_actor(),
true <- Visibility.is_public?(activity) do true <- Visibility.public?(activity) do
CommonAPI.repeat(activity.id, user) CommonAPI.repeat(activity.id, user)
else else
error -> format_error(error) error -> format_error(error)

View File

@ -258,7 +258,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
Utils.add_announce_to_object(object, announced_object) Utils.add_announce_to_object(object, announced_object)
if !User.is_internal_user?(user) do if !User.internal?(user) do
Notification.create_notifications(object) Notification.create_notifications(object)
ap_streamer().stream_out(object) ap_streamer().stream_out(object)
@ -304,9 +304,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
result = result =
case deleted_object do case deleted_object do
%Object{} -> %Object{} ->
with {:ok, deleted_object, _activity} <- Object.delete(deleted_object), with {_, {:ok, deleted_object, _activity}} <- {:object, Object.delete(deleted_object)},
{_, actor} when is_binary(actor) <- {:actor, deleted_object.data["actor"]}, {_, actor} when is_binary(actor) <- {:actor, deleted_object.data["actor"]},
%User{} = user <- User.get_cached_by_ap_id(actor) do {_, %User{} = user} <- {:user, User.get_cached_by_ap_id(actor)} do
User.remove_pinned_object_id(user, deleted_object.data["id"]) User.remove_pinned_object_id(user, deleted_object.data["id"])
{:ok, user} = ActivityPub.decrease_note_count_if_public(user, deleted_object) {:ok, user} = ActivityPub.decrease_note_count_if_public(user, deleted_object)
@ -328,6 +328,17 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:actor, _} -> {:actor, _} ->
@logger.error("The object doesn't have an actor: #{inspect(deleted_object)}") @logger.error("The object doesn't have an actor: #{inspect(deleted_object)}")
:no_object_actor :no_object_actor
{:user, _} ->
@logger.error(
"The object's actor could not be resolved to a user: #{inspect(deleted_object)}"
)
:no_object_user
{:object, _} ->
@logger.error("The object could not be deleted: #{inspect(deleted_object)}")
{:error, object}
end end
%User{} -> %User{} ->
@ -569,7 +580,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
def handle_undoing(object), do: {:error, ["don't know how to handle", object]} def handle_undoing(object), do: {:error, ["don't know how to handle", object]}
@spec delete_object(Object.t()) :: :ok | {:error, Ecto.Changeset.t()} @spec delete_object(Activity.t()) :: :ok | {:error, Ecto.Changeset.t()}
defp delete_object(object) do defp delete_object(object) do
with {:ok, _} <- Repo.delete(object), do: :ok with {:ok, _} <- Repo.delete(object), do: :ok
end end

View File

@ -4,5 +4,5 @@
defmodule Pleroma.Web.ActivityPub.SideEffects.Handling do defmodule Pleroma.Web.ActivityPub.SideEffects.Handling do
@callback handle(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()} @callback handle(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
@callback handle_after_transaction(map()) :: map() @callback handle_after_transaction(keyword()) :: keyword()
end end

View File

@ -783,7 +783,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Object.normalize(fetch: false) |> Object.normalize(fetch: false)
data = data =
if Visibility.is_private?(object) && object.data["actor"] == ap_id do if Visibility.private?(object) && object.data["actor"] == ap_id do
data |> Map.put("object", object |> Map.get(:data) |> prepare_object) data |> Map.put("object", object |> Map.get(:data) |> prepare_object)
else else
data |> maybe_fix_object_url data |> maybe_fix_object_url

View File

@ -167,7 +167,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
with true <- Config.get!([:instance, :federating]), with true <- Config.get!([:instance, :federating]),
true <- type != "Block" || outgoing_blocks, true <- type != "Block" || outgoing_blocks,
false <- Visibility.is_local_public?(activity) do false <- Visibility.local_public?(activity) do
Pleroma.Web.Federator.publish(activity) Pleroma.Web.Federator.publish(activity)
end end
@ -277,7 +277,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
object_actor = User.get_cached_by_ap_id(object_actor_id) object_actor = User.get_cached_by_ap_id(object_actor_id)
to = to =
if Visibility.is_public?(object) do if Visibility.public?(object) do
[actor.follower_address, object.data["actor"]] [actor.follower_address, object.data["actor"]]
else else
[object.data["actor"]] [object.data["actor"]]
@ -776,10 +776,9 @@ defmodule Pleroma.Web.ActivityPub.Utils do
build_flag_object(object) build_flag_object(object)
nil -> nil ->
if %Object{} = object = Object.get_by_ap_id(id) do case Object.get_by_ap_id(id) do
build_flag_object(object) %Object{} = object -> build_flag_object(object)
else _ -> %{"id" => id, "deleted" => true}
%{"id" => id, "deleted" => true}
end end
end end
end end

View File

@ -11,28 +11,28 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
require Pleroma.Constants require Pleroma.Constants
@spec is_public?(Object.t() | Activity.t() | map()) :: boolean() @spec public?(Object.t() | Activity.t() | map()) :: boolean()
def is_public?(%Object{data: %{"type" => "Tombstone"}}), do: false def public?(%Object{data: %{"type" => "Tombstone"}}), do: false
def is_public?(%Object{data: data}), do: is_public?(data) def public?(%Object{data: data}), do: public?(data)
def is_public?(%Activity{data: %{"type" => "Move"}}), do: true def public?(%Activity{data: %{"type" => "Move"}}), do: true
def is_public?(%Activity{data: data}), do: is_public?(data) def public?(%Activity{data: data}), do: public?(data)
def is_public?(%{"directMessage" => true}), do: false def public?(%{"directMessage" => true}), do: false
def is_public?(data) do def public?(data) do
Utils.label_in_message?(Pleroma.Constants.as_public(), data) or Utils.label_in_message?(Pleroma.Constants.as_public(), data) or
Utils.label_in_message?(Utils.as_local_public(), data) Utils.label_in_message?(Utils.as_local_public(), data)
end end
def is_local_public?(%Object{data: data}), do: is_local_public?(data) def local_public?(%Object{data: data}), do: local_public?(data)
def is_local_public?(%Activity{data: data}), do: is_local_public?(data) def local_public?(%Activity{data: data}), do: local_public?(data)
def is_local_public?(data) do def local_public?(data) do
Utils.label_in_message?(Utils.as_local_public(), data) and Utils.label_in_message?(Utils.as_local_public(), data) and
not Utils.label_in_message?(Pleroma.Constants.as_public(), data) not Utils.label_in_message?(Pleroma.Constants.as_public(), data)
end end
def is_private?(activity) do def private?(activity) do
with false <- is_public?(activity), with false <- public?(activity),
%User{follower_address: follower_address} <- %User{follower_address: follower_address} <-
User.get_cached_by_ap_id(activity.data["actor"]) do User.get_cached_by_ap_id(activity.data["actor"]) do
follower_address in activity.data["to"] follower_address in activity.data["to"]
@ -41,20 +41,20 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
end end
end end
def is_announceable?(activity, user, public \\ true) do def announceable?(activity, user, public \\ true) do
is_public?(activity) || public?(activity) ||
(!public && is_private?(activity) && activity.data["actor"] == user.ap_id) (!public && private?(activity) && activity.data["actor"] == user.ap_id)
end end
def is_direct?(%Activity{data: %{"directMessage" => true}}), do: true def direct?(%Activity{data: %{"directMessage" => true}}), do: true
def is_direct?(%Object{data: %{"directMessage" => true}}), do: true def direct?(%Object{data: %{"directMessage" => true}}), do: true
def is_direct?(activity) do def direct?(activity) do
!is_public?(activity) && !is_private?(activity) !public?(activity) && !private?(activity)
end end
def is_list?(%{data: %{"listMessage" => _}}), do: true def list?(%{data: %{"listMessage" => _}}), do: true
def is_list?(_), do: false def list?(_), do: false
@spec visible_for_user?(Object.t() | Activity.t() | nil, User.t() | nil) :: boolean() @spec visible_for_user?(Object.t() | Activity.t() | nil, User.t() | nil) :: boolean()
def visible_for_user?(%Object{data: %{"type" => "Tombstone"}}, _), do: false def visible_for_user?(%Object{data: %{"type" => "Tombstone"}}, _), do: false
@ -77,7 +77,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
when module in [Activity, Object] do when module in [Activity, Object] do
if restrict_unauthenticated_access?(message), if restrict_unauthenticated_access?(message),
do: false, do: false,
else: is_public?(message) and not is_local_public?(message) else: public?(message) and not local_public?(message)
end end
def visible_for_user?(%{__struct__: module} = message, user) def visible_for_user?(%{__struct__: module} = message, user)
@ -86,8 +86,8 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
y = [message.data["actor"]] ++ message.data["to"] ++ (message.data["cc"] || []) y = [message.data["actor"]] ++ message.data["to"] ++ (message.data["cc"] || [])
user_is_local = user.local user_is_local = user.local
federatable = not is_local_public?(message) federatable = not local_public?(message)
(is_public?(message) || Enum.any?(x, &(&1 in y))) and (user_is_local || federatable) (public?(message) || Enum.any?(x, &(&1 in y))) and (user_is_local || federatable)
end end
def entire_thread_visible_for_user?(%Activity{} = activity, %User{} = user) do def entire_thread_visible_for_user?(%Activity{} = activity, %User{} = user) do

View File

@ -9,7 +9,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
alias Pleroma.ConfigDB alias Pleroma.ConfigDB
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update) plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update)
plug( plug(
@ -76,7 +76,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
json(conn, translate_descriptions(descriptions)) json(conn, translate_descriptions(descriptions))
end end
def show(conn, %{only_db: true}) do def show(%{private: %{open_api_spex: %{params: %{only_db: true}}}} = conn, _) do
with :ok <- configurable_from_database() do with :ok <- configurable_from_database() do
configs = Pleroma.Repo.all(ConfigDB) configs = Pleroma.Repo.all(ConfigDB)
@ -128,7 +128,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
end end
end end
def update(%{body_params: %{configs: configs}} = conn, _) do def update(%{private: %{open_api_spex: %{body_params: %{configs: configs}}}} = conn, _) do
with :ok <- configurable_from_database() do with :ok <- configurable_from_database() do
results = results =
configs configs

View File

@ -9,7 +9,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
alias Pleroma.Web.Plugs.InstanceStatic alias Pleroma.Web.Plugs.InstanceStatic
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
action_fallback(Pleroma.Web.AdminAPI.FallbackController) action_fallback(Pleroma.Web.AdminAPI.FallbackController)
@ -18,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:update, :delete]) plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:update, :delete])
def show(conn, %{name: document_name}) do def show(%{private: %{open_api_spex: %{params: %{name: document_name}}}} = conn, _) do
with {:ok, url} <- InstanceDocument.get(document_name), with {:ok, url} <- InstanceDocument.get(document_name),
{:ok, content} <- File.read(InstanceStatic.file_path(url)) do {:ok, content} <- File.read(InstanceStatic.file_path(url)) do
conn conn
@ -27,13 +27,18 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
end end
end end
def update(%{body_params: %{file: file}} = conn, %{name: document_name}) do def update(
%{
private: %{open_api_spex: %{body_params: %{file: file}, params: %{name: document_name}}}
} = conn,
_
) do
with {:ok, url} <- InstanceDocument.put(document_name, file.path) do with {:ok, url} <- InstanceDocument.put(document_name, file.path) do
json(conn, %{"url" => url}) json(conn, %{"url" => url})
end end
end end
def delete(conn, %{name: document_name}) do def delete(%{private: %{open_api_spex: %{params: %{name: document_name}}}} = conn, _) do
with :ok <- InstanceDocument.delete(document_name) do with :ok <- InstanceDocument.delete(document_name) do
json(conn, %{}) json(conn, %{})
end end

View File

@ -13,7 +13,7 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
require Logger require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["admin:read:invites"]} when action == :index) plug(OAuthScopesPlug, %{scopes: ["admin:read:invites"]} when action == :index)
plug( plug(
@ -33,14 +33,14 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
end end
@doc "Create an account registration invite token" @doc "Create an account registration invite token"
def create(%{body_params: params} = conn, _) do def create(%{private: %{open_api_spex: %{body_params: params}}} = conn, _) do
{:ok, invite} = UserInviteToken.create_invite(params) {:ok, invite} = UserInviteToken.create_invite(params)
render(conn, "show.json", invite: invite) render(conn, "show.json", invite: invite)
end end
@doc "Revokes invite by token" @doc "Revokes invite by token"
def revoke(%{body_params: %{token: token}} = conn, _) do def revoke(%{private: %{open_api_spex: %{body_params: %{token: token}}}} = conn, _) do
with {:ok, invite} <- UserInviteToken.find_by_token(token), with {:ok, invite} <- UserInviteToken.find_by_token(token),
{:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
render(conn, "show.json", invite: updated_invite) render(conn, "show.json", invite: updated_invite)
@ -51,7 +51,13 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
end end
@doc "Sends registration invite via email" @doc "Sends registration invite via email"
def email(%{assigns: %{user: user}, body_params: %{email: email} = params} = conn, _) do def email(
%{
assigns: %{user: user},
private: %{open_api_spex: %{body_params: %{email: email} = params}}
} = conn,
_
) do
with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])}, with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
{_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])}, {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
{:ok, invite_token} <- UserInviteToken.create_invite(), {:ok, invite_token} <- UserInviteToken.create_invite(),

View File

@ -11,7 +11,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
@cachex Pleroma.Config.get([:cachex, :provider], Cachex) @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
@ -27,7 +27,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
defdelegate open_api_operation(action), to: Spec.MediaProxyCacheOperation defdelegate open_api_operation(action), to: Spec.MediaProxyCacheOperation
def index(%{assigns: %{user: _}} = conn, params) do def index(%{assigns: %{user: _}, private: %{open_api_spex: %{params: params}}} = conn, _) do
entries = fetch_entries(params) entries = fetch_entries(params)
urls = paginate_entries(entries, params.page, params.page_size) urls = paginate_entries(entries, params.page, params.page_size)
@ -59,12 +59,19 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
Enum.slice(entries, offset, page_size) Enum.slice(entries, offset, page_size)
end end
def delete(%{assigns: %{user: _}, body_params: %{urls: urls}} = conn, _) do def delete(
%{assigns: %{user: _}, private: %{open_api_spex: %{body_params: %{urls: urls}}}} = conn,
_
) do
MediaProxy.remove_from_banned_urls(urls) MediaProxy.remove_from_banned_urls(urls)
json(conn, %{}) json(conn, %{})
end end
def purge(%{assigns: %{user: _}, body_params: %{urls: urls, ban: ban}} = conn, _) do def purge(
%{assigns: %{user: _}, private: %{open_api_spex: %{body_params: %{urls: urls, ban: ban}}}} =
conn,
_
) do
MediaProxy.Invalidation.purge(urls) MediaProxy.Invalidation.purge(urls)
if ban do if ban do

View File

@ -11,7 +11,7 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
require Logger require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
@ -31,7 +31,13 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
end end
end end
def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn, _) do def follow(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{relay_url: target}}}
} = conn,
_
) do
with {:ok, _message} <- Relay.follow(target) do with {:ok, _message} <- Relay.follow(target) do
ModerationLog.insert_log(%{action: "relay_follow", actor: admin, target: target}) ModerationLog.insert_log(%{action: "relay_follow", actor: admin, target: target})
@ -44,7 +50,13 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
end end
end end
def unfollow(%{assigns: %{user: admin}, body_params: %{relay_url: target} = params} = conn, _) do def unfollow(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{relay_url: target} = params}}
} = conn,
_
) do
with {:ok, _message} <- Relay.unfollow(target, %{force: params[:force]}) do with {:ok, _message} <- Relay.unfollow(target, %{force: params[:force]}) do
ModerationLog.insert_log(%{action: "relay_unfollow", actor: admin, target: target}) ModerationLog.insert_log(%{action: "relay_unfollow", actor: admin, target: target})

View File

@ -18,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
require Logger require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["admin:read:reports"]} when action in [:index, :show]) plug(OAuthScopesPlug, %{scopes: ["admin:read:reports"]} when action in [:index, :show])
plug( plug(
@ -31,13 +31,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ReportOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ReportOperation
def index(conn, params) do def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
reports = Utils.get_reports(params, params.page, params.page_size) reports = Utils.get_reports(params, params.page, params.page_size)
render(conn, "index.json", reports: reports) render(conn, "index.json", reports: reports)
end end
def show(conn, %{id: id}) do def show(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Activity{} = report <- Activity.get_report(id) do with %Activity{} = report <- Activity.get_report(id) do
render(conn, "show.json", Report.extract_report_info(report)) render(conn, "show.json", Report.extract_report_info(report))
else else
@ -45,7 +45,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end end
end end
def update(%{assigns: %{user: admin}, body_params: %{reports: reports}} = conn, _) do def update(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{reports: reports}}}
} = conn,
_
) do
result = result =
Enum.map(reports, fn report -> Enum.map(reports, fn report ->
case CommonAPI.update_report_state(report.id, report.state) do case CommonAPI.update_report_state(report.id, report.state) do
@ -73,9 +79,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end end
end end
def notes_create(%{assigns: %{user: user}, body_params: %{content: content}} = conn, %{ def notes_create(
id: report_id %{
}) do assigns: %{user: user},
private: %{open_api_spex: %{body_params: %{content: content}, params: %{id: report_id}}}
} = conn,
_
) do
with {:ok, _} <- ReportNote.create(user.id, report_id, content), with {:ok, _} <- ReportNote.create(user.id, report_id, content),
report <- Activity.get_by_id_with_user_actor(report_id) do report <- Activity.get_by_id_with_user_actor(report_id) do
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{
@ -92,10 +102,20 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end end
end end
def notes_delete(%{assigns: %{user: user}} = conn, %{ def notes_delete(
id: note_id, %{
report_id: report_id assigns: %{user: user},
}) do private: %{
open_api_spex: %{
params: %{
id: note_id,
report_id: report_id
}
}
}
} = conn,
_
) do
with {:ok, note} <- ReportNote.destroy(note_id), with {:ok, note} <- ReportNote.destroy(note_id),
report <- Activity.get_by_id_with_user_actor(report_id) do report <- Activity.get_by_id_with_user_actor(report_id) do
ModerationLog.insert_log(%{ ModerationLog.insert_log(%{

View File

@ -18,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
@users_page_size 50 @users_page_size 50
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
@ -51,13 +51,22 @@ defmodule Pleroma.Web.AdminAPI.UserController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation
def delete(conn, %{nickname: nickname}) do def delete(%{private: %{open_api_spex: %{params: %{nickname: nickname}}}} = conn, _) do
conn conn
|> Map.put(:body_params, %{nicknames: [nickname]}) |> do_deletes([nickname])
|> delete(%{})
end end
def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def delete(
%{
private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
} = conn,
_
) do
conn
|> do_deletes(nicknames)
end
defp do_deletes(%{assigns: %{user: admin}} = conn, nicknames) when is_list(nicknames) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1) users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
Enum.each(users, fn user -> Enum.each(users, fn user ->
@ -77,9 +86,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
def follow( def follow(
%{ %{
assigns: %{user: admin}, assigns: %{user: admin},
body_params: %{ private: %{
follower: follower_nick, open_api_spex: %{
followed: followed_nick body_params: %{
follower: follower_nick,
followed: followed_nick
}
}
} }
} = conn, } = conn,
_ _
@ -102,9 +115,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
def unfollow( def unfollow(
%{ %{
assigns: %{user: admin}, assigns: %{user: admin},
body_params: %{ private: %{
follower: follower_nick, open_api_spex: %{
followed: followed_nick body_params: %{
follower: follower_nick,
followed: followed_nick
}
}
} }
} = conn, } = conn,
_ _
@ -124,7 +141,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
json(conn, "ok") json(conn, "ok")
end end
def create(%{assigns: %{user: admin}, body_params: %{users: users}} = conn, _) do def create(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{users: users}}}
} = conn,
_
) do
changesets = changesets =
users users
|> Enum.map(fn %{nickname: nickname, email: email, password: password} -> |> Enum.map(fn %{nickname: nickname, email: email, password: password} ->
@ -178,7 +201,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
end end
end end
def show(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do def show(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{params: %{nickname: nickname}}}
} = conn,
_
) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
render(conn, "show.json", %{user: user}) render(conn, "show.json", %{user: user})
else else
@ -186,7 +215,11 @@ defmodule Pleroma.Web.AdminAPI.UserController do
end end
end end
def toggle_activation(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do def toggle_activation(
%{assigns: %{user: admin}, private: %{open_api_spex: %{params: %{nickname: nickname}}}} =
conn,
_
) do
user = User.get_cached_by_nickname(nickname) user = User.get_cached_by_nickname(nickname)
{:ok, updated_user} = User.set_activation(user, !user.is_active) {:ok, updated_user} = User.set_activation(user, !user.is_active)
@ -202,7 +235,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "show.json", user: updated_user) render(conn, "show.json", user: updated_user)
end end
def activate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def activate(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
} = conn,
_
) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1) users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_activation(users, true) {:ok, updated_users} = User.set_activation(users, true)
@ -212,10 +251,16 @@ defmodule Pleroma.Web.AdminAPI.UserController do
action: "activate" action: "activate"
}) })
render(conn, "index.json", users: Keyword.values(updated_users)) render(conn, "index.json", users: updated_users)
end end
def deactivate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def deactivate(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
} = conn,
_
) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1) users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_activation(users, false) {:ok, updated_users} = User.set_activation(users, false)
@ -225,10 +270,16 @@ defmodule Pleroma.Web.AdminAPI.UserController do
action: "deactivate" action: "deactivate"
}) })
render(conn, "index.json", users: Keyword.values(updated_users)) render(conn, "index.json", users: updated_users)
end end
def approve(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def approve(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
} = conn,
_
) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1) users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.approve(users) {:ok, updated_users} = User.approve(users)
@ -241,7 +292,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users) render(conn, "index.json", users: updated_users)
end end
def suggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def suggest(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
} = conn,
_
) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1) users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_suggestion(users, true) {:ok, updated_users} = User.set_suggestion(users, true)
@ -254,7 +311,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users) render(conn, "index.json", users: updated_users)
end end
def unsuggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def unsuggest(
%{
assigns: %{user: admin},
private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
} = conn,
_
) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1) users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_suggestion(users, false) {:ok, updated_users} = User.set_suggestion(users, false)
@ -267,7 +330,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users) render(conn, "index.json", users: updated_users)
end end
def index(conn, params) do def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
{page, page_size} = page_params(params) {page, page_size} = page_params(params)
filters = maybe_parse_filters(params[:filters]) filters = maybe_parse_filters(params[:filters])

View File

@ -27,10 +27,12 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
@impl Plug @impl Plug
def call(conn, %{operation_id: operation_id, render_error: render_error}) do def call(conn, %{operation_id: operation_id, render_error: render_error} = opts) do
{spec, operation_lookup} = PutApiSpec.get_spec_and_operation_lookup(conn) {spec, operation_lookup} = PutApiSpec.get_spec_and_operation_lookup(conn)
operation = operation_lookup[operation_id] operation = operation_lookup[operation_id]
cast_opts = opts |> Map.take([:replace_params]) |> Map.to_list()
content_type = content_type =
case Conn.get_req_header(conn, "content-type") do case Conn.get_req_header(conn, "content-type") do
[header_value | _] -> [header_value | _] ->
@ -44,7 +46,7 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
conn = Conn.put_private(conn, :operation_id, operation_id) conn = Conn.put_private(conn, :operation_id, operation_id)
case cast_and_validate(spec, operation, conn, content_type, strict?()) do case cast_and_validate(spec, operation, conn, content_type, strict?(), cast_opts) do
{:ok, conn} -> {:ok, conn} ->
conn conn
@ -94,11 +96,11 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
def call(conn, opts), do: OpenApiSpex.Plug.CastAndValidate.call(conn, opts) def call(conn, opts), do: OpenApiSpex.Plug.CastAndValidate.call(conn, opts)
defp cast_and_validate(spec, operation, conn, content_type, true = _strict) do defp cast_and_validate(spec, operation, conn, content_type, true = _strict, cast_opts) do
OpenApiSpex.cast_and_validate(spec, operation, conn, content_type) OpenApiSpex.cast_and_validate(spec, operation, conn, content_type, cast_opts)
end end
defp cast_and_validate(spec, operation, conn, content_type, false = _strict) do defp cast_and_validate(spec, operation, conn, content_type, false = _strict, cast_opts) do
case OpenApiSpex.cast_and_validate(spec, operation, conn, content_type) do case OpenApiSpex.cast_and_validate(spec, operation, conn, content_type) do
{:ok, conn} -> {:ok, conn} ->
{:ok, conn} {:ok, conn}
@ -123,7 +125,7 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
end) end)
conn = %Conn{conn | query_params: query_params} conn = %Conn{conn | query_params: query_params}
OpenApiSpex.cast_and_validate(spec, operation, conn, content_type) OpenApiSpex.cast_and_validate(spec, operation, conn, content_type, cast_opts)
end end
end end

View File

@ -62,7 +62,7 @@ defmodule Pleroma.Web.ApiSpec.Helpers do
Operation.parameter( Operation.parameter(
:with_relationships, :with_relationships,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Embed relationships into accounts. **If this parameter is not set account's `pleroma.relationship` is going to be `null`.**" "Embed relationships into accounts. **If this parameter is not set account's `pleroma.relationship` is going to be `null`.**"
) )
end end

View File

@ -122,22 +122,27 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
parameters: parameters:
[ [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}, %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
Operation.parameter(:pinned, :query, BooleanLike, "Include only pinned statuses"), Operation.parameter(
:pinned,
:query,
BooleanLike.schema(),
"Include only pinned statuses"
),
Operation.parameter(:tagged, :query, :string, "With tag"), Operation.parameter(:tagged, :query, :string, "With tag"),
Operation.parameter( Operation.parameter(
:only_media, :only_media,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Include only statuses with media attached" "Include only statuses with media attached"
), ),
Operation.parameter( Operation.parameter(
:with_muted, :with_muted,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Include statuses from muted accounts." "Include statuses from muted accounts."
), ),
Operation.parameter(:exclude_reblogs, :query, BooleanLike, "Exclude reblogs"), Operation.parameter(:exclude_reblogs, :query, BooleanLike.schema(), "Exclude reblogs"),
Operation.parameter(:exclude_replies, :query, BooleanLike, "Exclude replies"), Operation.parameter(:exclude_replies, :query, BooleanLike.schema(), "Exclude replies"),
Operation.parameter( Operation.parameter(
:exclude_visibilities, :exclude_visibilities,
:query, :query,
@ -147,7 +152,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
Operation.parameter( Operation.parameter(
:with_muted, :with_muted,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Include reactions from muted accounts." "Include reactions from muted accounts."
) )
] ++ pagination_params(), ] ++ pagination_params(),

View File

@ -141,7 +141,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
end end
def id_param do def id_param do
Operation.parameter(:id, :path, FlakeID, "Report ID", Operation.parameter(:id, :path, FlakeID.schema(), "Report ID",
example: "9umDrYheeY451cQnEe", example: "9umDrYheeY451cQnEe",
required: true required: true
) )

View File

@ -137,7 +137,12 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"Deprecated due to no support for pagination. Using [/api/v2/pleroma/chats](#operation/ChatController.index2) instead is recommended.", "Deprecated due to no support for pagination. Using [/api/v2/pleroma/chats](#operation/ChatController.index2) instead is recommended.",
operationId: "ChatController.index", operationId: "ChatController.index",
parameters: [ parameters: [
Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users") Operation.parameter(
:with_muted,
:query,
BooleanLike.schema(),
"Include chats from muted users"
)
], ],
responses: %{ responses: %{
200 => Operation.response("The chats of the user", "application/json", chats_response()) 200 => Operation.response("The chats of the user", "application/json", chats_response())
@ -156,7 +161,12 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
summary: "Retrieve list of chats", summary: "Retrieve list of chats",
operationId: "ChatController.index2", operationId: "ChatController.index2",
parameters: [ parameters: [
Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users") Operation.parameter(
:with_muted,
:query,
BooleanLike.schema(),
"Include chats from muted users"
)
| pagination_params() | pagination_params()
], ],
responses: %{ responses: %{

View File

@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.DirectoryOperation do
"Order by recent activity or account creation", "Order by recent activity or account creation",
required: nil required: nil
), ),
Operation.parameter(:local, :query, BooleanLike, "Include local users only") Operation.parameter(:local, :query, BooleanLike.schema(), "Include local users only")
] ++ pagination_params(), ] ++ pagination_params(),
responses: %{ responses: %{
200 => 200 =>

View File

@ -21,7 +21,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
summary: summary:
"Get an object of emoji to account mappings with accounts that reacted to the post", "Get an object of emoji to account mappings with accounts that reacted to the post",
parameters: [ parameters: [
Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), Operation.parameter(:id, :path, FlakeID.schema(), "Status ID", required: true),
Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji", Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji",
required: nil required: nil
), ),
@ -45,7 +45,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
tags: ["Emoji reactions"], tags: ["Emoji reactions"],
summary: "React to a post with a unicode emoji", summary: "React to a post with a unicode emoji",
parameters: [ parameters: [
Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), Operation.parameter(:id, :path, FlakeID.schema(), "Status ID", required: true),
Operation.parameter(:emoji, :path, :string, "A single character unicode emoji", Operation.parameter(:emoji, :path, :string, "A single character unicode emoji",
required: true required: true
) )
@ -64,7 +64,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
tags: ["Emoji reactions"], tags: ["Emoji reactions"],
summary: "Remove a reaction to a post with a unicode emoji", summary: "Remove a reaction to a post with a unicode emoji",
parameters: [ parameters: [
Operation.parameter(:id, :path, FlakeID, "Status ID", required: true), Operation.parameter(:id, :path, FlakeID.schema(), "Status ID", required: true),
Operation.parameter(:emoji, :path, :string, "A single character unicode emoji", Operation.parameter(:emoji, :path, :string, "A single character unicode emoji",
required: true required: true
) )

View File

@ -62,7 +62,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
Operation.parameter( Operation.parameter(
:with_muted, :with_muted,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Include the notifications from muted users" "Include the notifications from muted users"
) )
] ++ pagination_params(), ] ++ pagination_params(),

View File

@ -142,7 +142,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
end end
defp id_param do defp id_param do
Operation.parameter(:id, :path, FlakeID, "Account ID", Operation.parameter(:id, :path, FlakeID.schema(), "Account ID",
example: "9umDrYheeY451cQnEe", example: "9umDrYheeY451cQnEe",
required: true required: true
) )

View File

@ -37,7 +37,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaStatusOperation do
end end
def id_param do def id_param do
Operation.parameter(:id, :path, FlakeID, "Status ID", Operation.parameter(:id, :path, FlakeID.schema(), "Status ID",
example: "9umDrYheeY451cQnEe", example: "9umDrYheeY451cQnEe",
required: true required: true
) )

View File

@ -47,7 +47,7 @@ defmodule Pleroma.Web.ApiSpec.PollOperation do
end end
defp id_param do defp id_param do
Operation.parameter(:id, :path, FlakeID, "Poll ID", Operation.parameter(:id, :path, FlakeID.schema(), "Poll ID",
example: "123", example: "123",
required: true required: true
) )

View File

@ -88,7 +88,7 @@ defmodule Pleroma.Web.ApiSpec.ScheduledActivityOperation do
end end
defp id_param do defp id_param do
Operation.parameter(:id, :path, FlakeID, "Poll ID", Operation.parameter(:id, :path, FlakeID.schema(), "Poll ID",
example: "123", example: "123",
required: true required: true
) )

View File

@ -70,7 +70,7 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do
Operation.parameter( Operation.parameter(
:account_id, :account_id,
:query, :query,
FlakeID, FlakeID.schema(),
"If provided, statuses returned will be authored only by this account" "If provided, statuses returned will be authored only by this account"
), ),
Operation.parameter( Operation.parameter(
@ -116,7 +116,7 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do
Operation.parameter( Operation.parameter(
:account_id, :account_id,
:query, :query,
FlakeID, FlakeID.schema(),
"If provided, statuses returned will be authored only by this account" "If provided, statuses returned will be authored only by this account"
), ),
Operation.parameter( Operation.parameter(

View File

@ -39,7 +39,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
Operation.parameter( Operation.parameter(
:with_muted, :with_muted,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Include reactions from muted acccounts." "Include reactions from muted acccounts."
) )
], ],
@ -82,7 +82,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
Operation.parameter( Operation.parameter(
:with_muted, :with_muted,
:query, :query,
BooleanLike, BooleanLike.schema(),
"Include reactions from muted acccounts." "Include reactions from muted acccounts."
) )
], ],
@ -685,7 +685,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
end end
def id_param do def id_param do
Operation.parameter(:id, :path, FlakeID, "Status ID", Operation.parameter(:id, :path, FlakeID.schema(), "Status ID",
example: "9umDrYheeY451cQnEe", example: "9umDrYheeY451cQnEe",
required: true required: true
) )

View File

@ -176,7 +176,12 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
end end
defp with_muted_param do defp with_muted_param do
Operation.parameter(:with_muted, :query, BooleanLike, "Include activities by muted users") Operation.parameter(
:with_muted,
:query,
BooleanLike.schema(),
"Include activities by muted users"
)
end end
defp exclude_visibilities_param do defp exclude_visibilities_param do

View File

@ -146,13 +146,13 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
Operation.parameter( Operation.parameter(
:block_from_strangers, :block_from_strangers,
:query, :query,
BooleanLike, BooleanLike.schema(),
"blocks notifications from accounts you do not follow" "blocks notifications from accounts you do not follow"
), ),
Operation.parameter( Operation.parameter(
:hide_notification_contents, :hide_notification_contents,
:query, :query,
BooleanLike, BooleanLike.schema(),
"removes the contents of a message from the push notification" "removes the contents of a message from the push notification"
) )
], ],

View File

@ -372,7 +372,7 @@ defmodule Pleroma.Web.CommonAPI do
do: visibility in ~w(public unlisted) do: visibility in ~w(public unlisted)
def public_announce?(object, _) do def public_announce?(object, _) do
Visibility.is_public?(object) Visibility.public?(object)
end end
def get_visibility(_, _, %Participation{}), do: {"direct", "direct"} def get_visibility(_, _, %Participation{}), do: {"direct", "direct"}
@ -500,7 +500,7 @@ defmodule Pleroma.Web.CommonAPI do
end end
defp activity_is_public(activity) do defp activity_is_public(activity) do
with false <- Visibility.is_public?(activity) do with false <- Visibility.public?(activity) do
{:error, :visibility_error} {:error, :visibility_error}
end end
end end

View File

@ -109,7 +109,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
def get_to_and_cc(%{visibility: "direct"} = draft) do def get_to_and_cc(%{visibility: "direct"} = draft) do
# If the OP is a DM already, add the implicit actor. # If the OP is a DM already, add the implicit actor.
if draft.in_reply_to && Visibility.is_direct?(draft.in_reply_to) do if draft.in_reply_to && Visibility.direct?(draft.in_reply_to) do
{Enum.uniq([draft.in_reply_to.data["actor"] | draft.mentions]), []} {Enum.uniq([draft.in_reply_to.data["actor"] | draft.mentions]), []}
else else
{draft.mentions, []} {draft.mentions, []}

View File

@ -20,7 +20,7 @@ defmodule Pleroma.Web.ControllerHelper do
|> json(json) |> json(json)
end end
@spec fetch_integer_param(map(), String.t(), integer() | nil) :: integer() | nil @spec fetch_integer_param(map(), String.t() | atom(), integer() | nil) :: integer() | nil
def fetch_integer_param(params, name, default \\ nil) do def fetch_integer_param(params, name, default \\ nil) do
params params
|> Map.get(name, default) |> Map.get(name, default)
@ -53,10 +53,15 @@ defmodule Pleroma.Web.ControllerHelper do
end end
end end
# TODO: Only fetch the params from open_api_spex when everything is converted
@id_keys Pagination.page_keys() -- ["limit", "order"] @id_keys Pagination.page_keys() -- ["limit", "order"]
defp build_pagination_fields(conn, min_id, max_id, extra_params) do defp build_pagination_fields(conn, min_id, max_id, extra_params) do
params = params =
conn.params if Map.has_key?(conn.private, :open_api_spex) do
get_in(conn, [Access.key(:private), Access.key(:open_api_spex), Access.key(:params)])
else
conn.params
end
|> Map.drop(Map.keys(conn.path_params) |> Enum.map(&String.to_existing_atom/1)) |> Map.drop(Map.keys(conn.path_params) |> Enum.map(&String.to_existing_atom/1))
|> Map.merge(extra_params) |> Map.merge(extra_params)
|> Map.drop(@id_keys) |> Map.drop(@id_keys)
@ -85,18 +90,15 @@ defmodule Pleroma.Web.ControllerHelper do
end end
end end
def assign_account_by_id(conn, _) do def assign_account_by_id(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
case Pleroma.User.get_cached_by_id(conn.params.id) do case Pleroma.User.get_cached_by_id(id) do
%Pleroma.User{} = account -> assign(conn, :account, account) %Pleroma.User{} = account -> assign(conn, :account, account)
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt() nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()
end end
end end
def try_render(conn, target, params) when is_binary(target) do def try_render(conn, target, params) when is_binary(target) do
case render(conn, target, params) do render(conn, target, params)
nil -> render_error(conn, :not_implemented, "Can't display this activity")
res -> res
end
end end
def try_render(conn, _, _) do def try_render(conn, _, _) do

View File

@ -11,12 +11,10 @@ defmodule Pleroma.Web.EmbedController do
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
plug(:put_layout, :embed)
def show(conn, %{"id" => id}) do def show(conn, %{"id" => id}) do
with %Activity{local: true} = activity <- with %Activity{local: true} = activity <-
Activity.get_by_id_with_object(id), Activity.get_by_id_with_object(id),
true <- Visibility.is_public?(activity.object) do true <- Visibility.public?(activity.object) do
{:ok, author} = User.get_or_fetch(activity.object.data["actor"]) {:ok, author} = User.get_or_fetch(activity.object.data["actor"])
conn conn

View File

@ -85,12 +85,12 @@ defmodule Pleroma.Web.Gettext do
Process.get({Pleroma.Web.Gettext, :locales}, []) Process.get({Pleroma.Web.Gettext, :locales}, [])
end end
def is_locale_list(locales) do def locale_list?(locales) do
Enum.all?(locales, &is_binary/1) Enum.all?(locales, &is_binary/1)
end end
def put_locales(locales) do def put_locales(locales) do
if is_locale_list(locales) do if locale_list?(locales) do
Process.put({Pleroma.Web.Gettext, :locales}, Enum.uniq(locales)) Process.put({Pleroma.Web.Gettext, :locales}, Enum.uniq(locales))
Gettext.put_locale(Enum.at(locales, 0, Gettext.get_locale())) Gettext.put_locale(Enum.at(locales, 0, Gettext.get_locale()))
:ok :ok

View File

@ -30,7 +30,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
alias Pleroma.Web.TwitterAPI.TwitterAPI alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.Utils.Params alias Pleroma.Web.Utils.Params
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:skip_auth when action in [:create, :lookup]) plug(:skip_auth when action in [:create, :lookup])
@ -92,7 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug( plug(
RateLimiter, RateLimiter,
[name: :relation_id_action, params: [:id, :uri]] when action in @relationship_actions [name: :relation_id_action, params: ["id", "uri"]] when action in @relationship_actions
) )
plug(RateLimiter, [name: :relations_actions] when action in @relationship_actions) plug(RateLimiter, [name: :relations_actions] when action in @relationship_actions)
@ -104,7 +104,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AccountOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AccountOperation
@doc "POST /api/v1/accounts" @doc "POST /api/v1/accounts"
def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do def create(
%{assigns: %{app: app}, private: %{open_api_spex: %{body_params: params}}} = conn,
_params
) do
with :ok <- validate_email_param(params), with :ok <- validate_email_param(params),
:ok <- TwitterAPI.validate_captcha(app, params), :ok <- TwitterAPI.validate_captcha(app, params),
{:ok, user} <- TwitterAPI.register_user(params), {:ok, user} <- TwitterAPI.register_user(params),
@ -168,7 +171,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "PATCH /api/v1/accounts/update_credentials" @doc "PATCH /api/v1/accounts/update_credentials"
def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _params) do def update_credentials(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: params}}} = conn,
_params
) do
params = params =
params params
|> Enum.filter(fn {_, value} -> not is_nil(value) end) |> Enum.filter(fn {_, value} -> not is_nil(value) end)
@ -289,7 +295,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "GET /api/v1/accounts/relationships" @doc "GET /api/v1/accounts/relationships"
def relationships(%{assigns: %{user: user}} = conn, %{id: id}) do def relationships(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
targets = User.get_all_by_ids(List.wrap(id)) targets = User.get_all_by_ids(List.wrap(id))
render(conn, "relationships.json", user: user, targets: targets) render(conn, "relationships.json", user: user, targets: targets)
@ -299,7 +308,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, []) def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
@doc "GET /api/v1/accounts/:id" @doc "GET /api/v1/accounts/:id"
def show(%{assigns: %{user: for_user}} = conn, %{id: nickname_or_id} = params) do def show(
%{
assigns: %{user: for_user},
private: %{open_api_spex: %{params: %{id: nickname_or_id} = params}}
} = conn,
_params
) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user), with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
:visible <- User.visible_for(user, for_user) do :visible <- User.visible_for(user, for_user) do
render(conn, "show.json", render(conn, "show.json",
@ -313,7 +328,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "GET /api/v1/accounts/:id/statuses" @doc "GET /api/v1/accounts/:id/statuses"
def statuses(%{assigns: %{user: reading_user}} = conn, params) do def statuses(
%{assigns: %{user: reading_user}, private: %{open_api_spex: %{params: params}}} = conn,
_params
) do
with %User{} = user <- User.get_cached_by_nickname_or_id(params.id, for: reading_user), with %User{} = user <- User.get_cached_by_nickname_or_id(params.id, for: reading_user),
:visible <- User.visible_for(user, reading_user) do :visible <- User.visible_for(user, reading_user) do
params = params =
@ -348,7 +366,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "GET /api/v1/accounts/:id/followers" @doc "GET /api/v1/accounts/:id/followers"
def followers(%{assigns: %{user: for_user, account: user}} = conn, params) do def followers(
%{assigns: %{user: for_user, account: user}, private: %{open_api_spex: %{params: params}}} =
conn,
_params
) do
params = params =
params params
|> Enum.map(fn {key, value} -> {to_string(key), value} end) |> Enum.map(fn {key, value} -> {to_string(key), value} end)
@ -373,7 +395,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "GET /api/v1/accounts/:id/following" @doc "GET /api/v1/accounts/:id/following"
def following(%{assigns: %{user: for_user, account: user}} = conn, params) do def following(
%{assigns: %{user: for_user, account: user}, private: %{open_api_spex: %{params: params}}} =
conn,
_params
) do
params = params =
params params
|> Enum.map(fn {key, value} -> {to_string(key), value} end) |> Enum.map(fn {key, value} -> {to_string(key), value} end)
@ -411,7 +437,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
{:error, "Can not follow yourself"} {:error, "Can not follow yourself"}
end end
def follow(%{body_params: params, assigns: %{user: follower, account: followed}} = conn, _) do def follow(
%{
assigns: %{user: follower, account: followed},
private: %{open_api_spex: %{body_params: params}}
} = conn,
_
) do
with {:ok, follower} <- MastodonAPI.follow(follower, followed, params) do with {:ok, follower} <- MastodonAPI.follow(follower, followed, params) do
render(conn, "relationship.json", user: follower, target: followed) render(conn, "relationship.json", user: follower, target: followed)
else else
@ -431,7 +463,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "POST /api/v1/accounts/:id/mute" @doc "POST /api/v1/accounts/:id/mute"
def mute(%{assigns: %{user: muter, account: muted}, body_params: params} = conn, _params) do def mute(
%{
assigns: %{user: muter, account: muted},
private: %{open_api_spex: %{body_params: params}}
} = conn,
_params
) do
params = params =
params params
|> Map.put_new(:duration, Map.get(params, :expires_in, 0)) |> Map.put_new(:duration, Map.get(params, :expires_in, 0))
@ -472,7 +510,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
@doc "POST /api/v1/accounts/:id/note" @doc "POST /api/v1/accounts/:id/note"
def note( def note(
%{assigns: %{user: noter, account: target}, body_params: %{comment: comment}} = conn, %{
assigns: %{user: noter, account: target},
private: %{open_api_spex: %{body_params: %{comment: comment}}}
} = conn,
_params _params
) do ) do
with {:ok, _user_note} <- UserNote.create(noter, target, comment) do with {:ok, _user_note} <- UserNote.create(noter, target, comment) do
@ -513,7 +554,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "POST /api/v1/follows" @doc "POST /api/v1/follows"
def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do def follow_by_uri(%{private: %{open_api_spex: %{body_params: %{uri: uri}}}} = conn, _) do
case User.get_cached_by_nickname(uri) do case User.get_cached_by_nickname(uri) do
%User{} = user -> %User{} = user ->
conn conn
@ -561,7 +602,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end end
@doc "GET /api/v1/accounts/lookup" @doc "GET /api/v1/accounts/lookup"
def lookup(conn, %{acct: nickname} = _params) do def lookup(%{private: %{open_api_spex: %{params: %{acct: nickname}}}} = conn, _params) do
with %User{} = user <- User.get_by_nickname(nickname) do with %User{} = user <- User.get_by_nickname(nickname) do
render(conn, "show.json", render(conn, "show.json",
user: user, user: user,

View File

@ -15,7 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.DirectoryController do
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:skip_auth when action == "index") plug(:skip_auth when action == :index)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DirectoryOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DirectoryOperation

View File

@ -8,7 +8,7 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DomainBlockOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DomainBlockOperation
plug( plug(
@ -27,23 +27,31 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
end end
@doc "POST /api/v1/domain_blocks" @doc "POST /api/v1/domain_blocks"
def create(%{assigns: %{user: blocker}, body_params: %{domain: domain}} = conn, _params) do def create(
%{assigns: %{user: blocker}, private: %{open_api_spex: %{body_params: %{domain: domain}}}} =
conn,
_params
) do
User.block_domain(blocker, domain) User.block_domain(blocker, domain)
json(conn, %{}) json(conn, %{})
end end
def create(%{assigns: %{user: blocker}} = conn, %{domain: domain}) do def create(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
User.block_domain(blocker, domain) User.block_domain(blocker, domain)
json(conn, %{}) json(conn, %{})
end end
@doc "DELETE /api/v1/domain_blocks" @doc "DELETE /api/v1/domain_blocks"
def delete(%{assigns: %{user: blocker}, body_params: %{domain: domain}} = conn, _params) do def delete(
%{assigns: %{user: blocker}, private: %{open_api_spex: %{body_params: %{domain: domain}}}} =
conn,
_params
) do
User.unblock_domain(blocker, domain) User.unblock_domain(blocker, domain)
json(conn, %{}) json(conn, %{})
end end
def delete(%{assigns: %{user: blocker}} = conn, %{domain: domain}) do def delete(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
User.unblock_domain(blocker, domain) User.unblock_domain(blocker, domain)
json(conn, %{}) json(conn, %{})
end end

View File

@ -9,7 +9,7 @@ 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(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:assign_follower when action != :index) plug(:assign_follower when action != :index)
action_fallback(:errors) action_fallback(:errors)
@ -44,7 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
end end
end end
defp assign_follower(%{params: %{id: id}} = conn, _) do defp assign_follower(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
case User.get_cached_by_id(id) do case User.get_cached_by_id(id) do
%User{} = follower -> assign(conn, :follower, follower) %User{} = follower -> assign(conn, :follower, follower)
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt() nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()

View File

@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
@oauth_read_actions [:index, :show, :list_accounts] @oauth_read_actions [:index, :show, :list_accounts]
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:list_by_id_and_user when action not in [:index, :create]) plug(:list_by_id_and_user when action not in [:index, :create])
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in @oauth_read_actions) plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in @oauth_read_actions)
plug(OAuthScopesPlug, %{scopes: ["write:lists"]} when action not in @oauth_read_actions) plug(OAuthScopesPlug, %{scopes: ["write:lists"]} when action not in @oauth_read_actions)
@ -21,25 +21,33 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ListOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ListOperation
# GET /api/v1/lists # GET /api/v1/lists
def index(%{assigns: %{user: user}} = conn, opts) do def index(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
lists = Pleroma.List.for_user(user, opts) lists = Pleroma.List.for_user(user, params)
render(conn, "index.json", lists: lists) render(conn, "index.json", lists: lists)
end end
# POST /api/v1/lists # POST /api/v1/lists
def create(%{assigns: %{user: user}, body_params: %{title: title}} = conn, _) do def create(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{title: title}}}} =
conn,
_
) do
with {:ok, %Pleroma.List{} = list} <- Pleroma.List.create(title, user) do with {:ok, %Pleroma.List{} = list} <- Pleroma.List.create(title, user) do
render(conn, "show.json", list: list) render(conn, "show.json", list: list)
end end
end end
# GET /api/v1/lists/:id # GET /api/v1/lists/:idOB
def show(%{assigns: %{list: list}} = conn, _) do def show(%{assigns: %{list: list}} = conn, _) do
render(conn, "show.json", list: list) render(conn, "show.json", list: list)
end end
# PUT /api/v1/lists/:id # PUT /api/v1/lists/:id
def update(%{assigns: %{list: list}, body_params: %{title: title}} = conn, _) do def update(
%{assigns: %{list: list}, private: %{open_api_spex: %{body_params: %{title: title}}}} =
conn,
_
) do
with {:ok, list} <- Pleroma.List.rename(list, title) do with {:ok, list} <- Pleroma.List.rename(list, title) do
render(conn, "show.json", list: list) render(conn, "show.json", list: list)
end end
@ -62,7 +70,13 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
end end
# POST /api/v1/lists/:id/accounts # POST /api/v1/lists/:id/accounts
def add_to_list(%{assigns: %{list: list}, body_params: %{account_ids: account_ids}} = conn, _) do def add_to_list(
%{
assigns: %{list: list},
private: %{open_api_spex: %{body_params: %{account_ids: account_ids}}}
} = conn,
_
) do
Enum.each(account_ids, fn account_id -> Enum.each(account_ids, fn account_id ->
with %User{} = followed <- User.get_cached_by_id(account_id) do with %User{} = followed <- User.get_cached_by_id(account_id) do
Pleroma.List.follow(list, followed) Pleroma.List.follow(list, followed)
@ -74,9 +88,22 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
# DELETE /api/v1/lists/:id/accounts # DELETE /api/v1/lists/:id/accounts
def remove_from_list( def remove_from_list(
%{assigns: %{list: list}, params: %{account_ids: account_ids}} = conn, %{
private: %{open_api_spex: %{params: %{account_ids: account_ids}}}
} = conn,
_ _
) do ) do
do_remove_from_list(conn, account_ids)
end
def remove_from_list(
%{private: %{open_api_spex: %{body_params: %{account_ids: account_ids}}}} = conn,
_
) do
do_remove_from_list(conn, account_ids)
end
defp do_remove_from_list(%{assigns: %{list: list}} = conn, account_ids) do
Enum.each(account_ids, fn account_id -> Enum.each(account_ids, fn account_id ->
with %User{} = followed <- User.get_cached_by_id(account_id) do with %User{} = followed <- User.get_cached_by_id(account_id) do
Pleroma.List.unfollow(list, followed) Pleroma.List.unfollow(list, followed)
@ -86,11 +113,10 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
json(conn, %{}) json(conn, %{})
end end
def remove_from_list(%{body_params: params} = conn, _) do defp list_by_id_and_user(
remove_from_list(%{conn | params: params}, %{}) %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
end _
) do
defp list_by_id_and_user(%{assigns: %{user: user}, params: %{id: id}} = conn, _) do
case Pleroma.List.get(id, user) do case Pleroma.List.get(id, user) do
%Pleroma.List{} = list -> assign(conn, :list, list) %Pleroma.List{} = list -> assign(conn, :list, list)
nil -> conn |> render_error(:not_found, "List not found") |> halt() nil -> conn |> render_error(:not_found, "List not found") |> halt()

View File

@ -12,7 +12,7 @@ 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, replace_params: false)
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)
@ -20,7 +20,11 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation
@doc "POST /api/v1/media" @doc "POST /api/v1/media"
def create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do def create(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{file: file} = data}}} =
conn,
_
) do
with {:ok, object} <- with {:ok, object} <-
ActivityPub.upload( ActivityPub.upload(
file, file,
@ -36,7 +40,11 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
def create(_conn, _data), do: {:error, :bad_request} def create(_conn, _data), do: {:error, :bad_request}
@doc "POST /api/v2/media" @doc "POST /api/v2/media"
def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do def create2(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{file: file} = data}}} =
conn,
_
) do
with {:ok, object} <- with {:ok, object} <-
ActivityPub.upload( ActivityPub.upload(
file, file,
@ -54,7 +62,15 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
def create2(_conn, _data), do: {:error, :bad_request} def create2(_conn, _data), do: {:error, :bad_request}
@doc "PUT /api/v1/media/:id" @doc "PUT /api/v1/media/:id"
def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do def update(
%{
assigns: %{user: user},
private: %{
open_api_spex: %{body_params: %{description: description}, params: %{id: id}}
}
} = conn,
_
) do
with %Object{} = object <- Object.get_by_id(id), with %Object{} = object <- Object.get_by_id(id),
:ok <- Object.authorize_access(object, user), :ok <- Object.authorize_access(object, user),
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do {:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
@ -67,7 +83,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
def update(conn, data), do: show(conn, data) def update(conn, data), do: show(conn, data)
@doc "GET /api/v1/media/:id" @doc "GET /api/v1/media/:id"
def show(%{assigns: %{user: user}} = conn, %{id: id}) do def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Object{data: data, id: object_id} = object <- Object.get_by_id(id), with %Object{data: data, id: object_id} = object <- Object.get_by_id(id),
:ok <- Object.authorize_access(object, user) do :ok <- Object.authorize_access(object, user) do
attachment_data = Map.put(data, "id", object_id) attachment_data = Map.put(data, "id", object_id)

View File

@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
@oauth_read_actions [:show, :index] @oauth_read_actions [:show, :index]
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
@ -24,8 +24,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.NotificationOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.NotificationOperation
@default_notification_types ~w{
mention
follow
follow_request
reblog
favourite
move
pleroma:emoji_reaction
poll
update
}
# GET /api/v1/notifications # GET /api/v1/notifications
def index(conn, %{account_id: account_id} = params) do def index(%{private: %{open_api_spex: %{params: %{account_id: account_id} = params}}} = conn, _) do
case Pleroma.User.get_cached_by_id(account_id) do case Pleroma.User.get_cached_by_id(account_id) do
%{ap_id: account_ap_id} -> %{ap_id: account_ap_id} ->
params = params =
@ -33,7 +45,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|> Map.delete(:account_id) |> Map.delete(:account_id)
|> Map.put(:account_ap_id, account_ap_id) |> Map.put(:account_ap_id, account_ap_id)
index(conn, params) do_get_notifications(conn, params)
_ -> _ ->
conn conn
@ -42,18 +54,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
end end
end end
@default_notification_types ~w{ def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
mention do_get_notifications(conn, params)
follow end
follow_request
reblog defp do_get_notifications(%{assigns: %{user: user}} = conn, params) do
favourite
move
pleroma:emoji_reaction
poll
update
}
def index(%{assigns: %{user: user}} = conn, params) do
params = params =
Map.new(params, fn {k, v} -> {to_string(k), v} end) Map.new(params, fn {k, v} -> {to_string(k), v} end)
|> Map.put_new("types", Map.get(params, :include_types, @default_notification_types)) |> Map.put_new("types", Map.get(params, :include_types, @default_notification_types))
@ -69,7 +74,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
end end
# GET /api/v1/notifications/:id # GET /api/v1/notifications/:id
def show(%{assigns: %{user: user}} = conn, %{id: id}) do def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with {:ok, notification} <- Notification.get(user, id) do with {:ok, notification} <- Notification.get(user, id) do
render(conn, "show.json", notification: notification, for: user) render(conn, "show.json", notification: notification, for: user)
else else
@ -88,8 +93,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
# POST /api/v1/notifications/:id/dismiss # POST /api/v1/notifications/:id/dismiss
def dismiss(%{assigns: %{user: user}} = conn, %{id: id} = _params) do def dismiss(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with {:ok, _notif} <- Notification.dismiss(user, id) do do_dismiss(conn, id)
end
# POST /api/v1/notifications/dismiss (deprecated)
def dismiss_via_body(
%{private: %{open_api_spex: %{body_params: %{id: id}}}} = conn,
_
) do
do_dismiss(conn, id)
end
defp do_dismiss(%{assigns: %{user: user}} = conn, notification_id) do
with {:ok, _notif} <- Notification.dismiss(user, notification_id) do
json(conn, %{}) json(conn, %{})
else else
{:error, reason} -> {:error, reason} ->
@ -99,13 +116,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
end end
end end
# POST /api/v1/notifications/dismiss (deprecated)
def dismiss_via_body(%{body_params: params} = conn, _) do
dismiss(conn, params)
end
# DELETE /api/v1/notifications/destroy_multiple # DELETE /api/v1/notifications/destroy_multiple
def destroy_multiple(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do def destroy_multiple(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{ids: ids}}}} = conn,
_
) do
Notification.destroy_multiple(user, ids) Notification.destroy_multiple(user, ids)
json(conn, %{}) json(conn, %{})
end end

View File

@ -15,7 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController) action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
@ -29,7 +29,7 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
@cachex Pleroma.Config.get([:cachex, :provider], Cachex) @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@doc "GET /api/v1/polls/:id" @doc "GET /api/v1/polls/:id"
def show(%{assigns: %{user: user}} = conn, %{id: id}) do def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60), with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]), %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
true <- Visibility.visible_for_user?(activity, user) do true <- Visibility.visible_for_user?(activity, user) do
@ -41,7 +41,13 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
end end
@doc "POST /api/v1/polls/:id/votes" @doc "POST /api/v1/polls/:id/votes"
def vote(%{assigns: %{user: user}, body_params: %{choices: choices}} = conn, %{id: id}) do def vote(
%{
assigns: %{user: user},
private: %{open_api_spex: %{body_params: %{choices: choices}, params: %{id: id}}}
} = conn,
_
) do
with %Object{data: %{"type" => "Question"}} = object <- Object.get_by_id(id), with %Object{data: %{"type" => "Question"}} = object <- Object.get_by_id(id),
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]), %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
true <- Visibility.visible_for_user?(activity, user), true <- Visibility.visible_for_user?(activity, user),

View File

@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
@oauth_read_actions [:show, :index] @oauth_read_actions [:show, :index]
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in @oauth_read_actions) plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in @oauth_read_actions)
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action not in @oauth_read_actions) plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action not in @oauth_read_actions)
plug(:assign_scheduled_activity when action != :index) plug(:assign_scheduled_activity when action != :index)
@ -23,7 +23,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ScheduledActivityOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ScheduledActivityOperation
@doc "GET /api/v1/scheduled_statuses" @doc "GET /api/v1/scheduled_statuses"
def index(%{assigns: %{user: user}} = conn, params) do def index(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
params = Map.new(params, fn {key, value} -> {to_string(key), value} end) params = Map.new(params, fn {key, value} -> {to_string(key), value} end)
with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do
@ -39,7 +39,13 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
end end
@doc "PUT /api/v1/scheduled_statuses/:id" @doc "PUT /api/v1/scheduled_statuses/:id"
def update(%{assigns: %{scheduled_activity: scheduled_activity}, body_params: params} = conn, _) do def update(
%{
assigns: %{scheduled_activity: scheduled_activity},
private: %{open_api_spex: %{body_params: params}}
} = conn,
_
) do
with {:ok, scheduled_activity} <- ScheduledActivity.update(scheduled_activity, params) do with {:ok, scheduled_activity} <- ScheduledActivity.update(scheduled_activity, params) do
render(conn, "show.json", scheduled_activity: scheduled_activity) render(conn, "show.json", scheduled_activity: scheduled_activity)
end end
@ -52,7 +58,10 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
end end
end end
defp assign_scheduled_activity(%{assigns: %{user: user}, params: %{id: id}} = conn, _) do defp assign_scheduled_activity(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
case ScheduledActivity.get(user, id) do case ScheduledActivity.get(user, id) do
%ScheduledActivity{} = activity -> assign(conn, :scheduled_activity, activity) %ScheduledActivity{} = activity -> assign(conn, :scheduled_activity, activity)
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt() nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()

View File

@ -18,7 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
@search_limit 40 @search_limit 40
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search) # Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated}) plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated})
@ -29,7 +29,11 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.SearchOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.SearchOperation
def account_search(%{assigns: %{user: user}} = conn, %{q: query} = params) do def account_search(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{q: query} = params}}} =
conn,
_
) do
accounts = User.search(query, search_options(params, user)) accounts = User.search(query, search_options(params, user))
conn conn
@ -44,7 +48,12 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
def search2(conn, params), do: do_search(:v2, conn, params) def search2(conn, params), do: do_search(:v2, conn, params)
def search(conn, params), do: do_search(:v1, conn, params) def search(conn, params), do: do_search(:v1, conn, params)
defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do defp do_search(
version,
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{q: query} = params}}} =
conn,
_
) do
query = String.trim(query) query = String.trim(query)
options = search_options(params, user) options = search_options(params, user)
timeout = Keyword.get(Repo.config(), :timeout, 15_000) timeout = Keyword.get(Repo.config(), :timeout, 15_000)
@ -147,7 +156,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
tags tags
end end
Pleroma.Pagination.paginate(tags, options) Pleroma.Pagination.paginate_list(tags, options)
end end
defp add_joined_tag(tags) do defp add_joined_tag(tags) do

View File

@ -25,7 +25,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.RateLimiter alias Pleroma.Web.Plugs.RateLimiter
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:skip_public_check when action in [:index, :show]) plug(:skip_public_check when action in [:index, :show])
@ -110,7 +110,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
`ids` query param is required `ids` query param is required
""" """
def index(%{assigns: %{user: user}} = conn, %{ids: ids} = params) do def index(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{ids: ids} = params}}} =
conn,
_
) do
limit = 100 limit = 100
activities = activities =
@ -134,7 +138,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
def create( def create(
%{ %{
assigns: %{user: user}, assigns: %{user: user},
body_params: %{status: _, scheduled_at: scheduled_at} = params private: %{
open_api_spex: %{body_params: %{status: _, scheduled_at: scheduled_at} = params}
}
} = conn, } = conn,
_ _
) )
@ -156,7 +162,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
else else
{:far_enough, _} -> {:far_enough, _} ->
params = Map.drop(params, [:scheduled_at]) params = Map.drop(params, [:scheduled_at])
create(%Plug.Conn{conn | body_params: params}, %{})
put_in(
conn,
[Access.key(:private), Access.key(:open_api_spex), Access.key(:body_params)],
params
)
|> do_create
error -> error ->
error error
@ -164,7 +176,35 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
# Creates a regular status # Creates a regular status
def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do def create(
%{
private: %{open_api_spex: %{body_params: %{status: _}}}
} = conn,
_
) do
do_create(conn)
end
def create(
%{
assigns: %{user: _user},
private: %{open_api_spex: %{body_params: %{media_ids: _} = params}}
} = conn,
_
) do
params = Map.put(params, :status, "")
put_in(
conn,
[Access.key(:private), Access.key(:open_api_spex), Access.key(:body_params)],
params
)
|> do_create
end
defp do_create(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: params}}} = conn
) do
params = params =
Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id]) Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|> put_application(conn) |> put_application(conn)
@ -189,13 +229,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
end end
def create(%{assigns: %{user: _user}, body_params: %{media_ids: _} = params} = conn, _) do
params = Map.put(params, :status, "")
create(%Plug.Conn{conn | body_params: params}, %{})
end
@doc "GET /api/v1/statuses/:id/history" @doc "GET /api/v1/statuses/:id/history"
def show_history(%{assigns: assigns} = conn, %{id: id} = params) do def show_history(
%{assigns: assigns, private: %{open_api_spex: %{params: %{id: id} = params}}} = conn,
_
) do
with user = assigns[:user], with user = assigns[:user],
%Activity{} = activity <- Activity.get_by_id_with_object(id), %Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do true <- Visibility.visible_for_user?(activity, user) do
@ -211,7 +249,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/statuses/:id/source" @doc "GET /api/v1/statuses/:id/source"
def show_source(%{assigns: assigns} = conn, %{id: id} = _params) do def show_source(%{assigns: assigns, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with user = assigns[:user], with user = assigns[:user],
%Activity{} = activity <- Activity.get_by_id_with_object(id), %Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do true <- Visibility.visible_for_user?(activity, user) do
@ -225,7 +263,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "PUT /api/v1/statuses/:id" @doc "PUT /api/v1/statuses/:id"
def update(%{assigns: %{user: user}, body_params: body_params} = conn, %{id: id} = params) do def update(
%{
assigns: %{user: user},
private: %{open_api_spex: %{body_params: body_params, params: %{id: id} = params}}
} = conn,
_
) do
with {_, %Activity{}} = {_, activity} <- {:activity, Activity.get_by_id_with_object(id)}, with {_, %Activity{}} = {_, activity} <- {:activity, Activity.get_by_id_with_object(id)},
{_, true} <- {:visible, Visibility.visible_for_user?(activity, user)}, {_, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
{_, true} <- {:is_create, activity.data["type"] == "Create"}, {_, true} <- {:is_create, activity.data["type"] == "Create"},
@ -248,7 +292,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/statuses/:id" @doc "GET /api/v1/statuses/:id"
def show(%{assigns: %{user: user}} = conn, %{id: id} = params) do def show(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id} = params}}} =
conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id), with %Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do true <- Visibility.visible_for_user?(activity, user) do
try_render(conn, "show.json", try_render(conn, "show.json",
@ -263,7 +311,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "DELETE /api/v1/statuses/:id" @doc "DELETE /api/v1/statuses/:id"
def delete(%{assigns: %{user: user}} = conn, %{id: id}) do def delete(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id), with %Activity{} = activity <- Activity.get_by_id_with_object(id),
{:ok, %Activity{}} <- CommonAPI.delete(id, user) do {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
try_render(conn, "show.json", try_render(conn, "show.json",
@ -278,7 +326,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/reblog" @doc "POST /api/v1/statuses/:id/reblog"
def reblog(%{assigns: %{user: user}, body_params: params} = conn, %{id: ap_id_or_id}) do def reblog(
%{
assigns: %{user: user},
private: %{open_api_spex: %{body_params: params, params: %{id: ap_id_or_id}}}
} = conn,
_
) do
with {:ok, announce} <- CommonAPI.repeat(ap_id_or_id, user, params), with {:ok, announce} <- CommonAPI.repeat(ap_id_or_id, user, params),
%Activity{} = announce <- Activity.normalize(announce.data) do %Activity{} = announce <- Activity.normalize(announce.data) do
try_render(conn, "show.json", %{activity: announce, for: user, as: :activity}) try_render(conn, "show.json", %{activity: announce, for: user, as: :activity})
@ -286,7 +340,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/unreblog" @doc "POST /api/v1/statuses/:id/unreblog"
def unreblog(%{assigns: %{user: user}} = conn, %{id: activity_id}) do def unreblog(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: activity_id}}}} =
conn,
_
) do
with {:ok, _unannounce} <- CommonAPI.unrepeat(activity_id, user), with {:ok, _unannounce} <- CommonAPI.unrepeat(activity_id, user),
%Activity{} = activity <- Activity.get_by_id(activity_id) do %Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", %{activity: activity, for: user, as: :activity}) try_render(conn, "show.json", %{activity: activity, for: user, as: :activity})
@ -294,7 +352,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/favourite" @doc "POST /api/v1/statuses/:id/favourite"
def favourite(%{assigns: %{user: user}} = conn, %{id: activity_id}) do def favourite(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: activity_id}}}} =
conn,
_
) do
with {:ok, _fav} <- CommonAPI.favorite(user, activity_id), with {:ok, _fav} <- CommonAPI.favorite(user, activity_id),
%Activity{} = activity <- Activity.get_by_id(activity_id) do %Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@ -302,7 +364,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/unfavourite" @doc "POST /api/v1/statuses/:id/unfavourite"
def unfavourite(%{assigns: %{user: user}} = conn, %{id: activity_id}) do def unfavourite(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: activity_id}}}} =
conn,
_
) do
with {:ok, _unfav} <- CommonAPI.unfavorite(activity_id, user), with {:ok, _unfav} <- CommonAPI.unfavorite(activity_id, user),
%Activity{} = activity <- Activity.get_by_id(activity_id) do %Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@ -310,7 +376,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/pin" @doc "POST /api/v1/statuses/:id/pin"
def pin(%{assigns: %{user: user}} = conn, %{id: ap_id_or_id}) do def pin(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: ap_id_or_id}}}} =
conn,
_
) do
with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
else else
@ -329,14 +399,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/unpin" @doc "POST /api/v1/statuses/:id/unpin"
def unpin(%{assigns: %{user: user}} = conn, %{id: ap_id_or_id}) do def unpin(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: ap_id_or_id}}}} =
conn,
_
) do
with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
end end
end end
@doc "POST /api/v1/statuses/:id/bookmark" @doc "POST /api/v1/statuses/:id/bookmark"
def bookmark(%{assigns: %{user: user}} = conn, %{id: id}) do def bookmark(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id), with %Activity{} = activity <- Activity.get_by_id_with_object(id),
%User{} = user <- User.get_cached_by_nickname(user.nickname), %User{} = user <- User.get_cached_by_nickname(user.nickname),
true <- Visibility.visible_for_user?(activity, user), true <- Visibility.visible_for_user?(activity, user),
@ -346,7 +423,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/unbookmark" @doc "POST /api/v1/statuses/:id/unbookmark"
def unbookmark(%{assigns: %{user: user}} = conn, %{id: id}) do def unbookmark(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id), with %Activity{} = activity <- Activity.get_by_id_with_object(id),
%User{} = user <- User.get_cached_by_nickname(user.nickname), %User{} = user <- User.get_cached_by_nickname(user.nickname),
true <- Visibility.visible_for_user?(activity, user), true <- Visibility.visible_for_user?(activity, user),
@ -356,7 +436,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/mute" @doc "POST /api/v1/statuses/:id/mute"
def mute_conversation(%{assigns: %{user: user}, body_params: params} = conn, %{id: id}) do def mute_conversation(
%{
assigns: %{user: user},
private: %{open_api_spex: %{body_params: params, params: %{id: id}}}
} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id(id), with %Activity{} = activity <- Activity.get_by_id(id),
{:ok, activity} <- CommonAPI.add_mute(user, activity, params) do {:ok, activity} <- CommonAPI.add_mute(user, activity, params) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@ -364,7 +450,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "POST /api/v1/statuses/:id/unmute" @doc "POST /api/v1/statuses/:id/unmute"
def unmute_conversation(%{assigns: %{user: user}} = conn, %{id: id}) do def unmute_conversation(
%{
assigns: %{user: user},
private: %{open_api_spex: %{params: %{id: id}}}
} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id(id), with %Activity{} = activity <- Activity.get_by_id(id),
{:ok, activity} <- CommonAPI.remove_mute(user, activity) do {:ok, activity} <- CommonAPI.remove_mute(user, activity) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity) try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@ -373,7 +465,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
@doc "GET /api/v1/statuses/:id/card" @doc "GET /api/v1/statuses/:id/card"
@deprecated "https://github.com/tootsuite/mastodon/pull/11213" @deprecated "https://github.com/tootsuite/mastodon/pull/11213"
def card(%{assigns: %{user: user}} = conn, %{id: status_id}) do def card(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: status_id}}}} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id(status_id), with %Activity{} = activity <- Activity.get_by_id(status_id),
true <- Visibility.visible_for_user?(activity, user) do true <- Visibility.visible_for_user?(activity, user) do
data = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) data = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
@ -384,7 +479,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/statuses/:id/favourited_by" @doc "GET /api/v1/statuses/:id/favourited_by"
def favourited_by(%{assigns: %{user: user}} = conn, %{id: id}) do def favourited_by(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
with true <- Pleroma.Config.get([:instance, :show_reactions]), with true <- Pleroma.Config.get([:instance, :show_reactions]),
%Activity{} = activity <- Activity.get_by_id_with_object(id), %Activity{} = activity <- Activity.get_by_id_with_object(id),
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)}, {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
@ -405,7 +503,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/statuses/:id/reblogged_by" @doc "GET /api/v1/statuses/:id/reblogged_by"
def reblogged_by(%{assigns: %{user: user}} = conn, %{id: id}) do def reblogged_by(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id), with %Activity{} = activity <- Activity.get_by_id_with_object(id),
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)}, {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
%Object{data: %{"announcements" => announces, "id" => ap_id}} <- %Object{data: %{"announcements" => announces, "id" => ap_id}} <-
@ -437,7 +538,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/statuses/:id/context" @doc "GET /api/v1/statuses/:id/context"
def context(%{assigns: %{user: user}} = conn, %{id: id}) do def context(
%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
_
) do
with %Activity{} = activity <- Activity.get_by_id(id) do with %Activity{} = activity <- Activity.get_by_id(id) do
activities = activities =
ActivityPub.fetch_activities_for_context(activity.data["context"], %{ ActivityPub.fetch_activities_for_context(activity.data["context"], %{
@ -451,7 +555,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/favourites" @doc "GET /api/v1/favourites"
def favourites(%{assigns: %{user: %User{} = user}} = conn, params) do def favourites(
%{assigns: %{user: %User{} = user}, private: %{open_api_spex: %{params: params}}} = conn,
_
) do
activities = ActivityPub.fetch_favourites(user, params) activities = ActivityPub.fetch_favourites(user, params)
conn conn
@ -464,7 +571,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end end
@doc "GET /api/v1/bookmarks" @doc "GET /api/v1/bookmarks"
def bookmarks(%{assigns: %{user: user}} = conn, params) do def bookmarks(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
user = User.get_cached_by_id(user.id) user = User.get_cached_by_id(user.id)
bookmarks = bookmarks =

View File

@ -214,7 +214,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
do: user.follower_count, do: user.follower_count,
else: 0 else: 0
bot = is_bot?(user) bot = bot?(user)
emojis = emojis =
Enum.map(user.emoji, fn {shortcode, raw_url} -> Enum.map(user.emoji, fn {shortcode, raw_url} ->
@ -471,7 +471,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
defp image_url(_), do: nil defp image_url(_), do: nil
defp is_bot?(user) do defp bot?(user) do
# Because older and/or Mastodon clients may not recognize a Group actor properly, # Because older and/or Mastodon clients may not recognize a Group actor properly,
# and currently the group actor can only boost things, we should let these clients # and currently the group actor can only boost things, we should let these clients
# think groups are bots. # think groups are bots.

View File

@ -796,8 +796,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
URI.merge(page_url_data, image_url_data) |> to_string URI.merge(page_url_data, image_url_data) |> to_string
end end
defp build_image_url(_, _), do: nil
defp get_source_text(%{"content" => content} = _source) do defp get_source_text(%{"content" => content} = _source) do
content content
end end

View File

@ -56,7 +56,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
media_proxy_url = MediaProxy.url(url) media_proxy_url = MediaProxy.url(url)
with {:ok, %{status: status} = head_response} when status in 200..299 <- with {:ok, %{status: status} = head_response} when status in 200..299 <-
Pleroma.HTTP.request("HEAD", media_proxy_url, [], [], pool: :media) do Pleroma.HTTP.request(:head, media_proxy_url, "", [], pool: :media) do
content_type = Tesla.get_header(head_response, "content-type") content_type = Tesla.get_header(head_response, "content-type")
content_length = Tesla.get_header(head_response, "content-length") content_length = Tesla.get_header(head_response, "content-length")
content_length = content_length && String.to_integer(content_length) content_length = content_length && String.to_integer(content_length)

View File

@ -610,13 +610,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end end
end end
@spec validate_scopes(App.t(), map() | list()) :: @spec validate_scopes(App.t(), list()) ::
{:ok, list()} | {:error, :missing_scopes | :unsupported_scopes} {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes}
defp validate_scopes(%App{} = app, params) when is_map(params) do
requested_scopes = Scopes.fetch_scopes(params, app.scopes)
validate_scopes(app, requested_scopes)
end
defp validate_scopes(%App{} = app, requested_scopes) when is_list(requested_scopes) do defp validate_scopes(%App{} = app, requested_scopes) when is_list(requested_scopes) do
Scopes.validate(requested_scopes, app.scopes) Scopes.validate(requested_scopes, app.scopes)
end end

View File

@ -138,9 +138,9 @@ defmodule Pleroma.Web.OAuth.Token do
|> Repo.all() |> Repo.all()
end end
def is_expired?(%__MODULE__{valid_until: valid_until}) do def expired?(%__MODULE__{valid_until: valid_until}) do
NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) > 0 NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) > 0
end end
def is_expired?(_), do: false def expired?(_), do: false
end end

View File

@ -37,7 +37,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
with id <- Endpoint.url() <> conn.request_path, with id <- Endpoint.url() <> conn.request_path,
{_, %Activity{} = activity} <- {_, %Activity{} = activity} <-
{:activity, Activity.get_create_by_object_ap_id_with_object(id)}, {:activity, Activity.get_create_by_object_ap_id_with_object(id)},
{_, true} <- {:public?, Visibility.is_public?(activity)} do {_, true} <- {:public?, Visibility.public?(activity)} do
redirect(conn, to: "/notice/#{activity.id}") redirect(conn, to: "/notice/#{activity.id}")
else else
reason when reason in [{:public?, false}, {:activity, nil}] -> reason when reason in [{:public?, false}, {:activity, nil}] ->
@ -56,7 +56,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
def activity(conn, _params) do def activity(conn, _params) do
with id <- Endpoint.url() <> conn.request_path, with id <- Endpoint.url() <> conn.request_path,
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
{_, true} <- {:public?, Visibility.is_public?(activity)} do {_, true} <- {:public?, Visibility.public?(activity)} do
redirect(conn, to: "/notice/#{activity.id}") redirect(conn, to: "/notice/#{activity.id}")
else else
reason when reason in [{:public?, false}, {:activity, nil}] -> reason when reason in [{:public?, false}, {:activity, nil}] ->
@ -69,7 +69,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do
with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)}, with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)},
{_, true} <- {:public?, Visibility.is_public?(activity)}, {_, true} <- {:public?, Visibility.public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
cond do cond do
format in ["json", "activity+json"] -> format in ["json", "activity+json"] ->
@ -106,13 +106,12 @@ defmodule Pleroma.Web.OStatus.OStatusController do
# Returns an HTML embedded <audio> or <video> player suitable for embed iframes. # Returns an HTML embedded <audio> or <video> player suitable for embed iframes.
def notice_player(conn, %{"id" => id}) do def notice_player(conn, %{"id" => id}) do
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id_with_object(id), with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.is_public?(activity), true <- Visibility.public?(activity),
{_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)}, {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)},
%Object{} = object <- Object.normalize(activity, fetch: false), %Object{} = object <- Object.normalize(activity, fetch: false),
%{data: %{"attachment" => [%{"url" => [url | _]} | _]}} <- object, %{data: %{"attachment" => [%{"url" => [url | _]} | _]}} <- object,
true <- String.starts_with?(url["mediaType"], ["audio", "video"]) do true <- String.starts_with?(url["mediaType"], ["audio", "video"]) do
conn conn
|> put_layout(:metadata_player)
|> put_resp_header("x-frame-options", "ALLOW") |> put_resp_header("x-frame-options", "ALLOW")
|> put_resp_header( |> put_resp_header(
"content-security-policy", "content-security-policy",

View File

@ -38,14 +38,24 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
%{scopes: ["read:chats"]} when action in [:messages, :index, :index2, :show] %{scopes: ["read:chats"]} when action in [:messages, :index, :index2, :show]
) )
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation
def delete_message(%{assigns: %{user: %{id: user_id} = user}} = conn, %{ def delete_message(
message_id: message_id, %{
id: chat_id assigns: %{user: %{id: user_id} = user},
}) do private: %{
open_api_spex: %{
params: %{
message_id: message_id,
id: chat_id
}
}
}
} = conn,
_
) do
with %MessageReference{} = cm_ref <- with %MessageReference{} = cm_ref <-
MessageReference.get_by_id(message_id), MessageReference.get_by_id(message_id),
^chat_id <- to_string(cm_ref.chat_id), ^chat_id <- to_string(cm_ref.chat_id),
@ -72,11 +82,14 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
defp remove_or_delete(cm_ref, _), do: MessageReference.delete(cm_ref) defp remove_or_delete(cm_ref, _), do: MessageReference.delete(cm_ref)
def post_chat_message( def post_chat_message(
%{body_params: params, assigns: %{user: user}} = conn, %{
%{id: id} private: %{open_api_spex: %{body_params: params, params: %{id: id}}},
assigns: %{user: user}
} = conn,
_
) do ) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id), with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
%User{} = recipient <- User.get_cached_by_ap_id(chat.recipient), {_, %User{} = recipient} <- {:user, User.get_cached_by_ap_id(chat.recipient)},
{:ok, activity} <- {:ok, activity} <-
CommonAPI.post_chat_message(user, recipient, params[:content], CommonAPI.post_chat_message(user, recipient, params[:content],
media_id: params[:media_id], media_id: params[:media_id],
@ -97,12 +110,20 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
conn conn
|> put_status(:bad_request) |> put_status(:bad_request)
|> json(%{error: message}) |> json(%{error: message})
{:user, nil} ->
conn
|> put_status(:bad_request)
|> json(%{error: "Recipient does not exist"})
end end
end end
def mark_message_as_read( def mark_message_as_read(
%{assigns: %{user: %{id: user_id}}} = conn, %{
%{id: chat_id, message_id: message_id} assigns: %{user: %{id: user_id}},
private: %{open_api_spex: %{params: %{id: chat_id, message_id: message_id}}}
} = conn,
_
) do ) do
with %MessageReference{} = cm_ref <- MessageReference.get_by_id(message_id), with %MessageReference{} = cm_ref <- MessageReference.get_by_id(message_id),
^chat_id <- to_string(cm_ref.chat_id), ^chat_id <- to_string(cm_ref.chat_id),
@ -115,8 +136,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
end end
def mark_as_read( def mark_as_read(
%{body_params: %{last_read_id: last_read_id}, assigns: %{user: user}} = conn, %{
%{id: id} assigns: %{user: user},
private: %{
open_api_spex: %{
body_params: %{last_read_id: last_read_id},
params: %{id: id}
}
}
} = conn,
_
) do ) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id), with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
{_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do {_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do
@ -124,7 +153,13 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
end end
end end
def messages(%{assigns: %{user: user}} = conn, %{id: id} = params) do def messages(
%{
assigns: %{user: user},
private: %{open_api_spex: %{params: %{id: id} = params}}
} = conn,
_
) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
chat_message_refs = chat_message_refs =
chat chat
@ -138,7 +173,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
end end
end end
def index(%{assigns: %{user: user}} = conn, params) do def index(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
chats = chats =
index_query(user, params) index_query(user, params)
|> Repo.all() |> Repo.all()
@ -146,7 +181,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
render(conn, "index.json", chats: chats) render(conn, "index.json", chats: chats)
end end
def index2(%{assigns: %{user: user}} = conn, params) do def index2(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
chats = chats =
index_query(user, params) index_query(user, params)
|> Pagination.fetch_paginated(params) |> Pagination.fetch_paginated(params)
@ -166,14 +201,14 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|> where([c], c.recipient not in ^exclude_users) |> where([c], c.recipient not in ^exclude_users)
end end
def create(%{assigns: %{user: user}} = conn, %{id: id}) do def create(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %User{ap_id: recipient} <- User.get_cached_by_id(id), with %User{ap_id: recipient} <- User.get_cached_by_id(id),
{:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do {:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
render(conn, "show.json", chat: chat) render(conn, "show.json", chat: chat)
end end
end end
def show(%{assigns: %{user: user}} = conn, %{id: id}) do def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
render(conn, "show.json", chat: chat) render(conn, "show.json", chat: chat)
end end

View File

@ -8,7 +8,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
alias Pleroma.Emoji.Pack alias Pleroma.Emoji.Pack
alias Pleroma.Web.ApiSpec alias Pleroma.Web.ApiSpec
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
Pleroma.Web.Plugs.OAuthScopesPlug, Pleroma.Web.Plugs.OAuthScopesPlug,
@ -22,7 +22,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
defdelegate open_api_operation(action), to: ApiSpec.PleromaEmojiFileOperation defdelegate open_api_operation(action), to: ApiSpec.PleromaEmojiFileOperation
def create(%{body_params: params} = conn, %{name: pack_name}) do def create(
%{private: %{open_api_spex: %{body_params: params, params: %{name: pack_name}}}} = conn,
_
) do
filename = params[:filename] || get_filename(params[:file]) filename = params[:filename] || get_filename(params[:file])
shortcode = params[:shortcode] || Path.basename(filename, Path.extname(filename)) shortcode = params[:shortcode] || Path.basename(filename, Path.extname(filename))
@ -49,7 +52,17 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
end end
end end
def update(%{body_params: %{shortcode: shortcode} = params} = conn, %{name: pack_name}) do def update(
%{
private: %{
open_api_spex: %{
body_params: %{shortcode: shortcode} = params,
params: %{name: pack_name}
}
}
} = conn,
_
) do
new_shortcode = params[:new_shortcode] new_shortcode = params[:new_shortcode]
new_filename = params[:new_filename] new_filename = params[:new_filename]
force = params[:force] force = params[:force]
@ -80,7 +93,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
end end
end end
def delete(conn, %{name: pack_name, shortcode: shortcode}) do def delete(
%{private: %{open_api_spex: %{params: %{name: pack_name, shortcode: shortcode}}}} = conn,
_
) do
with {:ok, pack} <- Pack.load_pack(pack_name), with {:ok, pack} <- Pack.load_pack(pack_name),
{:ok, pack} <- Pack.delete_file(pack, shortcode) do {:ok, pack} <- Pack.delete_file(pack, shortcode) do
json(conn, pack.files) json(conn, pack.files)

View File

@ -7,7 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
alias Pleroma.Emoji.Pack alias Pleroma.Emoji.Pack
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
Pleroma.Web.Plugs.OAuthScopesPlug, Pleroma.Web.Plugs.OAuthScopesPlug,
@ -26,7 +26,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaEmojiPackOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaEmojiPackOperation
def remote(conn, params) do def remote(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
with {:ok, packs} <- with {:ok, packs} <-
Pack.list_remote(url: params.url, page_size: params.page_size, page: params.page) do Pack.list_remote(url: params.url, page_size: params.page_size, page: params.page) do
json(conn, packs) json(conn, packs)
@ -38,7 +38,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def index(conn, params) do def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
emoji_path = emoji_path =
[:instance, :static_dir] [:instance, :static_dir]
|> Pleroma.Config.get!() |> Pleroma.Config.get!()
@ -61,7 +61,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def show(conn, %{name: name, page: page, page_size: page_size}) do def show(
%{private: %{open_api_spex: %{params: %{name: name, page: page, page_size: page_size}}}} =
conn,
_
) do
name = String.trim(name) name = String.trim(name)
with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do
@ -90,7 +94,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def archive(conn, %{name: name}) do def archive(%{private: %{open_api_spex: %{params: %{name: name}}}} = conn, _) do
with {:ok, archive} <- Pack.get_archive(name) do with {:ok, archive} <- Pack.get_archive(name) do
send_download(conn, {:binary, archive}, filename: "#{name}.zip") send_download(conn, {:binary, archive}, filename: "#{name}.zip")
else else
@ -109,7 +113,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def download(%{body_params: %{url: url, name: name} = params} = conn, _) do def download(
%{private: %{open_api_spex: %{body_params: %{url: url, name: name} = params}}} = conn,
_
) do
with {:ok, _pack} <- Pack.download(name, url, params[:as]) do with {:ok, _pack} <- Pack.download(name, url, params[:as]) do
json(conn, "ok") json(conn, "ok")
else else
@ -130,7 +137,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def create(conn, %{name: name}) do def create(%{private: %{open_api_spex: %{params: %{name: name}}}} = conn, _) do
name = String.trim(name) name = String.trim(name)
with {:ok, _pack} <- Pack.create(name) do with {:ok, _pack} <- Pack.create(name) do
@ -159,7 +166,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def delete(conn, %{name: name}) do def delete(%{private: %{open_api_spex: %{params: %{name: name}}}} = conn, _) do
name = String.trim(name) name = String.trim(name)
with {:ok, deleted} when deleted != [] <- Pack.delete(name) do with {:ok, deleted} when deleted != [] <- Pack.delete(name) do
@ -184,7 +191,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end end
end end
def update(%{body_params: %{metadata: metadata}} = conn, %{name: name}) do def update(
%{private: %{open_api_spex: %{body_params: %{metadata: metadata}, params: %{name: name}}}} =
conn,
_
) do
with {:ok, pack} <- Pack.update_metadata(name, metadata) do with {:ok, pack} <- Pack.update_metadata(name, metadata) do
json(conn, pack.pack) json(conn, pack.pack)
else else

View File

@ -10,7 +10,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:update]) plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:update])
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show) plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show)
@ -22,9 +22,13 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
end end
@doc "PUT /api/v1/pleroma/mascot" @doc "PUT /api/v1/pleroma/mascot"
def update(%{assigns: %{user: user}, body_params: %{file: file}} = conn, _) do def update(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{file: file}}}} =
conn,
_
) do
with {:content_type, "image" <> _} <- {:content_type, file.content_type}, with {:content_type, "image" <> _} <- {:content_type, file.content_type},
{:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)) do {_, {:ok, object}} <- {:upload, ActivityPub.upload(file, actor: User.ap_id(user))} do
attachment = render_attachment(object) attachment = render_attachment(object)
{:ok, _user} = User.mascot_update(user, attachment) {:ok, _user} = User.mascot_update(user, attachment)
@ -32,6 +36,9 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
else else
{:content_type, _} -> {:content_type, _} ->
render_error(conn, :unsupported_media_type, "mascots can only be images") render_error(conn, :unsupported_media_type, "mascots can only be images")
{:upload, {:error, _}} ->
render_error(conn, :error, "error uploading file")
end end
end end

View File

@ -7,7 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
alias Pleroma.Notification alias Pleroma.Notification
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug( plug(
Pleroma.Web.Plugs.OAuthScopesPlug, Pleroma.Web.Plugs.OAuthScopesPlug,
@ -16,7 +16,13 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
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},
private: %{open_api_spex: %{body_params: %{id: notification_id}}}
} = conn,
_
) do
with {:ok, notification} <- Notification.read_one(user, notification_id) do with {:ok, notification} <- Notification.read_one(user, notification_id) do
render(conn, "show.json", notification: notification, for: user) render(conn, "show.json", notification: notification, for: user)
else else
@ -27,7 +33,11 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
end end
end end
def mark_as_read(%{assigns: %{user: user}, body_params: %{max_id: max_id}} = conn, _) do def mark_as_read(
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{max_id: max_id}}}} =
conn,
_
) do
notifications = notifications =
user user
|> Notification.set_read_up_to(max_id) |> Notification.set_read_up_to(max_id)

View File

@ -15,14 +15,21 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks) plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks)
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action == :mutes) plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action == :mutes)
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
defdelegate open_api_operation(action), to: ApiSpec.UserImportOperation defdelegate open_api_operation(action), to: ApiSpec.UserImportOperation
def follow(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do def follow(
follow(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) %{private: %{open_api_spex: %{body_params: %{list: %Plug.Upload{path: path}}}}} = conn,
_
) do
list = File.read!(path)
do_follow(conn, list)
end end
def follow(%{assigns: %{user: follower}, body_params: %{list: list}} = conn, _) do def follow(%{private: %{open_api_spex: %{body_params: %{list: list}}}} = conn, _),
do: do_follow(conn, list)
def do_follow(%{assigns: %{user: follower}} = conn, list) do
identifiers = identifiers =
list list
|> String.split("\n") |> String.split("\n")
@ -35,20 +42,34 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
json(conn, "job started") json(conn, "job started")
end end
def blocks(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do def blocks(
blocks(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) %{private: %{open_api_spex: %{body_params: %{list: %Plug.Upload{path: path}}}}} = conn,
_
) do
list = File.read!(path)
do_block(conn, list)
end end
def blocks(%{assigns: %{user: blocker}, body_params: %{list: list}} = conn, _) do def blocks(%{private: %{open_api_spex: %{body_params: %{list: list}}}} = conn, _),
do: do_block(conn, list)
defp do_block(%{assigns: %{user: blocker}} = conn, list) do
User.Import.blocks_import(blocker, prepare_user_identifiers(list)) User.Import.blocks_import(blocker, prepare_user_identifiers(list))
json(conn, "job started") json(conn, "job started")
end end
def mutes(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do def mutes(
mutes(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) %{private: %{open_api_spex: %{body_params: %{list: %Plug.Upload{path: path}}}}} = conn,
_
) do
list = File.read!(path)
do_mute(conn, list)
end end
def mutes(%{assigns: %{user: user}, body_params: %{list: list}} = conn, _) do def mutes(%{private: %{open_api_spex: %{body_params: %{list: list}}}} = conn, _),
do: do_mute(conn, list)
defp do_mute(%{assigns: %{user: user}} = conn, list) do
User.Import.mutes_import(user, prepare_user_identifiers(list)) User.Import.mutes_import(user, prepare_user_identifiers(list))
json(conn, "job started") json(conn, "job started")
end end

View File

@ -23,14 +23,14 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
def call(conn, _) do def call(conn, _) do
with {:ok, token_str} <- fetch_token_str(conn) do with {:ok, token_str} <- fetch_token_str(conn) do
with {:ok, user, user_token} <- fetch_user_and_token(token_str), with {:ok, user, user_token} <- fetch_user_and_token(token_str),
false <- Token.is_expired?(user_token) do false <- Token.expired?(user_token) do
conn conn
|> assign(:token, user_token) |> assign(:token, user_token)
|> assign(:user, user) |> assign(:user, user)
else else
_ -> _ ->
with {:ok, app, app_token} <- fetch_app_and_token(token_str), with {:ok, app, app_token} <- fetch_app_and_token(token_str),
false <- Token.is_expired?(app_token) do false <- Token.expired?(app_token) do
conn conn
|> assign(:token, app_token) |> assign(:token, app_token)
|> assign(:app, app) |> assign(:app, app)

View File

@ -14,7 +14,7 @@ defmodule Pleroma.Web.Plugs.RateLimiter.Supervisor do
Pleroma.Web.Plugs.RateLimiter.LimiterSupervisor Pleroma.Web.Plugs.RateLimiter.LimiterSupervisor
] ]
opts = [strategy: :one_for_one, name: Pleroma.Web.Streamer.Supervisor] opts = [strategy: :one_for_one]
Supervisor.init(children, opts) Supervisor.init(children, opts)
end end
end end

View File

@ -43,6 +43,6 @@ defmodule Pleroma.Web.Plugs.RemoteIp do
InetCidr.v6?(InetCidr.parse_address!(proxy)) -> proxy <> "/128" InetCidr.v6?(InetCidr.parse_address!(proxy)) -> proxy <> "/128"
end end
InetCidr.parse(proxy, true) InetCidr.parse_cidr!(proxy, true)
end end
end end

Some files were not shown because too many files have changed in this diff Show More