logo

pleroma

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

20220509180452_change_thread_visibility_to_be_local_only_aware.exs (6017B)


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