Merge remote-tracking branch 'remotes/origin/develop' into 2168-media-preview-proxy
# Conflicts: # mix.lock
This commit is contained in:
commit
e4b12494d7
|
@ -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
|
||||
|
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- NodeInfo: `pleroma:api/v1/notifications:include_types_filter` to the `features` list.
|
||||
- NodeInfo: `pleroma_emoji_reactions` to the `features` list.
|
||||
- Configuration: `:restrict_unauthenticated` setting, restrict access for unauthenticated users to timelines (public and federate), user profiles and statuses.
|
||||
- Configuration: Add `:database_config_whitelist` setting to whitelist settings which can be configured from AdminFE.
|
||||
- New HTTP adapter [gun](https://github.com/ninenines/gun). Gun adapter requires minimum OTP version of 22.2 otherwise Pleroma won’t start. For hackney OTP update is not required.
|
||||
- Mix task to create trusted OAuth App.
|
||||
- Notifications: Added `follow_request` notification type.
|
||||
|
@ -40,24 +41,45 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Filtering of push notifications on activities from blocked domains
|
||||
- Resolving Peertube accounts with Webfinger
|
||||
|
||||
## [unreleased-patch]
|
||||
## [Unreleased (patch)]
|
||||
|
||||
### 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
|
||||
|
||||
### Security
|
||||
- Disallow re-registration of previously deleted users, which allowed viewing direct messages addressed to them
|
||||
- Mastodon API: Fix `POST /api/v1/follow_requests/:id/authorize` allowing to force a follow from a local user even if they didn't request to follow
|
||||
- CSP: Sandbox uploads
|
||||
|
||||
### Fixed
|
||||
- Logger configuration through AdminFE
|
||||
- Notifications from blocked domains
|
||||
- Potential federation issues with Mastodon versions before 3.0.0
|
||||
- HTTP Basic Authentication permissions issue
|
||||
- Follow/Block imports not being able to find the user if the nickname started with an `@`
|
||||
- Instance stats counting internal users
|
||||
- Inability to run a From Source release without git
|
||||
- ObjectAgePolicy didn't filter out old messages
|
||||
- Transmogrifier: Keep object sensitive settings for outgoing representation (AP C2S)
|
||||
- `blob:` urls not being allowed by CSP
|
||||
|
||||
### Added
|
||||
- NodeInfo: ObjectAgePolicy settings to the `federation` list.
|
||||
- Follow request notifications
|
||||
<details>
|
||||
<summary>API Changes</summary>
|
||||
- Admin API: `GET /api/pleroma/admin/need_reboot`.
|
||||
</details>
|
||||
|
||||
### Upgrade notes
|
||||
|
||||
1. Restart Pleroma
|
||||
2. Run database migrations (inside Pleroma directory):
|
||||
- OTP: `./bin/pleroma_ctl migrate`
|
||||
- From Source: `mix ecto.migrate`
|
||||
|
||||
|
||||
## [2.0.2] - 2020-04-08
|
||||
### Added
|
||||
- Support for Funkwhale's `Audio` activity
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -911,6 +911,21 @@ config :auto_linker,
|
|||
|
||||
Boolean, enables/disables in-database configuration. Read [Transfering the config to/from the database](../administration/CLI_tasks/config.md) for more information.
|
||||
|
||||
## :database_config_whitelist
|
||||
|
||||
List of valid configuration sections which are allowed to be configured from the
|
||||
database. Settings stored in the database before the whitelist is configured are
|
||||
still applied, so it is suggested to only use the whitelist on instances that
|
||||
have not migrated the config to the database.
|
||||
|
||||
Example:
|
||||
```elixir
|
||||
config :pleroma, :database_config_whitelist, [
|
||||
{:pleroma, :instance},
|
||||
{:pleroma, Pleroma.Web.Metadata},
|
||||
{:auto_linker}
|
||||
]
|
||||
```
|
||||
|
||||
### Multi-factor authentication - :two_factor_authentication
|
||||
* `totp` - a list containing TOTP configuration
|
||||
|
|
|
@ -1,21 +1,45 @@
|
|||
#!/sbin/openrc-run
|
||||
|
||||
# Requires OpenRC >= 0.35
|
||||
directory=/opt/pleroma
|
||||
|
||||
command=/usr/bin/mix
|
||||
command_args="phx.server"
|
||||
supervisor=supervise-daemon
|
||||
command_user=pleroma:pleroma
|
||||
command_background=1
|
||||
|
||||
export PORT=4000
|
||||
export MIX_ENV=prod
|
||||
|
||||
# Ask process to terminate within 30 seconds, otherwise kill it
|
||||
retry="SIGTERM/30/SIGKILL/5"
|
||||
|
||||
pidfile="/var/run/pleroma.pid"
|
||||
directory=/opt/pleroma
|
||||
healthcheck_delay=60
|
||||
healthcheck_timer=30
|
||||
|
||||
: ${pleroma_port:-4000}
|
||||
|
||||
# Needs OpenRC >= 0.42
|
||||
#respawn_max=0
|
||||
#respawn_delay=5
|
||||
|
||||
# put pleroma_console=YES in /etc/conf.d/pleroma if you want to be able to
|
||||
# connect to pleroma via an elixir console
|
||||
if yesno "${pleroma_console}"; then
|
||||
command=elixir
|
||||
command_args="--name pleroma@127.0.0.1 --erl '-kernel inet_dist_listen_min 9001 inet_dist_listen_max 9001 inet_dist_use_interface {127,0,0,1}' -S mix phx.server"
|
||||
|
||||
start_post() {
|
||||
einfo "You can get a console by using this command as pleroma's user:"
|
||||
einfo "iex --name console@127.0.0.1 --remsh pleroma@127.0.0.1"
|
||||
}
|
||||
else
|
||||
command=/usr/bin/mix
|
||||
command_args="phx.server"
|
||||
fi
|
||||
|
||||
export MIX_ENV=prod
|
||||
|
||||
depend() {
|
||||
need nginx postgresql
|
||||
need nginx postgresql
|
||||
}
|
||||
|
||||
healthcheck() {
|
||||
# put pleroma_health=YES in /etc/conf.d/pleroma if you want healthchecking
|
||||
# and make sure you have curl installed
|
||||
yesno "$pleroma_health" || return 0
|
||||
|
||||
curl -q "localhost:${pleroma_port}/api/pleroma/healthcheck"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
defmodule Pleroma.BBS.Authenticator do
|
||||
use Sshd.PasswordAuthenticator
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Plugs.AuthenticationPlug
|
||||
alias Pleroma.User
|
||||
|
||||
def authenticate(username, password) do
|
||||
|
@ -12,7 +12,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)
|
||||
AuthenticationPlug.checkpw(password, user.password_hash)
|
||||
else
|
||||
_e -> false
|
||||
end
|
||||
|
|
|
@ -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...")
|
||||
|
|
|
@ -17,7 +17,8 @@ defmodule Pleroma.Constants do
|
|||
"announcement_count",
|
||||
"emoji",
|
||||
"context_id",
|
||||
"deleted_activity_id"
|
||||
"deleted_activity_id",
|
||||
"pleroma_internal"
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ def compile do
|
|||
with config <- Pleroma.Config.Loader.read("config/description.exs") do
|
||||
config[:pleroma][:config_description]
|
||||
|> Pleroma.Docs.Generator.convert_to_strings()
|
||||
|> Jason.encode!()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ defmodule Pleroma.Healthcheck do
|
|||
@spec system_info() :: t()
|
||||
def system_info do
|
||||
%Healthcheck{
|
||||
memory_used: Float.round(:erlang.memory(:total) / 1024 / 1024, 2)
|
||||
memory_used: Float.round(:recon_alloc.memory(:allocated) / 1024 / 1024, 2)
|
||||
}
|
||||
|> assign_db_info()
|
||||
|> assign_job_queue_stats()
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -17,8 +16,13 @@ def checkpw(password, "$6" <> _ = password_hash) do
|
|||
:crypt.crypt(password, password_hash) == password_hash
|
||||
end
|
||||
|
||||
def checkpw(password, "$2" <> _ = password_hash) do
|
||||
# Handle bcrypt passwords for Mastodon migration
|
||||
Bcrypt.verify_pass(password, password_hash)
|
||||
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 +41,7 @@ def call(
|
|||
} = conn,
|
||||
_
|
||||
) do
|
||||
if Pbkdf2.checkpw(password, password_hash) do
|
||||
if checkpw(password, password_hash) do
|
||||
conn
|
||||
|> assign(:user, auth_user)
|
||||
|> OAuthScopesPlug.skip_plug()
|
||||
|
@ -47,7 +51,7 @@ def call(
|
|||
end
|
||||
|
||||
def call(%{assigns: %{auth_credentials: %{password: _}}} = conn, _) do
|
||||
Pbkdf2.dummy_checkpw()
|
||||
Pbkdf2.no_user_verify()
|
||||
conn
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -134,7 +134,7 @@ defp prepare_upload(%Plug.Upload{} = file, opts) do
|
|||
end
|
||||
end
|
||||
|
||||
defp prepare_upload(%{"img" => "data:image/" <> image_data}, opts) do
|
||||
defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do
|
||||
parsed = Regex.named_captures(~r/(?<filetype>jpeg|png|gif);base64,(?<data>.*)/, image_data)
|
||||
data = Base.decode64!(parsed["data"], ignore: :whitespace)
|
||||
hash = String.downcase(Base.encode16(:crypto.hash(:sha256, data)))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -51,6 +51,7 @@ def add_deleted_activity_id(cng) do
|
|||
Page
|
||||
Question
|
||||
Video
|
||||
Tombstone
|
||||
}
|
||||
def validate_data(cng) do
|
||||
cng
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
|
||||
require Logger
|
||||
|
||||
@descriptions_json Pleroma.Docs.JSON.compile()
|
||||
@descriptions Pleroma.Docs.JSON.compile()
|
||||
@users_page_size 50
|
||||
|
||||
plug(
|
||||
|
@ -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
|
||||
|
@ -892,9 +897,9 @@ def list_log(conn, params) do
|
|||
end
|
||||
|
||||
def config_descriptions(conn, _params) do
|
||||
conn
|
||||
|> Plug.Conn.put_resp_content_type("application/json")
|
||||
|> Plug.Conn.send_resp(200, @descriptions_json)
|
||||
descriptions = Enum.filter(@descriptions, &whitelisted_config?/1)
|
||||
|
||||
json(conn, descriptions)
|
||||
end
|
||||
|
||||
def config_show(conn, %{"only_db" => true}) do
|
||||
|
@ -949,7 +954,9 @@ def config_show(conn, _params) do
|
|||
def config_update(conn, %{"configs" => configs}) do
|
||||
with :ok <- configurable_from_database(conn) do
|
||||
{_errors, results} =
|
||||
Enum.map(configs, fn
|
||||
configs
|
||||
|> Enum.filter(&whitelisted_config?/1)
|
||||
|> Enum.map(fn
|
||||
%{"group" => group, "key" => key, "delete" => true} = params ->
|
||||
ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
|
||||
|
||||
|
@ -1011,6 +1018,28 @@ defp configurable_from_database(conn) do
|
|||
end
|
||||
end
|
||||
|
||||
defp whitelisted_config?(group, key) do
|
||||
if whitelisted_configs = Config.get(:database_config_whitelist) do
|
||||
Enum.any?(whitelisted_configs, fn
|
||||
{whitelisted_group} ->
|
||||
group == inspect(whitelisted_group)
|
||||
|
||||
{whitelisted_group, whitelisted_key} ->
|
||||
group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
|
||||
end)
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
defp whitelisted_config?(%{"group" => group, "key" => key}) do
|
||||
whitelisted_config?(group, key)
|
||||
end
|
||||
|
||||
defp whitelisted_config?(%{:group => group} = config) do
|
||||
whitelisted_config?(group, config[:key])
|
||||
end
|
||||
|
||||
def reload_emoji(conn, _params) do
|
||||
Pleroma.Emoji.reload()
|
||||
|
||||
|
|
|
@ -54,4 +54,8 @@ def empty_object_response do
|
|||
def empty_array_response do
|
||||
Operation.response("Empty array", "application/json", %Schema{type: :array, example: []})
|
||||
end
|
||||
|
||||
def no_content_response do
|
||||
Operation.response("No Content", "application/json", %Schema{type: :string, example: ""})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Schemas.AccountRelationship
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
||||
alias Pleroma.Web.ApiSpec.StatusOperation
|
||||
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def confirmation_resend_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Resend confirmation email. Expects `email` or `nickname`",
|
||||
operationId: "PleromaAPI.AccountController.confirmation_resend",
|
||||
parameters: [
|
||||
Operation.parameter(:email, :query, :string, "Email of that needs to be verified",
|
||||
example: "cofe@cofe.io"
|
||||
),
|
||||
Operation.parameter(
|
||||
:nickname,
|
||||
:query,
|
||||
:string,
|
||||
"Nickname of user that needs to be verified",
|
||||
example: "cofefe"
|
||||
)
|
||||
],
|
||||
responses: %{
|
||||
204 => no_content_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def update_avatar_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Set/clear user avatar image",
|
||||
operationId: "PleromaAPI.AccountController.update_avatar",
|
||||
requestBody:
|
||||
request_body("Parameters", update_avatar_or_background_request(), required: true),
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
responses: %{
|
||||
200 => update_response(),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def update_banner_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Set/clear user banner image",
|
||||
operationId: "PleromaAPI.AccountController.update_banner",
|
||||
requestBody: request_body("Parameters", update_banner_request(), required: true),
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
responses: %{
|
||||
200 => update_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def update_background_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Set/clear user background image",
|
||||
operationId: "PleromaAPI.AccountController.update_background",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
requestBody:
|
||||
request_body("Parameters", update_avatar_or_background_request(), required: true),
|
||||
responses: %{
|
||||
200 => update_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def favourites_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Returns favorites timeline of any user",
|
||||
operationId: "PleromaAPI.AccountController.favourites",
|
||||
parameters: [id_param() | pagination_params()],
|
||||
security: [%{"oAuth" => ["read:favourites"]}],
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Array of Statuses",
|
||||
"application/json",
|
||||
StatusOperation.array_of_statuses()
|
||||
),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def subscribe_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Subscribe to receive notifications for all statuses posted by a user",
|
||||
operationId: "PleromaAPI.AccountController.subscribe",
|
||||
parameters: [id_param()],
|
||||
security: [%{"oAuth" => ["follow", "write:follows"]}],
|
||||
responses: %{
|
||||
200 => Operation.response("Relationship", "application/json", AccountRelationship),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unsubscribe_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
summary: "Unsubscribe to stop receiving notifications from user statuses",
|
||||
operationId: "PleromaAPI.AccountController.unsubscribe",
|
||||
parameters: [id_param()],
|
||||
security: [%{"oAuth" => ["follow", "write:follows"]}],
|
||||
responses: %{
|
||||
200 => Operation.response("Relationship", "application/json", AccountRelationship),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp id_param do
|
||||
Operation.parameter(:id, :path, FlakeID, "Account ID",
|
||||
example: "9umDrYheeY451cQnEe",
|
||||
required: true
|
||||
)
|
||||
end
|
||||
|
||||
defp update_avatar_or_background_request do
|
||||
%Schema{
|
||||
title: "PleromaAccountUpdateAvatarOrBackgroundRequest",
|
||||
type: :object,
|
||||
properties: %{
|
||||
img: %Schema{
|
||||
type: :string,
|
||||
format: :binary,
|
||||
description: "Image encoded using `multipart/form-data` or an empty string to clear"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp update_banner_request do
|
||||
%Schema{
|
||||
title: "PleromaAccountUpdateBannerRequest",
|
||||
type: :object,
|
||||
properties: %{
|
||||
banner: %Schema{
|
||||
type: :string,
|
||||
format: :binary,
|
||||
description: "Image encoded using `multipart/form-data` or an empty string to clear"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp update_response do
|
||||
Operation.response("PleromaAccountUpdateResponse", "application/json", %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
url: %Schema{
|
||||
type: :string,
|
||||
format: :uri,
|
||||
nullable: true,
|
||||
description: "Image URL"
|
||||
}
|
||||
},
|
||||
example: %{
|
||||
"url" =>
|
||||
"https://cofe.party/media/9d0add56-bcb6-4c0f-8225-cbbd0b6dd773/13eadb6972c9ccd3f4ffa3b8196f0e0d38b4d2f27594457c52e52946c054cd9a.gif"
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
|
@ -0,0 +1,499 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.StatusOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.AccountOperation
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ScheduledStatus
|
||||
alias Pleroma.Web.ApiSpec.Schemas.Status
|
||||
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
||||
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def index_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Get multiple statuses by IDs",
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:ids,
|
||||
:query,
|
||||
%Schema{type: :array, items: FlakeID},
|
||||
"Array of status IDs"
|
||||
)
|
||||
],
|
||||
operationId: "StatusController.index",
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def create_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Publish new status",
|
||||
security: [%{"oAuth" => ["write:statuses"]}],
|
||||
description: "Post a new status",
|
||||
operationId: "StatusController.create",
|
||||
requestBody: request_body("Parameters", create_request(), required: true),
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Status. When `scheduled_at` is present, ScheduledStatus is returned instead",
|
||||
"application/json",
|
||||
%Schema{oneOf: [Status, ScheduledStatus]}
|
||||
),
|
||||
422 => Operation.response("Bad Request", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def show_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "View specific status",
|
||||
description: "View information about a status",
|
||||
operationId: "StatusController.show",
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def delete_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Delete status",
|
||||
security: [%{"oAuth" => ["write:statuses"]}],
|
||||
description: "Delete one of your own statuses",
|
||||
operationId: "StatusController.delete",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => empty_object_response(),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def reblog_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Boost",
|
||||
security: [%{"oAuth" => ["write:statuses"]}],
|
||||
description: "Share a status",
|
||||
operationId: "StatusController.reblog",
|
||||
parameters: [id_param()],
|
||||
requestBody:
|
||||
request_body("Parameters", %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
visibility: %Schema{allOf: [VisibilityScope], default: "public"}
|
||||
}
|
||||
}),
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unreblog_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Undo boost",
|
||||
security: [%{"oAuth" => ["write:statuses"]}],
|
||||
description: "Undo a reshare of a status",
|
||||
operationId: "StatusController.unreblog",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def favourite_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Favourite",
|
||||
security: [%{"oAuth" => ["write:favourites"]}],
|
||||
description: "Add a status to your favourites list",
|
||||
operationId: "StatusController.favourite",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unfavourite_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Undo favourite",
|
||||
security: [%{"oAuth" => ["write:favourites"]}],
|
||||
description: "Remove a status from your favourites list",
|
||||
operationId: "StatusController.unfavourite",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def pin_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Pin to profile",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
description: "Feature one of your own public statuses at the top of your profile",
|
||||
operationId: "StatusController.pin",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
400 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unpin_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Unpin to profile",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
description: "Unfeature a status from the top of your profile",
|
||||
operationId: "StatusController.unpin",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
400 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def bookmark_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Bookmark",
|
||||
security: [%{"oAuth" => ["write:bookmarks"]}],
|
||||
description: "Privately bookmark a status",
|
||||
operationId: "StatusController.bookmark",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unbookmark_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Undo bookmark",
|
||||
security: [%{"oAuth" => ["write:bookmarks"]}],
|
||||
description: "Remove a status from your private bookmarks",
|
||||
operationId: "StatusController.unbookmark",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def mute_conversation_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Mute conversation",
|
||||
security: [%{"oAuth" => ["write:mutes"]}],
|
||||
description: "Do not receive notifications for the thread that this status is part of.",
|
||||
operationId: "StatusController.mute_conversation",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
400 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def unmute_conversation_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Unmute conversation",
|
||||
security: [%{"oAuth" => ["write:mutes"]}],
|
||||
description:
|
||||
"Start receiving notifications again for the thread that this status is part of",
|
||||
operationId: "StatusController.unmute_conversation",
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => status_response(),
|
||||
400 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def card_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
deprecated: true,
|
||||
summary: "Preview card",
|
||||
description: "Deprecated in favor of card property inlined on Status entity",
|
||||
operationId: "StatusController.card",
|
||||
parameters: [id_param()],
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Card", "application/json", %Schema{
|
||||
type: :object,
|
||||
nullable: true,
|
||||
properties: %{
|
||||
type: %Schema{type: :string, enum: ["link", "photo", "video", "rich"]},
|
||||
provider_name: %Schema{type: :string, nullable: true},
|
||||
provider_url: %Schema{type: :string, format: :uri},
|
||||
url: %Schema{type: :string, format: :uri},
|
||||
image: %Schema{type: :string, nullable: true, format: :uri},
|
||||
title: %Schema{type: :string},
|
||||
description: %Schema{type: :string}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def favourited_by_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Favourited by",
|
||||
description: "View who favourited a given status",
|
||||
operationId: "StatusController.favourited_by",
|
||||
security: [%{"oAuth" => ["read:accounts"]}],
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Array of Accounts",
|
||||
"application/json",
|
||||
AccountOperation.array_of_accounts()
|
||||
),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def reblogged_by_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Boosted by",
|
||||
description: "View who boosted a given status",
|
||||
operationId: "StatusController.reblogged_by",
|
||||
security: [%{"oAuth" => ["read:accounts"]}],
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Array of Accounts",
|
||||
"application/json",
|
||||
AccountOperation.array_of_accounts()
|
||||
),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def context_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Parent and child statuses",
|
||||
description: "View statuses above and below this status in the thread",
|
||||
operationId: "StatusController.context",
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
parameters: [id_param()],
|
||||
responses: %{
|
||||
200 => Operation.response("Context", "application/json", context())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def favourites_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Favourited statuses",
|
||||
description: "Statuses the user has favourited",
|
||||
operationId: "StatusController.favourites",
|
||||
parameters: pagination_params(),
|
||||
security: [%{"oAuth" => ["read:favourites"]}],
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def bookmarks_operation do
|
||||
%Operation{
|
||||
tags: ["Statuses"],
|
||||
summary: "Bookmarked statuses",
|
||||
description: "Statuses the user has bookmarked",
|
||||
operationId: "StatusController.bookmarks",
|
||||
parameters: [
|
||||
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships")
|
||||
| pagination_params()
|
||||
],
|
||||
security: [%{"oAuth" => ["read:bookmarks"]}],
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def array_of_statuses do
|
||||
%Schema{type: :array, items: Status, example: [Status.schema().example]}
|
||||
end
|
||||
|
||||
defp create_request do
|
||||
%Schema{
|
||||
title: "StatusCreateRequest",
|
||||
type: :object,
|
||||
properties: %{
|
||||
status: %Schema{
|
||||
type: :string,
|
||||
description:
|
||||
"Text content of the status. If `media_ids` is provided, this becomes optional. Attaching a `poll` is optional while `status` is provided."
|
||||
},
|
||||
media_ids: %Schema{
|
||||
type: :array,
|
||||
items: %Schema{type: :string},
|
||||
description: "Array of Attachment ids to be attached as media."
|
||||
},
|
||||
poll: %Schema{
|
||||
type: :object,
|
||||
required: [:options],
|
||||
properties: %{
|
||||
options: %Schema{
|
||||
type: :array,
|
||||
items: %Schema{type: :string},
|
||||
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
|
||||
},
|
||||
expires_in: %Schema{
|
||||
type: :integer,
|
||||
description:
|
||||
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
|
||||
},
|
||||
multiple: %Schema{type: :boolean, description: "Allow multiple choices?"},
|
||||
hide_totals: %Schema{
|
||||
type: :boolean,
|
||||
description: "Hide vote counts until the poll ends?"
|
||||
}
|
||||
}
|
||||
},
|
||||
in_reply_to_id: %Schema{
|
||||
allOf: [FlakeID],
|
||||
description: "ID of the status being replied to, if status is a reply"
|
||||
},
|
||||
sensitive: %Schema{
|
||||
type: :boolean,
|
||||
description: "Mark status and attached media as sensitive?"
|
||||
},
|
||||
spoiler_text: %Schema{
|
||||
type: :string,
|
||||
description:
|
||||
"Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field."
|
||||
},
|
||||
scheduled_at: %Schema{
|
||||
type: :string,
|
||||
format: :"date-time",
|
||||
nullable: true,
|
||||
description:
|
||||
"ISO 8601 Datetime at which to schedule a status. Providing this paramter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future."
|
||||
},
|
||||
language: %Schema{type: :string, description: "ISO 639 language code for this status."},
|
||||
# Pleroma-specific properties:
|
||||
preview: %Schema{
|
||||
type: :boolean,
|
||||
description:
|
||||
"If set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example"
|
||||
},
|
||||
content_type: %Schema{
|
||||
type: :string,
|
||||
description:
|
||||
"The MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint."
|
||||
},
|
||||
to: %Schema{
|
||||
type: :array,
|
||||
items: %Schema{type: :string},
|
||||
description:
|
||||
"A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply"
|
||||
},
|
||||
visibility: %Schema{
|
||||
anyOf: [
|
||||
VisibilityScope,
|
||||
%Schema{type: :string, description: "`list:LIST_ID`", example: "LIST:123"}
|
||||
],
|
||||
description:
|
||||
"Visibility of the posted status. Besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`"
|
||||
},
|
||||
expires_in: %Schema{
|
||||
type: :integer,
|
||||
description:
|
||||
"The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour."
|
||||
},
|
||||
in_reply_to_conversation_id: %Schema{
|
||||
type: :string,
|
||||
description:
|
||||
"Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`."
|
||||
}
|
||||
},
|
||||
example: %{
|
||||
"status" => "What time is it?",
|
||||
"sensitive" => "false",
|
||||
"poll" => %{
|
||||
"options" => ["Cofe", "Adventure"],
|
||||
"expires_in" => 420
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp id_param do
|
||||
Operation.parameter(:id, :path, FlakeID, "Status ID",
|
||||
example: "9umDrYheeY451cQnEe",
|
||||
required: true
|
||||
)
|
||||
end
|
||||
|
||||
defp status_response do
|
||||
Operation.response("Status", "application/json", Status)
|
||||
end
|
||||
|
||||
defp context do
|
||||
%Schema{
|
||||
title: "StatusContext",
|
||||
description:
|
||||
"Represents the tree around a given status. Used for reconstructing threads of statuses.",
|
||||
type: :object,
|
||||
required: [:ancestors, :descendants],
|
||||
properties: %{
|
||||
ancestors: array_of_statuses(),
|
||||
descendants: array_of_statuses()
|
||||
},
|
||||
example: %{
|
||||
"ancestors" => [Status.schema().example],
|
||||
"descendants" => [Status.schema().example]
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,199 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.TimelineOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||
alias Pleroma.Web.ApiSpec.Schemas.Status
|
||||
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
||||
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def home_operation do
|
||||
%Operation{
|
||||
tags: ["Timelines"],
|
||||
summary: "Home timeline",
|
||||
description: "View statuses from followed users",
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
parameters: [
|
||||
local_param(),
|
||||
with_muted_param(),
|
||||
exclude_visibilities_param(),
|
||||
reply_visibility_param(),
|
||||
with_relationships_param() | pagination_params()
|
||||
],
|
||||
operationId: "TimelineController.home",
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def direct_operation do
|
||||
%Operation{
|
||||
tags: ["Timelines"],
|
||||
summary: "Direct timeline",
|
||||
description:
|
||||
"View statuses with a “direct” privacy, from your account or in your notifications",
|
||||
deprecated: true,
|
||||
parameters: pagination_params(),
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
operationId: "TimelineController.direct",
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def public_operation do
|
||||
%Operation{
|
||||
tags: ["Timelines"],
|
||||
summary: "Public timeline",
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
parameters: [
|
||||
local_param(),
|
||||
only_media_param(),
|
||||
with_muted_param(),
|
||||
exclude_visibilities_param(),
|
||||
reply_visibility_param(),
|
||||
with_relationships_param() | pagination_params()
|
||||
],
|
||||
operationId: "TimelineController.public",
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Status", "application/json", array_of_statuses()),
|
||||
401 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def hashtag_operation do
|
||||
%Operation{
|
||||
tags: ["Timelines"],
|
||||
summary: "Hashtag timeline",
|
||||
description: "View public statuses containing the given hashtag",
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:tag,
|
||||
:path,
|
||||
%Schema{type: :string},
|
||||
"Content of a #hashtag, not including # symbol.",
|
||||
required: true
|
||||
),
|
||||
Operation.parameter(
|
||||
:any,
|
||||
:query,
|
||||
%Schema{type: :array, items: %Schema{type: :string}},
|
||||
"Statuses that also includes any of these tags"
|
||||
),
|
||||
Operation.parameter(
|
||||
:all,
|
||||
:query,
|
||||
%Schema{type: :array, items: %Schema{type: :string}},
|
||||
"Statuses that also includes all of these tags"
|
||||
),
|
||||
Operation.parameter(
|
||||
:none,
|
||||
:query,
|
||||
%Schema{type: :array, items: %Schema{type: :string}},
|
||||
"Statuses that do not include these tags"
|
||||
),
|
||||
local_param(),
|
||||
only_media_param(),
|
||||
with_muted_param(),
|
||||
exclude_visibilities_param(),
|
||||
with_relationships_param() | pagination_params()
|
||||
],
|
||||
operationId: "TimelineController.hashtag",
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def list_operation do
|
||||
%Operation{
|
||||
tags: ["Timelines"],
|
||||
summary: "List timeline",
|
||||
description: "View statuses in the given list timeline",
|
||||
security: [%{"oAuth" => ["read:lists"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:list_id,
|
||||
:path,
|
||||
%Schema{type: :string},
|
||||
"Local ID of the list in the database",
|
||||
required: true
|
||||
),
|
||||
with_muted_param(),
|
||||
exclude_visibilities_param(),
|
||||
with_relationships_param() | pagination_params()
|
||||
],
|
||||
operationId: "TimelineController.list",
|
||||
responses: %{
|
||||
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp array_of_statuses do
|
||||
%Schema{
|
||||
title: "ArrayOfStatuses",
|
||||
type: :array,
|
||||
items: Status,
|
||||
example: [Status.schema().example]
|
||||
}
|
||||
end
|
||||
|
||||
defp with_relationships_param do
|
||||
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships")
|
||||
end
|
||||
|
||||
defp local_param do
|
||||
Operation.parameter(
|
||||
:local,
|
||||
:query,
|
||||
%Schema{allOf: [BooleanLike], default: false},
|
||||
"Show only local statuses?"
|
||||
)
|
||||
end
|
||||
|
||||
defp with_muted_param do
|
||||
Operation.parameter(:with_muted, :query, BooleanLike, "Includeactivities by muted users")
|
||||
end
|
||||
|
||||
defp exclude_visibilities_param do
|
||||
Operation.parameter(
|
||||
:exclude_visibilities,
|
||||
:query,
|
||||
%Schema{type: :array, items: VisibilityScope},
|
||||
"Exclude the statuses with the given visibilities"
|
||||
)
|
||||
end
|
||||
|
||||
defp reply_visibility_param do
|
||||
Operation.parameter(
|
||||
:reply_visibility,
|
||||
:query,
|
||||
%Schema{type: :string, enum: ["following", "self"]},
|
||||
"Filter replies. Possible values: without parameter (default) shows all replies, `following` - replies directed to you or users you follow, `self` - replies directed to you."
|
||||
)
|
||||
end
|
||||
|
||||
defp only_media_param do
|
||||
Operation.parameter(
|
||||
:only_media,
|
||||
:query,
|
||||
%Schema{allOf: [BooleanLike], default: false},
|
||||
"Show only statuses with media attached?"
|
||||
)
|
||||
end
|
||||
end
|
|
@ -19,60 +19,127 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
|||
description: "Response schema for a status",
|
||||
type: :object,
|
||||
properties: %{
|
||||
account: Account,
|
||||
account: %Schema{allOf: [Account], description: "The account that authored this status"},
|
||||
application: %Schema{
|
||||
description: "The application used to post this status",
|
||||
type: :object,
|
||||
properties: %{
|
||||
name: %Schema{type: :string},
|
||||
website: %Schema{type: :string, nullable: true, format: :uri}
|
||||
}
|
||||
},
|
||||
bookmarked: %Schema{type: :boolean},
|
||||
bookmarked: %Schema{type: :boolean, description: "Have you bookmarked this status?"},
|
||||
card: %Schema{
|
||||
type: :object,
|
||||
nullable: true,
|
||||
description: "Preview card for links included within status content",
|
||||
required: [:url, :title, :description, :type],
|
||||
properties: %{
|
||||
type: %Schema{type: :string, enum: ["link", "photo", "video", "rich"]},
|
||||
provider_name: %Schema{type: :string, nullable: true},
|
||||
provider_url: %Schema{type: :string, format: :uri},
|
||||
url: %Schema{type: :string, format: :uri},
|
||||
image: %Schema{type: :string, nullable: true, format: :uri},
|
||||
title: %Schema{type: :string},
|
||||
description: %Schema{type: :string}
|
||||
type: %Schema{
|
||||
type: :string,
|
||||
enum: ["link", "photo", "video", "rich"],
|
||||
description: "The type of the preview card"
|
||||
},
|
||||
provider_name: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "The provider of the original resource"
|
||||
},
|
||||
provider_url: %Schema{
|
||||
type: :string,
|
||||
format: :uri,
|
||||
description: "A link to the provider of the original resource"
|
||||
},
|
||||
url: %Schema{type: :string, format: :uri, description: "Location of linked resource"},
|
||||
image: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
format: :uri,
|
||||
description: "Preview thumbnail"
|
||||
},
|
||||
title: %Schema{type: :string, description: "Title of linked resource"},
|
||||
description: %Schema{type: :string, description: "Description of preview"}
|
||||
}
|
||||
},
|
||||
content: %Schema{type: :string, format: :html},
|
||||
created_at: %Schema{type: :string, format: "date-time"},
|
||||
emojis: %Schema{type: :array, items: Emoji},
|
||||
favourited: %Schema{type: :boolean},
|
||||
favourites_count: %Schema{type: :integer},
|
||||
content: %Schema{type: :string, format: :html, description: "HTML-encoded status content"},
|
||||
created_at: %Schema{
|
||||
type: :string,
|
||||
format: "date-time",
|
||||
description: "The date when this status was created"
|
||||
},
|
||||
emojis: %Schema{
|
||||
type: :array,
|
||||
items: Emoji,
|
||||
description: "Custom emoji to be used when rendering status content"
|
||||
},
|
||||
favourited: %Schema{type: :boolean, description: "Have you favourited this status?"},
|
||||
favourites_count: %Schema{
|
||||
type: :integer,
|
||||
description: "How many favourites this status has received"
|
||||
},
|
||||
id: FlakeID,
|
||||
in_reply_to_account_id: %Schema{type: :string, nullable: true},
|
||||
in_reply_to_id: %Schema{type: :string, nullable: true},
|
||||
language: %Schema{type: :string, nullable: true},
|
||||
in_reply_to_account_id: %Schema{
|
||||
allOf: [FlakeID],
|
||||
nullable: true,
|
||||
description: "ID of the account being replied to"
|
||||
},
|
||||
in_reply_to_id: %Schema{
|
||||
allOf: [FlakeID],
|
||||
nullable: true,
|
||||
description: "ID of the status being replied"
|
||||
},
|
||||
language: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "Primary language of this status"
|
||||
},
|
||||
media_attachments: %Schema{
|
||||
type: :array,
|
||||
items: Attachment
|
||||
items: Attachment,
|
||||
description: "Media that is attached to this status"
|
||||
},
|
||||
mentions: %Schema{
|
||||
type: :array,
|
||||
description: "Mentions of users within the status content",
|
||||
items: %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
id: %Schema{type: :string},
|
||||
acct: %Schema{type: :string},
|
||||
username: %Schema{type: :string},
|
||||
url: %Schema{type: :string, format: :uri}
|
||||
id: %Schema{allOf: [FlakeID], description: "The account id of the mentioned user"},
|
||||
acct: %Schema{
|
||||
type: :string,
|
||||
description:
|
||||
"The webfinger acct: URI of the mentioned user. Equivalent to `username` for local users, or `username@domain` for remote users."
|
||||
},
|
||||
username: %Schema{type: :string, description: "The username of the mentioned user"},
|
||||
url: %Schema{
|
||||
type: :string,
|
||||
format: :uri,
|
||||
description: "The location of the mentioned user's profile"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
muted: %Schema{type: :boolean},
|
||||
pinned: %Schema{type: :boolean},
|
||||
muted: %Schema{
|
||||
type: :boolean,
|
||||
description: "Have you muted notifications for this status's conversation?"
|
||||
},
|
||||
pinned: %Schema{
|
||||
type: :boolean,
|
||||
description: "Have you pinned this status? Only appears if the status is pinnable."
|
||||
},
|
||||
pleroma: %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
content: %Schema{type: :object, additionalProperties: %Schema{type: :string}},
|
||||
conversation_id: %Schema{type: :integer},
|
||||
content: %Schema{
|
||||
type: :object,
|
||||
additionalProperties: %Schema{type: :string},
|
||||
description:
|
||||
"A map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`"
|
||||
},
|
||||
conversation_id: %Schema{
|
||||
type: :integer,
|
||||
description: "The ID of the AP context the status is associated with (if any)"
|
||||
},
|
||||
direct_conversation_id: %Schema{
|
||||
type: :integer,
|
||||
nullable: true,
|
||||
|
@ -81,6 +148,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
|||
},
|
||||
emoji_reactions: %Schema{
|
||||
type: :array,
|
||||
description:
|
||||
"A list with emoji / reaction maps. Contains no information about the reacting users, for that use the /statuses/:id/reactions endpoint.",
|
||||
items: %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
|
@ -90,27 +159,74 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
|||
}
|
||||
}
|
||||
},
|
||||
expires_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||
in_reply_to_account_acct: %Schema{type: :string, nullable: true},
|
||||
local: %Schema{type: :boolean},
|
||||
spoiler_text: %Schema{type: :object, additionalProperties: %Schema{type: :string}},
|
||||
thread_muted: %Schema{type: :boolean}
|
||||
expires_at: %Schema{
|
||||
type: :string,
|
||||
format: "date-time",
|
||||
nullable: true,
|
||||
description:
|
||||
"A datetime (ISO 8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire"
|
||||
},
|
||||
in_reply_to_account_acct: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "The `acct` property of User entity for replied user (if any)"
|
||||
},
|
||||
local: %Schema{
|
||||
type: :boolean,
|
||||
description: "`true` if the post was made on the local instance"
|
||||
},
|
||||
spoiler_text: %Schema{
|
||||
type: :object,
|
||||
additionalProperties: %Schema{type: :string},
|
||||
description:
|
||||
"A map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`."
|
||||
},
|
||||
thread_muted: %Schema{
|
||||
type: :boolean,
|
||||
description: "`true` if the thread the post belongs to is muted"
|
||||
}
|
||||
}
|
||||
},
|
||||
poll: %Schema{type: Poll, nullable: true},
|
||||
poll: %Schema{allOf: [Poll], nullable: true, description: "The poll attached to the status"},
|
||||
reblog: %Schema{
|
||||
allOf: [%OpenApiSpex.Reference{"$ref": "#/components/schemas/Status"}],
|
||||
nullable: true
|
||||
nullable: true,
|
||||
description: "The status being reblogged"
|
||||
},
|
||||
reblogged: %Schema{type: :boolean, description: "Have you boosted this status?"},
|
||||
reblogs_count: %Schema{
|
||||
type: :integer,
|
||||
description: "How many boosts this status has received"
|
||||
},
|
||||
replies_count: %Schema{
|
||||
type: :integer,
|
||||
description: "How many replies this status has received"
|
||||
},
|
||||
sensitive: %Schema{
|
||||
type: :boolean,
|
||||
description: "Is this status marked as sensitive content?"
|
||||
},
|
||||
spoiler_text: %Schema{
|
||||
type: :string,
|
||||
description:
|
||||
"Subject or summary line, below which status content is collapsed until expanded"
|
||||
},
|
||||
reblogged: %Schema{type: :boolean},
|
||||
reblogs_count: %Schema{type: :integer},
|
||||
replies_count: %Schema{type: :integer},
|
||||
sensitive: %Schema{type: :boolean},
|
||||
spoiler_text: %Schema{type: :string},
|
||||
tags: %Schema{type: :array, items: Tag},
|
||||
uri: %Schema{type: :string, format: :uri},
|
||||
url: %Schema{type: :string, nullable: true, format: :uri},
|
||||
visibility: VisibilityScope
|
||||
uri: %Schema{
|
||||
type: :string,
|
||||
format: :uri,
|
||||
description: "URI of the status used for federation"
|
||||
},
|
||||
url: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
format: :uri,
|
||||
description: "A link to the status's HTML representation"
|
||||
},
|
||||
visibility: %Schema{
|
||||
allOf: [VisibilityScope],
|
||||
description: "Visibility of this status"
|
||||
}
|
||||
},
|
||||
example: %{
|
||||
"account" => %{
|
||||
|
|
|
@ -9,6 +9,6 @@ defmodule Pleroma.Web.ApiSpec.Schemas.VisibilityScope do
|
|||
title: "VisibilityScope",
|
||||
description: "Status visibility",
|
||||
type: :string,
|
||||
enum: ["public", "unlisted", "private", "direct"]
|
||||
enum: ["public", "unlisted", "private", "direct", "list"]
|
||||
})
|
||||
end
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Auth.TOTPAuthenticator do
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.MFA
|
||||
alias Pleroma.MFA.TOTP
|
||||
alias Pleroma.Plugs.AuthenticationPlug
|
||||
alias Pleroma.User
|
||||
|
||||
@doc "Verify code or check backup code."
|
||||
|
@ -31,7 +31,7 @@ def verify_recovery_code(
|
|||
code
|
||||
)
|
||||
when is_list(codes) and is_binary(code) do
|
||||
hash_code = Enum.find(codes, fn hash -> Pbkdf2.checkpw(code, hash) end)
|
||||
hash_code = Enum.find(codes, fn hash -> AuthenticationPlug.checkpw(code, hash) end)
|
||||
|
||||
if hash_code do
|
||||
MFA.invalidate_backup_code(user, hash_code)
|
||||
|
|
|
@ -58,16 +58,16 @@ def create(user, params) do
|
|||
end
|
||||
|
||||
defp put_params(draft, params) do
|
||||
params = Map.put_new(params, "in_reply_to_status_id", params["in_reply_to_id"])
|
||||
params = Map.put_new(params, :in_reply_to_status_id, params[:in_reply_to_id])
|
||||
%__MODULE__{draft | params: params}
|
||||
end
|
||||
|
||||
defp status(%{params: %{"status" => status}} = draft) do
|
||||
defp status(%{params: %{status: status}} = draft) do
|
||||
%__MODULE__{draft | status: String.trim(status)}
|
||||
end
|
||||
|
||||
defp summary(%{params: params} = draft) do
|
||||
%__MODULE__{draft | summary: Map.get(params, "spoiler_text", "")}
|
||||
%__MODULE__{draft | summary: Map.get(params, :spoiler_text, "")}
|
||||
end
|
||||
|
||||
defp full_payload(%{status: status, summary: summary} = draft) do
|
||||
|
@ -84,20 +84,20 @@ defp attachments(%{params: params} = draft) do
|
|||
%__MODULE__{draft | attachments: attachments}
|
||||
end
|
||||
|
||||
defp in_reply_to(%{params: %{"in_reply_to_status_id" => ""}} = draft), do: draft
|
||||
defp in_reply_to(%{params: %{in_reply_to_status_id: ""}} = draft), do: draft
|
||||
|
||||
defp in_reply_to(%{params: %{"in_reply_to_status_id" => id}} = draft) when is_binary(id) do
|
||||
defp in_reply_to(%{params: %{in_reply_to_status_id: id}} = draft) when is_binary(id) do
|
||||
%__MODULE__{draft | in_reply_to: Activity.get_by_id(id)}
|
||||
end
|
||||
|
||||
defp in_reply_to(%{params: %{"in_reply_to_status_id" => %Activity{} = in_reply_to}} = draft) do
|
||||
defp in_reply_to(%{params: %{in_reply_to_status_id: %Activity{} = in_reply_to}} = draft) do
|
||||
%__MODULE__{draft | in_reply_to: in_reply_to}
|
||||
end
|
||||
|
||||
defp in_reply_to(draft), do: draft
|
||||
|
||||
defp in_reply_to_conversation(draft) do
|
||||
in_reply_to_conversation = Participation.get(draft.params["in_reply_to_conversation_id"])
|
||||
in_reply_to_conversation = Participation.get(draft.params[:in_reply_to_conversation_id])
|
||||
%__MODULE__{draft | in_reply_to_conversation: in_reply_to_conversation}
|
||||
end
|
||||
|
||||
|
@ -112,7 +112,7 @@ defp visibility(%{params: params} = draft) do
|
|||
end
|
||||
|
||||
defp expires_at(draft) do
|
||||
case CommonAPI.check_expiry_date(draft.params["expires_in"]) do
|
||||
case CommonAPI.check_expiry_date(draft.params[:expires_in]) do
|
||||
{:ok, expires_at} -> %__MODULE__{draft | expires_at: expires_at}
|
||||
{:error, message} -> add_error(draft, message)
|
||||
end
|
||||
|
@ -144,7 +144,7 @@ defp to_and_cc(draft) do
|
|||
addressed_users =
|
||||
draft.mentions
|
||||
|> Enum.map(fn {_, mentioned_user} -> mentioned_user.ap_id end)
|
||||
|> Utils.get_addressed_users(draft.params["to"])
|
||||
|> Utils.get_addressed_users(draft.params[:to])
|
||||
|
||||
{to, cc} =
|
||||
Utils.get_to_and_cc(
|
||||
|
@ -164,7 +164,7 @@ defp context(draft) do
|
|||
end
|
||||
|
||||
defp sensitive(draft) do
|
||||
sensitive = draft.params["sensitive"] || Enum.member?(draft.tags, {"#nsfw", "nsfw"})
|
||||
sensitive = draft.params[:sensitive] || Enum.member?(draft.tags, {"#nsfw", "nsfw"})
|
||||
%__MODULE__{draft | sensitive: sensitive}
|
||||
end
|
||||
|
||||
|
@ -191,7 +191,7 @@ defp object(draft) do
|
|||
end
|
||||
|
||||
defp preview?(draft) do
|
||||
preview? = Pleroma.Web.ControllerHelper.truthy_param?(draft.params["preview"])
|
||||
preview? = Pleroma.Web.ControllerHelper.truthy_param?(draft.params[:preview])
|
||||
%__MODULE__{draft | preview?: preview?}
|
||||
end
|
||||
|
||||
|
|
|
@ -83,33 +83,51 @@ def reject_follow_request(follower, followed) do
|
|||
end
|
||||
|
||||
def delete(activity_id, user) do
|
||||
with {_, %Activity{data: %{"object" => _}} = activity} <-
|
||||
{:find_activity, Activity.get_by_id_with_object(activity_id)},
|
||||
%Object{} = object <- Object.normalize(activity),
|
||||
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <-
|
||||
{:find_activity, Activity.get_by_id(activity_id)},
|
||||
{_, %Object{} = object, _} <-
|
||||
{:find_object, Object.normalize(activity, false), activity},
|
||||
true <- User.superuser?(user) || user.ap_id == object.data["actor"],
|
||||
{:ok, delete_data, _} <- Builder.delete(user, object.data["id"]),
|
||||
{:ok, delete, _} <- Pipeline.common_pipeline(delete_data, local: true) do
|
||||
{:ok, delete}
|
||||
else
|
||||
{:find_activity, _} -> {:error, :not_found}
|
||||
_ -> {:error, dgettext("errors", "Could not delete")}
|
||||
{:find_activity, _} ->
|
||||
{:error, :not_found}
|
||||
|
||||
{:find_object, nil, %Activity{data: %{"actor" => actor, "object" => object}}} ->
|
||||
# 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(actor, object),
|
||||
{:ok, _tombstone} <- Object.create(tombstone_data) do
|
||||
delete(activity_id, user)
|
||||
else
|
||||
_ ->
|
||||
Logger.error(
|
||||
"Could not insert tombstone for missing object on deletion. Object is #{object}."
|
||||
)
|
||||
|
||||
{:error, dgettext("errors", "Could not delete")}
|
||||
end
|
||||
|
||||
_ ->
|
||||
{:error, dgettext("errors", "Could not delete")}
|
||||
end
|
||||
end
|
||||
|
||||
def repeat(id, user, params \\ %{}) do
|
||||
with {_, %Activity{data: %{"type" => "Create"}} = activity} <-
|
||||
{:find_activity, Activity.get_by_id(id)},
|
||||
object <- Object.normalize(activity),
|
||||
announce_activity <- Utils.get_existing_announce(user.ap_id, object),
|
||||
public <- public_announce?(object, params) do
|
||||
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id(id) do
|
||||
object = Object.normalize(activity)
|
||||
announce_activity = Utils.get_existing_announce(user.ap_id, object)
|
||||
public = public_announce?(object, params)
|
||||
|
||||
if announce_activity do
|
||||
{:ok, announce_activity, object}
|
||||
else
|
||||
ActivityPub.announce(user, object, nil, true, public)
|
||||
end
|
||||
else
|
||||
{:find_activity, _} -> {:error, :not_found}
|
||||
_ -> {:error, dgettext("errors", "Could not repeat")}
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -267,7 +285,7 @@ defp normalize_and_validate_choices(choices, object) do
|
|||
end
|
||||
end
|
||||
|
||||
def public_announce?(_, %{"visibility" => visibility})
|
||||
def public_announce?(_, %{visibility: visibility})
|
||||
when visibility in ~w{public unlisted private direct},
|
||||
do: visibility in ~w(public unlisted)
|
||||
|
||||
|
@ -277,11 +295,11 @@ def public_announce?(object, _) do
|
|||
|
||||
def get_visibility(_, _, %Participation{}), do: {"direct", "direct"}
|
||||
|
||||
def get_visibility(%{"visibility" => visibility}, in_reply_to, _)
|
||||
def get_visibility(%{visibility: visibility}, in_reply_to, _)
|
||||
when visibility in ~w{public unlisted private direct},
|
||||
do: {visibility, get_replied_to_visibility(in_reply_to)}
|
||||
|
||||
def get_visibility(%{"visibility" => "list:" <> list_id}, in_reply_to, _) do
|
||||
def get_visibility(%{visibility: "list:" <> list_id}, in_reply_to, _) do
|
||||
visibility = {:list, String.to_integer(list_id)}
|
||||
{visibility, get_replied_to_visibility(in_reply_to)}
|
||||
end
|
||||
|
@ -339,7 +357,7 @@ def listen(user, %{"title" => _} = data) do
|
|||
end
|
||||
end
|
||||
|
||||
def post(user, %{"status" => _} = data) do
|
||||
def post(user, %{status: _} = data) do
|
||||
with {:ok, draft} <- Pleroma.Web.CommonAPI.ActivityDraft.create(user, data) do
|
||||
draft.changes
|
||||
|> ActivityPub.create(draft.preview?)
|
||||
|
@ -448,11 +466,11 @@ def update_activity_scope(activity_id, opts \\ %{}) do
|
|||
end
|
||||
end
|
||||
|
||||
defp toggle_sensitive(activity, %{"sensitive" => sensitive}) when sensitive in ~w(true false) do
|
||||
toggle_sensitive(activity, %{"sensitive" => String.to_existing_atom(sensitive)})
|
||||
defp toggle_sensitive(activity, %{sensitive: sensitive}) when sensitive in ~w(true false) do
|
||||
toggle_sensitive(activity, %{sensitive: String.to_existing_atom(sensitive)})
|
||||
end
|
||||
|
||||
defp toggle_sensitive(%Activity{object: object} = activity, %{"sensitive" => sensitive})
|
||||
defp toggle_sensitive(%Activity{object: object} = activity, %{sensitive: sensitive})
|
||||
when is_boolean(sensitive) do
|
||||
new_data = Map.put(object.data, "sensitive", sensitive)
|
||||
|
||||
|
@ -466,7 +484,7 @@ defp toggle_sensitive(%Activity{object: object} = activity, %{"sensitive" => sen
|
|||
|
||||
defp toggle_sensitive(activity, _), do: {:ok, activity}
|
||||
|
||||
defp set_visibility(activity, %{"visibility" => visibility}) do
|
||||
defp set_visibility(activity, %{visibility: visibility}) do
|
||||
Utils.update_activity_visibility(activity, visibility)
|
||||
end
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
require Logger
|
||||
require Pleroma.Constants
|
||||
|
||||
def attachments_from_ids(%{"media_ids" => ids, "descriptions" => desc} = _) do
|
||||
def attachments_from_ids(%{media_ids: ids, descriptions: desc}) do
|
||||
attachments_from_ids_descs(ids, desc)
|
||||
end
|
||||
|
||||
def attachments_from_ids(%{"media_ids" => ids} = _) do
|
||||
def attachments_from_ids(%{media_ids: ids}) do
|
||||
attachments_from_ids_no_descs(ids)
|
||||
end
|
||||
|
||||
|
@ -37,11 +37,11 @@ def attachments_from_ids_no_descs([]), do: []
|
|||
def attachments_from_ids_no_descs(ids) do
|
||||
Enum.map(ids, fn media_id ->
|
||||
case Repo.get(Object, media_id) do
|
||||
%Object{data: data} = _ -> data
|
||||
%Object{data: data} -> data
|
||||
_ -> nil
|
||||
end
|
||||
end)
|
||||
|> Enum.filter(& &1)
|
||||
|> Enum.reject(&is_nil/1)
|
||||
end
|
||||
|
||||
def attachments_from_ids_descs([], _), do: []
|
||||
|
@ -51,14 +51,14 @@ def attachments_from_ids_descs(ids, descs_str) do
|
|||
|
||||
Enum.map(ids, fn media_id ->
|
||||
case Repo.get(Object, media_id) do
|
||||
%Object{data: data} = _ ->
|
||||
%Object{data: data} ->
|
||||
Map.put(data, "name", descs[media_id])
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
end)
|
||||
|> Enum.filter(& &1)
|
||||
|> Enum.reject(&is_nil/1)
|
||||
end
|
||||
|
||||
@spec get_to_and_cc(
|
||||
|
@ -140,7 +140,7 @@ def make_poll_data(%{"poll" => %{"expires_in" => expires_in}} = data)
|
|||
|> make_poll_data()
|
||||
end
|
||||
|
||||
def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_in}} = data)
|
||||
def make_poll_data(%{poll: %{options: options, expires_in: expires_in}} = data)
|
||||
when is_list(options) do
|
||||
limits = Pleroma.Config.get([:instance, :poll_limits])
|
||||
|
||||
|
@ -163,7 +163,7 @@ def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_i
|
|||
|> DateTime.add(expires_in)
|
||||
|> DateTime.to_iso8601()
|
||||
|
||||
key = if truthy_param?(data["poll"]["multiple"]), do: "anyOf", else: "oneOf"
|
||||
key = if truthy_param?(data.poll[:multiple]), do: "anyOf", else: "oneOf"
|
||||
poll = %{"type" => "Question", key => option_notes, "closed" => end_time}
|
||||
|
||||
{:ok, {poll, emoji}}
|
||||
|
@ -213,7 +213,7 @@ def make_content_html(
|
|||
|> Map.get("attachment_links", Config.get([:instance, :attachment_links]))
|
||||
|> truthy_param?()
|
||||
|
||||
content_type = get_content_type(data["content_type"])
|
||||
content_type = get_content_type(data[:content_type])
|
||||
|
||||
options =
|
||||
if visibility == "direct" && Config.get([:instance, :safe_dm_mentions]) do
|
||||
|
|
|
@ -24,6 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
|||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
plug(:skip_plug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action in [:index, :show])
|
||||
|
||||
@unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []}
|
||||
|
@ -97,12 +98,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
|||
|
||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.StatusOperation
|
||||
|
||||
@doc """
|
||||
GET `/api/v1/statuses?ids[]=1&ids[]=2`
|
||||
|
||||
`ids` query param is required
|
||||
"""
|
||||
def index(%{assigns: %{user: user}} = conn, %{"ids" => ids} = params) do
|
||||
def index(%{assigns: %{user: user}} = conn, %{ids: ids} = params) do
|
||||
limit = 100
|
||||
|
||||
activities =
|
||||
|
@ -125,21 +128,29 @@ def index(%{assigns: %{user: user}} = conn, %{"ids" => ids} = params) do
|
|||
Creates a scheduled status when `scheduled_at` param is present and it's far enough
|
||||
"""
|
||||
def create(
|
||||
%{assigns: %{user: user}} = conn,
|
||||
%{"status" => _, "scheduled_at" => scheduled_at} = params
|
||||
%{
|
||||
assigns: %{user: user},
|
||||
body_params: %{status: _, scheduled_at: scheduled_at} = params
|
||||
} = conn,
|
||||
_
|
||||
)
|
||||
when not is_nil(scheduled_at) do
|
||||
params = Map.put(params, "in_reply_to_status_id", params["in_reply_to_id"])
|
||||
params = Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|
||||
|
||||
attrs = %{
|
||||
params: Map.new(params, fn {key, value} -> {to_string(key), value} end),
|
||||
scheduled_at: scheduled_at
|
||||
}
|
||||
|
||||
with {:far_enough, true} <- {:far_enough, ScheduledActivity.far_enough?(scheduled_at)},
|
||||
attrs <- %{"params" => params, "scheduled_at" => scheduled_at},
|
||||
{:ok, scheduled_activity} <- ScheduledActivity.create(user, attrs) do
|
||||
conn
|
||||
|> put_view(ScheduledActivityView)
|
||||
|> render("show.json", scheduled_activity: scheduled_activity)
|
||||
else
|
||||
{:far_enough, _} ->
|
||||
create(conn, Map.drop(params, ["scheduled_at"]))
|
||||
params = Map.drop(params, [:scheduled_at])
|
||||
create(%Plug.Conn{conn | body_params: params}, %{})
|
||||
|
||||
error ->
|
||||
error
|
||||
|
@ -151,8 +162,8 @@ def create(
|
|||
|
||||
Creates a regular status
|
||||
"""
|
||||
def create(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do
|
||||
params = Map.put(params, "in_reply_to_status_id", params["in_reply_to_id"])
|
||||
def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do
|
||||
params = Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|
||||
|
||||
with {:ok, activity} <- CommonAPI.post(user, params) do
|
||||
try_render(conn, "show.json",
|
||||
|
@ -169,12 +180,13 @@ def create(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do
|
|||
end
|
||||
end
|
||||
|
||||
def create(%{assigns: %{user: _user}} = conn, %{"media_ids" => _} = params) do
|
||||
create(conn, Map.put(params, "status", ""))
|
||||
def create(%{assigns: %{user: _user}, body_params: %{media_ids: _} = params} = conn, _) do
|
||||
params = Map.put(params, :status, "")
|
||||
create(%Plug.Conn{conn | body_params: params}, %{})
|
||||
end
|
||||
|
||||
@doc "GET /api/v1/statuses/:id"
|
||||
def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
true <- Visibility.visible_for_user?(activity, user) do
|
||||
try_render(conn, "show.json",
|
||||
|
@ -188,7 +200,7 @@ def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "DELETE /api/v1/statuses/:id"
|
||||
def delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
|
||||
json(conn, %{})
|
||||
else
|
||||
|
@ -198,7 +210,7 @@ def delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/reblog"
|
||||
def reblog(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id} = params) do
|
||||
def reblog(%{assigns: %{user: user}, body_params: params} = conn, %{id: ap_id_or_id}) do
|
||||
with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user, params),
|
||||
%Activity{} = announce <- Activity.normalize(announce.data) do
|
||||
try_render(conn, "show.json", %{activity: announce, for: user, as: :activity})
|
||||
|
@ -206,7 +218,7 @@ def reblog(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id} = params) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/unreblog"
|
||||
def unreblog(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
||||
def unreblog(%{assigns: %{user: user}} = conn, %{id: activity_id}) do
|
||||
with {:ok, _unannounce} <- CommonAPI.unrepeat(activity_id, user),
|
||||
%Activity{} = activity <- Activity.get_by_id(activity_id) do
|
||||
try_render(conn, "show.json", %{activity: activity, for: user, as: :activity})
|
||||
|
@ -214,7 +226,7 @@ def unreblog(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/favourite"
|
||||
def favourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
||||
def favourite(%{assigns: %{user: user}} = conn, %{id: activity_id}) do
|
||||
with {:ok, _fav} <- CommonAPI.favorite(user, activity_id),
|
||||
%Activity{} = activity <- Activity.get_by_id(activity_id) do
|
||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||
|
@ -222,7 +234,7 @@ def favourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/unfavourite"
|
||||
def unfavourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
||||
def unfavourite(%{assigns: %{user: user}} = conn, %{id: activity_id}) do
|
||||
with {:ok, _unfav} <- CommonAPI.unfavorite(activity_id, user),
|
||||
%Activity{} = activity <- Activity.get_by_id(activity_id) do
|
||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||
|
@ -230,21 +242,21 @@ def unfavourite(%{assigns: %{user: user}} = conn, %{"id" => activity_id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/pin"
|
||||
def pin(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
||||
def pin(%{assigns: %{user: user}} = conn, %{id: ap_id_or_id}) do
|
||||
with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do
|
||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||
end
|
||||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/unpin"
|
||||
def unpin(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
||||
def unpin(%{assigns: %{user: user}} = conn, %{id: ap_id_or_id}) do
|
||||
with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do
|
||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||
end
|
||||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/bookmark"
|
||||
def bookmark(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def bookmark(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
%User{} = user <- User.get_cached_by_nickname(user.nickname),
|
||||
true <- Visibility.visible_for_user?(activity, user),
|
||||
|
@ -254,7 +266,7 @@ def bookmark(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/unbookmark"
|
||||
def unbookmark(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def unbookmark(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
%User{} = user <- User.get_cached_by_nickname(user.nickname),
|
||||
true <- Visibility.visible_for_user?(activity, user),
|
||||
|
@ -264,7 +276,7 @@ def unbookmark(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/mute"
|
||||
def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def mute_conversation(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id(id),
|
||||
{:ok, activity} <- CommonAPI.add_mute(user, activity) do
|
||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||
|
@ -272,7 +284,7 @@ def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "POST /api/v1/statuses/:id/unmute"
|
||||
def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def unmute_conversation(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id(id),
|
||||
{:ok, activity} <- CommonAPI.remove_mute(user, activity) do
|
||||
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
|
||||
|
@ -281,7 +293,7 @@ def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
|
||||
@doc "GET /api/v1/statuses/:id/card"
|
||||
@deprecated "https://github.com/tootsuite/mastodon/pull/11213"
|
||||
def card(%{assigns: %{user: user}} = conn, %{"id" => status_id}) do
|
||||
def card(%{assigns: %{user: user}} = conn, %{id: status_id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id(status_id),
|
||||
true <- Visibility.visible_for_user?(activity, user) do
|
||||
data = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
|
||||
|
@ -292,7 +304,7 @@ def card(%{assigns: %{user: user}} = conn, %{"id" => status_id}) do
|
|||
end
|
||||
|
||||
@doc "GET /api/v1/statuses/:id/favourited_by"
|
||||
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def favourited_by(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
|
||||
%Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
|
||||
|
@ -312,7 +324,7 @@ def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "GET /api/v1/statuses/:id/reblogged_by"
|
||||
def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def reblogged_by(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
|
||||
%Object{data: %{"announcements" => announces, "id" => ap_id}} <-
|
||||
|
@ -344,7 +356,7 @@ def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
end
|
||||
|
||||
@doc "GET /api/v1/statuses/:id/context"
|
||||
def context(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
def context(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id(id) do
|
||||
activities =
|
||||
ActivityPub.fetch_activities_for_context(activity.data["context"], %{
|
||||
|
@ -359,11 +371,12 @@ def context(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
|
||||
@doc "GET /api/v1/favourites"
|
||||
def favourites(%{assigns: %{user: %User{} = user}} = conn, params) do
|
||||
activities =
|
||||
ActivityPub.fetch_favourites(
|
||||
user,
|
||||
Map.take(params, Pleroma.Pagination.page_keys())
|
||||
)
|
||||
params =
|
||||
params
|
||||
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|
||||
|> Map.take(Pleroma.Pagination.page_keys())
|
||||
|
||||
activities = ActivityPub.fetch_favourites(user, params)
|
||||
|
||||
conn
|
||||
|> add_link_headers(activities)
|
||||
|
|
|
@ -5,11 +5,26 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.SuggestionController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
|
||||
require Logger
|
||||
|
||||
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :index)
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
plug(Pleroma.Plugs.OAuthScopesPlug, %{scopes: ["read"]} when action == :index)
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def index_operation do
|
||||
%OpenApiSpex.Operation{
|
||||
tags: ["Suggestions"],
|
||||
summary: "Follow suggestions (Not implemented)",
|
||||
operationId: "SuggestionController.index",
|
||||
responses: %{
|
||||
200 => Pleroma.Web.ApiSpec.Helpers.empty_array_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@doc "GET /api/v1/suggestions"
|
||||
def index(conn, params),
|
||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
|||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper,
|
||||
only: [add_link_headers: 2, add_link_headers: 3, truthy_param?: 1, skip_relationships?: 1]
|
||||
only: [add_link_headers: 2, add_link_headers: 3, skip_relationships?: 1]
|
||||
|
||||
alias Pleroma.Pagination
|
||||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||
|
@ -15,6 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
|||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:public, :hashtag])
|
||||
|
||||
# TODO: Replace with a macro when there is a Phoenix release with the following commit in it:
|
||||
|
@ -37,10 +38,13 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
|||
|
||||
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TimelineOperation
|
||||
|
||||
# GET /api/v1/timelines/home
|
||||
def home(%{assigns: %{user: user}} = conn, params) do
|
||||
params =
|
||||
params
|
||||
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|
||||
|> Map.put("type", ["Create", "Announce"])
|
||||
|> Map.put("blocking_user", user)
|
||||
|> Map.put("muting_user", user)
|
||||
|
@ -68,6 +72,7 @@ def home(%{assigns: %{user: user}} = conn, params) do
|
|||
def direct(%{assigns: %{user: user}} = conn, params) do
|
||||
params =
|
||||
params
|
||||
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|
||||
|> Map.put("type", "Create")
|
||||
|> Map.put("blocking_user", user)
|
||||
|> Map.put("user", user)
|
||||
|
@ -90,7 +95,9 @@ def direct(%{assigns: %{user: user}} = conn, params) do
|
|||
|
||||
# GET /api/v1/timelines/public
|
||||
def public(%{assigns: %{user: user}} = conn, params) do
|
||||
local_only = truthy_param?(params["local"])
|
||||
params = Map.new(params, fn {key, value} -> {to_string(key), value} end)
|
||||
|
||||
local_only = params["local"]
|
||||
|
||||
cfg_key =
|
||||
if local_only do
|
||||
|
@ -157,8 +164,8 @@ defp hashtag_fetching(params, user, local_only) do
|
|||
|
||||
# GET /api/v1/timelines/tag/:tag
|
||||
def hashtag(%{assigns: %{user: user}} = conn, params) do
|
||||
local_only = truthy_param?(params["local"])
|
||||
|
||||
params = Map.new(params, fn {key, value} -> {to_string(key), value} end)
|
||||
local_only = params["local"]
|
||||
activities = hashtag_fetching(params, user, local_only)
|
||||
|
||||
conn
|
||||
|
@ -172,10 +179,11 @@ def hashtag(%{assigns: %{user: user}} = conn, params) do
|
|||
end
|
||||
|
||||
# GET /api/v1/timelines/list/:list_id
|
||||
def list(%{assigns: %{user: user}} = conn, %{"list_id" => id} = params) do
|
||||
def list(%{assigns: %{user: user}} = conn, %{list_id: id} = params) do
|
||||
with %Pleroma.List{title: _title, following: following} <- Pleroma.List.get(id, user) do
|
||||
params =
|
||||
params
|
||||
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|
||||
|> Map.put("type", "Create")
|
||||
|> Map.put("blocking_user", user)
|
||||
|> Map.put("user", user)
|
||||
|
|
|
@ -261,7 +261,10 @@ defp do_render("show.json", %{user: user} = opts) do
|
|||
defp prepare_user_bio(%User{bio: ""}), do: ""
|
||||
|
||||
defp prepare_user_bio(%User{bio: bio}) when is_binary(bio) do
|
||||
bio |> String.replace(~r(<br */?>), "\n") |> Pleroma.HTML.strip_tags()
|
||||
bio
|
||||
|> String.replace(~r(<br */?>), "\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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
defmodule Pleroma.Web.MongooseIM.MongooseIMController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Plugs.AuthenticationPlug
|
||||
alias Pleroma.Plugs.RateLimiter
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
@ -28,7 +28,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 <- AuthenticationPlug.checkpw(password, password_hash) do
|
||||
conn
|
||||
|> json(true)
|
||||
else
|
||||
|
|
|
@ -18,6 +18,13 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
plug(
|
||||
OpenApiSpex.Plug.PutApiSpec,
|
||||
[module: Pleroma.Web.ApiSpec] when action == :confirmation_resend
|
||||
)
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
|
||||
plug(
|
||||
:skip_plug,
|
||||
[OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirmation_resend
|
||||
|
@ -49,9 +56,11 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
|
|||
plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
|
||||
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation
|
||||
|
||||
@doc "POST /api/v1/pleroma/accounts/confirmation_resend"
|
||||
def confirmation_resend(conn, params) do
|
||||
nickname_or_email = params["email"] || params["nickname"]
|
||||
nickname_or_email = params[:email] || params[:nickname]
|
||||
|
||||
with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
|
||||
{:ok, _} <- User.try_send_confirmation_email(user) do
|
||||
|
@ -60,7 +69,7 @@ def confirmation_resend(conn, params) do
|
|||
end
|
||||
|
||||
@doc "PATCH /api/v1/pleroma/accounts/update_avatar"
|
||||
def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
||||
def update_avatar(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do
|
||||
{:ok, _user} =
|
||||
user
|
||||
|> Changeset.change(%{avatar: nil})
|
||||
|
@ -69,7 +78,7 @@ def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
|||
json(conn, %{url: nil})
|
||||
end
|
||||
|
||||
def update_avatar(%{assigns: %{user: user}} = conn, params) do
|
||||
def update_avatar(%{assigns: %{user: user}, body_params: params} = conn, _params) do
|
||||
{:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar)
|
||||
{:ok, _user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache()
|
||||
%{"url" => [%{"href" => href} | _]} = data
|
||||
|
@ -78,14 +87,14 @@ def update_avatar(%{assigns: %{user: user}} = conn, params) do
|
|||
end
|
||||
|
||||
@doc "PATCH /api/v1/pleroma/accounts/update_banner"
|
||||
def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
|
||||
def update_banner(%{assigns: %{user: user}, body_params: %{banner: ""}} = conn, _) do
|
||||
with {:ok, _user} <- User.update_banner(user, %{}) do
|
||||
json(conn, %{url: nil})
|
||||
end
|
||||
end
|
||||
|
||||
def update_banner(%{assigns: %{user: user}} = conn, params) do
|
||||
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner),
|
||||
def update_banner(%{assigns: %{user: user}, body_params: params} = conn, _) do
|
||||
with {:ok, object} <- ActivityPub.upload(%{img: params[:banner]}, type: :banner),
|
||||
{:ok, _user} <- User.update_banner(user, object.data) do
|
||||
%{"url" => [%{"href" => href} | _]} = object.data
|
||||
|
||||
|
@ -94,13 +103,13 @@ def update_banner(%{assigns: %{user: user}} = conn, params) do
|
|||
end
|
||||
|
||||
@doc "PATCH /api/v1/pleroma/accounts/update_background"
|
||||
def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
||||
def update_background(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do
|
||||
with {:ok, _user} <- User.update_background(user, %{}) do
|
||||
json(conn, %{url: nil})
|
||||
end
|
||||
end
|
||||
|
||||
def update_background(%{assigns: %{user: user}} = conn, params) do
|
||||
def update_background(%{assigns: %{user: user}, body_params: params} = conn, _) do
|
||||
with {:ok, object} <- ActivityPub.upload(params, type: :background),
|
||||
{:ok, _user} <- User.update_background(user, object.data) do
|
||||
%{"url" => [%{"href" => href} | _]} = object.data
|
||||
|
@ -117,6 +126,7 @@ def favourites(%{assigns: %{account: %{hide_favorites: true}}} = conn, _params)
|
|||
def favourites(%{assigns: %{user: for_user, account: user}} = conn, params) do
|
||||
params =
|
||||
params
|
||||
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|
||||
|> Map.put("type", "Create")
|
||||
|> Map.put("favorited_by", user.ap_id)
|
||||
|> Map.put("blocking_user", for_user)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
17
mix.exs
17
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,8 @@ 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"},
|
||||
{:bcrypt_elixir, "~> 2.0"},
|
||||
{:trailing_format_plug, "~> 0.0.7"},
|
||||
{:fast_sanitize, "~> 0.1"},
|
||||
{:html_entities, "~> 0.5", override: true},
|
||||
|
@ -193,7 +200,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
|
||||
|
||||
|
|
8
mix.lock
8
mix.lock
|
@ -5,6 +5,7 @@
|
|||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
|
||||
"bbcode": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/bbcode.git", "f2d267675e9a7e1ad1ea9beb4cc23382762b66c2", [ref: "v0.2.0"]},
|
||||
"bbcode_pleroma": {:hex, :bbcode_pleroma, "0.2.0", "d36f5bca6e2f62261c45be30fa9b92725c0655ad45c99025cb1c3e28e25803ef", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "19851074419a5fedb4ef49e1f01b30df504bb5dbb6d6adfc135238063bebd1c3"},
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.2.0", "3df902b81ce7fa8867a2ae30d20a1da6877a2c056bfb116fd0bc8a5f0190cea4", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "762be3fcb779f08207531bc6612cca480a338e4b4357abb49f5ce00240a77d1e"},
|
||||
"benchee": {:hex, :benchee, "1.0.1", "66b211f9bfd84bd97e6d1beaddf8fc2312aaabe192f776e8931cb0c16f53a521", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm", "3ad58ae787e9c7c94dd7ceda3b587ec2c64604563e049b2a0e8baafae832addb"},
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||
"cachex": {:hex, :cachex, "3.2.0", "a596476c781b0646e6cb5cd9751af2e2974c3e0d5498a8cab71807618b74fe2f", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "aef93694067a43697ae0531727e097754a9e992a1e7946296f5969d6dd9ac986"},
|
||||
|
@ -13,7 +14,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"},
|
||||
|
@ -30,6 +31,7 @@
|
|||
"ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.3.4", "aa18af12eb875fbcda2f75e608b3bd534ebf020fc4f6448e4672fcdcbb081244", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4 or ~> 3.3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5eccbdbf92e3c6f213007a82d5dbba4cd9bb659d1a21331f89f408e4c0efd7a8"},
|
||||
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"},
|
||||
"esshd": {:hex, :esshd, "0.1.1", "d4dd4c46698093a40a56afecce8a46e246eb35463c457c246dacba2e056f31b5", [:mix], [], "hexpm", "d73e341e3009d390aa36387dc8862860bf9f874c94d9fd92ade2926376f49981"},
|
||||
"eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm", "b14f1dc204321429479c569cfbe8fb287541184ed040956c8862cb7a677b8406"},
|
||||
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
|
||||
|
@ -75,10 +77,10 @@
|
|||
"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"]},
|
||||
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"},
|
||||
"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"},
|
||||
|
|
|
@ -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 ""
|
|
@ -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 ""
|
||||
|
|
|
@ -8,8 +8,16 @@
|
|||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2020-05-12 15:52+0000\n"
|
||||
"Last-Translator: Haelwenn (lanodan) Monnier "
|
||||
"<contact+translate.pleroma.social@hacktivis.me>\n"
|
||||
"Language-Team: French <https://translate.pleroma.social/projects/pleroma/"
|
||||
"pleroma/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.0.4\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr "ne peut être vide"
|
||||
|
@ -35,10 +43,10 @@ msgid "does not match confirmation"
|
|||
msgstr "ne correspondent pas"
|
||||
|
||||
msgid "is still associated with this entry"
|
||||
msgstr ""
|
||||
msgstr "est toujours associé à cette entrée"
|
||||
|
||||
msgid "are still associated with this entry"
|
||||
msgstr ""
|
||||
msgstr "sont toujours associés à cette entrée"
|
||||
|
||||
msgid "should be %{count} character(s)"
|
||||
msgid_plural "should be %{count} character(s)"
|
||||
|
@ -85,375 +93,375 @@ msgstr "doit être supérieur ou égal à %{number}"
|
|||
msgid "must be equal to %{number}"
|
||||
msgstr "doit égal à %{number}"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:381
|
||||
#, elixir-format
|
||||
msgid "Account not found"
|
||||
msgstr "Compte non trouvé"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:153
|
||||
#, elixir-format
|
||||
msgid "Already voted"
|
||||
msgstr "A déjà voté"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:263
|
||||
#, elixir-format
|
||||
msgid "Bad request"
|
||||
msgstr "Requête Invalide"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:254
|
||||
#, elixir-format
|
||||
msgid "Can't delete object"
|
||||
msgstr "Ne peut supprimer cet objet"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:569
|
||||
#, elixir-format
|
||||
msgid "Can't delete this post"
|
||||
msgstr "Ne peut supprimer ce message"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1731
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1737
|
||||
#, elixir-format
|
||||
msgid "Can't display this activity"
|
||||
msgstr "Ne peut afficher cette activitée"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:195
|
||||
#, elixir-format
|
||||
msgid "Can't find user"
|
||||
msgstr "Compte non trouvé"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1148
|
||||
#, elixir-format
|
||||
msgid "Can't get favorites"
|
||||
msgstr "Favoris non trouvables"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:263
|
||||
#, elixir-format
|
||||
msgid "Can't like object"
|
||||
msgstr "Ne peut aimer cet objet"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:518
|
||||
#, elixir-format
|
||||
msgid "Cannot post an empty status without attachments"
|
||||
msgstr "Ne peut envoyer un status vide sans attachements"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:461
|
||||
#, elixir-format
|
||||
msgid "Comment must be up to %{max_size} characters"
|
||||
msgstr "Le commentaire ne doit faire plus de %{max_size} charactères"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/admin_api/config.ex:63
|
||||
#, elixir-format
|
||||
msgid "Config with params %{params} not found"
|
||||
msgstr "Configuration avec les paramètres %{params} non trouvée"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:78
|
||||
#, elixir-format
|
||||
msgid "Could not delete"
|
||||
msgstr "Échec de la suppression"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:110
|
||||
#, elixir-format
|
||||
msgid "Could not favorite"
|
||||
msgstr "Échec de mise en favoris"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:310
|
||||
#, elixir-format
|
||||
msgid "Could not pin"
|
||||
msgstr "Échec de l'épinglage"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:89
|
||||
#, elixir-format
|
||||
msgid "Could not repeat"
|
||||
msgstr "Échec de création la répétition"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:120
|
||||
#, elixir-format
|
||||
msgid "Could not unfavorite"
|
||||
msgstr "Échec de suppression des favoris"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:327
|
||||
#, elixir-format
|
||||
msgid "Could not unpin"
|
||||
msgstr "Échec du dépinglage"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:99
|
||||
#, elixir-format
|
||||
msgid "Could not unrepeat"
|
||||
msgstr "Échec de suppression de la répétition"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:392
|
||||
#, elixir-format
|
||||
msgid "Could not update state"
|
||||
msgstr "Échec de la mise à jour du status"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1271
|
||||
#, elixir-format
|
||||
msgid "Error."
|
||||
msgstr "Erreur."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/captcha/kocaptcha.ex:36
|
||||
#, elixir-format
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "CAPTCHA invalide"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1700
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:465
|
||||
#, elixir-format
|
||||
msgid "Invalid credentials"
|
||||
msgstr "Paramètres d'authentification invalides"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:20
|
||||
#, elixir-format
|
||||
msgid "Invalid credentials."
|
||||
msgstr "Paramètres d'authentification invalides."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:154
|
||||
#, elixir-format
|
||||
msgid "Invalid indices"
|
||||
msgstr "Indices invalides"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:411
|
||||
#, elixir-format
|
||||
msgid "Invalid parameters"
|
||||
msgstr "Paramètres invalides"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:377
|
||||
#, elixir-format
|
||||
msgid "Invalid password."
|
||||
msgstr "Mot de passe invalide."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:163
|
||||
#, elixir-format
|
||||
msgid "Invalid request"
|
||||
msgstr "Requête invalide"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/captcha/kocaptcha.ex:16
|
||||
#, elixir-format
|
||||
msgid "Kocaptcha service unavailable"
|
||||
msgstr "Service Kocaptcha non disponible"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:1696
|
||||
#, elixir-format
|
||||
msgid "Missing parameters"
|
||||
msgstr "Paramètres manquants"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:496
|
||||
#, elixir-format
|
||||
msgid "No such conversation"
|
||||
msgstr "Conversation inconnue"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:163
|
||||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:206
|
||||
#, elixir-format
|
||||
msgid "No such permission_group"
|
||||
msgstr "Groupe de permission inconnu"
|
||||
|
||||
#, 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
|
||||
#, elixir-format
|
||||
msgid "Not found"
|
||||
msgstr "Non Trouvé"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:152
|
||||
#, elixir-format
|
||||
msgid "Poll's author can't vote"
|
||||
msgstr "L'auteur·rice d'un sondage ne peut voter"
|
||||
|
||||
#, 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
|
||||
#, elixir-format
|
||||
msgid "Record not found"
|
||||
msgstr "Enregistrement non trouvé"
|
||||
|
||||
#, 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
|
||||
#, elixir-format
|
||||
msgid "Something went wrong"
|
||||
msgstr "Erreur inconnue"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:253
|
||||
#, elixir-format
|
||||
msgid "The message visibility must be direct"
|
||||
msgstr "La visibilitée du message doit être « direct »"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:521
|
||||
#, elixir-format
|
||||
msgid "The status is over the character limit"
|
||||
msgstr "Le status est au-delà de la limite de charactères"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:27
|
||||
#, elixir-format
|
||||
msgid "This resource requires authentication."
|
||||
msgstr "Cette resource nécessite une authentification."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/plugs/rate_limiter.ex:89
|
||||
#, elixir-format
|
||||
msgid "Throttled"
|
||||
msgstr "Limité"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:155
|
||||
#, elixir-format
|
||||
msgid "Too many choices"
|
||||
msgstr "Trop de choix"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:268
|
||||
#, elixir-format
|
||||
msgid "Unhandled activity type"
|
||||
msgstr "Type d'activitée non-gérée"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/plugs/user_is_admin_plug.ex:20
|
||||
#, elixir-format
|
||||
msgid "User is not admin."
|
||||
msgstr "Le compte n'est pas admin."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:380
|
||||
#, elixir-format
|
||||
msgid "Valid `account_id` required"
|
||||
msgstr "Un `account_id` valide est requis"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:185
|
||||
#, elixir-format
|
||||
msgid "You can't revoke your own admin status."
|
||||
msgstr "Vous ne pouvez révoquer votre propre status d'admin."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:216
|
||||
#, elixir-format
|
||||
msgid "Your account is currently disabled"
|
||||
msgstr "Votre compte est actuellement désactivé"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:158
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:213
|
||||
#, elixir-format
|
||||
msgid "Your login is missing a confirmed e-mail address"
|
||||
msgstr "Une confirmation de l'addresse de couriel est requise pour l'authentification"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:221
|
||||
#, elixir-format
|
||||
msgid "can't read inbox of %{nickname} as %{as_nickname}"
|
||||
msgstr "Ne peut lire la boite de réception de %{nickname} en tant que %{as_nickname}"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:297
|
||||
#, elixir-format
|
||||
msgid "can't update outbox of %{nickname} as %{as_nickname}"
|
||||
msgstr "Ne peut poster dans la boite d'émission de %{nickname} en tant que %{as_nickname}"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api/common_api.ex:335
|
||||
#, elixir-format
|
||||
msgid "conversation is already muted"
|
||||
msgstr "la conversation est déjà baillonée"
|
||||
|
||||
#, 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
|
||||
#, elixir-format
|
||||
msgid "error"
|
||||
msgstr "erreur"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/mastodon_api_controller.ex:789
|
||||
#, elixir-format
|
||||
msgid "mascots can only be images"
|
||||
msgstr "les mascottes ne peuvent être que des images"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:34
|
||||
#, elixir-format
|
||||
msgid "not found"
|
||||
msgstr "non trouvé"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:298
|
||||
#, elixir-format
|
||||
msgid "Bad OAuth request."
|
||||
msgstr "Requête OAuth invalide."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/captcha/captcha.ex:92
|
||||
#, elixir-format
|
||||
msgid "CAPTCHA already used"
|
||||
msgstr "CAPTCHA déjà utilisé"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/captcha/captcha.ex:89
|
||||
#, elixir-format
|
||||
msgid "CAPTCHA expired"
|
||||
msgstr "CAPTCHA expiré"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/plugs/uploaded_media.ex:50
|
||||
#, elixir-format
|
||||
msgid "Failed"
|
||||
msgstr "Échec"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:314
|
||||
msgid "Failed to authenticate: %{message}."
|
||||
msgstr "Échec de l'authentification: %{message}"
|
||||
|
||||
#, elixir-format
|
||||
msgid "Failed to authenticate: %{message}."
|
||||
msgstr "Échec de l'authentification : %{message}."
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:345
|
||||
#, elixir-format
|
||||
msgid "Failed to set up user account."
|
||||
msgstr "Échec de création de votre compte."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/plugs/oauth_scopes_plug.ex:37
|
||||
msgid "Insufficient permissions: %{permissions}."
|
||||
msgstr "Permissions insuffisantes: %{permissions}."
|
||||
|
||||
#, elixir-format
|
||||
msgid "Insufficient permissions: %{permissions}."
|
||||
msgstr "Permissions insuffisantes : %{permissions}."
|
||||
|
||||
#: lib/pleroma/plugs/uploaded_media.ex:89
|
||||
#, elixir-format
|
||||
msgid "Internal Error"
|
||||
msgstr "Erreur interne"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/fallback_controller.ex:22
|
||||
#: lib/pleroma/web/oauth/fallback_controller.ex:29
|
||||
#, elixir-format
|
||||
msgid "Invalid Username/Password"
|
||||
msgstr "Nom d'utilisateur/mot de passe invalide"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/captcha/captcha.ex:107
|
||||
#, elixir-format
|
||||
msgid "Invalid answer data"
|
||||
msgstr "Réponse invalide"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:204
|
||||
#, elixir-format
|
||||
msgid "Nodeinfo schema version not handled"
|
||||
msgstr "Version du schéma nodeinfo non géré"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:145
|
||||
msgid "This action is outside the authorized scopes"
|
||||
msgstr "Cette action est en dehors des authorisations" # "scopes" ?
|
||||
|
||||
#, elixir-format
|
||||
msgid "This action is outside the authorized scopes"
|
||||
msgstr "Cette action est en dehors des authorisations" # "scopes"
|
||||
|
||||
#: lib/pleroma/web/oauth/fallback_controller.ex:14
|
||||
#, elixir-format
|
||||
msgid "Unknown error, please check the details and try again."
|
||||
msgstr "Erreur inconnue, veuillez vérifier les détails et réessayer."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:93
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:131
|
||||
#, elixir-format
|
||||
msgid "Unlisted redirect_uri."
|
||||
msgstr "redirect_uri non listé."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:294
|
||||
#, elixir-format
|
||||
msgid "Unsupported OAuth provider: %{provider}."
|
||||
msgstr "Fournisseur OAuth non supporté : %{provider}."
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/uploaders/uploader.ex:71
|
||||
msgid "Uploader callback timeout"
|
||||
msgstr ""
|
||||
## msgstr "Attente écoulée"
|
||||
|
||||
#, elixir-format
|
||||
msgid "Uploader callback timeout"
|
||||
msgstr "Temps d'attente du téléverseur écoulé"
|
||||
|
||||
## msgstr "Attente écoulée"
|
||||
#: lib/pleroma/web/uploader_controller.ex:11
|
||||
#: lib/pleroma/web/uploader_controller.ex:23
|
||||
#, elixir-format
|
||||
msgid "bad request"
|
||||
msgstr "requête invalide"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -1 +1 @@
|
|||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.18fea621d430000acc27.css rel=stylesheet><link href=/static/css/app.613cef07981cd95ccceb.css rel=stylesheet><link href=/static/fontello.1588419330867.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.8aa781e6dd81307f544b.js></script><script type=text/javascript src=/static/js/app.fa89b90e606f4facd209.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.18fea621d430000acc27.css rel=stylesheet><link href=/static/css/app.613cef07981cd95ccceb.css rel=stylesheet><link href=/static/fontello.1588947937982.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.561a1c605d1dfb0e6f74.js></script><script type=text/javascript src=/static/js/app.996428ccaaaa7f28cb8d.js></script></body></html>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -114,6 +114,8 @@
|
|||
|
||||
<glyph glyph-name="thumbs-up-alt" unicode="" d="M143 107q0 15-11 25t-25 11q-15 0-25-11t-11-25q0-15 11-25t25-11q15 0 25 11t11 25z m89 286v-357q0-15-10-25t-26-11h-160q-15 0-25 11t-11 25v357q0 14 11 25t25 10h160q15 0 26-10t10-25z m661 0q0-48-31-83 9-25 9-43 1-42-24-76 9-31 0-66-9-31-31-52 5-62-27-101-36-43-110-44h-72q-37 0-80 9t-68 16-67 22q-69 24-88 25-15 0-25 11t-11 25v357q0 14 10 25t24 11q13 1 42 33t57 67q38 49 56 67 10 10 17 27t10 27 8 34q4 22 7 34t11 29 19 28q10 11 25 11 25 0 46-6t33-15 22-22 14-25 7-28 2-25 1-22q0-21-6-43t-10-33-16-31q-1-4-5-10t-6-13-5-13h155q43 0 75-32t32-75z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="share" unicode="" d="M679 286q74 0 126-53t52-126-52-126-126-53-127 53-52 126q0 7 1 19l-201 100q-51-48-121-48-75 0-127 53t-52 126 52 126 127 53q70 0 121-48l201 100q-1 12-1 19 0 74 52 126t127 53 126-53 52-126-52-126-126-53q-71 0-122 48l-201-100q1-12 1-19t-1-19l201-100q51 48 122 48z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="binoculars" unicode="" d="M393 678v-428q0-15-11-25t-25-11v-321q0-15-10-25t-26-11h-285q-15 0-25 11t-11 25v285l139 488q4 12 17 12h237z m178 0v-392h-142v392h142z m429-500v-285q0-15-11-25t-25-11h-285q-15 0-25 11t-11 25v321q-15 0-25 11t-11 25v428h237q13 0 17-12z m-589 661v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z m375 0v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="user-plus" unicode="" d="M393 357q-89 0-152 63t-62 151 62 152 152 63 151-63 63-152-63-151-151-63z m536-71h196q7 0 13-6t5-12v-107q0-8-5-13t-13-5h-196v-197q0-7-6-12t-12-6h-107q-8 0-13 6t-5 12v197h-197q-7 0-12 5t-6 13v107q0 7 6 12t12 6h197v196q0 7 5 13t13 5h107q7 0 12-5t6-13v-196z m-411-125q0-29 21-51t50-21h143v-133q-38-28-95-28h-488q-67 0-108 39t-41 106q0 30 2 58t8 61 15 60 24 55 34 45 48 30 62 11q11 0 22-10 44-34 86-51t92-17 92 17 86 51q11 10 22 10 73 0 121-54h-125q-29 0-50-21t-21-50v-107z" horiz-adv-x="1142.9" />
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -346,6 +346,12 @@
|
|||
"code": 59427,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "4aad6bb50b02c18508aae9cbe14e784e",
|
||||
"css": "share",
|
||||
"code": 61920,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "8b80d36d4ef43889db10bc1f0dc9a862",
|
||||
"css": "user",
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -11,6 +11,11 @@ defmodule Pleroma.ActivityTest do
|
|||
alias Pleroma.ThreadMute
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "returns an activity by it's AP id" do
|
||||
activity = insert(:note_activity)
|
||||
found_activity = Activity.get_by_ap_id(activity.data["id"])
|
||||
|
@ -107,8 +112,6 @@ test "when association is not loaded" do
|
|||
|
||||
describe "search" do
|
||||
setup do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
params = %{
|
||||
|
@ -125,8 +128,8 @@ test "when association is not loaded" do
|
|||
"to" => ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
}
|
||||
|
||||
{:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "find me!"})
|
||||
{:ok, japanese_activity} = Pleroma.Web.CommonAPI.post(user, %{"status" => "更新情報"})
|
||||
{:ok, local_activity} = Pleroma.Web.CommonAPI.post(user, %{status: "find me!"})
|
||||
{:ok, japanese_activity} = Pleroma.Web.CommonAPI.post(user, %{status: "更新情報"})
|
||||
{:ok, job} = Pleroma.Web.Federator.incoming_ap_doc(params)
|
||||
{:ok, remote_activity} = ObanHelpers.perform(job)
|
||||
|
||||
|
@ -225,8 +228,8 @@ test "get_by_id/1" do
|
|||
test "all_by_actor_and_id/2" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, %{id: id1}} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"})
|
||||
{:ok, %{id: id2}} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofefe"})
|
||||
{:ok, %{id: id1}} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
|
||||
{:ok, %{id: id2}} = Pleroma.Web.CommonAPI.post(user, %{status: "cofefe"})
|
||||
|
||||
assert [] == Activity.all_by_actor_and_id(user, [])
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ test "getting the home timeline" do
|
|||
|
||||
{:ok, user} = User.follow(user, followed)
|
||||
|
||||
{:ok, _first} = CommonAPI.post(user, %{"status" => "hey"})
|
||||
{:ok, _second} = CommonAPI.post(followed, %{"status" => "hello"})
|
||||
{:ok, _first} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, _second} = CommonAPI.post(followed, %{status: "hello"})
|
||||
|
||||
output =
|
||||
capture_io(fn ->
|
||||
|
@ -62,7 +62,7 @@ test "replying" do
|
|||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{"status" => "this is a test post"})
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{status: "this is a test post"})
|
||||
activity_object = Object.normalize(activity)
|
||||
|
||||
output =
|
||||
|
|
|
@ -11,7 +11,7 @@ defmodule Pleroma.BookmarkTest do
|
|||
describe "create/2" do
|
||||
test "with valid params" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Some cool information"})
|
||||
{:ok, bookmark} = Bookmark.create(user.id, activity.id)
|
||||
assert bookmark.user_id == user.id
|
||||
assert bookmark.activity_id == activity.id
|
||||
|
@ -32,7 +32,7 @@ test "with invalid params" do
|
|||
test "with valid params" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Some cool information"})
|
||||
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
|
||||
|
||||
{:ok, _deleted_bookmark} = Bookmark.destroy(user.id, activity.id)
|
||||
|
@ -45,7 +45,7 @@ test "gets a bookmark" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
status:
|
||||
"Scientists Discover The Secret Behind Tenshi Eating A Corndog Being So Cute – Science Daily"
|
||||
})
|
||||
|
||||
|
|
|
@ -43,11 +43,9 @@ test "get_all_as_keyword/0" do
|
|||
{ConfigDB.from_string(saved.key), ConfigDB.from_binary(saved.value)}
|
||||
]
|
||||
|
||||
assert config[:quack] == [
|
||||
level: :info,
|
||||
meta: [:none],
|
||||
webhook_url: "https://hooks.slack.com/services/KEY/some_val"
|
||||
]
|
||||
assert config[:quack][:level] == :info
|
||||
assert config[:quack][:meta] == [:none]
|
||||
assert config[:quack][:webhook_url] == "https://hooks.slack.com/services/KEY/some_val"
|
||||
end
|
||||
|
||||
describe "update_or_create/1" do
|
||||
|
|
|
@ -16,7 +16,7 @@ test "getting a participation will also preload things" do
|
|||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
|
||||
CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
|
@ -30,7 +30,7 @@ test "for a new conversation or a reply, it doesn't mark the author's participat
|
|||
other_user = insert(:user)
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
|
||||
CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
@ -43,9 +43,9 @@ test "for a new conversation or a reply, it doesn't mark the author's participat
|
|||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(other_user, %{
|
||||
"status" => "Hey @#{user.nickname}.",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_conversation_id" => participation.id
|
||||
status: "Hey @#{user.nickname}.",
|
||||
visibility: "direct",
|
||||
in_reply_to_conversation_id: participation.id
|
||||
})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
@ -64,7 +64,7 @@ test "for a new conversation, it sets the recipents of the participation" do
|
|||
third_user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
|
||||
CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
@ -79,9 +79,9 @@ test "for a new conversation, it sets the recipents of the participation" do
|
|||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"in_reply_to_status_id" => activity.id,
|
||||
"status" => "Hey @#{third_user.nickname}.",
|
||||
"visibility" => "direct"
|
||||
in_reply_to_status_id: activity.id,
|
||||
status: "Hey @#{third_user.nickname}.",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
@ -154,14 +154,14 @@ test "it marks all the user's participations as read" do
|
|||
|
||||
test "gets all the participations for a user, ordered by updated at descending" do
|
||||
user = insert(:user)
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
|
||||
{:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{status: "x", visibility: "direct"})
|
||||
{:ok, activity_two} = CommonAPI.post(user, %{status: "x", visibility: "direct"})
|
||||
|
||||
{:ok, activity_three} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "x",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity_one.id
|
||||
status: "x",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: activity_one.id
|
||||
})
|
||||
|
||||
# Offset participations because the accuracy of updated_at is down to a second
|
||||
|
@ -201,7 +201,7 @@ test "gets all the participations for a user, ordered by updated at descending"
|
|||
test "Doesn't die when the conversation gets empty" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
[participation] = Participation.for_user_with_last_activity_id(user)
|
||||
|
||||
assert participation.last_activity_id == activity.id
|
||||
|
@ -215,7 +215,7 @@ test "it sets recipients, always keeping the owner of the participation even whe
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
[participation] = Participation.for_user_with_last_activity_id(user)
|
||||
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
@ -239,26 +239,26 @@ test "when the user blocks a recipient, the existing conversations with them are
|
|||
|
||||
{:ok, _direct1} =
|
||||
CommonAPI.post(third_user, %{
|
||||
"status" => "Hi @#{blocker.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{blocker.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, _direct2} =
|
||||
CommonAPI.post(third_user, %{
|
||||
"status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{blocker.nickname}, @#{blocked.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, _direct3} =
|
||||
CommonAPI.post(blocked, %{
|
||||
"status" => "Hi @#{blocker.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{blocker.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, _direct4} =
|
||||
CommonAPI.post(blocked, %{
|
||||
"status" => "Hi @#{blocker.nickname}, @#{third_user.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{blocker.nickname}, @#{third_user.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] =
|
||||
|
@ -293,8 +293,8 @@ test "the new conversation with the blocked user is not marked as unread " do
|
|||
# When the blocked user is the author
|
||||
{:ok, _direct1} =
|
||||
CommonAPI.post(blocked, %{
|
||||
"status" => "Hi @#{blocker.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{blocker.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
assert [%{read: true}] = Participation.for_user(blocker)
|
||||
|
@ -303,8 +303,8 @@ test "the new conversation with the blocked user is not marked as unread " do
|
|||
# When the blocked user is a recipient
|
||||
{:ok, _direct2} =
|
||||
CommonAPI.post(third_user, %{
|
||||
"status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{blocker.nickname}, @#{blocked.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
assert [%{read: true}, %{read: true}] = Participation.for_user(blocker)
|
||||
|
@ -321,8 +321,8 @@ test "the conversation with the blocked user is not marked as unread on a reply"
|
|||
|
||||
{:ok, _direct1} =
|
||||
CommonAPI.post(blocker, %{
|
||||
"status" => "Hi @#{third_user.nickname}, @#{blocked.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "Hi @#{third_user.nickname}, @#{blocked.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, _user_relationship} = User.block(blocker, blocked)
|
||||
|
@ -334,9 +334,9 @@ test "the conversation with the blocked user is not marked as unread on a reply"
|
|||
# When it's a reply from the blocked user
|
||||
{:ok, _direct2} =
|
||||
CommonAPI.post(blocked, %{
|
||||
"status" => "reply",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_conversation_id" => blocked_participation.id
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_conversation_id: blocked_participation.id
|
||||
})
|
||||
|
||||
assert [%{read: true}] = Participation.for_user(blocker)
|
||||
|
@ -347,9 +347,9 @@ test "the conversation with the blocked user is not marked as unread on a reply"
|
|||
# When it's a reply from the third user
|
||||
{:ok, _direct3} =
|
||||
CommonAPI.post(third_user, %{
|
||||
"status" => "reply",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_conversation_id" => third_user_participation.id
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_conversation_id: third_user_participation.id
|
||||
})
|
||||
|
||||
assert [%{read: true}] = Participation.for_user(blocker)
|
||||
|
|
|
@ -18,7 +18,7 @@ test "it goes through old direct conversations" do
|
|||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{"visibility" => "direct", "status" => "hey @#{other_user.nickname}"})
|
||||
CommonAPI.post(user, %{visibility: "direct", status: "hey @#{other_user.nickname}"})
|
||||
|
||||
Pleroma.Tests.ObanHelpers.perform_all()
|
||||
|
||||
|
@ -46,7 +46,7 @@ test "it creates a conversation for given ap_id" do
|
|||
|
||||
test "public posts don't create conversations" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Hey"})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
context = object.data["context"]
|
||||
|
@ -62,7 +62,7 @@ test "it creates or updates a conversation and participations for a given DM" do
|
|||
tridi = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "direct"})
|
||||
CommonAPI.post(har, %{status: "Hey @#{jafnhar.nickname}", visibility: "direct"})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
context = object.data["context"]
|
||||
|
@ -81,9 +81,9 @@ test "it creates or updates a conversation and participations for a given DM" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(jafnhar, %{
|
||||
"status" => "Hey @#{har.nickname}",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "Hey @#{har.nickname}",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
|
@ -105,9 +105,9 @@ test "it creates or updates a conversation and participations for a given DM" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(tridi, %{
|
||||
"status" => "Hey @#{har.nickname}",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "Hey @#{har.nickname}",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
|
@ -149,14 +149,14 @@ test "create_or_bump_for returns the conversation with participations" do
|
|||
jafnhar = insert(:user, local: false)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "direct"})
|
||||
CommonAPI.post(har, %{status: "Hey @#{jafnhar.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, conversation} = Conversation.create_or_bump_for(activity)
|
||||
|
||||
assert length(conversation.participations) == 2
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "public"})
|
||||
CommonAPI.post(har, %{status: "Hey @#{jafnhar.nickname}", visibility: "public"})
|
||||
|
||||
assert {:error, _} = Conversation.create_or_bump_for(activity)
|
||||
end
|
||||
|
|
|
@ -171,7 +171,7 @@ test "extracts the url" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
status:
|
||||
"I think I just found the best github repo https://github.com/komeiji-satori/Dress"
|
||||
})
|
||||
|
||||
|
@ -186,7 +186,7 @@ test "skips mentions" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
status:
|
||||
"@#{other_user.nickname} install misskey! https://github.com/syuilo/misskey/blob/develop/docs/setup.en.md"
|
||||
})
|
||||
|
||||
|
@ -203,8 +203,7 @@ test "skips hashtags" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
"#cofe https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
|
||||
status: "#cofe https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
@ -218,9 +217,9 @@ test "skips microformats hashtags" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
status:
|
||||
"<a href=\"https://pleroma.gov/tags/cofe\" rel=\"tag\">#cofe</a> https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140",
|
||||
"content_type" => "text/html"
|
||||
content_type: "text/html"
|
||||
})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
@ -232,8 +231,7 @@ test "skips microformats hashtags" do
|
|||
test "does not crash when there is an HTML entity in a link" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{"status" => "\"http://cofe.com/?boomer=ok&foo=bar\""})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "\"http://cofe.com/?boomer=ok&foo=bar\""})
|
||||
|
||||
object = Object.normalize(activity)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.HTTP.ConnectionTest do
|
||||
use ExUnit.Case, async: true
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
|
|
|
@ -3,23 +3,19 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.HTTP.RequestBuilderTest do
|
||||
use ExUnit.Case, async: true
|
||||
use ExUnit.Case
|
||||
use Pleroma.Tests.Helpers
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.HTTP.Request
|
||||
alias Pleroma.HTTP.RequestBuilder
|
||||
|
||||
describe "headers/2" do
|
||||
setup do: clear_config([:http, :send_user_agent])
|
||||
setup do: clear_config([:http, :user_agent])
|
||||
|
||||
test "don't send pleroma user agent" do
|
||||
assert RequestBuilder.headers(%Request{}, []) == %Request{headers: []}
|
||||
end
|
||||
|
||||
test "send pleroma user agent" do
|
||||
Config.put([:http, :send_user_agent], true)
|
||||
Config.put([:http, :user_agent], :default)
|
||||
clear_config([:http, :send_user_agent], true)
|
||||
clear_config([:http, :user_agent], :default)
|
||||
|
||||
assert RequestBuilder.headers(%Request{}, []) == %Request{
|
||||
headers: [{"user-agent", Pleroma.Application.user_agent()}]
|
||||
|
@ -27,8 +23,8 @@ test "send pleroma user agent" do
|
|||
end
|
||||
|
||||
test "send custom user agent" do
|
||||
Config.put([:http, :send_user_agent], true)
|
||||
Config.put([:http, :user_agent], "totally-not-pleroma")
|
||||
clear_config([:http, :send_user_agent], true)
|
||||
clear_config([:http, :user_agent], "totally-not-pleroma")
|
||||
|
||||
assert RequestBuilder.headers(%Request{}, []) == %Request{
|
||||
headers: [{"user-agent", "totally-not-pleroma"}]
|
||||
|
|
|
@ -32,7 +32,7 @@ def start_socket(qs \\ nil, headers \\ []) do
|
|||
|
||||
test "refuses invalid requests" do
|
||||
capture_log(fn ->
|
||||
assert {:error, {400, _}} = start_socket()
|
||||
assert {:error, {404, _}} = start_socket()
|
||||
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
|
||||
Process.sleep(30)
|
||||
end)
|
||||
|
@ -40,8 +40,8 @@ test "refuses invalid requests" do
|
|||
|
||||
test "requires authentication and a valid token for protected streams" do
|
||||
capture_log(fn ->
|
||||
assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
||||
assert {:error, {403, _}} = start_socket("?stream=user")
|
||||
assert {:error, {401, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
||||
assert {:error, {401, _}} = start_socket("?stream=user")
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
@ -55,7 +55,7 @@ test "allows public streams without authentication" do
|
|||
test "receives well formatted events" do
|
||||
user = insert(:user)
|
||||
{:ok, _} = start_socket("?stream=public")
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "nice echo chamber"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "nice echo chamber"})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
assert {:ok, json} = Jason.decode(raw_json)
|
||||
|
@ -100,7 +100,7 @@ test "accepts the 'user' stream", %{token: token} = _state do
|
|||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, {403, "Forbidden"}} = start_socket("?stream=user")
|
||||
assert {:error, {401, _}} = start_socket("?stream=user")
|
||||
Process.sleep(30)
|
||||
end) =~ ":badarg"
|
||||
end
|
||||
|
@ -109,7 +109,7 @@ test "accepts the 'user:notification' stream", %{token: token} = _state do
|
|||
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, {403, "Forbidden"}} = start_socket("?stream=user:notification")
|
||||
assert {:error, {401, _}} = start_socket("?stream=user:notification")
|
||||
Process.sleep(30)
|
||||
end) =~ ":badarg"
|
||||
end
|
||||
|
@ -118,7 +118,7 @@ test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
|||
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, {403, "Forbidden"}} =
|
||||
assert {:error, {401, _}} =
|
||||
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||
|
||||
Process.sleep(30)
|
||||
|
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.MFATest do
|
|||
use Pleroma.DataCase
|
||||
|
||||
import Pleroma.Factory
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.MFA
|
||||
|
||||
describe "mfa_settings" do
|
||||
|
@ -31,8 +30,8 @@ test "returns backup codes" do
|
|||
{:ok, [code1, code2]} = MFA.generate_backup_codes(user)
|
||||
updated_user = refresh_record(user)
|
||||
[hash1, hash2] = updated_user.multi_factor_authentication_settings.backup_codes
|
||||
assert Pbkdf2.checkpw(code1, hash1)
|
||||
assert Pbkdf2.checkpw(code2, hash2)
|
||||
assert Pbkdf2.verify_pass(code1, hash1)
|
||||
assert Pbkdf2.verify_pass(code2, hash2)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ test "creates a notification for an emoji reaction" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
|
||||
{:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
@ -40,7 +40,7 @@ test "notifies someone when they are directly addressed" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname} and @#{third_user.nickname}"
|
||||
status: "hey @#{other_user.nickname} and @#{third_user.nickname}"
|
||||
})
|
||||
|
||||
{:ok, [notification, other_notification]} = Notification.create_notifications(activity)
|
||||
|
@ -60,7 +60,7 @@ test "it creates a notification for subscribed users" do
|
|||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
|
||||
{:ok, [notification]} = Notification.create_notifications(status)
|
||||
|
||||
assert notification.user_id == subscriber.id
|
||||
|
@ -73,12 +73,12 @@ test "does not create a notification for subscribed users if status is a reply"
|
|||
|
||||
User.subscribe(subscriber, other_user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
{:ok, _reply_activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
"status" => "test reply",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "test reply",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
user_notifications = Notification.for_user(user)
|
||||
|
@ -98,7 +98,7 @@ test "does not create a notification for subscribed users if status is a reply"
|
|||
blocker = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(blocker, user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{blocker.nickname}!"})
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{blocker.nickname}!"})
|
||||
|
||||
blocker_id = blocker.id
|
||||
assert [%Notification{user_id: ^blocker_id}] = Repo.all(Notification)
|
||||
|
@ -113,7 +113,7 @@ test "does not create a notification for subscribed users if status is a reply"
|
|||
muter = insert(:user)
|
||||
{:ok, _user_relationships} = User.mute(muter, user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{"status" => "hey @#{muter.nickname}!"})
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "hey @#{muter.nickname}!"})
|
||||
|
||||
muter_id = muter.id
|
||||
assert [%Notification{user_id: ^muter_id}] = Repo.all(Notification)
|
||||
|
@ -127,14 +127,14 @@ test "does not create a notification for subscribed users if status is a reply"
|
|||
user = insert(:user)
|
||||
thread_muter = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{thread_muter.nickname}!"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{thread_muter.nickname}!"})
|
||||
|
||||
{:ok, _} = CommonAPI.add_mute(thread_muter, activity)
|
||||
|
||||
{:ok, _same_context_activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey-hey-hey @#{thread_muter.nickname}!",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "hey-hey-hey @#{thread_muter.nickname}!",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
[pre_mute_notification, post_mute_notification] =
|
||||
|
@ -170,13 +170,13 @@ test "it creates a notification for user and send to the 'user' and the 'user:no
|
|||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
Streamer.add_socket("user", user)
|
||||
Streamer.get_topic_and_add_socket("user", user)
|
||||
assert_receive {:render_with_user, _, _, _}, 4_000
|
||||
end)
|
||||
|
||||
task_user_notification =
|
||||
Task.async(fn ->
|
||||
Streamer.add_socket("user:notification", user)
|
||||
Streamer.get_topic_and_add_socket("user:notification", user)
|
||||
assert_receive {:render_with_user, _, _, _}, 4_000
|
||||
end)
|
||||
|
||||
|
@ -202,7 +202,7 @@ test "it creates a notification for the user if the user mutes the activity auth
|
|||
muted = insert(:user)
|
||||
{:ok, _} = User.mute(muter, muted)
|
||||
muter = Repo.get(User, muter.id)
|
||||
{:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
|
||||
|
||||
assert Notification.create_notification(activity, muter)
|
||||
end
|
||||
|
@ -213,7 +213,7 @@ test "notification created if user is muted without notifications" do
|
|||
|
||||
{:ok, _user_relationships} = User.mute(muter, muted, false)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(muted, %{"status" => "Hi @#{muter.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
|
||||
|
||||
assert Notification.create_notification(activity, muter)
|
||||
end
|
||||
|
@ -221,13 +221,13 @@ test "notification created if user is muted without notifications" do
|
|||
test "it creates a notification for an activity from a muted thread" do
|
||||
muter = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(muter, %{"status" => "hey"})
|
||||
{:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
|
||||
CommonAPI.add_mute(muter, activity)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
"status" => "Hi @#{muter.nickname}",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "Hi @#{muter.nickname}",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
assert Notification.create_notification(activity, muter)
|
||||
|
@ -240,7 +240,7 @@ test "it disables notifications from followers" do
|
|||
insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
|
||||
|
||||
User.follow(follower, followed)
|
||||
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
|
||||
refute Notification.create_notification(activity, followed)
|
||||
end
|
||||
|
||||
|
@ -252,7 +252,7 @@ test "it disables notifications from non-followers" do
|
|||
notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
|
||||
)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
|
||||
refute Notification.create_notification(activity, followed)
|
||||
end
|
||||
|
||||
|
@ -263,7 +263,7 @@ test "it disables notifications from people the user follows" do
|
|||
followed = insert(:user)
|
||||
User.follow(follower, followed)
|
||||
follower = Repo.get(User, follower.id)
|
||||
{:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
|
||||
refute Notification.create_notification(activity, follower)
|
||||
end
|
||||
|
||||
|
@ -272,7 +272,7 @@ test "it disables notifications from people the user does not follow" do
|
|||
insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
|
||||
|
||||
followed = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(followed, %{status: "hey @#{follower.nickname}"})
|
||||
refute Notification.create_notification(activity, follower)
|
||||
end
|
||||
|
||||
|
@ -289,7 +289,7 @@ test "it doesn't create duplicate notifications for follow+subscribed users" do
|
|||
|
||||
{:ok, _, _, _} = CommonAPI.follow(subscriber, user)
|
||||
User.subscribe(subscriber, user)
|
||||
{:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"})
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
|
||||
{:ok, [_notif]} = Notification.create_notifications(status)
|
||||
end
|
||||
|
||||
|
@ -299,7 +299,7 @@ test "it doesn't create subscription notifications if the recipient cannot see t
|
|||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} = CommonAPI.post(user, %{"status" => "inwisible", "visibility" => "direct"})
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "inwisible", visibility: "direct"})
|
||||
|
||||
assert {:ok, []} == Notification.create_notifications(status)
|
||||
end
|
||||
|
@ -370,7 +370,7 @@ test "it gets a notification that belongs to the user" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
{:ok, notification} = Notification.get(other_user, notification.id)
|
||||
|
@ -382,7 +382,7 @@ test "it returns error if the notification doesn't belong to the user" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
{:error, _notification} = Notification.get(user, notification.id)
|
||||
|
@ -394,7 +394,7 @@ test "it dismisses a notification that belongs to the user" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
{:ok, notification} = Notification.dismiss(other_user, notification.id)
|
||||
|
@ -406,7 +406,7 @@ test "it returns error if the notification doesn't belong to the user" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}"})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
{:error, _notification} = Notification.dismiss(user, notification.id)
|
||||
|
@ -421,14 +421,14 @@ test "it clears all notifications belonging to the user" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname} and @#{third_user.nickname} !"
|
||||
status: "hey @#{other_user.nickname} and @#{third_user.nickname} !"
|
||||
})
|
||||
|
||||
{:ok, _notifs} = Notification.create_notifications(activity)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
|
||||
status: "hey again @#{other_user.nickname} and @#{third_user.nickname} !"
|
||||
})
|
||||
|
||||
{:ok, _notifs} = Notification.create_notifications(activity)
|
||||
|
@ -446,12 +446,12 @@ test "it sets all notifications as read up to a specified notification ID" do
|
|||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname}!"
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey again @#{other_user.nickname}!"
|
||||
status: "hey again @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
[n2, n1] = notifs = Notification.for_user(other_user)
|
||||
|
@ -461,7 +461,7 @@ test "it sets all notifications as read up to a specified notification ID" do
|
|||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey yet again @#{other_user.nickname}!"
|
||||
status: "hey yet again @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
Notification.set_read_up_to(other_user, n2.id)
|
||||
|
@ -500,7 +500,7 @@ test "Returns recent notifications" do
|
|||
Enum.each(0..10, fn i ->
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user1, %{
|
||||
"status" => "hey ##{i} @#{user2.nickname}!"
|
||||
status: "hey ##{i} @#{user2.nickname}!"
|
||||
})
|
||||
end)
|
||||
|
||||
|
@ -536,7 +536,7 @@ test "it sends notifications to addressed users in new messages" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname}!"
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||
|
@ -605,7 +605,7 @@ test "it does not send notification to mentioned users in likes" do
|
|||
|
||||
{:ok, activity_one} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname}!"
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
|
||||
|
@ -623,7 +623,7 @@ test "it only notifies the post's author in likes" do
|
|||
|
||||
{:ok, activity_one} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname}!"
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, like_data, _} = Builder.like(third_user, activity_one.object)
|
||||
|
@ -645,7 +645,7 @@ test "it does not send notification to mentioned users in announces" do
|
|||
|
||||
{:ok, activity_one} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{other_user.nickname}!"
|
||||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, activity_two, _} = CommonAPI.repeat(activity_one.id, third_user)
|
||||
|
@ -661,7 +661,7 @@ test "it returns blocking recipient in disabled recipients list" do
|
|||
other_user = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(other_user, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
|
||||
|
||||
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||
|
||||
|
@ -674,7 +674,7 @@ test "it returns notification-muting recipient in disabled recipients list" do
|
|||
other_user = insert(:user)
|
||||
{:ok, _user_relationships} = User.mute(other_user, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
|
||||
|
||||
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||
|
||||
|
@ -686,14 +686,14 @@ test "it returns thread-muting recipient in disabled recipients list" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
|
||||
|
||||
{:ok, _} = CommonAPI.add_mute(other_user, activity)
|
||||
|
||||
{:ok, same_context_activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey-hey-hey @#{other_user.nickname}!",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "hey-hey-hey @#{other_user.nickname}!",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
{enabled_receivers, disabled_receivers} =
|
||||
|
@ -710,7 +710,7 @@ test "it returns non-following domain-blocking recipient in disabled recipients
|
|||
|
||||
{:ok, other_user} = User.block_domain(other_user, blocked_domain)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
|
||||
|
||||
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||
|
||||
|
@ -726,7 +726,7 @@ test "it returns following domain-blocking recipient in enabled recipients list"
|
|||
{:ok, other_user} = User.block_domain(other_user, blocked_domain)
|
||||
{:ok, other_user} = User.follow(other_user, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
|
||||
|
||||
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
|
||||
|
||||
|
@ -740,7 +740,7 @@ test "liking an activity results in 1 notification, then 0 if the activity is de
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
|
@ -757,7 +757,7 @@ test "liking an activity results in 1 notification, then 0 if the activity is un
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
|
@ -774,7 +774,7 @@ test "repeating an activity results in 1 notification, then 0 if the activity is
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
|
@ -791,7 +791,7 @@ test "repeating an activity results in 1 notification, then 0 if the activity is
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
|
@ -808,7 +808,7 @@ test "liking an activity which is already deleted does not generate a notificati
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
|
@ -825,7 +825,7 @@ test "repeating an activity which is already deleted does not generate a notific
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
|
@ -842,13 +842,13 @@ test "replying to a deleted post without tagging does not generate a notificatio
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
{:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
|
||||
|
||||
{:ok, _reply_activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
"status" => "test reply",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
status: "test reply",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
@ -859,7 +859,7 @@ test "notifications are deleted if a local user is deleted" do
|
|||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}", "visibility" => "direct"})
|
||||
CommonAPI.post(user, %{status: "hi @#{other_user.nickname}", visibility: "direct"})
|
||||
|
||||
refute Enum.empty?(Notification.for_user(other_user))
|
||||
|
||||
|
@ -970,7 +970,7 @@ test "it returns notifications for muted user without notifications" do
|
|||
muted = insert(:user)
|
||||
{:ok, _user_relationships} = User.mute(user, muted, false)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert length(Notification.for_user(user)) == 1
|
||||
end
|
||||
|
@ -980,7 +980,7 @@ test "it doesn't return notifications for muted user with notifications" do
|
|||
muted = insert(:user)
|
||||
{:ok, _user_relationships} = User.mute(user, muted)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert Notification.for_user(user) == []
|
||||
end
|
||||
|
@ -990,7 +990,7 @@ test "it doesn't return notifications for blocked user" do
|
|||
blocked = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(user, blocked)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert Notification.for_user(user) == []
|
||||
end
|
||||
|
@ -1000,7 +1000,7 @@ test "it doesn't return notifications for domain-blocked non-followed user" do
|
|||
blocked = insert(:user, ap_id: "http://some-domain.com")
|
||||
{:ok, user} = User.block_domain(user, "some-domain.com")
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert Notification.for_user(user) == []
|
||||
end
|
||||
|
@ -1012,7 +1012,7 @@ test "it returns notifications for domain-blocked but followed user" do
|
|||
{:ok, user} = User.block_domain(user, "some-domain.com")
|
||||
{:ok, _} = User.follow(user, blocked)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert length(Notification.for_user(user)) == 1
|
||||
end
|
||||
|
@ -1021,7 +1021,7 @@ test "it doesn't return notifications for muted thread" do
|
|||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
{:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
|
||||
assert Notification.for_user(user) == []
|
||||
|
@ -1032,7 +1032,7 @@ test "it returns notifications from a muted user when with_muted is set" do
|
|||
muted = insert(:user)
|
||||
{:ok, _user_relationships} = User.mute(user, muted)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(muted, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(muted, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert length(Notification.for_user(user, %{with_muted: true})) == 1
|
||||
end
|
||||
|
@ -1042,7 +1042,7 @@ test "it doesn't return notifications from a blocked user when with_muted is set
|
|||
blocked = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(user, blocked)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
|
||||
end
|
||||
|
@ -1053,7 +1053,7 @@ test "when with_muted is set, " <>
|
|||
blocked = insert(:user, ap_id: "http://some-domain.com")
|
||||
{:ok, user} = User.block_domain(user, "some-domain.com")
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
|
||||
end
|
||||
|
@ -1062,7 +1062,7 @@ test "it returns notifications from muted threads when with_muted is set" do
|
|||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{"status" => "hey @#{user.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(another_user, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
{:ok, _} = Pleroma.ThreadMute.add_mute(user.id, activity.data["context"])
|
||||
assert length(Notification.for_user(user, %{with_muted: true})) == 1
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
|
|||
user = %User{
|
||||
id: 1,
|
||||
name: "dude",
|
||||
password_hash: Comeonin.Pbkdf2.hashpwsalt("guy")
|
||||
password_hash: Pbkdf2.hash_pwd_salt("guy")
|
||||
}
|
||||
|
||||
conn =
|
||||
|
@ -79,6 +79,13 @@ test "check sha512-crypt hash" do
|
|||
assert AuthenticationPlug.checkpw("password", hash)
|
||||
end
|
||||
|
||||
test "check bcrypt hash" do
|
||||
hash = "$2a$10$uyhC/R/zoE1ndwwCtMusK.TLVzkQ/Ugsbqp3uXI.CTTz0gBw.24jS"
|
||||
|
||||
assert AuthenticationPlug.checkpw("password", hash)
|
||||
refute AuthenticationPlug.checkpw("password1", hash)
|
||||
end
|
||||
|
||||
test "it returns false when hash invalid" do
|
||||
hash =
|
||||
"psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
||||
|
|
|
@ -22,26 +22,26 @@ test "on new status" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
|
||||
CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
|
||||
Enum.each(0..1, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
"visibility" => "unlisted",
|
||||
"status" => "hey"
|
||||
visibility: "unlisted",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..2, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
"visibility" => "direct",
|
||||
"status" => "hey @#{other_user.nickname}"
|
||||
visibility: "direct",
|
||||
status: "hey @#{other_user.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..3, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
"visibility" => "private",
|
||||
"status" => "hey"
|
||||
visibility: "private",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
|
@ -51,7 +51,7 @@ test "on new status" do
|
|||
|
||||
test "on status delete" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
assert %{public: 1} = Pleroma.Stats.get_status_visibility_count()
|
||||
CommonAPI.delete(activity.id, user)
|
||||
assert %{public: 0} = Pleroma.Stats.get_status_visibility_count()
|
||||
|
@ -59,16 +59,16 @@ test "on status delete" do
|
|||
|
||||
test "on status visibility update" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
assert %{public: 1, private: 0} = Pleroma.Stats.get_status_visibility_count()
|
||||
{:ok, _} = CommonAPI.update_activity_scope(activity.id, %{"visibility" => "private"})
|
||||
{:ok, _} = CommonAPI.update_activity_scope(activity.id, %{visibility: "private"})
|
||||
assert %{public: 0, private: 1} = Pleroma.Stats.get_status_visibility_count()
|
||||
end
|
||||
|
||||
test "doesn't count unrelated activities" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
_ = CommonAPI.follow(user, other_user)
|
||||
CommonAPI.favorite(other_user, activity.id)
|
||||
CommonAPI.repeat(activity.id, other_user)
|
||||
|
|
|
@ -7,7 +7,7 @@ def build(data \\ %{}) do
|
|||
email: "test@example.org",
|
||||
name: "Test Name",
|
||||
nickname: "testname",
|
||||
password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
|
||||
password_hash: Pbkdf2.hash_pwd_salt("test"),
|
||||
bio: "A tester.",
|
||||
ap_id: "some id",
|
||||
last_digest_emailed_at: NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
|
||||
|
|
|
@ -29,7 +29,7 @@ def user_factory do
|
|||
name: sequence(:name, &"Test テスト User #{&1}"),
|
||||
email: sequence(:email, &"user#{&1}@example.com"),
|
||||
nickname: sequence(:nickname, &"nick#{&1}"),
|
||||
password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
|
||||
password_hash: Pbkdf2.hash_pwd_salt("test"),
|
||||
bio: sequence(:bio, &"Tester Number #{&1}"),
|
||||
last_digest_emailed_at: NaiveDateTime.utc_now(),
|
||||
last_refreshed_at: NaiveDateTime.utc_now(),
|
||||
|
|
|
@ -13,11 +13,11 @@ defmodule Mix.Tasks.Pleroma.CountStatusesTest do
|
|||
|
||||
test "counts statuses" do
|
||||
user = insert(:user)
|
||||
{:ok, _} = CommonAPI.post(user, %{"status" => "test"})
|
||||
{:ok, _} = CommonAPI.post(user, %{"status" => "test2"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "test2"})
|
||||
|
||||
user2 = insert(:user)
|
||||
{:ok, _} = CommonAPI.post(user2, %{"status" => "test3"})
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "test3"})
|
||||
|
||||
user = refresh_record(user)
|
||||
user2 = refresh_record(user2)
|
||||
|
|
|
@ -26,7 +26,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
describe "running remove_embedded_objects" do
|
||||
test "it replaces objects with references" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
new_data = Map.put(activity.data, "object", activity.object.data)
|
||||
|
||||
{:ok, activity} =
|
||||
|
@ -99,8 +99,8 @@ test "following and followers count are updated" do
|
|||
test "it turns OrderedCollection likes into empty arrays" do
|
||||
[user, user2] = insert_pair(:user)
|
||||
|
||||
{:ok, %{id: id, object: object}} = CommonAPI.post(user, %{"status" => "test"})
|
||||
{:ok, %{object: object2}} = CommonAPI.post(user, %{"status" => "test test"})
|
||||
{:ok, %{id: id, object: object}} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, %{object: object2}} = CommonAPI.post(user, %{status: "test test"})
|
||||
|
||||
CommonAPI.favorite(user2, id)
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ test "Sends digest to the given user" do
|
|||
Enum.each(0..10, fn i ->
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user1, %{
|
||||
"status" => "hey ##{i} @#{user2.nickname}!"
|
||||
status: "hey ##{i} @#{user2.nickname}!"
|
||||
})
|
||||
end)
|
||||
|
||||
|
|
|
@ -12,26 +12,26 @@ test "counts statuses" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
|
||||
CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
|
||||
Enum.each(0..1, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
"visibility" => "unlisted",
|
||||
"status" => "hey"
|
||||
visibility: "unlisted",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..2, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
"visibility" => "direct",
|
||||
"status" => "hey @#{other_user.nickname}"
|
||||
visibility: "direct",
|
||||
status: "hey @#{other_user.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..3, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
"visibility" => "private",
|
||||
"status" => "hey"
|
||||
visibility: "private",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.UserTest do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
|
@ -103,6 +106,28 @@ test "user is deleted" do
|
|||
end
|
||||
end
|
||||
|
||||
test "a remote user's create activity is deleted when the object has been pruned" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "uguu"})
|
||||
object = Object.normalize(post)
|
||||
Object.prune(object)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert_received {:mix_shell, :info, [message]}
|
||||
assert message =~ " deleted"
|
||||
assert %{deactivated: true} = User.get_by_nickname(user.nickname)
|
||||
|
||||
assert called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
|
||||
refute Activity.get_by_id(post.id)
|
||||
end
|
||||
|
||||
test "no user to delete" do
|
||||
Mix.Tasks.Pleroma.User.run(["rm", "nonexistent"])
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ test "it returns path with bucket namespace when namespace is set" do
|
|||
name: "image-tet.jpg",
|
||||
content_type: "image/jpg",
|
||||
path: "test_folder/image-tet.jpg",
|
||||
tempfile: Path.absname("test/fixtures/image_tmp.jpg")
|
||||
tempfile: Path.absname("test/instance_static/add/shortcode.png")
|
||||
}
|
||||
|
||||
[file_upload: file_upload]
|
||||
|
|
|
@ -990,7 +990,7 @@ test "works for announces" do
|
|||
actor = insert(:user)
|
||||
user = insert(:user, local: true)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(actor, %{"status" => "hello"})
|
||||
{:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
|
||||
{:ok, announce, _} = CommonAPI.repeat(activity.id, user)
|
||||
|
||||
recipients = User.get_recipients_from_activity(announce)
|
||||
|
@ -1007,7 +1007,7 @@ test "get recipients" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(actor, %{
|
||||
"status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
|
||||
status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
|
||||
})
|
||||
|
||||
assert Enum.map([actor, addressed], & &1.ap_id) --
|
||||
|
@ -1029,7 +1029,7 @@ test "has following" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(actor, %{
|
||||
"status" => "hey @#{addressed.nickname}"
|
||||
status: "hey @#{addressed.nickname}"
|
||||
})
|
||||
|
||||
assert Enum.map([actor, addressed], & &1.ap_id) --
|
||||
|
@ -1090,7 +1090,7 @@ test "hide a user's statuses from timelines and notifications" do
|
|||
|
||||
{:ok, user2} = User.follow(user2, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
|
||||
|
||||
activity = Repo.preload(activity, :bookmark)
|
||||
|
||||
|
@ -1126,7 +1126,7 @@ test "hide a user's statuses from timelines and notifications" do
|
|||
setup do: clear_config([:instance, :federating])
|
||||
|
||||
test ".delete_user_activities deletes all create activities", %{user: user} do
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
|
||||
|
||||
User.delete_user_activities(user)
|
||||
|
||||
|
@ -1411,7 +1411,7 @@ test "Only includes users who has no recent activity" do
|
|||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "hey @#{to.nickname}"
|
||||
status: "hey @#{to.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
|
@ -1443,12 +1443,12 @@ test "Only includes users with no read notifications" do
|
|||
Enum.each(recipients, fn to ->
|
||||
{:ok, _} =
|
||||
CommonAPI.post(sender, %{
|
||||
"status" => "hey @#{to.nickname}"
|
||||
status: "hey @#{to.nickname}"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(sender, %{
|
||||
"status" => "hey again @#{to.nickname}"
|
||||
status: "hey again @#{to.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
|
|
|
@ -341,7 +341,7 @@ test "it caches a response", %{conn: conn} do
|
|||
|
||||
test "cached purged after activity deletion", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "cofe"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "cofe"})
|
||||
|
||||
uuid = String.split(activity.data["id"], "/") |> List.last()
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
describe "streaming out participations" do
|
||||
test "it streams them out" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
|
||||
{:ok, conversation} = Pleroma.Conversation.create_or_bump_for(activity)
|
||||
|
||||
|
@ -56,8 +56,8 @@ test "streams them out on activity creation" do
|
|||
stream: fn _, _ -> nil end do
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_one, %{
|
||||
"status" => "@#{user_two.nickname}",
|
||||
"visibility" => "direct"
|
||||
status: "@#{user_two.nickname}",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
conversation =
|
||||
|
@ -74,15 +74,13 @@ test "streams them out on activity creation" do
|
|||
test "it restricts by the appropriate visibility" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
|
||||
{:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
|
||||
{:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
{: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"})
|
||||
|
||||
activities =
|
||||
ActivityPub.fetch_activities([], %{:visibility => "direct", "actor_id" => user.ap_id})
|
||||
|
@ -118,15 +116,13 @@ test "it restricts by the appropriate visibility" do
|
|||
test "it excludes by the appropriate visibility" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
|
||||
{:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
|
||||
|
||||
{:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
{: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"})
|
||||
|
||||
activities =
|
||||
ActivityPub.fetch_activities([], %{
|
||||
|
@ -193,9 +189,9 @@ test "it returns a user that is invisible" do
|
|||
test "it fetches the appropriate tag-restricted posts" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, status_one} = CommonAPI.post(user, %{"status" => ". #test"})
|
||||
{:ok, status_two} = CommonAPI.post(user, %{"status" => ". #essais"})
|
||||
{:ok, status_three} = CommonAPI.post(user, %{"status" => ". #test #reject"})
|
||||
{:ok, status_one} = CommonAPI.post(user, %{status: ". #test"})
|
||||
{:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"})
|
||||
{:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"})
|
||||
|
||||
fetch_one = ActivityPub.fetch_activities([], %{"type" => "Create", "tag" => "test"})
|
||||
|
||||
|
@ -432,26 +428,26 @@ test "increases user note count only for public activities" do
|
|||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "1",
|
||||
"visibility" => "public"
|
||||
status: "1",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "2",
|
||||
"visibility" => "unlisted"
|
||||
status: "2",
|
||||
visibility: "unlisted"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "2",
|
||||
"visibility" => "private"
|
||||
status: "2",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, _} =
|
||||
CommonAPI.post(User.get_cached_by_id(user.id), %{
|
||||
"status" => "3",
|
||||
"visibility" => "direct"
|
||||
status: "3",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
@ -462,27 +458,27 @@ test "increases replies count" do
|
|||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "1", "visibility" => "public"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
|
||||
ap_id = activity.data["id"]
|
||||
reply_data = %{"status" => "1", "in_reply_to_status_id" => activity.id}
|
||||
reply_data = %{status: "1", in_reply_to_status_id: activity.id}
|
||||
|
||||
# public
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "public"))
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "public"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 1
|
||||
|
||||
# unlisted
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "unlisted"))
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "unlisted"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
# private
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "private"))
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "private"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 2
|
||||
|
||||
# direct
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, "visibility", "direct"))
|
||||
{:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "direct"))
|
||||
assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id)
|
||||
assert object.data["repliesCount"] == 2
|
||||
end
|
||||
|
@ -569,13 +565,13 @@ test "doesn't return transitive interactions concerning blocked users" do
|
|||
|
||||
{:ok, _user_relationship} = User.block(blocker, blockee)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
|
||||
{:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
|
||||
|
||||
{:ok, activity_two} = CommonAPI.post(friend, %{"status" => "hey! @#{blockee.nickname}"})
|
||||
{:ok, activity_two} = CommonAPI.post(friend, %{status: "hey! @#{blockee.nickname}"})
|
||||
|
||||
{:ok, activity_three} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
|
||||
{:ok, activity_three} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
|
||||
|
||||
{:ok, activity_four} = CommonAPI.post(blockee, %{"status" => "hey! @#{blocker.nickname}"})
|
||||
{:ok, activity_four} = CommonAPI.post(blockee, %{status: "hey! @#{blocker.nickname}"})
|
||||
|
||||
activities = ActivityPub.fetch_activities([], %{"blocking_user" => blocker})
|
||||
|
||||
|
@ -592,9 +588,9 @@ test "doesn't return announce activities concerning blocked users" do
|
|||
|
||||
{:ok, _user_relationship} = User.block(blocker, blockee)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(friend, %{"status" => "hey!"})
|
||||
{:ok, activity_one} = CommonAPI.post(friend, %{status: "hey!"})
|
||||
|
||||
{:ok, activity_two} = CommonAPI.post(blockee, %{"status" => "hey! @#{friend.nickname}"})
|
||||
{:ok, activity_two} = CommonAPI.post(blockee, %{status: "hey! @#{friend.nickname}"})
|
||||
|
||||
{:ok, activity_three, _} = CommonAPI.repeat(activity_two.id, friend)
|
||||
|
||||
|
@ -774,10 +770,9 @@ test "excludes reblogs on request" do
|
|||
test "doesn't retrieve unlisted activities" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, _unlisted_activity} =
|
||||
CommonAPI.post(user, %{"status" => "yeah", "visibility" => "unlisted"})
|
||||
{:ok, _unlisted_activity} = CommonAPI.post(user, %{status: "yeah", visibility: "unlisted"})
|
||||
|
||||
{:ok, listed_activity} = CommonAPI.post(user, %{"status" => "yeah"})
|
||||
{:ok, listed_activity} = CommonAPI.post(user, %{status: "yeah"})
|
||||
|
||||
[activity] = ActivityPub.fetch_public_activities()
|
||||
|
||||
|
@ -912,7 +907,7 @@ test "reverts annouce from object on error" do
|
|||
describe "announcing a private object" do
|
||||
test "adds an announce activity to the db if the audience is not widened" do
|
||||
user = insert(:user)
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
{:ok, announce_activity, object} = ActivityPub.announce(user, object, nil, true, false)
|
||||
|
@ -926,7 +921,7 @@ test "adds an announce activity to the db if the audience is not widened" do
|
|||
|
||||
test "does not add an announce activity to the db if the audience is widened" do
|
||||
user = insert(:user)
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
assert {:error, _} = ActivityPub.announce(user, object, nil, true, true)
|
||||
|
@ -935,7 +930,7 @@ test "does not add an announce activity to the db if the audience is widened" do
|
|||
test "does not add an announce activity to the db if the announcer is not the author" do
|
||||
user = insert(:user)
|
||||
announcer = insert(:user)
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
|
||||
{:ok, note_activity} = CommonAPI.post(user, %{status: ".", visibility: "private"})
|
||||
object = Object.normalize(note_activity)
|
||||
|
||||
assert {:error, _} = ActivityPub.announce(announcer, object, nil, true, false)
|
||||
|
@ -956,7 +951,7 @@ test "copies the file to the configured folder" do
|
|||
|
||||
test "works with base64 encoded images" do
|
||||
file = %{
|
||||
"img" => data_uri()
|
||||
img: data_uri()
|
||||
}
|
||||
|
||||
{:ok, %Object{}} = ActivityPub.upload(file)
|
||||
|
@ -1061,14 +1056,38 @@ test "reverts block activity on error" do
|
|||
end
|
||||
|
||||
test "creates a block activity" do
|
||||
clear_config([:instance, :federating], true)
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
|
||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
||||
|
||||
assert activity.data["type"] == "Block"
|
||||
assert activity.data["actor"] == blocker.ap_id
|
||||
assert activity.data["object"] == blocked.ap_id
|
||||
assert activity.data["type"] == "Block"
|
||||
assert activity.data["actor"] == blocker.ap_id
|
||||
assert activity.data["object"] == blocked.ap_id
|
||||
|
||||
assert called(Pleroma.Web.Federator.publish(activity))
|
||||
end
|
||||
end
|
||||
|
||||
test "works with outgoing blocks disabled, but doesn't federate" do
|
||||
clear_config([:instance, :federating], true)
|
||||
clear_config([:activitypub, :outgoing_blocks], false)
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
{:ok, activity} = ActivityPub.block(blocker, blocked)
|
||||
|
||||
assert activity.data["type"] == "Block"
|
||||
assert activity.data["actor"] == blocker.ap_id
|
||||
assert activity.data["object"] == blocked.ap_id
|
||||
|
||||
refute called(Pleroma.Web.Federator.publish(:_))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1087,23 +1106,22 @@ test "it filters broken threads" do
|
|||
{:ok, user3} = User.follow(user3, user2)
|
||||
assert User.following?(user3, user2)
|
||||
|
||||
{:ok, public_activity} = CommonAPI.post(user3, %{"status" => "hi 1"})
|
||||
{:ok, public_activity} = CommonAPI.post(user3, %{status: "hi 1"})
|
||||
|
||||
{:ok, private_activity_1} =
|
||||
CommonAPI.post(user3, %{"status" => "hi 2", "visibility" => "private"})
|
||||
{:ok, private_activity_1} = CommonAPI.post(user3, %{status: "hi 2", visibility: "private"})
|
||||
|
||||
{:ok, private_activity_2} =
|
||||
CommonAPI.post(user2, %{
|
||||
"status" => "hi 3",
|
||||
"visibility" => "private",
|
||||
"in_reply_to_status_id" => private_activity_1.id
|
||||
status: "hi 3",
|
||||
visibility: "private",
|
||||
in_reply_to_status_id: private_activity_1.id
|
||||
})
|
||||
|
||||
{:ok, private_activity_3} =
|
||||
CommonAPI.post(user3, %{
|
||||
"status" => "hi 4",
|
||||
"visibility" => "private",
|
||||
"in_reply_to_status_id" => private_activity_2.id
|
||||
status: "hi 4",
|
||||
visibility: "private",
|
||||
in_reply_to_status_id: private_activity_2.id
|
||||
})
|
||||
|
||||
activities =
|
||||
|
@ -1153,9 +1171,9 @@ test "returned pinned statuses" do
|
|||
Config.put([:instance, :max_pinned_statuses], 3)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{"status" => "HI!!!"})
|
||||
{:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
|
||||
{:ok, activity_three} = CommonAPI.post(user, %{"status" => "HI!!!"})
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{status: "HI!!!"})
|
||||
{:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"})
|
||||
{:ok, activity_three} = CommonAPI.post(user, %{status: "HI!!!"})
|
||||
|
||||
CommonAPI.pin(activity_one.id, user)
|
||||
user = refresh_record(user)
|
||||
|
@ -1176,7 +1194,7 @@ test "returned pinned statuses" do
|
|||
reporter = insert(:user)
|
||||
target_account = insert(:user)
|
||||
content = "foobar"
|
||||
{:ok, activity} = CommonAPI.post(target_account, %{"status" => content})
|
||||
{:ok, activity} = CommonAPI.post(target_account, %{status: content})
|
||||
context = Utils.generate_context_id()
|
||||
|
||||
reporter_ap_id = reporter.ap_id
|
||||
|
@ -1272,8 +1290,7 @@ test "fetch_activities/2 returns activities addressed to a list " do
|
|||
{:ok, list} = Pleroma.List.create("foo", user)
|
||||
{:ok, list} = Pleroma.List.follow(list, member)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
|
||||
|
||||
activity = Repo.preload(activity, :bookmark)
|
||||
activity = %Activity{activity | thread_muted?: !!activity.thread_muted?}
|
||||
|
@ -1291,8 +1308,8 @@ test "fetches private posts for followed users" do
|
|||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "thought I looked cute might delete later :3",
|
||||
"visibility" => "private"
|
||||
status: "thought I looked cute might delete later :3",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
[result] = ActivityPub.fetch_activities_bounded([user.follower_address], [])
|
||||
|
@ -1301,12 +1318,12 @@ test "fetches private posts for followed users" do
|
|||
|
||||
test "fetches only public posts for other users" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe", "visibility" => "public"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe", visibility: "public"})
|
||||
|
||||
{:ok, _private_activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "why is tenshi eating a corndog so cute?",
|
||||
"visibility" => "private"
|
||||
status: "why is tenshi eating a corndog so cute?",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
[result] = ActivityPub.fetch_activities_bounded([], [user.follower_address])
|
||||
|
@ -1434,11 +1451,11 @@ test "returns a favourite activities sorted by adds to favorite" do
|
|||
other_user = insert(:user)
|
||||
user1 = insert(:user)
|
||||
user2 = insert(:user)
|
||||
{:ok, a1} = CommonAPI.post(user1, %{"status" => "bla"})
|
||||
{:ok, _a2} = CommonAPI.post(user2, %{"status" => "traps are happy"})
|
||||
{:ok, a3} = CommonAPI.post(user2, %{"status" => "Trees Are "})
|
||||
{:ok, a4} = CommonAPI.post(user2, %{"status" => "Agent Smith "})
|
||||
{:ok, a5} = CommonAPI.post(user1, %{"status" => "Red or Blue "})
|
||||
{:ok, a1} = CommonAPI.post(user1, %{status: "bla"})
|
||||
{:ok, _a2} = CommonAPI.post(user2, %{status: "traps are happy"})
|
||||
{:ok, a3} = CommonAPI.post(user2, %{status: "Trees Are "})
|
||||
{:ok, a4} = CommonAPI.post(user2, %{status: "Agent Smith "})
|
||||
{:ok, a5} = CommonAPI.post(user1, %{status: "Red or Blue "})
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(user, a4.id)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, a3.id)
|
||||
|
@ -1518,10 +1535,9 @@ test "old user must be in the new user's `also_known_as` list" do
|
|||
test "doesn't retrieve replies activities with exclude_replies" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
|
||||
|
||||
{:ok, _reply} =
|
||||
CommonAPI.post(user, %{"status" => "yeah", "in_reply_to_status_id" => activity.id})
|
||||
{:ok, _reply} = CommonAPI.post(user, %{status: "yeah", in_reply_to_status_id: activity.id})
|
||||
|
||||
[result] = ActivityPub.fetch_public_activities(%{"exclude_replies" => "true"})
|
||||
|
||||
|
@ -1834,84 +1850,84 @@ defp public_messages(_) do
|
|||
{:ok, u2} = User.follow(u2, u3)
|
||||
{:ok, u3} = User.follow(u3, u2)
|
||||
|
||||
{:ok, a1} = CommonAPI.post(u1, %{"status" => "Status"})
|
||||
{:ok, a1} = CommonAPI.post(u1, %{status: "Status"})
|
||||
|
||||
{:ok, r1_1} =
|
||||
CommonAPI.post(u2, %{
|
||||
"status" => "@#{u1.nickname} reply from u2 to u1",
|
||||
"in_reply_to_status_id" => a1.id
|
||||
status: "@#{u1.nickname} reply from u2 to u1",
|
||||
in_reply_to_status_id: a1.id
|
||||
})
|
||||
|
||||
{:ok, r1_2} =
|
||||
CommonAPI.post(u3, %{
|
||||
"status" => "@#{u1.nickname} reply from u3 to u1",
|
||||
"in_reply_to_status_id" => a1.id
|
||||
status: "@#{u1.nickname} reply from u3 to u1",
|
||||
in_reply_to_status_id: a1.id
|
||||
})
|
||||
|
||||
{:ok, r1_3} =
|
||||
CommonAPI.post(u4, %{
|
||||
"status" => "@#{u1.nickname} reply from u4 to u1",
|
||||
"in_reply_to_status_id" => a1.id
|
||||
status: "@#{u1.nickname} reply from u4 to u1",
|
||||
in_reply_to_status_id: a1.id
|
||||
})
|
||||
|
||||
{:ok, a2} = CommonAPI.post(u2, %{"status" => "Status"})
|
||||
{:ok, a2} = CommonAPI.post(u2, %{status: "Status"})
|
||||
|
||||
{:ok, r2_1} =
|
||||
CommonAPI.post(u1, %{
|
||||
"status" => "@#{u2.nickname} reply from u1 to u2",
|
||||
"in_reply_to_status_id" => a2.id
|
||||
status: "@#{u2.nickname} reply from u1 to u2",
|
||||
in_reply_to_status_id: a2.id
|
||||
})
|
||||
|
||||
{:ok, r2_2} =
|
||||
CommonAPI.post(u3, %{
|
||||
"status" => "@#{u2.nickname} reply from u3 to u2",
|
||||
"in_reply_to_status_id" => a2.id
|
||||
status: "@#{u2.nickname} reply from u3 to u2",
|
||||
in_reply_to_status_id: a2.id
|
||||
})
|
||||
|
||||
{:ok, r2_3} =
|
||||
CommonAPI.post(u4, %{
|
||||
"status" => "@#{u2.nickname} reply from u4 to u2",
|
||||
"in_reply_to_status_id" => a2.id
|
||||
status: "@#{u2.nickname} reply from u4 to u2",
|
||||
in_reply_to_status_id: a2.id
|
||||
})
|
||||
|
||||
{:ok, a3} = CommonAPI.post(u3, %{"status" => "Status"})
|
||||
{:ok, a3} = CommonAPI.post(u3, %{status: "Status"})
|
||||
|
||||
{:ok, r3_1} =
|
||||
CommonAPI.post(u1, %{
|
||||
"status" => "@#{u3.nickname} reply from u1 to u3",
|
||||
"in_reply_to_status_id" => a3.id
|
||||
status: "@#{u3.nickname} reply from u1 to u3",
|
||||
in_reply_to_status_id: a3.id
|
||||
})
|
||||
|
||||
{:ok, r3_2} =
|
||||
CommonAPI.post(u2, %{
|
||||
"status" => "@#{u3.nickname} reply from u2 to u3",
|
||||
"in_reply_to_status_id" => a3.id
|
||||
status: "@#{u3.nickname} reply from u2 to u3",
|
||||
in_reply_to_status_id: a3.id
|
||||
})
|
||||
|
||||
{:ok, r3_3} =
|
||||
CommonAPI.post(u4, %{
|
||||
"status" => "@#{u3.nickname} reply from u4 to u3",
|
||||
"in_reply_to_status_id" => a3.id
|
||||
status: "@#{u3.nickname} reply from u4 to u3",
|
||||
in_reply_to_status_id: a3.id
|
||||
})
|
||||
|
||||
{:ok, a4} = CommonAPI.post(u4, %{"status" => "Status"})
|
||||
{:ok, a4} = CommonAPI.post(u4, %{status: "Status"})
|
||||
|
||||
{:ok, r4_1} =
|
||||
CommonAPI.post(u1, %{
|
||||
"status" => "@#{u4.nickname} reply from u1 to u4",
|
||||
"in_reply_to_status_id" => a4.id
|
||||
status: "@#{u4.nickname} reply from u1 to u4",
|
||||
in_reply_to_status_id: a4.id
|
||||
})
|
||||
|
||||
{:ok, r4_2} =
|
||||
CommonAPI.post(u2, %{
|
||||
"status" => "@#{u4.nickname} reply from u2 to u4",
|
||||
"in_reply_to_status_id" => a4.id
|
||||
status: "@#{u4.nickname} reply from u2 to u4",
|
||||
in_reply_to_status_id: a4.id
|
||||
})
|
||||
|
||||
{:ok, r4_3} =
|
||||
CommonAPI.post(u3, %{
|
||||
"status" => "@#{u4.nickname} reply from u3 to u4",
|
||||
"in_reply_to_status_id" => a4.id
|
||||
status: "@#{u4.nickname} reply from u3 to u4",
|
||||
in_reply_to_status_id: a4.id
|
||||
})
|
||||
|
||||
{:ok,
|
||||
|
@ -1935,68 +1951,68 @@ defp private_messages(_) do
|
|||
{:ok, u2} = User.follow(u2, u3)
|
||||
{:ok, u3} = User.follow(u3, u2)
|
||||
|
||||
{:ok, a1} = CommonAPI.post(u1, %{"status" => "Status", "visibility" => "private"})
|
||||
{:ok, a1} = CommonAPI.post(u1, %{status: "Status", visibility: "private"})
|
||||
|
||||
{:ok, r1_1} =
|
||||
CommonAPI.post(u2, %{
|
||||
"status" => "@#{u1.nickname} reply from u2 to u1",
|
||||
"in_reply_to_status_id" => a1.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u1.nickname} reply from u2 to u1",
|
||||
in_reply_to_status_id: a1.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, r1_2} =
|
||||
CommonAPI.post(u3, %{
|
||||
"status" => "@#{u1.nickname} reply from u3 to u1",
|
||||
"in_reply_to_status_id" => a1.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u1.nickname} reply from u3 to u1",
|
||||
in_reply_to_status_id: a1.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, r1_3} =
|
||||
CommonAPI.post(u4, %{
|
||||
"status" => "@#{u1.nickname} reply from u4 to u1",
|
||||
"in_reply_to_status_id" => a1.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u1.nickname} reply from u4 to u1",
|
||||
in_reply_to_status_id: a1.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, a2} = CommonAPI.post(u2, %{"status" => "Status", "visibility" => "private"})
|
||||
{:ok, a2} = CommonAPI.post(u2, %{status: "Status", visibility: "private"})
|
||||
|
||||
{:ok, r2_1} =
|
||||
CommonAPI.post(u1, %{
|
||||
"status" => "@#{u2.nickname} reply from u1 to u2",
|
||||
"in_reply_to_status_id" => a2.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u2.nickname} reply from u1 to u2",
|
||||
in_reply_to_status_id: a2.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, r2_2} =
|
||||
CommonAPI.post(u3, %{
|
||||
"status" => "@#{u2.nickname} reply from u3 to u2",
|
||||
"in_reply_to_status_id" => a2.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u2.nickname} reply from u3 to u2",
|
||||
in_reply_to_status_id: a2.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, a3} = CommonAPI.post(u3, %{"status" => "Status", "visibility" => "private"})
|
||||
{:ok, a3} = CommonAPI.post(u3, %{status: "Status", visibility: "private"})
|
||||
|
||||
{:ok, r3_1} =
|
||||
CommonAPI.post(u1, %{
|
||||
"status" => "@#{u3.nickname} reply from u1 to u3",
|
||||
"in_reply_to_status_id" => a3.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u3.nickname} reply from u1 to u3",
|
||||
in_reply_to_status_id: a3.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, r3_2} =
|
||||
CommonAPI.post(u2, %{
|
||||
"status" => "@#{u3.nickname} reply from u2 to u3",
|
||||
"in_reply_to_status_id" => a3.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u3.nickname} reply from u2 to u3",
|
||||
in_reply_to_status_id: a3.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok, a4} = CommonAPI.post(u4, %{"status" => "Status", "visibility" => "private"})
|
||||
{:ok, a4} = CommonAPI.post(u4, %{status: "Status", visibility: "private"})
|
||||
|
||||
{:ok, r4_1} =
|
||||
CommonAPI.post(u1, %{
|
||||
"status" => "@#{u4.nickname} reply from u1 to u4",
|
||||
"in_reply_to_status_id" => a4.id,
|
||||
"visibility" => "private"
|
||||
status: "@#{u4.nickname} reply from u1 to u4",
|
||||
in_reply_to_status_id: a4.id,
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
{:ok,
|
||||
|
|
|
@ -13,7 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
|
|||
describe "EmojiReacts" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"})
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
|
||||
|
||||
object = Pleroma.Object.get_by_ap_id(post_activity.data["object"])
|
||||
|
||||
|
@ -53,7 +53,7 @@ test "it is not valid with a non-emoji content field", %{valid_emoji_react: vali
|
|||
describe "Undos" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"})
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
|
||||
{:ok, like} = CommonAPI.favorite(user, post_activity.id)
|
||||
{:ok, valid_like_undo, []} = Builder.undo(user, like)
|
||||
|
||||
|
@ -93,7 +93,7 @@ test "it does not validate if the object is missing", %{valid_like_undo: valid_l
|
|||
describe "deletes" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{"status" => "cancel me daddy"})
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"})
|
||||
|
||||
{:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
|
||||
{:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
|
||||
|
@ -185,7 +185,7 @@ test "it's valid if the actor of the object is a local superuser",
|
|||
describe "likes" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"})
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
|
||||
|
||||
valid_like = %{
|
||||
"to" => [user.ap_id],
|
||||
|
|
|
@ -25,17 +25,58 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, op} = CommonAPI.post(other_user, %{"status" => "big oof"})
|
||||
{:ok, post} = CommonAPI.post(user, %{"status" => "hey", "in_reply_to_id" => op})
|
||||
{:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
|
||||
{:ok, favorite} = CommonAPI.favorite(user, post.id)
|
||||
object = Object.normalize(post)
|
||||
{:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
|
||||
{:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
|
||||
{:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
|
||||
{:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
|
||||
%{user: user, delete: delete, post: post, object: object, delete_user: delete_user, op: op}
|
||||
|
||||
%{
|
||||
user: user,
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
delete_user: delete_user,
|
||||
op: op,
|
||||
favorite: favorite
|
||||
}
|
||||
end
|
||||
|
||||
test "it handles object deletions", %{
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
user: user,
|
||||
op: op,
|
||||
favorite: favorite
|
||||
} do
|
||||
with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
|
||||
stream_out: fn _ -> nil end,
|
||||
stream_out_participations: fn _, _ -> nil end do
|
||||
{:ok, delete, _} = SideEffects.handle(delete)
|
||||
user = User.get_cached_by_ap_id(object.data["actor"])
|
||||
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
|
||||
assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
|
||||
end
|
||||
|
||||
object = Object.get_by_id(object.id)
|
||||
assert object.data["type"] == "Tombstone"
|
||||
refute Activity.get_by_id(post.id)
|
||||
refute Activity.get_by_id(favorite.id)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.note_count == 0
|
||||
|
||||
object = Object.normalize(op.data["object"], false)
|
||||
|
||||
assert object.data["repliesCount"] == 0
|
||||
end
|
||||
|
||||
test "it handles object deletions when the object itself has been pruned", %{
|
||||
delete: delete,
|
||||
post: post,
|
||||
object: object,
|
||||
|
@ -77,7 +118,7 @@ test "it handles user deletions", %{delete_user: delete, user: user} do
|
|||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
|
||||
{:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
|
||||
{:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
|
||||
|
@ -103,7 +144,7 @@ test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
|
|||
setup do
|
||||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
{:ok, like} = CommonAPI.favorite(user, post.id)
|
||||
{:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
|
||||
{:ok, announce, _} = CommonAPI.repeat(post.id, user)
|
||||
|
@ -203,7 +244,7 @@ test "deletes the original like", %{like_undo: like_undo, like: like} do
|
|||
setup do
|
||||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
|
||||
{:ok, like_data, _meta} = Builder.like(user, post.object)
|
||||
{:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
|
||||
|
|
|
@ -44,6 +44,34 @@ test "it works for incoming deletes" do
|
|||
assert object.data["type"] == "Tombstone"
|
||||
end
|
||||
|
||||
test "it works for incoming when the object has been pruned" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
{:ok, object} =
|
||||
Object.normalize(activity.data["object"])
|
||||
|> Repo.delete()
|
||||
|
||||
Cachex.del(:object_cache, "object:#{object.data["id"]}")
|
||||
|
||||
deleting_user = insert(:user)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("actor", deleting_user.ap_id)
|
||||
|> put_in(["object", "id"], activity.data["object"])
|
||||
|
||||
{:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert id == data["id"]
|
||||
|
||||
# We delete the Create activity because we base our timelines on it.
|
||||
# This should be changed after we unify objects and activities
|
||||
refute Activity.get_by_id(activity.id)
|
||||
assert actor == deleting_user.ap_id
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
activity = insert(:note_activity)
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
|
||||
|
|
|
@ -15,7 +15,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do
|
|||
test "it works for incoming emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction.json")
|
||||
|
@ -40,7 +40,7 @@ test "it works for incoming emoji reactions" do
|
|||
test "it reject invalid emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction-too-long.json")
|
||||
|
|
|
@ -14,7 +14,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do
|
|||
test "it works for incoming likes" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-like.json")
|
||||
|
@ -36,7 +36,7 @@ test "it works for incoming likes" do
|
|||
test "it works for incoming misskey likes, turning them into EmojiReacts" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/misskey-like.json")
|
||||
|
@ -57,7 +57,7 @@ test "it works for incoming misskey likes, turning them into EmojiReacts" do
|
|||
test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/misskey-like.json")
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue