logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

20220821004840_change_thread_visibility_to_use_new_object_id_index.exs (6076B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Repo.Migrations.ChangeThreadVisibilityToUseNewObjectIdIndex do
  5. use Ecto.Migration
  6. def up do
  7. execute(update_thread_visibility())
  8. end
  9. def down do
  10. execute(restore_thread_visibility())
  11. end
  12. def update_thread_visibility do
  13. """
  14. CREATE OR REPLACE FUNCTION thread_visibility(actor varchar, activity_id varchar, local_public varchar default '') RETURNS boolean AS $$
  15. DECLARE
  16. public varchar := 'https://www.w3.org/ns/activitystreams#Public';
  17. child objects%ROWTYPE;
  18. activity activities%ROWTYPE;
  19. author_fa varchar;
  20. valid_recipients varchar[];
  21. actor_user_following varchar[];
  22. BEGIN
  23. --- Fetch actor following
  24. SELECT array_agg(following.follower_address) INTO actor_user_following FROM following_relationships
  25. JOIN users ON users.id = following_relationships.follower_id
  26. JOIN users AS following ON following.id = following_relationships.following_id
  27. WHERE users.ap_id = actor;
  28. --- Fetch our initial activity.
  29. SELECT * INTO activity FROM activities WHERE activities.data->>'id' = activity_id;
  30. LOOP
  31. --- Ensure that we have an activity before continuing.
  32. --- If we don't, the thread is not satisfiable.
  33. IF activity IS NULL THEN
  34. RETURN false;
  35. END IF;
  36. --- We only care about Create activities.
  37. IF activity.data->>'type' != 'Create' THEN
  38. RETURN true;
  39. END IF;
  40. --- Normalize the child object into child.
  41. SELECT * INTO child FROM objects
  42. INNER JOIN activities ON associated_object_id(activities.data) = objects.data->>'id'
  43. WHERE associated_object_id(activity.data) = objects.data->>'id';
  44. --- Fetch the author's AS2 following collection.
  45. SELECT COALESCE(users.follower_address, '') INTO author_fa FROM users WHERE users.ap_id = activity.actor;
  46. --- Prepare valid recipients array.
  47. valid_recipients := ARRAY[actor, public];
  48. --- If we specified local public, add it.
  49. IF local_public <> '' THEN
  50. valid_recipients := valid_recipients || local_public;
  51. END IF;
  52. IF ARRAY[author_fa] && actor_user_following THEN
  53. valid_recipients := valid_recipients || author_fa;
  54. END IF;
  55. --- Check visibility.
  56. IF NOT valid_recipients && activity.recipients THEN
  57. --- activity not visible, break out of the loop
  58. RETURN false;
  59. END IF;
  60. --- If there's a parent, load it and do this all over again.
  61. IF (child.data->'inReplyTo' IS NOT NULL) AND (child.data->'inReplyTo' != 'null'::jsonb) THEN
  62. SELECT * INTO activity FROM activities
  63. INNER JOIN objects ON associated_object_id(activities.data) = objects.data->>'id'
  64. WHERE child.data->>'inReplyTo' = objects.data->>'id';
  65. ELSE
  66. RETURN true;
  67. END IF;
  68. END LOOP;
  69. END;
  70. $$ LANGUAGE plpgsql IMMUTABLE;
  71. """
  72. end
  73. # priv/repo/migrations/20220509180452_change_thread_visibility_to_be_local_only_aware.exs
  74. def restore_thread_visibility do
  75. """
  76. CREATE OR REPLACE FUNCTION thread_visibility(actor varchar, activity_id varchar, local_public varchar default '') RETURNS boolean AS $$
  77. DECLARE
  78. public varchar := 'https://www.w3.org/ns/activitystreams#Public';
  79. child objects%ROWTYPE;
  80. activity activities%ROWTYPE;
  81. author_fa varchar;
  82. valid_recipients varchar[];
  83. actor_user_following varchar[];
  84. BEGIN
  85. --- Fetch actor following
  86. SELECT array_agg(following.follower_address) INTO actor_user_following FROM following_relationships
  87. JOIN users ON users.id = following_relationships.follower_id
  88. JOIN users AS following ON following.id = following_relationships.following_id
  89. WHERE users.ap_id = actor;
  90. --- Fetch our initial activity.
  91. SELECT * INTO activity FROM activities WHERE activities.data->>'id' = activity_id;
  92. LOOP
  93. --- Ensure that we have an activity before continuing.
  94. --- If we don't, the thread is not satisfiable.
  95. IF activity IS NULL THEN
  96. RETURN false;
  97. END IF;
  98. --- We only care about Create activities.
  99. IF activity.data->>'type' != 'Create' THEN
  100. RETURN true;
  101. END IF;
  102. --- Normalize the child object into child.
  103. SELECT * INTO child FROM objects
  104. INNER JOIN activities ON COALESCE(activities.data->'object'->>'id', activities.data->>'object') = objects.data->>'id'
  105. WHERE COALESCE(activity.data->'object'->>'id', activity.data->>'object') = objects.data->>'id';
  106. --- Fetch the author's AS2 following collection.
  107. SELECT COALESCE(users.follower_address, '') INTO author_fa FROM users WHERE users.ap_id = activity.actor;
  108. --- Prepare valid recipients array.
  109. valid_recipients := ARRAY[actor, public];
  110. --- If we specified local public, add it.
  111. IF local_public <> '' THEN
  112. valid_recipients := valid_recipients || local_public;
  113. END IF;
  114. IF ARRAY[author_fa] && actor_user_following THEN
  115. valid_recipients := valid_recipients || author_fa;
  116. END IF;
  117. --- Check visibility.
  118. IF NOT valid_recipients && activity.recipients THEN
  119. --- activity not visible, break out of the loop
  120. RETURN false;
  121. END IF;
  122. --- If there's a parent, load it and do this all over again.
  123. IF (child.data->'inReplyTo' IS NOT NULL) AND (child.data->'inReplyTo' != 'null'::jsonb) THEN
  124. SELECT * INTO activity FROM activities
  125. INNER JOIN objects ON COALESCE(activities.data->'object'->>'id', activities.data->>'object') = objects.data->>'id'
  126. WHERE child.data->>'inReplyTo' = objects.data->>'id';
  127. ELSE
  128. RETURN true;
  129. END IF;
  130. END LOOP;
  131. END;
  132. $$ LANGUAGE plpgsql IMMUTABLE;
  133. """
  134. end
  135. end