From f378e93bf4ca4bc9547f242e76e6258e25852972 Mon Sep 17 00:00:00 2001
From: lain
Date: Fri, 26 Jun 2020 16:15:27 +0200
Subject: [PATCH 01/25] AccountController: Return scope in proper format.
---
lib/pleroma/web/api_spec/operations/account_operation.ex | 4 ++--
.../web/mastodon_api/controllers/account_controller.ex | 2 +-
.../mastodon_api/controllers/account_controller_test.exs | 6 +++---
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 9bde8fc0d..d94dae374 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -446,13 +446,13 @@ defp create_response do
properties: %{
token_type: %Schema{type: :string},
access_token: %Schema{type: :string},
- scope: %Schema{type: :array, items: %Schema{type: :string}},
+ scope: %Schema{type: :string},
created_at: %Schema{type: :integer, format: :"date-time"}
},
example: %{
"access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
"created_at" => 1_585_918_714,
- "scope" => ["read", "write", "follow", "push"],
+ "scope" => "read write follow push",
"token_type" => "Bearer"
}
}
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index 7a88a847c..a87dddddf 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -104,7 +104,7 @@ def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
json(conn, %{
token_type: "Bearer",
access_token: token.token,
- scope: app.scopes,
+ scope: app.scopes |> Enum.join(" "),
created_at: Token.Utils.format_created_at(token)
})
else
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index ebfcedd01..fcc1e792b 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -905,7 +905,7 @@ test "Account registration via Application", %{conn: conn} do
%{
"access_token" => token,
"created_at" => _created_at,
- "scope" => _scope,
+ "scope" => ^scope,
"token_type" => "Bearer"
} = json_response_and_validate_schema(conn, 200)
@@ -1067,7 +1067,7 @@ test "registration from trusted app" do
assert %{
"access_token" => access_token,
"created_at" => _,
- "scope" => ["read", "write", "follow", "push"],
+ "scope" => "read write follow push",
"token_type" => "Bearer"
} = response
@@ -1185,7 +1185,7 @@ test "creates an account and returns 200 if captcha is valid", %{conn: conn} do
assert %{
"access_token" => access_token,
"created_at" => _,
- "scope" => ["read"],
+ "scope" => "read",
"token_type" => "Bearer"
} =
conn
From bb168ed94a6b4d02879472e30149a494d7b7ebb5 Mon Sep 17 00:00:00 2001
From: lain
Date: Mon, 29 Jun 2020 13:39:09 +0200
Subject: [PATCH 02/25] OAuth: Extract view-type functions to a view.
---
lib/pleroma/web/oauth/mfa_controller.ex | 3 +-
lib/pleroma/web/oauth/mfa_view.ex | 9 ++++++
lib/pleroma/web/oauth/oauth_controller.ex | 18 +++++------
lib/pleroma/web/oauth/oauth_view.ex | 22 +++++++++++++
lib/pleroma/web/oauth/token/response.ex | 39 -----------------------
5 files changed, 41 insertions(+), 50 deletions(-)
diff --git a/lib/pleroma/web/oauth/mfa_controller.ex b/lib/pleroma/web/oauth/mfa_controller.ex
index 53e19f82e..f102c93e7 100644
--- a/lib/pleroma/web/oauth/mfa_controller.ex
+++ b/lib/pleroma/web/oauth/mfa_controller.ex
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.OAuth.MFAController do
alias Pleroma.Web.Auth.TOTPAuthenticator
alias Pleroma.Web.OAuth.MFAView, as: View
alias Pleroma.Web.OAuth.OAuthController
+ alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.OAuth.Token
plug(:fetch_session when action in [:show, :verify])
@@ -74,7 +75,7 @@ def challenge(conn, %{"mfa_token" => mfa_token} = params) do
{:ok, %{user: user, authorization: auth}} <- MFA.Token.validate(mfa_token),
{:ok, _} <- validates_challenge(user, params),
{:ok, token} <- Token.exchange_token(app, auth) do
- json(conn, Token.Response.build(user, token))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
_error ->
conn
diff --git a/lib/pleroma/web/oauth/mfa_view.ex b/lib/pleroma/web/oauth/mfa_view.ex
index 41d5578dc..5d87db268 100644
--- a/lib/pleroma/web/oauth/mfa_view.ex
+++ b/lib/pleroma/web/oauth/mfa_view.ex
@@ -5,4 +5,13 @@
defmodule Pleroma.Web.OAuth.MFAView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+ alias Pleroma.MFA
+
+ def render("mfa_response.json", %{token: token, user: user}) do
+ %{
+ error: "mfa_required",
+ mfa_token: token.token,
+ supported_challenge_types: MFA.supported_methods(user)
+ }
+ end
end
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index c557778ca..3da104933 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -6,8 +6,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
use Pleroma.Web, :controller
alias Pleroma.Helpers.UriHelper
- alias Pleroma.Maps
alias Pleroma.MFA
+ alias Pleroma.Maps
alias Pleroma.Plugs.RateLimiter
alias Pleroma.Registration
alias Pleroma.Repo
@@ -17,6 +17,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
alias Pleroma.Web.OAuth.App
alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.MFAController
+ alias Pleroma.Web.OAuth.OAuthView
+ alias Pleroma.Web.OAuth.MFAView
alias Pleroma.Web.OAuth.Scopes
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.OAuth.Token.Strategy.RefreshToken
@@ -233,9 +235,7 @@ def token_exchange(
with {:ok, app} <- Token.Utils.fetch_app(conn),
{:ok, %{user: user} = token} <- Token.get_by_refresh_token(app, token),
{:ok, token} <- RefreshToken.grant(token) do
- response_attrs = %{created_at: Token.Utils.format_created_at(token)}
-
- json(conn, Token.Response.build(user, token, response_attrs))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
_error -> render_invalid_credentials_error(conn)
end
@@ -247,9 +247,7 @@ def token_exchange(%Plug.Conn{} = conn, %{"grant_type" => "authorization_code"}
{:ok, auth} <- Authorization.get_by_token(app, fixed_token),
%User{} = user <- User.get_cached_by_id(auth.user_id),
{:ok, token} <- Token.exchange_token(app, auth) do
- response_attrs = %{created_at: Token.Utils.format_created_at(token)}
-
- json(conn, Token.Response.build(user, token, response_attrs))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
error ->
handle_token_exchange_error(conn, error)
@@ -267,7 +265,7 @@ def token_exchange(
{:ok, auth} <- Authorization.create_authorization(app, user, scopes),
{:mfa_required, _, _, false} <- {:mfa_required, user, auth, MFA.require?(user)},
{:ok, token} <- Token.exchange_token(app, auth) do
- json(conn, Token.Response.build(user, token))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
error ->
handle_token_exchange_error(conn, error)
@@ -290,7 +288,7 @@ def token_exchange(%Plug.Conn{} = conn, %{"grant_type" => "client_credentials"}
with {:ok, app} <- Token.Utils.fetch_app(conn),
{:ok, auth} <- Authorization.create_authorization(app, %User{}),
{:ok, token} <- Token.exchange_token(app, auth) do
- json(conn, Token.Response.build_for_client_credentials(token))
+ json(conn, OAuthView.render("token.json", %{token: token}))
else
_error ->
handle_token_exchange_error(conn, :invalid_credentails)
@@ -548,7 +546,7 @@ defp put_session_registration_id(%Plug.Conn{} = conn, registration_id),
defp build_and_response_mfa_token(user, auth) do
with {:ok, token} <- MFA.Token.create_token(user, auth) do
- Token.Response.build_for_mfa_token(user, token)
+ MFAView.render("mfa_response.json", %{token: token, user: user})
end
end
diff --git a/lib/pleroma/web/oauth/oauth_view.ex b/lib/pleroma/web/oauth/oauth_view.ex
index 94ddaf913..f55247ebd 100644
--- a/lib/pleroma/web/oauth/oauth_view.ex
+++ b/lib/pleroma/web/oauth/oauth_view.ex
@@ -5,4 +5,26 @@
defmodule Pleroma.Web.OAuth.OAuthView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+
+ alias Pleroma.Web.OAuth.Token.Utils
+
+ def render("token.json", %{token: token} = opts) do
+ response = %{
+ token_type: "Bearer",
+ access_token: token.token,
+ refresh_token: token.refresh_token,
+ expires_in: expires_in(),
+ scope: Enum.join(token.scopes, " "),
+ created_at: Utils.format_created_at(token)
+ }
+
+ if user = opts[:user] do
+ response
+ |> Map.put(:me, user.ap_id)
+ else
+ response
+ end
+ end
+
+ defp expires_in, do: Pleroma.Config.get([:oauth2, :token_expires_in], 600)
end
diff --git a/lib/pleroma/web/oauth/token/response.ex b/lib/pleroma/web/oauth/token/response.ex
index 0e72c31e9..a12a6865c 100644
--- a/lib/pleroma/web/oauth/token/response.ex
+++ b/lib/pleroma/web/oauth/token/response.ex
@@ -3,43 +3,4 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.OAuth.Token.Response do
- @moduledoc false
-
- alias Pleroma.MFA
- alias Pleroma.User
- alias Pleroma.Web.OAuth.Token.Utils
-
- @doc false
- def build(%User{} = user, token, opts \\ %{}) do
- %{
- token_type: "Bearer",
- access_token: token.token,
- refresh_token: token.refresh_token,
- expires_in: expires_in(),
- scope: Enum.join(token.scopes, " "),
- me: user.ap_id
- }
- |> Map.merge(opts)
- end
-
- def build_for_client_credentials(token) do
- %{
- token_type: "Bearer",
- access_token: token.token,
- refresh_token: token.refresh_token,
- created_at: Utils.format_created_at(token),
- expires_in: expires_in(),
- scope: Enum.join(token.scopes, " ")
- }
- end
-
- def build_for_mfa_token(user, mfa_token) do
- %{
- error: "mfa_required",
- mfa_token: mfa_token.token,
- supported_challenge_types: MFA.supported_methods(user)
- }
- end
-
- defp expires_in, do: Pleroma.Config.get([:oauth2, :token_expires_in], 600)
end
From e374872fe7d10aa659723ee31003f3e9188edfdd Mon Sep 17 00:00:00 2001
From: lain
Date: Mon, 29 Jun 2020 13:49:48 +0200
Subject: [PATCH 03/25] AccountOperation: Correctly describe create response.
---
.../web/api_spec/operations/account_operation.ex | 11 +++++++++--
.../mastodon_api/controllers/account_controller.ex | 8 ++------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index d94dae374..f3ffa1ad4 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -438,6 +438,7 @@ defp create_request do
}
end
+ # TODO: This is actually a token respone, but there's no oauth operation file yet.
defp create_response do
%Schema{
title: "AccountCreateResponse",
@@ -446,14 +447,20 @@ defp create_response do
properties: %{
token_type: %Schema{type: :string},
access_token: %Schema{type: :string},
+ refresh_token: %Schema{type: :string},
scope: %Schema{type: :string},
- created_at: %Schema{type: :integer, format: :"date-time"}
+ created_at: %Schema{type: :integer, format: :"date-time"},
+ me: %Schema{type: :string},
+ expires_in: %Schema{type: :integer}
},
example: %{
+ "token_type" => "Bearer",
"access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
+ "refresh_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzz",
"created_at" => 1_585_918_714,
+ "expires_in" => 600,
"scope" => "read write follow push",
- "token_type" => "Bearer"
+ "me" => "https://gensokyo.2hu/users/raymoo"
}
}
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index a87dddddf..a143675ec 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -28,6 +28,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
alias Pleroma.Web.MastodonAPI.MastodonAPIController
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.OAuth.Token
+ alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.TwitterAPI.TwitterAPI
plug(Pleroma.Web.ApiSpec.CastAndValidate)
@@ -101,12 +102,7 @@ def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
:ok <- TwitterAPI.validate_captcha(app, params),
{:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
- json(conn, %{
- token_type: "Bearer",
- access_token: token.token,
- scope: app.scopes |> Enum.join(" "),
- created_at: Token.Utils.format_created_at(token)
- })
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
{:error, error} -> json_response(conn, :bad_request, %{error: error})
end
From f308196b7528fab92b3cfba12ea71c464e2f9ab0 Mon Sep 17 00:00:00 2001
From: lain
Date: Mon, 29 Jun 2020 13:52:50 +0200
Subject: [PATCH 04/25] Token Response: Remove empty file.
---
lib/pleroma/web/oauth/token/response.ex | 6 ------
1 file changed, 6 deletions(-)
delete mode 100644 lib/pleroma/web/oauth/token/response.ex
diff --git a/lib/pleroma/web/oauth/token/response.ex b/lib/pleroma/web/oauth/token/response.ex
deleted file mode 100644
index a12a6865c..000000000
--- a/lib/pleroma/web/oauth/token/response.ex
+++ /dev/null
@@ -1,6 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.OAuth.Token.Response do
-end
From 59540131c189afb10faf98d1bfeccf8f94985a90 Mon Sep 17 00:00:00 2001
From: lain
Date: Mon, 29 Jun 2020 14:09:03 +0200
Subject: [PATCH 05/25] Credo fixes.
---
.../web/mastodon_api/controllers/account_controller.ex | 2 +-
lib/pleroma/web/oauth/oauth_controller.ex | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index a143675ec..2942ed336 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -27,8 +27,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
alias Pleroma.Web.MastodonAPI.MastodonAPI
alias Pleroma.Web.MastodonAPI.MastodonAPIController
alias Pleroma.Web.MastodonAPI.StatusView
- alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.OAuth.OAuthView
+ alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.TwitterAPI.TwitterAPI
plug(Pleroma.Web.ApiSpec.CastAndValidate)
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index 3da104933..7683589cf 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -6,8 +6,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
use Pleroma.Web, :controller
alias Pleroma.Helpers.UriHelper
- alias Pleroma.MFA
alias Pleroma.Maps
+ alias Pleroma.MFA
alias Pleroma.Plugs.RateLimiter
alias Pleroma.Registration
alias Pleroma.Repo
@@ -17,8 +17,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
alias Pleroma.Web.OAuth.App
alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.MFAController
- alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.OAuth.MFAView
+ alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.OAuth.Scopes
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.OAuth.Token.Strategy.RefreshToken
From eaa59daa4c229bf47e30ac389563c82b11378e07 Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Fri, 3 Jul 2020 17:06:20 -0500
Subject: [PATCH 06/25] Add Captcha endpoint to CSP headers when MediaProxy is
enabled.
Our CSP rules are lax when MediaProxy enabled, but lenient otherwise.
This fixes broken captcha on instances not using MediaProxy.
---
lib/pleroma/plugs/http_security_plug.ex | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 1420a9611..f7192ebfc 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -125,11 +125,19 @@ defp get_proxy_and_attachment_sources do
if Config.get([Pleroma.Upload, :uploader]) == Pleroma.Uploaders.S3,
do: URI.parse(Config.get([Pleroma.Uploaders.S3, :public_endpoint])).host
+ captcha_method = Config.get([Pleroma.Captcha, :method])
+
+ captcha_endpoint =
+ if Config.get([Pleroma.Captcha, :enabled]) &&
+ captcha_method != "Pleroma.Captcha.Native",
+ do: Config.get([captcha_method, :endpoint])
+
[]
|> add_source(media_proxy_base_url)
|> add_source(upload_base_url)
|> add_source(s3_endpoint)
|> add_source(media_proxy_whitelist)
+ |> add_source(captcha_endpoint)
end
defp add_source(iodata, nil), do: iodata
From e9a28078ad969204faae600df3ddff8e75ed2f8a Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Fri, 3 Jul 2020 17:18:22 -0500
Subject: [PATCH 07/25] Rename function and clarify that CSP is only strict
with MediaProxy enabled
---
lib/pleroma/plugs/http_security_plug.ex | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index f7192ebfc..23a641faf 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -69,10 +69,11 @@ defp csp_string do
img_src = "img-src 'self' data: blob:"
media_src = "media-src 'self'"
+ # Strict multimedia CSP enforcement only when MediaProxy is enabled
{img_src, media_src} =
if Config.get([:media_proxy, :enabled]) &&
!Config.get([:media_proxy, :proxy_opts, :redirect_on_failure]) do
- sources = get_proxy_and_attachment_sources()
+ sources = build_csp_multimedia_source_list()
{[img_src, sources], [media_src, sources]}
else
{[img_src, " https:"], [media_src, " https:"]}
@@ -107,7 +108,7 @@ defp csp_string do
|> :erlang.iolist_to_binary()
end
- defp get_proxy_and_attachment_sources do
+ defp build_csp_multimedia_source_list do
media_proxy_whitelist =
Enum.reduce(Config.get([:media_proxy, :whitelist]), [], fn host, acc ->
add_source(acc, host)
From 991bd78ddad74641f8032c7b373771a5acb10da9 Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Fri, 3 Jul 2020 17:19:43 -0500
Subject: [PATCH 08/25] Document the Captcha CSP fix
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 85401809a..4b74d064c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -73,6 +73,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Resolving Peertube accounts with Webfinger
- `blob:` urls not being allowed by connect-src CSP
- Mastodon API: fix `GET /api/v1/notifications` not returning the full result set
+- Fix CSP policy generation to include remote Captcha services
## [Unreleased (patch)]
From af612bd006a2792e27f9b995c0c86e010cc77e6c Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Sun, 5 Jul 2020 10:11:43 -0500
Subject: [PATCH 09/25] Ensure all CSP parameters for remote hosts have a
scheme
---
lib/pleroma/plugs/http_security_plug.ex | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 23a641faf..3bf0b8ce7 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -116,22 +116,22 @@ defp build_csp_multimedia_source_list do
media_proxy_base_url =
if Config.get([:media_proxy, :base_url]),
- do: URI.parse(Config.get([:media_proxy, :base_url])).host
+ do: build_csp_param(Config.get([:media_proxy, :base_url]))
upload_base_url =
if Config.get([Pleroma.Upload, :base_url]),
- do: URI.parse(Config.get([Pleroma.Upload, :base_url])).host
+ do: build_csp_param(Config.get([Pleroma.Upload, :base_url]))
s3_endpoint =
if Config.get([Pleroma.Upload, :uploader]) == Pleroma.Uploaders.S3,
- do: URI.parse(Config.get([Pleroma.Uploaders.S3, :public_endpoint])).host
+ do: build_csp_param(Config.get([Pleroma.Uploaders.S3, :public_endpoint]))
captcha_method = Config.get([Pleroma.Captcha, :method])
captcha_endpoint =
if Config.get([Pleroma.Captcha, :enabled]) &&
captcha_method != "Pleroma.Captcha.Native",
- do: Config.get([captcha_method, :endpoint])
+ do: build_csp_param(Config.get([captcha_method, :endpoint]))
[]
|> add_source(media_proxy_base_url)
@@ -148,6 +148,14 @@ defp add_csp_param(csp_iodata, nil), do: csp_iodata
defp add_csp_param(csp_iodata, param), do: [[param, ?;] | csp_iodata]
+ defp build_csp_param(url) when is_binary(url) do
+ %{host: host, scheme: scheme} = URI.parse(url)
+
+ if scheme do
+ scheme <> "://" <> host
+ end
+ end
+
def warn_if_disabled do
unless Config.get([:http_security, :enabled]) do
Logger.warn("
From 65843d92c4d3999f727d00500dcf8943cfe7bbc0 Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Mon, 6 Jul 2020 10:59:41 -0500
Subject: [PATCH 10/25] Simplify the logic
---
lib/pleroma/plugs/http_security_plug.ex | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 3bf0b8ce7..13423ca3f 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -114,24 +114,15 @@ defp build_csp_multimedia_source_list do
add_source(acc, host)
end)
- media_proxy_base_url =
- if Config.get([:media_proxy, :base_url]),
- do: build_csp_param(Config.get([:media_proxy, :base_url]))
+ media_proxy_base_url = build_csp_param(Config.get([:media_proxy, :base_url]))
- upload_base_url =
- if Config.get([Pleroma.Upload, :base_url]),
- do: build_csp_param(Config.get([Pleroma.Upload, :base_url]))
+ upload_base_url = build_csp_param(Config.get([Pleroma.Upload, :base_url]))
- s3_endpoint =
- if Config.get([Pleroma.Upload, :uploader]) == Pleroma.Uploaders.S3,
- do: build_csp_param(Config.get([Pleroma.Uploaders.S3, :public_endpoint]))
+ s3_endpoint = build_csp_param(Config.get([Pleroma.Uploaders.S3, :public_endpoint]))
captcha_method = Config.get([Pleroma.Captcha, :method])
- captcha_endpoint =
- if Config.get([Pleroma.Captcha, :enabled]) &&
- captcha_method != "Pleroma.Captcha.Native",
- do: build_csp_param(Config.get([captcha_method, :endpoint]))
+ captcha_endpoint = build_csp_param(Config.get([captcha_method, :endpoint]))
[]
|> add_source(media_proxy_base_url)
@@ -148,6 +139,8 @@ defp add_csp_param(csp_iodata, nil), do: csp_iodata
defp add_csp_param(csp_iodata, param), do: [[param, ?;] | csp_iodata]
+ defp build_csp_param(nil), do: nil
+
defp build_csp_param(url) when is_binary(url) do
%{host: host, scheme: scheme} = URI.parse(url)
From da4029391d217b1e2c151e69479de42e2221e02f Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Mon, 6 Jul 2020 11:28:08 -0500
Subject: [PATCH 11/25] IO list, not concatenation
---
lib/pleroma/plugs/http_security_plug.ex | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 13423ca3f..472a3ff42 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -145,7 +145,7 @@ defp build_csp_param(url) when is_binary(url) do
%{host: host, scheme: scheme} = URI.parse(url)
if scheme do
- scheme <> "://" <> host
+ [scheme, "://", host]
end
end
From f6d09fafee83514889bbcf6531e0bc01e33b0b16 Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Sun, 1 Mar 2020 09:48:32 +0100
Subject: [PATCH 12/25] Add support for remote favicons
---
lib/pleroma/user.ex | 30 +++++++++++++++++++
.../web/mastodon_api/views/account_view.ex | 3 +-
test/support/http_request_mock.ex | 4 +++
.../mastodon_api/views/account_view_test.exs | 2 ++
4 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index e98332744..25ea112a2 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -2253,4 +2253,34 @@ def sanitize_html(%User{} = user, filter) do
|> Map.put(:bio, HTML.filter_tags(user.bio, filter))
|> Map.put(:fields, fields)
end
+
+ def get_cached_favicon(%User{} = user) do
+ key = "favicon:#{user.ap_id}"
+ Cachex.fetch!(:user_cache, key, fn _ -> get_favicon(user) end)
+ end
+
+ def get_cached_favicon(_user) do
+ nil
+ end
+
+ def get_favicon(user) do
+ try do
+ with url <- user.ap_id,
+ true <- is_binary(url),
+ {:ok, %Tesla.Env{body: html}} <- Pleroma.HTTP.get(url),
+ favicon_rel <-
+ html
+ |> Floki.parse_document!()
+ |> Floki.attribute("link[rel=icon]", "href")
+ |> List.first(),
+ favicon_url <- URI.merge(URI.parse(url), favicon_rel) |> to_string(),
+ true <- is_binary(favicon_url) do
+ favicon_url
+ else
+ _ -> nil
+ end
+ rescue
+ _ -> nil
+ end
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index a6e64b4ab..efe835e3c 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -245,7 +245,8 @@ defp do_render("show.json", %{user: user} = opts) do
hide_favorites: user.hide_favorites,
relationship: relationship,
skip_thread_containment: user.skip_thread_containment,
- background_image: image_url(user.background) |> MediaProxy.url()
+ background_image: image_url(user.background) |> MediaProxy.url(),
+ favicon: User.get_cached_favicon(user) |> MediaProxy.url()
}
}
|> maybe_put_role(user, opts[:for])
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index da04ac6f1..4d33c6250 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -1342,6 +1342,10 @@ def get("https://relay.mastodon.host/actor", _, _, _) do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/relay/relay.json")}}
end
+ def get("http://localhost:4001/users/" <> _, _, _, _) do
+ {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/7369654.html")}}
+ end
+
def get(url, query, body, headers) do
{:error,
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index 80b1f734c..e01a7c1ee 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -75,6 +75,7 @@ test "Represent a user account" do
pleroma: %{
ap_id: user.ap_id,
background_image: "https://example.com/images/asuka_hospital.png",
+ favicon: nil,
confirmation_pending: false,
tags: [],
is_admin: false,
@@ -152,6 +153,7 @@ test "Represent a Service(bot) account" do
pleroma: %{
ap_id: user.ap_id,
background_image: nil,
+ favicon: nil,
confirmation_pending: false,
tags: [],
is_admin: false,
From 6a679d80c9030afa8327377928f8ac2fcf1a4a0e Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Mon, 2 Mar 2020 05:38:25 +0100
Subject: [PATCH 13/25] Move get_favicon to Pleroma.Instances, use /
---
lib/pleroma/application.ex | 1 +
lib/pleroma/instances.ex | 28 ++
lib/pleroma/user.ex | 30 --
.../web/mastodon_api/views/account_view.ex | 11 +-
.../https___osada.macgirvin.com.html | 301 ++++++++++++++++++
test/support/http_request_mock.ex | 10 +-
.../mastodon_api/views/account_view_test.exs | 6 +-
7 files changed, 353 insertions(+), 34 deletions(-)
create mode 100644 test/fixtures/tesla_mock/https___osada.macgirvin.com.html
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 9615af122..c7fc95f75 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -150,6 +150,7 @@ defp cachex_children do
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
build_cachex("failed_proxy_url", limit: 2500),
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000)
+ build_cachex("instances", default_ttl: 25_000, ttl_interval: 1000, limit: 2500)
]
end
diff --git a/lib/pleroma/instances.ex b/lib/pleroma/instances.ex
index 557e8decf..c9b1ed4ce 100644
--- a/lib/pleroma/instances.ex
+++ b/lib/pleroma/instances.ex
@@ -37,4 +37,32 @@ def host(url_or_host) when is_binary(url_or_host) do
url_or_host
end
end
+
+ def get_cached_favicon(instance_url) when is_binary(instance_url) do
+ Cachex.fetch!(:instances_cache, instance_url, fn _ -> get_favicon(instance_url) end)
+ end
+
+ def get_cached_favicon(_instance_url) do
+ nil
+ end
+
+ def get_favicon(instance_url) when is_binary(instance_url) do
+ try do
+ with {:ok, %Tesla.Env{body: html}} <-
+ Pleroma.HTTP.get(instance_url, [{:Accept, "text/html"}]),
+ favicon_rel <-
+ html
+ |> Floki.parse_document!()
+ |> Floki.attribute("link[rel=icon]", "href")
+ |> List.first(),
+ favicon_url <- URI.merge(URI.parse(instance_url), favicon_rel) |> to_string(),
+ true <- is_binary(favicon_url) do
+ favicon_url
+ else
+ _ -> nil
+ end
+ rescue
+ _ -> nil
+ end
+ end
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 25ea112a2..e98332744 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -2253,34 +2253,4 @@ def sanitize_html(%User{} = user, filter) do
|> Map.put(:bio, HTML.filter_tags(user.bio, filter))
|> Map.put(:fields, fields)
end
-
- def get_cached_favicon(%User{} = user) do
- key = "favicon:#{user.ap_id}"
- Cachex.fetch!(:user_cache, key, fn _ -> get_favicon(user) end)
- end
-
- def get_cached_favicon(_user) do
- nil
- end
-
- def get_favicon(user) do
- try do
- with url <- user.ap_id,
- true <- is_binary(url),
- {:ok, %Tesla.Env{body: html}} <- Pleroma.HTTP.get(url),
- favicon_rel <-
- html
- |> Floki.parse_document!()
- |> Floki.attribute("link[rel=icon]", "href")
- |> List.first(),
- favicon_url <- URI.merge(URI.parse(url), favicon_rel) |> to_string(),
- true <- is_binary(favicon_url) do
- favicon_url
- else
- _ -> nil
- end
- rescue
- _ -> nil
- end
- end
end
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index efe835e3c..3ee50dfd0 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -204,6 +204,15 @@ defp do_render("show.json", %{user: user} = opts) do
%{}
end
+ favicon =
+ user
+ |> Map.get(:ap_id, "")
+ |> URI.parse()
+ |> URI.merge("/")
+ |> to_string()
+ |> Pleroma.Instances.get_cached_favicon()
+ |> MediaProxy.url()
+
%{
id: to_string(user.id),
username: username_from_nickname(user.nickname),
@@ -246,7 +255,7 @@ defp do_render("show.json", %{user: user} = opts) do
relationship: relationship,
skip_thread_containment: user.skip_thread_containment,
background_image: image_url(user.background) |> MediaProxy.url(),
- favicon: User.get_cached_favicon(user) |> MediaProxy.url()
+ favicon: favicon
}
}
|> maybe_put_role(user, opts[:for])
diff --git a/test/fixtures/tesla_mock/https___osada.macgirvin.com.html b/test/fixtures/tesla_mock/https___osada.macgirvin.com.html
new file mode 100644
index 000000000..880273d74
--- /dev/null
+++ b/test/fixtures/tesla_mock/https___osada.macgirvin.com.html
@@ -0,0 +1,301 @@
+
+
+
+ Osada
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Welcome to Osada
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index 4d33c6250..19a202654 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -1342,10 +1342,18 @@ def get("https://relay.mastodon.host/actor", _, _, _) do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/relay/relay.json")}}
end
- def get("http://localhost:4001/users/" <> _, _, _, _) do
+ def get("http://localhost:4001/", _, "", Accept: "text/html") do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/7369654.html")}}
end
+ def get("https://osada.macgirvin.com/", _, "", Accept: "text/html") do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/https___osada.macgirvin.com.html")
+ }}
+ end
+
def get(url, query, body, headers) do
{:error,
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index e01a7c1ee..c4341cb28 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -75,7 +75,8 @@ test "Represent a user account" do
pleroma: %{
ap_id: user.ap_id,
background_image: "https://example.com/images/asuka_hospital.png",
- favicon: nil,
+ favicon:
+ "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png",
confirmation_pending: false,
tags: [],
is_admin: false,
@@ -153,7 +154,8 @@ test "Represent a Service(bot) account" do
pleroma: %{
ap_id: user.ap_id,
background_image: nil,
- favicon: nil,
+ favicon:
+ "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png",
confirmation_pending: false,
tags: [],
is_admin: false,
From 013e2c505786dff311bcc8bf23631d6a1a1636ef Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Tue, 7 Jul 2020 11:13:38 +0200
Subject: [PATCH 14/25] Use instances table instead of Cachex
---
lib/pleroma/application.ex | 1 -
lib/pleroma/instances.ex | 28 ----------
lib/pleroma/instances/instance.ex | 55 ++++++++++++++++++-
.../web/mastodon_api/views/account_view.ex | 3 +-
.../20200707112859_instances_add_favicon.exs | 10 ++++
5 files changed, 65 insertions(+), 32 deletions(-)
create mode 100644 priv/repo/migrations/20200707112859_instances_add_favicon.exs
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index c7fc95f75..9615af122 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -150,7 +150,6 @@ defp cachex_children do
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
build_cachex("failed_proxy_url", limit: 2500),
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000)
- build_cachex("instances", default_ttl: 25_000, ttl_interval: 1000, limit: 2500)
]
end
diff --git a/lib/pleroma/instances.ex b/lib/pleroma/instances.ex
index c9b1ed4ce..557e8decf 100644
--- a/lib/pleroma/instances.ex
+++ b/lib/pleroma/instances.ex
@@ -37,32 +37,4 @@ def host(url_or_host) when is_binary(url_or_host) do
url_or_host
end
end
-
- def get_cached_favicon(instance_url) when is_binary(instance_url) do
- Cachex.fetch!(:instances_cache, instance_url, fn _ -> get_favicon(instance_url) end)
- end
-
- def get_cached_favicon(_instance_url) do
- nil
- end
-
- def get_favicon(instance_url) when is_binary(instance_url) do
- try do
- with {:ok, %Tesla.Env{body: html}} <-
- Pleroma.HTTP.get(instance_url, [{:Accept, "text/html"}]),
- favicon_rel <-
- html
- |> Floki.parse_document!()
- |> Floki.attribute("link[rel=icon]", "href")
- |> List.first(),
- favicon_url <- URI.merge(URI.parse(instance_url), favicon_rel) |> to_string(),
- true <- is_binary(favicon_url) do
- favicon_url
- else
- _ -> nil
- end
- rescue
- _ -> nil
- end
- end
end
diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex
index 74458c09a..b97e229e5 100644
--- a/lib/pleroma/instances/instance.ex
+++ b/lib/pleroma/instances/instance.ex
@@ -17,6 +17,8 @@ defmodule Pleroma.Instances.Instance do
schema "instances" do
field(:host, :string)
field(:unreachable_since, :naive_datetime_usec)
+ field(:favicon, :string)
+ field(:favicon_updated_at, :naive_datetime)
timestamps()
end
@@ -25,7 +27,7 @@ defmodule Pleroma.Instances.Instance do
def changeset(struct, params \\ %{}) do
struct
- |> cast(params, [:host, :unreachable_since])
+ |> cast(params, [:host, :unreachable_since, :favicon, :favicon_updated_at])
|> validate_required([:host])
|> unique_constraint(:host)
end
@@ -120,4 +122,55 @@ defp parse_datetime(datetime) when is_binary(datetime) do
end
defp parse_datetime(datetime), do: datetime
+
+ def get_or_update_favicon(%URI{host: host} = instance_uri) do
+ existing_record = Repo.get_by(Instance, %{host: host})
+ now = NaiveDateTime.utc_now()
+
+ if existing_record && existing_record.favicon &&
+ NaiveDateTime.diff(now, existing_record.favicon_updated_at) < 86_400 do
+ existing_record.favicon
+ else
+ favicon = scrape_favicon(instance_uri)
+
+ cond do
+ is_binary(favicon) && existing_record ->
+ existing_record
+ |> changeset(%{favicon: favicon, favicon_updated_at: now})
+ |> Repo.update()
+
+ favicon
+
+ is_binary(favicon) ->
+ %Instance{}
+ |> changeset(%{host: host, favicon: favicon, favicon_updated_at: now})
+ |> Repo.insert()
+
+ favicon
+
+ true ->
+ nil
+ end
+ end
+ end
+
+ defp scrape_favicon(%URI{} = instance_uri) do
+ try do
+ with {:ok, %Tesla.Env{body: html}} <-
+ Pleroma.HTTP.get(to_string(instance_uri), [{:Accept, "text/html"}]),
+ favicon_rel <-
+ html
+ |> Floki.parse_document!()
+ |> Floki.attribute("link[rel=icon]", "href")
+ |> List.first(),
+ favicon <- URI.merge(instance_uri, favicon_rel) |> to_string(),
+ true <- is_binary(favicon) do
+ favicon
+ else
+ _ -> nil
+ end
+ rescue
+ _ -> nil
+ end
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index 3ee50dfd0..db5739254 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -209,8 +209,7 @@ defp do_render("show.json", %{user: user} = opts) do
|> Map.get(:ap_id, "")
|> URI.parse()
|> URI.merge("/")
- |> to_string()
- |> Pleroma.Instances.get_cached_favicon()
+ |> Pleroma.Instances.Instance.get_or_update_favicon()
|> MediaProxy.url()
%{
diff --git a/priv/repo/migrations/20200707112859_instances_add_favicon.exs b/priv/repo/migrations/20200707112859_instances_add_favicon.exs
new file mode 100644
index 000000000..5538749dc
--- /dev/null
+++ b/priv/repo/migrations/20200707112859_instances_add_favicon.exs
@@ -0,0 +1,10 @@
+defmodule Pleroma.Repo.Migrations.InstancesAddFavicon do
+ use Ecto.Migration
+
+ def change do
+ alter table(:instances) do
+ add(:favicon, :string)
+ add(:favicon_updated_at, :naive_datetime)
+ end
+ end
+end
From 8c9df2d2e6a5a3639f6b411cd3e9b57248a0650c Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Tue, 7 Jul 2020 12:07:30 +0200
Subject: [PATCH 15/25] instance: Prevent loop of updates
---
lib/pleroma/instances/instance.ex | 29 +++++++++++------------------
1 file changed, 11 insertions(+), 18 deletions(-)
diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex
index b97e229e5..a1f935232 100644
--- a/lib/pleroma/instances/instance.ex
+++ b/lib/pleroma/instances/instance.ex
@@ -127,30 +127,23 @@ def get_or_update_favicon(%URI{host: host} = instance_uri) do
existing_record = Repo.get_by(Instance, %{host: host})
now = NaiveDateTime.utc_now()
- if existing_record && existing_record.favicon &&
+ if existing_record && existing_record.favicon_updated_at &&
NaiveDateTime.diff(now, existing_record.favicon_updated_at) < 86_400 do
existing_record.favicon
else
favicon = scrape_favicon(instance_uri)
- cond do
- is_binary(favicon) && existing_record ->
- existing_record
- |> changeset(%{favicon: favicon, favicon_updated_at: now})
- |> Repo.update()
-
- favicon
-
- is_binary(favicon) ->
- %Instance{}
- |> changeset(%{host: host, favicon: favicon, favicon_updated_at: now})
- |> Repo.insert()
-
- favicon
-
- true ->
- nil
+ if existing_record do
+ existing_record
+ |> changeset(%{favicon: favicon, favicon_updated_at: now})
+ |> Repo.update()
+ else
+ %Instance{}
+ |> changeset(%{host: host, favicon: favicon, favicon_updated_at: now})
+ |> Repo.insert()
end
+
+ favicon
end
end
From 312fc55f14e1b7f88ec43b72c577bf5df595beac Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Wed, 8 Jul 2020 05:56:24 +0200
Subject: [PATCH 16/25] Add [:instances_favicons, :enabled] setting, defaults
to false
---
config/config.exs | 2 ++
config/description.exs | 13 ++++++++++++
config/test.exs | 2 ++
docs/configuration/cheatsheet.md | 6 ++++++
.../web/mastodon_api/views/account_view.ex | 16 +++++++++------
.../mastodon_api/views/account_view_test.exs | 20 +++++++++++++++++++
6 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/config/config.exs b/config/config.exs
index 458d3a99a..3577cd101 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -706,6 +706,8 @@
config :ex_aws, http_client: Pleroma.HTTP.ExAws
+config :pleroma, :instances_favicons, enabled: false
+
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
diff --git a/config/description.exs b/config/description.exs
index 650610fbe..7c432d67d 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -3447,5 +3447,18 @@
suggestions: [false]
}
]
+ },
+ %{
+ group: :pleroma,
+ key: :instances_favicons,
+ type: :group,
+ description: "Control favicons for instances",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Allow/disallow displaying and getting instances favicons"
+ }
+ ]
}
]
diff --git a/config/test.exs b/config/test.exs
index e38b9967d..e6596e0bc 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -111,6 +111,8 @@
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
+config :pleroma, :instances_favicons, enabled: true
+
if File.exists?("./config/test.secret.exs") do
import_config "test.secret.exs"
else
diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md
index 6b640cebc..7a3200e01 100644
--- a/docs/configuration/cheatsheet.md
+++ b/docs/configuration/cheatsheet.md
@@ -987,3 +987,9 @@ Restrict access for unauthenticated users to timelines (public and federate), us
## Pleroma.Web.ApiSpec.CastAndValidate
* `:strict` a boolean, enables strict input validation (useful in development, not recommended in production). Defaults to `false`.
+
+## :instances_favicons
+
+Control favicons for instances.
+
+* `enabled`: Allow/disallow displaying and getting instances favicons
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index db5739254..2feba4778 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -205,12 +205,16 @@ defp do_render("show.json", %{user: user} = opts) do
end
favicon =
- user
- |> Map.get(:ap_id, "")
- |> URI.parse()
- |> URI.merge("/")
- |> Pleroma.Instances.Instance.get_or_update_favicon()
- |> MediaProxy.url()
+ if Pleroma.Config.get([:instances_favicons, :enabled]) do
+ user
+ |> Map.get(:ap_id, "")
+ |> URI.parse()
+ |> URI.merge("/")
+ |> Pleroma.Instances.Instance.get_or_update_favicon()
+ |> MediaProxy.url()
+ else
+ nil
+ end
%{
id: to_string(user.id),
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index c4341cb28..ac6d50e3a 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
use Pleroma.DataCase
+ alias Pleroma.Config
alias Pleroma.User
alias Pleroma.UserRelationship
alias Pleroma.Web.CommonAPI
@@ -18,6 +19,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
:ok
end
+ setup do: clear_config([:instances_favicons, :enabled])
+
test "Represent a user account" do
background_image = %{
"url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]
@@ -94,6 +97,23 @@ test "Represent a user account" do
assert expected == AccountView.render("show.json", %{user: user})
end
+ test "Favicon is nil when :instances_favicons is disabled" do
+ user = insert(:user)
+
+ Config.put([:instances_favicons, :enabled], true)
+
+ assert %{
+ pleroma: %{
+ favicon:
+ "https://shitposter.club/plugins/Qvitter/img/gnusocial-favicons/favicon-16x16.png"
+ }
+ } = AccountView.render("show.json", %{user: user})
+
+ Config.put([:instances_favicons, :enabled], false)
+
+ assert %{pleroma: %{favicon: nil}} = AccountView.render("show.json", %{user: user})
+ end
+
test "Represent the user account for the account owner" do
user = insert(:user)
From 31fef95e35d3cbc2d65c76a57ba8f4047809ce1b Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier"
Date: Wed, 8 Jul 2020 06:09:39 +0200
Subject: [PATCH 17/25] Add changelog and documentation
---
CHANGELOG.md | 2 ++
docs/API/differences_in_mastoapi_responses.md | 1 +
lib/pleroma/web/api_spec/schemas/account.ex | 6 ++++++
3 files changed, 9 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92d8c3d8e..0f3447069 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -55,6 +55,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Added `:reject_deletes` group to SimplePolicy
- MRF (`EmojiStealPolicy`): New MRF Policy which allows to automatically download emojis from remote instances
- Support pagination in emoji packs API (for packs and for files in pack)
+- Support for viewing instances favicons next to posts and accounts
API Changes
@@ -65,6 +66,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Add support for filtering replies in public and home timelines.
- Mastodon API: Support for `bot` field in `/api/v1/accounts/update_credentials`.
- Mastodon API: Support irreversible property for filters.
+- Mastodon API: Add pleroma.favicon field to accounts.
- Admin API: endpoints for create/update/delete OAuth Apps.
- Admin API: endpoint for status view.
- OTP: Add command to reload emoji packs
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index 29141ed0c..03c7f4608 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -71,6 +71,7 @@ Has these additional fields under the `pleroma` object:
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
- `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
- `notification_settings`: object, can be absent. See `/api/pleroma/notification_settings` for the parameters/keys returned.
+- `favicon`: nullable URL string, Favicon image of the user's instance
### Source
diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex
index 84f18f1b6..e6f163cb7 100644
--- a/lib/pleroma/web/api_spec/schemas/account.ex
+++ b/lib/pleroma/web/api_spec/schemas/account.ex
@@ -102,6 +102,12 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
type: :object,
description:
"A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`"
+ },
+ favicon: %Schema{
+ type: :string,
+ format: :uri,
+ nullable: true,
+ description: "Favicon image of the user's instance"
}
}
},
From c0385cf47ae9c2dac527387225dee7d45dd33d8c Mon Sep 17 00:00:00 2001
From: lain
Date: Wed, 8 Jul 2020 11:52:29 +0200
Subject: [PATCH 18/25] AccountController: Fix muting / unmuting reblogs.
---
.../api_spec/operations/account_operation.ex | 23 ++++++++----
.../controllers/account_controller.ex | 2 +-
.../controllers/account_controller_test.exs | 37 ++++++++++++++++++-
3 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 9bde8fc0d..989bab122 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -203,14 +203,23 @@ def follow_operation do
security: [%{"oAuth" => ["follow", "write:follows"]}],
description: "Follow the given account",
parameters: [
- %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
- Operation.parameter(
- :reblogs,
- :query,
- BooleanLike,
- "Receive this account's reblogs in home timeline? Defaults to true."
- )
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
],
+ requestBody:
+ request_body(
+ "Parameters",
+ %Schema{
+ type: :object,
+ properties: %{
+ reblogs: %Schema{
+ type: :boolean,
+ description: "Receive this account's reblogs in home timeline? Defaults to true.",
+ default: true
+ }
+ }
+ },
+ required: false
+ ),
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index d4532258c..fd89faf02 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -353,7 +353,7 @@ def follow(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
{:error, "Can not follow yourself"}
end
- def follow(%{assigns: %{user: follower, account: followed}} = conn, params) do
+ def follow(%{body_params: params, assigns: %{user: follower, account: followed}} = conn, _) do
with {:ok, follower} <- MastodonAPI.follow(follower, followed, params) do
render(conn, "relationship.json", user: follower, target: followed)
else
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index 260ad2306..f102c0cd2 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -708,7 +708,10 @@ test "following without reblogs" do
followed = insert(:user)
other_user = insert(:user)
- ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=false")
+ ret_conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200)
@@ -722,7 +725,8 @@ test "following without reblogs" do
assert %{"showing_reblogs" => true} =
conn
- |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: true})
|> json_response_and_validate_schema(200)
assert [%{"id" => ^reblog_id}] =
@@ -731,6 +735,35 @@ test "following without reblogs" do
|> json_response(200)
end
+ test "following with reblogs" do
+ %{conn: conn} = oauth_access(["follow", "read:statuses"])
+ followed = insert(:user)
+ other_user = insert(:user)
+
+ ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow")
+
+ assert %{"showing_reblogs" => true} = json_response_and_validate_schema(ret_conn, 200)
+
+ {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"})
+ {:ok, %{id: reblog_id}} = CommonAPI.repeat(activity.id, followed)
+
+ assert [%{"id" => ^reblog_id}] =
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
+
+ assert %{"showing_reblogs" => false} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{followed.id}/follow", %{reblogs: false})
+ |> json_response_and_validate_schema(200)
+
+ assert [] ==
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
+ end
+
test "following / unfollowing errors", %{user: user, conn: conn} do
# self follow
conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
From 704a3830556d94e0dbc39873480e9ba95a143be9 Mon Sep 17 00:00:00 2001
From: Ivan Tashkinov
Date: Wed, 8 Jul 2020 13:14:18 +0300
Subject: [PATCH 19/25] Improved search results for localized nickname match.
Tweaked user search to rank nickname matches higher than name matches.
---
lib/pleroma/user/search.ex | 8 +++++++-
test/tasks/user_test.exs | 16 ++++++++--------
test/user_search_test.exs | 35 +++++++++++++++++++++++++++++------
3 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index 42ff1de78..7ff1c7e24 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -88,15 +88,21 @@ defp to_tsquery(query_string) do
|> Enum.join(" | ")
end
+ # Considers nickname match, localized nickname match, name match; preferences nickname match
defp trigram_rank(query, query_string) do
from(
u in query,
select_merge: %{
search_rank:
fragment(
- "similarity(?, trim(? || ' ' || coalesce(?, '')))",
+ "similarity(?, ?) + \
+ similarity(?, regexp_replace(?, '@.+', '')) + \
+ similarity(?, trim(coalesce(?, '')))",
^query_string,
u.nickname,
+ ^query_string,
+ u.nickname,
+ ^query_string,
u.name
)
}
diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs
index 9220d23fc..7bb49b038 100644
--- a/test/tasks/user_test.exs
+++ b/test/tasks/user_test.exs
@@ -464,17 +464,17 @@ test "it returns users matching" do
moot = insert(:user, nickname: "moot")
kawen = insert(:user, nickname: "kawen", name: "fediverse expert moon")
- {:ok, user} = User.follow(user, kawen)
+ {:ok, user} = User.follow(user, moon)
assert [moon.id, kawen.id] == User.Search.search("moon") |> Enum.map(& &1.id)
- res = User.search("moo") |> Enum.map(& &1.id)
- assert moon.id in res
- assert moot.id in res
- assert kawen.id in res
- assert [moon.id, kawen.id] == User.Search.search("moon fediverse") |> Enum.map(& &1.id)
- assert [kawen.id, moon.id] ==
- User.Search.search("moon fediverse", for_user: user) |> Enum.map(& &1.id)
+ res = User.search("moo") |> Enum.map(& &1.id)
+ assert Enum.sort([moon.id, moot.id, kawen.id]) == Enum.sort(res)
+
+ assert [kawen.id, moon.id] == User.Search.search("expert fediverse") |> Enum.map(& &1.id)
+
+ assert [moon.id, kawen.id] ==
+ User.Search.search("expert fediverse", for_user: user) |> Enum.map(& &1.id)
end
end
diff --git a/test/user_search_test.exs b/test/user_search_test.exs
index f030523d3..758822072 100644
--- a/test/user_search_test.exs
+++ b/test/user_search_test.exs
@@ -46,30 +46,53 @@ test "accepts offset parameter" do
assert length(User.search("john", limit: 3, offset: 3)) == 2
end
- test "finds a user by full or partial nickname" do
+ defp clear_virtual_fields(user) do
+ Map.merge(user, %{search_rank: nil, search_type: nil})
+ end
+
+ test "finds a user by full nickname or its leading fragment" do
user = insert(:user, %{nickname: "john"})
Enum.each(["john", "jo", "j"], fn query ->
assert user ==
User.search(query)
|> List.first()
- |> Map.put(:search_rank, nil)
- |> Map.put(:search_type, nil)
+ |> clear_virtual_fields()
end)
end
- test "finds a user by full or partial name" do
+ test "finds a user by full name or leading fragment(s) of its words" do
user = insert(:user, %{name: "John Doe"})
Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->
assert user ==
User.search(query)
|> List.first()
- |> Map.put(:search_rank, nil)
- |> Map.put(:search_type, nil)
+ |> clear_virtual_fields()
end)
end
+ test "is not [yet] capable of matching by non-leading fragments (e.g. by domain)" do
+ user1 = insert(:user, %{nickname: "iamthedude"})
+ insert(:user, %{nickname: "arandom@dude.com"})
+
+ assert [] == User.search("dude")
+
+ # Matching by leading fragment works, though
+ user1_id = user1.id
+ assert ^user1_id = User.search("iam") |> List.first() |> Map.get(:id)
+ end
+
+ test "ranks full nickname match higher than full name match" do
+ nicknamed_user = insert(:user, %{nickname: "hj@shigusegubu.club"})
+ named_user = insert(:user, %{nickname: "xyz@sample.com", name: "HJ"})
+
+ results = User.search("hj")
+
+ assert [nicknamed_user.id, named_user.id] == Enum.map(results, & &1.id)
+ assert Enum.at(results, 0).search_rank > Enum.at(results, 1).search_rank
+ end
+
test "finds users, considering density of matched tokens" do
u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})
From 123352ffa1c80aab658fca0c2276d1c06de43a02 Mon Sep 17 00:00:00 2001
From: Ivan Tashkinov
Date: Wed, 8 Jul 2020 22:50:15 +0300
Subject: [PATCH 20/25] Removed unused trigram index on `users`. Fixed
`users_fts_index` usage.
---
lib/pleroma/user/search.ex | 16 +++++++++++-----
.../20200708193702_drop_user_trigram_index.exs | 18 ++++++++++++++++++
test/user_search_test.exs | 12 ++++--------
3 files changed, 33 insertions(+), 13 deletions(-)
create mode 100644 priv/repo/migrations/20200708193702_drop_user_trigram_index.exs
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index 7ff1c7e24..d4fd31069 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -69,11 +69,15 @@ defp fts_search(query, query_string) do
u in query,
where:
fragment(
+ # The fragment must _exactly_ match `users_fts_index`, otherwise the index won't work
"""
- (to_tsvector('simple', ?) || to_tsvector('simple', ?)) @@ to_tsquery('simple', ?)
+ (
+ setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') ||
+ setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B')
+ ) @@ to_tsquery('simple', ?)
""",
- u.name,
u.nickname,
+ u.name,
^query_string
)
)
@@ -95,9 +99,11 @@ defp trigram_rank(query, query_string) do
select_merge: %{
search_rank:
fragment(
- "similarity(?, ?) + \
- similarity(?, regexp_replace(?, '@.+', '')) + \
- similarity(?, trim(coalesce(?, '')))",
+ """
+ similarity(?, ?) +
+ similarity(?, regexp_replace(?, '@.+', '')) +
+ similarity(?, trim(coalesce(?, '')))
+ """,
^query_string,
u.nickname,
^query_string,
diff --git a/priv/repo/migrations/20200708193702_drop_user_trigram_index.exs b/priv/repo/migrations/20200708193702_drop_user_trigram_index.exs
new file mode 100644
index 000000000..94efe323a
--- /dev/null
+++ b/priv/repo/migrations/20200708193702_drop_user_trigram_index.exs
@@ -0,0 +1,18 @@
+defmodule Pleroma.Repo.Migrations.DropUserTrigramIndex do
+ @moduledoc "Drops unused trigram index on `users` (FTS index is being used instead)"
+
+ use Ecto.Migration
+
+ def up do
+ drop_if_exists(index(:users, [], name: :users_trigram_index))
+ end
+
+ def down do
+ create_if_not_exists(
+ index(:users, ["(trim(nickname || ' ' || coalesce(name, ''))) gist_trgm_ops"],
+ name: :users_trigram_index,
+ using: :gist
+ )
+ )
+ end
+end
diff --git a/test/user_search_test.exs b/test/user_search_test.exs
index 758822072..559ba5966 100644
--- a/test/user_search_test.exs
+++ b/test/user_search_test.exs
@@ -72,15 +72,11 @@ test "finds a user by full name or leading fragment(s) of its words" do
end)
end
- test "is not [yet] capable of matching by non-leading fragments (e.g. by domain)" do
- user1 = insert(:user, %{nickname: "iamthedude"})
- insert(:user, %{nickname: "arandom@dude.com"})
+ test "matches by leading fragment of user domain" do
+ user = insert(:user, %{nickname: "arandom@dude.com"})
+ insert(:user, %{nickname: "iamthedude"})
- assert [] == User.search("dude")
-
- # Matching by leading fragment works, though
- user1_id = user1.id
- assert ^user1_id = User.search("iam") |> List.first() |> Map.get(:id)
+ assert [user.id] == User.search("dud") |> Enum.map(& &1.id)
end
test "ranks full nickname match higher than full name match" do
From d23804f191eb9e14cfb087863320ae90653c9544 Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Thu, 9 Jul 2020 10:53:51 -0500
Subject: [PATCH 21/25] Use the Pleroma.Config alias
---
lib/mix/tasks/pleroma/instance.ex | 4 +-
lib/pleroma/application.ex | 2 +-
lib/pleroma/emails/admin_email.ex | 2 +-
lib/pleroma/emoji/loader.ex | 2 +-
lib/pleroma/plugs/http_security_plug.ex | 4 +-
lib/pleroma/user.ex | 52 +++++++++----------
.../web/activity_pub/mrf/object_age_policy.ex | 2 +-
.../web/activity_pub/mrf/reject_non_public.ex | 2 +-
.../web/activity_pub/mrf/simple_policy.ex | 2 +-
lib/pleroma/web/common_api/utils.ex | 6 +--
lib/pleroma/web/media_proxy/media_proxy.ex | 2 +-
.../controllers/util_controller.ex | 2 +-
12 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index 86409738a..91440b453 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -145,7 +145,7 @@ def run(["gen" | rest]) do
options,
:uploads_dir,
"What directory should media uploads go in (when using the local uploader)?",
- Pleroma.Config.get([Pleroma.Uploaders.Local, :uploads])
+ Config.get([Pleroma.Uploaders.Local, :uploads])
)
|> Path.expand()
@@ -154,7 +154,7 @@ def run(["gen" | rest]) do
options,
:static_dir,
"What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
- Pleroma.Config.get([:instance, :static_dir])
+ Config.get([:instance, :static_dir])
)
|> Path.expand()
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 9615af122..32773d3c9 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -35,7 +35,7 @@ def user_agent do
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
- Pleroma.Config.Holder.save_default()
+ Config.Holder.save_default()
Pleroma.HTML.compile_scrubbers()
Config.DeprecationWarnings.warn()
Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex
index 55f61024e..c67ba63ad 100644
--- a/lib/pleroma/emails/admin_email.ex
+++ b/lib/pleroma/emails/admin_email.ex
@@ -10,7 +10,7 @@ defmodule Pleroma.Emails.AdminEmail do
alias Pleroma.Config
alias Pleroma.Web.Router.Helpers
- defp instance_config, do: Pleroma.Config.get(:instance)
+ defp instance_config, do: Config.get(:instance)
defp instance_name, do: instance_config()[:name]
defp instance_notify_email do
diff --git a/lib/pleroma/emoji/loader.ex b/lib/pleroma/emoji/loader.ex
index 3de2dc762..03a6bca0b 100644
--- a/lib/pleroma/emoji/loader.ex
+++ b/lib/pleroma/emoji/loader.ex
@@ -108,7 +108,7 @@ defp load_pack(pack_dir, emoji_groups) do
if File.exists?(emoji_txt) do
load_from_file(emoji_txt, emoji_groups)
else
- extensions = Pleroma.Config.get([:emoji, :pack_extensions])
+ extensions = Config.get([:emoji, :pack_extensions])
Logger.info(
"No emoji.txt found for pack \"#{pack_name}\", assuming all #{
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 472a3ff42..7d65cf078 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -82,14 +82,14 @@ defp csp_string do
connect_src = ["connect-src 'self' blob: ", static_url, ?\s, websocket_url]
connect_src =
- if Pleroma.Config.get(:env) == :dev do
+ if Config.get(:env) == :dev do
[connect_src, " http://localhost:3035/"]
else
connect_src
end
script_src =
- if Pleroma.Config.get(:env) == :dev do
+ if Config.get(:env) == :dev do
"script-src 'self' 'unsafe-eval'"
else
"script-src 'self'"
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 9d1314f81..0078f9831 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -388,8 +388,8 @@ defp fix_follower_address(%{nickname: nickname} = params),
defp fix_follower_address(params), do: params
def remote_user_changeset(struct \\ %User{local: false}, params) do
- bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
- name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+ bio_limit = Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Config.get([:instance, :user_name_length], 100)
name =
case params[:name] do
@@ -448,8 +448,8 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do
end
def update_changeset(struct, params \\ %{}) do
- bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
- name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+ bio_limit = Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Config.get([:instance, :user_name_length], 100)
struct
|> cast(
@@ -618,12 +618,12 @@ def force_password_reset_async(user) do
def force_password_reset(user), do: update_password_reset_pending(user, true)
def register_changeset(struct, params \\ %{}, opts \\ []) do
- bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
- name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+ bio_limit = Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Config.get([:instance, :user_name_length], 100)
need_confirmation? =
if is_nil(opts[:need_confirmation]) do
- Pleroma.Config.get([:instance, :account_activation_required])
+ Config.get([:instance, :account_activation_required])
else
opts[:need_confirmation]
end
@@ -644,7 +644,7 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do
|> validate_confirmation(:password)
|> unique_constraint(:email)
|> unique_constraint(:nickname)
- |> validate_exclusion(:nickname, Pleroma.Config.get([User, :restricted_nicknames]))
+ |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
|> validate_format(:nickname, local_nickname_regex())
|> validate_format(:email, @email_regex)
|> validate_length(:bio, max: bio_limit)
@@ -659,7 +659,7 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do
def maybe_validate_required_email(changeset, true), do: changeset
def maybe_validate_required_email(changeset, _) do
- if Pleroma.Config.get([:instance, :account_activation_required]) do
+ if Config.get([:instance, :account_activation_required]) do
validate_required(changeset, [:email])
else
changeset
@@ -679,7 +679,7 @@ defp put_following_and_follower_address(changeset) do
end
defp autofollow_users(user) do
- candidates = Pleroma.Config.get([:instance, :autofollowed_nicknames])
+ candidates = Config.get([:instance, :autofollowed_nicknames])
autofollowed_users =
User.Query.build(%{nickname: candidates, local: true, deactivated: false})
@@ -706,7 +706,7 @@ def post_register_action(%User{} = user) do
def try_send_confirmation_email(%User{} = user) do
if user.confirmation_pending &&
- Pleroma.Config.get([:instance, :account_activation_required]) do
+ Config.get([:instance, :account_activation_required]) do
user
|> Pleroma.Emails.UserEmail.account_confirmation_email()
|> Pleroma.Emails.Mailer.deliver_async()
@@ -763,7 +763,7 @@ def follow_all(follower, followeds) do
defdelegate following(user), to: FollowingRelationship
def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do
- deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
+ deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
cond do
followed.deactivated ->
@@ -964,7 +964,7 @@ def get_cached_by_nickname(nickname) do
end
def get_cached_by_nickname_or_id(nickname_or_id, opts \\ []) do
- restrict_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
+ restrict_to_local = Config.get([:instance, :limit_to_local_content])
cond do
is_integer(nickname_or_id) or FlakeId.flake_id?(nickname_or_id) ->
@@ -1160,7 +1160,7 @@ defp follow_information_changeset(user, params) do
@spec update_follower_count(User.t()) :: {:ok, User.t()}
def update_follower_count(%User{} = user) do
- if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do
+ if user.local or !Config.get([:instance, :external_user_synchronization]) do
follower_count = FollowingRelationship.follower_count(user)
user
@@ -1173,7 +1173,7 @@ def update_follower_count(%User{} = user) do
@spec update_following_count(User.t()) :: {:ok, User.t()}
def update_following_count(%User{local: false} = user) do
- if Pleroma.Config.get([:instance, :external_user_synchronization]) do
+ if Config.get([:instance, :external_user_synchronization]) do
{:ok, maybe_fetch_follow_information(user)}
else
{:ok, user}
@@ -1260,7 +1260,7 @@ def unmute(%User{} = muter, %User{} = mutee) do
end
def subscribe(%User{} = subscriber, %User{} = target) do
- deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
+ deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
if blocks?(target, subscriber) and deny_follow_blocked do
{:error, "Could not subscribe: #{target.nickname} is blocking you"}
@@ -1651,7 +1651,7 @@ def html_filter_policy(%User{no_rich_text: true}) do
Pleroma.HTML.Scrubber.TwitterText
end
- def html_filter_policy(_), do: Pleroma.Config.get([:markup, :scrub_policy])
+ def html_filter_policy(_), do: Config.get([:markup, :scrub_policy])
def fetch_by_ap_id(ap_id), do: ActivityPub.make_user_from_ap_id(ap_id)
@@ -1833,7 +1833,7 @@ defp normalize_tags(tags) do
end
defp local_nickname_regex do
- if Pleroma.Config.get([:instance, :extended_nickname_format]) do
+ if Config.get([:instance, :extended_nickname_format]) do
@extended_local_nickname_regex
else
@strict_local_nickname_regex
@@ -1961,8 +1961,8 @@ def get_mascot(%{mascot: %{} = mascot}) when not is_nil(mascot) do
def get_mascot(%{mascot: mascot}) when is_nil(mascot) do
# use instance-default
- config = Pleroma.Config.get([:assets, :mascots])
- default_mascot = Pleroma.Config.get([:assets, :default_mascot])
+ config = Config.get([:assets, :mascots])
+ default_mascot = Config.get([:assets, :default_mascot])
mascot = Keyword.get(config, default_mascot)
%{
@@ -2057,7 +2057,7 @@ def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
def validate_fields(changeset, remote? \\ false) do
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
- limit = Pleroma.Config.get([:instance, limit_name], 0)
+ limit = Config.get([:instance, limit_name], 0)
changeset
|> validate_length(:fields, max: limit)
@@ -2071,8 +2071,8 @@ def validate_fields(changeset, remote? \\ false) do
end
defp valid_field?(%{"name" => name, "value" => value}) do
- name_limit = Pleroma.Config.get([:instance, :account_field_name_length], 255)
- value_limit = Pleroma.Config.get([:instance, :account_field_value_length], 255)
+ name_limit = Config.get([:instance, :account_field_name_length], 255)
+ value_limit = Config.get([:instance, :account_field_value_length], 255)
is_binary(name) && is_binary(value) && String.length(name) <= name_limit &&
String.length(value) <= value_limit
@@ -2082,10 +2082,10 @@ defp valid_field?(_), do: false
defp truncate_field(%{"name" => name, "value" => value}) do
{name, _chopped} =
- String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255))
+ String.split_at(name, Config.get([:instance, :account_field_name_length], 255))
{value, _chopped} =
- String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255))
+ String.split_at(value, Config.get([:instance, :account_field_value_length], 255))
%{"name" => name, "value" => value}
end
@@ -2140,7 +2140,7 @@ def confirmation_changeset(user, need_confirmation: need_confirmation?) do
def add_pinnned_activity(user, %Pleroma.Activity{id: id}) do
if id not in user.pinned_activities do
- max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0)
+ max_pinned_statuses = Config.get([:instance, :max_pinned_statuses], 0)
params = %{pinned_activities: user.pinned_activities ++ [id]}
user
diff --git a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
index b0ccb63c8..a62914135 100644
--- a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
@@ -98,7 +98,7 @@ def filter(message), do: {:ok, message}
@impl true
def describe do
mrf_object_age =
- Pleroma.Config.get(:mrf_object_age)
+ Config.get(:mrf_object_age)
|> Enum.into(%{})
{:ok, %{mrf_object_age: mrf_object_age}}
diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
index 3092f3272..4fd63106d 100644
--- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
+++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
@@ -47,5 +47,5 @@ def filter(object), do: {:ok, object}
@impl true
def describe,
- do: {:ok, %{mrf_rejectnonpublic: Pleroma.Config.get(:mrf_rejectnonpublic) |> Enum.into(%{})}}
+ do: {:ok, %{mrf_rejectnonpublic: Config.get(:mrf_rejectnonpublic) |> Enum.into(%{})}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index 9cea6bcf9..70a2ca053 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -155,7 +155,7 @@ def filter(%{"type" => "Delete", "actor" => actor} = object) do
%{host: actor_host} = URI.parse(actor)
reject_deletes =
- Pleroma.Config.get([:mrf_simple, :reject_deletes])
+ Config.get([:mrf_simple, :reject_deletes])
|> MRF.subdomains_regex()
if MRF.subdomain_match?(reject_deletes, actor_host) do
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 15594125f..9c38b73eb 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -143,7 +143,7 @@ def make_poll_data(%{"poll" => %{"expires_in" => expires_in}} = data)
def make_poll_data(%{poll: %{options: options, expires_in: expires_in}} = data)
when is_list(options) do
- limits = Pleroma.Config.get([:instance, :poll_limits])
+ limits = Config.get([:instance, :poll_limits])
with :ok <- validate_poll_expiration(expires_in, limits),
:ok <- validate_poll_options_amount(options, limits),
@@ -502,7 +502,7 @@ def maybe_extract_mentions(_), do: []
def make_report_content_html(nil), do: {:ok, {nil, [], []}}
def make_report_content_html(comment) do
- max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
+ max_size = Config.get([:instance, :max_report_comment_size], 1000)
if String.length(comment) <= max_size do
{:ok, format_input(comment, "text/plain")}
@@ -564,7 +564,7 @@ def validate_character_limit("" = _full_payload, [] = _attachments) do
end
def validate_character_limit(full_payload, _attachments) do
- limit = Pleroma.Config.get([:instance, :limit])
+ limit = Config.get([:instance, :limit])
length = String.length(full_payload)
if length <= limit do
diff --git a/lib/pleroma/web/media_proxy/media_proxy.ex b/lib/pleroma/web/media_proxy/media_proxy.ex
index 077fabe47..6f35826da 100644
--- a/lib/pleroma/web/media_proxy/media_proxy.ex
+++ b/lib/pleroma/web/media_proxy/media_proxy.ex
@@ -106,7 +106,7 @@ def filename(url_or_path) do
def build_url(sig_base64, url_base64, filename \\ nil) do
[
- Pleroma.Config.get([:media_proxy, :base_url], Web.base_url()),
+ Config.get([:media_proxy, :base_url], Web.base_url()),
"proxy",
sig_base64,
url_base64,
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 8314e75b4..f02c4075c 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -83,7 +83,7 @@ def notifications_read(%{assigns: %{user: user}} = conn, %{"id" => notification_
def frontend_configurations(conn, _params) do
config =
- Pleroma.Config.get(:frontend_configurations, %{})
+ Config.get(:frontend_configurations, %{})
|> Enum.into(%{})
json(conn, config)
From 2b979cc90c4e466a8d0a83706e642b325cc24d0e Mon Sep 17 00:00:00 2001
From: Mark Felder
Date: Thu, 9 Jul 2020 11:55:40 -0500
Subject: [PATCH 22/25] Add AdminFE reports URL to report emails
---
lib/pleroma/emails/admin_email.ex | 2 ++
test/emails/admin_email_test.exs | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex
index c67ba63ad..aa0b2a66b 100644
--- a/lib/pleroma/emails/admin_email.ex
+++ b/lib/pleroma/emails/admin_email.ex
@@ -72,6 +72,8 @@ def report(to, reporter, account, statuses, comment) do
Reported Account: #{account.nickname}
#{comment_html}
#{statuses_html}
+
+ View Reports in AdminFE
"""
new()
diff --git a/test/emails/admin_email_test.exs b/test/emails/admin_email_test.exs
index bc871a0a9..9082ae5a7 100644
--- a/test/emails/admin_email_test.exs
+++ b/test/emails/admin_email_test.exs
@@ -31,7 +31,7 @@ test "build report email" do
account_url
}\">#{account.nickname}
\nComment: Test comment\n
Statuses:\n
\n
\n\n"
+ }\">#{status_url}\n \n\n\n\nView Reports in AdminFE\n"
end
test "it works when the reporter is a remote user without email" do
From b6688030fad62cc8be32faf928ff6ec418940efc Mon Sep 17 00:00:00 2001
From: Alexander Strizhakov
Date: Fri, 10 Jul 2020 10:35:59 +0300
Subject: [PATCH 23/25] prometheus update for OTP 23
---
mix.exs | 1 +
mix.lock | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/mix.exs b/mix.exs
index e2ab53bde..126aa4709 100644
--- a/mix.exs
+++ b/mix.exs
@@ -178,6 +178,7 @@ defp deps do
ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"},
{:telemetry, "~> 0.3"},
{:poolboy, "~> 1.5"},
+ {:prometheus, "~> 4.6"},
{:prometheus_ex, "~> 3.0"},
{:prometheus_plugs, "~> 1.1"},
{:prometheus_phoenix, "~> 1.3"},
diff --git a/mix.lock b/mix.lock
index 4f2777fa7..30464ddf2 100644
--- a/mix.lock
+++ b/mix.lock
@@ -92,7 +92,7 @@
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
"postgrex": {:hex, :postgrex, "0.15.3", "5806baa8a19a68c4d07c7a624ccdb9b57e89cbc573f1b98099e3741214746ae4", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4737ce62a31747b4c63c12b20c62307e51bb4fcd730ca0c32c280991e0606c90"},
"pot": {:hex, :pot, "0.10.2", "9895c83bcff8cd22d9f5bc79dfc88a188176b261b618ad70d93faf5c5ca36e67", [:rebar3], [], "hexpm", "ac589a8e296b7802681e93cd0a436faec117ea63e9916709c628df31e17e91e2"},
- "prometheus": {:hex, :prometheus, "4.5.0", "8f4a2246fe0beb50af0f77c5e0a5bb78fe575c34a9655d7f8bc743aad1c6bf76", [:mix, :rebar3], [], "hexpm", "679b5215480fff612b8351f45c839d995a07ce403e42ff02f1c6b20960d41a4e"},
+ "prometheus": {:hex, :prometheus, "4.6.0", "20510f381db1ccab818b4cf2fac5fa6ab5cc91bc364a154399901c001465f46f", [:mix, :rebar3], [], "hexpm", "4905fd2992f8038eccd7aa0cd22f40637ed618c0bed1f75c05aacec15b7545de"},
"prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "8d66289f77f913b37eda81fd287340c17e61a447549deb28efc254532b2bed82"},
"prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm", "9fd13404a48437e044b288b41f76e64acd9735fb8b0e3809f494811dfa66d0fb"},
"prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "c4d1404ac4e9d3d963da601db2a7d8ea31194f0017057fabf0cfb9bf5a6c8c75"},
From 11c9654a32830b2e36efd42324069c637719555e Mon Sep 17 00:00:00 2001
From: Ben Is
Date: Wed, 8 Jul 2020 22:51:39 +0000
Subject: [PATCH 24/25] Translated using Weblate (Polish)
Currently translated at 66.0% (70 of 106 strings)
Translation: Pleroma/Pleroma backend
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma/pl/
---
priv/gettext/pl/LC_MESSAGES/errors.po | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/priv/gettext/pl/LC_MESSAGES/errors.po b/priv/gettext/pl/LC_MESSAGES/errors.po
index 7bc39c52a..7241d8a0a 100644
--- a/priv/gettext/pl/LC_MESSAGES/errors.po
+++ b/priv/gettext/pl/LC_MESSAGES/errors.po
@@ -3,8 +3,8 @@ 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 \n"
+"PO-Revision-Date: 2020-07-09 14:40+0000\n"
+"Last-Translator: Ben Is \n"
"Language-Team: Polish \n"
"Language: pl\n"
@@ -50,7 +50,7 @@ msgstr "jest zarezerwowany"
## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
-msgstr ""
+msgstr "nie pasuje do potwierdzenia"
## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry"
From b6de9b1987438a3b790c3bc1cd687a7575206e9d Mon Sep 17 00:00:00 2001
From: Ben Is
Date: Wed, 8 Jul 2020 00:00:40 +0000
Subject: [PATCH 25/25] Translated using Weblate (Italian)
Currently translated at 100.0% (106 of 106 strings)
Translation: Pleroma/Pleroma backend
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma/it/
---
priv/gettext/it/LC_MESSAGES/errors.po | 223 +++++++++++++-------------
1 file changed, 114 insertions(+), 109 deletions(-)
diff --git a/priv/gettext/it/LC_MESSAGES/errors.po b/priv/gettext/it/LC_MESSAGES/errors.po
index 726be628b..406a297d1 100644
--- a/priv/gettext/it/LC_MESSAGES/errors.po
+++ b/priv/gettext/it/LC_MESSAGES/errors.po
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-19 14:33+0000\n"
-"PO-Revision-Date: 2020-06-19 20:38+0000\n"
+"PO-Revision-Date: 2020-07-09 14:40+0000\n"
"Last-Translator: Ben Is \n"
"Language-Team: Italian \n"
@@ -29,258 +29,258 @@ msgstr "non può essere nullo"
## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
-msgstr ""
+msgstr "è stato già creato"
## From Ecto.Changeset.put_change/3
msgid "is invalid"
-msgstr ""
+msgstr "non è valido"
## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
-msgstr ""
+msgstr "è in un formato invalido"
## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
-msgstr ""
+msgstr "ha una voce invalida"
## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
-msgstr ""
+msgstr "è vietato"
## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
-msgstr ""
+msgstr "non corrisponde alla verifica"
## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry"
-msgstr ""
+msgstr "è ancora associato con questa voce"
msgid "are still associated with this entry"
-msgstr ""
+msgstr "sono ancora associati con questa voce"
## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dovrebbe essere %{count} carattere"
+msgstr[1] "dovrebbero essere %{count} caratteri"
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dovrebbe avere %{count} voce"
+msgstr[1] "dovrebbe avere %{count} voci"
msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dovrebbe contenere almeno %{count} carattere"
+msgstr[1] "dovrebbe contenere almeno %{count} caratteri"
msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dovrebbe avere almeno %{count} voce"
+msgstr[1] "dovrebbe avere almeno %{count} voci"
msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dovrebbe avere al massimo %{count} carattere"
+msgstr[1] "dovrebbe avere al massimo %{count} caratteri"
msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "dovrebbe avere al massimo %{count} voce"
+msgstr[1] "dovrebbe avere al massimo %{count} voci"
## From Ecto.Changeset.validate_number/3
msgid "must be less than %{number}"
-msgstr ""
+msgstr "dev'essere minore di %{number}"
msgid "must be greater than %{number}"
-msgstr ""
+msgstr "dev'essere maggiore di %{number}"
msgid "must be less than or equal to %{number}"
-msgstr ""
+msgstr "dev'essere minore o uguale a %{number}"
msgid "must be greater than or equal to %{number}"
-msgstr ""
+msgstr "dev'essere maggiore o uguale a %{number}"
msgid "must be equal to %{number}"
-msgstr ""
+msgstr "dev'essere uguale a %{number}"
#: lib/pleroma/web/common_api/common_api.ex:421
#, elixir-format
msgid "Account not found"
-msgstr ""
+msgstr "Profilo non trovato"
#: lib/pleroma/web/common_api/common_api.ex:249
#, elixir-format
msgid "Already voted"
-msgstr ""
+msgstr "Hai già votato"
#: lib/pleroma/web/oauth/oauth_controller.ex:360
#, elixir-format
msgid "Bad request"
-msgstr ""
+msgstr "Richiesta invalida"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:425
#, elixir-format
msgid "Can't delete object"
-msgstr ""
+msgstr "Non puoi eliminare quest'oggetto"
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:196
#, elixir-format
msgid "Can't delete this post"
-msgstr ""
+msgstr "Non puoi eliminare questo messaggio"
#: lib/pleroma/web/controller_helper.ex:95
#: lib/pleroma/web/controller_helper.ex:101
#, elixir-format
msgid "Can't display this activity"
-msgstr ""
+msgstr "Non puoi vedere questo elemento"
#: 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 ""
+msgstr "Non trovo questo utente"
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:114
#, elixir-format
msgid "Can't get favorites"
-msgstr ""
+msgstr "Non posso ricevere i gradimenti"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:437
#, elixir-format
msgid "Can't like object"
-msgstr ""
+msgstr "Non posso gradire quest'oggetto"
#: lib/pleroma/web/common_api/utils.ex:556
#, elixir-format
msgid "Cannot post an empty status without attachments"
-msgstr ""
+msgstr "Non puoi pubblicare un messaggio vuoto senza allegati"
#: lib/pleroma/web/common_api/utils.ex:504
#, elixir-format
msgid "Comment must be up to %{max_size} characters"
-msgstr ""
+msgstr "I commenti posso al massimo consistere di %{max_size} caratteri"
#: lib/pleroma/config/config_db.ex:222
#, elixir-format
msgid "Config with params %{params} not found"
-msgstr ""
+msgstr "Configurazione con parametri %{max_size} non trovata"
#: lib/pleroma/web/common_api/common_api.ex:95
#, elixir-format
msgid "Could not delete"
-msgstr ""
+msgstr "Non eliminato"
#: lib/pleroma/web/common_api/common_api.ex:141
#, elixir-format
msgid "Could not favorite"
-msgstr ""
+msgstr "Non gradito"
#: lib/pleroma/web/common_api/common_api.ex:370
#, elixir-format
msgid "Could not pin"
-msgstr ""
+msgstr "Non intestato"
#: lib/pleroma/web/common_api/common_api.ex:112
#, elixir-format
msgid "Could not repeat"
-msgstr ""
+msgstr "Non ripetuto"
#: lib/pleroma/web/common_api/common_api.ex:188
#, elixir-format
msgid "Could not unfavorite"
-msgstr ""
+msgstr "Non sgradito"
#: lib/pleroma/web/common_api/common_api.ex:380
#, elixir-format
msgid "Could not unpin"
-msgstr ""
+msgstr "Non de-intestato"
#: lib/pleroma/web/common_api/common_api.ex:126
#, elixir-format
msgid "Could not unrepeat"
-msgstr ""
+msgstr "Non de-ripetuto"
#: 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 ""
+msgstr "Non aggiornato"
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:202
#, elixir-format
msgid "Error."
-msgstr ""
+msgstr "Errore."
#: lib/pleroma/web/twitter_api/twitter_api.ex:106
#, elixir-format
msgid "Invalid CAPTCHA"
-msgstr ""
+msgstr "CAPTCHA invalido"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:117
#: lib/pleroma/web/oauth/oauth_controller.ex:569
#, elixir-format
msgid "Invalid credentials"
-msgstr ""
+msgstr "Credenziali invalide"
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38
#, elixir-format
msgid "Invalid credentials."
-msgstr ""
+msgstr "Credenziali invalide."
#: lib/pleroma/web/common_api/common_api.ex:265
#, elixir-format
msgid "Invalid indices"
-msgstr ""
+msgstr "Indici invalidi"
#: lib/pleroma/web/admin_api/admin_api_controller.ex:1147
#, elixir-format
msgid "Invalid parameters"
-msgstr ""
+msgstr "Parametri invalidi"
#: lib/pleroma/web/common_api/utils.ex:411
#, elixir-format
msgid "Invalid password."
-msgstr ""
+msgstr "Parola d'ordine invalida."
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:187
#, elixir-format
msgid "Invalid request"
-msgstr ""
+msgstr "Richiesta invalida"
#: lib/pleroma/web/twitter_api/twitter_api.ex:109
#, elixir-format
msgid "Kocaptcha service unavailable"
-msgstr ""
+msgstr "Servizio Kocaptcha non disponibile"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:113
#, elixir-format
msgid "Missing parameters"
-msgstr ""
+msgstr "Parametri mancanti"
#: lib/pleroma/web/common_api/utils.ex:540
#, elixir-format
msgid "No such conversation"
-msgstr ""
+msgstr "Conversazione inesistente"
#: 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 ""
+msgstr "permission_group non esistente"
#: 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 ""
+msgstr "Non trovato"
#: lib/pleroma/web/common_api/common_api.ex:241
#, elixir-format
msgid "Poll's author can't vote"
-msgstr ""
+msgstr "L'autore del sondaggio non può votare"
#: 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
@@ -288,215 +288,215 @@ msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71
#, elixir-format
msgid "Record not found"
-msgstr ""
+msgstr "Voce non trovata"
#: 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 ""
+msgstr "C'è stato un problema"
#: lib/pleroma/web/common_api/activity_draft.ex:107
#, elixir-format
msgid "The message visibility must be direct"
-msgstr ""
+msgstr "Il messaggio dev'essere privato"
#: lib/pleroma/web/common_api/utils.ex:566
#, elixir-format
msgid "The status is over the character limit"
-msgstr ""
+msgstr "Il messaggio ha superato la lunghezza massima"
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
#, elixir-format
msgid "This resource requires authentication."
-msgstr ""
+msgstr "Accedi per leggere."
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
#, elixir-format
msgid "Throttled"
-msgstr ""
+msgstr "Strozzato"
#: lib/pleroma/web/common_api/common_api.ex:266
#, elixir-format
msgid "Too many choices"
-msgstr ""
+msgstr "Troppe alternative"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:442
#, elixir-format
msgid "Unhandled activity type"
-msgstr ""
+msgstr "Tipo di attività non gestibile"
#: lib/pleroma/web/admin_api/admin_api_controller.ex:536
#, elixir-format
msgid "You can't revoke your own admin status."
-msgstr ""
+msgstr "Non puoi divestirti da solo."
#: 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 ""
+msgstr "Il tuo profilo è attualmente disabilitato"
#: 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 ""
+msgstr "Devi aggiungere un indirizzo email valido"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:389
#, elixir-format
msgid "can't read inbox of %{nickname} as %{as_nickname}"
-msgstr ""
+msgstr "non puoi leggere i messaggi privati di %{nickname} come %{as_nickname}"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:472
#, elixir-format
msgid "can't update outbox of %{nickname} as %{as_nickname}"
-msgstr ""
+msgstr "non puoi aggiornare gli inviati di %{nickname} come %{as_nickname}"
#: lib/pleroma/web/common_api/common_api.ex:388
#, elixir-format
msgid "conversation is already muted"
-msgstr ""
+msgstr "la conversazione è già zittita"
#: 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 ""
+msgstr "errore"
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:29
#, elixir-format
msgid "mascots can only be images"
-msgstr ""
+msgstr "le mascotte possono solo essere immagini"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:60
#, elixir-format
msgid "not found"
-msgstr ""
+msgstr "non trovato"
#: lib/pleroma/web/oauth/oauth_controller.ex:395
#, elixir-format
msgid "Bad OAuth request."
-msgstr ""
+msgstr "Richiesta OAuth malformata."
#: lib/pleroma/web/twitter_api/twitter_api.ex:115
#, elixir-format
msgid "CAPTCHA already used"
-msgstr ""
+msgstr "CAPTCHA già utilizzato"
#: lib/pleroma/web/twitter_api/twitter_api.ex:112
#, elixir-format
msgid "CAPTCHA expired"
-msgstr ""
+msgstr "CAPTCHA scaduto"
#: lib/pleroma/plugs/uploaded_media.ex:55
#, elixir-format
msgid "Failed"
-msgstr ""
+msgstr "Fallito"
#: lib/pleroma/web/oauth/oauth_controller.ex:411
#, elixir-format
msgid "Failed to authenticate: %{message}."
-msgstr ""
+msgstr "Autenticazione fallita per: %{message}."
#: lib/pleroma/web/oauth/oauth_controller.ex:442
#, elixir-format
msgid "Failed to set up user account."
-msgstr ""
+msgstr "Profilo utente non creato."
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38
#, elixir-format
msgid "Insufficient permissions: %{permissions}."
-msgstr ""
+msgstr "Permessi insufficienti: %{permissions}."
#: lib/pleroma/plugs/uploaded_media.ex:94
#, elixir-format
msgid "Internal Error"
-msgstr ""
+msgstr "Errore interno"
#: lib/pleroma/web/oauth/fallback_controller.ex:22
#: lib/pleroma/web/oauth/fallback_controller.ex:29
#, elixir-format
msgid "Invalid Username/Password"
-msgstr ""
+msgstr "Nome utente/parola d'ordine invalidi"
#: lib/pleroma/web/twitter_api/twitter_api.ex:118
#, elixir-format
msgid "Invalid answer data"
-msgstr ""
+msgstr "Risposta malformata"
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:128
#, elixir-format
msgid "Nodeinfo schema version not handled"
-msgstr ""
+msgstr "Versione schema nodeinfo non compatibile"
#: lib/pleroma/web/oauth/oauth_controller.ex:169
#, elixir-format
msgid "This action is outside the authorized scopes"
-msgstr ""
+msgstr "Quest'azione non è consentita in questa visibilità"
#: lib/pleroma/web/oauth/fallback_controller.ex:14
#, elixir-format
msgid "Unknown error, please check the details and try again."
-msgstr ""
+msgstr "Errore sconosciuto, controlla i dettagli e riprova."
#: lib/pleroma/web/oauth/oauth_controller.ex:116
#: lib/pleroma/web/oauth/oauth_controller.ex:155
#, elixir-format
msgid "Unlisted redirect_uri."
-msgstr ""
+msgstr "redirect_uri nascosto."
#: lib/pleroma/web/oauth/oauth_controller.ex:391
#, elixir-format
msgid "Unsupported OAuth provider: %{provider}."
-msgstr ""
+msgstr "Gestore OAuth non supportato: %{provider}."
#: lib/pleroma/uploaders/uploader.ex:72
#, elixir-format
msgid "Uploader callback timeout"
-msgstr ""
+msgstr "Callback caricatmento scaduta"
#: lib/pleroma/web/uploader_controller.ex:23
#, elixir-format
msgid "bad request"
-msgstr ""
+msgstr "richiesta malformata"
#: lib/pleroma/web/twitter_api/twitter_api.ex:103
#, elixir-format
msgid "CAPTCHA Error"
-msgstr ""
+msgstr "Errore CAPTCHA"
#: lib/pleroma/web/common_api/common_api.ex:200
#, elixir-format
msgid "Could not add reaction emoji"
-msgstr ""
+msgstr "Reazione emoji non riuscita"
#: lib/pleroma/web/common_api/common_api.ex:211
#, elixir-format
msgid "Could not remove reaction emoji"
-msgstr ""
+msgstr "Rimozione reazione non riuscita"
#: lib/pleroma/web/twitter_api/twitter_api.ex:129
#, elixir-format
msgid "Invalid CAPTCHA (Missing parameter: %{name})"
-msgstr ""
+msgstr "CAPTCHA invalido (Parametro mancante: %{name})"
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
#, elixir-format
msgid "List not found"
-msgstr ""
+msgstr "Lista non trovata"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:124
#, elixir-format
msgid "Missing parameter: %{name}"
-msgstr ""
+msgstr "Parametro mancante: %{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 ""
+msgstr "Necessario reimpostare parola d'ordine"
#: 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
@@ -528,53 +528,58 @@ msgstr ""
#, elixir-format
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
msgstr ""
+"Sicurezza violata: il controllo autorizzazioni di OAuth non è stato svolto "
+"né saltato."
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
#, elixir-format
msgid "Two-factor authentication enabled, you must use a access token."
msgstr ""
+"Autenticazione bifattoriale abilitata, devi utilizzare una chiave d'accesso."
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:210
#, elixir-format
msgid "Unexpected error occurred while adding file to pack."
-msgstr ""
+msgstr "Errore inaspettato durante l'aggiunta del file al pacchetto."
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:138
#, elixir-format
msgid "Unexpected error occurred while creating pack."
-msgstr ""
+msgstr "Errore inaspettato durante la creazione del pacchetto."
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:278
#, elixir-format
msgid "Unexpected error occurred while removing file from pack."
-msgstr ""
+msgstr "Errore inaspettato durante la rimozione del file dal pacchetto."
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:250
#, elixir-format
msgid "Unexpected error occurred while updating file in pack."
-msgstr ""
+msgstr "Errore inaspettato durante l'aggiornamento del file nel pacchetto."
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:179
#, elixir-format
msgid "Unexpected error occurred while updating pack metadata."
-msgstr ""
+msgstr "Errore inaspettato durante l'aggiornamento dei metadati del pacchetto."
#: 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 ""
+"L'utente non è un amministratore o non ha ricevuto questa autorizzazione "
+"OAuth."
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
#, elixir-format
msgid "Web push subscription is disabled on this Pleroma instance"
-msgstr ""
+msgstr "Gli aggiornamenti web push non sono disponibili in questa stanza"
#: lib/pleroma/web/admin_api/admin_api_controller.ex:502
#, elixir-format
msgid "You can't revoke your own admin/moderator status."
-msgstr ""
+msgstr "Non puoi divestire te stesso."
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:105
#, elixir-format
msgid "authorization required for timeline view"
-msgstr ""
+msgstr "autorizzazione richiesta per vedere la sequenza"