Skip to content
Snippets Groups Projects
Commit 9b40e5f5 authored by rinpatch's avatar rinpatch
Browse files

Merge branch 'fix/blocked-follows' into 'develop'

Add a migration to fix blocked follows

Closes #1359

See merge request pleroma/pleroma!1922
parents eba8acff 40d5fb6e
No related branches found
No related tags found
No related merge requests found
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment