logo

pleroma

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

20191007073319_create_following_relationships.exs (6074B)


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