Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

147 行
3.7KB

  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. # Code based on CreateChatMessageValidator
  5. # NOTES
  6. # - doesn't embed, will only get the object id
  7. defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
  8. use Ecto.Schema
  9. alias Pleroma.EctoType.ActivityPub.ObjectValidators
  10. alias Pleroma.Object
  11. alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
  12. alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
  13. import Ecto.Changeset
  14. @primary_key false
  15. embedded_schema do
  16. field(:id, ObjectValidators.ObjectID, primary_key: true)
  17. field(:actor, ObjectValidators.ObjectID)
  18. field(:type, :string)
  19. field(:to, ObjectValidators.Recipients, default: [])
  20. field(:cc, ObjectValidators.Recipients, default: [])
  21. field(:object, ObjectValidators.ObjectID)
  22. field(:expires_at, ObjectValidators.DateTime)
  23. # Should be moved to object, done for CommonAPI.Utils.make_context
  24. field(:context, :string)
  25. end
  26. def cast_data(data, meta \\ []) do
  27. data = fix(data, meta)
  28. %__MODULE__{}
  29. |> changeset(data)
  30. end
  31. def cast_and_apply(data) do
  32. data
  33. |> cast_data
  34. |> apply_action(:insert)
  35. end
  36. def cast_and_validate(data, meta \\ []) do
  37. data
  38. |> cast_data(meta)
  39. |> validate_data(meta)
  40. end
  41. def changeset(struct, data) do
  42. struct
  43. |> cast(data, __schema__(:fields))
  44. end
  45. defp fix_context(data, meta) do
  46. if object = meta[:object_data] do
  47. Map.put_new(data, "context", object["context"])
  48. else
  49. data
  50. end
  51. end
  52. defp fix_addressing(data, meta) do
  53. if object = meta[:object_data] do
  54. data
  55. |> Map.put_new("to", object["to"] || [])
  56. |> Map.put_new("cc", object["cc"] || [])
  57. else
  58. data
  59. end
  60. end
  61. defp fix(data, meta) do
  62. data
  63. |> fix_context(meta)
  64. |> fix_addressing(meta)
  65. |> CommonFixes.fix_actor()
  66. end
  67. defp validate_data(cng, meta) do
  68. cng
  69. |> validate_required([:actor, :type, :object])
  70. |> validate_inclusion(:type, ["Create"])
  71. |> CommonValidations.validate_actor_presence()
  72. |> CommonValidations.validate_any_presence([:to, :cc])
  73. |> validate_actors_match(meta)
  74. |> validate_context_match(meta)
  75. |> validate_object_nonexistence()
  76. |> validate_object_containment()
  77. end
  78. def validate_object_containment(cng) do
  79. actor = get_field(cng, :actor)
  80. cng
  81. |> validate_change(:object, fn :object, object_id ->
  82. %URI{host: object_id_host} = URI.parse(object_id)
  83. %URI{host: actor_host} = URI.parse(actor)
  84. if object_id_host == actor_host do
  85. []
  86. else
  87. [{:object, "The host of the object id doesn't match with the host of the actor"}]
  88. end
  89. end)
  90. end
  91. def validate_object_nonexistence(cng) do
  92. cng
  93. |> validate_change(:object, fn :object, object_id ->
  94. if Object.get_cached_by_ap_id(object_id) do
  95. [{:object, "The object to create already exists"}]
  96. else
  97. []
  98. end
  99. end)
  100. end
  101. def validate_actors_match(cng, meta) do
  102. attributed_to = meta[:object_data]["attributedTo"] || meta[:object_data]["actor"]
  103. cng
  104. |> validate_change(:actor, fn :actor, actor ->
  105. if actor == attributed_to do
  106. []
  107. else
  108. [{:actor, "Actor doesn't match with object attributedTo"}]
  109. end
  110. end)
  111. end
  112. def validate_context_match(cng, %{object_data: %{"context" => object_context}}) do
  113. cng
  114. |> validate_change(:context, fn :context, context ->
  115. if context == object_context do
  116. []
  117. else
  118. [{:context, "context field not matching between Create and object (#{object_context})"}]
  119. end
  120. end)
  121. end
  122. def validate_context_match(cng, _), do: cng
  123. end