@@ -28,6 +28,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. | |||
@@ -387,56 +387,47 @@ defmodule Pleroma.LoadTesting.Fetcher do | |||
favourites = ActivityPub.fetch_favourites(user) | |||
output_relationships = | |||
!!Pleroma.Config.get([:extensions, :output_relationships_in_statuses_by_default]) | |||
Benchee.run( | |||
%{ | |||
"Rendering home timeline" => fn -> | |||
StatusView.render("index.json", %{ | |||
activities: home_activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: !output_relationships | |||
as: :activity | |||
}) | |||
end, | |||
"Rendering direct timeline" => fn -> | |||
StatusView.render("index.json", %{ | |||
activities: direct_activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: !output_relationships | |||
as: :activity | |||
}) | |||
end, | |||
"Rendering public timeline" => fn -> | |||
StatusView.render("index.json", %{ | |||
activities: public_activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: !output_relationships | |||
as: :activity | |||
}) | |||
end, | |||
"Rendering tag timeline" => fn -> | |||
StatusView.render("index.json", %{ | |||
activities: tag_activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: !output_relationships | |||
as: :activity | |||
}) | |||
end, | |||
"Rendering notifications" => fn -> | |||
Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{ | |||
notifications: notifications, | |||
for: user, | |||
skip_relationships: !output_relationships | |||
for: user | |||
}) | |||
end, | |||
"Rendering favourites timeline" => fn -> | |||
StatusView.render("index.json", %{ | |||
activities: favourites, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: !output_relationships | |||
as: :activity | |||
}) | |||
end | |||
}, | |||
@@ -251,8 +251,6 @@ config :pleroma, :instance, | |||
] | |||
] | |||
config :pleroma, :extensions, output_relationships_in_statuses_by_default: true | |||
config :pleroma, :feed, | |||
post_title: %{ | |||
max_length: 100, | |||
@@ -680,15 +680,6 @@ config :pleroma, :config_description, [ | |||
] | |||
}, | |||
%{ | |||
key: :federation_publisher_modules, | |||
type: {:list, :module}, | |||
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 | |||
] | |||
}, | |||
%{ | |||
key: :allow_relay, | |||
type: :boolean, | |||
description: "Enable Pleroma's Relay, which makes it possible to follow a whole instance" | |||
@@ -1105,38 +1096,40 @@ config :pleroma, :config_description, [ | |||
description: "Settings for Pleroma FE", | |||
suggestions: [ | |||
%{ | |||
theme: "pleroma-dark", | |||
logo: "/static/logo.png", | |||
background: "/images/city.jpg", | |||
redirectRootNoLogin: "/main/all", | |||
redirectRootLogin: "/main/friends", | |||
showInstanceSpecificPanel: true, | |||
scopeOptionsEnabled: false, | |||
formattingOptionsEnabled: false, | |||
alwaysShowSubjectInput: true, | |||
background: "/static/aurora_borealis.jpg", | |||
collapseMessageWithSubject: false, | |||
disableChat: false, | |||
greentext: false, | |||
hideFilteredStatuses: false, | |||
hideMutedPosts: false, | |||
hidePostStats: false, | |||
hideSitename: false, | |||
hideUserStats: false, | |||
loginMethod: "password", | |||
logo: "/static/logo.png", | |||
logoMargin: ".1em", | |||
logoMask: true, | |||
minimalScopesMode: false, | |||
noAttachmentLinks: false, | |||
nsfwCensorImage: "", | |||
postContentType: "text/plain", | |||
redirectRootLogin: "/main/friends", | |||
redirectRootNoLogin: "/main/all", | |||
scopeCopy: true, | |||
showFeaturesPanel: true, | |||
showInstanceSpecificPanel: false, | |||
subjectLineBehavior: "email", | |||
alwaysShowSubjectInput: true, | |||
logoMask: false, | |||
logoMargin: ".1em", | |||
stickers: false, | |||
enableEmojiPicker: false | |||
theme: "pleroma-dark", | |||
webPushNotifications: false | |||
} | |||
], | |||
children: [ | |||
%{ | |||
key: :theme, | |||
type: :string, | |||
description: "Which theme to use, they are defined in styles.json", | |||
suggestions: ["pleroma-dark"] | |||
}, | |||
%{ | |||
key: :logo, | |||
type: :string, | |||
description: "URL of the logo, defaults to Pleroma's logo", | |||
suggestions: ["/static/logo.png"] | |||
key: :alwaysShowSubjectInput, | |||
label: "Always show subject input", | |||
type: :boolean, | |||
description: "When disabled, auto-hide the subject field if it's empty" | |||
}, | |||
%{ | |||
key: :background, | |||
@@ -1146,46 +1139,35 @@ config :pleroma, :config_description, [ | |||
suggestions: ["/images/city.jpg"] | |||
}, | |||
%{ | |||
key: :redirectRootNoLogin, | |||
label: "Redirect root no login", | |||
type: :string, | |||
description: | |||
"Relative URL which indicates where to redirect when a user isn't logged in", | |||
suggestions: ["/main/all"] | |||
}, | |||
%{ | |||
key: :redirectRootLogin, | |||
label: "Redirect root login", | |||
type: :string, | |||
key: :collapseMessageWithSubject, | |||
label: "Collapse message with subject", | |||
type: :boolean, | |||
description: | |||
"Relative URL which indicates where to redirect when a user is logged in", | |||
suggestions: ["/main/friends"] | |||
"When a message has a subject (aka Content Warning), collapse it by default" | |||
}, | |||
%{ | |||
key: :showInstanceSpecificPanel, | |||
label: "Show instance specific panel", | |||
key: :disableChat, | |||
label: "PleromaFE Chat", | |||
type: :boolean, | |||
description: "Whenether to show the instance's specific panel" | |||
description: "Disables PleromaFE Chat component" | |||
}, | |||
%{ | |||
key: :scopeOptionsEnabled, | |||
label: "Scope options enabled", | |||
key: :greentext, | |||
label: "Greentext", | |||
type: :boolean, | |||
description: "Enable setting a notice visibility and subject/CW when posting" | |||
description: "Enables green text on lines prefixed with the > character." | |||
}, | |||
%{ | |||
key: :formattingOptionsEnabled, | |||
label: "Formatting options enabled", | |||
key: :hideFilteredStatuses, | |||
label: "Hide Filtered Statuses", | |||
type: :boolean, | |||
description: | |||
"Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to `:instance`, `allowed_post_formats`" | |||
description: "Hides filtered statuses from timelines." | |||
}, | |||
%{ | |||
key: :collapseMessageWithSubject, | |||
label: "Collapse message with subject", | |||
key: :hideMutedPosts, | |||
label: "Hide Muted Posts", | |||
type: :boolean, | |||
description: | |||
"When a message has a subject (aka Content Warning), collapse it by default" | |||
description: "Hides muted statuses from timelines." | |||
}, | |||
%{ | |||
key: :hidePostStats, | |||
@@ -1194,6 +1176,12 @@ config :pleroma, :config_description, [ | |||
description: "Hide notices statistics (repeats, favorites, ...)" | |||
}, | |||
%{ | |||
key: :hideSitename, | |||
label: "Hide Sitename", | |||
type: :boolean, | |||
description: "Hides instance name from PleromaFE banner." | |||
}, | |||
%{ | |||
key: :hideUserStats, | |||
label: "Hide user stats", | |||
type: :boolean, | |||
@@ -1201,26 +1189,19 @@ config :pleroma, :config_description, [ | |||
"Hide profile statistics (posts, posts per day, followers, followings, ...)" | |||
}, | |||
%{ | |||
key: :scopeCopy, | |||
label: "Scope copy", | |||
type: :boolean, | |||
description: "Copy the scope (private/unlisted/public) in replies to posts by default" | |||
}, | |||
%{ | |||
key: :subjectLineBehavior, | |||
label: "Subject line behavior", | |||
key: :logo, | |||
type: :string, | |||
description: "Allows changing the default behaviour of subject lines in replies. | |||
`email`: copy and preprend re:, as in email, | |||
`masto`: copy verbatim, as in Mastodon, | |||
`noop`: don't copy the subject.", | |||
suggestions: ["email", "masto", "noop"] | |||
description: "URL of the logo, defaults to Pleroma's logo", | |||
suggestions: ["/static/logo.png"] | |||
}, | |||
%{ | |||
key: :alwaysShowSubjectInput, | |||
label: "Always show subject input", | |||
type: :boolean, | |||
description: "When disabled, auto-hide the subject field if it's empty" | |||
key: :logoMargin, | |||
label: "Logo margin", | |||
type: :string, | |||
description: | |||
"Allows you to adjust vertical margins between logo boundary and navbar borders. " <> | |||
"The idea is that to have logo's image without any extra margins and instead adjust them to your need in layout.", | |||
suggestions: [".1em"] | |||
}, | |||
%{ | |||
key: :logoMask, | |||
@@ -1231,24 +1212,78 @@ config :pleroma, :config_description, [ | |||
"If you want a colorful logo you must disable logoMask." | |||
}, | |||
%{ | |||
key: :logoMargin, | |||
label: "Logo margin", | |||
key: :minimalScopesMode, | |||
label: "Minimal scopes mode", | |||
type: :boolean, | |||
description: | |||
"Limit scope selection to Direct, User default, and Scope of post replying to. " <> | |||
"Also prevents replying to a DM with a public post from PleromaFE." | |||
}, | |||
%{ | |||
key: :nsfwCensorImage, | |||
label: "NSFW Censor Image", | |||
type: :string, | |||
description: | |||
"Allows you to adjust vertical margins between logo boundary and navbar borders. " <> | |||
"The idea is that to have logo's image without any extra margins and instead adjust them to your need in layout.", | |||
suggestions: [".1em"] | |||
"URL of the image to use for hiding NSFW media attachments in the timeline.", | |||
suggestions: ["/static/img/nsfw.png"] | |||
}, | |||
%{ | |||
key: :postContentType, | |||
label: "Post Content Type", | |||
type: {:dropdown, :atom}, | |||
description: "Default post formatting option.", | |||
suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"] | |||
}, | |||
%{ | |||
key: :redirectRootNoLogin, | |||
label: "Redirect root no login", | |||
type: :string, | |||
description: | |||
"Relative URL which indicates where to redirect when a user isn't logged in", | |||
suggestions: ["/main/all"] | |||
}, | |||
%{ | |||
key: :redirectRootLogin, | |||
label: "Redirect root login", | |||
type: :string, | |||
description: | |||
"Relative URL which indicates where to redirect when a user is logged in", | |||
suggestions: ["/main/friends"] | |||
}, | |||
%{ | |||
key: :scopeCopy, | |||
label: "Scope copy", | |||
type: :boolean, | |||
description: "Copy the scope (private/unlisted/public) in replies to posts by default" | |||
}, | |||
%{ | |||
key: :stickers, | |||
key: :showFeaturesPanel, | |||
label: "Show instance features panel", | |||
type: :boolean, | |||
description: "Enables stickers." | |||
description: | |||
"Enables panel displaying functionality of the instance on the About page." | |||
}, | |||
%{ | |||
key: :enableEmojiPicker, | |||
label: "Emoji picker", | |||
key: :showInstanceSpecificPanel, | |||
label: "Show instance specific panel", | |||
type: :boolean, | |||
description: "Enables emoji picker." | |||
description: "Whether to show the instance's custom panel" | |||
}, | |||
%{ | |||
key: :subjectLineBehavior, | |||
label: "Subject line behavior", | |||
type: :string, | |||
description: "Allows changing the default behaviour of subject lines in replies. | |||
`email`: copy and preprend re:, as in email, | |||
`masto`: copy verbatim, as in Mastodon, | |||
`noop`: don't copy the subject.", | |||
suggestions: ["email", "masto", "noop"] | |||
}, | |||
%{ | |||
key: :theme, | |||
type: :string, | |||
description: "Which theme to use. Available themes are defined in styles.json", | |||
suggestions: ["pleroma-dark"] | |||
} | |||
] | |||
}, | |||
@@ -1859,12 +1894,6 @@ config :pleroma, :config_description, [ | |||
""", | |||
children: [ | |||
%{ | |||
key: :repo, | |||
type: :module, | |||
description: "Application's Ecto repo", | |||
suggestions: [Pleroma.Repo] | |||
}, | |||
%{ | |||
key: :verbose, | |||
type: {:dropdown, :atom}, | |||
description: "Logs verbose mode", | |||
@@ -2639,18 +2668,6 @@ config :pleroma, :config_description, [ | |||
] | |||
}, | |||
%{ | |||
group: :http_signatures, | |||
type: :group, | |||
description: "HTTP Signatures settings", | |||
children: [ | |||
%{ | |||
key: :adapter, | |||
type: :module, | |||
suggestions: [Pleroma.Signature] | |||
} | |||
] | |||
}, | |||
%{ | |||
group: :pleroma, | |||
key: :http, | |||
type: :group, | |||
@@ -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" | |||
} |
@@ -67,8 +67,7 @@ defmodule Mix.Tasks.Pleroma.Benchmark do | |||
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{ | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: true | |||
as: :activity | |||
}) | |||
end | |||
}, | |||
@@ -1,5 +1,6 @@ | |||
defmodule Mix.Tasks.Pleroma.Digest do | |||
use Mix.Task | |||
import Mix.Pleroma | |||
@shortdoc "Manages digest emails" | |||
@moduledoc File.read!("docs/administration/CLI_tasks/digest.md") | |||
@@ -22,12 +23,10 @@ defmodule Mix.Tasks.Pleroma.Digest do | |||
with %Swoosh.Email{} = email <- Pleroma.Emails.UserEmail.digest_email(patched_user) do | |||
{:ok, _} = Pleroma.Emails.Mailer.deliver(email) | |||
Mix.shell().info("Digest email have been sent to #{nickname} (#{user.email})") | |||
shell_info("Digest email have been sent to #{nickname} (#{user.email})") | |||
else | |||
_ -> | |||
Mix.shell().info( | |||
"Cound't find any mentions for #{nickname} since #{last_digest_emailed_at}" | |||
) | |||
shell_info("Cound't find any mentions for #{nickname} since #{last_digest_emailed_at}") | |||
end | |||
end | |||
end |
@@ -4,6 +4,7 @@ | |||
defmodule Pleroma.BBS.Authenticator do | |||
use Sshd.PasswordAuthenticator | |||
alias Pleroma.Plugs.AuthenticationPlug | |||
alias Pleroma.User | |||
def authenticate(username, password) do | |||
@@ -11,7 +12,7 @@ defmodule Pleroma.BBS.Authenticator do | |||
password = to_string(password) | |||
with %User{} = user <- User.get_by_nickname(username) do | |||
Pbkdf2.verify_pass(password, user.password_hash) | |||
AuthenticationPlug.checkpw(password, user.password_hash) | |||
else | |||
_e -> false | |||
end | |||
@@ -278,6 +278,8 @@ defmodule Pleroma.ConfigDB do | |||
} | |||
end | |||
defp do_convert({:partial_chain, entity}), do: %{"tuple" => [":partial_chain", inspect(entity)]} | |||
defp do_convert(entity) when is_tuple(entity) do | |||
value = | |||
entity | |||
@@ -321,6 +323,15 @@ defmodule Pleroma.ConfigDB do | |||
{:proxy_url, {do_transform_string(type), parse_host(host), port}} | |||
end | |||
defp do_transform(%{"tuple" => [":partial_chain", entity]}) do | |||
{partial_chain, []} = | |||
entity | |||
|> String.replace(~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "") | |||
|> Code.eval_string() | |||
{:partial_chain, partial_chain} | |||
end | |||
defp do_transform(%{"tuple" => entity}) do | |||
Enum.reduce(entity, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end) | |||
end | |||
@@ -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 @@ defmodule Pleroma.Docs.JSON 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 |
@@ -16,6 +16,11 @@ defmodule Pleroma.Plugs.AuthenticationPlug 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.verify_pass(password, password_hash) | |||
end | |||
@@ -25,6 +30,25 @@ defmodule Pleroma.Plugs.AuthenticationPlug do | |||
false | |||
end | |||
def maybe_update_password(%User{password_hash: "$2" <> _} = user, password) do | |||
do_update_password(user, password) | |||
end | |||
def maybe_update_password(%User{password_hash: "$6" <> _} = user, password) do | |||
do_update_password(user, password) | |||
end | |||
def maybe_update_password(user, _), do: {:ok, user} | |||
defp do_update_password(user, password) do | |||
user | |||
|> User.password_update_changeset(%{ | |||
"password" => password, | |||
"password_confirmation" => password | |||
}) | |||
|> Pleroma.Repo.update() | |||
end | |||
def call(%{assigns: %{user: %User{}}} = conn, _), do: conn | |||
def call( | |||
@@ -36,7 +60,9 @@ defmodule Pleroma.Plugs.AuthenticationPlug do | |||
} = conn, | |||
_ | |||
) do | |||
if Pbkdf2.verify_pass(password, password_hash) do | |||
if checkpw(password, password_hash) do | |||
{:ok, auth_user} = maybe_update_password(auth_user, password) | |||
conn | |||
|> assign(:user, auth_user) | |||
|> OAuthScopesPlug.skip_plug() | |||
@@ -134,7 +134,7 @@ defmodule Pleroma.Upload 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))) | |||
@@ -87,6 +87,22 @@ defmodule Pleroma.UserRelationship do | |||
source_to_target_rel_types \\ nil, | |||
target_to_source_rel_types \\ nil | |||
) | |||
def dictionary( | |||
_source_users, | |||
_target_users, | |||
[] = _source_to_target_rel_types, | |||
[] = _target_to_source_rel_types | |||
) do | |||
[] | |||
end | |||
def dictionary( | |||
source_users, | |||
target_users, | |||
source_to_target_rel_types, | |||
target_to_source_rel_types | |||
) | |||
when is_list(source_users) and is_list(target_users) do | |||
source_user_ids = User.binary_id(source_users) | |||
target_user_ids = User.binary_id(target_users) | |||
@@ -138,11 +154,16 @@ defmodule Pleroma.UserRelationship do | |||
def view_relationships_option(%User{} = reading_user, actors, opts) do | |||
{source_to_target_rel_types, target_to_source_rel_types} = | |||
if opts[:source_mutes_only] do | |||
# This option is used for rendering statuses (FE needs `muted` flag for each one anyways) | |||
{[:mute], []} | |||
else | |||
{[:block, :mute, :notification_mute, :reblog_mute], [:block, :inverse_subscription]} | |||
case opts[:subset] do | |||
:source_mutes -> | |||
# Used for statuses rendering (FE needs `muted` flag for each status when statuses load) | |||
{[:mute], []} | |||
nil -> | |||
{[:block, :mute, :notification_mute, :reblog_mute], [:block, :inverse_subscription]} | |||
unknown -> | |||
raise "Unsupported :subset option value: #{inspect(unknown)}" | |||
end | |||
user_relationships = | |||
@@ -153,7 +174,17 @@ defmodule Pleroma.UserRelationship do | |||
target_to_source_rel_types | |||
) | |||
following_relationships = FollowingRelationship.all_between_user_sets([reading_user], actors) | |||
following_relationships = | |||
case opts[:subset] do | |||
:source_mutes -> | |||
[] | |||
nil -> | |||
FollowingRelationship.all_between_user_sets([reading_user], actors) | |||
unknown -> | |||
raise "Unsupported :subset option value: #{inspect(unknown)}" | |||
end | |||
%{user_relationships: user_relationships, following_relationships: following_relationships} | |||
end | |||
@@ -22,6 +22,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||
alias Pleroma.Web.ActivityPub.Pipeline | |||
alias Pleroma.Web.ActivityPub.Relay | |||
alias Pleroma.Web.ActivityPub.Utils | |||
alias Pleroma.Web.AdminAPI | |||
alias Pleroma.Web.AdminAPI.AccountView | |||
alias Pleroma.Web.AdminAPI.ConfigView | |||
alias Pleroma.Web.AdminAPI.ModerationLogView | |||
@@ -30,14 +31,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||
alias Pleroma.Web.AdminAPI.Search | |||
alias Pleroma.Web.CommonAPI | |||
alias Pleroma.Web.Endpoint | |||
alias Pleroma.Web.MastodonAPI | |||
alias Pleroma.Web.MastodonAPI.AppView | |||
alias Pleroma.Web.MastodonAPI.StatusView | |||
alias Pleroma.Web.OAuth.App | |||
alias Pleroma.Web.Router | |||
require Logger | |||
@descriptions_json Pleroma.Docs.JSON.compile() | |||
@descriptions Pleroma.Docs.JSON.compile() | |||
@users_page_size 50 | |||
plug( | |||
@@ -280,8 +281,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||
}) | |||
conn | |||
|> put_view(Pleroma.Web.AdminAPI.StatusView) | |||
|> render("index.json", %{activities: activities, as: :activity, skip_relationships: false}) | |||
|> put_view(AdminAPI.StatusView) | |||
|> render("index.json", %{activities: activities, as: :activity}) | |||
end | |||
def list_user_statuses(conn, %{"nickname" => nickname} = params) do | |||
@@ -299,8 +300,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||
}) | |||
conn | |||
|> put_view(StatusView) | |||
|> render("index.json", %{activities: activities, as: :activity, skip_relationships: false}) | |||
|> put_view(MastodonAPI.StatusView) | |||
|> render("index.json", %{activities: activities, as: :activity}) | |||
else | |||
_ -> {:error, :not_found} | |||
end | |||
@@ -829,14 +830,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||
}) | |||
conn | |||
|> put_view(Pleroma.Web.AdminAPI.StatusView) | |||
|> render("index.json", %{activities: activities, as: :activity, skip_relationships: false}) | |||
|> put_view(AdminAPI.StatusView) | |||
|> render("index.json", %{activities: activities, as: :activity}) | |||
end | |||
def status_show(conn, %{"id" => id}) do | |||
with %Activity{} = activity <- Activity.get_by_id(id) do | |||
conn | |||
|> put_view(StatusView) | |||
|> put_view(MastodonAPI.StatusView) | |||
|> render("show.json", %{activity: activity}) | |||
else | |||
_ -> errors(conn, {:error, :not_found}) | |||
@@ -861,7 +862,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||
}) | |||
conn | |||
|> put_view(StatusView) | |||
|> put_view(MastodonAPI.StatusView) | |||
|> render("show.json", %{activity: activity}) | |||
end | |||
end | |||
@@ -897,9 +898,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController 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 | |||
@@ -954,7 +955,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController 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"]}) | |||
@@ -1016,6 +1019,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController 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() | |||
@@ -6,7 +6,9 @@ defmodule Pleroma.Web.AdminAPI.AccountView do | |||
use Pleroma.Web, :view | |||
alias Pleroma.User | |||
alias Pleroma.Web.AdminAPI | |||
alias Pleroma.Web.AdminAPI.AccountView | |||
alias Pleroma.Web.MastodonAPI | |||
alias Pleroma.Web.MediaProxy | |||
def render("index.json", %{users: users, count: count, page_size: page_size}) do | |||
@@ -119,6 +121,13 @@ defmodule Pleroma.Web.AdminAPI.AccountView do | |||
} | |||
end | |||
def merge_account_views(%User{} = user) do | |||
MastodonAPI.AccountView.render("show.json", %{user: user}) | |||
|> Map.merge(AdminAPI.AccountView.render("show.json", %{user: user})) | |||
end | |||
def merge_account_views(_), do: %{} | |||
defp parse_error([]), do: "" | |||
defp parse_error(errors) do | |||
@@ -7,10 +7,13 @@ defmodule Pleroma.Web.AdminAPI.ReportView do | |||
alias Pleroma.HTML | |||
alias Pleroma.User | |||
alias Pleroma.Web.AdminAPI | |||
alias Pleroma.Web.AdminAPI.Report | |||
alias Pleroma.Web.CommonAPI.Utils | |||
alias Pleroma.Web.MastodonAPI.StatusView | |||
defdelegate merge_account_views(user), to: AdminAPI.AccountView | |||
def render("index.json", %{reports: reports}) do | |||
%{ | |||
reports: | |||
@@ -41,8 +44,7 @@ defmodule Pleroma.Web.AdminAPI.ReportView do | |||
statuses: | |||
StatusView.render("index.json", %{ | |||
activities: statuses, | |||
as: :activity, | |||
skip_relationships: false | |||
as: :activity | |||
}), | |||
state: report.data["state"], | |||
notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes}) | |||
@@ -70,11 +72,4 @@ defmodule Pleroma.Web.AdminAPI.ReportView do | |||
created_at: Utils.to_masto_date(inserted_at) | |||
} | |||
end | |||
defp merge_account_views(%User{} = user) do | |||
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user}) | |||
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})) | |||
end | |||
defp merge_account_views(_), do: %{} | |||
end |
@@ -7,24 +7,19 @@ defmodule Pleroma.Web.AdminAPI.StatusView do | |||
require Pleroma.Constants | |||
alias Pleroma.User | |||
alias Pleroma.Web.MastodonAPI.StatusView | |||
alias Pleroma.Web.AdminAPI | |||
alias Pleroma.Web.MastodonAPI | |||
defdelegate merge_account_views(user), to: AdminAPI.AccountView | |||
def render("index.json", opts) do | |||
safe_render_many(opts.activities, __MODULE__, "show.json", opts) | |||
end | |||
def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do | |||
user = StatusView.get_user(activity.data["actor"]) | |||
user = MastodonAPI.StatusView.get_user(activity.data["actor"]) | |||
StatusView.render("show.json", opts) | |||
MastodonAPI.StatusView.render("show.json", opts) | |||
|> Map.merge(%{account: merge_account_views(user)}) | |||
end | |||
defp merge_account_views(%User{} = user) do | |||
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user}) | |||
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})) | |||
end | |||
defp merge_account_views(_), do: %{} | |||
end |
@@ -5,6 +5,7 @@ | |||
defmodule Pleroma.Web.ApiSpec.Helpers do | |||
alias OpenApiSpex.Operation | |||
alias OpenApiSpex.Schema | |||
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike | |||
def request_body(description, schema_ref, opts \\ []) do | |||
media_types = ["application/json", "multipart/form-data", "application/x-www-form-urlencoded"] | |||
@@ -47,6 +48,15 @@ defmodule Pleroma.Web.ApiSpec.Helpers do | |||
] | |||
end | |||
def with_relationships_param do | |||
Operation.parameter( | |||
:with_relationships, | |||
:query, | |||
BooleanLike, | |||
"Embed relationships into accounts." | |||
) | |||
end | |||
def empty_object_response do | |||
Operation.response("Empty object", "application/json", %Schema{type: :object, example: %{}}) | |||
end | |||
@@ -54,4 +64,8 @@ defmodule Pleroma.Web.ApiSpec.Helpers 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 |
@@ -155,8 +155,10 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
security: [%{"oAuth" => ["read:accounts"]}], | |||
description: | |||
"Accounts which follow the given account, if network is not hidden by the account owner.", | |||
parameters: | |||
[%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}] ++ pagination_params(), | |||
parameters: [ | |||
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}, | |||
with_relationships_param() | pagination_params() | |||
], | |||
responses: %{ | |||
200 => Operation.response("Accounts", "application/json", array_of_accounts()) | |||
} | |||
@@ -171,8 +173,10 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
security: [%{"oAuth" => ["read:accounts"]}], | |||
description: | |||
"Accounts which the given account is following, if network is not hidden by the account owner.", | |||
parameters: | |||
[%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}] ++ pagination_params(), | |||
parameters: [ | |||
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}, | |||
with_relationships_param() | pagination_params() | |||
], | |||
responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())} | |||
} | |||
end | |||
@@ -367,15 +371,18 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
title: "AccountCreateRequest", | |||
description: "POST body for creating an account", | |||
type: :object, | |||
required: [:username, :password, :agreement], | |||
properties: %{ | |||
reason: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: | |||
"Text that will be reviewed by moderators if registrations require manual approval" | |||
}, | |||
username: %Schema{type: :string, description: "The desired username for the account"}, | |||
email: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: | |||
"The email address to be used for login. Required when `account_activation_required` is enabled.", | |||
format: :email | |||
@@ -392,23 +399,33 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
}, | |||
locale: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "The language of the confirmation email that will be sent" | |||
}, | |||
# Pleroma-specific properties: | |||
fullname: %Schema{type: :string, description: "Full name"}, | |||
bio: %Schema{type: :string, description: "Bio", default: ""}, | |||
fullname: %Schema{type: :string, nullable: true, description: "Full name"}, | |||
bio: %Schema{type: :string, description: "Bio", nullable: true, default: ""}, | |||
captcha_solution: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Provider-specific captcha solution" | |||
}, | |||
captcha_token: %Schema{type: :string, description: "Provider-specific captcha token"}, | |||
captcha_answer_data: %Schema{type: :string, description: "Provider-specific captcha data"}, | |||
captcha_token: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Provider-specific captcha token" | |||
}, | |||
captcha_answer_data: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Provider-specific captcha data" | |||
}, | |||
token: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Invite token required when the registrations aren't public" | |||
} | |||
}, | |||
required: [:username, :password, :agreement], | |||
example: %{ | |||
"username" => "cofe", | |||
"email" => "cofe@example.com", | |||
@@ -447,28 +464,34 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
properties: %{ | |||
bot: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Whether the account has a bot flag." | |||
}, | |||
display_name: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "The display name to use for the profile." | |||
}, | |||
note: %Schema{type: :string, description: "The account bio."}, | |||
avatar: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Avatar image encoded using multipart/form-data", | |||
format: :binary | |||
}, | |||
header: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Header image encoded using multipart/form-data", | |||
format: :binary | |||
}, | |||
locked: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Whether manual approval of follow requests is required." | |||
}, | |||
fields_attributes: %Schema{ | |||
nullable: true, | |||
oneOf: [ | |||
%Schema{type: :array, items: attribute_field()}, | |||
%Schema{type: :object, additionalProperties: %Schema{type: attribute_field()}} | |||
@@ -488,47 +511,65 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
# Pleroma-specific fields | |||
no_rich_text: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "html tags are stripped from all statuses requested from the API" | |||
}, | |||
hide_followers: %Schema{type: :boolean, description: "user's followers will be hidden"}, | |||
hide_follows: %Schema{type: :boolean, description: "user's follows will be hidden"}, | |||
hide_followers: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "user's followers will be hidden" | |||
}, | |||
hide_follows: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "user's follows will be hidden" | |||
}, | |||
hide_followers_count: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "user's follower count will be hidden" | |||
}, | |||
hide_follows_count: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "user's follow count will be hidden" | |||
}, | |||
hide_favorites: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "user's favorites timeline will be hidden" | |||
}, | |||
show_role: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "user's role (e.g admin, moderator) will be exposed to anyone in the | |||
API" | |||
}, | |||
default_scope: VisibilityScope, | |||
pleroma_settings_store: %Schema{ | |||
type: :object, | |||
nullable: true, | |||
description: "Opaque user settings to be saved on the backend." | |||
}, | |||
skip_thread_containment: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Skip filtering out broken threads" | |||
}, | |||
allow_following_move: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Allows automatically follow moved following accounts" | |||
}, | |||
pleroma_background_image: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Sets the background image of the user.", | |||
format: :binary | |||
}, | |||
discoverable: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: | |||
"Discovery of this account in search results and other services is allowed." | |||
}, | |||
@@ -624,7 +665,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
description: "POST body for muting an account", | |||
type: :object, | |||
properties: %{ | |||
uri: %Schema{type: :string, format: :uri} | |||
uri: %Schema{type: :string, nullable: true, format: :uri} | |||
}, | |||
required: [:uri] | |||
} | |||
@@ -638,6 +679,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do | |||
properties: %{ | |||
notifications: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Mute notifications in addition to statuses? Defaults to true.", | |||
default: true | |||
} | |||
@@ -105,7 +105,11 @@ defmodule Pleroma.Web.ApiSpec.AppOperation do | |||
description: "Space separated list of scopes", | |||
default: "read" | |||
}, | |||
website: %Schema{type: :string, description: "A URL to the homepage of your app"} | |||
website: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "A URL to the homepage of your app" | |||
} | |||
}, | |||
required: [:client_name, :redirect_uris], | |||
example: %{ | |||
@@ -199,12 +199,14 @@ defmodule Pleroma.Web.ApiSpec.FilterOperation do | |||
"Array of enumerable strings `home`, `notifications`, `public`, `thread`. At least one context must be specified." | |||
}, | |||
irreversible: %Schema{ | |||
type: :bolean, | |||
type: :boolean, | |||
nullable: true, | |||
description: | |||
"Should the server irreversibly drop matching entities from home and notifications?" | |||
}, | |||
whole_word: %Schema{ | |||
type: :bolean, | |||
type: :boolean, | |||
nullable: true, | |||
description: "Consider word boundaries?", | |||
default: true | |||
} | |||
@@ -110,14 +110,16 @@ defmodule Pleroma.Web.ApiSpec.MarkerOperation do | |||
properties: %{ | |||
notifications: %Schema{ | |||
type: :object, | |||
nullable: true, | |||
properties: %{ | |||
last_read_id: %Schema{type: :string} | |||
last_read_id: %Schema{nullable: true, type: :string} | |||
} | |||
}, | |||
home: %Schema{ | |||
type: :object, | |||
nullable: true, | |||
properties: %{ | |||
last_read_id: %Schema{type: :string} | |||
last_read_id: %Schema{nullable: true, type: :string} | |||
} | |||
} | |||
}, | |||
@@ -0,0 +1,132 @@ | |||
# 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.MediaOperation do | |||
alias OpenApiSpex.Operation | |||
alias OpenApiSpex.Schema | |||
alias Pleroma.Web.ApiSpec.Helpers | |||
alias Pleroma.Web.ApiSpec.Schemas.ApiError | |||
alias Pleroma.Web.ApiSpec.Schemas.Attachment | |||
def open_api_operation(action) do | |||
operation = String.to_existing_atom("#{action}_operation") | |||
apply(__MODULE__, operation, []) | |||
end | |||
def create_operation do | |||
%Operation{ | |||
tags: ["media"], | |||
summary: "Upload media as attachment", | |||
description: "Creates an attachment to be used with a new status.", | |||
operationId: "MediaController.create", | |||
security: [%{"oAuth" => ["write:media"]}], | |||
requestBody: Helpers.request_body("Parameters", create_request()), | |||
responses: %{ | |||
200 => Operation.response("Media", "application/json", Attachment), | |||
401 => Operation.response("Media", "application/json", ApiError), | |||
422 => Operation.response("Media", "application/json", ApiError) | |||
} | |||
} | |||
end | |||
defp create_request do | |||
%Schema{ | |||
title: "MediaCreateRequest", | |||
description: "POST body for creating an attachment", | |||
type: :object, | |||
required: [:file], | |||
properties: %{ | |||
file: %Schema{ | |||
type: :string, | |||
format: :binary, | |||
description: "The file to be attached, using multipart form data." | |||
}, | |||
description: %Schema{ | |||
type: :string, | |||
description: "A plain-text description of the media, for accessibility purposes." | |||
}, | |||
focus: %Schema{ | |||
type: :string, | |||
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0." | |||
} | |||
} | |||
} | |||
end | |||
def update_operation do | |||
%Operation{ | |||
tags: ["media"], | |||
summary: "Upload media as attachment", | |||
description: "Creates an attachment to be used with a new status.", | |||
operationId: "MediaController.update", | |||
security: [%{"oAuth" => ["write:media"]}], | |||
parameters: [id_param()], | |||
requestBody: Helpers.request_body("Parameters", update_request()), | |||
responses: %{ | |||
200 => Operation.response("Media", "application/json", Attachment), | |||
400 => Operation.response("Media", "application/json", ApiError), | |||
401 => Operation.response("Media", "application/json", ApiError), | |||
422 => Operation.response("Media", "application/json", ApiError) | |||
} | |||
} | |||
end | |||
defp update_request do | |||
%Schema{ | |||
title: "MediaUpdateRequest", | |||
description: "POST body for updating an attachment", | |||
type: :object, | |||
properties: %{ | |||
file: %Schema{ | |||
type: :string, | |||
format: :binary, | |||
description: "The file to be attached, using multipart form data." | |||
}, | |||
description: %Schema{ | |||
type: :string, | |||
description: "A plain-text description of the media, for accessibility purposes." | |||
}, | |||
focus: %Schema{ | |||
type: :string, | |||
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0." | |||
} | |||
} | |||
} | |||
end | |||
def show_operation do | |||
%Operation{ | |||
tags: ["media"], | |||
summary: "Show Uploaded media attachment", | |||
operationId: "MediaController.show", | |||
parameters: [id_param()], | |||
security: [%{"oAuth" => ["read:media"]}], | |||
responses: %{ | |||
200 => Operation.response("Media", "application/json", Attachment), | |||
401 => Operation.response("Media", "application/json", ApiError), | |||
422 => Operation.response("Media", "application/json", ApiError) | |||
} | |||
} | |||
end | |||
def create2_operation do | |||
%Operation{ | |||
tags: ["media"], | |||
summary: "Upload media as attachment", | |||
description: "Creates an attachment to be used with a new status.", | |||
operationId: "MediaController.create2", | |||
security: [%{"oAuth" => ["write:media"]}], | |||
requestBody: Helpers.request_body("Parameters", create_request()), | |||
responses: %{ | |||
202 => Operation.response("Media", "application/json", Attachment), | |||
422 => Operation.response("Media", "application/json", ApiError), | |||
500 => Operation.response("Media", "application/json", ApiError) | |||
} | |||
} | |||
end | |||
defp id_param do | |||
Operation.parameter(:id, :path, :string, "The ID of the Attachment entity") | |||
end | |||
end |
@@ -0,0 +1,187 @@ | |||
# 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{ | |||
nullable: true, | |||
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, | |||
nullable: true, | |||
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 |
@@ -37,15 +37,18 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do | |||
account_id: %Schema{type: :string, description: "ID of the account to report"}, | |||
status_ids: %Schema{ | |||
type: :array, | |||
nullable: true, | |||
items: %Schema{type: :string}, | |||
description: "Array of Statuses to attach to the report, for context" | |||
}, | |||
comment: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "Reason for the report" | |||
}, | |||
forward: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
default: false, | |||
description: | |||
"If the account is remote, should the report be forwarded to the remote admin?" | |||
@@ -19,6 +19,7 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do | |||
apply(__MODULE__, operation, []) | |||
end | |||
# Note: `with_relationships` param is not supported (PleromaFE uses this op for autocomplete) | |||
def account_search_operation do | |||
%Operation{ | |||
tags: ["Search"], | |||
@@ -96,8 +97,8 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do | |||
:query, | |||
%Schema{type: :integer}, | |||
"Offset" | |||
) | |||
| pagination_params() | |||
), | |||
with_relationships_param() | pagination_params() | |||
], | |||
responses: %{ | |||
200 => Operation.response("Results", "application/json", results()) | |||
@@ -138,8 +139,8 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do | |||
:query, | |||
%Schema{allOf: [BooleanLike], default: false}, | |||
"Only include accounts that the user is following" | |||
) | |||
| pagination_params() | |||
), | |||
with_relationships_param() | pagination_params() | |||
], | |||
responses: %{ | |||
200 => Operation.response("Results", "application/json", results2()) | |||
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
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 | |||
@@ -349,10 +348,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
summary: "Bookmarked statuses", | |||
description: "Statuses the user has bookmarked", | |||
operationId: "StatusController.bookmarks", | |||
parameters: [ | |||
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships") | |||
| pagination_params() | |||
], | |||
parameters: pagination_params(), | |||
security: [%{"oAuth" => ["read:bookmarks"]}], | |||
responses: %{ | |||
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses()) | |||
@@ -360,7 +356,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
} | |||
end | |||
defp array_of_statuses do | |||
def array_of_statuses do | |||
%Schema{type: :array, items: Status, example: [Status.schema().example]} | |||
end | |||
@@ -371,15 +367,18 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
properties: %{ | |||
status: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
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{ | |||
nullable: true, | |||
type: :array, | |||
items: %Schema{type: :string}, | |||
description: "Array of Attachment ids to be attached as media." | |||
}, | |||
poll: %Schema{ | |||
nullable: true, | |||
type: :object, | |||
required: [:options], | |||
properties: %{ | |||
@@ -390,26 +389,35 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
}, | |||
expires_in: %Schema{ | |||
type: :integer, | |||
nullable: true, | |||
description: | |||
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`" | |||
}, | |||
multiple: %Schema{type: :boolean, description: "Allow multiple choices?"}, | |||
multiple: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Allow multiple choices?" | |||
}, | |||
hide_totals: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Hide vote counts until the poll ends?" | |||
} | |||
} | |||
}, | |||
in_reply_to_id: %Schema{ | |||
nullable: true, | |||
allOf: [FlakeID], | |||
description: "ID of the status being replied to, if status is a reply" | |||
}, | |||
sensitive: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Mark status and attached media as sensitive?" | |||
}, | |||
spoiler_text: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: | |||
"Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field." | |||
}, | |||
@@ -420,25 +428,33 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
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."}, | |||
language: %Schema{ | |||
type: :string, | |||
nullable: true, | |||
description: "ISO 639 language code for this status." | |||
}, | |||
# Pleroma-specific properties: | |||
preview: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
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, | |||
nullable: true, | |||
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, | |||
nullable: true, | |||
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{ | |||
nullable: true, | |||
anyOf: [ | |||
VisibilityScope, | |||
%Schema{type: :string, description: "`list:LIST_ID`", example: "LIST:123"} | |||
@@ -447,11 +463,13 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do | |||
"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{ | |||
nullable: true, | |||
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{ | |||
nullable: true, | |||
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`." | |||
@@ -109,19 +109,38 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do | |||
required: [:endpoint, :keys] | |||
}, | |||
data: %Schema{ | |||
nullable: true, | |||
type: :object, | |||
properties: %{ | |||
alerts: %Schema{ | |||
nullable: true, | |||
type: :object, | |||
properties: %{ | |||
follow: %Schema{type: :boolean, description: "Receive follow notifications?"}, | |||
follow: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive follow notifications?" | |||
}, | |||
favourite: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive favourite notifications?" | |||
}, | |||
reblog: %Schema{type: :boolean, description: "Receive reblog notifications?"}, | |||
mention: %Schema{type: :boolean, description: "Receive mention notifications?"}, | |||
poll: %Schema{type: :boolean, description: "Receive poll notifications?"} | |||
reblog: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive reblog notifications?" | |||
}, | |||
mention: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive mention notifications?" | |||
}, | |||
poll: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive poll notifications?" | |||
} | |||
} | |||
} | |||
} | |||
@@ -154,19 +173,38 @@ defmodule Pleroma.Web.ApiSpec.SubscriptionOperation do | |||
type: :object, | |||
properties: %{ | |||
data: %Schema{ | |||
nullable: true, | |||
type: :object, | |||
properties: %{ | |||
alerts: %Schema{ | |||
nullable: true, | |||
type: :object, | |||
properties: %{ | |||
follow: %Schema{type: :boolean, description: "Receive follow notifications?"}, | |||
follow: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive follow notifications?" | |||
}, | |||
favourite: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive favourite notifications?" | |||
}, | |||
reblog: %Schema{type: :boolean, description: "Receive reblog notifications?"}, | |||
mention: %Schema{type: :boolean, description: "Receive mention notifications?"}, | |||
poll: %Schema{type: :boolean, description: "Receive poll notifications?"} | |||
reblog: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive reblog notifications?" | |||
}, | |||
mention: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive mention notifications?" | |||
}, | |||
poll: %Schema{ | |||
type: :boolean, | |||
nullable: true, | |||
description: "Receive poll notifications?" | |||
} | |||
} | |||
} | |||
} | |||
@@ -27,8 +27,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do | |||
local_param(), | |||
with_muted_param(), | |||
exclude_visibilities_param(), | |||
reply_visibility_param(), | |||
with_relationships_param() | pagination_params() | |||
reply_visibility_param() | pagination_params() | |||
], | |||
operationId: "TimelineController.home", | |||
responses: %{ | |||
@@ -63,8 +62,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do | |||
only_media_param(), | |||
with_muted_param(), | |||
exclude_visibilities_param(), | |||
reply_visibility_param(), | |||
with_relationships_param() | pagination_params() | |||
reply_visibility_param() | pagination_params() | |||
], | |||
operationId: "TimelineController.public", | |||
responses: %{ | |||
@@ -109,8 +107,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do | |||
local_param(), | |||
only_media_param(), | |||
with_muted_param(), | |||
exclude_visibilities_param(), | |||
with_relationships_param() | pagination_params() | |||
exclude_visibilities_param() | pagination_params() | |||
], | |||
operationId: "TimelineController.hashtag", | |||
responses: %{ | |||
@@ -134,8 +131,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do | |||
required: true | |||
), | |||
with_muted_param(), | |||
exclude_visibilities_param(), | |||
with_relationships_param() | pagination_params() | |||
exclude_visibilities_param() | pagination_params() | |||
], | |||
operationId: "TimelineController.list", | |||
responses: %{ | |||
@@ -153,10 +149,6 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do | |||
} | |||
end | |||
defp with_relationships_param do | |||
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships") | |||
end | |||
defp local_param do | |||
Operation.parameter( | |||
:local, | |||
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Attachment do | |||
type: :object, | |||
requried: [:id, :url, :preview_url], | |||
properties: %{ | |||
id: %Schema{type: :string}, | |||
id: %Schema{type: :string, description: "The ID of the attachment in the database."}, | |||
url: %Schema{ | |||
type: :string, | |||
format: :uri, | |||
@@ -16,7 +16,8 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do | |||
def get_user(%Plug.Conn{} = conn) do | |||
with {:ok, {name, password}} <- fetch_credentials(conn), | |||
{_, %User{} = user} <- {:user, fetch_user(name)}, | |||
{_, true} <- {:checkpw, AuthenticationPlug.checkpw(password, user.password_hash)} do | |||
{_, true} <- {:checkpw, AuthenticationPlug.checkpw(password, user.password_hash)}, | |||
{:ok, user} <- AuthenticationPlug.maybe_update_password(user, password) do | |||
{:ok, user} | |||
else | |||
{:error, _reason} = error -> error | |||
@@ -5,6 +5,7 @@ | |||
defmodule Pleroma.Web.Auth.TOTPAuthenticator do | |||
alias Pleroma.MFA | |||
alias Pleroma.MFA.TOTP | |||
alias Pleroma.Plugs.AuthenticationPlug | |||
alias Pleroma.User | |||
@doc "Verify code or check backup code." | |||
@@ -30,7 +31,7 @@ defmodule Pleroma.Web.Auth.TOTPAuthenticator do | |||
code | |||
) | |||
when is_list(codes) and is_binary(code) do | |||
hash_code = Enum.find(codes, fn hash -> Pbkdf2.verify_pass(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) | |||
@@ -23,6 +23,7 @@ defmodule Pleroma.Web.ChatChannel do | |||
if String.length(text) in 1..Pleroma.Config.get([:instance, :chat_limit]) do | |||
author = User.get_cached_by_nickname(user_name) | |||
author = Pleroma.Web.MastodonAPI.AccountView.render("show.json", user: author) | |||
message = ChatChannelState.add_message(%{text: text, author: author}) | |||
broadcast!(socket, "new_msg", message) | |||
@@ -25,10 +25,21 @@ defmodule Pleroma.Web.CommonAPI do | |||
require Logger | |||
def unblock(blocker, blocked) do | |||
with %Activity{} = block <- Utils.fetch_latest_block(blocker, blocked), | |||
with {_, %Activity{} = block} <- {:fetch_block, Utils.fetch_latest_block(blocker, blocked)}, | |||
{:ok, unblock_data, _} <- Builder.undo(blocker, block), | |||
{:ok, unblock, _} <- Pipeline.common_pipeline(unblock_data, local: true) do | |||
{:ok, unblock} | |||
else | |||
{:fetch_block, nil} -> | |||
if User.blocks?(blocker, blocked) do | |||
User.unblock(blocker, blocked) | |||
{:ok, :no_activity} | |||
else | |||
{:error, :not_blocking} | |||
end | |||
e -> | |||
e | |||
end | |||
end | |||
@@ -5,8 +5,6 @@ | |||
defmodule Pleroma.Web.ControllerHelper do | |||
use Pleroma.Web, :controller | |||
alias Pleroma.Config | |||
# As in Mastodon API, per https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html | |||
@falsy_param_values [false, 0, "0", "f", "F", "false", "False", "FALSE", "off", "OFF"] | |||
@@ -106,13 +104,16 @@ defmodule Pleroma.Web.ControllerHelper do | |||
def put_if_exist(map, key, value), do: Map.put(map, key, value) | |||
@doc "Whether to skip rendering `[:account][:pleroma][:relationship]`for statuses/notifications" | |||
def skip_relationships?(params) do | |||
if Config.get([:extensions, :output_relationships_in_statuses_by_default]) do | |||
false | |||
else | |||
# BREAKING: older PleromaFE versions do not send this param but _do_ expect relationships. | |||
not truthy_param?(params["with_relationships"]) | |||
end | |||
@doc """ | |||
Returns true if request specifies to include embedded relationships in account objects. | |||
May only be used in selected account-related endpoints; has no effect for status- or | |||
notification-related endpoints. | |||
""" | |||
# Intended for PleromaFE: https://git.pleroma.social/pleroma/pleroma-fe/-/issues/838 | |||
def embed_relationships?(params) do | |||
# To do once OpenAPI transition mess is over: just `truthy_param?(params[:with_relationships])` | |||
params | |||
|> Map.get(:with_relationships, params["with_relationships"]) | |||
|> truthy_param?() | |||
end | |||
end |
@@ -10,8 +10,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do | |||
add_link_headers: 2, | |||
truthy_param?: 1, | |||
assign_account_by_id: 2, | |||
json_response: 3, | |||
skip_relationships?: 1 | |||
embed_relationships?: 1, | |||
json_response: 3 | |||
] | |||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug | |||
@@ -247,8 +247,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: reading_user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
else | |||
_e -> render_error(conn, :not_found, "Can't find user") | |||
@@ -271,7 +270,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do | |||
conn | |||
|> add_link_headers(followers) | |||
|> render("index.json", for: for_user, users: followers, as: :user) | |||
# https://git.pleroma.social/pleroma/pleroma-fe/-/issues/838#note_59223 | |||
|> render("index.json", | |||
for: for_user, | |||
users: followers, | |||
as: :user, | |||
embed_relationships: embed_relationships?(params) | |||
) | |||
end | |||
@doc "GET /api/v1/accounts/:id/following" | |||
@@ -290,7 +295,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do | |||
conn | |||
|> add_link_headers(followers) | |||
|> render("index.json", for: for_user, users: followers, as: :user) | |||
# https://git.pleroma.social/pleroma/pleroma-fe/-/issues/838#note_59223 | |||
|> render("index.json", | |||
for: for_user, | |||
users: followers, | |||
as: :user, | |||
embed_relationships: embed_relationships?(params) | |||
) | |||
end | |||
@doc "GET /api/v1/accounts/:id/lists" | |||
@@ -11,17 +11,20 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do | |||
alias Pleroma.Web.ActivityPub.ActivityPub | |||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController) | |||
plug(Pleroma.Web.ApiSpec.CastAndValidate) | |||
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView) | |||
plug(OAuthScopesPlug, %{scopes: ["write:media"]}) | |||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation | |||
@doc "POST /api/v1/media" | |||
def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do | |||
def create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do | |||
with {:ok, object} <- | |||
ActivityPub.upload( | |||
file, | |||
actor: User.ap_id(user), | |||
description: Map.get(data, "description") | |||
description: Map.get(data, :description) | |||
) do | |||
attachment_data = Map.put(object.data, "id", object.id) | |||
@@ -29,9 +32,28 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do | |||
end | |||
end | |||
def create(_conn, _data), do: {:error, :bad_request} | |||
@doc "POST /api/v2/media" | |||
def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do | |||
with {:ok, object} <- | |||
ActivityPub.upload( | |||
file, | |||
actor: User.ap_id(user), | |||
description: Map.get(data, :description) | |||
) do | |||
attachment_data = Map.put(object.data, "id", object.id) | |||
conn | |||
|> put_status(202) | |||
|> render("attachment.json", %{attachment: attachment_data}) | |||
end | |||
end | |||
def create2(_conn, _data), do: {:error, :bad_request} | |||
@doc "PUT /api/v1/media/:id" | |||
def update(%{assigns: %{user: user}} = conn, %{"id" => id, "description" => description}) | |||
when is_binary(description) do | |||
def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do | |||
with %Object{} = object <- Object.get_by_id(id), | |||
true <- Object.authorize_mutation(object, user), | |||
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do | |||
@@ -41,5 +63,16 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do | |||
end | |||
end | |||
def update(_conn, _data), do: {:error, :bad_request} | |||
def update(conn, data), do: show(conn, data) | |||
@doc "GET /api/v1/media/:id" | |||
def show(conn, %{id: id}) do | |||
with %Object{data: data, id: object_id} <- Object.get_by_id(id) do | |||
attachment_data = Map.put(data, "id", object_id) | |||
render(conn, "attachment.json", %{attachment: attachment_data}) | |||
end | |||
end | |||
def get_media(_conn, _data), do: {:error, :bad_request} | |||
end |
@@ -5,7 +5,7 @@ | |||
defmodule Pleroma.Web.MastodonAPI.NotificationController do | |||
use Pleroma.Web, :controller | |||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, skip_relationships?: 1] | |||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] | |||
alias Pleroma.Notification | |||
alias Pleroma.Plugs.OAuthScopesPlug | |||
@@ -50,8 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do | |||
|> add_link_headers(notifications) | |||
|> render("index.json", | |||
notifications: notifications, | |||
for: user, | |||
skip_relationships: skip_relationships?(params) | |||
for: user | |||
) | |||
end | |||
@@ -5,14 +5,13 @@ | |||
defmodule Pleroma.Web.MastodonAPI.SearchController do | |||
use Pleroma.Web, :controller | |||
import Pleroma.Web.ControllerHelper, only: [skip_relationships?: 1] | |||
alias Pleroma.Activity | |||
alias Pleroma.Plugs.OAuthScopesPlug | |||
alias Pleroma.Plugs.RateLimiter | |||
alias Pleroma.Repo | |||
alias Pleroma.User | |||
alias Pleroma.Web | |||
alias Pleroma.Web.ControllerHelper | |||
alias Pleroma.Web.MastodonAPI.AccountView | |||
alias Pleroma.Web.MastodonAPI.StatusView | |||
@@ -34,7 +33,11 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do | |||
conn | |||
|> put_view(AccountView) | |||
|> render("index.json", users: accounts, for: user, as: :user) | |||
|> render("index.json", | |||
users: accounts, | |||
for: user, | |||
as: :user | |||
) | |||
end | |||
def search2(conn, params), do: do_search(:v2, conn, params) | |||
@@ -71,13 +74,13 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do | |||
defp search_options(params, user) do | |||
[ | |||
skip_relationships: skip_relationships?(params), | |||
resolve: params[:resolve], | |||
following: params[:following], | |||
limit: params[:limit], | |||
offset: params[:offset], | |||
type: params[:type], | |||
author: get_author(params), | |||
embed_relationships: ControllerHelper.embed_relationships?(params), | |||
for_user: user | |||
] | |||
|> Enum.filter(&elem(&1, 1)) | |||
@@ -90,7 +93,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do | |||
users: accounts, | |||
for: options[:for_user], | |||
as: :user, | |||
skip_relationships: false | |||
embed_relationships: options[:embed_relationships] | |||
) | |||
end | |||
@@ -100,8 +103,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do | |||
StatusView.render("index.json", | |||
activities: statuses, | |||
for: options[:for_user], | |||
as: :activity, | |||
skip_relationships: options[:skip_relationships] | |||
as: :activity | |||
) | |||
end | |||
@@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||
use Pleroma.Web, :controller | |||
import Pleroma.Web.ControllerHelper, | |||
only: [try_render: 3, add_link_headers: 2, skip_relationships?: 1] | |||
only: [try_render: 3, add_link_headers: 2] | |||
require Ecto.Query | |||
@@ -105,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||
`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 = | |||
@@ -117,8 +117,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||
render(conn, "index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
@@ -383,8 +382,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
@@ -406,8 +404,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
end |
@@ -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, skip_relationships?: 1] | |||
only: [add_link_headers: 2, add_link_headers: 3] | |||
alias Pleroma.Pagination | |||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug | |||
@@ -63,8 +63,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
@@ -88,8 +87,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
@@ -125,8 +123,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
end | |||
@@ -173,8 +170,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
@@ -203,8 +199,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do | |||
render(conn, "index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
else | |||
_e -> render_error(conn, :forbidden, "Error.") | |||
@@ -15,13 +15,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do | |||
def render("index.json", %{users: users} = opts) do | |||
reading_user = opts[:for] | |||
# Note: :skip_relationships option is currently intentionally not supported for accounts | |||
relationships_opt = | |||
cond do | |||
Map.has_key?(opts, :relationships) -> | |||
opts[:relationships] | |||
is_nil(reading_user) -> | |||
is_nil(reading_user) || !opts[:embed_relationships] -> | |||
UserRelationship.view_relationships_option(nil, []) | |||
true -> | |||
@@ -193,14 +192,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do | |||
end) | |||
relationship = | |||
if opts[:skip_relationships] do | |||
%{} | |||
else | |||
if opts[:embed_relationships] do | |||
render("relationship.json", %{ | |||
user: opts[:for], | |||
target: user, | |||
relationships: opts[:relationships] | |||
}) | |||
else | |||
%{} | |||
end | |||
%{ | |||
@@ -51,9 +51,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do | |||
|> Enum.filter(& &1) | |||
|> Kernel.++(move_activities_targets) | |||
UserRelationship.view_relationships_option(reading_user, actors, | |||
source_mutes_only: opts[:skip_relationships] | |||
) | |||
UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes) | |||
end | |||
opts = | |||
@@ -83,15 +81,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do | |||
mastodon_type = Activity.mastodon_notification_type(activity) | |||
render_opts = %{ | |||
relationships: opts[:relationships], | |||
skip_relationships: opts[:skip_relationships] | |||
} | |||
# Note: :relationships contain user mutes (needed for :muted flag in :status) | |||
status_render_opts = %{relationships: opts[:relationships]} | |||
with %{id: _} = account <- | |||
AccountView.render( | |||
"show.json", | |||
Map.merge(render_opts, %{user: actor, for: reading_user}) | |||
%{user: actor, for: reading_user} | |||
) do | |||
response = %{ | |||
id: to_string(notification.id), | |||
@@ -105,21 +101,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do | |||
case mastodon_type do | |||
"mention" -> | |||
put_status(response, activity, reading_user, render_opts) | |||
put_status(response, activity, reading_user, status_render_opts) | |||
"favourite" -> | |||
put_status(response, parent_activity_fn.(), reading_user, render_opts) | |||
put_status(response, parent_activity_fn.(), reading_user, status_render_opts) | |||
"reblog" -> | |||
put_status(response, parent_activity_fn.(), reading_user, render_opts) | |||
put_status(response, parent_activity_fn.(), reading_user, status_render_opts) | |||
"move" -> | |||
# Note: :skip_relationships option being applied to _account_ rendering (here) | |||
put_target(response, activity, reading_user, render_opts) | |||
put_target(response, activity, reading_user, %{}) | |||
"pleroma:emoji_reaction" -> | |||
response | |||
|> put_status(parent_activity_fn.(), reading_user, render_opts) | |||
|> put_status(parent_activity_fn.(), reading_user, status_render_opts) | |||
|> put_emoji(activity) | |||
type when type in ["follow", "follow_request"] -> | |||
@@ -107,9 +107,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do | |||
|> Enum.map(&get_user(&1.data["actor"], false)) | |||
|> Enum.filter(& &1) | |||
UserRelationship.view_relationships_option(reading_user, actors, | |||
source_mutes_only: opts[:skip_relationships] | |||
) | |||
UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes) | |||
end | |||
opts = | |||
@@ -162,9 +160,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do | |||
account: | |||
AccountView.render("show.json", %{ | |||
user: user, | |||
for: opts[:for], | |||
relationships: opts[:relationships], | |||
skip_relationships: opts[:skip_relationships] | |||
for: opts[:for] | |||
}), | |||
in_reply_to_id: nil, | |||
in_reply_to_account_id: nil, | |||
@@ -330,9 +326,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do | |||
account: | |||
AccountView.render("show.json", %{ | |||
user: user, | |||
for: opts[:for], | |||
relationships: opts[:relationships], | |||
skip_relationships: opts[:skip_relationships] | |||
for: opts[:for] | |||
}), | |||
in_reply_to_id: reply_to && to_string(reply_to.id), | |||
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id), | |||
@@ -5,6 +5,7 @@ | |||
defmodule Pleroma.Web.MongooseIM.MongooseIMController do | |||
use Pleroma.Web, :controller | |||
alias Pleroma.Plugs.AuthenticationPlug | |||
alias Pleroma.Plugs.RateLimiter | |||
alias Pleroma.Repo | |||
alias Pleroma.User | |||
@@ -27,7 +28,7 @@ defmodule Pleroma.Web.MongooseIM.MongooseIMController 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.verify_pass(password, password_hash) do | |||
true <- AuthenticationPlug.checkpw(password, password_hash) do | |||
conn | |||
|> json(true) | |||
else | |||
@@ -6,7 +6,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do | |||
use Pleroma.Web, :controller | |||
import Pleroma.Web.ControllerHelper, | |||
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2, skip_relationships?: 1] | |||
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2] | |||
alias Ecto.Changeset | |||
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug | |||
@@ -19,6 +19,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 @@ defmodule Pleroma.Web.PleromaAPI.AccountController 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 @@ defmodule Pleroma.Web.PleromaAPI.AccountController 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 @@ defmodule Pleroma.Web.PleromaAPI.AccountController 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 @@ defmodule Pleroma.Web.PleromaAPI.AccountController 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 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do | |||
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) | |||
@@ -139,8 +149,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: for_user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
end | |||
@@ -5,7 +5,7 @@ | |||
defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do | |||
use Pleroma.Web, :controller | |||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, skip_relationships?: 1] | |||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] | |||
alias Pleroma.Activity | |||
alias Pleroma.Conversation.Participation | |||
@@ -69,7 +69,12 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do | |||
%{ | |||
name: emoji, | |||
count: length(users), | |||
accounts: AccountView.render("index.json", %{users: users, for: user, as: :user}), | |||
accounts: | |||
AccountView.render("index.json", %{ | |||
users: users, | |||
for: user, | |||
as: :user | |||
}), | |||
me: !!(user && user.ap_id in user_ap_ids) | |||
} | |||
end | |||
@@ -145,8 +150,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do | |||
|> render("index.json", | |||
activities: activities, | |||
for: user, | |||
as: :activity, | |||
skip_relationships: skip_relationships?(params) | |||
as: :activity | |||
) | |||
else | |||
_error -> | |||
@@ -201,7 +205,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do | |||
end | |||
end | |||
def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => max_id} = params) do | |||
def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => max_id}) do | |||
with notifications <- Notification.set_read_up_to(user, max_id) do | |||
notifications = Enum.take(notifications, 80) | |||
@@ -209,8 +213,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do | |||
|> put_view(NotificationView) | |||
|> render("index.json", | |||
notifications: notifications, | |||
for: user, | |||
skip_relationships: skip_relationships?(params) | |||
for: user | |||
) | |||
end | |||
end | |||
@@ -403,6 +403,7 @@ defmodule Pleroma.Web.Router do | |||
post("/markers", MarkerController, :upsert) | |||
post("/media", MediaController, :create) | |||
get("/media/:id", MediaController, :show) | |||
put("/media/:id", MediaController, :update) | |||
get("/notifications", NotificationController, :index) | |||
@@ -497,6 +498,8 @@ defmodule Pleroma.Web.Router do | |||
scope "/api/v2", Pleroma.Web.MastodonAPI do | |||
pipe_through(:api) | |||
get("/search", SearchController, :search2) | |||
post("/media", MediaController, :create2) | |||
end | |||
scope "/api", Pleroma.Web do | |||
@@ -127,6 +127,7 @@ defmodule Pleroma.Mixfile do | |||
{:oban, "~> 1.2"}, | |||
{:gettext, "~> 0.15"}, | |||
{:pbkdf2_elixir, "~> 1.0"}, | |||
{:bcrypt_elixir, "~> 2.0"}, | |||
{:trailing_format_plug, "~> 0.0.7"}, | |||
{:fast_sanitize, "~> 0.1"}, | |||
{:html_entities, "~> 0.5", override: true}, | |||
@@ -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"}, | |||
@@ -29,6 +30,7 @@ | |||
"ecto": {:hex, :ecto, "3.4.0", "a7a83ab8359bf816ce729e5e65981ce25b9fc5adfc89c2ea3980f4fed0bfd7c1", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "5eed18252f5b5bbadec56a24112b531343507dbe046273133176b12190ce19cc"}, | |||
"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"}, | |||
"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"}, | |||
@@ -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 | |||
#, elixir-format | |||
msgid "Failed to authenticate: %{message}." | |||
msgstr "Échec de l'authentification: %{message}" | |||
msgstr "Échec de l'authentification : %{message}." | |||
#, elixir-format | |||
#: 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 | |||
#, elixir-format | |||
msgid "Insufficient permissions: %{permissions}." | |||
msgstr "Permissions insuffisantes: %{permissions}." | |||
msgstr "Permissions insuffisantes : %{permissions}." | |||
#, elixir-format | |||
#: 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 | |||
#, elixir-format | |||
msgid "This action is outside the authorized scopes" | |||
msgstr "Cette action est en dehors des authorisations" # "scopes" ? | |||
msgstr "Cette action est en dehors des authorisations" # "scopes" | |||
#, elixir-format | |||
#: 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 | |||
#, elixir-format | |||
msgid "Uploader callback timeout" | |||
msgstr "" | |||
## msgstr "Attente écoulée" | |||
msgstr "Temps d'attente du téléverseur écoulé" | |||
#, elixir-format | |||
## 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" |
@@ -0,0 +1,578 @@ | |||
msgid "" | |||
msgstr "" | |||
"Project-Id-Version: PACKAGE VERSION\n" | |||
"Report-Msgid-Bugs-To: \n" | |||
"POT-Creation-Date: 2020-05-15 09:37+0000\n" | |||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | |||
"Last-Translator: Automatically generated\n" | |||
"Language-Team: none\n" | |||
"Language: nl\n" | |||
"MIME-Version: 1.0\n" | |||
"Content-Type: text/plain; charset=UTF-8\n" | |||
"Content-Transfer-Encoding: 8bit\n" | |||
"X-Generator: Translate Toolkit 2.5.1\n" | |||
## This file is a PO Template file. | |||
## | |||
## `msgid`s here are often extracted from source code. | |||
## Add new translations manually only if they're dynamic | |||
## translations that can't be statically extracted. | |||
## | |||
## Run `mix gettext.extract` to bring this file up to | |||
## date. Leave `msgstr`s empty as changing them here as no | |||
## effect: edit them in PO (`.po`) files instead. | |||
## 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 "" | |||
#: lib/pleroma/web/common_api/common_api.ex:421 | |||
#, elixir-format | |||
msgid "Account not found" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:249 | |||
#, elixir-format | |||
msgid "Already voted" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:360 | |||
#, elixir-format | |||
msgid "Bad request" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:425 | |||
#, elixir-format | |||
msgid "Can't delete object" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:196 | |||
#, elixir-format | |||
msgid "Can't delete this post" | |||
msgstr "" | |||
#: lib/pleroma/web/controller_helper.ex:95 | |||
#: lib/pleroma/web/controller_helper.ex:101 | |||
#, elixir-format | |||
msgid "Can't display this activity" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:227 | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:254 | |||
#, elixir-format | |||
msgid "Can't find user" | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:114 | |||
#, elixir-format | |||
msgid "Can't get favorites" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:437 | |||
#, elixir-format | |||
msgid "Can't like object" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:556 | |||
#, elixir-format | |||
msgid "Cannot post an empty status without attachments" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:504 | |||
#, elixir-format | |||
msgid "Comment must be up to %{max_size} characters" | |||
msgstr "" | |||
#: lib/pleroma/config/config_db.ex:222 | |||
#, elixir-format | |||
msgid "Config with params %{params} not found" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:95 | |||
#, elixir-format | |||
msgid "Could not delete" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:141 | |||
#, elixir-format | |||
msgid "Could not favorite" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:370 | |||
#, elixir-format | |||
msgid "Could not pin" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:112 | |||
#, elixir-format | |||
msgid "Could not repeat" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:188 | |||
#, elixir-format | |||
msgid "Could not unfavorite" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:380 | |||
#, elixir-format | |||
msgid "Could not unpin" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:126 | |||
#, elixir-format | |||
msgid "Could not unrepeat" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:428 | |||
#: lib/pleroma/web/common_api/common_api.ex:437 | |||
#, elixir-format | |||
msgid "Could not update state" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:202 | |||
#, elixir-format | |||
msgid "Error." | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:106 | |||
#, elixir-format | |||
msgid "Invalid CAPTCHA" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:117 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:569 | |||
#, elixir-format | |||
msgid "Invalid credentials" | |||
msgstr "" | |||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 | |||
#, elixir-format | |||
msgid "Invalid credentials." | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:265 | |||
#, elixir-format | |||
msgid "Invalid indices" | |||
msgstr "" | |||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:1147 | |||
#, elixir-format | |||
msgid "Invalid parameters" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:411 | |||
#, elixir-format | |||
msgid "Invalid password." | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:187 | |||
#, elixir-format | |||
msgid "Invalid request" | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:109 | |||
#, elixir-format | |||
msgid "Kocaptcha service unavailable" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:113 | |||
#, elixir-format | |||
msgid "Missing parameters" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:540 | |||
#, elixir-format | |||
msgid "No such conversation" | |||
msgstr "" | |||
#: 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 | |||
#, elixir-format | |||
msgid "No such permission_group" | |||
msgstr "" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Not found" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:241 | |||
#, elixir-format | |||
msgid "Poll's author can't vote" | |||
msgstr "" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Record not found" | |||
msgstr "" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Something went wrong" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/activity_draft.ex:107 | |||
#, elixir-format | |||
msgid "The message visibility must be direct" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:566 | |||
#, elixir-format | |||
msgid "The status is over the character limit" | |||
msgstr "" | |||
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 | |||
#, elixir-format | |||
msgid "This resource requires authentication." | |||
msgstr "" | |||
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 | |||
#, elixir-format | |||
msgid "Throttled" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:266 | |||
#, elixir-format | |||
msgid "Too many choices" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:442 | |||
#, elixir-format | |||
msgid "Unhandled activity type" | |||
msgstr "" | |||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:536 | |||
#, elixir-format | |||
msgid "You can't revoke your own admin status." | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:218 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:309 | |||
#, elixir-format | |||
msgid "Your account is currently disabled" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:180 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:332 | |||
#, elixir-format | |||
msgid "Your login is missing a confirmed e-mail address" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:389 | |||
#, elixir-format | |||
msgid "can't read inbox of %{nickname} as %{as_nickname}" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:472 | |||
#, elixir-format | |||
msgid "can't update outbox of %{nickname} as %{as_nickname}" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:388 | |||
#, elixir-format | |||
msgid "conversation is already muted" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:316 | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:491 | |||
#, elixir-format | |||
msgid "error" | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:29 | |||
#, elixir-format | |||
msgid "mascots can only be images" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:60 | |||
#, elixir-format | |||
msgid "not found" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:395 | |||
#, elixir-format | |||
msgid "Bad OAuth request." | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:115 | |||
#, elixir-format | |||
msgid "CAPTCHA already used" | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:112 | |||
#, elixir-format | |||
msgid "CAPTCHA expired" | |||
msgstr "" | |||
#: lib/pleroma/plugs/uploaded_media.ex:55 | |||
#, elixir-format | |||
msgid "Failed" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:411 | |||
#, elixir-format | |||
msgid "Failed to authenticate: %{message}." | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:442 | |||
#, elixir-format | |||
msgid "Failed to set up user account." | |||
msgstr "" | |||
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 | |||
#, elixir-format | |||
msgid "Insufficient permissions: %{permissions}." | |||
msgstr "" | |||
#: lib/pleroma/plugs/uploaded_media.ex:94 | |||
#, elixir-format | |||
msgid "Internal Error" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/fallback_controller.ex:22 | |||
#: lib/pleroma/web/oauth/fallback_controller.ex:29 | |||
#, elixir-format | |||
msgid "Invalid Username/Password" | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:118 | |||
#, elixir-format | |||
msgid "Invalid answer data" | |||
msgstr "" | |||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:128 | |||
#, elixir-format | |||
msgid "Nodeinfo schema version not handled" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:169 | |||
#, elixir-format | |||
msgid "This action is outside the authorized scopes" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/fallback_controller.ex:14 | |||
#, elixir-format | |||
msgid "Unknown error, please check the details and try again." | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:116 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:155 | |||
#, elixir-format | |||
msgid "Unlisted redirect_uri." | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:391 | |||
#, elixir-format | |||
msgid "Unsupported OAuth provider: %{provider}." | |||
msgstr "" | |||
#: lib/pleroma/uploaders/uploader.ex:72 | |||
#, elixir-format | |||
msgid "Uploader callback timeout" | |||
msgstr "" | |||
#: lib/pleroma/web/uploader_controller.ex:23 | |||
#, elixir-format | |||
msgid "bad request" | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:103 | |||
#, elixir-format | |||
msgid "CAPTCHA Error" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:200 | |||
#, elixir-format | |||
msgid "Could not add reaction emoji" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:211 | |||
#, elixir-format | |||
msgid "Could not remove reaction emoji" | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:129 | |||
#, elixir-format | |||
msgid "Invalid CAPTCHA (Missing parameter: %{name})" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 | |||
#, elixir-format | |||
msgid "List not found" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:124 | |||
#, elixir-format | |||
msgid "Missing parameter: %{name}" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:207 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:322 | |||
#, elixir-format | |||
msgid "Password reset is required" | |||
msgstr "" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." | |||
msgstr "" | |||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 | |||
#, elixir-format | |||
msgid "Two-factor authentication enabled, you must use a access token." | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:210 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while adding file to pack." | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:138 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while creating pack." | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:278 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while removing file from pack." | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:250 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while updating file in pack." | |||
msgstr "" | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:179 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while updating pack metadata." | |||
msgstr "" | |||
#: lib/pleroma/plugs/user_is_admin_plug.ex:40 | |||
#, elixir-format | |||
msgid "User is not an admin or OAuth admin scope is not granted." | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 | |||
#, elixir-format | |||
msgid "Web push subscription is disabled on this Pleroma instance" | |||
msgstr "" | |||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:502 | |||
#, elixir-format | |||
msgid "You can't revoke your own admin/moderator status." | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:105 | |||
#, elixir-format | |||
msgid "authorization required for timeline view" | |||
msgstr "" |
@@ -0,0 +1,587 @@ | |||
msgid "" | |||
msgstr "" | |||
"Project-Id-Version: PACKAGE VERSION\n" | |||
"Report-Msgid-Bugs-To: \n" | |||
"POT-Creation-Date: 2020-05-13 16:37+0000\n" | |||
"PO-Revision-Date: 2020-05-16 17:13+0000\n" | |||
"Last-Translator: Jędrzej Tomaszewski <jederow@hotmail.com>\n" | |||
"Language-Team: Polish <https://translate.pleroma.social/projects/pleroma/" | |||
"pleroma/pl/>\n" | |||
"Language: pl\n" | |||
"MIME-Version: 1.0\n" | |||
"Content-Type: text/plain; charset=UTF-8\n" | |||
"Content-Transfer-Encoding: 8bit\n" | |||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " | |||
"|| n%100>=20) ? 1 : 2;\n" | |||
"X-Generator: Weblate 4.0.4\n" | |||
## This file is a PO Template file. | |||
## | |||
## `msgid`s here are often extracted from source code. | |||
## Add new translations manually only if they're dynamic | |||
## translations that can't be statically extracted. | |||
## | |||
## Run `mix gettext.extract` to bring this file up to | |||
## date. Leave `msgstr`s empty as changing them here as no | |||
## effect: edit them in PO (`.po`) files instead. | |||
## From Ecto.Changeset.cast/4 | |||
msgid "can't be blank" | |||
msgstr "nie może być pusty" | |||
## From Ecto.Changeset.unique_constraint/3 | |||
msgid "has already been taken" | |||
msgstr "jest już zajęty" | |||
## From Ecto.Changeset.put_change/3 | |||
msgid "is invalid" | |||
msgstr "jest nieprawidłowy" | |||
## From Ecto.Changeset.validate_format/3 | |||
msgid "has invalid format" | |||
msgstr "ma niepoprawny format" | |||
## From Ecto.Changeset.validate_subset/3 | |||
msgid "has an invalid entry" | |||
msgstr "ma niepoprawny wpis" | |||
## From Ecto.Changeset.validate_exclusion/3 | |||
msgid "is reserved" | |||
msgstr "jest zarezerwowany" | |||
## 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 "jest wciąż powiązane z tym wpisem" | |||
msgid "are still associated with this entry" | |||
msgstr "są wciąż powiązane z tym wpisem" | |||
## From Ecto.Changeset.validate_length/3 | |||
msgid "should be %{count} character(s)" | |||
msgid_plural "should be %{count} character(s)" | |||
msgstr[0] "powinno mieć %{count} znak" | |||
msgstr[1] "powinno mieć %{count} znaki" | |||
msgstr[2] "powinno mieć %{count} znaków" | |||
msgid "should have %{count} item(s)" | |||
msgid_plural "should have %{count} item(s)" | |||
msgstr[0] "" | |||
msgstr[1] "" | |||
msgstr[2] "" | |||
msgid "should be at least %{count} character(s)" | |||
msgid_plural "should be at least %{count} character(s)" | |||
msgstr[0] "" | |||
msgstr[1] "" | |||
msgstr[2] "" | |||
msgid "should have at least %{count} item(s)" | |||
msgid_plural "should have at least %{count} item(s)" | |||
msgstr[0] "" | |||
msgstr[1] "" | |||
msgstr[2] "" | |||
msgid "should be at most %{count} character(s)" | |||
msgid_plural "should be at most %{count} character(s)" | |||
msgstr[0] "" | |||
msgstr[1] "" | |||
msgstr[2] "" | |||
msgid "should have at most %{count} item(s)" | |||
msgid_plural "should have at most %{count} item(s)" | |||
msgstr[0] "" | |||
msgstr[1] "" | |||
msgstr[2] "" | |||
## 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 "" | |||
#: lib/pleroma/web/common_api/common_api.ex:421 | |||
#, elixir-format | |||
msgid "Account not found" | |||
msgstr "Nie znaleziono konta" | |||
#: lib/pleroma/web/common_api/common_api.ex:249 | |||
#, elixir-format | |||
msgid "Already voted" | |||
msgstr "Już zagłosowano" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:360 | |||
#, elixir-format | |||
msgid "Bad request" | |||
msgstr "Nieprawidłowe żądanie" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:425 | |||
#, elixir-format | |||
msgid "Can't delete object" | |||
msgstr "Nie można usunąć obiektu" | |||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:196 | |||
#, elixir-format | |||
msgid "Can't delete this post" | |||
msgstr "Nie udało się usunąć tego statusu" | |||
#: lib/pleroma/web/controller_helper.ex:95 | |||
#: lib/pleroma/web/controller_helper.ex:101 | |||
#, elixir-format | |||
msgid "Can't display this activity" | |||
msgstr "Nie można wyświetlić tej aktywności" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:227 | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:254 | |||
#, elixir-format | |||
msgid "Can't find user" | |||
msgstr "Nie znaleziono użytkownika" | |||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:114 | |||
#, elixir-format | |||
msgid "Can't get favorites" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:437 | |||
#, elixir-format | |||
msgid "Can't like object" | |||
msgstr "Nie udało się polubić obiektu" | |||
#: lib/pleroma/web/common_api/utils.ex:556 | |||
#, elixir-format | |||
msgid "Cannot post an empty status without attachments" | |||
msgstr "Nie można opublikować pustego statusu bez załączników" | |||
#: lib/pleroma/web/common_api/utils.ex:504 | |||
#, elixir-format | |||
msgid "Comment must be up to %{max_size} characters" | |||
msgstr "Komentarz może mieć co najwyżej %{max_size} znaków" | |||
#: lib/pleroma/config/config_db.ex:222 | |||
#, elixir-format | |||
msgid "Config with params %{params} not found" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:95 | |||
#, elixir-format | |||
msgid "Could not delete" | |||
msgstr "Nie udało się usunąć" | |||
#: lib/pleroma/web/common_api/common_api.ex:141 | |||
#, elixir-format | |||
msgid "Could not favorite" | |||
msgstr "Nie udało się dodać do ulubionych" | |||
#: lib/pleroma/web/common_api/common_api.ex:370 | |||
#, elixir-format | |||
msgid "Could not pin" | |||
msgstr "Nie udało się przypiąć" | |||
#: lib/pleroma/web/common_api/common_api.ex:112 | |||
#, elixir-format | |||
msgid "Could not repeat" | |||
msgstr "Nie udało się powtórzyć" | |||
#: lib/pleroma/web/common_api/common_api.ex:188 | |||
#, elixir-format | |||
msgid "Could not unfavorite" | |||
msgstr "Nie udało się usunąć z ulubionych" | |||
#: lib/pleroma/web/common_api/common_api.ex:380 | |||
#, elixir-format | |||
msgid "Could not unpin" | |||
msgstr "Nie udało się odpiąć" | |||
#: lib/pleroma/web/common_api/common_api.ex:126 | |||
#, elixir-format | |||
msgid "Could not unrepeat" | |||
msgstr "Nie udało się cofnąć powtórzenia" | |||
#: lib/pleroma/web/common_api/common_api.ex:428 | |||
#: lib/pleroma/web/common_api/common_api.ex:437 | |||
#, elixir-format | |||
msgid "Could not update state" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:202 | |||
#, elixir-format | |||
msgid "Error." | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:106 | |||
#, elixir-format | |||
msgid "Invalid CAPTCHA" | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:117 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:569 | |||
#, elixir-format | |||
msgid "Invalid credentials" | |||
msgstr "" | |||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 | |||
#, elixir-format | |||
msgid "Invalid credentials." | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:265 | |||
#, elixir-format | |||
msgid "Invalid indices" | |||
msgstr "" | |||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:1147 | |||
#, elixir-format | |||
msgid "Invalid parameters" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:411 | |||
#, elixir-format | |||
msgid "Invalid password." | |||
msgstr "Nieprawidłowe hasło." | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:187 | |||
#, elixir-format | |||
msgid "Invalid request" | |||
msgstr "Nieprawidłowe żądanie" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:109 | |||
#, elixir-format | |||
msgid "Kocaptcha service unavailable" | |||
msgstr "Usługa Kocaptcha niedostępna" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:113 | |||
#, elixir-format | |||
msgid "Missing parameters" | |||
msgstr "Brakujące parametry" | |||
#: lib/pleroma/web/common_api/utils.ex:540 | |||
#, elixir-format | |||
msgid "No such conversation" | |||
msgstr "Nie ma takiej rozmowy" | |||
#: 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 | |||
#, elixir-format | |||
msgid "No such permission_group" | |||
msgstr "Nie ma takiej grupy uprawnień" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Not found" | |||
msgstr "Nie znaleziono" | |||
#: lib/pleroma/web/common_api/common_api.ex:241 | |||
#, elixir-format | |||
msgid "Poll's author can't vote" | |||
msgstr "Autor ankiety nie może głosować" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Record not found" | |||
msgstr "Nie znaleziono rekordu" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Something went wrong" | |||
msgstr "Coś się zepsuło" | |||
#: lib/pleroma/web/common_api/activity_draft.ex:107 | |||
#, elixir-format | |||
msgid "The message visibility must be direct" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/utils.ex:566 | |||
#, elixir-format | |||
msgid "The status is over the character limit" | |||
msgstr "Ten status przekracza limit znaków" | |||
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 | |||
#, elixir-format | |||
msgid "This resource requires authentication." | |||
msgstr "" | |||
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 | |||
#, elixir-format | |||
msgid "Throttled" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:266 | |||
#, elixir-format | |||
msgid "Too many choices" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:442 | |||
#, elixir-format | |||
msgid "Unhandled activity type" | |||
msgstr "Nieobsługiwany typ aktywności" | |||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:536 | |||
#, elixir-format | |||
msgid "You can't revoke your own admin status." | |||
msgstr "Nie możesz odebrać samemu sobie statusu administratora." | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:218 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:309 | |||
#, elixir-format | |||
msgid "Your account is currently disabled" | |||
msgstr "Twoje konto jest obecnie nieaktywne" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:180 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:332 | |||
#, elixir-format | |||
msgid "Your login is missing a confirmed e-mail address" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:389 | |||
#, elixir-format | |||
msgid "can't read inbox of %{nickname} as %{as_nickname}" | |||
msgstr "" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:472 | |||
#, elixir-format | |||
msgid "can't update outbox of %{nickname} as %{as_nickname}" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:388 | |||
#, elixir-format | |||
msgid "conversation is already muted" | |||
msgstr "rozmowa jest już wyciszona" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:316 | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:491 | |||
#, elixir-format | |||
msgid "error" | |||
msgstr "błąd" | |||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:29 | |||
#, elixir-format | |||
msgid "mascots can only be images" | |||
msgstr "maskotki muszą być obrazkami" | |||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:60 | |||
#, elixir-format | |||
msgid "not found" | |||
msgstr "nie znaleziono" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:395 | |||
#, elixir-format | |||
msgid "Bad OAuth request." | |||
msgstr "Niepoprawne żądanie OAuth." | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:115 | |||
#, elixir-format | |||
msgid "CAPTCHA already used" | |||
msgstr "Zużyta CAPTCHA" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:112 | |||
#, elixir-format | |||
msgid "CAPTCHA expired" | |||
msgstr "CAPTCHA wygasła" | |||
#: lib/pleroma/plugs/uploaded_media.ex:55 | |||
#, elixir-format | |||
msgid "Failed" | |||
msgstr "Nie udało się" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:411 | |||
#, elixir-format | |||
msgid "Failed to authenticate: %{message}." | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:442 | |||
#, elixir-format | |||
msgid "Failed to set up user account." | |||
msgstr "" | |||
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 | |||
#, elixir-format | |||
msgid "Insufficient permissions: %{permissions}." | |||
msgstr "Niewystarczające uprawnienia: %{permissions}." | |||
#: lib/pleroma/plugs/uploaded_media.ex:94 | |||
#, elixir-format | |||
msgid "Internal Error" | |||
msgstr "Błąd wewnętrzny" | |||
#: lib/pleroma/web/oauth/fallback_controller.ex:22 | |||
#: lib/pleroma/web/oauth/fallback_controller.ex:29 | |||
#, elixir-format | |||
msgid "Invalid Username/Password" | |||
msgstr "Nieprawidłowa nazwa użytkownika lub hasło" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:118 | |||
#, elixir-format | |||
msgid "Invalid answer data" | |||
msgstr "" | |||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:128 | |||
#, elixir-format | |||
msgid "Nodeinfo schema version not handled" | |||
msgstr "Nieobsługiwana wersja schematu Nodeinfo" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:169 | |||
#, elixir-format | |||
msgid "This action is outside the authorized scopes" | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/fallback_controller.ex:14 | |||
#, elixir-format | |||
msgid "Unknown error, please check the details and try again." | |||
msgstr "Nieznany błąd, sprawdź szczegóły i spróbuj ponownie." | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:116 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:155 | |||
#, elixir-format | |||
msgid "Unlisted redirect_uri." | |||
msgstr "" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:391 | |||
#, elixir-format | |||
msgid "Unsupported OAuth provider: %{provider}." | |||
msgstr "Nieobsługiwany dostawca OAuth: %{provider}." | |||
#: lib/pleroma/uploaders/uploader.ex:72 | |||
#, elixir-format | |||
msgid "Uploader callback timeout" | |||
msgstr "" | |||
#: lib/pleroma/web/uploader_controller.ex:23 | |||
#, elixir-format | |||
msgid "bad request" | |||
msgstr "nieprawidłowe żądanie" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:103 | |||
#, elixir-format | |||
msgid "CAPTCHA Error" | |||
msgstr "Błąd CAPTCHA" | |||
#: lib/pleroma/web/common_api/common_api.ex:200 | |||
#, elixir-format | |||
msgid "Could not add reaction emoji" | |||
msgstr "" | |||
#: lib/pleroma/web/common_api/common_api.ex:211 | |||
#, elixir-format | |||
msgid "Could not remove reaction emoji" | |||
msgstr "" | |||
#: lib/pleroma/web/twitter_api/twitter_api.ex:129 | |||
#, elixir-format | |||
msgid "Invalid CAPTCHA (Missing parameter: %{name})" | |||
msgstr "Nieprawidłowa CAPTCHA (Brakujący parametr: %{name})" | |||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 | |||
#, elixir-format | |||
msgid "List not found" | |||
msgstr "Nie znaleziono listy" | |||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:124 | |||
#, elixir-format | |||
msgid "Missing parameter: %{name}" | |||
msgstr "Brakujący parametr: %{name}" | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:207 | |||
#: lib/pleroma/web/oauth/oauth_controller.ex:322 | |||
#, elixir-format | |||
msgid "Password reset is required" | |||
msgstr "Wymagany reset hasła" | |||
#: 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 | |||
#, elixir-format | |||
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." | |||
msgstr "" | |||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 | |||
#, elixir-format | |||
msgid "Two-factor authentication enabled, you must use a access token." | |||
msgstr "Uwierzytelnienie dwuskładnikowe jest włączone, musisz użyć tokenu." | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:210 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while adding file to pack." | |||
msgstr "Nieoczekiwany błąd podczas dodawania pliku do paczki." | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:138 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while creating pack." | |||
msgstr "Nieoczekiwany błąd podczas tworzenia paczki." | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:278 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while removing file from pack." | |||
msgstr "Nieoczekiwany błąd podczas usuwania pliku z paczki." | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:250 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while updating file in pack." | |||
msgstr "Nieoczekiwany błąd podczas zmieniania pliku w paczce." | |||
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:179 | |||
#, elixir-format | |||
msgid "Unexpected error occurred while updating pack metadata." | |||
msgstr "Nieoczekiwany błąd podczas zmieniania metadanych paczki." | |||
#: lib/pleroma/plugs/user_is_admin_plug.ex:40 | |||
#, elixir-format | |||
msgid "User is not an admin or OAuth admin scope is not granted." | |||
msgstr "" | |||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 | |||
#, elixir-format | |||
msgid "Web push subscription is disabled on this Pleroma instance" | |||
msgstr "Powiadomienia web push są wyłączone na tej instancji Pleromy" | |||
#: lib/pleroma/web/admin_api/admin_api_controller.ex:502 | |||
#, elixir-format | |||
msgid "You can't revoke your own admin/moderator status." | |||
msgstr "Nie możesz odebrać samemu sobie statusu administratora/moderatora." | |||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:105 | |||
#, elixir-format | |||
msgid "authorization required for timeline view" | |||
msgstr "logowanie wymagane do przeglądania osi czasu" |
@@ -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.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> | |||
<!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.1589385935077.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.838ffa9aecf210c7d744.js></script></body></html> |
@@ -1,23 +1,28 @@ | |||
{ | |||
"theme": "pleroma-dark", | |||
"alwaysShowSubjectInput": true, | |||
"background": "/static/aurora_borealis.jpg", | |||
"logo": "/static/logo.png", | |||
"logoMask": true, | |||
"logoMargin": ".1em", | |||
"redirectRootNoLogin": "/main/all", | |||
"redirectRootLogin": "/main/friends", | |||
"showInstanceSpecificPanel": false, | |||
"collapseMessageWithSubject": false, | |||
"scopeCopy": true, | |||
"subjectLineBehavior": "email", | |||
"postContentType": "text/plain", | |||
"alwaysShowSubjectInput": true, | |||
"disableChat": false, | |||
"greentext": false, | |||
"hideFilteredStatuses": false, | |||
"hideMutedPosts": false, | |||
"hidePostStats": false, | |||
"hideSitename": false, | |||
"hideUserStats": false, | |||
"loginMethod": "password", | |||
"webPushNotifications": false, | |||
"logo": "/static/logo.png", | |||
"logoMargin": ".1em", | |||
"logoMask": true, | |||
"minimalScopesMode": false, | |||
"noAttachmentLinks": false, | |||
"nsfwCensorImage": "", | |||
"postContentType": "text/plain", | |||
"redirectRootLogin": "/main/friends", | |||
"redirectRootNoLogin": "/main/all", | |||
"scopeCopy": true, | |||
"showFeaturesPanel": true, | |||
"minimalScopesMode": false | |||
"showInstanceSpecificPanel": false, | |||
"subjectLineBehavior": "email", | |||
"theme": "pleroma-dark", | |||
"webPushNotifications": false | |||
} |
@@ -1,11 +1,11 @@ | |||
@font-face { | |||
font-family: "Icons"; | |||
src: url("./font/fontello.1588947937982.eot"); | |||
src: url("./font/fontello.1588947937982.eot") format("embedded-opentype"), | |||
url("./font/fontello.1588947937982.woff2") format("woff2"), | |||
url("./font/fontello.1588947937982.woff") format("woff"), | |||
url("./font/fontello.1588947937982.ttf") format("truetype"), | |||
url("./font/fontello.1588947937982.svg") format("svg"); | |||
src: url("./font/fontello.1589385935077.eot"); | |||
src: url("./font/fontello.1589385935077.eot") format("embedded-opentype"), | |||
url("./font/fontello.1589385935077.woff2") format("woff2"), | |||
url("./font/fontello.1589385935077.woff") format("woff"), | |||
url("./font/fontello.1589385935077.ttf") format("truetype"), | |||
url("./font/fontello.1589385935077.svg") format("svg"); | |||
font-weight: normal; | |||
font-style: normal; | |||
} |
@@ -1,4 +1,4 @@ | |||
var serviceWorkerOption = {"assets":["/static/fontello.1588947937982.css","/static/font/fontello.1588947937982.eot","/static/font/fontello.1588947937982.svg","/static/font/fontello.1588947937982.ttf","/static/font/fontello.1588947937982.woff","/static/font/fontello.1588947937982.woff2","/static/img/nsfw.74818f9.png","/static/css/app.613cef07981cd95ccceb.css","/static/js/app.996428ccaaaa7f28cb8d.js","/static/css/vendors~app.18fea621d430000acc27.css","/static/js/vendors~app.561a1c605d1dfb0e6f74.js","/static/js/2.18e4adec273c4ce867a8.js"]}; | |||
var serviceWorkerOption = {"assets":["/static/fontello.1589385935077.css","/static/font/fontello.1589385935077.eot","/static/font/fontello.1589385935077.svg","/static/font/fontello.1589385935077.ttf","/static/font/fontello.1589385935077.woff","/static/font/fontello.1589385935077.woff2","/static/img/nsfw.74818f9.png","/static/css/app.613cef07981cd95ccceb.css","/static/js/app.838ffa9aecf210c7d744.js","/static/css/vendors~app.18fea621d430000acc27.css","/static/js/vendors~app.561a1c605d1dfb0e6f74.js","/static/js/2.18e4adec273c4ce867a8.js"]}; | |||
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=1)}([function(e,n){ | |||
/*! | |||
@@ -476,6 +476,14 @@ defmodule Pleroma.ConfigDBTest do | |||
assert ConfigDB.from_binary(binary) == [key: "value"] | |||
end | |||
test "keyword with partial_chain key" do | |||
binary = | |||
ConfigDB.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}]) | |||
assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1) | |||
assert ConfigDB.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1] | |||
end | |||
test "keyword" do | |||
binary = | |||
ConfigDB.transform([ | |||
@@ -11,6 +11,7 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do | |||
alias Pleroma.User | |||
import ExUnit.CaptureLog | |||
import Pleroma.Factory | |||
setup %{conn: conn} do | |||
user = %User{ | |||
@@ -50,16 +51,41 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do | |||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug) | |||
end | |||
test "with a wrong password in the credentials, it does nothing", %{conn: conn} do | |||
test "with a bcrypt hash, it updates to a pkbdf2 hash", %{conn: conn} do | |||
user = insert(:user, password_hash: Bcrypt.hash_pwd_salt("123")) | |||
assert "$2" <> _ = user.password_hash | |||
conn = | |||
conn | |||
|> assign(:auth_credentials, %{password: "wrong"}) | |||
|> assign(:auth_user, user) | |||
|> assign(:auth_credentials, %{password: "123"}) | |||
|> AuthenticationPlug.call(%{}) | |||
ret_conn = | |||
assert conn.assigns.user.id == conn.assigns.auth_user.id | |||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug) | |||
user = User.get_by_id(user.id) | |||
assert "$pbkdf2" <> _ = user.password_hash | |||
end | |||
test "with a crypt hash, it updates to a pkbdf2 hash", %{conn: conn} do | |||
user = | |||
insert(:user, | |||
password_hash: | |||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1" | |||
) | |||
conn = | |||
conn | |||
|> assign(:auth_user, user) | |||
|> assign(:auth_credentials, %{password: "password"}) | |||
|> AuthenticationPlug.call(%{}) | |||
assert conn == ret_conn | |||
assert conn.assigns.user.id == conn.assigns.auth_user.id | |||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug) | |||
user = User.get_by_id(user.id) | |||
assert "$pbkdf2" <> _ = user.password_hash | |||
end | |||
describe "checkpw/2" do | |||
@@ -79,6 +105,13 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest 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" | |||
@@ -951,7 +951,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do | |||
test "works with base64 encoded images" do | |||
file = %{ | |||
"img" => data_uri() | |||
img: data_uri() | |||
} | |||
{:ok, %Object{}} = ActivityPub.upload(file) | |||
@@ -2509,6 +2509,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do | |||
%{"tuple" => [":seconds_valid", 60]}, | |||
%{"tuple" => [":path", ""]}, | |||
%{"tuple" => [":key1", nil]}, | |||
%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}, | |||
%{"tuple" => [":regex1", "~r/https:\/\/example.com/"]}, | |||
%{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]}, | |||
%{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]}, | |||
@@ -2532,6 +2533,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do | |||
%{"tuple" => [":seconds_valid", 60]}, | |||
%{"tuple" => [":path", ""]}, | |||
%{"tuple" => [":key1", nil]}, | |||
%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}, | |||
%{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]}, | |||
%{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]}, | |||
%{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]}, | |||
@@ -2544,6 +2546,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do | |||
":seconds_valid", | |||
":path", | |||
":key1", | |||
":partial_chain", | |||
":regex1", | |||
":regex2", | |||
":regex3", | |||
@@ -2940,6 +2943,33 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do | |||
assert %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]} in value | |||
assert ":proxy_url" in db | |||
end | |||
test "doesn't set keys not in the whitelist", %{conn: conn} do | |||
clear_config(:database_config_whitelist, [ | |||
{:pleroma, :key1}, | |||
{:pleroma, :key2}, | |||
{:pleroma, Pleroma.Captcha.NotReal}, | |||
{:not_real} | |||
]) | |||
post(conn, "/api/pleroma/admin/config", %{ | |||
configs: [ | |||
%{group: ":pleroma", key: ":key1", value: "value1"}, | |||
%{group: ":pleroma", key: ":key2", value: "value2"}, | |||
%{group: ":pleroma", key: ":key3", value: "value3"}, | |||
%{group: ":pleroma", key: "Pleroma.Web.Endpoint.NotReal", value: "value4"}, | |||
%{group: ":pleroma", key: "Pleroma.Captcha.NotReal", value: "value5"}, | |||
%{group: ":not_real", key: ":anything", value: "value6"} | |||
] | |||
}) | |||
assert Application.get_env(:pleroma, :key1) == "value1" | |||
assert Application.get_env(:pleroma, :key2) == "value2" | |||
assert Application.get_env(:pleroma, :key3) == nil | |||
assert Application.get_env(:pleroma, Pleroma.Web.Endpoint.NotReal) == nil | |||
assert Application.get_env(:pleroma, Pleroma.Captcha.NotReal) == "value5" | |||
assert Application.get_env(:not_real, :anything) == "value6" | |||
end | |||
end | |||
describe "GET /api/pleroma/admin/restart" do | |||
@@ -3571,19 +3601,54 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do | |||
end | |||
end | |||
test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do | |||
admin = insert(:user, is_admin: true) | |||
describe "GET /api/pleroma/admin/config/descriptions" do | |||
test "structure", %{conn: conn} do | |||
admin = insert(:user, is_admin: true) | |||
conn = | |||
assign(conn, :user, admin) | |||
|> get("/api/pleroma/admin/config/descriptions") | |||
conn = | |||
assign(conn, :user, admin) | |||
|> get("/api/pleroma/admin/config/descriptions") | |||
assert [child | _others] = json_response(conn, 200) | |||
assert child["children"] | |||
assert child["key"] | |||
assert String.starts_with?(child["group"], ":") | |||
assert child["description"] | |||
end | |||
test "filters by database configuration whitelist", %{conn: conn} do | |||
clear_config(:database_config_whitelist, [ | |||
{:pleroma, :instance}, | |||
{:pleroma, :activitypub}, | |||
{:pleroma, Pleroma.Upload}, | |||
{:esshd} | |||
]) | |||
admin = insert(:user, is_admin: true) | |||
conn = | |||
assign(conn, :user, admin) | |||
|> get("/api/pleroma/admin/config/descriptions") | |||
assert [child | _others] = json_response(conn, 200) | |||
children = json_response(conn, 200) | |||
assert child["children"] | |||
assert child["key"] | |||
assert String.starts_with?(child["group"], ":") | |||
assert child["description"] | |||
assert length(children) == 4 | |||
assert Enum.count(children, fn c -> c["group"] == ":pleroma" end) == 3 | |||
instance = Enum.find(children, fn c -> c["key"] == ":instance" end) | |||
assert instance["children"] | |||
activitypub = Enum.find(children, fn c -> c["key"] == ":activitypub" end) | |||
assert activitypub["children"] | |||
web_endpoint = Enum.find(children, fn c -> c["key"] == "Pleroma.Upload" end) | |||
assert web_endpoint["children"] | |||
esshd = Enum.find(children, fn c -> c["group"] == ":esshd" end) | |||
assert esshd["children"] | |||
end | |||
end | |||
describe "/api/pleroma/admin/stats" do | |||
@@ -15,11 +15,16 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticatorTest do | |||
{:ok, [user: user, name: name, password: password]} | |||
end | |||
test "get_user/authorization", %{user: user, name: name, password: password} do | |||
test "get_user/authorization", %{name: name, password: password} do | |||
name = name <> "1" | |||
user = insert(:user, nickname: name, password_hash: Bcrypt.hash_pwd_salt(password)) | |||
params = %{"authorization" => %{"name" => name, "password" => password}} | |||
res = PleromaAuthenticator.get_user(%Plug.Conn{params: params}) | |||
assert {:ok, user} == res | |||
assert {:ok, returned_user} = res | |||
assert returned_user.id == user.id | |||
assert "$pbkdf2" <> _ = returned_user.password_hash | |||
end | |||
test "get_user/authorization with invalid password", %{name: name} do | |||
@@ -23,6 +23,18 @@ defmodule Pleroma.Web.CommonAPITest do | |||
setup do: clear_config([:instance, :limit]) | |||
setup do: clear_config([:instance, :max_pinned_statuses]) | |||
describe "unblocking" do | |||
test "it works even without an existing block activity" do | |||
blocked = insert(:user) | |||
blocker = insert(:user) | |||
User.block(blocker, blocked) | |||
assert User.blocks?(blocker, blocked) | |||
assert {:ok, :no_activity} == CommonAPI.unblock(blocker, blocked) | |||
refute User.blocks?(blocker, blocked) | |||
end | |||
end | |||
describe "deletion" do | |||
test "it works with pruned objects" do | |||
user = insert(:user) | |||
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do | |||
setup do: oauth_access(["write:media"]) | |||
describe "media upload" do | |||
describe "Upload media" do | |||
setup do | |||
image = %Plug.Upload{ | |||
content_type: "image/jpg", | |||
@@ -25,13 +25,14 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do | |||
setup do: clear_config([:media_proxy]) | |||
setup do: clear_config([Pleroma.Upload]) | |||
test "returns uploaded image", %{conn: conn, image: image} do | |||
test "/api/v1/media", %{conn: conn, image: image} do | |||
desc = "Description of the image" | |||
media = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> post("/api/v1/media", %{"file" => image, "description" => desc}) | |||
|> json_response(:ok) | |||
|> json_response_and_validate_schema(:ok) | |||
assert media["type"] == "image" | |||
assert media["description"] == desc | |||
@@ -40,9 +41,32 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do | |||
object = Object.get_by_id(media["id"]) | |||
assert object.data["actor"] == User.ap_id(conn.assigns[:user]) | |||
end | |||
test "/api/v2/media", %{conn: conn, image: image} do | |||
desc = "Description of the image" | |||
response = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> post("/api/v2/media", %{"file" => image, "description" => desc}) | |||
|> json_response_and_validate_schema(202) | |||
assert media_id = response["id"] | |||
media = | |||
conn | |||
|> get("/api/v1/media/#{media_id}") | |||
|> json_response_and_validate_schema(200) | |||
assert media["type"] == "image" | |||
assert media["description"] == desc | |||
assert media["id"] | |||
object = Object.get_by_id(media["id"]) | |||
assert object.data["actor"] == User.ap_id(conn.assigns[:user]) | |||
end | |||
end | |||
describe "PUT /api/v1/media/:id" do | |||
describe "Update media description" do | |||
setup %{user: actor} do | |||
file = %Plug.Upload{ | |||
content_type: "image/jpg", | |||
@@ -60,23 +84,45 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do | |||
[object: object] | |||
end | |||
test "updates name of media", %{conn: conn, object: object} do | |||
test "/api/v1/media/:id good request", %{conn: conn, object: object} do | |||
media = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> put("/api/v1/media/#{object.id}", %{"description" => "test-media"}) | |||
|> json_response(:ok) | |||
|> json_response_and_validate_schema(:ok) | |||
assert media["description"] == "test-media" | |||
assert refresh_record(object).data["name"] == "test-media" | |||
end | |||
end | |||
test "returns error when request is bad", %{conn: conn, object: object} do | |||
describe "Get media by id" do | |||
setup %{user: actor} do | |||
file = %Plug.Upload{ | |||
content_type: "image/jpg", | |||
path: Path.absname("test/fixtures/image.jpg"), | |||
filename: "an_image.jpg" | |||
} | |||
{:ok, %Object{} = object} = | |||
ActivityPub.upload( | |||
file, | |||
actor: User.ap_id(actor), | |||
description: "test-media" | |||
) | |||
[object: object] | |||
end | |||
test "/api/v1/media/:id", %{conn: conn, object: object} do | |||
media = | |||
conn | |||
|> put("/api/v1/media/#{object.id}", %{}) | |||
|> json_response(400) | |||
|> get("/api/v1/media/#{object.id}") | |||
|> json_response_and_validate_schema(:ok) | |||
assert media == %{"error" => "bad_request"} | |||
assert media["description"] == "test-media" | |||
assert media["type"] == "image" | |||
assert media["id"] | |||
end | |||
end | |||
end |
@@ -12,9 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do | |||
import Pleroma.Factory | |||
test "does NOT render account/pleroma/relationship if this is disabled by default" do | |||
clear_config([:extensions, :output_relationships_in_statuses_by_default], false) | |||
test "does NOT render account/pleroma/relationship by default" do | |||
%{user: user, conn: conn} = oauth_access(["read:notifications"]) | |||
other_user = insert(:user) | |||
@@ -1176,7 +1176,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||
end | |||
test "bookmarks" do | |||
bookmarks_uri = "/api/v1/bookmarks?with_relationships=true" | |||
bookmarks_uri = "/api/v1/bookmarks" | |||
%{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"]) | |||
author = insert(:user) | |||
@@ -20,12 +20,10 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do | |||
describe "home" do | |||
setup do: oauth_access(["read:statuses"]) | |||
test "does NOT render account/pleroma/relationship if this is disabled by default", %{ | |||
test "does NOT embed account/pleroma/relationship in statuses", %{ | |||
user: user, | |||
conn: conn | |||
} do | |||
clear_config([:extensions, :output_relationships_in_statuses_by_default], false) | |||
other_user = insert(:user) | |||
{:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) | |||
@@ -41,72 +39,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do | |||
end) | |||
end | |||
test "the home timeline", %{user: user, conn: conn} do | |||
uri = "/api/v1/timelines/home?with_relationships=1" | |||
following = insert(:user, nickname: "followed") | |||
third_user = insert(:user, nickname: "repeated") | |||
{:ok, _activity} = CommonAPI.post(following, %{status: "post"}) | |||
{:ok, activity} = CommonAPI.post(third_user, %{status: "repeated post"}) | |||
{:ok, _, _} = CommonAPI.repeat(activity.id, following) | |||
ret_conn = get(conn, uri) | |||
assert Enum.empty?(json_response_and_validate_schema(ret_conn, :ok)) | |||
{:ok, _user} = User.follow(user, following) | |||
ret_conn = get(conn, uri) | |||
assert [ | |||
%{ | |||
"reblog" => %{ | |||
"content" => "repeated post", | |||
"account" => %{ | |||
"pleroma" => %{ | |||
"relationship" => %{"following" => false, "followed_by" => false} | |||
} | |||
} | |||
}, | |||
"account" => %{"pleroma" => %{"relationship" => %{"following" => true}}} | |||
}, | |||
%{ | |||
"content" => "post", | |||
"account" => %{ | |||
"acct" => "followed", | |||
"pleroma" => %{"relationship" => %{"following" => true}} | |||
} | |||
} | |||
] = json_response_and_validate_schema(ret_conn, :ok) | |||
{:ok, _user} = User.follow(third_user, user) | |||
ret_conn = get(conn, uri) | |||
assert [ | |||
%{ | |||
"reblog" => %{ | |||
"content" => "repeated post", | |||
"account" => %{ | |||
"acct" => "repeated", | |||
"pleroma" => %{ | |||
"relationship" => %{"following" => false, "followed_by" => true} | |||
} | |||
} | |||
}, | |||
"account" => %{"pleroma" => %{"relationship" => %{"following" => true}}} | |||
}, | |||
%{ | |||
"content" => "post", | |||
"account" => %{ | |||
"acct" => "followed", | |||
"pleroma" => %{"relationship" => %{"following" => true}} | |||
} | |||
} | |||
] = json_response_and_validate_schema(ret_conn, :ok) | |||
end | |||
test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do | |||
{:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"}) | |||
{:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"}) | |||
@@ -302,82 +302,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do | |||
end | |||
end | |||
test "represent an embedded relationship" do | |||
user = | |||
insert(:user, %{ | |||
follower_count: 0, | |||
note_count: 5, | |||
actor_type: "Service", | |||
nickname: "shp@shitposter.club", | |||
inserted_at: ~N[2017-08-15 15:47:06.597036] | |||
}) | |||
other_user = insert(:user) | |||
{:ok, other_user} = User.follow(other_user, user) | |||
{:ok, _user_relationship} = User.block(other_user, user) | |||
{:ok, _} = User.follow(insert(:user), user) | |||
expected = %{ | |||
id: to_string(user.id), | |||
username: "shp", | |||
acct: user.nickname, | |||
display_name: user.name, | |||
locked: false, | |||
created_at: "2017-08-15T15:47:06.000Z", | |||
followers_count: 1, | |||
following_count: 0, | |||
statuses_count: 5, | |||
note: user.bio, | |||
url: user.ap_id, | |||
avatar: "http://localhost:4001/images/avi.png", | |||
avatar_static: "http://localhost:4001/images/avi.png", | |||
header: "http://localhost:4001/images/banner.png", | |||
header_static: "http://localhost:4001/images/banner.png", | |||
emojis: [], | |||
fields: [], | |||
bot: true, | |||
source: %{ | |||
note: user.bio, | |||
sensitive: false, | |||
pleroma: %{ | |||
actor_type: "Service", | |||
discoverable: false | |||
}, | |||
fields: [] | |||
}, | |||
pleroma: %{ | |||
background_image: nil, | |||
confirmation_pending: false, | |||
tags: [], | |||
is_admin: false, | |||
is_moderator: false, | |||
hide_favorites: true, | |||
hide_followers: false, | |||
hide_follows: false, | |||
hide_followers_count: false, | |||
hide_follows_count: false, | |||
relationship: %{ | |||
id: to_string(user.id), | |||
following: false, | |||
followed_by: false, | |||
blocking: true, | |||
blocked_by: false, | |||
subscribing: false, | |||
muting: false, | |||
muting_notifications: false, | |||
requested: false, | |||
domain_blocking: false, | |||
showing_reblogs: true, | |||
endorsed: false | |||
}, | |||
skip_thread_containment: false | |||
} | |||
} | |||
assert expected == | |||
AccountView.render("show.json", %{user: refresh_record(user), for: other_user}) | |||
end | |||
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do | |||
user = insert(:user, pleroma_settings_store: %{fe: "test"}) | |||
@@ -42,7 +42,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do | |||
id: to_string(notification.id), | |||
pleroma: %{is_seen: false}, | |||
type: "mention", | |||
account: AccountView.render("show.json", %{user: user, for: mentioned_user}), | |||
account: | |||
AccountView.render("show.json", %{ | |||
user: user, | |||
for: mentioned_user | |||
}), | |||
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}), | |||
created_at: Utils.to_masto_date(notification.inserted_at) | |||
} | |||
@@ -576,7 +576,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do | |||
end | |||
end | |||
test "embeds a relationship in the account" do | |||
test "does not embed a relationship in the account" do | |||
user = insert(:user) | |||
other_user = insert(:user) | |||
@@ -587,13 +587,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do | |||
result = StatusView.render("show.json", %{activity: activity, for: other_user}) | |||
assert result[:account][:pleroma][:relationship] == | |||
AccountView.render("relationship.json", %{user: other_user, target: user}) | |||
assert result[:account][:pleroma][:relationship] == %{} | |||
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec()) | |||
end | |||
test "embeds a relationship in the account in reposts" do | |||
test "does not embed a relationship in the account in reposts" do | |||
user = insert(:user) | |||
other_user = insert(:user) | |||
@@ -606,12 +604,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do | |||
result = StatusView.render("show.json", %{activity: activity, for: user}) | |||
assert result[:account][:pleroma][:relationship] == | |||
AccountView.render("relationship.json", %{user: user, target: other_user}) | |||
assert result[:reblog][:account][:pleroma][:relationship] == | |||
AccountView.render("relationship.json", %{user: user, target: user}) | |||
assert result[:account][:pleroma][:relationship] == %{} | |||
assert result[:reblog][:account][:pleroma][:relationship] == %{} | |||
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec()) | |||
end | |||
@@ -31,8 +31,28 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
test "resend account confirmation email", %{conn: conn, user: user} do | |||
conn | |||
|> put_req_header("content-type", "application/json") | |||
|> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}") | |||
|> json_response(:no_content) | |||
|> json_response_and_validate_schema(:no_content) | |||
ObanHelpers.perform_all() | |||
email = Pleroma.Emails.UserEmail.account_confirmation_email(user) | |||
notify_email = Config.get([:instance, :notify_email]) | |||
instance_name = Config.get([:instance, :name]) | |||
assert_email_sent( | |||
from: {instance_name, notify_email}, | |||
to: {user.name, user.email}, | |||
html_body: email.html_body | |||
) | |||
end | |||
test "resend account confirmation email (with nickname)", %{conn: conn, user: user} do | |||
conn | |||
|> put_req_header("content-type", "application/json") | |||
|> post("/api/v1/pleroma/accounts/confirmation_resend?nickname=#{user.nickname}") | |||
|> json_response_and_validate_schema(:no_content) | |||
ObanHelpers.perform_all() | |||
@@ -54,7 +74,10 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
test "user avatar can be set", %{user: user, conn: conn} do | |||
avatar_image = File.read!("test/fixtures/avatar_data_uri") | |||
conn = patch(conn, "/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image}) | |||
user = refresh_record(user) | |||
@@ -70,17 +93,20 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
] | |||
} = user.avatar | |||
assert %{"url" => _} = json_response(conn, 200) | |||
assert %{"url" => _} = json_response_and_validate_schema(conn, 200) | |||
end | |||
test "user avatar can be reset", %{user: user, conn: conn} do | |||
conn = patch(conn, "/api/v1/pleroma/accounts/update_avatar", %{img: ""}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""}) | |||
user = User.get_cached_by_id(user.id) | |||
assert user.avatar == nil | |||
assert %{"url" => nil} = json_response(conn, 200) | |||
assert %{"url" => nil} = json_response_and_validate_schema(conn, 200) | |||
end | |||
end | |||
@@ -88,21 +114,27 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
setup do: oauth_access(["write:accounts"]) | |||
test "can set profile banner", %{user: user, conn: conn} do | |||
conn = patch(conn, "/api/v1/pleroma/accounts/update_banner", %{"banner" => @image}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image}) | |||
user = refresh_record(user) | |||
assert user.banner["type"] == "Image" | |||
assert %{"url" => _} = json_response(conn, 200) | |||
assert %{"url" => _} = json_response_and_validate_schema(conn, 200) | |||
end | |||
test "can reset profile banner", %{user: user, conn: conn} do | |||
conn = patch(conn, "/api/v1/pleroma/accounts/update_banner", %{"banner" => ""}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""}) | |||
user = refresh_record(user) | |||
assert user.banner == %{} | |||
assert %{"url" => nil} = json_response(conn, 200) | |||
assert %{"url" => nil} = json_response_and_validate_schema(conn, 200) | |||
end | |||
end | |||
@@ -110,19 +142,26 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
setup do: oauth_access(["write:accounts"]) | |||
test "background image can be set", %{user: user, conn: conn} do | |||
conn = patch(conn, "/api/v1/pleroma/accounts/update_background", %{"img" => @image}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image}) | |||
user = refresh_record(user) | |||
assert user.background["type"] == "Image" | |||
assert %{"url" => _} = json_response(conn, 200) | |||
# assert %{"url" => _} = json_response(conn, 200) | |||
assert %{"url" => _} = json_response_and_validate_schema(conn, 200) | |||
end | |||
test "background image can be reset", %{user: user, conn: conn} do | |||
conn = patch(conn, "/api/v1/pleroma/accounts/update_background", %{"img" => ""}) | |||
conn = | |||
conn | |||
|> put_req_header("content-type", "multipart/form-data") | |||
|> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""}) | |||
user = refresh_record(user) | |||
assert user.background == %{} | |||
assert %{"url" => nil} = json_response(conn, 200) | |||
assert %{"url" => nil} = json_response_and_validate_schema(conn, 200) | |||
end | |||
end | |||
@@ -143,7 +182,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
conn | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
|> json_response(:ok) | |||
|> json_response_and_validate_schema(:ok) | |||
[like] = response | |||
@@ -160,7 +199,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
build_conn() | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
|> json_response(200) | |||
|> json_response_and_validate_schema(200) | |||
assert length(response) == 1 | |||
end | |||
@@ -183,7 +222,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
|> assign(:user, u) | |||
|> assign(:token, insert(:oauth_token, user: u, scopes: ["read:favourites"])) | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
|> json_response(:ok) | |||
|> json_response_and_validate_schema(:ok) | |||
assert length(response) == 1 | |||
end | |||
@@ -191,7 +230,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
build_conn() | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
|> json_response(200) | |||
|> json_response_and_validate_schema(200) | |||
assert length(response) == 0 | |||
end | |||
@@ -213,7 +252,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
conn | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
|> json_response(:ok) | |||
|> json_response_and_validate_schema(:ok) | |||
assert Enum.empty?(response) | |||
end | |||
@@ -233,11 +272,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
conn | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{ | |||
since_id: third_activity.id, | |||
max_id: seventh_activity.id | |||
}) | |||
|> json_response(:ok) | |||
|> get( | |||
"/api/v1/pleroma/accounts/#{user.id}/favourites?since_id=#{third_activity.id}&max_id=#{ | |||
seventh_activity.id | |||
}" | |||
) | |||
|> json_response_and_validate_schema(:ok) | |||
assert length(response) == 3 | |||
refute third_activity in response | |||
@@ -256,8 +296,8 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
conn | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"}) | |||
|> json_response(:ok) | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites?limit=3") | |||
|> json_response_and_validate_schema(:ok) | |||
assert length(response) == 3 | |||
end | |||
@@ -269,7 +309,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
response = | |||
conn | |||
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
|> json_response(:ok) | |||
|> json_response_and_validate_schema(:ok) | |||
assert Enum.empty?(response) | |||
end | |||
@@ -277,7 +317,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
test "returns 404 error when specified user is not exist", %{conn: conn} do | |||
conn = get(conn, "/api/v1/pleroma/accounts/test/favourites") | |||
assert json_response(conn, 404) == %{"error" => "Record not found"} | |||
assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"} | |||
end | |||
test "returns 403 error when user has hidden own favorites", %{conn: conn} do | |||
@@ -287,7 +327,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
assert json_response(conn, 403) == %{"error" => "Can't get favorites"} | |||
assert json_response_and_validate_schema(conn, 403) == %{"error" => "Can't get favorites"} | |||
end | |||
test "hides favorites for new users by default", %{conn: conn} do | |||
@@ -298,7 +338,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
assert user.hide_favorites | |||
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/favourites") | |||
assert json_response(conn, 403) == %{"error" => "Can't get favorites"} | |||
assert json_response_and_validate_schema(conn, 403) == %{"error" => "Can't get favorites"} | |||
end | |||
end | |||
@@ -312,11 +352,12 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
|> assign(:user, user) | |||
|> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe") | |||
assert %{"id" => _id, "subscribing" => true} = json_response(ret_conn, 200) | |||
assert %{"id" => _id, "subscribing" => true} = | |||
json_response_and_validate_schema(ret_conn, 200) | |||
conn = post(conn, "/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe") | |||
assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200) | |||
assert %{"id" => _id, "subscribing" => false} = json_response_and_validate_schema(conn, 200) | |||
end | |||
end | |||
@@ -326,7 +367,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
conn = post(conn, "/api/v1/pleroma/accounts/target_id/subscribe") | |||
assert %{"error" => "Record not found"} = json_response(conn, 404) | |||
assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404) | |||
end | |||
end | |||
@@ -336,7 +377,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do | |||
conn = post(conn, "/api/v1/pleroma/accounts/target_id/unsubscribe") | |||
assert %{"error" => "Record not found"} = json_response(conn, 404) | |||
assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn, 404) | |||
end | |||
end | |||
end |