logo

pleroma

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

update_validator.ex (2615B)


  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.UpdateValidator do
  5. use Ecto.Schema
  6. alias Pleroma.EctoType.ActivityPub.ObjectValidators
  7. alias Pleroma.Object
  8. alias Pleroma.User
  9. import Ecto.Changeset
  10. import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
  11. @primary_key false
  12. embedded_schema do
  13. quote do
  14. unquote do
  15. import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields
  16. message_fields()
  17. end
  18. end
  19. field(:actor, ObjectValidators.ObjectID)
  20. # In this case, we save the full object in this activity instead of just a
  21. # reference, so we can always see what was actually changed by this.
  22. field(:object, :map)
  23. end
  24. def cast_data(data) do
  25. %__MODULE__{}
  26. |> cast(data, __schema__(:fields))
  27. end
  28. defp validate_data(cng, meta) do
  29. cng
  30. |> validate_required([:id, :type, :actor, :to, :cc, :object])
  31. |> validate_inclusion(:type, ["Update"])
  32. |> validate_actor_presence()
  33. |> validate_updating_rights(meta)
  34. end
  35. def cast_and_validate(data, meta \\ []) do
  36. data
  37. |> cast_data
  38. |> validate_data(meta)
  39. end
  40. def validate_updating_rights(cng, meta) do
  41. if meta[:local] do
  42. validate_updating_rights_local(cng)
  43. else
  44. validate_updating_rights_remote(cng)
  45. end
  46. end
  47. # For local Updates, verify the actor can edit the object
  48. def validate_updating_rights_local(cng) do
  49. actor = get_field(cng, :actor)
  50. updated_object = get_field(cng, :object)
  51. if {:ok, actor} == ObjectValidators.ObjectID.cast(updated_object) do
  52. cng
  53. else
  54. with %User{} = user <- User.get_cached_by_ap_id(actor),
  55. {_, %Object{} = orig_object} <- {:object, Object.normalize(updated_object)},
  56. :ok <- Object.authorize_access(orig_object, user) do
  57. cng
  58. else
  59. _e ->
  60. cng
  61. |> add_error(:object, "Can't be updated by this actor")
  62. end
  63. end
  64. end
  65. # For remote Updates, verify the host is the same.
  66. def validate_updating_rights_remote(cng) do
  67. with actor = get_field(cng, :actor),
  68. object = get_field(cng, :object),
  69. {:ok, object_id} <- ObjectValidators.ObjectID.cast(object),
  70. actor_uri <- URI.parse(actor),
  71. object_uri <- URI.parse(object_id),
  72. true <- actor_uri.host == object_uri.host do
  73. cng
  74. else
  75. _e ->
  76. cng
  77. |> add_error(:object, "Can't be updated by this actor")
  78. end
  79. end
  80. end