aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/pleroma/moderation_log.ex76
-rw-r--r--lib/pleroma/user/query.ex1
-rw-r--r--priv/repo/migrations/20191025143434_add_defaults_to_tables.exs68
-rw-r--r--priv/repo/migrations/20191029172832_fix_blocked_follows.exs112
-rw-r--r--test/user_test.exs65
5 files changed, 301 insertions, 21 deletions
diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex
index e8884e6e8..9dc4a94c9 100644
--- a/lib/pleroma/moderation_log.ex
+++ b/lib/pleroma/moderation_log.ex
@@ -374,6 +374,24 @@ defmodule Pleroma.ModerationLog do
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "activate",
+ "subject" => user
+ }
+ })
+ when is_map(user) do
+ get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "activate",
+ "subject" => [user]
+ }
+ })
+ end
+
+ @spec get_log_entry_message(ModerationLog) :: String.t()
+ def get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "activate",
"subject" => users
}
}) do
@@ -385,6 +403,24 @@ defmodule Pleroma.ModerationLog do
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "deactivate",
+ "subject" => user
+ }
+ })
+ when is_map(user) do
+ get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "deactivate",
+ "subject" => [user]
+ }
+ })
+ end
+
+ @spec get_log_entry_message(ModerationLog) :: String.t()
+ def get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "deactivate",
"subject" => users
}
}) do
@@ -424,6 +460,26 @@ defmodule Pleroma.ModerationLog do
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "grant",
+ "subject" => user,
+ "permission" => permission
+ }
+ })
+ when is_map(user) do
+ get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "grant",
+ "subject" => [user],
+ "permission" => permission
+ }
+ })
+ end
+
+ @spec get_log_entry_message(ModerationLog) :: String.t()
+ def get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "grant",
"subject" => users,
"permission" => permission
}
@@ -436,6 +492,26 @@ defmodule Pleroma.ModerationLog do
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "revoke",
+ "subject" => user,
+ "permission" => permission
+ }
+ })
+ when is_map(user) do
+ get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "revoke",
+ "subject" => [user],
+ "permission" => permission
+ }
+ })
+ end
+
+ @spec get_log_entry_message(ModerationLog) :: String.t()
+ def get_log_entry_message(%ModerationLog{
+ data: %{
+ "actor" => %{"nickname" => actor_nickname},
+ "action" => "revoke",
"subject" => users,
"permission" => permission
}
diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex
index 2eda454bc..364bc1c89 100644
--- a/lib/pleroma/user/query.ex
+++ b/lib/pleroma/user/query.ex
@@ -175,6 +175,7 @@ defmodule Pleroma.User.Query do
[u, following: f, relationships: r],
u.ap_id in ^to or (f.follower_address in ^to and r.state == "accept")
)
+ |> distinct(true)
end
defp compose_query({:order_by, key}, query) do
diff --git a/priv/repo/migrations/20191025143434_add_defaults_to_tables.exs b/priv/repo/migrations/20191025143434_add_defaults_to_tables.exs
new file mode 100644
index 000000000..a5bc82335
--- /dev/null
+++ b/priv/repo/migrations/20191025143434_add_defaults_to_tables.exs
@@ -0,0 +1,68 @@
+defmodule Pleroma.Repo.Migrations.AddDefaultsToTables do
+ use Ecto.Migration
+
+ def up do
+ execute("ALTER TABLE activities
+ ALTER COLUMN recipients SET DEFAULT ARRAY[]::character varying[]")
+
+ execute("ALTER TABLE filters
+ ALTER COLUMN whole_word SET DEFAULT true")
+
+ execute("ALTER TABLE push_subscriptions
+ ALTER COLUMN data SET DEFAULT '{}'::jsonb")
+
+ execute(~s(ALTER TABLE users
+ ALTER COLUMN tags SET DEFAULT ARRAY[]::character varying[],
+ ALTER COLUMN notification_settings SET DEFAULT
+ '{"followers": true, "follows": true, "non_follows": true, "non_followers": true}'::jsonb))
+
+ # irreversible updates
+
+ execute(
+ "UPDATE activities SET recipients = ARRAY[]::character varying[] WHERE recipients IS NULL"
+ )
+
+ execute("UPDATE filters SET whole_word = true WHERE whole_word IS NULL")
+
+ execute("UPDATE push_subscriptions SET data = '{}'::jsonb WHERE data IS NULL")
+
+ execute("UPDATE users SET source_data = '{}'::jsonb where source_data IS NULL")
+ execute("UPDATE users SET note_count = 0 where note_count IS NULL")
+ execute("UPDATE users SET background = '{}'::jsonb where background IS NULL")
+ execute("UPDATE users SET follower_count = 0 where follower_count IS NULL")
+
+ execute(
+ "UPDATE users SET unread_conversation_count = 0 where unread_conversation_count IS NULL"
+ )
+
+ execute(
+ ~s(UPDATE users SET email_notifications = '{"digest": false}'::jsonb where email_notifications IS NULL)
+ )
+
+ execute("UPDATE users SET default_scope = 'public' where default_scope IS NULL")
+
+ execute(
+ "UPDATE users SET pleroma_settings_store = '{}'::jsonb where pleroma_settings_store IS NULL"
+ )
+
+ execute("UPDATE users SET tags = ARRAY[]::character varying[] WHERE tags IS NULL")
+ execute(~s(UPDATE users SET notification_settings =
+ '{"followers": true, "follows": true, "non_follows": true, "non_followers": true}'::jsonb
+ WHERE notification_settings = '{}'::jsonb))
+ end
+
+ def down do
+ execute("ALTER TABLE activities
+ ALTER COLUMN recipients DROP DEFAULT")
+
+ execute("ALTER TABLE filters
+ ALTER COLUMN whole_word DROP DEFAULT")
+
+ execute("ALTER TABLE push_subscriptions
+ ALTER COLUMN data DROP DEFAULT")
+
+ execute("ALTER TABLE users
+ ALTER COLUMN tags DROP DEFAULT,
+ ALTER COLUMN notification_settings SET DEFAULT '{}'::jsonb")
+ end
+end
diff --git a/priv/repo/migrations/20191029172832_fix_blocked_follows.exs b/priv/repo/migrations/20191029172832_fix_blocked_follows.exs
new file mode 100644
index 000000000..71f8f1330
--- /dev/null
+++ b/priv/repo/migrations/20191029172832_fix_blocked_follows.exs
@@ -0,0 +1,112 @@
+defmodule Pleroma.Repo.Migrations.FixBlockedFollows do
+ use Ecto.Migration
+
+ import Ecto.Query
+ alias Pleroma.Config
+ alias Pleroma.Repo
+
+ def up do
+ unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
+
+ if unfollow_blocked do
+ "activities"
+ |> where([activity], fragment("? ->> 'type' = 'Block'", activity.data))
+ |> distinct([activity], [
+ activity.actor,
+ fragment(
+ "coalesce((?)->'object'->>'id', (?)->>'object')",
+ activity.data,
+ activity.data
+ )
+ ])
+ |> order_by([activity], [fragment("? desc nulls last", activity.id)])
+ |> select([activity], %{
+ blocker: activity.actor,
+ blocked:
+ fragment("coalesce((?)->'object'->>'id', (?)->>'object')", activity.data, activity.data),
+ created_at: activity.id
+ })
+ |> Repo.stream()
+ |> Enum.map(&unfollow_if_blocked/1)
+ |> Enum.uniq()
+ |> Enum.each(&update_follower_count/1)
+ end
+ end
+
+ def down do
+ end
+
+ def unfollow_if_blocked(%{blocker: blocker_id, blocked: blocked_id, created_at: blocked_at}) do
+ query =
+ from(
+ activity in "activities",
+ where: fragment("? ->> 'type' = 'Follow'", activity.data),
+ where: activity.actor == ^blocked_id,
+ # this is to use the index
+ where:
+ fragment(
+ "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
+ activity.data,
+ activity.data,
+ ^blocker_id
+ ),
+ where: activity.id > ^blocked_at,
+ where: fragment("(?)->>'state' = 'accept'", activity.data),
+ order_by: [fragment("? desc nulls last", activity.id)]
+ )
+
+ unless Repo.exists?(query) do
+ blocker = "users" |> select([:id, :local]) |> Repo.get_by(ap_id: blocker_id)
+ blocked = "users" |> select([:id]) |> Repo.get_by(ap_id: blocked_id)
+
+ if !is_nil(blocker) && !is_nil(blocked) do
+ unfollow(blocked, blocker)
+ end
+ end
+ end
+
+ def unfollow(%{id: follower_id}, %{id: followed_id} = followed) do
+ following_relationship =
+ "following_relationships"
+ |> where(follower_id: ^follower_id, following_id: ^followed_id, state: "accept")
+ |> select([:id])
+ |> Repo.one()
+
+ case following_relationship do
+ nil ->
+ {:ok, nil}
+
+ %{id: following_relationship_id} ->
+ "following_relationships"
+ |> where(id: ^following_relationship_id)
+ |> Repo.delete_all()
+
+ followed
+ end
+ end
+
+ def update_follower_count(%{id: user_id} = user) do
+ if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do
+ follower_count_query =
+ "users"
+ |> where([u], u.id != ^user_id)
+ |> where([u], u.deactivated != ^true)
+ |> join(:inner, [u], r in "following_relationships",
+ as: :relationships,
+ on: r.following_id == ^user_id and r.follower_id == u.id
+ )
+ |> where([relationships: r], r.state == "accept")
+ |> select([u], %{count: count(u.id)})
+
+ "users"
+ |> where(id: ^user_id)
+ |> join(:inner, [u], s in subquery(follower_count_query))
+ |> update([u, s],
+ set: [follower_count: s.count]
+ )
+ |> Repo.update_all([])
+ end
+ end
+
+ def update_follower_count(_), do: :noop
+end
diff --git a/test/user_test.exs b/test/user_test.exs
index 188295a86..6b1b24ce5 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -878,27 +878,50 @@ defmodule Pleroma.UserTest do
end
end
- test "get recipients from activity" do
- actor = insert(:user)
- user = insert(:user, local: true)
- user_two = insert(:user, local: false)
- addressed = insert(:user, local: true)
- addressed_remote = insert(:user, local: false)
-
- {:ok, activity} =
- CommonAPI.post(actor, %{
- "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
- })
-
- assert Enum.map([actor, addressed], & &1.ap_id) --
- Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
-
- {:ok, user} = User.follow(user, actor)
- {:ok, _user_two} = User.follow(user_two, actor)
- recipients = User.get_recipients_from_activity(activity)
- assert length(recipients) == 3
- assert user in recipients
- assert addressed in recipients
+ describe "get_recipients_from_activity" do
+ test "get recipients" do
+ actor = insert(:user)
+ user = insert(:user, local: true)
+ user_two = insert(:user, local: false)
+ addressed = insert(:user, local: true)
+ addressed_remote = insert(:user, local: false)
+
+ {:ok, activity} =
+ CommonAPI.post(actor, %{
+ "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
+ })
+
+ assert Enum.map([actor, addressed], & &1.ap_id) --
+ Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
+
+ {:ok, user} = User.follow(user, actor)
+ {:ok, _user_two} = User.follow(user_two, actor)
+ recipients = User.get_recipients_from_activity(activity)
+ assert length(recipients) == 3
+ assert user in recipients
+ assert addressed in recipients
+ end
+
+ test "has following" do
+ actor = insert(:user)
+ user = insert(:user)
+ user_two = insert(:user)
+ addressed = insert(:user, local: true)
+
+ {:ok, activity} =
+ CommonAPI.post(actor, %{
+ "status" => "hey @#{addressed.nickname}"
+ })
+
+ assert Enum.map([actor, addressed], & &1.ap_id) --
+ Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
+
+ {:ok, _actor} = User.follow(actor, user)
+ {:ok, _actor} = User.follow(actor, user_two)
+ recipients = User.get_recipients_from_activity(activity)
+ assert length(recipients) == 2
+ assert addressed in recipients
+ end
end
describe ".deactivate" do