diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1b7c03ebb..aad28a2d8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -48,6 +48,7 @@ benchmark:
unit-testing:
stage: test
+ retry: 2
cache: &testing_cache_policy
<<: *global_cache_policy
policy: pull
@@ -80,6 +81,7 @@ unit-testing:
unit-testing-rum:
stage: test
+ retry: 2
cache: *testing_cache_policy
services:
- name: minibikini/postgres-with-rum:12
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2c9e106e..b385264f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,6 +53,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
- Healthcheck reporting the number of memory currently used, rather than allocated in total
+- `InsertSkeletonsForDeletedUsers` failing on some instances
## [2.0.3] - 2020-05-02
diff --git a/benchmarks/load_testing/users.ex b/benchmarks/load_testing/users.ex
index 1a8c6e22f..e4d0b22ff 100644
--- a/benchmarks/load_testing/users.ex
+++ b/benchmarks/load_testing/users.ex
@@ -55,7 +55,7 @@ defp generate_user(i) do
name: "Test テスト User #{i}",
email: "user#{i}@example.com",
nickname: "nick#{i}",
- password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
+ password_hash: Pbkdf2.hash_pwd_salt("test"),
bio: "Tester Number #{i}",
local: !remote
}
diff --git a/config/description.exs b/config/description.exs
index 504161a9f..36ec3d40a 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -28,7 +28,8 @@
%{
key: :filters,
type: {:list, :module},
- description: "List of filter modules for uploads",
+ description:
+ "List of filter modules for uploads. Module names are shortened (removed leading `Pleroma.Upload.Filter.` part), but on adding custom module you need to use full name.",
suggestions:
Generator.list_modules_in_dir(
"lib/pleroma/upload/filter",
@@ -681,7 +682,8 @@
%{
key: :federation_publisher_modules,
type: {:list, :module},
- description: "List of modules for federation publishing",
+ description:
+ "List of modules for federation publishing. Module names are shortened (removed leading `Pleroma.Web.` part), but on adding custom module you need to use full name.",
suggestions: [
Pleroma.Web.ActivityPub.Publisher
]
@@ -694,7 +696,8 @@
%{
key: :rewrite_policy,
type: [:module, {:list, :module}],
- description: "A list of MRF policies enabled",
+ description:
+ "A list of enabled MRF policies. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
suggestions:
Generator.list_modules_in_dir(
"lib/pleroma/web/activity_pub/mrf",
@@ -2031,7 +2034,8 @@
%{
key: :parsers,
type: {:list, :module},
- description: "List of Rich Media parsers.",
+ description:
+ "List of Rich Media parsers. Module names are shortened (removed leading `Pleroma.Web.RichMedia.Parsers.` part), but on adding custom module you need to use full name.",
suggestions: [
Pleroma.Web.RichMedia.Parsers.MetaTagsParser,
Pleroma.Web.RichMedia.Parsers.OEmbed,
@@ -2043,7 +2047,8 @@
key: :ttl_setters,
label: "TTL setters",
type: {:list, :module},
- description: "List of rich media TTL setters.",
+ description:
+ "List of rich media TTL setters. Module names are shortened (removed leading `Pleroma.Web.RichMedia.Parser.` part), but on adding custom module you need to use full name.",
suggestions: [
Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl
]
@@ -2717,6 +2722,8 @@
%{
key: :scrub_policy,
type: {:list, :module},
+ description:
+ "Module names are shortened (removed leading `Pleroma.HTML.` part), but on adding custom module you need to use full name.",
suggestions: [Pleroma.HTML.Transform.MediaProxy, Pleroma.HTML.Scrubber.Default]
}
]
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index a00bc0624..9d3d92b38 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -56,7 +56,7 @@ def start(_type, _args) do
if (major == 22 and minor < 2) or major < 22 do
raise "
!!!OTP VERSION WARNING!!!
- You are using gun adapter with OTP version #{version}, which doesn't support correct handling of unordered certificates chains.
+ You are using gun adapter with OTP version #{version}, which doesn't support correct handling of unordered certificates chains. Please update your Erlang/OTP to at least 22.2.
"
end
else
diff --git a/lib/pleroma/bbs/authenticator.ex b/lib/pleroma/bbs/authenticator.ex
index e5b37f33e..d4494b003 100644
--- a/lib/pleroma/bbs/authenticator.ex
+++ b/lib/pleroma/bbs/authenticator.ex
@@ -4,7 +4,6 @@
defmodule Pleroma.BBS.Authenticator do
use Sshd.PasswordAuthenticator
- alias Comeonin.Pbkdf2
alias Pleroma.User
def authenticate(username, password) do
@@ -12,7 +11,7 @@ def authenticate(username, password) do
password = to_string(password)
with %User{} = user <- User.get_by_nickname(username) do
- Pbkdf2.checkpw(password, user.password_hash)
+ Pbkdf2.verify_pass(password, user.password_hash)
else
_e -> false
end
diff --git a/lib/pleroma/bbs/handler.ex b/lib/pleroma/bbs/handler.ex
index c7bc8ef6c..12d64c2fe 100644
--- a/lib/pleroma/bbs/handler.ex
+++ b/lib/pleroma/bbs/handler.ex
@@ -66,7 +66,7 @@ def handle_command(%{user: user} = state, "r " <> text) do
with %Activity{} <- Activity.get_by_id(activity_id),
{:ok, _activity} <-
- CommonAPI.post(user, %{"status" => rest, "in_reply_to_status_id" => activity_id}) do
+ CommonAPI.post(user, %{status: rest, in_reply_to_status_id: activity_id}) do
IO.puts("Replied!")
else
_e -> IO.puts("Could not reply...")
@@ -78,7 +78,7 @@ def handle_command(%{user: user} = state, "r " <> text) do
def handle_command(%{user: user} = state, "p " <> text) do
text = String.trim(text)
- with {:ok, _activity} <- CommonAPI.post(user, %{"status" => text}) do
+ with {:ok, _activity} <- CommonAPI.post(user, %{status: text}) do
IO.puts("Posted!")
else
_e -> IO.puts("Could not post...")
diff --git a/lib/pleroma/mfa.ex b/lib/pleroma/mfa.ex
index d353a4dad..2b77f5426 100644
--- a/lib/pleroma/mfa.ex
+++ b/lib/pleroma/mfa.ex
@@ -7,7 +7,6 @@ defmodule Pleroma.MFA do
The MFA context.
"""
- alias Comeonin.Pbkdf2
alias Pleroma.User
alias Pleroma.MFA.BackupCodes
@@ -72,7 +71,7 @@ def invalidate_backup_code(%User{} = user, hash_code) do
@spec generate_backup_codes(User.t()) :: {:ok, list(binary)} | {:error, String.t()}
def generate_backup_codes(%User{} = user) do
with codes <- BackupCodes.generate(),
- hashed_codes <- Enum.map(codes, &Pbkdf2.hashpwsalt/1),
+ hashed_codes <- Enum.map(codes, &Pbkdf2.hash_pwd_salt/1),
changeset <- Changeset.cast_backup_codes(user, hashed_codes),
{:ok, _} <- User.update_and_set_cache(changeset) do
{:ok, codes}
diff --git a/lib/pleroma/plugs/authentication_plug.ex b/lib/pleroma/plugs/authentication_plug.ex
index 0061c69dc..ae4a235bd 100644
--- a/lib/pleroma/plugs/authentication_plug.ex
+++ b/lib/pleroma/plugs/authentication_plug.ex
@@ -3,7 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Plugs.AuthenticationPlug do
- alias Comeonin.Pbkdf2
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.User
@@ -18,7 +17,7 @@ def checkpw(password, "$6" <> _ = password_hash) do
end
def checkpw(password, "$pbkdf2" <> _ = password_hash) do
- Pbkdf2.checkpw(password, password_hash)
+ Pbkdf2.verify_pass(password, password_hash)
end
def checkpw(_password, _password_hash) do
@@ -37,7 +36,7 @@ def call(
} = conn,
_
) do
- if Pbkdf2.checkpw(password, password_hash) do
+ if Pbkdf2.verify_pass(password, password_hash) do
conn
|> assign(:user, auth_user)
|> OAuthScopesPlug.skip_plug()
@@ -47,7 +46,7 @@ def call(
end
def call(%{assigns: %{auth_credentials: %{password: _}}} = conn, _) do
- Pbkdf2.dummy_checkpw()
+ Pbkdf2.no_user_verify()
conn
end
diff --git a/lib/pleroma/scheduled_activity.ex b/lib/pleroma/scheduled_activity.ex
index 8ff06a462..0937cb7db 100644
--- a/lib/pleroma/scheduled_activity.ex
+++ b/lib/pleroma/scheduled_activity.ex
@@ -40,7 +40,7 @@ defp with_media_attachments(
%{changes: %{params: %{"media_ids" => media_ids} = params}} = changeset
)
when is_list(media_ids) do
- media_attachments = Utils.attachments_from_ids(%{"media_ids" => media_ids})
+ media_attachments = Utils.attachments_from_ids(%{media_ids: media_ids})
params =
params
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 2a6a23fec..cba391072 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -9,7 +9,6 @@ defmodule Pleroma.User do
import Ecto.Query
import Ecto, only: [assoc: 2]
- alias Comeonin.Pbkdf2
alias Ecto.Multi
alias Pleroma.Activity
alias Pleroma.Config
@@ -1554,10 +1553,23 @@ def delete_user_activities(%User{ap_id: ap_id} = user) do
|> Stream.run()
end
- defp delete_activity(%{data: %{"type" => "Create", "object" => object}}, user) do
- {:ok, delete_data, _} = Builder.delete(user, object)
+ defp delete_activity(%{data: %{"type" => "Create", "object" => object}} = activity, user) do
+ with {_, %Object{}} <- {:find_object, Object.get_by_ap_id(object)},
+ {:ok, delete_data, _} <- Builder.delete(user, object) do
+ Pipeline.common_pipeline(delete_data, local: user.local)
+ else
+ {:find_object, nil} ->
+ # We have the create activity, but not the object, it was probably pruned.
+ # Insert a tombstone and try again
+ with {:ok, tombstone_data, _} <- Builder.tombstone(user.ap_id, object),
+ {:ok, _tombstone} <- Object.create(tombstone_data) do
+ delete_activity(activity, user)
+ end
- Pipeline.common_pipeline(delete_data, local: user.local)
+ e ->
+ Logger.error("Could not delete #{object} created by #{activity.data["ap_id"]}")
+ Logger.error("Error: #{inspect(e)}")
+ end
end
defp delete_activity(%{data: %{"type" => type}} = activity, user)
@@ -1913,7 +1925,7 @@ def get_ap_ids_by_nicknames(nicknames) do
defp put_password_hash(
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
) do
- change(changeset, password_hash: Pbkdf2.hashpwsalt(password))
+ change(changeset, password_hash: Pbkdf2.hash_pwd_salt(password))
end
defp put_password_hash(changeset), do: changeset
diff --git a/lib/pleroma/user/welcome_message.ex b/lib/pleroma/user/welcome_message.ex
index f0ac8ebae..f8f520285 100644
--- a/lib/pleroma/user/welcome_message.ex
+++ b/lib/pleroma/user/welcome_message.ex
@@ -10,8 +10,8 @@ def post_welcome_message_to_user(user) do
with %User{} = sender_user <- welcome_user(),
message when is_binary(message) <- welcome_message() do
CommonAPI.post(sender_user, %{
- "visibility" => "direct",
- "status" => "@#{user.nickname}\n#{message}"
+ visibility: "direct",
+ status: "@#{user.nickname}\n#{message}"
})
else
_ -> {:ok, nil}
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 4955243ab..d752f4f04 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -439,7 +439,6 @@ def block(blocker, blocked, activity_id \\ nil, local \\ true) do
end
defp do_block(blocker, blocked, activity_id, local) do
- outgoing_blocks = Config.get([:activitypub, :outgoing_blocks])
unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
if unfollow_blocked do
@@ -447,8 +446,7 @@ defp do_block(blocker, blocked, activity_id, local) do
if follow_activity, do: unfollow(blocker, blocked, nil, local)
end
- with true <- outgoing_blocks,
- block_data <- make_block_data(blocker, blocked, activity_id),
+ with block_data <- make_block_data(blocker, blocked, activity_id),
{:ok, activity} <- insert(block_data, local),
_ <- notify_and_stream(activity),
:ok <- maybe_federate(activity) do
diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex
index 922a444a9..4a247ad0c 100644
--- a/lib/pleroma/web/activity_pub/builder.ex
+++ b/lib/pleroma/web/activity_pub/builder.ex
@@ -62,6 +62,16 @@ def delete(actor, object_id) do
}, []}
end
+ @spec tombstone(String.t(), String.t()) :: {:ok, map(), keyword()}
+ def tombstone(actor, id) do
+ {:ok,
+ %{
+ "id" => id,
+ "actor" => actor,
+ "type" => "Tombstone"
+ }, []}
+ end
+
@spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
def like(actor, object) do
with {:ok, data, meta} <- object_action(actor, object) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex
index e06de3dff..f42c03510 100644
--- a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex
@@ -51,6 +51,7 @@ def add_deleted_activity_id(cng) do
Page
Question
Video
+ Tombstone
}
def validate_data(cng) do
cng
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index be7b57f13..80701bb63 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -14,7 +14,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.ObjectValidator
+ alias Pleroma.Web.ActivityPub.ObjectValidators.Types
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
@@ -590,6 +592,9 @@ def handle_incoming(
{:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
{:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do
+ User.update_follower_count(followed)
+ User.update_following_count(follower)
+
ActivityPub.accept(%{
to: follow_activity.data["to"],
type: "Accept",
@@ -599,7 +604,8 @@ def handle_incoming(
activity_id: id
})
else
- _e -> :error
+ _e ->
+ :error
end
end
@@ -720,6 +726,19 @@ def handle_incoming(
) do
with {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
+ else
+ {:error, {:validate_object, _}} = e ->
+ # Check if we have a create activity for this
+ with {:ok, object_id} <- Types.ObjectID.cast(data["object"]),
+ %Activity{data: %{"actor" => actor}} <-
+ Activity.create_by_object_ap_id(object_id) |> Repo.one(),
+ # We have one, insert a tombstone and retry
+ {:ok, tombstone_data, _} <- Builder.tombstone(actor, object_id),
+ {:ok, _tombstone} <- Object.create(tombstone_data) do
+ handle_incoming(data)
+ else
+ _ -> e
+ end
end
end
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 09b80fa57..f2375bcc4 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Ecto.Changeset
alias Ecto.UUID
alias Pleroma.Activity
+ alias Pleroma.Config
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
@@ -169,8 +170,11 @@ def create_context(context) do
Enqueues an activity for federation if it's local
"""
@spec maybe_federate(any()) :: :ok
- def maybe_federate(%Activity{local: true} = activity) do
- if Pleroma.Config.get!([:instance, :federating]) do
+ def maybe_federate(%Activity{local: true, data: %{"type" => type}} = activity) do
+ outgoing_blocks = Config.get([:activitypub, :outgoing_blocks])
+
+ with true <- Config.get!([:instance, :federating]),
+ true <- type != "Block" || outgoing_blocks do
Pleroma.Web.Federator.publish(activity)
end
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 4db9f4cac..9175b1904 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -844,15 +844,20 @@ def status_show(conn, %{"id" => id}) do
end
def status_update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do
+ params =
+ params
+ |> Map.take(["sensitive", "visibility"])
+ |> Map.new(fn {key, value} -> {String.to_existing_atom(key), value} end)
+
with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
- {:ok, sensitive} = Ecto.Type.cast(:boolean, params["sensitive"])
+ {:ok, sensitive} = Ecto.Type.cast(:boolean, params[:sensitive])
ModerationLog.insert_log(%{
action: "status_update",
actor: admin,
subject: activity,
sensitive: sensitive,
- visibility: params["visibility"]
+ visibility: params[:visibility]
})
conn
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
new file mode 100644
index 000000000..a6bb87560
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -0,0 +1,499 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
), "\n") |> Pleroma.HTML.strip_tags()
+ bio
+ |> String.replace(~r(
), "\n")
+ |> Pleroma.HTML.strip_tags()
+ |> HtmlEntities.decode()
end
defp prepare_user_bio(_), do: ""
@@ -334,7 +337,11 @@ defp maybe_put_role(data, %User{id: user_id} = user, %User{id: user_id}) do
defp maybe_put_role(data, _, _), do: data
defp maybe_put_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do
- Kernel.put_in(data, [:pleroma, :notification_settings], user.notification_settings)
+ Kernel.put_in(
+ data,
+ [:pleroma, :notification_settings],
+ Map.from_struct(user.notification_settings)
+ )
end
defp maybe_put_notification_settings(data, _, _), do: data
diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex
index e2ffd02d0..94e4595d8 100644
--- a/lib/pleroma/web/mastodon_api/websocket_handler.ex
+++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex
@@ -12,31 +12,19 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
@behaviour :cowboy_websocket
+ # Client ping period.
+ @tick :timer.seconds(30)
# Cowboy timeout period.
- @timeout :timer.seconds(30)
+ @timeout :timer.seconds(60)
# Hibernate every X messages
@hibernate_every 100
- @streams [
- "public",
- "public:local",
- "public:media",
- "public:local:media",
- "user",
- "user:notification",
- "direct",
- "list",
- "hashtag"
- ]
- @anonymous_streams ["public", "public:local", "hashtag"]
-
def init(%{qs: qs} = req, state) do
- with params <- :cow_qs.parse_qs(qs),
+ with params <- Enum.into(:cow_qs.parse_qs(qs), %{}),
sec_websocket <- :cowboy_req.header("sec-websocket-protocol", req, nil),
- access_token <- List.keyfind(params, "access_token", 0),
- {_, stream} <- List.keyfind(params, "stream", 0),
- {:ok, user} <- allow_request(stream, [access_token, sec_websocket]),
- topic when is_binary(topic) <- expand_topic(stream, params) do
+ access_token <- Map.get(params, "access_token"),
+ {:ok, user} <- authenticate_request(access_token, sec_websocket),
+ {:ok, topic} <- Streamer.get_topic(Map.get(params, "stream"), user, params) do
req =
if sec_websocket do
:cowboy_req.set_resp_header("sec-websocket-protocol", sec_websocket, req)
@@ -44,16 +32,17 @@ def init(%{qs: qs} = req, state) do
req
end
- {:cowboy_websocket, req, %{user: user, topic: topic, count: 0}, %{idle_timeout: @timeout}}
+ {:cowboy_websocket, req, %{user: user, topic: topic, count: 0, timer: nil},
+ %{idle_timeout: @timeout}}
else
- {:error, code} ->
- Logger.debug("#{__MODULE__} denied connection: #{inspect(code)} - #{inspect(req)}")
- {:ok, req} = :cowboy_req.reply(code, req)
+ {:error, :bad_topic} ->
+ Logger.debug("#{__MODULE__} bad topic #{inspect(req)}")
+ {:ok, req} = :cowboy_req.reply(404, req)
{:ok, req, state}
- error ->
- Logger.debug("#{__MODULE__} denied connection: #{inspect(error)} - #{inspect(req)}")
- {:ok, req} = :cowboy_req.reply(400, req)
+ {:error, :unauthorized} ->
+ Logger.debug("#{__MODULE__} authentication error: #{inspect(req)}")
+ {:ok, req} = :cowboy_req.reply(401, req)
{:ok, req, state}
end
end
@@ -66,11 +55,18 @@ def websocket_init(state) do
)
Streamer.add_socket(state.topic, state.user)
- {:ok, state}
+ {:ok, %{state | timer: timer()}}
+ end
+
+ # Client's Pong frame.
+ def websocket_handle(:pong, state) do
+ if state.timer, do: Process.cancel_timer(state.timer)
+ {:ok, %{state | timer: timer()}}
end
# We never receive messages.
- def websocket_handle(_frame, state) do
+ def websocket_handle(frame, state) do
+ Logger.error("#{__MODULE__} received frame: #{inspect(frame)}")
{:ok, state}
end
@@ -94,6 +90,14 @@ def websocket_info({:text, message}, state) do
end
end
+ # Ping tick. We don't re-queue a timer there, it is instead queued when :pong is received.
+ # As we hibernate there, reset the count to 0.
+ # If the client misses :pong, Cowboy will automatically timeout the connection after
+ # `@idle_timeout`.
+ def websocket_info(:tick, state) do
+ {:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
+ end
+
def terminate(reason, _req, state) do
Logger.debug(
"#{__MODULE__} terminating websocket connection for user #{
@@ -106,47 +110,24 @@ def terminate(reason, _req, state) do
end
# Public streams without authentication.
- defp allow_request(stream, [nil, nil]) when stream in @anonymous_streams do
+ defp authenticate_request(nil, nil) do
{:ok, nil}
end
# Authenticated streams.
- defp allow_request(stream, [access_token, sec_websocket]) when stream in @streams do
- token =
- with {"access_token", token} <- access_token do
- token
- else
- _ -> sec_websocket
- end
+ defp authenticate_request(access_token, sec_websocket) do
+ token = access_token || sec_websocket
with true <- is_bitstring(token),
%Token{user_id: user_id} <- Repo.get_by(Token, token: token),
user = %User{} <- User.get_cached_by_id(user_id) do
{:ok, user}
else
- _ -> {:error, 403}
+ _ -> {:error, :unauthorized}
end
end
- # Not authenticated.
- defp allow_request(stream, _) when stream in @streams, do: {:error, 403}
-
- # No matching stream.
- defp allow_request(_, _), do: {:error, 404}
-
- defp expand_topic("hashtag", params) do
- case List.keyfind(params, "tag", 0) do
- {_, tag} -> "hashtag:#{tag}"
- _ -> nil
- end
+ defp timer do
+ Process.send_after(self(), :tick, @tick)
end
-
- defp expand_topic("list", params) do
- case List.keyfind(params, "list", 0) do
- {_, list} -> "list:#{list}"
- _ -> nil
- end
- end
-
- defp expand_topic(topic, _), do: topic
end
diff --git a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex
index 1ed6ee521..0814b3bc3 100644
--- a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex
+++ b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.MongooseIM.MongooseIMController do
use Pleroma.Web, :controller
- alias Comeonin.Pbkdf2
alias Pleroma.Plugs.RateLimiter
alias Pleroma.Repo
alias Pleroma.User
@@ -28,7 +27,7 @@ def user_exists(conn, %{"user" => username}) do
def check_password(conn, %{"user" => username, "pass" => password}) do
with %User{password_hash: password_hash, deactivated: false} <-
Repo.get_by(User, nickname: username, local: true),
- true <- Pbkdf2.checkpw(password, password_hash) do
+ true <- Pbkdf2.verify_pass(password, password_hash) do
conn
|> json(true)
else
diff --git a/lib/pleroma/web/streamer/streamer.ex b/lib/pleroma/web/streamer/streamer.ex
index 5ad4aa936..49a400df7 100644
--- a/lib/pleroma/web/streamer/streamer.ex
+++ b/lib/pleroma/web/streamer/streamer.ex
@@ -21,12 +21,68 @@ defmodule Pleroma.Web.Streamer do
def registry, do: @registry
- def add_socket(topic, %User{} = user) do
- if should_env_send?(), do: Registry.register(@registry, user_topic(topic, user), true)
+ @public_streams ["public", "public:local", "public:media", "public:local:media"]
+ @user_streams ["user", "user:notification", "direct"]
+
+ @doc "Expands and authorizes a stream, and registers the process for streaming."
+ @spec get_topic_and_add_socket(stream :: String.t(), User.t() | nil, Map.t() | nil) ::
+ {:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized}
+ def get_topic_and_add_socket(stream, user, params \\ %{}) do
+ case get_topic(stream, user, params) do
+ {:ok, topic} -> add_socket(topic, user)
+ error -> error
+ end
end
- def add_socket(topic, _) do
- if should_env_send?(), do: Registry.register(@registry, topic, false)
+ @doc "Expand and authorizes a stream"
+ @spec get_topic(stream :: String.t(), User.t() | nil, Map.t()) ::
+ {:ok, topic :: String.t()} | {:error, :bad_topic}
+ def get_topic(stream, user, params \\ %{})
+
+ # Allow all public steams.
+ def get_topic(stream, _, _) when stream in @public_streams do
+ {:ok, stream}
+ end
+
+ # Allow all hashtags streams.
+ def get_topic("hashtag", _, %{"tag" => tag}) do
+ {:ok, "hashtag:" <> tag}
+ end
+
+ # Expand user streams.
+ def get_topic(stream, %User{} = user, _) when stream in @user_streams do
+ {:ok, stream <> ":" <> to_string(user.id)}
+ end
+
+ def get_topic(stream, _, _) when stream in @user_streams do
+ {:error, :unauthorized}
+ end
+
+ # List streams.
+ def get_topic("list", %User{} = user, %{"list" => id}) do
+ if Pleroma.List.get(id, user) do
+ {:ok, "list:" <> to_string(id)}
+ else
+ {:error, :bad_topic}
+ end
+ end
+
+ def get_topic("list", _, _) do
+ {:error, :unauthorized}
+ end
+
+ def get_topic(_, _, _) do
+ {:error, :bad_topic}
+ end
+
+ @doc "Registers the process for streaming. Use `get_topic/3` to get the full authorized topic."
+ def add_socket(topic, user) do
+ if should_env_send?() do
+ auth? = if user, do: true
+ Registry.register(@registry, topic, auth?)
+ end
+
+ {:ok, topic}
end
def remove_socket(topic) do
@@ -231,13 +287,4 @@ def should_env_send?, do: false
true ->
def should_env_send?, do: true
end
-
- defp user_topic(topic, user)
- when topic in ~w[user user:notification direct] do
- "#{topic}:#{user.id}"
- end
-
- defp user_topic(topic, _) do
- topic
- end
end
diff --git a/lib/pleroma/workers/scheduled_activity_worker.ex b/lib/pleroma/workers/scheduled_activity_worker.ex
index 8905f4ad0..97d1efbfb 100644
--- a/lib/pleroma/workers/scheduled_activity_worker.ex
+++ b/lib/pleroma/workers/scheduled_activity_worker.ex
@@ -30,6 +30,8 @@ def perform(%{"activity_id" => activity_id}, _job) do
end
defp post_activity(%ScheduledActivity{user_id: user_id, params: params} = scheduled_activity) do
+ params = Map.new(params, fn {key, value} -> {String.to_existing_atom(key), value} end)
+
with {:delete, {:ok, _}} <- {:delete, ScheduledActivity.delete(scheduled_activity)},
{:user, %User{} = user} <- {:user, User.get_cached_by_id(user_id)},
{:post, {:ok, _}} <- {:post, CommonAPI.post(user, params)} do
diff --git a/mix.exs b/mix.exs
index 6d65e18d4..0186d291f 100644
--- a/mix.exs
+++ b/mix.exs
@@ -36,7 +36,7 @@ def project do
releases: [
pleroma: [
include_executables_for: [:unix],
- applications: [ex_syslogger: :load, syslog: :load],
+ applications: [ex_syslogger: :load, syslog: :load, eldap: :transient],
steps: [:assemble, &put_otp_version/1, ©_files/1, ©_nginx_config/1]
]
]
@@ -72,7 +72,14 @@ def copy_nginx_config(%{path: target_path} = release) do
def application do
[
mod: {Pleroma.Application, []},
- extra_applications: [:logger, :runtime_tools, :comeonin, :quack, :fast_sanitize, :ssl],
+ extra_applications: [
+ :logger,
+ :runtime_tools,
+ :comeonin,
+ :quack,
+ :fast_sanitize,
+ :ssl
+ ],
included_applications: [:ex_syslogger]
]
end
@@ -119,8 +126,7 @@ defp deps do
{:postgrex, ">= 0.13.5"},
{:oban, "~> 1.2"},
{:gettext, "~> 0.15"},
- {:comeonin, "~> 4.1.1"},
- {:pbkdf2_elixir, "~> 0.12.3"},
+ {:pbkdf2_elixir, "~> 1.0"},
{:trailing_format_plug, "~> 0.0.7"},
{:fast_sanitize, "~> 0.1"},
{:html_entities, "~> 0.5", override: true},
@@ -192,7 +198,7 @@ defp deps do
{:restarter, path: "./restarter"},
{:open_api_spex,
git: "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git",
- ref: "b862ebd78de0df95875cf46feb6e9607130dc2a8"}
+ ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"}
] ++ oauth_deps()
end
diff --git a/mix.lock b/mix.lock
index c400202b7..62fe35146 100644
--- a/mix.lock
+++ b/mix.lock
@@ -13,7 +13,7 @@
"castore": {:hex, :castore, "0.1.5", "591c763a637af2cc468a72f006878584bc6c306f8d111ef8ba1d4c10e0684010", [:mix], [], "hexpm", "6db356b2bc6cc22561e051ff545c20ad064af57647e436650aa24d7d06cd941a"},
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
- "comeonin": {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm", "d8700a0ca4dbb616c22c9b3f6dd539d88deaafec3efe66869d6370c9a559b3e9"},
+ "comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"},
"cors_plug": {:hex, :cors_plug, "1.5.2", "72df63c87e4f94112f458ce9d25800900cc88608c1078f0e4faddf20933eda6e", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9af027d20dc12dd0c4345a6b87247e0c62965871feea0bfecf9764648b02cc69"},
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "04fd8c6a39edc6aaa9c26123009200fc61f92a3a94f3178c527b70b767c6e605"},
@@ -74,9 +74,9 @@
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
"oban": {:hex, :oban, "1.2.0", "7cca94d341be43d220571e28f69131c4afc21095b25257397f50973d3fc59b07", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ba5f8b3f7d76967b3e23cf8014f6a13e4ccb33431e4808f036709a7f822362ee"},
- "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "b862ebd78de0df95875cf46feb6e9607130dc2a8", [ref: "b862ebd78de0df95875cf46feb6e9607130dc2a8"]},
+ "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "f296ac0924ba3cf79c7a588c4c252889df4c2edd", [ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"]},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
- "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.4", "8dd29ed783f2e12195d7e0a4640effc0a7c37e6537da491f1db01839eee6d053", [:mix], [], "hexpm", "595d09db74cb093b1903381c9de423276a931a2480a46a1a5dc7f932a2a6375b"},
+ "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"},
"phoenix": {:hex, :phoenix, "1.4.13", "67271ad69b51f3719354604f4a3f968f83aa61c19199343656c9caee057ff3b8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ab765a0feddb81fc62e2116c827b5f068df85159c162bee760745276ad7ddc1b"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"},
"phoenix_html": {:hex, :phoenix_html, "2.14.0", "d8c6bc28acc8e65f8ea0080ee05aa13d912c8758699283b8d3427b655aabe284", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "b0bb30eda478a06dbfbe96728061a93833db3861a49ccb516f839ecb08493fbb"},
diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po
deleted file mode 100644
index 25a2f73e4..000000000
--- a/priv/gettext/en/LC_MESSAGES/errors.po
+++ /dev/null
@@ -1,465 +0,0 @@
-## `msgid`s in this file come from POT (.pot) files.
-##
-## Do not add, change, or remove `msgid`s manually here as
-## they're tied to the ones in the corresponding POT file
-## (with the same domain).
-##
-## Use `mix gettext.extract --merge` or `mix gettext.merge`
-## to merge POT files into PO files.
-msgid ""
-msgstr ""
-"Language: en\n"
-
-## From Ecto.Changeset.cast/4
-msgid "can't be blank"
-msgstr ""
-
-## From Ecto.Changeset.unique_constraint/3
-msgid "has already been taken"
-msgstr ""
-
-## From Ecto.Changeset.put_change/3
-msgid "is invalid"
-msgstr ""
-
-## From Ecto.Changeset.validate_format/3
-msgid "has invalid format"
-msgstr ""
-
-## From Ecto.Changeset.validate_subset/3
-msgid "has an invalid entry"
-msgstr ""
-
-## From Ecto.Changeset.validate_exclusion/3
-msgid "is reserved"
-msgstr ""
-
-## From Ecto.Changeset.validate_confirmation/3
-msgid "does not match confirmation"
-msgstr ""
-
-## From Ecto.Changeset.no_assoc_constraint/3
-msgid "is still associated with this entry"
-msgstr ""
-
-msgid "are still associated with this entry"
-msgstr ""
-
-## From Ecto.Changeset.validate_length/3
-msgid "should be %{count} character(s)"
-msgid_plural "should be %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have %{count} item(s)"
-msgid_plural "should have %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should be at least %{count} character(s)"
-msgid_plural "should be at least %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have at least %{count} item(s)"
-msgid_plural "should have at least %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should be at most %{count} character(s)"
-msgid_plural "should be at most %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have at most %{count} item(s)"
-msgid_plural "should have at most %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-## From Ecto.Changeset.validate_number/3
-msgid "must be less than %{number}"
-msgstr ""
-
-msgid "must be greater than %{number}"
-msgstr ""
-
-msgid "must be less than or equal to %{number}"
-msgstr ""
-
-msgid "must be greater than or equal to %{number}"
-msgstr ""
-
-msgid "must be equal to %{number}"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:381
-msgid "Account not found"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:153
-msgid "Already voted"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:263
-msgid "Bad request"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:254
-msgid "Can't delete object"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:569
-msgid "Can't delete this post"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1731
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1737
-msgid "Can't display this activity"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:195
-msgid "Can't find user"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1148
-msgid "Can't get favorites"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:263
-msgid "Can't like object"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:518
-msgid "Cannot post an empty status without attachments"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:461
-msgid "Comment must be up to %{max_size} characters"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/admin_api/config.ex:63
-msgid "Config with params %{params} not found"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:78
-msgid "Could not delete"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:110
-msgid "Could not favorite"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:310
-msgid "Could not pin"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:89
-msgid "Could not repeat"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:120
-msgid "Could not unfavorite"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:327
-msgid "Could not unpin"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:99
-msgid "Could not unrepeat"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:392
-msgid "Could not update state"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1271
-msgid "Error."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/captcha/kocaptcha.ex:36
-msgid "Invalid CAPTCHA"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1700
-#: lib/pleroma/web/oauth/oauth_controller.ex:465
-msgid "Invalid credentials"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/ensure_authenticated_plug.ex:20
-msgid "Invalid credentials."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:154
-msgid "Invalid indices"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:411
-msgid "Invalid parameters"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:377
-msgid "Invalid password."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:163
-msgid "Invalid request"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/captcha/kocaptcha.ex:16
-msgid "Kocaptcha service unavailable"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1696
-msgid "Missing parameters"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:496
-msgid "No such conversation"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:163
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:206
-msgid "No such permission_group"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/uploaded_media.ex:69
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:311
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:399
-#: lib/pleroma/web/mastodon_api/subscription_controller.ex:63
-#: lib/pleroma/web/ostatus/ostatus_controller.ex:248
-msgid "Not found"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:152
-msgid "Poll's author can't vote"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:443
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:444
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:473
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:476
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1180
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1564
-msgid "Record not found"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:417
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1570
-#: lib/pleroma/web/mastodon_api/subscription_controller.ex:69
-#: lib/pleroma/web/ostatus/ostatus_controller.ex:252
-msgid "Something went wrong"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:253
-msgid "The message visibility must be direct"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:521
-msgid "The status is over the character limit"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:27
-msgid "This resource requires authentication."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/rate_limiter.ex:89
-msgid "Throttled"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:155
-msgid "Too many choices"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:268
-msgid "Unhandled activity type"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/user_is_admin_plug.ex:20
-msgid "User is not admin."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:380
-msgid "Valid `account_id` required"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:185
-msgid "You can't revoke your own admin status."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:216
-msgid "Your account is currently disabled"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:158
-#: lib/pleroma/web/oauth/oauth_controller.ex:213
-msgid "Your login is missing a confirmed e-mail address"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:221
-msgid "can't read inbox of %{nickname} as %{as_nickname}"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:297
-msgid "can't update outbox of %{nickname} as %{as_nickname}"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:335
-msgid "conversation is already muted"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:192
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:317
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1196
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1247
-msgid "error"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:789
-msgid "mascots can only be images"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:34
-msgid "not found"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:298
-msgid "Bad OAuth request."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/captcha/captcha.ex:92
-msgid "CAPTCHA already used"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/captcha/captcha.ex:89
-msgid "CAPTCHA expired"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/uploaded_media.ex:50
-msgid "Failed"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:314
-msgid "Failed to authenticate: %{message}."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:345
-msgid "Failed to set up user account."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/oauth_scopes_plug.ex:37
-msgid "Insufficient permissions: %{permissions}."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/plugs/uploaded_media.ex:89
-msgid "Internal Error"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/fallback_controller.ex:22
-#: lib/pleroma/web/oauth/fallback_controller.ex:29
-msgid "Invalid Username/Password"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/captcha/captcha.ex:107
-msgid "Invalid answer data"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:204
-msgid "Nodeinfo schema version not handled"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:145
-msgid "This action is outside the authorized scopes"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/fallback_controller.ex:14
-msgid "Unknown error, please check the details and try again."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:93
-#: lib/pleroma/web/oauth/oauth_controller.ex:131
-msgid "Unlisted redirect_uri."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:294
-msgid "Unsupported OAuth provider: %{provider}."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/uploaders/uploader.ex:71
-msgid "Uploader callback timeout"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/uploader_controller.ex:11
-#: lib/pleroma/web/uploader_controller.ex:23
-msgid "bad request"
-msgstr ""
diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot
index 2fd9c42e3..0e1cf37eb 100644
--- a/priv/gettext/errors.pot
+++ b/priv/gettext/errors.pot
@@ -90,326 +90,312 @@ msgid "must be equal to %{number}"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:381
+#: lib/pleroma/web/common_api/common_api.ex:421
msgid "Account not found"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:153
+#: lib/pleroma/web/common_api/common_api.ex:249
msgid "Already voted"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:263
+#: lib/pleroma/web/oauth/oauth_controller.ex:360
msgid "Bad request"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:254
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:425
msgid "Can't delete object"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:569
+#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:196
msgid "Can't delete this post"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1731
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1737
+#: lib/pleroma/web/controller_helper.ex:95
+#: lib/pleroma/web/controller_helper.ex:101
msgid "Can't display this activity"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:195
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:227
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:254
msgid "Can't find user"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1148
+#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:114
msgid "Can't get favorites"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:263
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:437
msgid "Can't like object"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:518
+#: lib/pleroma/web/common_api/utils.ex:556
msgid "Cannot post an empty status without attachments"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:461
+#: lib/pleroma/web/common_api/utils.ex:504
msgid "Comment must be up to %{max_size} characters"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/admin_api/config.ex:63
+#: lib/pleroma/config/config_db.ex:222
msgid "Config with params %{params} not found"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:78
+#: lib/pleroma/web/common_api/common_api.ex:95
msgid "Could not delete"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:110
+#: lib/pleroma/web/common_api/common_api.ex:141
msgid "Could not favorite"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:310
+#: lib/pleroma/web/common_api/common_api.ex:370
msgid "Could not pin"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:89
+#: lib/pleroma/web/common_api/common_api.ex:112
msgid "Could not repeat"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:120
+#: lib/pleroma/web/common_api/common_api.ex:188
msgid "Could not unfavorite"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:327
+#: lib/pleroma/web/common_api/common_api.ex:380
msgid "Could not unpin"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:99
+#: lib/pleroma/web/common_api/common_api.ex:126
msgid "Could not unrepeat"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:392
+#: lib/pleroma/web/common_api/common_api.ex:428
+#: lib/pleroma/web/common_api/common_api.ex:437
msgid "Could not update state"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1271
+#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:202
msgid "Error."
msgstr ""
#, elixir-format
-#: lib/pleroma/captcha/kocaptcha.ex:36
+#: lib/pleroma/web/twitter_api/twitter_api.ex:106
msgid "Invalid CAPTCHA"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1700
-#: lib/pleroma/web/oauth/oauth_controller.ex:465
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:117
+#: lib/pleroma/web/oauth/oauth_controller.ex:569
msgid "Invalid credentials"
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/ensure_authenticated_plug.ex:20
+#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38
msgid "Invalid credentials."
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:154
+#: lib/pleroma/web/common_api/common_api.ex:265
msgid "Invalid indices"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:411
+#: lib/pleroma/web/admin_api/admin_api_controller.ex:1147
msgid "Invalid parameters"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:377
+#: lib/pleroma/web/common_api/utils.ex:411
msgid "Invalid password."
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:163
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:187
msgid "Invalid request"
msgstr ""
#, elixir-format
-#: lib/pleroma/captcha/kocaptcha.ex:16
+#: lib/pleroma/web/twitter_api/twitter_api.ex:109
msgid "Kocaptcha service unavailable"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1696
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:113
msgid "Missing parameters"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:496
+#: lib/pleroma/web/common_api/utils.ex:540
msgid "No such conversation"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:163
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:206
+#: lib/pleroma/web/admin_api/admin_api_controller.ex:439
+#: lib/pleroma/web/admin_api/admin_api_controller.ex:465 lib/pleroma/web/admin_api/admin_api_controller.ex:507
msgid "No such permission_group"
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/uploaded_media.ex:69
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:311
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:399
-#: lib/pleroma/web/mastodon_api/subscription_controller.ex:63
-#: lib/pleroma/web/ostatus/ostatus_controller.ex:248
+#: lib/pleroma/plugs/uploaded_media.ex:74
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:485 lib/pleroma/web/admin_api/admin_api_controller.ex:1135
+#: lib/pleroma/web/feed/user_controller.ex:73 lib/pleroma/web/ostatus/ostatus_controller.ex:143
msgid "Not found"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:152
+#: lib/pleroma/web/common_api/common_api.ex:241
msgid "Poll's author can't vote"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:443
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:444
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:473
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:476
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1180
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1564
+#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
+#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49
+#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:290
+#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71
msgid "Record not found"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:417
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1570
-#: lib/pleroma/web/mastodon_api/subscription_controller.ex:69
-#: lib/pleroma/web/ostatus/ostatus_controller.ex:252
+#: lib/pleroma/web/admin_api/admin_api_controller.ex:1153
+#: lib/pleroma/web/feed/user_controller.ex:79 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:32
+#: lib/pleroma/web/ostatus/ostatus_controller.ex:149
msgid "Something went wrong"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:253
+#: lib/pleroma/web/common_api/activity_draft.ex:107
msgid "The message visibility must be direct"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/utils.ex:521
+#: lib/pleroma/web/common_api/utils.ex:566
msgid "The status is over the character limit"
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:27
+#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
msgid "This resource requires authentication."
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/rate_limiter.ex:89
+#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
msgid "Throttled"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:155
+#: lib/pleroma/web/common_api/common_api.ex:266
msgid "Too many choices"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:268
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:442
msgid "Unhandled activity type"
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/user_is_admin_plug.ex:20
-msgid "User is not admin."
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:380
-msgid "Valid `account_id` required"
-msgstr ""
-
-#, elixir-format
-#: lib/pleroma/web/admin_api/admin_api_controller.ex:185
+#: lib/pleroma/web/admin_api/admin_api_controller.ex:536
msgid "You can't revoke your own admin status."
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:216
+#: lib/pleroma/web/oauth/oauth_controller.ex:218
+#: lib/pleroma/web/oauth/oauth_controller.ex:309
msgid "Your account is currently disabled"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:158
-#: lib/pleroma/web/oauth/oauth_controller.ex:213
+#: lib/pleroma/web/oauth/oauth_controller.ex:180
+#: lib/pleroma/web/oauth/oauth_controller.ex:332
msgid "Your login is missing a confirmed e-mail address"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:221
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:389
msgid "can't read inbox of %{nickname} as %{as_nickname}"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:297
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:472
msgid "can't update outbox of %{nickname} as %{as_nickname}"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/common_api/common_api.ex:335
+#: lib/pleroma/web/common_api/common_api.ex:388
msgid "conversation is already muted"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:192
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:317
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1196
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1247
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:316
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:491
msgid "error"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:789
+#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:29
msgid "mascots can only be images"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:34
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:60
msgid "not found"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:298
+#: lib/pleroma/web/oauth/oauth_controller.ex:395
msgid "Bad OAuth request."
msgstr ""
#, elixir-format
-#: lib/pleroma/captcha/captcha.ex:92
+#: lib/pleroma/web/twitter_api/twitter_api.ex:115
msgid "CAPTCHA already used"
msgstr ""
#, elixir-format
-#: lib/pleroma/captcha/captcha.ex:89
+#: lib/pleroma/web/twitter_api/twitter_api.ex:112
msgid "CAPTCHA expired"
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/uploaded_media.ex:50
+#: lib/pleroma/plugs/uploaded_media.ex:55
msgid "Failed"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:314
+#: lib/pleroma/web/oauth/oauth_controller.ex:411
msgid "Failed to authenticate: %{message}."
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:345
+#: lib/pleroma/web/oauth/oauth_controller.ex:442
msgid "Failed to set up user account."
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/oauth_scopes_plug.ex:37
+#: lib/pleroma/plugs/oauth_scopes_plug.ex:38
msgid "Insufficient permissions: %{permissions}."
msgstr ""
#, elixir-format
-#: lib/pleroma/plugs/uploaded_media.ex:89
+#: lib/pleroma/plugs/uploaded_media.ex:94
msgid "Internal Error"
msgstr ""
@@ -420,17 +406,17 @@ msgid "Invalid Username/Password"
msgstr ""
#, elixir-format
-#: lib/pleroma/captcha/captcha.ex:107
+#: lib/pleroma/web/twitter_api/twitter_api.ex:118
msgid "Invalid answer data"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:204
+#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:128
msgid "Nodeinfo schema version not handled"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:145
+#: lib/pleroma/web/oauth/oauth_controller.ex:169
msgid "This action is outside the authorized scopes"
msgstr ""
@@ -440,23 +426,139 @@ msgid "Unknown error, please check the details and try again."
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:93
-#: lib/pleroma/web/oauth/oauth_controller.ex:131
+#: lib/pleroma/web/oauth/oauth_controller.ex:116
+#: lib/pleroma/web/oauth/oauth_controller.ex:155
msgid "Unlisted redirect_uri."
msgstr ""
#, elixir-format
-#: lib/pleroma/web/oauth/oauth_controller.ex:294
+#: lib/pleroma/web/oauth/oauth_controller.ex:391
msgid "Unsupported OAuth provider: %{provider}."
msgstr ""
#, elixir-format
-#: lib/pleroma/uploaders/uploader.ex:71
+#: lib/pleroma/uploaders/uploader.ex:72
msgid "Uploader callback timeout"
msgstr ""
#, elixir-format
-#: lib/pleroma/web/uploader_controller.ex:11
#: lib/pleroma/web/uploader_controller.ex:23
msgid "bad request"
msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/twitter_api/twitter_api.ex:103
+msgid "CAPTCHA Error"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/common_api/common_api.ex:200
+msgid "Could not add reaction emoji"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/common_api/common_api.ex:211
+msgid "Could not remove reaction emoji"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/twitter_api/twitter_api.ex:129
+msgid "Invalid CAPTCHA (Missing parameter: %{name})"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
+msgid "List not found"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:124
+msgid "Missing parameter: %{name}"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/oauth/oauth_controller.ex:207
+#: lib/pleroma/web/oauth/oauth_controller.ex:322
+msgid "Password reset is required"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/tests/auth_test_controller.ex:9
+#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/admin_api_controller.ex:6
+#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/fallback_redirect_controller.ex:6
+#: lib/pleroma/web/feed/tag_controller.ex:6 lib/pleroma/web/feed/user_controller.ex:6
+#: lib/pleroma/web/mailer/subscription_controller.ex:2 lib/pleroma/web/masto_fe_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6
+#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 lib/pleroma/web/media_proxy/media_proxy_controller.ex:6
+#: lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6
+#: lib/pleroma/web/oauth/fallback_controller.ex:6 lib/pleroma/web/oauth/mfa_controller.ex:10
+#: lib/pleroma/web/oauth/oauth_controller.ex:6 lib/pleroma/web/ostatus/ostatus_controller.ex:6
+#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:2
+#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex:6
+#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6
+#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6
+#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
+#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6
+#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6
+msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
+msgid "Two-factor authentication enabled, you must use a access token."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:210
+msgid "Unexpected error occurred while adding file to pack."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:138
+msgid "Unexpected error occurred while creating pack."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:278
+msgid "Unexpected error occurred while removing file from pack."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:250
+msgid "Unexpected error occurred while updating file in pack."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:179
+msgid "Unexpected error occurred while updating pack metadata."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/plugs/user_is_admin_plug.ex:40
+msgid "User is not an admin or OAuth admin scope is not granted."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
+msgid "Web push subscription is disabled on this Pleroma instance"
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/admin_api/admin_api_controller.ex:502
+msgid "You can't revoke your own admin/moderator status."
+msgstr ""
+
+#, elixir-format
+#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:105
+msgid "authorization required for timeline view"
+msgstr ""
diff --git a/priv/repo/migrations/20200415181818_update_markers.exs b/priv/repo/migrations/20200415181818_update_markers.exs
index 976363565..bb9d8e860 100644
--- a/priv/repo/migrations/20200415181818_update_markers.exs
+++ b/priv/repo/migrations/20200415181818_update_markers.exs
@@ -32,9 +32,13 @@ defp update_markers do
|> Map.put_new(:updated_at, now)
end)
- Repo.insert_all("markers", markers_attrs,
- on_conflict: {:replace, [:last_read_id]},
- conflict_target: [:user_id, :timeline]
- )
+ markers_attrs
+ |> Enum.chunk_every(1000)
+ |> Enum.each(fn markers_attrs_chunked ->
+ Repo.insert_all("markers", markers_attrs_chunked,
+ on_conflict: {:replace, [:last_read_id]},
+ conflict_target: [:user_id, :timeline]
+ )
+ end)
end
end
diff --git a/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs b/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs
index 11d9a70ba..2adc38186 100644
--- a/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs
+++ b/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs
@@ -30,7 +30,7 @@ def change do
Repo,
"select distinct unnest(nonexistent_locals.recipients) from activities, lateral (select array_agg(recipient) as recipients from unnest(activities.recipients) as recipient where recipient similar to '#{
instance_uri
- }/users/[A-Za-z0-9]*' and not(recipient in (select ap_id from users where local = true))) nonexistent_locals;",
+ }/users/[A-Za-z0-9]*' and not(recipient in (select ap_id from users))) nonexistent_locals;",
[],
timeout: :infinity
)
diff --git a/priv/static/index.html b/priv/static/index.html
index 4fac5c100..b37cbaa67 100644
--- a/priv/static/index.html
+++ b/priv/static/index.html
@@ -1 +1 @@
-
henlo from my Psion netBook
message sent from my Psion netBook
" end + test "it works for incoming honk announces" do + _user = insert(:user, ap_id: "https://honktest/u/test", local: false) + other_user = insert(:user) + {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"}) + + announce = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "actor" => "https://honktest/u/test", + "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx", + "object" => post.data["object"], + "published" => "2019-06-25T19:33:58Z", + "to" => "https://www.w3.org/ns/activitystreams#Public", + "type" => "Announce" + } + + {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(announce) + end + test "it works for incoming announces with actor being inlined (kroeg)" do data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!() @@ -344,7 +362,7 @@ test "it works for incoming announces" do test "it works for incoming announces with an existing activity" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) + {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) data = File.read!("test/fixtures/mastodon-announce.json") @@ -394,7 +412,7 @@ test "it rejects incoming announces with an inlined activity from another origin test "it does not clobber the addressing on announce activities" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) + {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) data = File.read!("test/fixtures/mastodon-announce.json") @@ -480,7 +498,7 @@ test "it strips internal likes" do test "it strips internal reactions" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"}) + {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"}) {:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "📢") %{object: object} = Activity.get_by_id_with_object(activity.id) @@ -815,6 +833,12 @@ test "it works for incoming accepts which are referenced by IRI only" do follower = User.get_cached_by_id(follower.id) assert User.following?(follower, followed) == true + + follower = User.get_by_id(follower.id) + assert follower.following_count == 1 + + followed = User.get_by_id(followed.id) + assert followed.follower_count == 1 end test "it fails for incoming accepts which cannot be correlated" do @@ -972,7 +996,7 @@ test "it accepts Flag activities" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "test post"}) + {:ok, activity} = CommonAPI.post(user, %{status: "test post"}) object = Object.normalize(activity) note_obj = %{ @@ -1116,13 +1140,13 @@ test "does NOT schedule background fetching of `replies` beyond max thread depth setup do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "post1"}) + {:ok, activity} = CommonAPI.post(user, %{status: "post1"}) {:ok, reply1} = - CommonAPI.post(user, %{"status" => "reply1", "in_reply_to_status_id" => activity.id}) + CommonAPI.post(user, %{status: "reply1", in_reply_to_status_id: activity.id}) {:ok, reply2} = - CommonAPI.post(user, %{"status" => "reply2", "in_reply_to_status_id" => activity.id}) + CommonAPI.post(user, %{status: "reply2", in_reply_to_status_id: activity.id}) replies_uris = Enum.map([reply1, reply2], fn a -> a.object.data["id"] end) @@ -1162,7 +1186,7 @@ test "does NOT schedule background fetching of `replies` beyond max thread depth test "it inlines private announced objects" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "hey", "visibility" => "private"}) + {:ok, activity} = CommonAPI.post(user, %{status: "hey", visibility: "private"}) {:ok, announce_activity, _} = CommonAPI.repeat(activity.id, user) @@ -1177,7 +1201,7 @@ test "it turns mentions into tags" do other_user = insert(:user) {:ok, activity} = - CommonAPI.post(user, %{"status" => "hey, @#{other_user.nickname}, how are ya? #2hu"}) + CommonAPI.post(user, %{status: "hey, @#{other_user.nickname}, how are ya? #2hu"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) object = modified["object"] @@ -1201,7 +1225,7 @@ test "it turns mentions into tags" do test "it adds the sensitive property" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "#nsfw hey"}) + {:ok, activity} = CommonAPI.post(user, %{status: "#nsfw hey"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) assert modified["object"]["sensitive"] @@ -1210,7 +1234,7 @@ test "it adds the sensitive property" do test "it adds the json-ld context and the conversation property" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) + {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) assert modified["@context"] == @@ -1222,7 +1246,7 @@ test "it adds the json-ld context and the conversation property" do test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"}) + {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) assert modified["object"]["actor"] == modified["object"]["attributedTo"] @@ -1231,7 +1255,7 @@ test "it sets the 'attributedTo' property to the actor of the object if it doesn test "it strips internal hashtag data" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu"}) + {:ok, activity} = CommonAPI.post(user, %{status: "#2hu"}) expected_tag = %{ "href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu", @@ -1247,7 +1271,7 @@ test "it strips internal hashtag data" do test "it strips internal fields" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu :firefox:"}) + {:ok, activity} = CommonAPI.post(user, %{status: "#2hu :firefox:"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) @@ -1279,14 +1303,13 @@ test "the directMessage flag is present" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu :moominmamma:"}) + {:ok, activity} = CommonAPI.post(user, %{status: "2hu :moominmamma:"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) assert modified["directMessage"] == false - {:ok, activity} = - CommonAPI.post(user, %{"status" => "@#{other_user.nickname} :moominmamma:"}) + {:ok, activity} = CommonAPI.post(user, %{status: "@#{other_user.nickname} :moominmamma:"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) @@ -1294,8 +1317,8 @@ test "the directMessage flag is present" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "@#{other_user.nickname} :moominmamma:", - "visibility" => "direct" + status: "@#{other_user.nickname} :moominmamma:", + visibility: "direct" }) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) @@ -1307,8 +1330,7 @@ test "it strips BCC field" do user = insert(:user) {:ok, list} = Pleroma.List.create("foo", user) - {:ok, activity} = - CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"}) + {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"}) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) @@ -1343,8 +1365,8 @@ test "it upgrades a user to activitypub" do user_two = insert(:user) Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept) - {:ok, activity} = CommonAPI.post(user, %{"status" => "test"}) - {:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"}) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) + {:ok, unrelated_activity} = CommonAPI.post(user_two, %{status: "test"}) assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients user = User.get_cached_by_id(user.id) @@ -1510,8 +1532,8 @@ test "Rewrites Answers to Notes" do {:ok, poll_activity} = CommonAPI.post(user, %{ - "status" => "suya...", - "poll" => %{"options" => ["suya", "suya.", "suya.."], "expires_in" => 10} + status: "suya...", + poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} }) poll_object = Object.normalize(poll_activity) @@ -1854,28 +1876,27 @@ test "returns unmodified object if activity doesn't have self-replies" do test "sets `replies` collection with a limited number of self-replies" do [user, another_user] = insert_list(2, :user) - {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{"status" => "1"}) + {:ok, %{id: id1} = activity} = CommonAPI.post(user, %{status: "1"}) {:ok, %{id: id2} = self_reply1} = - CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => id1}) + CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: id1}) {:ok, self_reply2} = - CommonAPI.post(user, %{"status" => "self-reply 2", "in_reply_to_status_id" => id1}) + CommonAPI.post(user, %{status: "self-reply 2", in_reply_to_status_id: id1}) # Assuming to _not_ be present in `replies` due to :note_replies_output_limit is set to 2 - {:ok, _} = - CommonAPI.post(user, %{"status" => "self-reply 3", "in_reply_to_status_id" => id1}) + {:ok, _} = CommonAPI.post(user, %{status: "self-reply 3", in_reply_to_status_id: id1}) {:ok, _} = CommonAPI.post(user, %{ - "status" => "self-reply to self-reply", - "in_reply_to_status_id" => id2 + status: "self-reply to self-reply", + in_reply_to_status_id: id2 }) {:ok, _} = CommonAPI.post(another_user, %{ - "status" => "another user's reply", - "in_reply_to_status_id" => id1 + status: "another user's reply", + in_reply_to_status_id: id1 }) object = Object.normalize(activity) diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index b8d811c73..9e0a0f1c4 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -120,7 +120,7 @@ test "addresses actor's follower address if the activity is public", %{ {:ok, activity} = CommonAPI.post(user, %{ - "status" => + status: "hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?" }) @@ -139,8 +139,8 @@ test "does not adress actor's follower address if the activity is not public", % {:ok, activity} = CommonAPI.post(user, %{ - "status" => "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!", - "visibility" => "private" + status: "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!", + visibility: "private" }) %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil) @@ -168,11 +168,11 @@ test "fetches existing votes" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "How do I pronounce LaTeX?", - "poll" => %{ - "options" => ["laytekh", "lahtekh", "latex"], - "expires_in" => 20, - "multiple" => true + status: "How do I pronounce LaTeX?", + poll: %{ + options: ["laytekh", "lahtekh", "latex"], + expires_in: 20, + multiple: true } }) @@ -187,10 +187,10 @@ test "fetches only Create activities" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "Are we living in a society?", - "poll" => %{ - "options" => ["yes", "no"], - "expires_in" => 20 + status: "Are we living in a society?", + poll: %{ + options: ["yes", "no"], + expires_in: 20 } }) @@ -469,7 +469,7 @@ test "returns empty map when params is invalid" do test "returns map with Flag object" do reporter = insert(:user) target_account = insert(:user) - {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"}) + {:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"}) context = Utils.generate_context_id() content = "foobar" diff --git a/test/web/activity_pub/views/object_view_test.exs b/test/web/activity_pub/views/object_view_test.exs index 6c006206b..43f0617f0 100644 --- a/test/web/activity_pub/views/object_view_test.exs +++ b/test/web/activity_pub/views/object_view_test.exs @@ -44,7 +44,7 @@ test "renders `replies` collection for a note activity" do activity = insert(:note_activity, user: user) {:ok, self_reply1} = - CommonAPI.post(user, %{"status" => "self-reply 1", "in_reply_to_status_id" => activity.id}) + CommonAPI.post(user, %{status: "self-reply 1", in_reply_to_status_id: activity.id}) replies_uris = [self_reply1.object.data["id"]] result = ObjectView.render("object.json", %{object: refresh_record(activity)}) diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index 8d00893a5..20b0f223c 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -164,7 +164,7 @@ test "activity collection page aginates correctly" do posts = for i <- 0..25 do - {:ok, activity} = CommonAPI.post(user, %{"status" => "post #{i}"}) + {:ok, activity} = CommonAPI.post(user, %{status: "post #{i}"}) activity end diff --git a/test/web/activity_pub/visibilty_test.exs b/test/web/activity_pub/visibilty_test.exs index 5b91630d4..8e9354c65 100644 --- a/test/web/activity_pub/visibilty_test.exs +++ b/test/web/activity_pub/visibilty_test.exs @@ -21,21 +21,21 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do Pleroma.List.follow(list, unrelated) {:ok, public} = - CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "public"}) + CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "public"}) {:ok, private} = - CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "private"}) + CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "private"}) {:ok, direct} = - CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "direct"}) + CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "direct"}) {:ok, unlisted} = - CommonAPI.post(user, %{"status" => "@#{mentioned.nickname}", "visibility" => "unlisted"}) + CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "unlisted"}) {:ok, list} = CommonAPI.post(user, %{ - "status" => "@#{mentioned.nickname}", - "visibility" => "list:#{list.id}" + status: "@#{mentioned.nickname}", + visibility: "list:#{list.id}" }) %{ diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index c3de89ac0..dd0c6b88d 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -1747,7 +1747,7 @@ test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do test "change visibility flag", %{conn: conn, id: id, admin: admin} do response = conn - |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"}) + |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "public"}) |> json_response(:ok) assert response["visibility"] == "public" @@ -1759,21 +1759,21 @@ test "change visibility flag", %{conn: conn, id: id, admin: admin} do response = conn - |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"}) + |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "private"}) |> json_response(:ok) assert response["visibility"] == "private" response = conn - |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"}) + |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "unlisted"}) |> json_response(:ok) assert response["visibility"] == "unlisted" end test "returns 400 when visibility is unknown", %{conn: conn, id: id} do - conn = put(conn, "/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"}) + conn = put(conn, "/api/pleroma/admin/statuses/#{id}", %{visibility: "test"}) assert json_response(conn, :bad_request) == "Unsupported visibility" end @@ -2862,26 +2862,25 @@ test "proxy tuple localhost", %{conn: conn} do group: ":pleroma", key: ":http", value: [ - %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}, - %{"tuple" => [":send_user_agent", false]} + %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]} ] } ] }) - assert json_response(conn, 200) == %{ + assert %{ "configs" => [ %{ "group" => ":pleroma", "key" => ":http", - "value" => [ - %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]}, - %{"tuple" => [":send_user_agent", false]} - ], - "db" => [":proxy_url", ":send_user_agent"] + "value" => value, + "db" => db } ] - } + } = json_response(conn, 200) + + assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]} in value + assert ":proxy_url" in db end test "proxy tuple domain", %{conn: conn} do @@ -2892,26 +2891,25 @@ test "proxy tuple domain", %{conn: conn} do group: ":pleroma", key: ":http", value: [ - %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}, - %{"tuple" => [":send_user_agent", false]} + %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]} ] } ] }) - assert json_response(conn, 200) == %{ + assert %{ "configs" => [ %{ "group" => ":pleroma", "key" => ":http", - "value" => [ - %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]}, - %{"tuple" => [":send_user_agent", false]} - ], - "db" => [":proxy_url", ":send_user_agent"] + "value" => value, + "db" => db } ] - } + } = json_response(conn, 200) + + assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]} in value + assert ":proxy_url" in db end test "proxy tuple ip", %{conn: conn} do @@ -2922,26 +2920,25 @@ test "proxy tuple ip", %{conn: conn} do group: ":pleroma", key: ":http", value: [ - %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}, - %{"tuple" => [":send_user_agent", false]} + %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} ] } ] }) - assert json_response(conn, 200) == %{ + assert %{ "configs" => [ %{ "group" => ":pleroma", "key" => ":http", - "value" => [ - %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]}, - %{"tuple" => [":send_user_agent", false]} - ], - "db" => [":proxy_url", ":send_user_agent"] + "value" => value, + "db" => db } ] - } + } = json_response(conn, 200) + + assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} in value + assert ":proxy_url" in db end end @@ -2977,13 +2974,12 @@ test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do user = insert(:user) User.block(admin, blocked) - {:ok, _} = - CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"}) + {:ok, _} = CommonAPI.post(user, %{status: "@#{admin.nickname}", visibility: "direct"}) - {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"}) - {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) - {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) - {:ok, _} = CommonAPI.post(blocked, %{"status" => ".", "visibility" => "public"}) + {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"}) + {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"}) + {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"}) + {:ok, _} = CommonAPI.post(blocked, %{status: ".", visibility: "public"}) response = conn @@ -3011,11 +3007,10 @@ test "returns only local statuses with local_only on", %{conn: conn} do test "returns private and direct statuses with godmode on", %{conn: conn, admin: admin} do user = insert(:user) - {:ok, _} = - CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"}) + {:ok, _} = CommonAPI.post(user, %{status: "@#{admin.nickname}", visibility: "direct"}) - {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) - {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) + {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"}) + {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"}) conn = get(conn, "/api/pleroma/admin/statuses?godmode=true") assert json_response(conn, 200) |> length() == 3 end @@ -3049,11 +3044,9 @@ test "renders user's statuses with a limit", %{conn: conn, user: user} do end test "doesn't return private statuses by default", %{conn: conn, user: user} do - {:ok, _private_status} = - CommonAPI.post(user, %{"status" => "private", "visibility" => "private"}) + {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"}) - {:ok, _public_status} = - CommonAPI.post(user, %{"status" => "public", "visibility" => "public"}) + {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"}) conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses") @@ -3061,11 +3054,9 @@ test "doesn't return private statuses by default", %{conn: conn, user: user} do end test "returns private statuses with godmode on", %{conn: conn, user: user} do - {:ok, _private_status} = - CommonAPI.post(user, %{"status" => "private", "visibility" => "private"}) + {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"}) - {:ok, _public_status} = - CommonAPI.post(user, %{"status" => "public", "visibility" => "public"}) + {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"}) conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true") @@ -3074,7 +3065,7 @@ test "returns private statuses with godmode on", %{conn: conn, user: user} do test "excludes reblogs by default", %{conn: conn, user: user} do other_user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) + {:ok, activity} = CommonAPI.post(user, %{status: "."}) {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, other_user) conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses") @@ -3599,9 +3590,9 @@ test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do test "status visibility count", %{conn: conn} do admin = insert(:user, is_admin: true) user = insert(:user) - CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) - CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"}) - CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"}) + CommonAPI.post(user, %{visibility: "public", status: "hey"}) + CommonAPI.post(user, %{visibility: "unlisted", status: "hey"}) + CommonAPI.post(user, %{visibility: "unlisted", status: "hey"}) response = conn @@ -3619,9 +3610,9 @@ test "by instance", %{conn: conn} do instance2 = "instance2.tld" user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"}) - CommonAPI.post(user1, %{"visibility" => "public", "status" => "hey"}) - CommonAPI.post(user2, %{"visibility" => "unlisted", "status" => "hey"}) - CommonAPI.post(user2, %{"visibility" => "private", "status" => "hey"}) + CommonAPI.post(user1, %{visibility: "public", status: "hey"}) + CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"}) + CommonAPI.post(user2, %{visibility: "private", status: "hey"}) response = conn diff --git a/test/web/admin_api/views/report_view_test.exs b/test/web/admin_api/views/report_view_test.exs index 8cfa1dcfa..f00b0afb2 100644 --- a/test/web/admin_api/views/report_view_test.exs +++ b/test/web/admin_api/views/report_view_test.exs @@ -45,7 +45,7 @@ test "renders a report" do test "includes reported statuses" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "toot"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "toot"}) {:ok, report_activity} = CommonAPI.report(user, %{account_id: other_user.id, status_ids: [activity.id]}) diff --git a/test/web/auth/basic_auth_test.exs b/test/web/auth/basic_auth_test.exs index 64f8a6863..bf6e3d2fc 100644 --- a/test/web/auth/basic_auth_test.exs +++ b/test/web/auth/basic_auth_test.exs @@ -11,7 +11,7 @@ test "with HTTP Basic Auth used, grants access to OAuth scope-restricted endpoin conn: conn } do user = insert(:user) - assert Comeonin.Pbkdf2.checkpw("test", user.password_hash) + assert Pbkdf2.verify_pass("test", user.password_hash) basic_auth_contents = (URI.encode_www_form(user.nickname) <> ":" <> URI.encode_www_form("test")) diff --git a/test/web/auth/pleroma_authenticator_test.exs b/test/web/auth/pleroma_authenticator_test.exs index 7125c5081..5a421e5ed 100644 --- a/test/web/auth/pleroma_authenticator_test.exs +++ b/test/web/auth/pleroma_authenticator_test.exs @@ -11,7 +11,7 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticatorTest do setup do password = "testpassword" name = "AgentSmith" - user = insert(:user, nickname: name, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) + user = insert(:user, nickname: name, password_hash: Pbkdf2.hash_pwd_salt(password)) {:ok, [user: user, name: name, password: password]} end diff --git a/test/web/auth/totp_authenticator_test.exs b/test/web/auth/totp_authenticator_test.exs index e08069490..e502e0ae8 100644 --- a/test/web/auth/totp_authenticator_test.exs +++ b/test/web/auth/totp_authenticator_test.exs @@ -34,7 +34,7 @@ test "checks backup codes" do hashed_codes = backup_codes - |> Enum.map(&Comeonin.Pbkdf2.hashpwsalt(&1)) + |> Enum.map(&Pbkdf2.hash_pwd_salt(&1)) user = insert(:user, diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 2fd17a1b8..26e41c313 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -24,10 +24,28 @@ defmodule Pleroma.Web.CommonAPITest do setup do: clear_config([:instance, :max_pinned_statuses]) describe "deletion" do + test "it works with pruned objects" do + user = insert(:user) + + {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"}) + + Object.normalize(post, false) + |> Object.prune() + + with_mock Pleroma.Web.Federator, + publish: fn _ -> nil end do + assert {:ok, delete} = CommonAPI.delete(post.id, user) + assert delete.local + assert called(Pleroma.Web.Federator.publish(delete)) + end + + refute Activity.get_by_id(post.id) + end + test "it allows users to delete their posts" do user = insert(:user) - {:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"}) + {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"}) with_mock Pleroma.Web.Federator, publish: fn _ -> nil end do @@ -43,7 +61,7 @@ test "it does not allow a user to delete their posts" do user = insert(:user) other_user = insert(:user) - {:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"}) + {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"}) assert {:error, "Could not delete"} = CommonAPI.delete(post.id, other_user) assert Activity.get_by_id(post.id) @@ -53,7 +71,7 @@ test "it allows moderators to delete other user's posts" do user = insert(:user) moderator = insert(:user, is_moderator: true) - {:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"}) + {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"}) assert {:ok, delete} = CommonAPI.delete(post.id, moderator) assert delete.local @@ -65,7 +83,7 @@ test "it allows admins to delete other user's posts" do user = insert(:user) moderator = insert(:user, is_admin: true) - {:ok, post} = CommonAPI.post(user, %{"status" => "namu amida butsu"}) + {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"}) assert {:ok, delete} = CommonAPI.delete(post.id, moderator) assert delete.local @@ -106,7 +124,7 @@ test "favoriting race condition" do users_serial = insert_list(10, :user) users = insert_list(10, :user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) + {:ok, activity} = CommonAPI.post(user, %{status: "."}) users_serial |> Enum.map(fn user -> @@ -133,7 +151,7 @@ test "repeating race condition" do users_serial = insert_list(10, :user) users = insert_list(10, :user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "."}) + {:ok, activity} = CommonAPI.post(user, %{status: "."}) users_serial |> Enum.map(fn user -> @@ -157,12 +175,12 @@ test "repeating race condition" do test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"}) + {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"}) [participation] = Participation.for_user(user) {:ok, convo_reply} = - CommonAPI.post(user, %{"status" => ".", "in_reply_to_conversation_id" => participation.id}) + CommonAPI.post(user, %{status: ".", in_reply_to_conversation_id: participation.id}) assert Visibility.is_direct?(convo_reply) @@ -176,8 +194,8 @@ test "when replying to a conversation / participation, it only mentions the reci {:ok, activity} = CommonAPI.post(har, %{ - "status" => "@#{jafnhar.nickname} hey", - "visibility" => "direct" + status: "@#{jafnhar.nickname} hey", + visibility: "direct" }) assert har.ap_id in activity.recipients @@ -187,10 +205,10 @@ test "when replying to a conversation / participation, it only mentions the reci {:ok, activity} = CommonAPI.post(har, %{ - "status" => "I don't really like @#{tridi.nickname}", - "visibility" => "direct", - "in_reply_to_status_id" => activity.id, - "in_reply_to_conversation_id" => participation.id + status: "I don't really like @#{tridi.nickname}", + visibility: "direct", + in_reply_to_status_id: activity.id, + in_reply_to_conversation_id: participation.id }) assert har.ap_id in activity.recipients @@ -207,8 +225,8 @@ test "with the safe_dm_mention option set, it does not mention people beyond the {:ok, activity} = CommonAPI.post(har, %{ - "status" => "@#{jafnhar.nickname} hey, i never want to see @#{tridi.nickname} again", - "visibility" => "direct" + status: "@#{jafnhar.nickname} hey, i never want to see @#{tridi.nickname} again", + visibility: "direct" }) refute tridi.ap_id in activity.recipients @@ -217,7 +235,7 @@ test "with the safe_dm_mention option set, it does not mention people beyond the test "it de-duplicates tags" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu #2HU"}) + {:ok, activity} = CommonAPI.post(user, %{status: "#2hu #2HU"}) object = Object.normalize(activity) @@ -226,7 +244,7 @@ test "it de-duplicates tags" do test "it adds emoji in the object" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => ":firefox:"}) + {:ok, activity} = CommonAPI.post(user, %{status: ":firefox:"}) assert Object.normalize(activity).data["emoji"]["firefox"] end @@ -240,9 +258,9 @@ test "it supports explicit addressing" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => + status: "Hey, I think @#{user_three.nickname} is ugly. @#{user_four.nickname} is alright though.", - "to" => [user_two.nickname, user_four.nickname, "nonexistent"] + to: [user_two.nickname, user_four.nickname, "nonexistent"] }) assert user.ap_id in activity.recipients @@ -258,8 +276,8 @@ test "it filters out obviously bad tags when accepting a post as HTML" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => post, - "content_type" => "text/html" + status: post, + content_type: "text/html" }) object = Object.normalize(activity) @@ -274,8 +292,8 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => post, - "content_type" => "text/markdown" + status: post, + content_type: "text/markdown" }) object = Object.normalize(activity) @@ -286,21 +304,21 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do test "it does not allow replies to direct messages that are not direct messages themselves" do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"}) + {:ok, activity} = CommonAPI.post(user, %{status: "suya..", visibility: "direct"}) assert {:ok, _} = CommonAPI.post(user, %{ - "status" => "suya..", - "visibility" => "direct", - "in_reply_to_status_id" => activity.id + status: "suya..", + visibility: "direct", + in_reply_to_status_id: activity.id }) Enum.each(["public", "private", "unlisted"], fn visibility -> assert {:error, "The message visibility must be direct"} = CommonAPI.post(user, %{ - "status" => "suya..", - "visibility" => visibility, - "in_reply_to_status_id" => activity.id + status: "suya..", + visibility: visibility, + in_reply_to_status_id: activity.id }) end) end @@ -309,8 +327,7 @@ test "it allows to address a list" do user = insert(:user) {:ok, list} = Pleroma.List.create("foo", user) - {:ok, activity} = - CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"}) + {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"}) assert activity.data["bcc"] == [list.ap_id] assert activity.recipients == [list.ap_id, user.ap_id] @@ -321,7 +338,7 @@ test "it returns error when status is empty and no attachments" do user = insert(:user) assert {:error, "Cannot post an empty status without attachments"} = - CommonAPI.post(user, %{"status" => ""}) + CommonAPI.post(user, %{status: ""}) end test "it validates character limits are correctly enforced" do @@ -330,9 +347,9 @@ test "it validates character limits are correctly enforced" do user = insert(:user) assert {:error, "The status is over the character limit"} = - CommonAPI.post(user, %{"status" => "foobar"}) + CommonAPI.post(user, %{status: "foobar"}) - assert {:ok, activity} = CommonAPI.post(user, %{"status" => "12345"}) + assert {:ok, activity} = CommonAPI.post(user, %{status: "12345"}) end test "it can handle activities that expire" do @@ -343,8 +360,7 @@ test "it can handle activities that expire" do |> NaiveDateTime.truncate(:second) |> NaiveDateTime.add(1_000_000, :second) - assert {:ok, activity} = - CommonAPI.post(user, %{"status" => "chai", "expires_in" => 1_000_000}) + assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000}) assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id) assert expiration.scheduled_at == expires_at @@ -356,14 +372,14 @@ test "reacting to a status with an emoji" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍") assert reaction.data["actor"] == user.ap_id assert reaction.data["content"] == "👍" - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:error, _} = CommonAPI.react_with_emoji(activity.id, user, ".") end @@ -372,7 +388,7 @@ test "unreacting to a status with an emoji" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍") {:ok, unreaction} = CommonAPI.unreact_with_emoji(activity.id, user, "👍") @@ -386,7 +402,7 @@ test "repeating a status" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user) end @@ -394,7 +410,7 @@ test "repeating a status" do test "can't repeat a repeat" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, %Activity{} = announce, _} = CommonAPI.repeat(activity.id, other_user) @@ -405,10 +421,10 @@ test "repeating a status privately" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, %Activity{} = announce_activity, _} = - CommonAPI.repeat(activity.id, user, %{"visibility" => "private"}) + CommonAPI.repeat(activity.id, user, %{visibility: "private"}) assert Visibility.is_private?(announce_activity) end @@ -417,7 +433,7 @@ test "favoriting a status" do user = insert(:user) other_user = insert(:user) - {:ok, post_activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, post_activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id) assert data["type"] == "Like" @@ -429,7 +445,7 @@ test "retweeting a status twice returns the status" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, %Activity{} = announce, object} = CommonAPI.repeat(activity.id, user) {:ok, ^announce, ^object} = CommonAPI.repeat(activity.id, user) end @@ -438,7 +454,7 @@ test "favoriting a status twice returns ok, but without the like activity" do user = insert(:user) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"}) {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id) assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id) end @@ -449,7 +465,7 @@ test "favoriting a status twice returns ok, but without the like activity" do Pleroma.Config.put([:instance, :max_pinned_statuses], 1) user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"}) [user: user, activity: activity] end @@ -466,8 +482,8 @@ test "pin status", %{user: user, activity: activity} do test "pin poll", %{user: user} do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "How is fediverse today?", - "poll" => %{"options" => ["Absolutely outstanding", "Not good"], "expires_in" => 20} + status: "How is fediverse today?", + poll: %{options: ["Absolutely outstanding", "Not good"], expires_in: 20} }) assert {:ok, ^activity} = CommonAPI.pin(activity.id, user) @@ -479,7 +495,7 @@ test "pin poll", %{user: user} do end test "unlisted statuses can be pinned", %{user: user} do - {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!", "visibility" => "unlisted"}) + {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!", visibility: "unlisted"}) assert {:ok, ^activity} = CommonAPI.pin(activity.id, user) end @@ -490,7 +506,7 @@ test "only self-authored can be pinned", %{activity: activity} do end test "max pinned statuses", %{user: user, activity: activity_one} do - {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"}) assert {:ok, ^activity_one} = CommonAPI.pin(activity_one.id, user) @@ -558,7 +574,7 @@ test "creates a report" do reporter = insert(:user) target_user = insert(:user) - {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"}) + {:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"}) reporter_ap_id = reporter.ap_id target_ap_id = target_user.ap_id @@ -795,8 +811,8 @@ test "does not allow to vote twice" do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "Am I cute?", - "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} + status: "Am I cute?", + poll: %{options: ["Yes", "No"], expires_in: 20} }) object = Object.normalize(activity) diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs index 18a3b3b87..5708db6a4 100644 --- a/test/web/common_api/common_api_utils_test.exs +++ b/test/web/common_api/common_api_utils_test.exs @@ -228,7 +228,7 @@ test "for public posts, a reply" do user = insert(:user) mentioned_user = insert(:user) third_user = insert(:user) - {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"}) + {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) mentions = [mentioned_user.ap_id] {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil) @@ -261,7 +261,7 @@ test "for unlisted posts, a reply" do user = insert(:user) mentioned_user = insert(:user) third_user = insert(:user) - {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"}) + {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) mentions = [mentioned_user.ap_id] {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil) @@ -292,7 +292,7 @@ test "for private posts, a reply" do user = insert(:user) mentioned_user = insert(:user) third_user = insert(:user) - {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"}) + {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) mentions = [mentioned_user.ap_id] {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil) @@ -322,7 +322,7 @@ test "for direct posts, a reply" do user = insert(:user) mentioned_user = insert(:user) third_user = insert(:user) - {:ok, activity} = CommonAPI.post(third_user, %{"status" => "uguu"}) + {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"}) mentions = [mentioned_user.ap_id] {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil) @@ -463,8 +463,8 @@ test "returns attachments with descs" do desc = Jason.encode!(%{object.id => "test-desc"}) assert Utils.attachments_from_ids(%{ - "media_ids" => ["#{object.id}"], - "descriptions" => desc + media_ids: ["#{object.id}"], + descriptions: desc }) == [ Map.merge(object.data, %{"name" => "test-desc"}) ] @@ -472,7 +472,7 @@ test "returns attachments with descs" do test "returns attachments without descs" do object = insert(:note) - assert Utils.attachments_from_ids(%{"media_ids" => ["#{object.id}"]}) == [object.data] + assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}) == [object.data] end test "returns [] when not pass media_ids" do diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs index 261518ef0..de90aa6e0 100644 --- a/test/web/federator_test.exs +++ b/test/web/federator_test.exs @@ -29,7 +29,7 @@ defmodule Pleroma.Web.FederatorTest do describe "Publish an activity" do setup do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "HI"}) + {:ok, activity} = CommonAPI.post(user, %{status: "HI"}) relay_mock = { Pleroma.Web.ActivityPub.Relay, @@ -96,7 +96,7 @@ test "it federates only to reachable instances via AP" do Instances.set_consistently_unreachable(URI.parse(inbox2).host) {:ok, _activity} = - CommonAPI.post(user, %{"status" => "HI @nick1@domain.com, @nick2@domain2.com!"}) + CommonAPI.post(user, %{status: "HI @nick1@domain.com, @nick2@domain2.com!"}) expected_dt = NaiveDateTime.to_iso8601(dt) diff --git a/test/web/feed/tag_controller_test.exs b/test/web/feed/tag_controller_test.exs index d95aac108..3c29cd94f 100644 --- a/test/web/feed/tag_controller_test.exs +++ b/test/web/feed/tag_controller_test.exs @@ -21,7 +21,7 @@ test "gets a feed (ATOM)", %{conn: conn} do ) user = insert(:user) - {:ok, activity1} = CommonAPI.post(user, %{"status" => "yeah #PleromaArt"}) + {:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"}) object = Object.normalize(activity1) @@ -43,9 +43,9 @@ test "gets a feed (ATOM)", %{conn: conn} do |> Ecto.Changeset.change(data: object_data) |> Pleroma.Repo.update() - {:ok, activity2} = CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"}) + {:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"}) - {:ok, _activity3} = CommonAPI.post(user, %{"status" => "This is :moominmamma"}) + {:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"}) response = conn @@ -88,7 +88,7 @@ test "gets a feed (RSS)", %{conn: conn} do ) user = insert(:user) - {:ok, activity1} = CommonAPI.post(user, %{"status" => "yeah #PleromaArt"}) + {:ok, activity1} = CommonAPI.post(user, %{status: "yeah #PleromaArt"}) object = Object.normalize(activity1) @@ -110,9 +110,9 @@ test "gets a feed (RSS)", %{conn: conn} do |> Ecto.Changeset.change(data: object_data) |> Pleroma.Repo.update() - {:ok, activity2} = CommonAPI.post(user, %{"status" => "42 This is :moominmamma #PleromaArt"}) + {:ok, activity2} = CommonAPI.post(user, %{status: "42 This is :moominmamma #PleromaArt"}) - {:ok, _activity3} = CommonAPI.post(user, %{"status" => "This is :moominmamma"}) + {:ok, _activity3} = CommonAPI.post(user, %{status: "This is :moominmamma"}) response = conn @@ -138,8 +138,8 @@ test "gets a feed (RSS)", %{conn: conn} do ] assert xpath(xml, ~x"//channel/item/pubDate/text()"sl) == [ - FeedView.pub_date(activity1.data["published"]), - FeedView.pub_date(activity2.data["published"]) + FeedView.pub_date(activity2.data["published"]), + FeedView.pub_date(activity1.data["published"]) ] assert xpath(xml, ~x"//channel/item/enclosure/@url"sl) == [ diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 256a8b304..280bd6aca 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -222,13 +222,40 @@ test "if user is authenticated", %{local: local, remote: remote} do describe "user timelines" do setup do: oauth_access(["read:statuses"]) + test "works with announces that are just addressed to public", %{conn: conn} do + user = insert(:user, ap_id: "https://honktest/u/test", local: false) + other_user = insert(:user) + + {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"}) + + {:ok, announce, _} = + %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "actor" => "https://honktest/u/test", + "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx", + "object" => post.data["object"], + "published" => "2019-06-25T19:33:58Z", + "to" => ["https://www.w3.org/ns/activitystreams#Public"], + "type" => "Announce" + } + |> ActivityPub.persist(local: false) + + assert resp = + conn + |> get("/api/v1/accounts/#{user.id}/statuses") + |> json_response_and_validate_schema(200) + + assert [%{"id" => id}] = resp + assert id == announce.id + end + test "respects blocks", %{user: user_one, conn: conn} do user_two = insert(:user) user_three = insert(:user) User.block(user_one, user_two) - {:ok, activity} = CommonAPI.post(user_two, %{"status" => "User one sux0rz"}) + {:ok, activity} = CommonAPI.post(user_two, %{status: "User one sux0rz"}) {:ok, repeat, _} = CommonAPI.repeat(activity.id, user_three) assert resp = @@ -271,16 +298,16 @@ test "gets users statuses", %{conn: conn} do {:ok, _user_three} = User.follow(user_three, user_one) - {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"}) + {:ok, activity} = CommonAPI.post(user_one, %{status: "HI!!!"}) {:ok, direct_activity} = CommonAPI.post(user_one, %{ - "status" => "Hi, @#{user_two.nickname}.", - "visibility" => "direct" + status: "Hi, @#{user_two.nickname}.", + visibility: "direct" }) {:ok, private_activity} = - CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"}) + CommonAPI.post(user_one, %{status: "private", visibility: "private"}) # TODO!!! resp = @@ -335,8 +362,7 @@ test "gets an users media", %{conn: conn} do {:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id) - {:ok, %{id: image_post_id}} = - CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]}) + {:ok, %{id: image_post_id}} = CommonAPI.post(user, %{status: "cofe", media_ids: [media_id]}) conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?only_media=true") @@ -348,7 +374,7 @@ test "gets an users media", %{conn: conn} do end test "gets a user's statuses without reblogs", %{user: user, conn: conn} do - {:ok, %{id: post_id}} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, %{id: post_id}} = CommonAPI.post(user, %{status: "HI!!!"}) {:ok, _, _} = CommonAPI.repeat(post_id, user) conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=true") @@ -359,8 +385,8 @@ test "gets a user's statuses without reblogs", %{user: user, conn: conn} do end test "filters user's statuses by a hashtag", %{user: user, conn: conn} do - {:ok, %{id: post_id}} = CommonAPI.post(user, %{"status" => "#hashtag"}) - {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"}) + {:ok, %{id: post_id}} = CommonAPI.post(user, %{status: "#hashtag"}) + {:ok, _post} = CommonAPI.post(user, %{status: "hashtag"}) conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?tagged=hashtag") assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200) @@ -371,9 +397,9 @@ test "the user views their own timelines and excludes direct messages", %{ conn: conn } do {:ok, %{id: public_activity_id}} = - CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) + CommonAPI.post(user, %{status: ".", visibility: "public"}) - {:ok, _direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"}) + {:ok, _direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"}) conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct") assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200) @@ -651,7 +677,7 @@ test "following without reblogs" do assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) {:ok, %{id: reblog_id}, _} = CommonAPI.repeat(activity.id, followed) assert [] == @@ -750,7 +776,7 @@ test "without notifications", %{conn: conn} do describe "pinned statuses" do setup do user = insert(:user) - {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"}) %{conn: conn} = oauth_access(["read:statuses"], user: user) [conn: conn, user: user, activity: activity] diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs index 04695572e..693ba51e5 100644 --- a/test/web/mastodon_api/controllers/conversation_controller_test.exs +++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs @@ -22,16 +22,16 @@ test "returns a list of conversations", %{user: user_one, conn: conn} do {:ok, direct} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}, @#{user_three.nickname}!", + visibility: "direct" }) assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 {:ok, _follower_only} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}!", - "visibility" => "private" + status: "Hi @#{user_two.nickname}!", + visibility: "private" }) res_conn = get(conn, "/api/v1/conversations") @@ -63,32 +63,32 @@ test "filters conversations by recipients", %{user: user_one, conn: conn} do {:ok, direct1} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}!", + visibility: "direct" }) {:ok, _direct2} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_three.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_three.nickname}!", + visibility: "direct" }) {:ok, direct3} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}, @#{user_three.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}, @#{user_three.nickname}!", + visibility: "direct" }) {:ok, _direct4} = CommonAPI.post(user_two, %{ - "status" => "Hi @#{user_three.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_three.nickname}!", + visibility: "direct" }) {:ok, direct5} = CommonAPI.post(user_two, %{ - "status" => "Hi @#{user_one.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_one.nickname}!", + visibility: "direct" }) assert [conversation1, conversation2] = @@ -112,15 +112,15 @@ test "updates the last_status on reply", %{user: user_one, conn: conn} do {:ok, direct} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}", + visibility: "direct" }) {:ok, direct_reply} = CommonAPI.post(user_two, %{ - "status" => "reply", - "visibility" => "direct", - "in_reply_to_status_id" => direct.id + status: "reply", + visibility: "direct", + in_reply_to_status_id: direct.id }) [%{"last_status" => res_last_status}] = @@ -136,8 +136,8 @@ test "the user marks a conversation as read", %{user: user_one, conn: conn} do {:ok, direct} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}", + visibility: "direct" }) assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 @@ -167,9 +167,9 @@ test "the user marks a conversation as read", %{user: user_one, conn: conn} do # The conversation is marked as unread on reply {:ok, _} = CommonAPI.post(user_two, %{ - "status" => "reply", - "visibility" => "direct", - "in_reply_to_status_id" => direct.id + status: "reply", + visibility: "direct", + in_reply_to_status_id: direct.id }) [%{"unread" => true}] = @@ -183,9 +183,9 @@ test "the user marks a conversation as read", %{user: user_one, conn: conn} do # A reply doesn't increment the user's unread_conversation_count if the conversation is unread {:ok, _} = CommonAPI.post(user_two, %{ - "status" => "reply", - "visibility" => "direct", - "in_reply_to_status_id" => direct.id + status: "reply", + visibility: "direct", + in_reply_to_status_id: direct.id }) assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1 @@ -197,8 +197,8 @@ test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do {:ok, direct} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}!", + visibility: "direct" }) res_conn = get(conn, "/api/v1/statuses/#{direct.id}/context") diff --git a/test/web/mastodon_api/controllers/instance_controller_test.exs b/test/web/mastodon_api/controllers/instance_controller_test.exs index 90840d5ab..2c61dc5ba 100644 --- a/test/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/web/mastodon_api/controllers/instance_controller_test.exs @@ -50,7 +50,7 @@ test "get instance stats", %{conn: conn} do insert(:user, %{local: false, nickname: "u@peer1.com"}) insert(:user, %{local: false, nickname: "u@peer2.com"}) - {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"}) + {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"}) Pleroma.Stats.force_update() diff --git a/test/web/mastodon_api/controllers/notification_controller_test.exs b/test/web/mastodon_api/controllers/notification_controller_test.exs index db380f76a..d9356a844 100644 --- a/test/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/web/mastodon_api/controllers/notification_controller_test.exs @@ -18,7 +18,7 @@ test "does NOT render account/pleroma/relationship if this is disabled by defaul %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, [_notification]} = Notification.create_notifications(activity) response = @@ -36,7 +36,7 @@ test "list of notifications" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, [_notification]} = Notification.create_notifications(activity) @@ -60,7 +60,7 @@ test "getting a single notification" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, [notification]} = Notification.create_notifications(activity) @@ -79,7 +79,7 @@ test "dismissing a single notification (deprecated endpoint)" do %{user: user, conn: conn} = oauth_access(["write:notifications"]) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, [notification]} = Notification.create_notifications(activity) @@ -96,7 +96,7 @@ test "dismissing a single notification" do %{user: user, conn: conn} = oauth_access(["write:notifications"]) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, [notification]} = Notification.create_notifications(activity) @@ -112,7 +112,7 @@ test "clearing all notifications" do %{user: user, conn: conn} = oauth_access(["write:notifications", "read:notifications"]) other_user = insert(:user) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, [_notification]} = Notification.create_notifications(activity) @@ -130,10 +130,10 @@ test "paginates notifications using min_id, since_id, max_id, and limit" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) - {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity1} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) + {:ok, activity2} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) + {:ok, activity3} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) + {:ok, activity4} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) notification1_id = get_notification_id_by_activity(activity1) notification2_id = get_notification_id_by_activity(activity2) @@ -173,16 +173,16 @@ test "filters notifications for mentions" do other_user = insert(:user) {:ok, public_activity} = - CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "public"}) + CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "public"}) {:ok, direct_activity} = - CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"}) + CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "direct"}) {:ok, unlisted_activity} = - CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "unlisted"}) + CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "unlisted"}) {:ok, private_activity} = - CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"}) + CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "private"}) query = params_to_query(%{exclude_visibilities: ["public", "unlisted", "private"]}) conn_res = get(conn, "/api/v1/notifications?" <> query) @@ -213,17 +213,15 @@ test "filters notifications for Like activities" do user = insert(:user) %{user: other_user, conn: conn} = oauth_access(["read:notifications"]) - {:ok, public_activity} = - CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"}) + {:ok, public_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "public"}) {:ok, direct_activity} = - CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"}) + CommonAPI.post(other_user, %{status: "@#{user.nickname}", visibility: "direct"}) {:ok, unlisted_activity} = - CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"}) + CommonAPI.post(other_user, %{status: ".", visibility: "unlisted"}) - {:ok, private_activity} = - CommonAPI.post(other_user, %{"status" => ".", "visibility" => "private"}) + {:ok, private_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "private"}) {:ok, _} = CommonAPI.favorite(user, public_activity.id) {:ok, _} = CommonAPI.favorite(user, direct_activity.id) @@ -279,11 +277,10 @@ test "filters notifications for Announce activities" do user = insert(:user) %{user: other_user, conn: conn} = oauth_access(["read:notifications"]) - {:ok, public_activity} = - CommonAPI.post(other_user, %{"status" => ".", "visibility" => "public"}) + {:ok, public_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "public"}) {:ok, unlisted_activity} = - CommonAPI.post(other_user, %{"status" => ".", "visibility" => "unlisted"}) + CommonAPI.post(other_user, %{status: ".", visibility: "unlisted"}) {:ok, _, _} = CommonAPI.repeat(public_activity.id, user) {:ok, _, _} = CommonAPI.repeat(unlisted_activity.id, user) @@ -303,8 +300,8 @@ test "filters notifications using exclude_types" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) - {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"}) - {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) + {:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"}) + {:ok, create_activity} = CommonAPI.post(user, %{status: "hey"}) {:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id) {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user) {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user) @@ -341,8 +338,8 @@ test "filters notifications using include_types" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) - {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"}) - {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"}) + {:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"}) + {:ok, create_activity} = CommonAPI.post(user, %{status: "hey"}) {:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id) {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user) {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user) @@ -388,10 +385,10 @@ test "destroy multiple" do %{user: user, conn: conn} = oauth_access(["read:notifications", "write:notifications"]) other_user = insert(:user) - {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, activity3} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"}) - {:ok, activity4} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"}) + {:ok, activity1} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) + {:ok, activity2} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) + {:ok, activity3} = CommonAPI.post(user, %{status: "hi @#{other_user.nickname}"}) + {:ok, activity4} = CommonAPI.post(user, %{status: "hi @#{other_user.nickname}"}) notification1_id = get_notification_id_by_activity(activity1) notification2_id = get_notification_id_by_activity(activity2) @@ -435,7 +432,7 @@ test "doesn't see notifications after muting user with notifications" do user2 = insert(:user) {:ok, _, _, _} = CommonAPI.follow(user, user2) - {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"}) + {:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"}) ret_conn = get(conn, "/api/v1/notifications") @@ -453,7 +450,7 @@ test "see notifications after muting user without notifications" do user2 = insert(:user) {:ok, _, _, _} = CommonAPI.follow(user, user2) - {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"}) + {:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"}) ret_conn = get(conn, "/api/v1/notifications") @@ -471,7 +468,7 @@ test "see notifications after muting user with notifications and with_muted para user2 = insert(:user) {:ok, _, _, _} = CommonAPI.follow(user, user2) - {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"}) + {:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"}) ret_conn = get(conn, "/api/v1/notifications") @@ -518,14 +515,14 @@ test "preserves parameters in link headers" do {:ok, activity1} = CommonAPI.post(other_user, %{ - "status" => "hi @#{user.nickname}", - "visibility" => "public" + status: "hi @#{user.nickname}", + visibility: "public" }) {:ok, activity2} = CommonAPI.post(other_user, %{ - "status" => "hi @#{user.nickname}", - "visibility" => "public" + status: "hi @#{user.nickname}", + visibility: "public" }) notification1 = Repo.get_by(Notification, activity_id: activity1.id) @@ -550,8 +547,8 @@ test "account_id" do %{id: account_id} = other_user1 = insert(:user) other_user2 = insert(:user) - {:ok, _activity} = CommonAPI.post(other_user1, %{"status" => "hi @#{user.nickname}"}) - {:ok, _activity} = CommonAPI.post(other_user2, %{"status" => "bye @#{user.nickname}"}) + {:ok, _activity} = CommonAPI.post(other_user1, %{status: "hi @#{user.nickname}"}) + {:ok, _activity} = CommonAPI.post(other_user2, %{status: "bye @#{user.nickname}"}) assert [%{"account" => %{"id" => ^account_id}}] = conn diff --git a/test/web/mastodon_api/controllers/poll_controller_test.exs b/test/web/mastodon_api/controllers/poll_controller_test.exs index d8f34aa86..f41de6448 100644 --- a/test/web/mastodon_api/controllers/poll_controller_test.exs +++ b/test/web/mastodon_api/controllers/poll_controller_test.exs @@ -16,8 +16,8 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do test "returns poll entity for object id", %{user: user, conn: conn} do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "Pleroma does", - "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20} + status: "Pleroma does", + poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20} }) object = Object.normalize(activity) @@ -34,9 +34,9 @@ test "does not expose polls for private statuses", %{conn: conn} do {:ok, activity} = CommonAPI.post(other_user, %{ - "status" => "Pleroma does", - "poll" => %{"options" => ["what Mastodon't", "n't what Mastodoes"], "expires_in" => 20}, - "visibility" => "private" + status: "Pleroma does", + poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20}, + visibility: "private" }) object = Object.normalize(activity) @@ -55,11 +55,11 @@ test "votes are added to the poll", %{conn: conn} do {:ok, activity} = CommonAPI.post(other_user, %{ - "status" => "A very delicious sandwich", - "poll" => %{ - "options" => ["Lettuce", "Grilled Bacon", "Tomato"], - "expires_in" => 20, - "multiple" => true + status: "A very delicious sandwich", + poll: %{ + options: ["Lettuce", "Grilled Bacon", "Tomato"], + expires_in: 20, + multiple: true } }) @@ -81,8 +81,8 @@ test "votes are added to the poll", %{conn: conn} do test "author can't vote", %{user: user, conn: conn} do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "Am I cute?", - "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} + status: "Am I cute?", + poll: %{options: ["Yes", "No"], expires_in: 20} }) object = Object.normalize(activity) @@ -102,8 +102,8 @@ test "does not allow multiple choices on a single-choice question", %{conn: conn {:ok, activity} = CommonAPI.post(other_user, %{ - "status" => "The glass is", - "poll" => %{"options" => ["half empty", "half full"], "expires_in" => 20} + status: "The glass is", + poll: %{options: ["half empty", "half full"], expires_in: 20} }) object = Object.normalize(activity) @@ -125,8 +125,8 @@ test "does not allow choice index to be greater than options count", %{conn: con {:ok, activity} = CommonAPI.post(other_user, %{ - "status" => "Am I cute?", - "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} + status: "Am I cute?", + poll: %{options: ["Yes", "No"], expires_in: 20} }) object = Object.normalize(activity) @@ -153,9 +153,9 @@ test "returns 404 when poll is private and not available for user", %{conn: conn {:ok, activity} = CommonAPI.post(other_user, %{ - "status" => "Am I cute?", - "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}, - "visibility" => "private" + status: "Am I cute?", + poll: %{options: ["Yes", "No"], expires_in: 20}, + visibility: "private" }) object = Object.normalize(activity) diff --git a/test/web/mastodon_api/controllers/report_controller_test.exs b/test/web/mastodon_api/controllers/report_controller_test.exs index 21b037237..6636cff96 100644 --- a/test/web/mastodon_api/controllers/report_controller_test.exs +++ b/test/web/mastodon_api/controllers/report_controller_test.exs @@ -14,7 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do setup do target_user = insert(:user) - {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"}) + {:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"}) [target_user: target_user, activity: activity] end diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs index 02476acb6..7d0cafccc 100644 --- a/test/web/mastodon_api/controllers/search_controller_test.exs +++ b/test/web/mastodon_api/controllers/search_controller_test.exs @@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do import Tesla.Mock import Mock - setup do + setup_all do mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) :ok end @@ -42,15 +42,15 @@ test "search", %{conn: conn} do user_two = insert(:user, %{nickname: "shp@shitposter.club"}) user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) - {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu private 天子"}) + {:ok, activity} = CommonAPI.post(user, %{status: "This is about 2hu private 天子"}) {:ok, _activity} = CommonAPI.post(user, %{ - "status" => "This is about 2hu, but private", - "visibility" => "private" + status: "This is about 2hu, but private", + visibility: "private" }) - {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"}) + {:ok, _} = CommonAPI.post(user_two, %{status: "This isn't"}) results = conn @@ -80,9 +80,9 @@ test "excludes a blocked users from search results", %{conn: conn} do user_smith = insert(:user, %{nickname: "Agent", name: "I love 2hu"}) user_neo = insert(:user, %{nickname: "Agent Neo", name: "Agent"}) - {:ok, act1} = CommonAPI.post(user, %{"status" => "This is about 2hu private 天子"}) - {:ok, act2} = CommonAPI.post(user_smith, %{"status" => "Agent Smith"}) - {:ok, act3} = CommonAPI.post(user_neo, %{"status" => "Agent Smith"}) + {:ok, act1} = CommonAPI.post(user, %{status: "This is about 2hu private 天子"}) + {:ok, act2} = CommonAPI.post(user_smith, %{status: "Agent Smith"}) + {:ok, act3} = CommonAPI.post(user_neo, %{status: "Agent Smith"}) Pleroma.User.block(user, user_smith) results = @@ -161,15 +161,15 @@ test "search", %{conn: conn} do user_two = insert(:user, %{nickname: "shp@shitposter.club"}) user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) - {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"}) + {:ok, activity} = CommonAPI.post(user, %{status: "This is about 2hu"}) {:ok, _activity} = CommonAPI.post(user, %{ - "status" => "This is about 2hu, but private", - "visibility" => "private" + status: "This is about 2hu, but private", + visibility: "private" }) - {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"}) + {:ok, _} = CommonAPI.post(user_two, %{status: "This isn't"}) results = conn @@ -189,7 +189,7 @@ test "search fetches remote statuses and prefers them over other results", %{con capture_log(fn -> {:ok, %{id: activity_id}} = CommonAPI.post(insert(:user), %{ - "status" => "check out https://shitposter.club/notice/2827873" + status: "check out https://shitposter.club/notice/2827873" }) results = @@ -207,8 +207,8 @@ test "search fetches remote statuses and prefers them over other results", %{con test "search doesn't show statuses that it shouldn't", %{conn: conn} do {:ok, activity} = CommonAPI.post(insert(:user), %{ - "status" => "This is about 2hu, but private", - "visibility" => "private" + status: "This is about 2hu, but private", + visibility: "private" }) capture_log(fn -> @@ -251,8 +251,8 @@ test "search with limit and offset", %{conn: conn} do _user_two = insert(:user, %{nickname: "shp@shitposter.club"}) _user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) - {:ok, _activity1} = CommonAPI.post(user, %{"status" => "This is about 2hu"}) - {:ok, _activity2} = CommonAPI.post(user, %{"status" => "This is also about 2hu"}) + {:ok, _activity1} = CommonAPI.post(user, %{status: "This is about 2hu"}) + {:ok, _activity2} = CommonAPI.post(user, %{status: "This is also about 2hu"}) result = conn @@ -277,7 +277,7 @@ test "search returns results only for the given type", %{conn: conn} do user = insert(:user) _user_two = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) - {:ok, _activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"}) + {:ok, _activity} = CommonAPI.post(user, %{status: "This is about 2hu"}) assert %{"statuses" => [_activity], "accounts" => [], "hashtags" => []} = conn @@ -294,8 +294,8 @@ test "search uses account_id to filter statuses by the author", %{conn: conn} do user = insert(:user, %{nickname: "shp@shitposter.club"}) user_two = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) - {:ok, activity1} = CommonAPI.post(user, %{"status" => "This is about 2hu"}) - {:ok, activity2} = CommonAPI.post(user_two, %{"status" => "This is also about 2hu"}) + {:ok, activity1} = CommonAPI.post(user, %{status: "This is about 2hu"}) + {:ok, activity2} = CommonAPI.post(user_two, %{status: "This is also about 2hu"}) results = conn diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index 85068edd0..a4403132c 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -32,13 +32,14 @@ test "posting a status does not increment reblog_count when relaying", %{conn: c response = conn + |> put_req_header("content-type", "application/json") |> post("api/v1/statuses", %{ "content_type" => "text/plain", "source" => "Pleroma FE", "status" => "Hello world", "visibility" => "public" }) - |> json_response(200) + |> json_response_and_validate_schema(200) assert response["reblogs_count"] == 0 ObanHelpers.perform_all() @@ -46,7 +47,7 @@ test "posting a status does not increment reblog_count when relaying", %{conn: c response = conn |> get("api/v1/statuses/#{response["id"]}", %{}) - |> json_response(200) + |> json_response_and_validate_schema(200) assert response["reblogs_count"] == 0 end @@ -56,6 +57,7 @@ test "posting a status", %{conn: conn} do conn_one = conn + |> put_req_header("content-type", "application/json") |> put_req_header("idempotency-key", idempotency_key) |> post("/api/v1/statuses", %{ "status" => "cofe", @@ -68,12 +70,13 @@ test "posting a status", %{conn: conn} do assert ttl > :timer.seconds(6 * 60 * 60 - 1) assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = - json_response(conn_one, 200) + json_response_and_validate_schema(conn_one, 200) assert Activity.get_by_id(id) conn_two = conn + |> put_req_header("content-type", "application/json") |> put_req_header("idempotency-key", idempotency_key) |> post("/api/v1/statuses", %{ "status" => "cofe", @@ -86,13 +89,14 @@ test "posting a status", %{conn: conn} do conn_three = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses", %{ "status" => "cofe", "spoiler_text" => "2hu", "sensitive" => "false" }) - assert %{"id" => third_id} = json_response(conn_three, 200) + assert %{"id" => third_id} = json_response_and_validate_schema(conn_three, 200) refute id == third_id # An activity that will expire: @@ -101,12 +105,15 @@ test "posting a status", %{conn: conn} do conn_four = conn + |> put_req_header("content-type", "application/json") |> post("api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) - assert fourth_response = %{"id" => fourth_id} = json_response(conn_four, 200) + assert fourth_response = + %{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200) + assert activity = Activity.get_by_id(fourth_id) assert expiration = ActivityExpiration.get_by_activity_id(fourth_id) @@ -130,22 +137,24 @@ test "it fails to create a status if `expires_in` is less or equal than an hour" assert %{"error" => "Expiry date is too soon"} = conn + |> put_req_header("content-type", "application/json") |> post("api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) - |> json_response(422) + |> json_response_and_validate_schema(422) # 30 minutes expires_in = 30 * 60 assert %{"error" => "Expiry date is too soon"} = conn + |> put_req_header("content-type", "application/json") |> post("api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) - |> json_response(422) + |> json_response_and_validate_schema(422) end test "posting an undefined status with an attachment", %{user: user, conn: conn} do @@ -158,21 +167,24 @@ test "posting an undefined status with an attachment", %{user: user, conn: conn} {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "media_ids" => [to_string(upload.id)] }) - assert json_response(conn, 200) + assert json_response_and_validate_schema(conn, 200) end test "replying to a status", %{user: user, conn: conn} do - {:ok, replied_to} = CommonAPI.post(user, %{"status" => "cofe"}) + {:ok, replied_to} = CommonAPI.post(user, %{status: "cofe"}) conn = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id}) - assert %{"content" => "xD", "id" => id} = json_response(conn, 200) + assert %{"content" => "xD", "id" => id} = json_response_and_validate_schema(conn, 200) activity = Activity.get_by_id(id) @@ -184,43 +196,56 @@ test "replying to a direct message with visibility other than direct", %{ user: user, conn: conn } do - {:ok, replied_to} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"}) + {:ok, replied_to} = CommonAPI.post(user, %{status: "suya..", visibility: "direct"}) Enum.each(["public", "private", "unlisted"], fn visibility -> conn = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses", %{ "status" => "@#{user.nickname} hey", "in_reply_to_id" => replied_to.id, "visibility" => visibility }) - assert json_response(conn, 422) == %{"error" => "The message visibility must be direct"} + assert json_response_and_validate_schema(conn, 422) == %{ + "error" => "The message visibility must be direct" + } end) end test "posting a status with an invalid in_reply_to_id", %{conn: conn} do - conn = post(conn, "/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""}) + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""}) - assert %{"content" => "xD", "id" => id} = json_response(conn, 200) + assert %{"content" => "xD", "id" => id} = json_response_and_validate_schema(conn, 200) assert Activity.get_by_id(id) end test "posting a sensitive status", %{conn: conn} do - conn = post(conn, "/api/v1/statuses", %{"status" => "cofe", "sensitive" => true}) + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true}) + + assert %{"content" => "cofe", "id" => id, "sensitive" => true} = + json_response_and_validate_schema(conn, 200) - assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200) assert Activity.get_by_id(id) end test "posting a fake status", %{conn: conn} do real_conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it" }) - real_status = json_response(real_conn, 200) + real_status = json_response_and_validate_schema(real_conn, 200) assert real_status assert Object.get_by_ap_id(real_status["uri"]) @@ -234,13 +259,15 @@ test "posting a fake status", %{conn: conn} do |> Kernel.put_in(["pleroma", "conversation_id"], nil) fake_conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it", "preview" => true }) - fake_status = json_response(fake_conn, 200) + fake_status = json_response_and_validate_schema(fake_conn, 200) assert fake_status refute Object.get_by_ap_id(fake_status["uri"]) @@ -261,11 +288,15 @@ test "posting a status with OGP link preview", %{conn: conn} do Config.put([:rich_media, :enabled], true) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "https://example.com/ogp" }) - assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200) + assert %{"id" => id, "card" => %{"title" => "The Rock"}} = + json_response_and_validate_schema(conn, 200) + assert Activity.get_by_id(id) end @@ -273,9 +304,12 @@ test "posting a direct status", %{conn: conn} do user2 = insert(:user) content = "direct cofe @#{user2.nickname}" - conn = post(conn, "api/v1/statuses", %{"status" => content, "visibility" => "direct"}) + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"}) - assert %{"id" => id} = response = json_response(conn, 200) + assert %{"id" => id} = response = json_response_and_validate_schema(conn, 200) assert response["visibility"] == "direct" assert response["pleroma"]["direct_conversation_id"] assert activity = Activity.get_by_id(id) @@ -289,32 +323,45 @@ test "posting a direct status", %{conn: conn} do setup do: oauth_access(["write:statuses"]) test "creates a scheduled activity", %{conn: conn} do - scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond) + scheduled_at = + NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond) + |> NaiveDateTime.to_iso8601() + |> Kernel.<>("Z") conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "scheduled", "scheduled_at" => scheduled_at }) - assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200) + assert %{"scheduled_at" => expected_scheduled_at} = + json_response_and_validate_schema(conn, 200) + assert expected_scheduled_at == CommonAPI.Utils.to_masto_date(scheduled_at) assert [] == Repo.all(Activity) end test "ignores nil values", %{conn: conn} do conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "not scheduled", "scheduled_at" => nil }) - assert result = json_response(conn, 200) + assert result = json_response_and_validate_schema(conn, 200) assert Activity.get_by_id(result["id"]) end test "creates a scheduled activity with a media attachment", %{user: user, conn: conn} do - scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond) + scheduled_at = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(:timer.minutes(120), :millisecond) + |> NaiveDateTime.to_iso8601() + |> Kernel.<>("Z") file = %Plug.Upload{ content_type: "image/jpg", @@ -325,13 +372,17 @@ test "creates a scheduled activity with a media attachment", %{user: user, conn: {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "media_ids" => [to_string(upload.id)], "status" => "scheduled", "scheduled_at" => scheduled_at }) - assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200) + assert %{"media_attachments" => [media_attachment]} = + json_response_and_validate_schema(conn, 200) + assert %{"type" => "image"} = media_attachment end @@ -339,14 +390,18 @@ test "skips the scheduling and creates the activity if scheduled_at is earlier t %{conn: conn} do scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond) + |> NaiveDateTime.to_iso8601() + |> Kernel.<>("Z") conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "not scheduled", "scheduled_at" => scheduled_at }) - assert %{"content" => "not scheduled"} = json_response(conn, 200) + assert %{"content" => "not scheduled"} = json_response_and_validate_schema(conn, 200) assert [] == Repo.all(ScheduledActivity) end @@ -355,14 +410,19 @@ test "returns error when daily user limit is exceeded", %{user: user, conn: conn NaiveDateTime.utc_now() |> NaiveDateTime.add(:timer.minutes(6), :millisecond) |> NaiveDateTime.to_iso8601() + # TODO + |> Kernel.<>("Z") attrs = %{params: %{}, scheduled_at: today} {:ok, _} = ScheduledActivity.create(user, attrs) {:ok, _} = ScheduledActivity.create(user, attrs) - conn = post(conn, "/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today}) + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today}) - assert %{"error" => "daily limit exceeded"} == json_response(conn, 422) + assert %{"error" => "daily limit exceeded"} == json_response_and_validate_schema(conn, 422) end test "returns error when total user limit is exceeded", %{user: user, conn: conn} do @@ -370,11 +430,13 @@ test "returns error when total user limit is exceeded", %{user: user, conn: conn NaiveDateTime.utc_now() |> NaiveDateTime.add(:timer.minutes(6), :millisecond) |> NaiveDateTime.to_iso8601() + |> Kernel.<>("Z") tomorrow = NaiveDateTime.utc_now() |> NaiveDateTime.add(:timer.hours(36), :millisecond) |> NaiveDateTime.to_iso8601() + |> Kernel.<>("Z") attrs = %{params: %{}, scheduled_at: today} {:ok, _} = ScheduledActivity.create(user, attrs) @@ -382,9 +444,11 @@ test "returns error when total user limit is exceeded", %{user: user, conn: conn {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow}) conn = - post(conn, "/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow}) + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow}) - assert %{"error" => "total limit exceeded"} == json_response(conn, 422) + assert %{"error" => "total limit exceeded"} == json_response_and_validate_schema(conn, 422) end end @@ -395,12 +459,17 @@ test "posting a poll", %{conn: conn} do time = NaiveDateTime.utc_now() conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "Who is the #bestgrill?", - "poll" => %{"options" => ["Rei", "Asuka", "Misato"], "expires_in" => 420} + "poll" => %{ + "options" => ["Rei", "Asuka", "Misato"], + "expires_in" => 420 + } }) - response = json_response(conn, 200) + response = json_response_and_validate_schema(conn, 200) assert Enum.all?(response["poll"]["options"], fn %{"title" => title} -> title in ["Rei", "Asuka", "Misato"] @@ -419,12 +488,14 @@ test "option limit is enforced", %{conn: conn} do limit = Config.get([:instance, :poll_limits, :max_options]) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "desu~", "poll" => %{"options" => Enum.map(0..limit, fn _ -> "desu" end), "expires_in" => 1} }) - %{"error" => error} = json_response(conn, 422) + %{"error" => error} = json_response_and_validate_schema(conn, 422) assert error == "Poll can't contain more than #{limit} options" end @@ -432,7 +503,9 @@ test "option character limit is enforced", %{conn: conn} do limit = Config.get([:instance, :poll_limits, :max_option_chars]) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "...", "poll" => %{ "options" => [Enum.reduce(0..limit, "", fn _, acc -> acc <> "." end)], @@ -440,7 +513,7 @@ test "option character limit is enforced", %{conn: conn} do } }) - %{"error" => error} = json_response(conn, 422) + %{"error" => error} = json_response_and_validate_schema(conn, 422) assert error == "Poll options cannot be longer than #{limit} characters each" end @@ -448,7 +521,9 @@ test "minimal date limit is enforced", %{conn: conn} do limit = Config.get([:instance, :poll_limits, :min_expiration]) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "imagine arbitrary limits", "poll" => %{ "options" => ["this post was made by pleroma gang"], @@ -456,7 +531,7 @@ test "minimal date limit is enforced", %{conn: conn} do } }) - %{"error" => error} = json_response(conn, 422) + %{"error" => error} = json_response_and_validate_schema(conn, 422) assert error == "Expiration date is too soon" end @@ -464,7 +539,9 @@ test "maximum date limit is enforced", %{conn: conn} do limit = Config.get([:instance, :poll_limits, :max_expiration]) conn = - post(conn, "/api/v1/statuses", %{ + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses", %{ "status" => "imagine arbitrary limits", "poll" => %{ "options" => ["this post was made by pleroma gang"], @@ -472,7 +549,7 @@ test "maximum date limit is enforced", %{conn: conn} do } }) - %{"error" => error} = json_response(conn, 422) + %{"error" => error} = json_response_and_validate_schema(conn, 422) assert error == "Expiration date is too far in the future" end end @@ -483,7 +560,7 @@ test "get a status" do conn = get(conn, "/api/v1/statuses/#{activity.id}") - assert %{"id" => id} = json_response(conn, 200) + assert %{"id" => id} = json_response_and_validate_schema(conn, 200) assert id == to_string(activity.id) end @@ -503,13 +580,13 @@ defp local_and_remote_activities do test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do res_conn = get(conn, "/api/v1/statuses/#{local.id}") - assert json_response(res_conn, :not_found) == %{ + assert json_response_and_validate_schema(res_conn, :not_found) == %{ "error" => "Record not found" } res_conn = get(conn, "/api/v1/statuses/#{remote.id}") - assert json_response(res_conn, :not_found) == %{ + assert json_response_and_validate_schema(res_conn, :not_found) == %{ "error" => "Record not found" } end @@ -517,10 +594,10 @@ test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} d test "if user is authenticated", %{local: local, remote: remote} do %{conn: conn} = oauth_access(["read"]) res_conn = get(conn, "/api/v1/statuses/#{local.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) res_conn = get(conn, "/api/v1/statuses/#{remote.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) end end @@ -532,21 +609,21 @@ test "if user is authenticated", %{local: local, remote: remote} do test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do res_conn = get(conn, "/api/v1/statuses/#{local.id}") - assert json_response(res_conn, :not_found) == %{ + assert json_response_and_validate_schema(res_conn, :not_found) == %{ "error" => "Record not found" } res_conn = get(conn, "/api/v1/statuses/#{remote.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) end test "if user is authenticated", %{local: local, remote: remote} do %{conn: conn} = oauth_access(["read"]) res_conn = get(conn, "/api/v1/statuses/#{local.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) res_conn = get(conn, "/api/v1/statuses/#{remote.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) end end @@ -557,11 +634,11 @@ test "if user is authenticated", %{local: local, remote: remote} do test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do res_conn = get(conn, "/api/v1/statuses/#{local.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) res_conn = get(conn, "/api/v1/statuses/#{remote.id}") - assert json_response(res_conn, :not_found) == %{ + assert json_response_and_validate_schema(res_conn, :not_found) == %{ "error" => "Record not found" } end @@ -569,10 +646,10 @@ test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} d test "if user is authenticated", %{local: local, remote: remote} do %{conn: conn} = oauth_access(["read"]) res_conn = get(conn, "/api/v1/statuses/#{local.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) res_conn = get(conn, "/api/v1/statuses/#{remote.id}") - assert %{"id" => _} = json_response(res_conn, 200) + assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200) end end @@ -582,7 +659,7 @@ test "getting a status that doesn't exist returns 404" do conn = get(conn, "/api/v1/statuses/#{String.downcase(activity.id)}") - assert json_response(conn, 404) == %{"error" => "Record not found"} + assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"} end test "get a direct status" do @@ -590,7 +667,7 @@ test "get a direct status" do other_user = insert(:user) {:ok, activity} = - CommonAPI.post(user, %{"status" => "@#{other_user.nickname}", "visibility" => "direct"}) + CommonAPI.post(user, %{status: "@#{other_user.nickname}", visibility: "direct"}) conn = conn @@ -599,7 +676,7 @@ test "get a direct status" do [participation] = Participation.for_user(user) - res = json_response(conn, 200) + res = json_response_and_validate_schema(conn, 200) assert res["pleroma"]["direct_conversation_id"] == participation.id end @@ -611,7 +688,8 @@ test "get statuses by IDs" do query_string = "ids[]=#{id1}&ids[]=#{id2}" conn = get(conn, "/api/v1/statuses/?#{query_string}") - assert [%{"id" => ^id1}, %{"id" => ^id2}] = Enum.sort_by(json_response(conn, :ok), & &1["id"]) + assert [%{"id" => ^id1}, %{"id" => ^id2}] = + Enum.sort_by(json_response_and_validate_schema(conn, :ok), & &1["id"]) end describe "getting statuses by ids with restricted unauthenticated for local and remote" do @@ -622,17 +700,17 @@ test "get statuses by IDs" do setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true) test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do - res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]}) + res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}") - assert json_response(res_conn, 200) == [] + assert json_response_and_validate_schema(res_conn, 200) == [] end test "if user is authenticated", %{local: local, remote: remote} do %{conn: conn} = oauth_access(["read"]) - res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]}) + res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}") - assert length(json_response(res_conn, 200)) == 2 + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end end @@ -642,18 +720,18 @@ test "if user is authenticated", %{local: local, remote: remote} do setup do: clear_config([:restrict_unauthenticated, :activities, :local], true) test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do - res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]}) + res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}") remote_id = remote.id - assert [%{"id" => ^remote_id}] = json_response(res_conn, 200) + assert [%{"id" => ^remote_id}] = json_response_and_validate_schema(res_conn, 200) end test "if user is authenticated", %{local: local, remote: remote} do %{conn: conn} = oauth_access(["read"]) - res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]}) + res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}") - assert length(json_response(res_conn, 200)) == 2 + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end end @@ -663,18 +741,18 @@ test "if user is authenticated", %{local: local, remote: remote} do setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true) test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do - res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]}) + res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}") local_id = local.id - assert [%{"id" => ^local_id}] = json_response(res_conn, 200) + assert [%{"id" => ^local_id}] = json_response_and_validate_schema(res_conn, 200) end test "if user is authenticated", %{local: local, remote: remote} do %{conn: conn} = oauth_access(["read"]) - res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]}) + res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}") - assert length(json_response(res_conn, 200)) == 2 + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end end @@ -688,7 +766,7 @@ test "when you created it" do |> assign(:user, author) |> delete("/api/v1/statuses/#{activity.id}") - assert %{} = json_response(conn, 200) + assert %{} = json_response_and_validate_schema(conn, 200) refute Activity.get_by_id(activity.id) end @@ -702,7 +780,7 @@ test "when it doesn't exist" do |> assign(:user, author) |> delete("/api/v1/statuses/#{String.downcase(activity.id)}") - assert %{"error" => "Record not found"} == json_response(conn, 404) + assert %{"error" => "Record not found"} == json_response_and_validate_schema(conn, 404) end test "when you didn't create it" do @@ -711,7 +789,7 @@ test "when you didn't create it" do conn = delete(conn, "/api/v1/statuses/#{activity.id}") - assert %{"error" => _} = json_response(conn, 403) + assert %{"error" => _} = json_response_and_validate_schema(conn, 403) assert Activity.get_by_id(activity.id) == activity end @@ -728,7 +806,7 @@ test "when you're an admin or moderator", %{conn: conn} do |> assign(:token, insert(:oauth_token, user: admin, scopes: ["write:statuses"])) |> delete("/api/v1/statuses/#{activity1.id}") - assert %{} = json_response(res_conn, 200) + assert %{} = json_response_and_validate_schema(res_conn, 200) res_conn = conn @@ -736,7 +814,7 @@ test "when you're an admin or moderator", %{conn: conn} do |> assign(:token, insert(:oauth_token, user: moderator, scopes: ["write:statuses"])) |> delete("/api/v1/statuses/#{activity2.id}") - assert %{} = json_response(res_conn, 200) + assert %{} = json_response_and_validate_schema(res_conn, 200) refute Activity.get_by_id(activity1.id) refute Activity.get_by_id(activity2.id) @@ -749,12 +827,15 @@ test "when you're an admin or moderator", %{conn: conn} do test "reblogs and returns the reblogged status", %{conn: conn} do activity = insert(:note_activity) - conn = post(conn, "/api/v1/statuses/#{activity.id}/reblog") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/reblog") assert %{ "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}, "reblogged" => true - } = json_response(conn, 200) + } = json_response_and_validate_schema(conn, 200) assert to_string(activity.id) == id end @@ -762,21 +843,30 @@ test "reblogs and returns the reblogged status", %{conn: conn} do test "returns 404 if the reblogged status doesn't exist", %{conn: conn} do activity = insert(:note_activity) - conn = post(conn, "/api/v1/statuses/#{String.downcase(activity.id)}/reblog") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{String.downcase(activity.id)}/reblog") - assert %{"error" => "Record not found"} = json_response(conn, 404) + assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404) end test "reblogs privately and returns the reblogged status", %{conn: conn} do activity = insert(:note_activity) - conn = post(conn, "/api/v1/statuses/#{activity.id}/reblog", %{"visibility" => "private"}) + conn = + conn + |> put_req_header("content-type", "application/json") + |> post( + "/api/v1/statuses/#{activity.id}/reblog", + %{"visibility" => "private"} + ) assert %{ "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}, "reblogged" => true, "visibility" => "private" - } = json_response(conn, 200) + } = json_response_and_validate_schema(conn, 200) assert to_string(activity.id) == id end @@ -802,7 +892,7 @@ test "reblogged status for another user" do "reblogged" => false, "favourited" => false, "bookmarked" => false - } = json_response(conn_res, 200) + } = json_response_and_validate_schema(conn_res, 200) conn_res = build_conn() @@ -815,7 +905,7 @@ test "reblogged status for another user" do "reblogged" => true, "favourited" => true, "bookmarked" => true - } = json_response(conn_res, 200) + } = json_response_and_validate_schema(conn_res, 200) assert to_string(activity.id) == id end @@ -829,17 +919,24 @@ test "unreblogs and returns the unreblogged status", %{user: user, conn: conn} d {:ok, _, _} = CommonAPI.repeat(activity.id, user) - conn = post(conn, "/api/v1/statuses/#{activity.id}/unreblog") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/unreblog") - assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200) + assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = + json_response_and_validate_schema(conn, 200) assert to_string(activity.id) == id end test "returns 404 error when activity does not exist", %{conn: conn} do - conn = post(conn, "/api/v1/statuses/foo/unreblog") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/foo/unreblog") - assert json_response(conn, 404) == %{"error" => "Record not found"} + assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"} end end @@ -849,10 +946,13 @@ test "returns 404 error when activity does not exist", %{conn: conn} do test "favs a status and returns it", %{conn: conn} do activity = insert(:note_activity) - conn = post(conn, "/api/v1/statuses/#{activity.id}/favourite") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/favourite") assert %{"id" => id, "favourites_count" => 1, "favourited" => true} = - json_response(conn, 200) + json_response_and_validate_schema(conn, 200) assert to_string(activity.id) == id end @@ -860,18 +960,23 @@ test "favs a status and returns it", %{conn: conn} do test "favoriting twice will just return 200", %{conn: conn} do activity = insert(:note_activity) - post(conn, "/api/v1/statuses/#{activity.id}/favourite") + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/favourite") - assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") - |> json_response(200) + assert conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/favourite") + |> json_response_and_validate_schema(200) end test "returns 404 error for a wrong id", %{conn: conn} do conn = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses/1/favourite") - assert json_response(conn, 404) == %{"error" => "Record not found"} + assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"} end end @@ -883,18 +988,24 @@ test "unfavorites a status and returns it", %{user: user, conn: conn} do {:ok, _} = CommonAPI.favorite(user, activity.id) - conn = post(conn, "/api/v1/statuses/#{activity.id}/unfavourite") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/unfavourite") assert %{"id" => id, "favourites_count" => 0, "favourited" => false} = - json_response(conn, 200) + json_response_and_validate_schema(conn, 200) assert to_string(activity.id) == id end test "returns 404 error for a wrong id", %{conn: conn} do - conn = post(conn, "/api/v1/statuses/1/unfavourite") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/1/unfavourite") - assert json_response(conn, 404) == %{"error" => "Record not found"} + assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"} end end @@ -902,7 +1013,7 @@ test "returns 404 error for a wrong id", %{conn: conn} do setup do: oauth_access(["write:accounts"]) setup %{user: user} do - {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"}) %{activity: activity} end @@ -914,21 +1025,25 @@ test "pin status", %{conn: conn, user: user, activity: activity} do assert %{"id" => ^id_str, "pinned" => true} = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses/#{activity.id}/pin") - |> json_response(200) + |> json_response_and_validate_schema(200) assert [%{"id" => ^id_str, "pinned" => true}] = conn |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true") - |> json_response(200) + |> json_response_and_validate_schema(200) end test "/pin: returns 400 error when activity is not public", %{conn: conn, user: user} do - {:ok, dm} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"}) + {:ok, dm} = CommonAPI.post(user, %{status: "test", visibility: "direct"}) - conn = post(conn, "/api/v1/statuses/#{dm.id}/pin") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{dm.id}/pin") - assert json_response(conn, 400) == %{"error" => "Could not pin"} + assert json_response_and_validate_schema(conn, 400) == %{"error" => "Could not pin"} end test "unpin status", %{conn: conn, user: user, activity: activity} do @@ -941,29 +1056,33 @@ test "unpin status", %{conn: conn, user: user, activity: activity} do conn |> assign(:user, user) |> post("/api/v1/statuses/#{activity.id}/unpin") - |> json_response(200) + |> json_response_and_validate_schema(200) assert [] = conn |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true") - |> json_response(200) + |> json_response_and_validate_schema(200) end test "/unpin: returns 400 error when activity is not exist", %{conn: conn} do - conn = post(conn, "/api/v1/statuses/1/unpin") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/1/unpin") - assert json_response(conn, 400) == %{"error" => "Could not unpin"} + assert json_response_and_validate_schema(conn, 400) == %{"error" => "Could not unpin"} end test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do - {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"}) id_str_one = to_string(activity_one.id) assert %{"id" => ^id_str_one, "pinned" => true} = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses/#{id_str_one}/pin") - |> json_response(200) + |> json_response_and_validate_schema(200) user = refresh_record(user) @@ -971,7 +1090,7 @@ test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do conn |> assign(:user, user) |> post("/api/v1/statuses/#{activity_two.id}/pin") - |> json_response(400) + |> json_response_and_validate_schema(400) end end @@ -985,7 +1104,7 @@ test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do test "returns rich-media card", %{conn: conn, user: user} do Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) - {:ok, activity} = CommonAPI.post(user, %{"status" => "https://example.com/ogp"}) + {:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp"}) card_data = %{ "image" => "http://ia.media-imdb.com/images/rock.jpg", @@ -1011,18 +1130,18 @@ test "returns rich-media card", %{conn: conn, user: user} do response = conn |> get("/api/v1/statuses/#{activity.id}/card") - |> json_response(200) + |> json_response_and_validate_schema(200) assert response == card_data # works with private posts {:ok, activity} = - CommonAPI.post(user, %{"status" => "https://example.com/ogp", "visibility" => "direct"}) + CommonAPI.post(user, %{status: "https://example.com/ogp", visibility: "direct"}) response_two = conn |> get("/api/v1/statuses/#{activity.id}/card") - |> json_response(200) + |> json_response_and_validate_schema(200) assert response_two == card_data end @@ -1030,13 +1149,12 @@ test "returns rich-media card", %{conn: conn, user: user} do test "replaces missing description with an empty string", %{conn: conn, user: user} do Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) - {:ok, activity} = - CommonAPI.post(user, %{"status" => "https://example.com/ogp-missing-data"}) + {:ok, activity} = CommonAPI.post(user, %{status: "https://example.com/ogp-missing-data"}) response = conn |> get("/api/v1/statuses/#{activity.id}/card") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert response == %{ "type" => "link", @@ -1063,36 +1181,42 @@ test "bookmarks" do %{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"]) author = insert(:user) - {:ok, activity1} = - CommonAPI.post(author, %{ - "status" => "heweoo?" - }) + {:ok, activity1} = CommonAPI.post(author, %{status: "heweoo?"}) + {:ok, activity2} = CommonAPI.post(author, %{status: "heweoo!"}) - {:ok, activity2} = - CommonAPI.post(author, %{ - "status" => "heweoo!" - }) + response1 = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity1.id}/bookmark") - response1 = post(conn, "/api/v1/statuses/#{activity1.id}/bookmark") + assert json_response_and_validate_schema(response1, 200)["bookmarked"] == true - assert json_response(response1, 200)["bookmarked"] == true + response2 = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity2.id}/bookmark") - response2 = post(conn, "/api/v1/statuses/#{activity2.id}/bookmark") - - assert json_response(response2, 200)["bookmarked"] == true + assert json_response_and_validate_schema(response2, 200)["bookmarked"] == true bookmarks = get(conn, bookmarks_uri) - assert [json_response(response2, 200), json_response(response1, 200)] == - json_response(bookmarks, 200) + assert [ + json_response_and_validate_schema(response2, 200), + json_response_and_validate_schema(response1, 200) + ] == + json_response_and_validate_schema(bookmarks, 200) - response1 = post(conn, "/api/v1/statuses/#{activity1.id}/unbookmark") + response1 = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity1.id}/unbookmark") - assert json_response(response1, 200)["bookmarked"] == false + assert json_response_and_validate_schema(response1, 200)["bookmarked"] == false bookmarks = get(conn, bookmarks_uri) - assert [json_response(response2, 200)] == json_response(bookmarks, 200) + assert [json_response_and_validate_schema(response2, 200)] == + json_response_and_validate_schema(bookmarks, 200) end describe "conversation muting" do @@ -1100,7 +1224,7 @@ test "bookmarks" do setup do post_user = insert(:user) - {:ok, activity} = CommonAPI.post(post_user, %{"status" => "HIE"}) + {:ok, activity} = CommonAPI.post(post_user, %{status: "HIE"}) %{activity: activity} end @@ -1109,16 +1233,22 @@ test "mute conversation", %{conn: conn, activity: activity} do assert %{"id" => ^id_str, "muted" => true} = conn + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses/#{activity.id}/mute") - |> json_response(200) + |> json_response_and_validate_schema(200) end test "cannot mute already muted conversation", %{conn: conn, user: user, activity: activity} do {:ok, _} = CommonAPI.add_mute(user, activity) - conn = post(conn, "/api/v1/statuses/#{activity.id}/mute") + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/statuses/#{activity.id}/mute") - assert json_response(conn, 400) == %{"error" => "conversation is already muted"} + assert json_response_and_validate_schema(conn, 400) == %{ + "error" => "conversation is already muted" + } end test "unmute conversation", %{conn: conn, user: user, activity: activity} do @@ -1130,7 +1260,7 @@ test "unmute conversation", %{conn: conn, user: user, activity: activity} do conn # |> assign(:user, user) |> post("/api/v1/statuses/#{activity.id}/unmute") - |> json_response(200) + |> json_response_and_validate_schema(200) end end @@ -1139,16 +1269,17 @@ test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{c user2 = insert(:user) user3 = insert(:user) - {:ok, replied_to} = CommonAPI.post(user1, %{"status" => "cofe"}) + {:ok, replied_to} = CommonAPI.post(user1, %{status: "cofe"}) # Reply to status from another user conn1 = conn |> assign(:user, user2) |> assign(:token, insert(:oauth_token, user: user2, scopes: ["write:statuses"])) + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id}) - assert %{"content" => "xD", "id" => id} = json_response(conn1, 200) + assert %{"content" => "xD", "id" => id} = json_response_and_validate_schema(conn1, 200) activity = Activity.get_by_id_with_object(id) @@ -1160,10 +1291,11 @@ test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{c conn |> assign(:user, user3) |> assign(:token, insert(:oauth_token, user: user3, scopes: ["write:statuses"])) + |> put_req_header("content-type", "application/json") |> post("/api/v1/statuses/#{activity.id}/reblog") assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} = - json_response(conn2, 200) + json_response_and_validate_schema(conn2, 200) assert to_string(activity.id) == id @@ -1186,7 +1318,7 @@ test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{c setup do: oauth_access(["read:accounts"]) setup %{user: user} do - {:ok, activity} = CommonAPI.post(user, %{"status" => "test"}) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) %{activity: activity} end @@ -1198,7 +1330,7 @@ test "returns users who have favorited the status", %{conn: conn, activity: acti response = conn |> get("/api/v1/statuses/#{activity.id}/favourited_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) [%{"id" => id}] = response @@ -1212,7 +1344,7 @@ test "returns empty array when status has not been favorited yet", %{ response = conn |> get("/api/v1/statuses/#{activity.id}/favourited_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert Enum.empty?(response) end @@ -1229,7 +1361,7 @@ test "does not return users who have favorited the status but are blocked", %{ response = conn |> get("/api/v1/statuses/#{activity.id}/favourited_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert Enum.empty?(response) end @@ -1241,7 +1373,7 @@ test "does not fail on an unauthenticated request", %{activity: activity} do response = build_conn() |> get("/api/v1/statuses/#{activity.id}/favourited_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) [%{"id" => id}] = response assert id == other_user.id @@ -1252,8 +1384,8 @@ test "requires authentication for private posts", %{user: user} do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "@#{other_user.nickname} wanna get some #cofe together?", - "visibility" => "direct" + status: "@#{other_user.nickname} wanna get some #cofe together?", + visibility: "direct" }) {:ok, _} = CommonAPI.favorite(other_user, activity.id) @@ -1262,7 +1394,7 @@ test "requires authentication for private posts", %{user: user} do build_conn() |> get(favourited_by_url) - |> json_response(404) + |> json_response_and_validate_schema(404) conn = build_conn() @@ -1272,12 +1404,12 @@ test "requires authentication for private posts", %{user: user} do conn |> assign(:token, nil) |> get(favourited_by_url) - |> json_response(404) + |> json_response_and_validate_schema(404) response = conn |> get(favourited_by_url) - |> json_response(200) + |> json_response_and_validate_schema(200) [%{"id" => id}] = response assert id == other_user.id @@ -1288,7 +1420,7 @@ test "requires authentication for private posts", %{user: user} do setup do: oauth_access(["read:accounts"]) setup %{user: user} do - {:ok, activity} = CommonAPI.post(user, %{"status" => "test"}) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) %{activity: activity} end @@ -1300,7 +1432,7 @@ test "returns users who have reblogged the status", %{conn: conn, activity: acti response = conn |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) [%{"id" => id}] = response @@ -1314,7 +1446,7 @@ test "returns empty array when status has not been reblogged yet", %{ response = conn |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert Enum.empty?(response) end @@ -1331,7 +1463,7 @@ test "does not return users who have reblogged the status but are blocked", %{ response = conn |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert Enum.empty?(response) end @@ -1342,12 +1474,12 @@ test "does not return users who have reblogged the status privately", %{ } do other_user = insert(:user) - {:ok, _, _} = CommonAPI.repeat(activity.id, other_user, %{"visibility" => "private"}) + {:ok, _, _} = CommonAPI.repeat(activity.id, other_user, %{visibility: "private"}) response = conn |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert Enum.empty?(response) end @@ -1359,7 +1491,7 @@ test "does not fail on an unauthenticated request", %{activity: activity} do response = build_conn() |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) [%{"id" => id}] = response assert id == other_user.id @@ -1370,20 +1502,20 @@ test "requires authentication for private posts", %{user: user} do {:ok, activity} = CommonAPI.post(user, %{ - "status" => "@#{other_user.nickname} wanna get some #cofe together?", - "visibility" => "direct" + status: "@#{other_user.nickname} wanna get some #cofe together?", + visibility: "direct" }) build_conn() |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(404) + |> json_response_and_validate_schema(404) response = build_conn() |> assign(:user, other_user) |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"])) |> get("/api/v1/statuses/#{activity.id}/reblogged_by") - |> json_response(200) + |> json_response_and_validate_schema(200) assert [] == response end @@ -1392,16 +1524,16 @@ test "requires authentication for private posts", %{user: user} do test "context" do user = insert(:user) - {:ok, %{id: id1}} = CommonAPI.post(user, %{"status" => "1"}) - {:ok, %{id: id2}} = CommonAPI.post(user, %{"status" => "2", "in_reply_to_status_id" => id1}) - {:ok, %{id: id3}} = CommonAPI.post(user, %{"status" => "3", "in_reply_to_status_id" => id2}) - {:ok, %{id: id4}} = CommonAPI.post(user, %{"status" => "4", "in_reply_to_status_id" => id3}) - {:ok, %{id: id5}} = CommonAPI.post(user, %{"status" => "5", "in_reply_to_status_id" => id4}) + {:ok, %{id: id1}} = CommonAPI.post(user, %{status: "1"}) + {:ok, %{id: id2}} = CommonAPI.post(user, %{status: "2", in_reply_to_status_id: id1}) + {:ok, %{id: id3}} = CommonAPI.post(user, %{status: "3", in_reply_to_status_id: id2}) + {:ok, %{id: id4}} = CommonAPI.post(user, %{status: "4", in_reply_to_status_id: id3}) + {:ok, %{id: id5}} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4}) response = build_conn() |> get("/api/v1/statuses/#{id3}/context") - |> json_response(:ok) + |> json_response_and_validate_schema(:ok) assert %{ "ancestors" => [%{"id" => ^id1}, %{"id" => ^id2}], @@ -1413,14 +1545,14 @@ test "returns the favorites of a user" do %{user: user, conn: conn} = oauth_access(["read:favourites"]) other_user = insert(:user) - {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"}) - {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"}) + {:ok, _} = CommonAPI.post(other_user, %{status: "bla"}) + {:ok, activity} = CommonAPI.post(other_user, %{status: "traps are happy"}) {:ok, _} = CommonAPI.favorite(user, activity.id) first_conn = get(conn, "/api/v1/favourites") - assert [status] = json_response(first_conn, 200) + assert [status] = json_response_and_validate_schema(first_conn, 200) assert status["id"] == to_string(activity.id) assert [{"link", _link_header}] = @@ -1429,8 +1561,7 @@ test "returns the favorites of a user" do # Honours query params {:ok, second_activity} = CommonAPI.post(other_user, %{ - "status" => - "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." + status: "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful." }) {:ok, _} = CommonAPI.favorite(user, second_activity.id) @@ -1439,17 +1570,17 @@ test "returns the favorites of a user" do second_conn = get(conn, "/api/v1/favourites?since_id=#{last_like}") - assert [second_status] = json_response(second_conn, 200) + assert [second_status] = json_response_and_validate_schema(second_conn, 200) assert second_status["id"] == to_string(second_activity.id) third_conn = get(conn, "/api/v1/favourites?limit=0") - assert [] = json_response(third_conn, 200) + assert [] = json_response_and_validate_schema(third_conn, 200) end test "expires_at is nil for another user" do %{conn: conn, user: user} = oauth_access(["read:statuses"]) - {:ok, activity} = CommonAPI.post(user, %{"status" => "foobar", "expires_in" => 1_000_000}) + {:ok, activity} = CommonAPI.post(user, %{status: "foobar", expires_in: 1_000_000}) expires_at = activity.id @@ -1458,11 +1589,15 @@ test "expires_at is nil for another user" do |> NaiveDateTime.to_iso8601() assert %{"pleroma" => %{"expires_at" => ^expires_at}} = - conn |> get("/api/v1/statuses/#{activity.id}") |> json_response(:ok) + conn + |> get("/api/v1/statuses/#{activity.id}") + |> json_response_and_validate_schema(:ok) %{conn: conn} = oauth_access(["read:statuses"]) assert %{"pleroma" => %{"expires_at" => nil}} = - conn |> get("/api/v1/statuses/#{activity.id}") |> json_response(:ok) + conn + |> get("/api/v1/statuses/#{activity.id}") + |> json_response_and_validate_schema(:ok) end end diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs index f120bd0cd..7f08e187c 100644 --- a/test/web/mastodon_api/controllers/suggestion_controller_test.exs +++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs @@ -11,7 +11,7 @@ test "returns empty result", %{conn: conn} do res = conn |> get("/api/v1/suggestions") - |> json_response(200) + |> json_response_and_validate_schema(200) assert res == [] end diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index 06efdc901..f8b9289f3 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -28,13 +28,13 @@ test "does NOT render account/pleroma/relationship if this is disabled by defaul other_user = insert(:user) - {:ok, _} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) response = conn |> assign(:user, user) |> get("/api/v1/timelines/home") - |> json_response(200) + |> json_response_and_validate_schema(200) assert Enum.all?(response, fn n -> get_in(n, ["account", "pleroma", "relationship"]) == %{} @@ -42,18 +42,18 @@ test "does NOT render account/pleroma/relationship if this is disabled by defaul end test "the home timeline", %{user: user, conn: conn} do - uri = "/api/v1/timelines/home?with_relationships=true" + uri = "/api/v1/timelines/home?with_relationships=1" following = insert(:user, nickname: "followed") third_user = insert(:user, nickname: "repeated") - {:ok, _activity} = CommonAPI.post(following, %{"status" => "post"}) - {:ok, activity} = CommonAPI.post(third_user, %{"status" => "repeated post"}) + {:ok, _activity} = CommonAPI.post(following, %{status: "post"}) + {:ok, activity} = CommonAPI.post(third_user, %{status: "repeated post"}) {:ok, _, _} = CommonAPI.repeat(activity.id, following) ret_conn = get(conn, uri) - assert Enum.empty?(json_response(ret_conn, :ok)) + assert Enum.empty?(json_response_and_validate_schema(ret_conn, :ok)) {:ok, _user} = User.follow(user, following) @@ -78,7 +78,7 @@ test "the home timeline", %{user: user, conn: conn} do "pleroma" => %{"relationship" => %{"following" => true}} } } - ] = json_response(ret_conn, :ok) + ] = json_response_and_validate_schema(ret_conn, :ok) {:ok, _user} = User.follow(third_user, user) @@ -104,22 +104,20 @@ test "the home timeline", %{user: user, conn: conn} do "pleroma" => %{"relationship" => %{"following" => true}} } } - ] = json_response(ret_conn, :ok) + ] = json_response_and_validate_schema(ret_conn, :ok) end test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do - {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"}) - {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"}) + {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"}) + {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"}) - {:ok, unlisted_activity} = - CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"}) + {:ok, unlisted_activity} = CommonAPI.post(user, %{status: ".", visibility: "unlisted"}) - {:ok, private_activity} = - CommonAPI.post(user, %{"status" => ".", "visibility" => "private"}) + {:ok, private_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"}) - conn = get(conn, "/api/v1/timelines/home", %{"exclude_visibilities" => ["direct"]}) + conn = get(conn, "/api/v1/timelines/home?exclude_visibilities[]=direct") - assert status_ids = json_response(conn, :ok) |> Enum.map(& &1["id"]) + assert status_ids = json_response_and_validate_schema(conn, :ok) |> Enum.map(& &1["id"]) assert public_activity.id in status_ids assert unlisted_activity.id in status_ids assert private_activity.id in status_ids @@ -132,33 +130,33 @@ test "the home timeline when the direct messages are excluded", %{user: user, co test "the public timeline", %{conn: conn} do following = insert(:user) - {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"}) + {:ok, _activity} = CommonAPI.post(following, %{status: "test"}) _activity = insert(:note_activity, local: false) - conn = get(conn, "/api/v1/timelines/public", %{"local" => "False"}) + conn = get(conn, "/api/v1/timelines/public?local=False") - assert length(json_response(conn, :ok)) == 2 + assert length(json_response_and_validate_schema(conn, :ok)) == 2 - conn = get(build_conn(), "/api/v1/timelines/public", %{"local" => "True"}) + conn = get(build_conn(), "/api/v1/timelines/public?local=True") - assert [%{"content" => "test"}] = json_response(conn, :ok) + assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok) - conn = get(build_conn(), "/api/v1/timelines/public", %{"local" => "1"}) + conn = get(build_conn(), "/api/v1/timelines/public?local=1") - assert [%{"content" => "test"}] = json_response(conn, :ok) + assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok) end test "the public timeline includes only public statuses for an authenticated user" do %{user: user, conn: conn} = oauth_access(["read:statuses"]) - {:ok, _activity} = CommonAPI.post(user, %{"status" => "test"}) - {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "private"}) - {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "unlisted"}) - {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"}) + {:ok, _activity} = CommonAPI.post(user, %{status: "test"}) + {:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "private"}) + {:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "unlisted"}) + {:ok, _activity} = CommonAPI.post(user, %{status: "test", visibility: "direct"}) res_conn = get(conn, "/api/v1/timelines/public") - assert length(json_response(res_conn, 200)) == 1 + assert length(json_response_and_validate_schema(res_conn, 200)) == 1 end end @@ -176,15 +174,15 @@ defp local_and_remote_activities do setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true) test "if user is unauthenticated", %{conn: conn} do - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"}) + res_conn = get(conn, "/api/v1/timelines/public?local=true") - assert json_response(res_conn, :unauthorized) == %{ + assert json_response_and_validate_schema(res_conn, :unauthorized) == %{ "error" => "authorization required for timeline view" } - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"}) + res_conn = get(conn, "/api/v1/timelines/public?local=false") - assert json_response(res_conn, :unauthorized) == %{ + assert json_response_and_validate_schema(res_conn, :unauthorized) == %{ "error" => "authorization required for timeline view" } end @@ -192,11 +190,11 @@ test "if user is unauthenticated", %{conn: conn} do test "if user is authenticated" do %{conn: conn} = oauth_access(["read:statuses"]) - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"}) - assert length(json_response(res_conn, 200)) == 1 + res_conn = get(conn, "/api/v1/timelines/public?local=true") + assert length(json_response_and_validate_schema(res_conn, 200)) == 1 - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"}) - assert length(json_response(res_conn, 200)) == 2 + res_conn = get(conn, "/api/v1/timelines/public?local=false") + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end end @@ -206,24 +204,24 @@ test "if user is authenticated" do setup do: clear_config([:restrict_unauthenticated, :timelines, :local], true) test "if user is unauthenticated", %{conn: conn} do - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"}) + res_conn = get(conn, "/api/v1/timelines/public?local=true") - assert json_response(res_conn, :unauthorized) == %{ + assert json_response_and_validate_schema(res_conn, :unauthorized) == %{ "error" => "authorization required for timeline view" } - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"}) - assert length(json_response(res_conn, 200)) == 2 + res_conn = get(conn, "/api/v1/timelines/public?local=false") + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end test "if user is authenticated", %{conn: _conn} do %{conn: conn} = oauth_access(["read:statuses"]) - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"}) - assert length(json_response(res_conn, 200)) == 1 + res_conn = get(conn, "/api/v1/timelines/public?local=true") + assert length(json_response_and_validate_schema(res_conn, 200)) == 1 - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"}) - assert length(json_response(res_conn, 200)) == 2 + res_conn = get(conn, "/api/v1/timelines/public?local=false") + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end end @@ -233,12 +231,12 @@ test "if user is authenticated", %{conn: _conn} do setup do: clear_config([:restrict_unauthenticated, :timelines, :federated], true) test "if user is unauthenticated", %{conn: conn} do - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"}) - assert length(json_response(res_conn, 200)) == 1 + res_conn = get(conn, "/api/v1/timelines/public?local=true") + assert length(json_response_and_validate_schema(res_conn, 200)) == 1 - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"}) + res_conn = get(conn, "/api/v1/timelines/public?local=false") - assert json_response(res_conn, :unauthorized) == %{ + assert json_response_and_validate_schema(res_conn, :unauthorized) == %{ "error" => "authorization required for timeline view" } end @@ -246,11 +244,11 @@ test "if user is unauthenticated", %{conn: conn} do test "if user is authenticated", %{conn: _conn} do %{conn: conn} = oauth_access(["read:statuses"]) - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "true"}) - assert length(json_response(res_conn, 200)) == 1 + res_conn = get(conn, "/api/v1/timelines/public?local=true") + assert length(json_response_and_validate_schema(res_conn, 200)) == 1 - res_conn = get(conn, "/api/v1/timelines/public", %{"local" => "false"}) - assert length(json_response(res_conn, 200)) == 2 + res_conn = get(conn, "/api/v1/timelines/public?local=false") + assert length(json_response_and_validate_schema(res_conn, 200)) == 2 end end @@ -263,14 +261,14 @@ test "direct timeline", %{conn: conn} do {:ok, direct} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}!", + visibility: "direct" }) {:ok, _follower_only} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}!", - "visibility" => "private" + status: "Hi @#{user_two.nickname}!", + visibility: "private" }) conn_user_two = @@ -281,7 +279,7 @@ test "direct timeline", %{conn: conn} do # Only direct should be visible here res_conn = get(conn_user_two, "api/v1/timelines/direct") - [status] = json_response(res_conn, :ok) + assert [status] = json_response_and_validate_schema(res_conn, :ok) assert %{"visibility" => "direct"} = status assert status["url"] != direct.data["id"] @@ -293,33 +291,34 @@ test "direct timeline", %{conn: conn} do |> assign(:token, insert(:oauth_token, user: user_one, scopes: ["read:statuses"])) |> get("api/v1/timelines/direct") - [status] = json_response(res_conn, :ok) + [status] = json_response_and_validate_schema(res_conn, :ok) assert %{"visibility" => "direct"} = status # Both should be visible here res_conn = get(conn_user_two, "api/v1/timelines/home") - [_s1, _s2] = json_response(res_conn, :ok) + [_s1, _s2] = json_response_and_validate_schema(res_conn, :ok) # Test pagination Enum.each(1..20, fn _ -> {:ok, _} = CommonAPI.post(user_one, %{ - "status" => "Hi @#{user_two.nickname}!", - "visibility" => "direct" + status: "Hi @#{user_two.nickname}!", + visibility: "direct" }) end) res_conn = get(conn_user_two, "api/v1/timelines/direct") - statuses = json_response(res_conn, :ok) + statuses = json_response_and_validate_schema(res_conn, :ok) assert length(statuses) == 20 - res_conn = - get(conn_user_two, "api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]}) + max_id = List.last(statuses)["id"] - [status] = json_response(res_conn, :ok) + res_conn = get(conn_user_two, "api/v1/timelines/direct?max_id=#{max_id}") + + assert [status] = json_response_and_validate_schema(res_conn, :ok) assert status["url"] != direct.data["id"] end @@ -332,19 +331,19 @@ test "doesn't include DMs from blocked users" do {:ok, _blocked_direct} = CommonAPI.post(blocked, %{ - "status" => "Hi @#{blocker.nickname}!", - "visibility" => "direct" + status: "Hi @#{blocker.nickname}!", + visibility: "direct" }) {:ok, direct} = CommonAPI.post(other_user, %{ - "status" => "Hi @#{blocker.nickname}!", - "visibility" => "direct" + status: "Hi @#{blocker.nickname}!", + visibility: "direct" }) res_conn = get(conn, "api/v1/timelines/direct") - [status] = json_response(res_conn, :ok) + [status] = json_response_and_validate_schema(res_conn, :ok) assert status["id"] == direct.id end end @@ -354,14 +353,14 @@ test "doesn't include DMs from blocked users" do test "list timeline", %{user: user, conn: conn} do other_user = insert(:user) - {:ok, _activity_one} = CommonAPI.post(user, %{"status" => "Marisa is cute."}) - {:ok, activity_two} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."}) + {:ok, _activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."}) + {:ok, activity_two} = CommonAPI.post(other_user, %{status: "Marisa is cute."}) {:ok, list} = Pleroma.List.create("name", user) {:ok, list} = Pleroma.List.follow(list, other_user) conn = get(conn, "/api/v1/timelines/list/#{list.id}") - assert [%{"id" => id}] = json_response(conn, :ok) + assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok) assert id == to_string(activity_two.id) end @@ -371,12 +370,12 @@ test "list timeline does not leak non-public statuses for unfollowed users", %{ conn: conn } do other_user = insert(:user) - {:ok, activity_one} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."}) + {:ok, activity_one} = CommonAPI.post(other_user, %{status: "Marisa is cute."}) {:ok, _activity_two} = CommonAPI.post(other_user, %{ - "status" => "Marisa is cute.", - "visibility" => "private" + status: "Marisa is cute.", + visibility: "private" }) {:ok, list} = Pleroma.List.create("name", user) @@ -384,7 +383,7 @@ test "list timeline does not leak non-public statuses for unfollowed users", %{ conn = get(conn, "/api/v1/timelines/list/#{list.id}") - assert [%{"id" => id}] = json_response(conn, :ok) + assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok) assert id == to_string(activity_one.id) end @@ -397,18 +396,18 @@ test "list timeline does not leak non-public statuses for unfollowed users", %{ test "hashtag timeline", %{conn: conn} do following = insert(:user) - {:ok, activity} = CommonAPI.post(following, %{"status" => "test #2hu"}) + {:ok, activity} = CommonAPI.post(following, %{status: "test #2hu"}) nconn = get(conn, "/api/v1/timelines/tag/2hu") - assert [%{"id" => id}] = json_response(nconn, :ok) + assert [%{"id" => id}] = json_response_and_validate_schema(nconn, :ok) assert id == to_string(activity.id) # works for different capitalization too nconn = get(conn, "/api/v1/timelines/tag/2HU") - assert [%{"id" => id}] = json_response(nconn, :ok) + assert [%{"id" => id}] = json_response_and_validate_schema(nconn, :ok) assert id == to_string(activity.id) end @@ -416,26 +415,25 @@ test "hashtag timeline", %{conn: conn} do test "multi-hashtag timeline", %{conn: conn} do user = insert(:user) - {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"}) - {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"}) - {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"}) + {:ok, activity_test} = CommonAPI.post(user, %{status: "#test"}) + {:ok, activity_test1} = CommonAPI.post(user, %{status: "#test #test1"}) + {:ok, activity_none} = CommonAPI.post(user, %{status: "#test #none"}) - any_test = get(conn, "/api/v1/timelines/tag/test", %{"any" => ["test1"]}) + any_test = get(conn, "/api/v1/timelines/tag/test?any[]=test1") - [status_none, status_test1, status_test] = json_response(any_test, :ok) + [status_none, status_test1, status_test] = json_response_and_validate_schema(any_test, :ok) assert to_string(activity_test.id) == status_test["id"] assert to_string(activity_test1.id) == status_test1["id"] assert to_string(activity_none.id) == status_none["id"] - restricted_test = - get(conn, "/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]}) + restricted_test = get(conn, "/api/v1/timelines/tag/test?all[]=test1&none[]=none") - assert [status_test1] == json_response(restricted_test, :ok) + assert [status_test1] == json_response_and_validate_schema(restricted_test, :ok) - all_test = get(conn, "/api/v1/timelines/tag/test", %{"all" => ["none"]}) + all_test = get(conn, "/api/v1/timelines/tag/test?all[]=none") - assert [status_none] == json_response(all_test, :ok) + assert [status_none] == json_response_and_validate_schema(all_test, :ok) end end end diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs index cb971806a..a7f9c5205 100644 --- a/test/web/mastodon_api/mastodon_api_test.exs +++ b/test/web/mastodon_api/mastodon_api_test.exs @@ -75,9 +75,9 @@ test "returns notifications for user" do User.subscribe(subscriber, user) - {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"}) + {:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"}) - {:ok, status1} = CommonAPI.post(user, %{"status" => "Magi"}) + {:ok, status1} = CommonAPI.post(user, %{status: "Magi"}) {:ok, [notification]} = Notification.create_notifications(status) {:ok, [notification1]} = Notification.create_notifications(status1) res = MastodonAPI.get_notifications(subscriber) diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 5fb162141..69ddbb5d4 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -31,7 +31,7 @@ test "Represent a user account" do nickname: "shp@shitposter.club", name: ":karjalanpiirakka: shp", bio: - "valid html. a