logo

pleroma

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

chat_message_validator.ex (3744B)


  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.ObjectValidators.ChatMessageValidator do
  5. use Ecto.Schema
  6. alias Pleroma.EctoType.ActivityPub.ObjectValidators
  7. alias Pleroma.User
  8. alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
  9. import Ecto.Changeset
  10. import Pleroma.Web.ActivityPub.Transmogrifier, only: [fix_emoji: 1]
  11. @primary_key false
  12. @derive Jason.Encoder
  13. embedded_schema do
  14. field(:id, ObjectValidators.ObjectID, primary_key: true)
  15. field(:to, ObjectValidators.Recipients, default: [])
  16. field(:type, :string)
  17. field(:content, ObjectValidators.SafeText)
  18. field(:actor, ObjectValidators.ObjectID)
  19. field(:published, ObjectValidators.DateTime)
  20. field(:emoji, ObjectValidators.Emoji, default: %{})
  21. embeds_one(:attachment, AttachmentValidator)
  22. end
  23. def cast_and_apply(data) do
  24. data
  25. |> cast_data
  26. |> apply_action(:insert)
  27. end
  28. def cast_and_validate(data) do
  29. data
  30. |> cast_data()
  31. |> validate_data()
  32. end
  33. def cast_data(data) do
  34. %__MODULE__{}
  35. |> changeset(data)
  36. end
  37. def fix(data) do
  38. data
  39. |> fix_emoji()
  40. |> fix_attachment()
  41. |> Map.put_new("actor", data["attributedTo"])
  42. end
  43. # Throws everything but the first one away
  44. def fix_attachment(%{"attachment" => [attachment | _]} = data) do
  45. data
  46. |> Map.put("attachment", attachment)
  47. end
  48. def fix_attachment(%{"attachment" => attachment} = data) when attachment == [] do
  49. data
  50. |> Map.drop(["attachment"])
  51. end
  52. def fix_attachment(data), do: data
  53. def changeset(struct, data) do
  54. data = fix(data)
  55. struct
  56. |> cast(data, List.delete(__schema__(:fields), :attachment))
  57. |> cast_embed(:attachment)
  58. end
  59. defp validate_data(data_cng) do
  60. data_cng
  61. |> validate_inclusion(:type, ["ChatMessage"])
  62. |> validate_required([:id, :actor, :to, :type, :published])
  63. |> validate_content_or_attachment()
  64. |> validate_length(:to, is: 1)
  65. |> validate_length(:content, max: Pleroma.Config.get([:instance, :remote_limit]))
  66. |> validate_local_concern()
  67. end
  68. def validate_content_or_attachment(cng) do
  69. attachment = get_field(cng, :attachment)
  70. if attachment do
  71. cng
  72. else
  73. cng
  74. |> validate_required([:content])
  75. end
  76. end
  77. @doc """
  78. Validates the following
  79. - If both users are in our system
  80. - If at least one of the users in this ChatMessage is a local user
  81. - If the recipient is not blocking the actor
  82. - If the recipient is explicitly not accepting chat messages
  83. """
  84. def validate_local_concern(cng) do
  85. with actor_ap <- get_field(cng, :actor),
  86. {_, %User{} = actor} <- {:find_actor, User.get_cached_by_ap_id(actor_ap)},
  87. {_, %User{} = recipient} <-
  88. {:find_recipient, User.get_cached_by_ap_id(get_field(cng, :to) |> hd())},
  89. {_, false} <- {:not_accepting_chats?, recipient.accepts_chat_messages == false},
  90. {_, false} <- {:blocking_actor?, User.blocks?(recipient, actor)},
  91. {_, true} <- {:local?, Enum.any?([actor, recipient], & &1.local)} do
  92. cng
  93. else
  94. {:blocking_actor?, true} ->
  95. cng
  96. |> add_error(:actor, "actor is blocked by recipient")
  97. {:not_accepting_chats?, true} ->
  98. cng
  99. |> add_error(:to, "recipient does not accept chat messages")
  100. {:local?, false} ->
  101. cng
  102. |> add_error(:actor, "actor and recipient are both remote")
  103. {:find_actor, _} ->
  104. cng
  105. |> add_error(:actor, "can't find user")
  106. {:find_recipient, _} ->
  107. cng
  108. |> add_error(:to, "can't find user")
  109. end
  110. end
  111. end