Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.8KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.ActivityPub.MRF do
  5. require Logger
  6. @behaviour Pleroma.Web.ActivityPub.MRF.PipelineFiltering
  7. @mrf_config_descriptions [
  8. %{
  9. group: :pleroma,
  10. key: :mrf,
  11. tab: :mrf,
  12. label: "MRF",
  13. type: :group,
  14. description: "General MRF settings",
  15. children: [
  16. %{
  17. key: :policies,
  18. type: [:module, {:list, :module}],
  19. description:
  20. "A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
  21. suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}
  22. },
  23. %{
  24. key: :transparency,
  25. label: "MRF transparency",
  26. type: :boolean,
  27. description:
  28. "Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
  29. },
  30. %{
  31. key: :transparency_exclusions,
  32. label: "MRF transparency exclusions",
  33. type: {:list, :string},
  34. description:
  35. "Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
  36. suggestions: [
  37. "exclusion.com"
  38. ]
  39. }
  40. ]
  41. }
  42. ]
  43. @default_description %{
  44. label: "",
  45. description: ""
  46. }
  47. @required_description_keys [:key, :related_policy]
  48. def filter(policies, %{} = message) do
  49. policies
  50. |> Enum.reduce({:ok, message}, fn
  51. policy, {:ok, message} -> policy.filter(message)
  52. _, error -> error
  53. end)
  54. end
  55. def filter(%{} = object), do: get_policies() |> filter(object)
  56. @impl true
  57. def pipeline_filter(%{} = message, meta) do
  58. object = meta[:object_data]
  59. ap_id = message["object"]
  60. if object && ap_id do
  61. with {:ok, message} <- filter(Map.put(message, "object", object)) do
  62. meta = Keyword.put(meta, :object_data, message["object"])
  63. {:ok, Map.put(message, "object", ap_id), meta}
  64. else
  65. {err, message} -> {err, message, meta}
  66. end
  67. else
  68. {err, message} = filter(message)
  69. {err, message, meta}
  70. end
  71. end
  72. def get_policies do
  73. Pleroma.Config.get([:mrf, :policies], [])
  74. |> get_policies()
  75. |> Enum.concat([Pleroma.Web.ActivityPub.MRF.HashtagPolicy])
  76. end
  77. defp get_policies(policy) when is_atom(policy), do: [policy]
  78. defp get_policies(policies) when is_list(policies), do: policies
  79. defp get_policies(_), do: []
  80. @spec subdomains_regex([String.t()]) :: [Regex.t()]
  81. def subdomains_regex(domains) when is_list(domains) do
  82. for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$)i
  83. end
  84. @spec subdomain_match?([Regex.t()], String.t()) :: boolean()
  85. def subdomain_match?(domains, host) do
  86. Enum.any?(domains, fn domain -> Regex.match?(domain, host) end)
  87. end
  88. def describe(policies) do
  89. {:ok, policy_configs} =
  90. policies
  91. |> Enum.reduce({:ok, %{}}, fn
  92. policy, {:ok, data} ->
  93. {:ok, policy_data} = policy.describe()
  94. {:ok, Map.merge(data, policy_data)}
  95. _, error ->
  96. error
  97. end)
  98. mrf_policies =
  99. get_policies()
  100. |> Enum.map(fn policy -> to_string(policy) |> String.split(".") |> List.last() end)
  101. exclusions = Pleroma.Config.get([:mrf, :transparency_exclusions])
  102. base =
  103. %{
  104. mrf_policies: mrf_policies,
  105. exclusions: length(exclusions) > 0
  106. }
  107. |> Map.merge(policy_configs)
  108. {:ok, base}
  109. end
  110. def describe, do: get_policies() |> describe()
  111. def config_descriptions do
  112. Pleroma.Web.ActivityPub.MRF.Policy
  113. |> Pleroma.Docs.Generator.list_behaviour_implementations()
  114. |> config_descriptions()
  115. end
  116. def config_descriptions(policies) do
  117. Enum.reduce(policies, @mrf_config_descriptions, fn policy, acc ->
  118. if function_exported?(policy, :config_description, 0) do
  119. description =
  120. @default_description
  121. |> Map.merge(policy.config_description)
  122. |> Map.put(:group, :pleroma)
  123. |> Map.put(:tab, :mrf)
  124. |> Map.put(:type, :group)
  125. if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do
  126. [description | acc]
  127. else
  128. Logger.warn(
  129. "#{policy} config description doesn't have one or all required keys #{
  130. inspect(@required_description_keys)
  131. }"
  132. )
  133. acc
  134. end
  135. else
  136. Logger.debug(
  137. "#{policy} is excluded from config descriptions, because does not implement `config_description/0` method."
  138. )
  139. acc
  140. end
  141. end)
  142. end
  143. end