logo

pleroma

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

add_remove_validator.ex (2160B)


  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.AddRemoveValidator do
  5. use Ecto.Schema
  6. import Ecto.Changeset
  7. import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
  8. require Pleroma.Constants
  9. alias Pleroma.User
  10. @primary_key false
  11. embedded_schema do
  12. field(:target)
  13. quote do
  14. unquote do
  15. import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields
  16. message_fields()
  17. activity_fields()
  18. end
  19. end
  20. end
  21. def cast_and_validate(data) do
  22. {:ok, actor} = User.get_or_fetch_by_ap_id(data["actor"])
  23. {:ok, actor} = maybe_refetch_user(actor)
  24. data
  25. |> maybe_fix_data_for_mastodon(actor)
  26. |> cast_data()
  27. |> validate_data(actor)
  28. end
  29. defp maybe_fix_data_for_mastodon(data, actor) do
  30. # Mastodon sends pin/unpin objects without id, to, cc fields
  31. data
  32. |> Map.put_new("id", Pleroma.Web.ActivityPub.Utils.generate_activity_id())
  33. |> Map.put_new("to", [Pleroma.Constants.as_public()])
  34. |> Map.put_new("cc", [actor.follower_address])
  35. end
  36. defp cast_data(data) do
  37. cast(%__MODULE__{}, data, __schema__(:fields))
  38. end
  39. defp validate_data(changeset, actor) do
  40. changeset
  41. |> validate_required([:id, :target, :object, :actor, :type, :to, :cc])
  42. |> validate_inclusion(:type, ~w(Add Remove))
  43. |> validate_actor_presence()
  44. |> validate_collection_belongs_to_actor(actor)
  45. |> validate_object_presence()
  46. end
  47. defp validate_collection_belongs_to_actor(changeset, actor) do
  48. validate_change(changeset, :target, fn :target, target ->
  49. if target == actor.featured_address do
  50. []
  51. else
  52. [target: "collection doesn't belong to actor"]
  53. end
  54. end)
  55. end
  56. defp maybe_refetch_user(%User{featured_address: address} = user) when is_binary(address) do
  57. {:ok, user}
  58. end
  59. defp maybe_refetch_user(%User{ap_id: ap_id}) do
  60. # Maybe it could use User.get_or_fetch_by_ap_id to avoid refreshing too often
  61. User.fetch_by_ap_id(ap_id)
  62. end
  63. end