@@ -64,6 +64,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). | |||
- Support pagination in emoji packs API (for packs and for files in pack) | |||
- Support for viewing instances favicons next to posts and accounts | |||
- Added Pleroma.Upload.Filter.Exiftool as an alternate EXIF stripping mechanism targeting GPS/location metadata. | |||
- Configuration: Add `:welcome` setting for welcoming message to a newly registered users. | |||
<details> | |||
<summary>API Changes</summary> | |||
@@ -225,8 +225,6 @@ config :pleroma, :instance, | |||
autofollowed_nicknames: [], | |||
max_pinned_statuses: 1, | |||
attachment_links: false, | |||
welcome_user_nickname: nil, | |||
welcome_message: nil, | |||
max_report_comment_size: 1000, | |||
safe_dm_mentions: false, | |||
healthcheck: false, | |||
@@ -254,6 +252,20 @@ config :pleroma, :instance, | |||
] | |||
] | |||
config :pleroma, :welcome, | |||
direct_message: [ | |||
enabled: false, | |||
sender_nickname: nil, | |||
message: nil | |||
], | |||
email: [ | |||
enabled: false, | |||
sender_nickname: nil, | |||
subject: "Welcome to <%= instance_name %>", | |||
html: "Welcome to <%= instance_name %>", | |||
text: "Welcome to <%= instance_name %>" | |||
] | |||
config :pleroma, :feed, | |||
post_title: %{ | |||
max_length: 100, | |||
@@ -63,6 +63,18 @@ To add configuration to your config file, you can copy it from the base config. | |||
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users. | |||
* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances. | |||
## Welcome | |||
* `direct_message`: - welcome message sent as a direct message. | |||
* `enabled`: Enables the send a direct message to a newly registered user. Defaults to `false`. | |||
* `sender_nickname`: The nickname of the local user that sends the welcome message. | |||
* `message`: A message that will be send to a newly registered users as a direct message. | |||
* `email`: - welcome message sent as a email. | |||
* `enabled`: Enables the send a welcome email to a newly registered user. Defaults to `false`. | |||
* `sender_nickname`: The nickname of the local user that sends the welcome email. | |||
* `subject`: A subject of welcome email. | |||
* `html`: A html that will be send to a newly registered users as a email. | |||
* `text`: A text that will be send to a newly registered users as a email. | |||
## Message rewrite facility | |||
### :mrf | |||
@@ -0,0 +1,17 @@ | |||
# Pleroma: A lightweight social networking server | |||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.Config.Helpers do | |||
alias Pleroma.Config | |||
def instance_name, do: Config.get([:instance, :name]) | |||
defp instance_notify_email do | |||
Config.get([:instance, :notify_email]) || Config.get([:instance, :email]) | |||
end | |||
def sender do | |||
{instance_name(), instance_notify_email()} | |||
end | |||
end |
@@ -0,0 +1,17 @@ | |||
# Pleroma: A lightweight social networking server | |||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.Config.Utils do | |||
alias Pleroma.Config | |||
def instance_name, do: Config.get([:instance, :name]) | |||
defp instance_notify_email do | |||
Config.get([:instance, :notify_email]) || Config.get([:instance, :email]) | |||
end | |||
def sender do | |||
{instance_name(), instance_notify_email()} | |||
end | |||
end |
@@ -12,17 +12,22 @@ defmodule Pleroma.Emails.UserEmail do | |||
alias Pleroma.Web.Endpoint | |||
alias Pleroma.Web.Router | |||
defp instance_name, do: Config.get([:instance, :name]) | |||
defp sender do | |||
email = Config.get([:instance, :notify_email]) || Config.get([:instance, :email]) | |||
{instance_name(), email} | |||
end | |||
import Pleroma.Config.Helpers, only: [instance_name: 0, sender: 0] | |||
defp recipient(email, nil), do: email | |||
defp recipient(email, name), do: {name, email} | |||
defp recipient(%User{} = user), do: recipient(user.email, user.name) | |||
@spec welcome(User.t(), map()) :: Swoosh.Email.t() | |||
def welcome(user, opts \\ %{}) do | |||
new() | |||
|> to(recipient(user)) | |||
|> from(Map.get(opts, :sender, sender())) | |||
|> subject(Map.get(opts, :subject, "Welcome to #{instance_name()}!")) | |||
|> html_body(Map.get(opts, :html, "Welcome to #{instance_name()}!")) | |||
|> text_body(Map.get(opts, :text, "Welcome to #{instance_name()}!")) | |||
end | |||
def password_reset_email(user, token) when is_binary(token) do | |||
password_reset_url = Router.Helpers.reset_password_url(Endpoint, :reset, token) | |||
@@ -713,12 +713,31 @@ defmodule Pleroma.User do | |||
def post_register_action(%User{} = user) do | |||
with {:ok, user} <- autofollow_users(user), | |||
{:ok, user} <- set_cache(user), | |||
{:ok, _} <- User.WelcomeMessage.post_welcome_message_to_user(user), | |||
{:ok, _} <- send_welcome_email(user), | |||
{:ok, _} <- send_welcome_message(user), | |||
{:ok, _} <- try_send_confirmation_email(user) do | |||
{:ok, user} | |||
end | |||
end | |||
def send_welcome_message(user) do | |||
if User.WelcomeMessage.enabled?() do | |||
User.WelcomeMessage.post_message(user) | |||
{:ok, :enqueued} | |||
else | |||
{:ok, :noop} | |||
end | |||
end | |||
def send_welcome_email(user) do | |||
if User.WelcomeEmail.enabled?() do | |||
User.WelcomeEmail.send_email(user) | |||
{:ok, :enqueued} | |||
else | |||
{:ok, :noop} | |||
end | |||
end | |||
def try_send_confirmation_email(%User{} = user) do | |||
if user.confirmation_pending && | |||
Config.get([:instance, :account_activation_required]) do | |||
@@ -0,0 +1,68 @@ | |||
# Pleroma: A lightweight social networking server | |||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.User.WelcomeEmail do | |||
@moduledoc """ | |||
The module represents the functions to send welcome email. | |||
""" | |||
alias Pleroma.Config | |||
alias Pleroma.Emails | |||
alias Pleroma.User | |||
import Pleroma.Config.Utils, only: [instance_name: 0] | |||
@spec enabled?() :: boolean() | |||
def enabled?, do: Config.get([:welcome, :email, :enabled], false) | |||
@spec send_email(User.t()) :: {:ok, Oban.Job.t()} | |||
def send_email(%User{} = user) do | |||
user | |||
|> Emails.UserEmail.welcome(email_options(user)) | |||
|> Emails.Mailer.deliver_async() | |||
end | |||
defp email_options(user) do | |||
bindings = [user: user, instance_name: instance_name()] | |||
%{} | |||
|> add_sender(Config.get([:welcome, :email, :sender_nickname], nil)) | |||
|> add_option(:subject, bindings) | |||
|> add_option(:html, bindings) | |||
|> add_option(:text, bindings) | |||
end | |||
defp add_option(opts, option, bindings) do | |||
[:welcome, :email, option] | |||
|> Config.get(nil) | |||
|> eval_string(bindings) | |||
|> merge_options(opts, option) | |||
end | |||
def add_sender(opts, nickname) do | |||
nickname | |||
|> fetch_sender() | |||
|> merge_options(opts, :sender) | |||
end | |||
defp merge_options(nil, options, _option), do: options | |||
defp merge_options(value, options, option) do | |||
Map.merge(options, %{option => value}) | |||
end | |||
defp fetch_sender(nickname) when is_binary(nickname) do | |||
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do | |||
{instance_name(), user.email} | |||
else | |||
_ -> nil | |||
end | |||
end | |||
defp fetch_sender(_), do: nil | |||
defp eval_string(nil, _), do: nil | |||
defp eval_string("", _), do: nil | |||
defp eval_string(str, bindings), do: EEx.eval_string(str, bindings) | |||
end |
@@ -3,32 +3,45 @@ | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.User.WelcomeMessage do | |||
alias Pleroma.Config | |||
alias Pleroma.User | |||
alias Pleroma.Web.CommonAPI | |||
def post_welcome_message_to_user(user) do | |||
with %User{} = sender_user <- welcome_user(), | |||
message when is_binary(message) <- welcome_message() do | |||
CommonAPI.post(sender_user, %{ | |||
@spec enabled?() :: boolean() | |||
def enabled?, do: Config.get([:welcome, :direct_message, :enabled], false) | |||
@spec post_message(User.t()) :: {:ok, Pleroma.Activity.t() | nil} | |||
def post_message(user) do | |||
[:welcome, :direct_message, :sender_nickname] | |||
|> Config.get(nil) | |||
|> fetch_sender() | |||
|> do_post(user, welcome_message()) | |||
end | |||
defp do_post(%User{} = sender, %User{nickname: nickname}, message) | |||
when is_binary(message) do | |||
CommonAPI.post( | |||
sender, | |||
%{ | |||
visibility: "direct", | |||
status: "@#{user.nickname}\n#{message}" | |||
}) | |||
else | |||
_ -> {:ok, nil} | |||
end | |||
status: "@#{nickname}\n#{message}" | |||
} | |||
) | |||
end | |||
defp welcome_user do | |||
with nickname when is_binary(nickname) <- | |||
Pleroma.Config.get([:instance, :welcome_user_nickname]), | |||
%User{local: true} = user <- User.get_cached_by_nickname(nickname) do | |||
defp do_post(_sender, _recipient, _message), do: {:ok, nil} | |||
defp fetch_sender(nickname) when is_binary(nickname) do | |||
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do | |||
user | |||
else | |||
_ -> nil | |||
end | |||
end | |||
defp fetch_sender(_), do: nil | |||
defp welcome_message do | |||
Pleroma.Config.get([:instance, :welcome_message]) | |||
Config.get([:welcome, :direct_message, :message], nil) | |||
end | |||
end |
@@ -10,6 +10,7 @@ defmodule Pleroma.Emails.UserEmailTest do | |||
alias Pleroma.Web.Router | |||
import Pleroma.Factory | |||
import Swoosh.TestAssertions | |||
test "build password reset email" do | |||
config = Pleroma.Config.get(:instance) | |||
@@ -129,8 +129,6 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do | |||
autofollowed_nicknames: [], | |||
max_pinned_statuses: 1, | |||
attachment_links: false, | |||
welcome_user_nickname: nil, | |||
welcome_message: nil, | |||
max_report_comment_size: 1000, | |||
safe_dm_mentions: false, | |||
healthcheck: false, | |||
@@ -172,7 +170,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do | |||
end | |||
assert file == | |||
"#{header}\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n welcome_user_nickname: nil,\n welcome_message: nil,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" | |||
"#{header}\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" | |||
end | |||
end | |||
end |
@@ -17,6 +17,7 @@ defmodule Pleroma.UserTest do | |||
import Pleroma.Factory | |||
import ExUnit.CaptureLog | |||
import Swoosh.TestAssertions | |||
setup_all do | |||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) | |||
@@ -386,8 +387,8 @@ defmodule Pleroma.UserTest do | |||
email: "email@example.com" | |||
} | |||
setup do: clear_config([:instance, :autofollowed_nicknames]) | |||
setup do: clear_config([:instance, :welcome_message]) | |||
setup do: clear_config([:instance, :welcome_user_nickname]) | |||
setup do: clear_config([:welcome]) | |||
test "it autofollows accounts that are set for it" do | |||
user = insert(:user) | |||
@@ -408,17 +409,35 @@ defmodule Pleroma.UserTest do | |||
test "it sends a welcome message if it is set" do | |||
welcome_user = insert(:user) | |||
Pleroma.Config.put([:welcome, :direct_message, :enabled], true) | |||
Pleroma.Config.put([:welcome, :direct_message, :sender_nickname], welcome_user.nickname) | |||
Pleroma.Config.put([:welcome, :direct_message, :message], "Hello, this is a cool site") | |||
Pleroma.Config.put([:welcome, :email, :enabled], true) | |||
Pleroma.Config.put([:welcome, :email, :sender_nickname], welcome_user.nickname) | |||
Pleroma.Config.put( | |||
[:welcome, :email, :subject], | |||
"Hello, welcome to cool site: <%= instance_name %>" | |||
) | |||
Pleroma.Config.put([:instance, :welcome_user_nickname], welcome_user.nickname) | |||
Pleroma.Config.put([:instance, :welcome_message], "Hello, this is a cool site") | |||
instance_name = Pleroma.Config.get([:instance, :name]) | |||
cng = User.register_changeset(%User{}, @full_user_data) | |||
{:ok, registered_user} = User.register(cng) | |||
ObanHelpers.perform_all() | |||
activity = Repo.one(Pleroma.Activity) | |||
assert registered_user.ap_id in activity.recipients | |||
assert Object.normalize(activity).data["content"] =~ "cool site" | |||
assert activity.actor == welcome_user.ap_id | |||
assert_email_sent( | |||
from: {instance_name, welcome_user.email}, | |||
to: {registered_user.name, registered_user.email}, | |||
subject: "Hello, welcome to cool site: #{instance_name}", | |||
html_body: "Welcome to #{instance_name}" | |||
) | |||
end | |||
setup do: clear_config([:instance, :account_activation_required]) | |||