logo

pleroma

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

visibility.ex (4822B)


  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.Web.ActivityPub.Visibility do
  5. alias Pleroma.Activity
  6. alias Pleroma.Object
  7. alias Pleroma.Repo
  8. alias Pleroma.User
  9. alias Pleroma.Web.ActivityPub.Utils
  10. require Pleroma.Constants
  11. @spec public?(Object.t() | Activity.t() | map()) :: boolean()
  12. def public?(%Object{data: %{"type" => "Tombstone"}}), do: false
  13. def public?(%Object{data: data}), do: public?(data)
  14. def public?(%Activity{data: %{"type" => "Move"}}), do: true
  15. def public?(%Activity{data: data}), do: public?(data)
  16. def public?(%{"directMessage" => true}), do: false
  17. def public?(data) do
  18. Utils.label_in_message?(Pleroma.Constants.as_public(), data) or
  19. Utils.label_in_message?(Utils.as_local_public(), data)
  20. end
  21. def local_public?(%Object{data: data}), do: local_public?(data)
  22. def local_public?(%Activity{data: data}), do: local_public?(data)
  23. def local_public?(data) do
  24. Utils.label_in_message?(Utils.as_local_public(), data) and
  25. not Utils.label_in_message?(Pleroma.Constants.as_public(), data)
  26. end
  27. def private?(activity) do
  28. with false <- public?(activity),
  29. %User{follower_address: follower_address} <-
  30. User.get_cached_by_ap_id(activity.data["actor"]) do
  31. follower_address in activity.data["to"]
  32. else
  33. _ -> false
  34. end
  35. end
  36. def announceable?(activity, user, public \\ true) do
  37. public?(activity) ||
  38. (!public && private?(activity) && activity.data["actor"] == user.ap_id)
  39. end
  40. def direct?(%Activity{data: %{"directMessage" => true}}), do: true
  41. def direct?(%Object{data: %{"directMessage" => true}}), do: true
  42. def direct?(activity) do
  43. !public?(activity) && !private?(activity)
  44. end
  45. def list?(%{data: %{"listMessage" => _}}), do: true
  46. def list?(_), do: false
  47. @spec visible_for_user?(Object.t() | Activity.t() | nil, User.t() | nil) :: boolean()
  48. def visible_for_user?(%Object{data: %{"type" => "Tombstone"}}, _), do: false
  49. def visible_for_user?(%Activity{actor: ap_id}, %User{ap_id: ap_id}), do: true
  50. def visible_for_user?(%Object{data: %{"actor" => ap_id}}, %User{ap_id: ap_id}), do: true
  51. def visible_for_user?(nil, _), do: false
  52. def visible_for_user?(%Activity{data: %{"listMessage" => _}}, nil), do: false
  53. def visible_for_user?(
  54. %Activity{data: %{"listMessage" => list_ap_id}} = activity,
  55. %User{} = user
  56. ) do
  57. user.ap_id in activity.data["to"] ||
  58. list_ap_id
  59. |> Pleroma.List.get_by_ap_id()
  60. |> Pleroma.List.member?(user)
  61. end
  62. def visible_for_user?(%{__struct__: module} = message, nil)
  63. when module in [Activity, Object] do
  64. if restrict_unauthenticated_access?(message),
  65. do: false,
  66. else: public?(message) and not local_public?(message)
  67. end
  68. def visible_for_user?(%{__struct__: module} = message, user)
  69. when module in [Activity, Object] do
  70. x = [user.ap_id | User.following(user)]
  71. y = [message.data["actor"]] ++ message.data["to"] ++ (message.data["cc"] || [])
  72. user_is_local = user.local
  73. federatable = not local_public?(message)
  74. (public?(message) || Enum.any?(x, &(&1 in y))) and (user_is_local || federatable)
  75. end
  76. def entire_thread_visible_for_user?(%Activity{} = activity, %User{} = user) do
  77. {:ok, %{rows: [[result]]}} =
  78. Ecto.Adapters.SQL.query(Repo, "SELECT thread_visibility($1, $2)", [
  79. user.ap_id,
  80. activity.data["id"]
  81. ])
  82. result
  83. end
  84. def restrict_unauthenticated_access?(%Activity{local: local}) do
  85. restrict_unauthenticated_access_to_activity?(local)
  86. end
  87. def restrict_unauthenticated_access?(%Object{} = object) do
  88. object
  89. |> Object.local?()
  90. |> restrict_unauthenticated_access_to_activity?()
  91. end
  92. def restrict_unauthenticated_access?(%User{} = user) do
  93. User.visible_for(user, _reading_user = nil)
  94. end
  95. defp restrict_unauthenticated_access_to_activity?(local?) when is_boolean(local?) do
  96. cfg_key = if local?, do: :local, else: :remote
  97. Pleroma.Config.restrict_unauthenticated_access?(:activities, cfg_key)
  98. end
  99. def get_visibility(object) do
  100. to = object.data["to"] || []
  101. cc = object.data["cc"] || []
  102. cond do
  103. Pleroma.Constants.as_public() in to ->
  104. "public"
  105. Pleroma.Constants.as_public() in cc ->
  106. "unlisted"
  107. Utils.as_local_public() in to ->
  108. "local"
  109. # this should use the sql for the object's activity
  110. Enum.any?(to, &String.contains?(&1, "/followers")) ->
  111. "private"
  112. object.data["directMessage"] == true ->
  113. "direct"
  114. is_binary(object.data["listMessage"]) ->
  115. "list"
  116. length(cc) > 0 ->
  117. "private"
  118. true ->
  119. "direct"
  120. end
  121. end
  122. end