Merge branch 'develop' into 'new-user-emails'
This commit is contained in:
commit
593c0851d9
15 changed files with 475 additions and 149 deletions
|
@ -19,6 +19,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Improved Apache webserver support: updated sample configuration, MediaProxy cache invalidation verified with the included sample script
|
||||
- Improve OAuth 2.0 provider support. A missing `fqn` field was added to the response, but does not expose the user's email address.
|
||||
- Provide redirect of external posts from `/notice/:id` to their original URL
|
||||
- Admins no longer receive notifications for reports if they are the actor making the report.
|
||||
- Improved Mailer configuration setting descriptions for AdminFE.
|
||||
|
||||
<details>
|
||||
<summary>API Changes</summary>
|
||||
|
@ -49,6 +51,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Ability to set ActivityPub aliases for follower migration.
|
||||
- Configurable background job limits for RichMedia (link previews) and MediaProxyWarmingPolicy
|
||||
- Ability to define custom HTTP headers per each frontend
|
||||
- MRF (`NoEmptyPolicy`): New MRF Policy which will deny empty statuses or statuses of only mentions from being created by local users
|
||||
|
||||
- New users will receive a simple email confirming their registration if no other emails will be dispatched. (e.g., Welcome, Confirmation, or Approval Required)
|
||||
|
||||
<details>
|
||||
|
|
|
@ -99,7 +99,8 @@ config :pleroma, :config_description, [
|
|||
key: :base_url,
|
||||
label: "Base URL",
|
||||
type: :string,
|
||||
description: "Base URL for the uploads, needed if you use CDN",
|
||||
description:
|
||||
"Base URL for the uploads. Required if you use a CDN or host attachments under a different domain.",
|
||||
suggestions: [
|
||||
"https://cdn-host.com"
|
||||
]
|
||||
|
@ -214,253 +215,216 @@ config :pleroma, :config_description, [
|
|||
type: :group,
|
||||
description: "Mailer-related settings",
|
||||
children: [
|
||||
%{
|
||||
key: :enabled,
|
||||
label: "Mailer Enabled",
|
||||
type: :boolean
|
||||
},
|
||||
%{
|
||||
key: :adapter,
|
||||
type: :module,
|
||||
description:
|
||||
"One of the mail adapters listed in [Swoosh readme](https://github.com/swoosh/swoosh#adapters)," <>
|
||||
" or Swoosh.Adapters.Local for in-memory mailbox",
|
||||
"One of the mail adapters listed in [Swoosh documentation](https://hexdocs.pm/swoosh/Swoosh.html#module-adapters)",
|
||||
suggestions: [
|
||||
Swoosh.Adapters.AmazonSES,
|
||||
Swoosh.Adapters.Dyn,
|
||||
Swoosh.Adapters.Gmail,
|
||||
Swoosh.Adapters.Mailgun,
|
||||
Swoosh.Adapters.Mailjet,
|
||||
Swoosh.Adapters.Mandrill,
|
||||
Swoosh.Adapters.Postmark,
|
||||
Swoosh.Adapters.SMTP,
|
||||
Swoosh.Adapters.Sendgrid,
|
||||
Swoosh.Adapters.Sendmail,
|
||||
Swoosh.Adapters.Mandrill,
|
||||
Swoosh.Adapters.Mailgun,
|
||||
Swoosh.Adapters.Mailjet,
|
||||
Swoosh.Adapters.Postmark,
|
||||
Swoosh.Adapters.SparkPost,
|
||||
Swoosh.Adapters.AmazonSES,
|
||||
Swoosh.Adapters.Dyn,
|
||||
Swoosh.Adapters.SocketLabs,
|
||||
Swoosh.Adapters.Gmail,
|
||||
Swoosh.Adapters.Local
|
||||
Swoosh.Adapters.SparkPost
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: :enabled,
|
||||
type: :boolean,
|
||||
description: "Allow/disallow send emails"
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :relay,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: ["smtp.gmail.com"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :username,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: ["pleroma"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :password,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: ["password"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :ssl,
|
||||
label: "SSL",
|
||||
type: :boolean,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting"
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :tls,
|
||||
label: "TLS",
|
||||
type: :atom,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: [:always, :never, :if_available]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :auth,
|
||||
type: :atom,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: [:always, :never, :if_available]
|
||||
description: "Hostname or IP address",
|
||||
suggestions: ["smtp.example.com"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :port,
|
||||
type: :integer,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: [1025]
|
||||
description: "SMTP port",
|
||||
suggestions: ["1025"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :username,
|
||||
type: :string,
|
||||
description: "SMTP AUTH username",
|
||||
suggestions: ["user@example.com"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :password,
|
||||
type: :string,
|
||||
description: "SMTP AUTH password",
|
||||
suggestions: ["password"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :ssl,
|
||||
label: "Use SSL",
|
||||
type: :boolean,
|
||||
description: "Use Implicit SSL/TLS. e.g. port 465"
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :tls,
|
||||
label: "STARTTLS Mode",
|
||||
type: {:dropdown, :atom},
|
||||
description: "Explicit TLS (STARTTLS) enforcement mode",
|
||||
suggestions: [:if_available, :always, :never]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :auth,
|
||||
label: "AUTH Mode",
|
||||
type: {:dropdown, :atom},
|
||||
description: "SMTP AUTH enforcement mode",
|
||||
suggestions: [:if_available, :always, :never]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :retries,
|
||||
type: :integer,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting",
|
||||
suggestions: [5]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SMTP},
|
||||
key: :no_mx_lookups,
|
||||
label: "No MX lookups",
|
||||
type: :boolean,
|
||||
description: "`Swoosh.Adapters.SMTP` adapter specific setting"
|
||||
description: "SMTP temporary (4xx) error retries",
|
||||
suggestions: [1]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Sendgrid},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "SendGrid API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Sendgrid` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
suggestions: ["YOUR_API_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Sendmail},
|
||||
key: :cmd_path,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Sendmail` adapter specific setting",
|
||||
suggestions: ["/usr/bin/sendmail"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Sendmail},
|
||||
key: :cmd_args,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Sendmail` adapter specific setting",
|
||||
suggestions: ["-N delay,failure,success"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Sendmail},
|
||||
key: :qmail,
|
||||
type: :boolean,
|
||||
description: "`Swoosh.Adapters.Sendmail` adapter specific setting"
|
||||
label: "Qmail compat mode",
|
||||
type: :boolean
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Mandrill},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "Mandrill API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Mandrill` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
suggestions: ["YOUR_API_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Mailgun},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "Mailgun API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Mailgun` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
suggestions: ["YOUR_API_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Mailgun},
|
||||
key: :domain,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Mailgun` adapter specific setting",
|
||||
suggestions: ["pleroma.com"]
|
||||
suggestions: ["YOUR_DOMAIN_NAME"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Mailjet},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "MailJet Public API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Mailjet` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
suggestions: ["MJ_APIKEY_PUBLIC"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Mailjet},
|
||||
key: :secret,
|
||||
label: "MailJet Private API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Mailjet` adapter specific setting",
|
||||
suggestions: ["my-secret-key"]
|
||||
suggestions: ["MJ_APIKEY_PRIVATE"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Postmark},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "Postmark API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Postmark` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
suggestions: ["X-Postmark-Server-Token"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SparkPost},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "SparkPost API key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SparkPost` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
suggestions: ["YOUR_API_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SparkPost},
|
||||
key: :endpoint,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SparkPost` adapter specific setting",
|
||||
suggestions: ["https://api.sparkpost.com/api/v1"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.AmazonSES},
|
||||
key: :region,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.AmazonSES` adapter specific setting",
|
||||
suggestions: ["us-east-1", "us-east-2"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.AmazonSES},
|
||||
key: :access_key,
|
||||
label: "AWS Access Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.AmazonSES` adapter specific setting",
|
||||
suggestions: ["aws-access-key"]
|
||||
suggestions: ["AWS_ACCESS_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.AmazonSES},
|
||||
key: :secret,
|
||||
label: "AWS Secret Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.AmazonSES` adapter specific setting",
|
||||
suggestions: ["aws-secret-key"]
|
||||
suggestions: ["AWS_SECRET_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.AmazonSES},
|
||||
key: :region,
|
||||
label: "AWS Region",
|
||||
type: :string,
|
||||
suggestions: ["us-east-1", "us-east-2"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Dyn},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "Dyn API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Dyn` adapter specific setting",
|
||||
suggestions: ["my-api-key"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SocketLabs},
|
||||
key: :server_id,
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SocketLabs` adapter specific setting"
|
||||
suggestions: ["apikey"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SocketLabs},
|
||||
key: :api_key,
|
||||
label: "API key",
|
||||
label: "SocketLabs API Key",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.SocketLabs` adapter specific setting"
|
||||
suggestions: ["INJECTION_API_KEY"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.SocketLabs},
|
||||
key: :server_id,
|
||||
label: "Server ID",
|
||||
type: :string,
|
||||
suggestions: ["SERVER_ID"]
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Gmail},
|
||||
key: :access_token,
|
||||
label: "GMail API Access Token",
|
||||
type: :string,
|
||||
description: "`Swoosh.Adapters.Gmail` adapter specific setting"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
group: :swoosh,
|
||||
type: :group,
|
||||
description: "`Swoosh.Adapters.Local` adapter specific settings",
|
||||
children: [
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Local},
|
||||
key: :serve_mailbox,
|
||||
type: :boolean,
|
||||
description: "Run the preview server together as part of your app"
|
||||
},
|
||||
%{
|
||||
group: {:subgroup, Swoosh.Adapters.Local},
|
||||
key: :preview_port,
|
||||
type: :integer,
|
||||
description: "The preview server port",
|
||||
suggestions: [4001]
|
||||
suggestions: ["GMAIL_API_ACCESS_TOKEN"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1545,7 +1509,8 @@ config :pleroma, :config_description, [
|
|||
%{
|
||||
key: :max_body_length,
|
||||
type: :integer,
|
||||
description: "Maximum file size allowed through the Pleroma MediaProxy cache."
|
||||
description:
|
||||
"Maximum file size (in bytes) allowed through the Pleroma MediaProxy cache."
|
||||
},
|
||||
%{
|
||||
key: :max_read_duration,
|
||||
|
@ -1595,7 +1560,7 @@ config :pleroma, :config_description, [
|
|||
key: :min_content_length,
|
||||
type: :integer,
|
||||
description:
|
||||
"Min content length to perform preview, in bytes. If greater than 0, media smaller in size will be served as is, without thumbnailing."
|
||||
"Min content length (in bytes) to perform preview. Media smaller in size will be served without thumbnailing."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1643,6 +1608,7 @@ config :pleroma, :config_description, [
|
|||
},
|
||||
%{
|
||||
key: :url_format,
|
||||
label: "URL Format",
|
||||
type: :string,
|
||||
description:
|
||||
"Optional URL format preprocessing. Only required for Apache's htcacheclean.",
|
||||
|
@ -2888,7 +2854,7 @@ config :pleroma, :config_description, [
|
|||
type: :integer,
|
||||
description:
|
||||
"Activity pub routes (except question activities). Default: `nil` (no expiration).",
|
||||
suggestions: [30_000, nil]
|
||||
suggestions: [nil]
|
||||
},
|
||||
%{
|
||||
key: :activity_pub_question,
|
||||
|
@ -3326,9 +3292,9 @@ config :pleroma, :config_description, [
|
|||
},
|
||||
%{
|
||||
key: :ip_whitelist,
|
||||
label: "IP Whitelist",
|
||||
type: [{:list, :string}, {:list, :charlist}, {:list, :tuple}],
|
||||
description:
|
||||
"[Pleroma extension] If non-empty, restricts access to app metrics endpoint to specified IP addresses."
|
||||
description: "Restrict access of app metrics endpoint to the specified IP addresses."
|
||||
},
|
||||
%{
|
||||
key: :auth,
|
||||
|
|
|
@ -141,3 +141,21 @@ but should only be run if necessary. **It is safe to cancel this.**
|
|||
```sh
|
||||
mix pleroma.database ensure_expiration
|
||||
```
|
||||
|
||||
## Change Text Search Configuration
|
||||
|
||||
Change `default_text_search_config` for database and (if necessary) text_search_config used in index, then rebuild index (it may take time).
|
||||
|
||||
=== "OTP"
|
||||
|
||||
```sh
|
||||
./bin/pleroma_ctl database set_text_search_config english
|
||||
```
|
||||
|
||||
=== "From Source"
|
||||
|
||||
```sh
|
||||
mix pleroma.database set_text_search_config english
|
||||
```
|
||||
|
||||
See [PostgreSQL documentation](https://www.postgresql.org/docs/current/textsearch-configuration.html) and `docs/configuration/howto_search_cjk.md` for more detail.
|
||||
|
|
42
docs/configuration/howto_search_cjk.md
Normal file
42
docs/configuration/howto_search_cjk.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
# How to enable text search for Chinese, Japanese and Korean
|
||||
|
||||
Pleroma's full text search feature is powered by PostgreSQL's native [text search](https://www.postgresql.org/docs/current/textsearch.html), it works well out of box for most of languages, but needs extra configurations for some asian languages like Chinese, Japanese and Korean (CJK).
|
||||
|
||||
|
||||
## Setup and test the new search config
|
||||
|
||||
In most cases, you would need an extension installed to support parsing CJK text. Here are a few extension you may choose from, or you are more than welcome to share additional ones you found working for you with the rest of Pleroma community.
|
||||
|
||||
* [a generic n-gram parser](https://github.com/huangjimmy/pg_cjk_parser) supports Simplifed/Traditional Chinese, Japanese, and Korean
|
||||
* [a Korean parser](https://github.com/i0seph/textsearch_ko) based on mecab
|
||||
* [a Japanese parser](https://www.amris.co.jp/tsja/index.html) based on mecab
|
||||
* [zhparser](https://github.com/amutu/zhparser/) is a PostgreSQL extension base on the Simple Chinese Word Segmentation(SCWS)
|
||||
* [another Chinese parser](https://github.com/jaiminpan/pg_jieba) based on Jieba Chinese Word Segmentation
|
||||
|
||||
Once you have the new search config , make sure you test it with the `pleroma` user in PostgreSQL (change `YOUR.CONFIG` to your real configuration name)
|
||||
```
|
||||
SELECT ts_debug('YOUR.CONFIG', '安装和配置Nginx, ElixirとErlangをインストールします');
|
||||
```
|
||||
Check output of the query, and see if it matches your expectation.
|
||||
|
||||
|
||||
## Update text search config and index in database
|
||||
|
||||
=== "OTP"
|
||||
|
||||
```sh
|
||||
./bin/pleroma_ctl database set_text_search_config YOUR.CONFIG
|
||||
```
|
||||
|
||||
=== "From Source"
|
||||
|
||||
```sh
|
||||
mix pleroma.database set_text_search_config YOUR.CONFIG
|
||||
```
|
||||
|
||||
Note: index update may take a while.
|
||||
|
||||
## Restart database connection
|
||||
Since some changes above will only apply with a new database connection, you will have to restart either Pleroma or PostgreSQL process, or use `pg_terminate_backend` SQL command without restarting either.
|
||||
|
||||
Now the search results of statuses should be much more friendly for your language of choice, the results for searching users and tags were not changed, as the default parsing/matching should work for most cases.
|
|
@ -59,6 +59,13 @@ sub vcl_backend_response {
|
|||
set beresp.http.CR = beresp.http.content-range;
|
||||
}
|
||||
|
||||
# Bypass cache for large files
|
||||
# 50000000 ~ 50MB
|
||||
if (std.integer(beresp.http.content-length, 0) > 50000000) {
|
||||
set beresp.uncacheable = true;
|
||||
return(deliver);
|
||||
}
|
||||
|
||||
# Don't cache objects that require authentication
|
||||
if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") {
|
||||
set beresp.uncacheable = true;
|
||||
|
|
|
@ -167,4 +167,51 @@ defmodule Mix.Tasks.Pleroma.Database do
|
|||
end)
|
||||
|> Stream.run()
|
||||
end
|
||||
|
||||
def run(["set_text_search_config", tsconfig]) do
|
||||
start_pleroma()
|
||||
%{rows: [[tsc]]} = Ecto.Adapters.SQL.query!(Pleroma.Repo, "SHOW default_text_search_config;")
|
||||
shell_info("Current default_text_search_config: #{tsc}")
|
||||
|
||||
%{rows: [[db]]} = Ecto.Adapters.SQL.query!(Pleroma.Repo, "SELECT current_database();")
|
||||
shell_info("Update default_text_search_config: #{tsconfig}")
|
||||
|
||||
%{messages: msg} =
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"ALTER DATABASE #{db} SET default_text_search_config = '#{tsconfig}';"
|
||||
)
|
||||
|
||||
# non-exist config will not raise excpetion but only give >0 messages
|
||||
if length(msg) > 0 do
|
||||
shell_info("Error: #{inspect(msg, pretty: true)}")
|
||||
else
|
||||
rum_enabled = Pleroma.Config.get([:database, :rum_enabled])
|
||||
shell_info("Recreate index, RUM: #{rum_enabled}")
|
||||
|
||||
# Note SQL below needs to be kept up-to-date with latest GIN or RUM index definition in future
|
||||
if rum_enabled do
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"CREATE OR REPLACE FUNCTION objects_fts_update() RETURNS trigger AS $$ BEGIN
|
||||
new.fts_content := to_tsvector(new.data->>'content');
|
||||
RETURN new;
|
||||
END
|
||||
$$ LANGUAGE plpgsql"
|
||||
)
|
||||
|
||||
shell_info("Refresh RUM index")
|
||||
Ecto.Adapters.SQL.query!(Pleroma.Repo, "UPDATE objects SET updated_at = NOW();")
|
||||
else
|
||||
Ecto.Adapters.SQL.query!(Pleroma.Repo, "DROP INDEX IF EXISTS objects_fts;")
|
||||
|
||||
Ecto.Adapters.SQL.query!(
|
||||
Pleroma.Repo,
|
||||
"CREATE INDEX objects_fts ON objects USING gin(to_tsvector('#{tsconfig}', data->>'content')); "
|
||||
)
|
||||
end
|
||||
|
||||
shell_info('Done.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -64,7 +64,7 @@ defmodule Pleroma.Activity.Search do
|
|||
from([a, o] in q,
|
||||
where:
|
||||
fragment(
|
||||
"to_tsvector('english', ?->>'content') @@ plainto_tsquery('english', ?)",
|
||||
"to_tsvector(?->>'content') @@ plainto_tsquery(?)",
|
||||
o.data,
|
||||
^search_query
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ defmodule Pleroma.Activity.Search do
|
|||
from([a, o] in q,
|
||||
where:
|
||||
fragment(
|
||||
"to_tsvector('english', ?->>'content') @@ websearch_to_tsquery('english', ?)",
|
||||
"to_tsvector(?->>'content') @@ websearch_to_tsquery(?)",
|
||||
o.data,
|
||||
^search_query
|
||||
)
|
||||
|
@ -86,7 +86,7 @@ defmodule Pleroma.Activity.Search do
|
|||
from([a, o] in q,
|
||||
where:
|
||||
fragment(
|
||||
"? @@ plainto_tsquery('english', ?)",
|
||||
"? @@ plainto_tsquery(?)",
|
||||
o.fts_content,
|
||||
^search_query
|
||||
),
|
||||
|
@ -98,7 +98,7 @@ defmodule Pleroma.Activity.Search do
|
|||
from([a, o] in q,
|
||||
where:
|
||||
fragment(
|
||||
"? @@ websearch_to_tsquery('english', ?)",
|
||||
"? @@ websearch_to_tsquery(?)",
|
||||
o.fts_content,
|
||||
^search_query
|
||||
),
|
||||
|
|
|
@ -507,8 +507,8 @@ defmodule Pleroma.Notification do
|
|||
[object_id]
|
||||
end
|
||||
|
||||
def get_potential_receiver_ap_ids(%{data: %{"type" => "Flag"}}) do
|
||||
User.all_superusers() |> Enum.map(fn user -> user.ap_id end)
|
||||
def get_potential_receiver_ap_ids(%{data: %{"type" => "Flag", "actor" => actor}}) do
|
||||
(User.all_superusers() |> Enum.map(fn user -> user.ap_id end)) -- [actor]
|
||||
end
|
||||
|
||||
def get_potential_receiver_ap_ids(activity) do
|
||||
|
|
|
@ -377,6 +377,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
:ok <-
|
||||
maybe_federate(stripped_activity) do
|
||||
User.all_superusers()
|
||||
|> Enum.filter(fn user -> user.ap_id != actor end)
|
||||
|> Enum.filter(fn user -> not is_nil(user.email) end)
|
||||
|> Enum.each(fn superuser ->
|
||||
superuser
|
||||
|
|
61
lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
Normal file
61
lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
|
||||
@moduledoc "Filter local activities which have no content"
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
alias Pleroma.Web
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = object) do
|
||||
with true <- is_local?(actor),
|
||||
true <- is_note?(object),
|
||||
false <- has_attachment?(object),
|
||||
true <- only_mentions?(object) do
|
||||
{:reject, "[NoEmptyPolicy]"}
|
||||
else
|
||||
_ ->
|
||||
{:ok, object}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
defp is_local?(actor) do
|
||||
if actor |> String.starts_with?("#{Web.base_url()}") do
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp has_attachment?(%{
|
||||
"type" => "Create",
|
||||
"object" => %{"type" => "Note", "attachment" => attachments}
|
||||
})
|
||||
when length(attachments) > 0,
|
||||
do: true
|
||||
|
||||
defp has_attachment?(_), do: false
|
||||
|
||||
defp only_mentions?(%{"type" => "Create", "object" => %{"type" => "Note", "source" => source}}) do
|
||||
non_mentions =
|
||||
source |> String.split() |> Enum.filter(&(not String.starts_with?(&1, "@"))) |> length
|
||||
|
||||
if non_mentions > 0 do
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
defp only_mentions?(_), do: false
|
||||
|
||||
defp is_note?(%{"type" => "Create", "object" => %{"type" => "Note"}}), do: true
|
||||
defp is_note?(_), do: false
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
|
@ -9,7 +9,6 @@
|
|||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||
<%= activity_context(@activity) %>
|
||||
</ostatus:conversation>
|
||||
<link rel="ostatus:conversation"><%= activity_context(@activity) %></link>
|
||||
|
||||
<%= if @data["summary"] do %>
|
||||
<description><%= escape(@data["summary"]) %></description>
|
||||
|
@ -21,6 +20,8 @@
|
|||
<link><%= @data["external_url"] %></link>
|
||||
<% end %>
|
||||
|
||||
<link rel="ostatus:conversation"><%= activity_context(@activity) %></link>
|
||||
|
||||
<%= for tag <- @data["tag"] || [] do %>
|
||||
<category term="<%= tag %>"></category>
|
||||
<% end %>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
defmodule Pleroma.Repo.Migrations.AddDefaultTextSearchConfig do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
execute("DO $$
|
||||
BEGIN
|
||||
execute 'ALTER DATABASE '||current_database()||' SET default_text_search_config = ''english'' ';
|
||||
END
|
||||
$$;")
|
||||
end
|
||||
end
|
|
@ -17,7 +17,7 @@ defmodule Pleroma.Repo.Migrations.AddFtsIndexToObjectsTwo do
|
|||
|
||||
execute("CREATE FUNCTION objects_fts_update() RETURNS trigger AS $$
|
||||
begin
|
||||
new.fts_content := to_tsvector('english', new.data->>'content');
|
||||
new.fts_content := to_tsvector(new.data->>'content');
|
||||
return new;
|
||||
end
|
||||
$$ LANGUAGE plpgsql")
|
||||
|
|
|
@ -45,6 +45,20 @@ defmodule Pleroma.NotificationTest do
|
|||
assert notification.type == "pleroma:report"
|
||||
end
|
||||
|
||||
test "suppresses notification to reporter if reporter is an admin" do
|
||||
reporting_admin = insert(:user, is_admin: true)
|
||||
reported_user = insert(:user)
|
||||
other_admin = insert(:user, is_admin: true)
|
||||
|
||||
{:ok, activity} = CommonAPI.report(reporting_admin, %{account_id: reported_user.id})
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
||||
refute notification.user_id == reporting_admin.id
|
||||
assert notification.user_id == other_admin.id
|
||||
assert notification.type == "pleroma:report"
|
||||
end
|
||||
|
||||
test "creates a notification for an emoji reaction" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
154
test/pleroma/web/activity_pub/mrf/no_empty_policy_test.exs
Normal file
154
test/pleroma/web/activity_pub/mrf/no_empty_policy_test.exs
Normal file
|
@ -0,0 +1,154 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy
|
||||
|
||||
setup_all do: clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy])
|
||||
|
||||
test "Notes with content are exempt" do
|
||||
message = %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"object" => %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"attachment" => [],
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"source" => "this is a test post",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Note"
|
||||
},
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert NoEmptyPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
test "Polls are exempt" do
|
||||
message = %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"object" => %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"attachment" => [],
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"oneOf" => [
|
||||
%{
|
||||
"name" => "chocolate",
|
||||
"replies" => %{"totalItems" => 0, "type" => "Collection"},
|
||||
"type" => "Note"
|
||||
},
|
||||
%{
|
||||
"name" => "vanilla",
|
||||
"replies" => %{"totalItems" => 0, "type" => "Collection"},
|
||||
"type" => "Note"
|
||||
}
|
||||
],
|
||||
"source" => "@user2",
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"http://localhost:4001/users/user2"
|
||||
],
|
||||
"type" => "Question"
|
||||
},
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"http://localhost:4001/users/user2"
|
||||
],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert NoEmptyPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
test "Notes with attachments are exempt" do
|
||||
message = %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"object" => %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"attachment" => [
|
||||
%{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"mediaType" => "image/png",
|
||||
"name" => "",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"http://localhost:4001/media/68ba231cf12e1382ce458f1979969f8ed5cc07ba198a02e653464abaf39bdb90.png",
|
||||
"mediaType" => "image/png",
|
||||
"type" => "Link"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"source" => "@user2",
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"http://localhost:4001/users/user2"
|
||||
],
|
||||
"type" => "Note"
|
||||
},
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"http://localhost:4001/users/user2"
|
||||
],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert NoEmptyPolicy.filter(message) == {:ok, message}
|
||||
end
|
||||
|
||||
test "Notes with only mentions are denied" do
|
||||
message = %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"object" => %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"attachment" => [],
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"source" => "@user2",
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"http://localhost:4001/users/user2"
|
||||
],
|
||||
"type" => "Note"
|
||||
},
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"http://localhost:4001/users/user2"
|
||||
],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert NoEmptyPolicy.filter(message) == {:reject, "[NoEmptyPolicy]"}
|
||||
end
|
||||
|
||||
test "Notes with no content are denied" do
|
||||
message = %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"object" => %{
|
||||
"actor" => "http://localhost:4001/users/testuser",
|
||||
"attachment" => [],
|
||||
"cc" => ["http://localhost:4001/users/testuser/followers"],
|
||||
"source" => "",
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type" => "Note"
|
||||
},
|
||||
"to" => [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type" => "Create"
|
||||
}
|
||||
|
||||
assert NoEmptyPolicy.filter(message) == {:reject, "[NoEmptyPolicy]"}
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue