Merge branch 'develop' into issue/1342
authorMaksim Pechnikov <parallel588@gmail.com>
Sun, 8 Dec 2019 18:25:26 +0000 (21:25 +0300)
committerMaksim Pechnikov <parallel588@gmail.com>
Sun, 8 Dec 2019 18:25:26 +0000 (21:25 +0300)
14 files changed:
lib/mix/tasks/pleroma/notification_settings.ex [new file with mode: 0644]
lib/pleroma/notification.ex
lib/pleroma/user.ex
lib/pleroma/user/notification_setting.ex [new file with mode: 0644]
lib/pleroma/web/push/impl.ex
lib/pleroma/workers/web_pusher_worker.ex
test/notification_test.exs
test/support/builders/user_builder.ex
test/support/factory.ex
test/user/notification_setting_test.exs [new file with mode: 0644]
test/user_search_test.exs
test/web/mastodon_api/views/account_view_test.exs
test/web/push/impl_test.exs
test/web/twitter_api/util_controller_test.exs

diff --git a/lib/mix/tasks/pleroma/notification_settings.ex b/lib/mix/tasks/pleroma/notification_settings.ex
new file mode 100644 (file)
index 0000000..7d65f05
--- /dev/null
@@ -0,0 +1,83 @@
+defmodule Mix.Tasks.Pleroma.NotificationSettings do
+  @shortdoc "Enable&Disable privacy option for push notifications"
+  @moduledoc """
+  Example:
+
+  > mix pleroma.notification_settings --privacy-option=false --nickname-users="parallel588"  # set false only for parallel588 user
+  > mix pleroma.notification_settings --privacy-option=true # set true for all users
+
+  """
+
+  use Mix.Task
+  import Mix.Pleroma
+  import Ecto.Query
+
+  def run(args) do
+    start_pleroma()
+
+    {options, _, _} =
+      OptionParser.parse(
+        args,
+        strict: [
+          privacy_option: :boolean,
+          email_users: :string,
+          nickname_users: :string
+        ]
+      )
+
+    privacy_option = Keyword.get(options, :privacy_option)
+
+    if not is_nil(privacy_option) do
+      privacy_option
+      |> build_query(options)
+      |> Pleroma.Repo.update_all([])
+    end
+
+    shell_info("Done")
+  end
+
+  defp build_query(privacy_option, options) do
+    query =
+      from(u in Pleroma.User,
+        update: [
+          set: [
+            notification_settings:
+              fragment(
+                "jsonb_set(notification_settings, '{privacy_option}', ?)",
+                ^privacy_option
+              )
+          ]
+        ]
+      )
+
+    user_emails =
+      options
+      |> Keyword.get(:email_users, "")
+      |> String.split(",")
+      |> Enum.map(&String.trim(&1))
+      |> Enum.reject(&(&1 == ""))
+
+    query =
+      if length(user_emails) > 0 do
+        where(query, [u], u.email in ^user_emails)
+      else
+        query
+      end
+
+    user_nicknames =
+      options
+      |> Keyword.get(:nickname_users, "")
+      |> String.split(",")
+      |> Enum.map(&String.trim(&1))
+      |> Enum.reject(&(&1 == ""))
+
+    query =
+      if length(user_nicknames) > 0 do
+        where(query, [u], u.nickname in ^user_nicknames)
+      else
+        query
+      end
+
+    query
+  end
+end
index 71423ce5e89695175073e6d44d41bfaba56b5f88..93f9628ff13840f7ea54d87881246ea68bdd01d4 100644 (file)
@@ -347,7 +347,7 @@ defmodule Pleroma.Notification 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)
@@ -357,14 +357,14 @@ defmodule Pleroma.Notification do
   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)
@@ -373,7 +373,7 @@ defmodule Pleroma.Notification do
   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)
index b7f50e5acb4cbbf2add0b8ae6739b79acaa1568f..e2afc6de8215b3555f41a8f44b56984e388ecac5 100644 (file)
@@ -129,13 +129,10 @@ defmodule Pleroma.User do
     field(:skip_thread_containment, :boolean, default: false)
     field(:also_known_as, {:array, :string}, default: [])
 
-    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)
@@ -1221,20 +1218,9 @@ defmodule Pleroma.User 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 (file)
index 0000000..f089961
--- /dev/null
@@ -0,0 +1,40 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.User.NotificationSetting do
+  use Ecto.Schema
+  import Ecto.Changeset
+
+  @derive Jason.Encoder
+  @primary_key false
+
+  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, :boolean, default: false)
+  end
+
+  def changeset(schema, params) do
+    schema
+    |> cast(prepare_attrs(params), [
+      :followers,
+      :follows,
+      :non_follows,
+      :non_followers,
+      :privacy_option
+    ])
+  end
+
+  defp prepare_attrs(params) do
+    Enum.reduce(params, %{}, fn
+      {k, v}, acc when is_binary(v) ->
+        Map.put(acc, k, String.downcase(v))
+
+      {k, v}, acc ->
+        Map.put(acc, k, v)
+    end)
+  end
+end
index a6a924d02f067191ddda7e157ffbb40209fd2f12..34ec1d8d967493140032966f90b80602cb334222 100644 (file)
@@ -22,8 +22,8 @@ defmodule Pleroma.Web.Push.Impl do
   @spec perform(Notification.t()) :: list(any) | :error
   def perform(
         %{
-          activity: %{data: %{"type" => activity_type}, id: activity_id} = activity,
-          user_id: user_id
+          activity: %{data: %{"type" => activity_type}} = activity,
+          user: %User{id: user_id}
         } = notif
       )
       when activity_type in @types do
@@ -39,18 +39,17 @@ defmodule Pleroma.Web.Push.Impl do
     for subscription <- fetch_subsriptions(user_id),
         get_in(subscription.data, ["alerts", type]) do
       %{
-        title: format_title(notif),
         access_token: subscription.token.token,
-        body: format_body(notif, actor, object),
         notification_id: notif.id,
         notification_type: type,
         icon: avatar_url,
         preferred_locale: "en",
         pleroma: %{
-          activity_id: activity_id,
+          activity_id: notif.activity.id,
           direct_conversation_id: direct_conversation_id
         }
       }
+      |> Map.merge(build_content(notif, actor, object))
       |> Jason.encode!()
       |> push_message(build_sub(subscription), gcm_api_key, subscription)
     end
@@ -100,6 +99,24 @@ defmodule Pleroma.Web.Push.Impl do
     }
   end
 
+  def build_content(
+        %{
+          activity: %{data: %{"directMessage" => true}},
+          user: %{notification_settings: %{privacy_option: true}}
+        },
+        actor,
+        _
+      ) do
+    %{title: "New Direct Message", body: "@#{actor.nickname}"}
+  end
+
+  def build_content(notif, actor, object) do
+    %{
+      title: format_title(notif),
+      body: format_body(notif, actor, object)
+    }
+  end
+
   def format_body(
         %{activity: %{data: %{"type" => "Create"}}},
         actor,
index 61b451e3ed99aecd8fb7bdee08c084b0138bf74f..a978c4013d03837dca7fc24cec2166e1f6ff0ec7 100644 (file)
@@ -13,7 +13,7 @@ defmodule Pleroma.Workers.WebPusherWorker do
     notification =
       Notification
       |> Repo.get(notification_id)
-      |> Repo.preload([:activity])
+      |> Repo.preload([:activity, :user])
 
     Pleroma.Web.Push.Impl.perform(notification)
   end
index 827ac4f06fe4ca9ff6cf9576456e94f911f8c53a..ffa3d4b8c52604f0c638928de65d49b9b1de0c24 100644 (file)
@@ -136,7 +136,10 @@ defmodule Pleroma.NotificationTest 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 @@ defmodule Pleroma.NotificationTest 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 @@ defmodule Pleroma.NotificationTest 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)
index 6da16f71a90df664f9467633cfef851502f4c132..fcfea666f1a2f517f2b8a698e632cc0f1c1a9728 100644 (file)
@@ -10,7 +10,8 @@ defmodule Pleroma.Builders.UserBuilder 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)
index 35ba523a1c48c795c25a5b1a475ca460b66d7ed0..314f26ec99d1de43b7d7f07311b50ab39753a867 100644 (file)
@@ -31,7 +31,8 @@ defmodule Pleroma.Factory do
       nickname: sequence(:nickname, &"nick#{&1}"),
       password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
       bio: sequence(:bio, &"Tester Number #{&1}"),
-      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 (file)
index 0000000..4744d7b
--- /dev/null
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# 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" => true}
+        )
+
+      assert %Ecto.Changeset{valid?: true} = changeset
+    end
+  end
+end
index 98841dbbda2c231f586a3b17896ca08815f2b737..82185847672a6a2e5affa1be18339721fd78f0f6 100644 (file)
@@ -174,6 +174,7 @@ defmodule Pleroma.UserSearchTest 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
index ed6f2ecbd7577f70de4c67c074c3d636c43531f1..5e297d1298015fe8a2637512c921d95ba6ede6f6 100644 (file)
@@ -92,13 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest 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 %{
index 9b554601d9c146079ccb1809a49ba37aef522bbd..acae7a734deca67cb8d147f0c58e8d26feebb349 100644 (file)
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.Push.ImplTest do
   use Pleroma.DataCase
 
   alias Pleroma.Object
+  alias Pleroma.User
   alias Pleroma.Web.CommonAPI
   alias Pleroma.Web.Push.Impl
   alias Pleroma.Web.Push.Subscription
@@ -182,4 +183,50 @@ defmodule Pleroma.Web.Push.ImplTest do
     assert Impl.format_title(%{activity: activity}) ==
              "New Direct Message"
   end
+
+  describe "build_content/3" do
+    test "returns info content for direct message with enabled privacy option" do
+      user = insert(:user, nickname: "Bob")
+      user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: true})
+
+      {:ok, activity} =
+        CommonAPI.post(user, %{
+          "visibility" => "direct",
+          "status" => "<Lorem ipsum dolor sit amet."
+        })
+
+      notif = insert(:notification, user: user2, activity: activity)
+
+      actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+      object = Object.normalize(activity)
+
+      assert Impl.build_content(notif, actor, object) == %{
+               body: "@Bob",
+               title: "New Direct Message"
+             }
+    end
+
+    test "returns regular content for direct message with disabled privacy option" do
+      user = insert(:user, nickname: "Bob")
+      user2 = insert(:user, nickname: "Rob", notification_settings: %{privacy_option: false})
+
+      {:ok, activity} =
+        CommonAPI.post(user, %{
+          "visibility" => "direct",
+          "status" =>
+            "<span>Lorem ipsum dolor sit amet</span>, consectetur :firefox: adipiscing elit. Fusce sagittis finibus turpis."
+        })
+
+      notif = insert(:notification, user: user2, activity: activity)
+
+      actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+      object = Object.normalize(activity)
+
+      assert Impl.build_content(notif, actor, object) == %{
+               body:
+                 "@Bob: Lorem ipsum dolor sit amet, consectetur  adipiscing elit. Fusce sagittis fini...",
+               title: "New Direct Message"
+             }
+    end
+  end
 end
index 986ee01f35ecb850f9493045942b4e28873d8e68..734cd221199554898ef40bbec79c0b658a4b139a 100644 (file)
@@ -159,11 +159,31 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest 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: false
+             } == 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" => "1"})
+      |> json_response(:ok)
+
+      user = refresh_record(user)
+
+      assert %Pleroma.User.NotificationSetting{
+               followers: true,
+               follows: true,
+               non_follows: true,
+               non_followers: true,
+               privacy_option: true
              } == user.notification_settings
     end
   end