diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index b7ecf51e4..acb635fdc 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -314,7 +314,7 @@ def skip?(:self, activity, user) do
def skip?(
:followers,
activity,
- %{notification_settings: %{"followers" => false}} = user
+ %{notification_settings: %{followers: false}} = user
) do
actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor)
@@ -324,14 +324,14 @@ def skip?(
def skip?(
:non_followers,
activity,
- %{notification_settings: %{"non_followers" => false}} = user
+ %{notification_settings: %{non_followers: false}} = user
) do
actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor)
!User.following?(follower, user)
end
- def skip?(:follows, activity, %{notification_settings: %{"follows" => false}} = user) do
+ def skip?(:follows, activity, %{notification_settings: %{follows: false}} = user) do
actor = activity.data["actor"]
followed = User.get_cached_by_ap_id(actor)
User.following?(user, followed)
@@ -340,7 +340,7 @@ def skip?(:follows, activity, %{notification_settings: %{"follows" => false}} =
def skip?(
:non_follows,
activity,
- %{notification_settings: %{"non_follows" => false}} = user
+ %{notification_settings: %{non_follows: false}} = user
) do
actor = activity.data["actor"]
followed = User.get_cached_by_ap_id(actor)
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index b18a4c6a5..94fca2a9f 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -105,13 +105,10 @@ defmodule Pleroma.User do
field(:invisible, :boolean, default: false)
field(:skip_thread_containment, :boolean, default: false)
- field(:notification_settings, :map,
- default: %{
- "followers" => true,
- "follows" => true,
- "non_follows" => true,
- "non_followers" => true
- }
+ embeds_one(
+ :notification_settings,
+ Pleroma.User.NotificationSetting,
+ on_replace: :update
)
has_many(:notifications, Notification)
@@ -1095,20 +1092,9 @@ def deactivate(%User{} = user, status) do
end
def update_notification_settings(%User{} = user, settings) do
- settings =
- settings
- |> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end)
- |> Map.new()
-
- notification_settings =
- user.notification_settings
- |> Map.merge(settings)
- |> Map.take(["followers", "follows", "non_follows", "non_followers"])
-
- params = %{notification_settings: notification_settings}
-
user
- |> cast(params, [:notification_settings])
+ |> cast(%{notification_settings: settings}, [])
+ |> cast_embed(:notification_settings)
|> validate_required([:notification_settings])
|> update_and_set_cache()
end
diff --git a/lib/pleroma/user/notification_setting.ex b/lib/pleroma/user/notification_setting.ex
new file mode 100644
index 000000000..64100c0e6
--- /dev/null
+++ b/lib/pleroma/user/notification_setting.ex
@@ -0,0 +1,49 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.User.NotificationSetting do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ @derive Jason.Encoder
+ @primary_key false
+
+ @privacy_options %{
+ name_and_message: "name_and_message",
+ name_only: "name_only",
+ no_name_or_message: "no_name_or_message"
+ }
+
+ embedded_schema do
+ field(:followers, :boolean, default: true)
+ field(:follows, :boolean, default: true)
+ field(:non_follows, :boolean, default: true)
+ field(:non_followers, :boolean, default: true)
+ field(:privacy_option, :string, default: @privacy_options.name_and_message)
+ end
+
+ def changeset(schema, params) do
+ schema
+ |> cast(prepare_attrs(params), [
+ :followers,
+ :follows,
+ :non_follows,
+ :non_followers,
+ :privacy_option
+ ])
+ |> validate_inclusion(:privacy_option, Map.values(@privacy_options))
+ end
+
+ defp prepare_attrs(params) do
+ Enum.reduce(params, %{}, fn
+ {k, v}, acc
+ when k in ["followers", "follows", "non_follows", "non_followers"] and
+ is_binary(v) ->
+ Map.put(acc, k, String.downcase(v))
+
+ {k, v}, acc ->
+ Map.put(acc, k, v)
+ end)
+ end
+end
diff --git a/test/notification_test.exs b/test/notification_test.exs
index f8d429223..e7c031c8f 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -136,7 +136,10 @@ test "it creates a notification for an activity from a muted thread" do
test "it disables notifications from followers" do
follower = insert(:user)
- followed = insert(:user, notification_settings: %{"followers" => false})
+
+ followed =
+ insert(:user, notification_settings: %Pleroma.User.NotificationSetting{followers: false})
+
User.follow(follower, followed)
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
refute Notification.create_notification(activity, followed)
@@ -144,13 +147,20 @@ test "it disables notifications from followers" do
test "it disables notifications from non-followers" do
follower = insert(:user)
- followed = insert(:user, notification_settings: %{"non_followers" => false})
+
+ followed =
+ insert(:user,
+ notification_settings: %Pleroma.User.NotificationSetting{non_followers: false}
+ )
+
{:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"})
refute Notification.create_notification(activity, followed)
end
test "it disables notifications from people the user follows" do
- follower = insert(:user, notification_settings: %{"follows" => false})
+ follower =
+ insert(:user, notification_settings: %Pleroma.User.NotificationSetting{follows: false})
+
followed = insert(:user)
User.follow(follower, followed)
follower = Repo.get(User, follower.id)
@@ -159,7 +169,9 @@ test "it disables notifications from people the user follows" do
end
test "it disables notifications from people the user does not follow" do
- follower = insert(:user, notification_settings: %{"non_follows" => false})
+ follower =
+ insert(:user, notification_settings: %Pleroma.User.NotificationSetting{non_follows: false})
+
followed = insert(:user)
{:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"})
refute Notification.create_notification(activity, follower)
diff --git a/test/support/builders/user_builder.ex b/test/support/builders/user_builder.ex
index 6da16f71a..fcfea666f 100644
--- a/test/support/builders/user_builder.ex
+++ b/test/support/builders/user_builder.ex
@@ -10,7 +10,8 @@ def build(data \\ %{}) do
password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
bio: "A tester.",
ap_id: "some id",
- last_digest_emailed_at: NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ last_digest_emailed_at: NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
+ notification_settings: %Pleroma.User.NotificationSetting{}
}
Map.merge(user, data)
diff --git a/test/support/factory.ex b/test/support/factory.ex
index e3f797f64..4bd82ebd6 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -32,7 +32,8 @@ def user_factory do
password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
bio: sequence(:bio, &"Tester Number #{&1}"),
info: %{},
- last_digest_emailed_at: NaiveDateTime.utc_now()
+ last_digest_emailed_at: NaiveDateTime.utc_now(),
+ notification_settings: %Pleroma.User.NotificationSetting{}
}
%{
diff --git a/test/user/notification_setting_test.exs b/test/user/notification_setting_test.exs
new file mode 100644
index 000000000..d1f766eb3
--- /dev/null
+++ b/test/user/notification_setting_test.exs
@@ -0,0 +1,40 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.User.NotificationSettingTest do
+ use Pleroma.DataCase
+
+ alias Pleroma.User.NotificationSetting
+
+ describe "changeset/2" do
+ test "sets valid privacy option" do
+ changeset =
+ NotificationSetting.changeset(
+ %NotificationSetting{},
+ %{"privacy_option" => "name_only"}
+ )
+
+ assert %Ecto.Changeset{valid?: true} = changeset
+ end
+
+ test "returns invalid changeset when privacy option is incorrect" do
+ changeset =
+ NotificationSetting.changeset(
+ %NotificationSetting{},
+ %{"privacy_option" => "full_content"}
+ )
+
+ assert %Ecto.Changeset{valid?: false} = changeset
+
+ assert [
+ privacy_option:
+ {"is invalid",
+ [
+ validation: :inclusion,
+ enum: ["name_and_message", "name_only", "no_name_or_message"]
+ ]}
+ ] = changeset.errors
+ end
+ end
+end
diff --git a/test/user_search_test.exs b/test/user_search_test.exs
index 98841dbbd..821858476 100644
--- a/test/user_search_test.exs
+++ b/test/user_search_test.exs
@@ -174,6 +174,7 @@ test "works with URIs" do
|> Map.put(:search_rank, nil)
|> Map.put(:search_type, nil)
|> Map.put(:last_digest_emailed_at, nil)
+ |> Map.put(:notification_settings, nil)
assert user == expected
end
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index d147079ab..7feff560c 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -92,13 +92,7 @@ test "Represent a user account" do
test "Represent the user account for the account owner" do
user = insert(:user)
- notification_settings = %{
- "followers" => true,
- "follows" => true,
- "non_follows" => true,
- "non_followers" => true
- }
-
+ notification_settings = %Pleroma.User.NotificationSetting{}
privacy = user.default_scope
assert %{
diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs
index f0211f59c..f1557c193 100644
--- a/test/web/twitter_api/util_controller_test.exs
+++ b/test/web/twitter_api/util_controller_test.exs
@@ -159,11 +159,31 @@ test "it updates notification settings", %{conn: conn} do
user = Repo.get(User, user.id)
- assert %{
- "followers" => false,
- "follows" => true,
- "non_follows" => true,
- "non_followers" => true
+ assert %Pleroma.User.NotificationSetting{
+ followers: false,
+ follows: true,
+ non_follows: true,
+ non_followers: true,
+ privacy_option: "name_and_message"
+ } == user.notification_settings
+ end
+
+ test "it update notificatin privacy option", %{conn: conn} do
+ user = insert(:user)
+
+ conn
+ |> assign(:user, user)
+ |> put("/api/pleroma/notification_settings", %{"privacy_option" => "name_only"})
+ |> json_response(:ok)
+
+ user = refresh_record(user)
+
+ assert %Pleroma.User.NotificationSetting{
+ followers: true,
+ follows: true,
+ non_follows: true,
+ non_followers: true,
+ privacy_option: "name_only"
} == user.notification_settings
end
end