瀏覽代碼

Merge branch 'develop' into feature/admin-api-status-count-per-instance

merge-requests/2720/head
Roman Chvanikov 4 年之前
父節點
當前提交
01bd6a1e54
共有 83 個檔案被更改,包括 2528 行新增657 行删除
  1. +1
    -0
      CHANGELOG.md
  2. +6
    -15
      benchmarks/load_testing/fetcher.ex
  3. +0
    -2
      config/config.exs
  4. +121
    -104
      config/description.exs
  5. +15
    -0
      docs/configuration/cheatsheet.md
  6. +36
    -12
      installation/init.d/pleroma
  7. +1
    -2
      lib/mix/tasks/pleroma/benchmark.ex
  8. +3
    -4
      lib/mix/tasks/pleroma/digest.ex
  9. +2
    -1
      lib/pleroma/bbs/authenticator.ex
  10. +11
    -0
      lib/pleroma/config/config_db.ex
  11. +2
    -1
      lib/pleroma/constants.ex
  12. +0
    -1
      lib/pleroma/docs/json.ex
  13. +27
    -1
      lib/pleroma/plugs/authentication_plug.ex
  14. +1
    -1
      lib/pleroma/upload.ex
  15. +37
    -6
      lib/pleroma/user_relationship.ex
  16. +39
    -14
      lib/pleroma/web/admin_api/admin_api_controller.ex
  17. +9
    -0
      lib/pleroma/web/admin_api/views/account_view.ex
  18. +4
    -9
      lib/pleroma/web/admin_api/views/report_view.ex
  19. +6
    -11
      lib/pleroma/web/admin_api/views/status_view.ex
  20. +14
    -0
      lib/pleroma/web/api_spec/helpers.ex
  21. +54
    -12
      lib/pleroma/web/api_spec/operations/account_operation.ex
  22. +5
    -1
      lib/pleroma/web/api_spec/operations/app_operation.ex
  23. +4
    -2
      lib/pleroma/web/api_spec/operations/filter_operation.ex
  24. +4
    -2
      lib/pleroma/web/api_spec/operations/marker_operation.ex
  25. +132
    -0
      lib/pleroma/web/api_spec/operations/media_operation.ex
  26. +187
    -0
      lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
  27. +3
    -0
      lib/pleroma/web/api_spec/operations/report_operation.ex
  28. +5
    -4
      lib/pleroma/web/api_spec/operations/search_operation.ex
  29. +26
    -8
      lib/pleroma/web/api_spec/operations/status_operation.ex
  30. +46
    -8
      lib/pleroma/web/api_spec/operations/subscription_operation.ex
  31. +4
    -12
      lib/pleroma/web/api_spec/operations/timeline_operation.ex
  32. +1
    -1
      lib/pleroma/web/api_spec/schemas/attachment.ex
  33. +2
    -1
      lib/pleroma/web/auth/pleroma_authenticator.ex
  34. +2
    -1
      lib/pleroma/web/auth/totp_authenticator.ex
  35. +1
    -0
      lib/pleroma/web/chat_channel.ex
  36. +12
    -1
      lib/pleroma/web/common_api/common_api.ex
  37. +11
    -10
      lib/pleroma/web/controller_helper.ex
  38. +17
    -6
      lib/pleroma/web/mastodon_api/controllers/account_controller.ex
  39. +38
    -5
      lib/pleroma/web/mastodon_api/controllers/media_controller.ex
  40. +2
    -3
      lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
  41. +9
    -7
      lib/pleroma/web/mastodon_api/controllers/search_controller.ex
  42. +5
    -8
      lib/pleroma/web/mastodon_api/controllers/status_controller.ex
  43. +6
    -11
      lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
  44. +4
    -5
      lib/pleroma/web/mastodon_api/views/account_view.ex
  45. +9
    -14
      lib/pleroma/web/mastodon_api/views/notification_view.ex
  46. +3
    -9
      lib/pleroma/web/mastodon_api/views/status_view.ex
  47. +2
    -1
      lib/pleroma/web/mongooseim/mongoose_im_controller.ex
  48. +20
    -11
      lib/pleroma/web/pleroma_api/controllers/account_controller.ex
  49. +10
    -7
      lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
  50. +3
    -0
      lib/pleroma/web/router.ex
  51. +1
    -0
      mix.exs
  52. +2
    -0
      mix.lock
  53. +86
    -78
      priv/gettext/fr/LC_MESSAGES/errors.po
  54. +578
    -0
      priv/gettext/nl/LC_MESSAGES/errors.po
  55. +587
    -0
      priv/gettext/pl/LC_MESSAGES/errors.po
  56. +1
    -1
      priv/static/index.html
  57. +18
    -13
      priv/static/static/config.json
  58. 二進制
      priv/static/static/font/fontello.1588947937982.woff2
  59. 二進制
      priv/static/static/font/fontello.1589385935077.eot
  60. +0
    -0
      priv/static/static/font/fontello.1589385935077.svg
  61. 二進制
      priv/static/static/font/fontello.1589385935077.ttf
  62. 二進制
      priv/static/static/font/fontello.1589385935077.woff
  63. 二進制
      priv/static/static/font/fontello.1589385935077.woff2
  64. +6
    -6
      priv/static/static/fontello.1589385935077.css
  65. +2
    -0
      priv/static/static/js/app.838ffa9aecf210c7d744.js
  66. +1
    -0
      priv/static/static/js/app.838ffa9aecf210c7d744.js.map
  67. +0
    -2
      priv/static/static/js/app.996428ccaaaa7f28cb8d.js
  68. +0
    -1
      priv/static/static/js/app.996428ccaaaa7f28cb8d.js.map
  69. +1
    -1
      priv/static/sw-pleroma.js
  70. +8
    -0
      test/config/config_db_test.exs
  71. +37
    -4
      test/plugs/authentication_plug_test.exs
  72. +1
    -1
      test/web/activity_pub/activity_pub_test.exs
  73. +75
    -10
      test/web/admin_api/admin_api_controller_test.exs
  74. +7
    -2
      test/web/auth/pleroma_authenticator_test.exs
  75. +12
    -0
      test/web/common_api/common_api_test.exs
  76. +56
    -10
      test/web/mastodon_api/controllers/media_controller_test.exs
  77. +1
    -3
      test/web/mastodon_api/controllers/notification_controller_test.exs
  78. +1
    -1
      test/web/mastodon_api/controllers/status_controller_test.exs
  79. +1
    -69
      test/web/mastodon_api/controllers/timeline_controller_test.exs
  80. +0
    -76
      test/web/mastodon_api/views/account_view_test.exs
  81. +5
    -1
      test/web/mastodon_api/views/notification_view_test.exs
  82. +5
    -11
      test/web/mastodon_api/views/status_view_test.exs
  83. +74
    -33
      test/web/pleroma_api/controllers/account_controller_test.exs

+ 1
- 0
CHANGELOG.md 查看文件

@@ -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.


+ 6
- 15
benchmarks/load_testing/fetcher.ex 查看文件

@@ -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
},


+ 0
- 2
config/config.exs 查看文件

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


+ 121
- 104
config/description.exs 查看文件

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


+ 15
- 0
docs/configuration/cheatsheet.md 查看文件

@@ -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


+ 36
- 12
installation/init.d/pleroma 查看文件

@@ -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"
}

+ 1
- 2
lib/mix/tasks/pleroma/benchmark.ex 查看文件

@@ -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
},


+ 3
- 4
lib/mix/tasks/pleroma/digest.ex 查看文件

@@ -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

+ 2
- 1
lib/pleroma/bbs/authenticator.ex 查看文件

@@ -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


+ 11
- 0
lib/pleroma/config/config_db.ex 查看文件

@@ -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


+ 2
- 1
lib/pleroma/constants.ex 查看文件

@@ -17,7 +17,8 @@ defmodule Pleroma.Constants do
"announcement_count",
"emoji",
"context_id",
"deleted_activity_id"
"deleted_activity_id",
"pleroma_internal"
]
)



+ 0
- 1
lib/pleroma/docs/json.ex 查看文件

@@ -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

+ 27
- 1
lib/pleroma/plugs/authentication_plug.ex 查看文件

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


+ 1
- 1
lib/pleroma/upload.ex 查看文件

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


+ 37
- 6
lib/pleroma/user_relationship.ex 查看文件

@@ -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


+ 39
- 14
lib/pleroma/web/admin_api/admin_api_controller.ex 查看文件

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



+ 9
- 0
lib/pleroma/web/admin_api/views/account_view.ex 查看文件

@@ -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


+ 4
- 9
lib/pleroma/web/admin_api/views/report_view.ex 查看文件

@@ -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

+ 6
- 11
lib/pleroma/web/admin_api/views/status_view.ex 查看文件

@@ -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

+ 14
- 0
lib/pleroma/web/api_spec/helpers.ex 查看文件

@@ -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

+ 54
- 12
lib/pleroma/web/api_spec/operations/account_operation.ex 查看文件

@@ -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
}


+ 5
- 1
lib/pleroma/web/api_spec/operations/app_operation.ex 查看文件

@@ -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: %{


+ 4
- 2
lib/pleroma/web/api_spec/operations/filter_operation.ex 查看文件

@@ -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
}


+ 4
- 2
lib/pleroma/web/api_spec/operations/marker_operation.ex 查看文件

@@ -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}
}
}
},


+ 132
- 0
lib/pleroma/web/api_spec/operations/media_operation.ex 查看文件

@@ -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

+ 187
- 0
lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex 查看文件

@@ -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

+ 3
- 0
lib/pleroma/web/api_spec/operations/report_operation.ex 查看文件

@@ -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?"


+ 5
- 4
lib/pleroma/web/api_spec/operations/search_operation.ex 查看文件

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


+ 26
- 8
lib/pleroma/web/api_spec/operations/status_operation.ex 查看文件

@@ -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`."


+ 46
- 8
lib/pleroma/web/api_spec/operations/subscription_operation.ex 查看文件

@@ -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?"
}
}
}
}


+ 4
- 12
lib/pleroma/web/api_spec/operations/timeline_operation.ex 查看文件

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


+ 1
- 1
lib/pleroma/web/api_spec/schemas/attachment.ex 查看文件

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


+ 2
- 1
lib/pleroma/web/auth/pleroma_authenticator.ex 查看文件

@@ -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


+ 2
- 1
lib/pleroma/web/auth/totp_authenticator.ex 查看文件

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


+ 1
- 0
lib/pleroma/web/chat_channel.ex 查看文件

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


+ 12
- 1
lib/pleroma/web/common_api/common_api.ex 查看文件

@@ -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



+ 11
- 10
lib/pleroma/web/controller_helper.ex 查看文件

@@ -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

+ 17
- 6
lib/pleroma/web/mastodon_api/controllers/account_controller.ex 查看文件

@@ -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"


+ 38
- 5
lib/pleroma/web/mastodon_api/controllers/media_controller.ex 查看文件

@@ -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

+ 2
- 3
lib/pleroma/web/mastodon_api/controllers/notification_controller.ex 查看文件

@@ -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



+ 9
- 7
lib/pleroma/web/mastodon_api/controllers/search_controller.ex 查看文件

@@ -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



+ 5
- 8
lib/pleroma/web/mastodon_api/controllers/status_controller.ex 查看文件

@@ -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
- 11
lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex 查看文件

@@ -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.")


+ 4
- 5
lib/pleroma/web/mastodon_api/views/account_view.ex 查看文件

@@ -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

%{


+ 9
- 14
lib/pleroma/web/mastodon_api/views/notification_view.ex 查看文件

@@ -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"] ->


+ 3
- 9
lib/pleroma/web/mastodon_api/views/status_view.ex 查看文件

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


+ 2
- 1
lib/pleroma/web/mongooseim/mongoose_im_controller.ex 查看文件

@@ -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


+ 20
- 11
lib/pleroma/web/pleroma_api/controllers/account_controller.ex 查看文件

@@ -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



+ 10
- 7
lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex 查看文件

@@ -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


+ 3
- 0
lib/pleroma/web/router.ex 查看文件

@@ -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


+ 1
- 0
mix.exs 查看文件

@@ -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},


+ 2
- 0
mix.lock 查看文件

@@ -5,6 +5,7 @@
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
"bbcode": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/bbcode.git", "f2d267675e9a7e1ad1ea9beb4cc23382762b66c2", [ref: "v0.2.0"]},
"bbcode_pleroma": {:hex, :bbcode_pleroma, "0.2.0", "d36f5bca6e2f62261c45be30fa9b92725c0655ad45c99025cb1c3e28e25803ef", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "19851074419a5fedb4ef49e1f01b30df504bb5dbb6d6adfc135238063bebd1c3"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.2.0", "3df902b81ce7fa8867a2ae30d20a1da6877a2c056bfb116fd0bc8a5f0190cea4", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "762be3fcb779f08207531bc6612cca480a338e4b4357abb49f5ce00240a77d1e"},
"benchee": {:hex, :benchee, "1.0.1", "66b211f9bfd84bd97e6d1beaddf8fc2312aaabe192f776e8931cb0c16f53a521", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm", "3ad58ae787e9c7c94dd7ceda3b587ec2c64604563e049b2a0e8baafae832addb"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"cachex": {:hex, :cachex, "3.2.0", "a596476c781b0646e6cb5cd9751af2e2974c3e0d5498a8cab71807618b74fe2f", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "aef93694067a43697ae0531727e097754a9e992a1e7946296f5969d6dd9ac986"},
@@ -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"},


+ 86
- 78
priv/gettext/fr/LC_MESSAGES/errors.po 查看文件

@@ -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"

+ 578
- 0
priv/gettext/nl/LC_MESSAGES/errors.po 查看文件

@@ -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 ""

+ 587
- 0
priv/gettext/pl/LC_MESSAGES/errors.po 查看文件

@@ -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
priv/static/index.html 查看文件

@@ -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>

+ 18
- 13
priv/static/static/config.json 查看文件

@@ -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
}

二進制
priv/static/static/font/fontello.1588947937982.woff2 查看文件


二進制
priv/static/static/font/fontello.1588947937982.eot → priv/static/static/font/fontello.1589385935077.eot 查看文件


priv/static/static/font/fontello.1588947937982.svg → priv/static/static/font/fontello.1589385935077.svg 查看文件


二進制
priv/static/static/font/fontello.1588947937982.ttf → priv/static/static/font/fontello.1589385935077.ttf 查看文件


二進制
priv/static/static/font/fontello.1588947937982.woff → priv/static/static/font/fontello.1589385935077.woff 查看文件


二進制
priv/static/static/font/fontello.1589385935077.woff2 查看文件


priv/static/static/fontello.1588947937982.css → priv/static/static/fontello.1589385935077.css 查看文件

@@ -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;
}

+ 2
- 0
priv/static/static/js/app.838ffa9aecf210c7d744.js
文件差異過大導致無法顯示
查看文件


+ 1
- 0
priv/static/static/js/app.838ffa9aecf210c7d744.js.map
文件差異過大導致無法顯示
查看文件


+ 0
- 2
priv/static/static/js/app.996428ccaaaa7f28cb8d.js
文件差異過大導致無法顯示
查看文件


+ 0
- 1
priv/static/static/js/app.996428ccaaaa7f28cb8d.js.map
文件差異過大導致無法顯示
查看文件


+ 1
- 1
priv/static/sw-pleroma.js 查看文件

@@ -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){
/*!


+ 8
- 0
test/config/config_db_test.exs 查看文件

@@ -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([


+ 37
- 4
test/plugs/authentication_plug_test.exs 查看文件

@@ -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"


+ 1
- 1
test/web/activity_pub/activity_pub_test.exs 查看文件

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


+ 75
- 10
test/web/admin_api/admin_api_controller_test.exs 查看文件

@@ -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


+ 7
- 2
test/web/auth/pleroma_authenticator_test.exs 查看文件

@@ -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


+ 12
- 0
test/web/common_api/common_api_test.exs 查看文件

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


+ 56
- 10
test/web/mastodon_api/controllers/media_controller_test.exs 查看文件

@@ -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

+ 1
- 3
test/web/mastodon_api/controllers/notification_controller_test.exs 查看文件

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



+ 1
- 1
test/web/mastodon_api/controllers/status_controller_test.exs 查看文件

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


+ 1
- 69
test/web/mastodon_api/controllers/timeline_controller_test.exs 查看文件

@@ -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"})


+ 0
- 76
test/web/mastodon_api/views/account_view_test.exs 查看文件

@@ -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"})



+ 5
- 1
test/web/mastodon_api/views/notification_view_test.exs 查看文件

@@ -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)
}


+ 5
- 11
test/web/mastodon_api/views/status_view_test.exs 查看文件

@@ -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



+ 74
- 33
test/web/pleroma_api/controllers/account_controller_test.exs 查看文件

@@ -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

Loading…
取消
儲存