Merge branch 'dialyzer-fixes' into 'develop'

More dialyzer fixes

See merge request pleroma/pleroma!4048
This commit is contained in:
feld 2024-01-28 23:20:25 +00:00
commit c9dc881747
44 changed files with 178 additions and 163 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

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

View File

@ -51,12 +51,12 @@ def reload 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

View File

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

View File

@ -242,17 +242,17 @@ def delete(%Object{data: %{"id" => id}} = 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

@ -84,13 +84,13 @@ def default_cache_control_header, do: @default_cache_control_header
{: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 @@ defp body_size_constraint(size, limit) when is_integer(limit) and limit > 0 and
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 @@ defp increase_read_duration({previous_duration, started})
{: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

@ -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(),

View File

@ -1787,7 +1787,10 @@ def set_activation_async(user, status \\ true) 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

View File

@ -173,6 +173,9 @@ def validate(
{:object_validation, e} -> {:object_validation, e} ->
e e
{:error, %Ecto.Changeset{} = e} ->
{:error, e}
end end
end end

View File

@ -304,9 +304,9 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object,
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 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object,
{: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 @@ def handle_undoing(
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

@ -776,10 +776,9 @@ defp build_flag_object(act) when is_map(act) or is_binary(act) 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

@ -128,7 +128,7 @@ def show(conn, _params) do
end end
end end
def update(%{body_params: %{configs: configs}} = conn, _) do def update(%{body_params: %{"configs" => configs}} = conn, _) do
with :ok <- configurable_from_database() do with :ok <- configurable_from_database() do
results = results =
configs configs

View File

@ -27,7 +27,7 @@ def show(conn, %{name: document_name}) do
end end
end end
def update(%{body_params: %{file: file}} = conn, %{name: document_name}) do def update(%{body_params: %{"file" => file}} = conn, %{name: document_name}) 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

View File

@ -40,7 +40,7 @@ def create(%{body_params: params} = conn, _) do
end end
@doc "Revokes invite by token" @doc "Revokes invite by token"
def revoke(%{body_params: %{token: token}} = conn, _) do def revoke(%{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,7 @@ def revoke(%{body_params: %{token: token}} = conn, _) 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}, 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(),
@ -60,7 +60,7 @@ def email(%{assigns: %{user: user}, body_params: %{email: email} = params} = con
|> Pleroma.Emails.UserEmail.user_invitation_email( |> Pleroma.Emails.UserEmail.user_invitation_email(
invite_token, invite_token,
email, email,
params[:name] params["name"]
) )
|> Pleroma.Emails.Mailer.deliver() do |> Pleroma.Emails.Mailer.deliver() do
json_response(conn, :no_content, "") json_response(conn, :no_content, "")

View File

@ -59,12 +59,12 @@ defp paginate_entries(entries, page, page_size) 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: _}, 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: _}, body_params: %{"urls" => urls, "ban" => ban}} = conn, _) do
MediaProxy.Invalidation.purge(urls) MediaProxy.Invalidation.purge(urls)
if ban do if ban do

View File

@ -31,7 +31,7 @@ def index(conn, _params) do
end end
end end
def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn, _) do def follow(%{assigns: %{user: admin}, 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,8 +44,11 @@ def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn,
end end
end end
def unfollow(%{assigns: %{user: admin}, body_params: %{relay_url: target} = params} = conn, _) do def unfollow(
with {:ok, _message} <- Relay.unfollow(target, %{force: params[:force]}) do %{assigns: %{user: admin}, body_params: %{"relay_url" => target} = params} = conn,
_
) 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})
json(conn, target) json(conn, target)

View File

@ -45,7 +45,7 @@ def show(conn, %{id: id}) do
end end
end end
def update(%{assigns: %{user: admin}, body_params: %{reports: reports}} = conn, _) do def update(%{assigns: %{user: admin}, 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,7 +73,7 @@ def update(%{assigns: %{user: admin}, body_params: %{reports: reports}} = conn,
end end
end end
def notes_create(%{assigns: %{user: user}, body_params: %{content: content}} = conn, %{ def notes_create(%{assigns: %{user: user}, body_params: %{"content" => content}} = conn, %{
id: report_id id: report_id
}) do }) do
with {:ok, _} <- ReportNote.create(user.id, report_id, content), with {:ok, _} <- ReportNote.create(user.id, report_id, content),

View File

@ -53,11 +53,11 @@ defmodule Pleroma.Web.AdminAPI.UserController do
def delete(conn, %{nickname: nickname}) do def delete(conn, %{nickname: nickname}) do
conn conn
|> Map.put(:body_params, %{nicknames: [nickname]}) |> Map.put(:body_params, %{"nicknames" => [nickname]})
|> delete(%{}) |> delete(%{})
end end
def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do def delete(%{assigns: %{user: admin}, 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)
Enum.each(users, fn user -> Enum.each(users, fn user ->
@ -78,8 +78,8 @@ def follow(
%{ %{
assigns: %{user: admin}, assigns: %{user: admin},
body_params: %{ body_params: %{
follower: follower_nick, "follower" => follower_nick,
followed: followed_nick "followed" => followed_nick
} }
} = conn, } = conn,
_ _
@ -103,8 +103,8 @@ def unfollow(
%{ %{
assigns: %{user: admin}, assigns: %{user: admin},
body_params: %{ body_params: %{
follower: follower_nick, "follower" => follower_nick,
followed: followed_nick "followed" => followed_nick
} }
} = conn, } = conn,
_ _
@ -124,7 +124,7 @@ def unfollow(
json(conn, "ok") json(conn, "ok")
end end
def create(%{assigns: %{user: admin}, body_params: %{users: users}} = conn, _) do def create(%{assigns: %{user: admin}, 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} ->
@ -202,7 +202,7 @@ def toggle_activation(%{assigns: %{user: admin}} = conn, %{nickname: nickname})
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}, 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 +212,10 @@ def activate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} =
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}, 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 +225,10 @@ def deactivate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}}
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}, 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 +241,7 @@ def approve(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = c
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}, 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 +254,7 @@ def suggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = c
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}, 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)

View File

@ -882,9 +882,9 @@ defp follow_by_uri_request do
description: "POST body for muting an account", description: "POST body for muting an account",
type: :object, type: :object,
properties: %{ properties: %{
uri: %Schema{type: :string, nullable: true, format: :uri} "uri" => %Schema{type: :string, nullable: true, format: :uri}
}, },
required: [:uri] required: ["uri"]
} }
end end
@ -925,7 +925,7 @@ defp note_request do
description: "POST body for adding a note for an account", description: "POST body for adding a note for an account",
type: :object, type: :object,
properties: %{ properties: %{
comment: %Schema{ "comment" => %Schema{
type: :string, type: :string,
description: "Account note body" description: "Account note body"
} }

View File

@ -47,7 +47,7 @@ def update_operation do
request_body("Parameters", %Schema{ request_body("Parameters", %Schema{
type: :object, type: :object,
properties: %{ properties: %{
configs: %Schema{ "configs" => %Schema{
type: :array, type: :array,
items: %Schema{ items: %Schema{
type: :object, type: :object,

View File

@ -61,9 +61,9 @@ defp update_request do
title: "UpdateRequest", title: "UpdateRequest",
description: "POST body for uploading the file", description: "POST body for uploading the file",
type: :object, type: :object,
required: [:file], required: ["file"],
properties: %{ properties: %{
file: %Schema{ "file" => %Schema{
type: :string, type: :string,
format: :binary, format: :binary,
description: "The file to be uploaded, using multipart form data." description: "The file to be uploaded, using multipart form data."

View File

@ -79,9 +79,9 @@ def revoke_operation do
"Parameters", "Parameters",
%Schema{ %Schema{
type: :object, type: :object,
required: [:token], required: ["token"],
properties: %{ properties: %{
token: %Schema{type: :string} "token" => %Schema{type: :string}
} }
}, },
required: true required: true
@ -106,10 +106,10 @@ def email_operation do
"Parameters", "Parameters",
%Schema{ %Schema{
type: :object, type: :object,
required: [:email], required: ["email"],
properties: %{ properties: %{
email: %Schema{type: :string, format: :email}, "email" => %Schema{type: :string, format: :email},
name: %Schema{type: :string} "name" => %Schema{type: :string}
} }
}, },
required: true required: true

View File

@ -78,9 +78,9 @@ def delete_operation do
"Parameters", "Parameters",
%Schema{ %Schema{
type: :object, type: :object,
required: [:urls], required: ["urls"],
properties: %{ properties: %{
urls: %Schema{type: :array, items: %Schema{type: :string, format: :uri}} "urls" => %Schema{type: :array, items: %Schema{type: :string, format: :uri}}
} }
}, },
required: true required: true
@ -104,10 +104,10 @@ def purge_operation do
"Parameters", "Parameters",
%Schema{ %Schema{
type: :object, type: :object,
required: [:urls], required: ["urls"],
properties: %{ properties: %{
urls: %Schema{type: :array, items: %Schema{type: :string, format: :uri}}, "urls" => %Schema{type: :array, items: %Schema{type: :string, format: :uri}},
ban: %Schema{type: :boolean, default: true} "ban" => %Schema{type: :boolean, default: true}
} }
}, },
required: true required: true

View File

@ -87,7 +87,7 @@ defp relay_url do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{
relay_url: %Schema{type: :string, format: :uri} "relay_url" => %Schema{type: :string, format: :uri}
} }
} }
end end
@ -96,8 +96,8 @@ defp relay_unfollow do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{
relay_url: %Schema{type: :string, format: :uri}, "relay_url" => %Schema{type: :string, format: :uri},
force: %Schema{type: :boolean, default: false} "force" => %Schema{type: :boolean, default: false}
} }
} }
end end

View File

@ -107,7 +107,7 @@ def notes_create_operation do
request_body("Parameters", %Schema{ request_body("Parameters", %Schema{
type: :object, type: :object,
properties: %{ properties: %{
content: %Schema{type: :string, description: "The message"} "content" => %Schema{type: :string, description: "The message"}
} }
}), }),
security: [%{"oAuth" => ["admin:write:reports"]}], security: [%{"oAuth" => ["admin:write:reports"]}],
@ -199,9 +199,9 @@ defp account_admin do
defp update_request do defp update_request do
%Schema{ %Schema{
type: :object, type: :object,
required: [:reports], required: ["reports"],
properties: %{ properties: %{
reports: %Schema{ "reports" => %Schema{
type: :array, type: :array,
items: %Schema{ items: %Schema{
type: :object, type: :object,

View File

@ -50,7 +50,7 @@ def index_operation do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{
users: %Schema{type: :array, items: user()}, "users" => %Schema{type: :array, items: user()},
count: %Schema{type: :integer}, count: %Schema{type: :integer},
page_size: %Schema{type: :integer} page_size: %Schema{type: :integer}
} }
@ -75,7 +75,7 @@ def create_operation do
description: "POST body for creating users", description: "POST body for creating users",
type: :object, type: :object,
properties: %{ properties: %{
users: %Schema{ "users" => %Schema{
type: :array, type: :array,
items: %Schema{ items: %Schema{
type: :object, type: :object,
@ -168,8 +168,8 @@ def follow_operation do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{
follower: %Schema{type: :string, description: "Follower nickname"}, "follower" => %Schema{type: :string, description: "Follower nickname"},
followed: %Schema{type: :string, description: "Followed nickname"} "followed" => %Schema{type: :string, description: "Followed nickname"}
} }
} }
), ),
@ -193,8 +193,8 @@ def unfollow_operation do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{
follower: %Schema{type: :string, description: "Follower nickname"}, "follower" => %Schema{type: :string, description: "Follower nickname"},
followed: %Schema{type: :string, description: "Followed nickname"} "followed" => %Schema{type: :string, description: "Followed nickname"}
} }
} }
), ),
@ -219,7 +219,7 @@ def approve_operation do
description: "POST body for approving multiple users", description: "POST body for approving multiple users",
type: :object, type: :object,
properties: %{ properties: %{
nicknames: %Schema{ "nicknames" => %Schema{
type: :array, type: :array,
items: %Schema{type: :string} items: %Schema{type: :string}
} }
@ -251,7 +251,7 @@ def suggest_operation do
description: "POST body for adding multiple suggested users", description: "POST body for adding multiple suggested users",
type: :object, type: :object,
properties: %{ properties: %{
nicknames: %Schema{ "nicknames" => %Schema{
type: :array, type: :array,
items: %Schema{type: :string} items: %Schema{type: :string}
} }
@ -283,7 +283,7 @@ def unsuggest_operation do
description: "POST body for removing multiple suggested users", description: "POST body for removing multiple suggested users",
type: :object, type: :object,
properties: %{ properties: %{
nicknames: %Schema{ "nicknames" => %Schema{
type: :array, type: :array,
items: %Schema{type: :string} items: %Schema{type: :string}
} }
@ -332,7 +332,7 @@ def activate_operation do
description: "POST body for deleting multiple users", description: "POST body for deleting multiple users",
type: :object, type: :object,
properties: %{ properties: %{
nicknames: %Schema{ "nicknames" => %Schema{
type: :array, type: :array,
items: %Schema{type: :string} items: %Schema{type: :string}
} }
@ -364,7 +364,7 @@ def deactivate_operation do
description: "POST body for deleting multiple users", description: "POST body for deleting multiple users",
type: :object, type: :object,
properties: %{ properties: %{
nicknames: %Schema{ "nicknames" => %Schema{
type: :array, type: :array,
items: %Schema{type: :string} items: %Schema{type: :string}
} }
@ -404,7 +404,7 @@ def delete_operation do
description: "POST body for deleting multiple users", description: "POST body for deleting multiple users",
type: :object, type: :object,
properties: %{ properties: %{
nicknames: %Schema{ "nicknames" => %Schema{
type: :array, type: :array,
items: %Schema{type: :string} items: %Schema{type: :string}
} }

View File

@ -368,9 +368,9 @@ def mark_as_read do
title: "MarkAsReadRequest", title: "MarkAsReadRequest",
description: "POST body for marking a number of chat messages as read", description: "POST body for marking a number of chat messages as read",
type: :object, type: :object,
required: [:last_read_id], required: ["last_read_id"],
properties: %{ properties: %{
last_read_id: %Schema{ "last_read_id" => %Schema{
type: :string, type: :string,
description: "The content of your message." description: "The content of your message."
} }

View File

@ -36,9 +36,9 @@ def create_operation do
defp create_request do defp create_request do
%Schema{ %Schema{
type: :object, type: :object,
required: [:file], required: ["file"],
properties: %{ properties: %{
file: %Schema{ "file" => %Schema{
description: description:
"File needs to be uploaded with the multipart request or link to remote file", "File needs to be uploaded with the multipart request or link to remote file",
anyOf: [ anyOf: [
@ -46,12 +46,12 @@ defp create_request do
%Schema{type: :string, format: :uri} %Schema{type: :string, format: :uri}
] ]
}, },
shortcode: %Schema{ "shortcode" => %Schema{
type: :string, type: :string,
description: description:
"Shortcode for new emoji, must be unique for all emoji. If not sended, shortcode will be taken from original filename." "Shortcode for new emoji, must be unique for all emoji. If not sended, shortcode will be taken from original filename."
}, },
filename: %Schema{ "filename" => %Schema{
type: :string, type: :string,
description: description:
"New emoji file name. If not specified will be taken from original filename." "New emoji file name. If not specified will be taken from original filename."
@ -81,21 +81,21 @@ def update_operation do
defp update_request do defp update_request do
%Schema{ %Schema{
type: :object, type: :object,
required: [:shortcode, :new_shortcode, :new_filename], required: ["shortcode", "new_shortcode", "new_filename"],
properties: %{ properties: %{
shortcode: %Schema{ "shortcode" => %Schema{
type: :string, type: :string,
description: "Emoji file shortcode" description: "Emoji file shortcode"
}, },
new_shortcode: %Schema{ "new_shortcode" => %Schema{
type: :string, type: :string,
description: "New emoji file shortcode" description: "New emoji file shortcode"
}, },
new_filename: %Schema{ "new_filename" => %Schema{
type: :string, type: :string,
description: "New filename for emoji file" description: "New filename for emoji file"
}, },
force: %Schema{ "force" => %Schema{
type: :boolean, type: :boolean,
description: "With true value to overwrite existing emoji with new shortcode", description: "With true value to overwrite existing emoji with new shortcode",
default: false default: false

View File

@ -130,15 +130,15 @@ def download_operation do
defp download_request do defp download_request do
%Schema{ %Schema{
type: :object, type: :object,
required: [:url, :name], required: ["url", "name"],
properties: %{ properties: %{
url: %Schema{ "url" => %Schema{
type: :string, type: :string,
format: :uri, format: :uri,
description: "URL of the instance to download from" description: "URL of the instance to download from"
}, },
name: %Schema{type: :string, format: :uri, description: "Pack Name"}, "name" => %Schema{type: :string, format: :uri, description: "Pack Name"},
as: %Schema{type: :string, format: :uri, description: "Save as"} "as" => %Schema{type: :string, format: :uri, description: "Save as"}
} }
} }
end end
@ -302,27 +302,7 @@ defp files_object do
defp update_request do defp update_request do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{"metadata" => metadata()}
metadata: %Schema{
type: :object,
description: "Metadata to replace the old one",
properties: %{
license: %Schema{type: :string},
homepage: %Schema{type: :string, format: :uri},
description: %Schema{type: :string},
"fallback-src": %Schema{
type: :string,
format: :uri,
description: "Fallback url to download pack from"
},
"fallback-src-sha256": %Schema{
type: :string,
description: "SHA256 encoded for fallback pack archive"
},
"share-files": %Schema{type: :boolean, description: "Is pack allowed for sharing?"}
}
}
}
} }
end end

View File

@ -39,7 +39,7 @@ def update_operation do
%Schema{ %Schema{
type: :object, type: :object,
properties: %{ properties: %{
file: %Schema{type: :string, format: :binary} "file" => %Schema{type: :string, format: :binary}
} }
}, },
required: true required: true

View File

@ -24,8 +24,11 @@ def mark_as_read_operation do
request_body("Parameters", %Schema{ request_body("Parameters", %Schema{
type: :object, type: :object,
properties: %{ properties: %{
id: %Schema{type: :integer, description: "A single notification ID to read"}, "id" => %Schema{type: :integer, description: "A single notification ID to read"},
max_id: %Schema{type: :integer, description: "Read all notifications up to this ID"} "max_id" => %Schema{
type: :integer,
description: "Read all notifications up to this ID"
}
} }
}), }),
security: [%{"oAuth" => ["write:notifications"]}], security: [%{"oAuth" => ["write:notifications"]}],

View File

@ -404,10 +404,10 @@ defp remote_interaction_request do
title: "RemoteInteractionRequest", title: "RemoteInteractionRequest",
description: "POST body for remote interaction", description: "POST body for remote interaction",
type: :object, type: :object,
required: [:ap_id, :profile], required: ["ap_id", "profile"],
properties: %{ properties: %{
ap_id: %Schema{type: :string, description: "Profile or status ActivityPub ID"}, "ap_id" => %Schema{type: :string, description: "Profile or status ActivityPub ID"},
profile: %Schema{type: :string, description: "Remote profile webfinger"} "profile" => %Schema{type: :string, description: "Remote profile webfinger"}
} }
} }
end end

View File

@ -61,9 +61,9 @@ def mutes_operation do
defp import_request do defp import_request do
%Schema{ %Schema{
type: :object, type: :object,
required: [:list], required: ["list"],
properties: %{ properties: %{
list: %Schema{ "list" => %Schema{
description: description:
"STRING or FILE containing a whitespace-separated list of accounts to import.", "STRING or FILE containing a whitespace-separated list of accounts to import.",
anyOf: [ anyOf: [

View File

@ -472,7 +472,7 @@ def unblock(%{assigns: %{user: blocker, account: blocked}} = conn, _params) 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}, 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 +513,7 @@ def remove_from_followers(%{assigns: %{user: followed, account: follower}} = con
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(%{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

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

@ -76,7 +76,7 @@ def post_chat_message(
%{id: id} %{id: id}
) 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,6 +97,11 @@ def post_chat_message(
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
@ -115,7 +120,7 @@ def mark_message_as_read(
end end
def mark_as_read( def mark_as_read(
%{body_params: %{last_read_id: last_read_id}, assigns: %{user: user}} = conn, %{body_params: %{"last_read_id" => last_read_id}, assigns: %{user: user}} = conn,
%{id: id} %{id: id}
) do ) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id), with {:ok, chat} <- Chat.get_by_user_and_id(user, id),

View File

@ -23,11 +23,11 @@ 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(%{body_params: params} = conn, %{name: pack_name}) 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))
with {:ok, pack} <- Pack.load_pack(pack_name), with {:ok, pack} <- Pack.load_pack(pack_name),
{:ok, file} <- get_file(params[:file]), {:ok, file} <- get_file(params["file"]),
{:ok, pack} <- Pack.add_file(pack, shortcode, filename, file) do {:ok, pack} <- Pack.add_file(pack, shortcode, filename, file) do
json(conn, pack.files) json(conn, pack.files)
else else
@ -49,10 +49,10 @@ def create(%{body_params: params} = conn, %{name: pack_name}) do
end end
end end
def update(%{body_params: %{shortcode: shortcode} = params} = conn, %{name: pack_name}) do def update(%{body_params: %{"shortcode" => shortcode} = params} = conn, %{name: pack_name}) 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"]
with {:ok, pack} <- Pack.load_pack(pack_name), with {:ok, pack} <- Pack.load_pack(pack_name),
{:ok, pack} <- Pack.update_file(pack, shortcode, new_shortcode, new_filename, force) do {:ok, pack} <- Pack.update_file(pack, shortcode, new_shortcode, new_filename, force) do
@ -128,9 +128,9 @@ defp handle_error(conn, {:error, error}, opts) do
defp get_filename(%Plug.Upload{filename: filename}), do: filename defp get_filename(%Plug.Upload{filename: filename}), do: filename
defp get_filename(url) when is_binary(url), do: Path.basename(url) defp get_filename(url) when is_binary(url), do: Path.basename(url)
def get_file(%Plug.Upload{} = file), do: {:ok, file} defp get_file(%Plug.Upload{} = file), do: {:ok, file}
def get_file(url) when is_binary(url) do defp get_file(url) when is_binary(url) do
with {:ok, %Tesla.Env{body: body, status: code, headers: headers}} with {:ok, %Tesla.Env{body: body, status: code, headers: headers}}
when code in 200..299 <- Pleroma.HTTP.get(url) do when code in 200..299 <- Pleroma.HTTP.get(url) do
path = Plug.Upload.random_file!("emoji") path = Plug.Upload.random_file!("emoji")

View File

@ -109,8 +109,8 @@ def archive(conn, %{name: name}) do
end end
end end
def download(%{body_params: %{url: url, name: name} = params} = conn, _) do def download(%{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
{:error, :not_shareable} -> {:error, :not_shareable} ->
@ -184,7 +184,7 @@ def delete(conn, %{name: name}) do
end end
end end
def update(%{body_params: %{metadata: metadata}} = conn, %{name: name}) do def update(%{body_params: %{"metadata" => metadata}} = conn, %{name: name}) 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

@ -22,9 +22,9 @@ def show(%{assigns: %{user: user}} = conn, _params) 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}, body_params: %{"file" => file}} = conn, _) do
with {:content_type, "image" <> _} <- {:content_type, file.content_type}, with {_, "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 +32,9 @@ def update(%{assigns: %{user: user}, body_params: %{file: file}} = conn, _) 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

@ -16,7 +16,7 @@ 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}, 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 +27,7 @@ def mark_as_read(%{assigns: %{user: user}, body_params: %{id: notification_id}}
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}, 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

@ -18,11 +18,11 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
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(%{body_params: %{"list" => %Plug.Upload{path: path}}} = conn, _) do
follow(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) follow(%Plug.Conn{conn | body_params: %{"list" => File.read!(path)}}, %{})
end end
def follow(%{assigns: %{user: follower}, body_params: %{list: list}} = conn, _) do def follow(%{assigns: %{user: follower}, body_params: %{"list" => list}} = conn, _) do
identifiers = identifiers =
list list
|> String.split("\n") |> String.split("\n")
@ -35,20 +35,20 @@ def follow(%{assigns: %{user: follower}, body_params: %{list: list}} = conn, _)
json(conn, "job started") json(conn, "job started")
end end
def blocks(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do def blocks(%{body_params: %{"list" => %Plug.Upload{path: path}}} = conn, _) do
blocks(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) blocks(%Plug.Conn{conn | body_params: %{"list" => File.read!(path)}}, %{})
end end
def blocks(%{assigns: %{user: blocker}, body_params: %{list: list}} = conn, _) do def blocks(%{assigns: %{user: blocker}, body_params: %{"list" => list}} = conn, _) 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(%{body_params: %{"list" => %Plug.Upload{path: path}}} = conn, _) do
mutes(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{}) mutes(%Plug.Conn{conn | body_params: %{"list" => File.read!(path)}}, %{})
end end
def mutes(%{assigns: %{user: user}, body_params: %{list: list}} = conn, _) do def mutes(%{assigns: %{user: user}, body_params: %{"list" => list}} = conn, _) 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

@ -150,7 +150,10 @@ def remote_subscribe(conn, %{"status" => %{"status_id" => id, "profile" => profi
end end
end end
def remote_interaction(%{body_params: %{ap_id: ap_id, profile: profile}} = conn, _params) do def remote_interaction(
%{body_params: %{"ap_id" => ap_id, "profile" => profile}} = conn,
_params
) do
with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile) do with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile) do
conn conn
|> json(%{url: String.replace(template, "{uri}", ap_id)}) |> json(%{url: String.replace(template, "{uri}", ap_id)})

View File

@ -873,7 +873,7 @@ test "tuples with more than two values", %{conn: conn} do
%{ %{
"tuple" => [ "tuple" => [
":_", ":_",
"Phoenix.Endpoint.Cowboy2Handler", "Plug.Cowboy.Handler",
%{"tuple" => ["Pleroma.Web.Endpoint", []]} %{"tuple" => ["Pleroma.Web.Endpoint", []]}
] ]
} }
@ -937,7 +937,7 @@ test "tuples with more than two values", %{conn: conn} do
%{ %{
"tuple" => [ "tuple" => [
":_", ":_",
"Phoenix.Endpoint.Cowboy2Handler", "Plug.Cowboy.Handler",
%{"tuple" => ["Pleroma.Web.Endpoint", []]} %{"tuple" => ["Pleroma.Web.Endpoint", []]}
] ]
} }