CommonAPI: Use object validation pipeline

This commit is contained in:
Haelwenn (lanodan) Monnier 2024-02-20 06:45:53 +01:00
parent 0b9bc4a0d0
commit 535e972112
No known key found for this signature in database
28 changed files with 134 additions and 36 deletions

View file

View file

@ -231,6 +231,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
defp maybe_create_activity_expiration(%{data: %{"expires_at" => expires_at}} = activity) when is_bitstring(expires_at) do
with {_, {:ok, expires_at, _}} <- {:datetime, DateTime.from_iso8601(expires_at)},
{:ok, _job} <-
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
activity_id: activity.id,
expires_at: expires_at
}) do
{:ok, activity}
else
{:datetime, _} -> {:ok, activity}
e -> e
end
end
defp maybe_create_activity_expiration(activity), do: {:ok, activity}
defp create_or_bump_conversation(activity, actor) do

View file

@ -207,6 +207,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
data =
%{
"type" => "Note",
"id" => Utils.generate_object_id(),
"to" => draft.to,
"cc" => draft.cc,
"content" => draft.content_html,

View file

@ -132,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
do_separate_with_history(object, fn object ->
with {:ok, object} <-
object
|> validator.cast_and_validate()
|> validator.cast_and_validate(meta)
|> Ecto.Changeset.apply_action(:insert) do
object = stringify_keys(object)

View file

@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do
|> validate_accept_reject_rights()
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data
|> validate_data

View file

@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
end
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
{:ok, actor} = User.get_or_fetch_by_ap_id(data["actor"])
{:ok, actor} = maybe_refetch_user(actor)

View file

@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
field(:published, ObjectValidators.DateTime)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -37,7 +37,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do
|> apply_action(:insert)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -34,13 +34,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|> apply_action(:insert)
end
def cast_and_validate(data) do
def cast_and_validate(data, meta \\ []) do
data
|> cast_data()
|> validate_data()
|> cast_data(meta)
|> validate_data(meta)
end
def cast_data(data) do
def cast_data(data, meta \\ []) do
data = fix(data, meta)
%__MODULE__{}
|> changeset(data)
end
@ -76,7 +78,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
def fix_attachments(data), do: data
defp fix(data) do
defp fix(data, _meta) do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_object_defaults()
@ -90,21 +92,29 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
end
def changeset(struct, data) do
data = fix(data)
struct
|> cast(data, __schema__(:fields) -- [:attachment, :tag])
|> cast(data, __schema__(:fields) -- [:attachment, :tag, :generator])
|> cast_embed(:attachment)
|> cast_embed(:tag)
|> cast_embed(:generator)
end
defp validate_data(data_cng) do
defp validate_data(data_cng, meta) do
data_cng
|> validate_inclusion(:type, ["Article", "Note", "Page"])
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|> CommonValidations.validate_any_presence([:cc, :to])
|> maybe_to_cc(meta)
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|> CommonValidations.validate_actor_presence()
|> CommonValidations.validate_host_match()
end
defp maybe_to_cc(data_cng, meta) do
if meta[:local] != true do
data_cng
|> CommonValidations.validate_any_presence([:cc, :to])
else
data_cng
end
end
end

View file

@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
end
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -31,7 +31,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator do
|> apply_action(:insert)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()
@ -109,9 +109,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator do
data = fix(data)
struct
|> cast(data, __schema__(:fields) -- [:attachment, :tag])
|> cast(data, __schema__(:fields) -- [:attachment, :tag, :generator])
|> cast_embed(:attachment, required: true)
|> cast_embed(:tag)
|> cast_embed(:generator)
end
defp validate_data(data_cng) do

View file

@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do
|> CommonValidations.validate_actor_presence(field_name: :object)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data
|> validate_data

View file

@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
|> apply_action(:insert)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -5,6 +5,7 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.GeneratorValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator
# Activities and Objects, except (Create)ChatMessage
@ -64,6 +65,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
embeds_one(:generator, GeneratorValidator)
end
end
end

View file

@ -82,8 +82,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
defp validate_data(cng, meta) do
object = meta[:object_data]
required = [:actor, :type, :object]
required = if meta[:local] == true do
required
else
required ++ [:to, :cc]
end
cng
|> validate_required([:actor, :type, :object, :to, :cc])
|> validate_required(required)
|> validate_inclusion(:type, ["Create"])
|> CommonValidations.validate_actor_presence()
|> validate_actors_match(object)

View file

@ -70,7 +70,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator do
!same_domain?(cng)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data
|> validate_data

View file

@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
field(:content, :string)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do
|> apply_action(:insert)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()
@ -54,9 +54,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do
data = fix(data)
struct
|> cast(data, __schema__(:fields) -- [:attachment, :tag])
|> cast(data, __schema__(:fields) -- [:attachment, :tag, :generator])
|> cast_embed(:attachment)
|> cast_embed(:tag)
|> cast_embed(:generator)
end
defp validate_data(data_cng) do

View file

@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator do
|> validate_actor_presence(field_name: :object)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data
|> validate_data

View file

@ -0,0 +1,40 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.GeneratorValidator do
use Ecto.Schema
alias Pleroma.EctoType.ActivityPub.ObjectValidators
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:type, :string)
field(:name, :string)
field(:url, ObjectValidators.BareUri)
end
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> changeset(data)
end
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
end
defp validate_data(cng) do
cng
|> validate_inclusion(:type, ~w[Application])
|> validate_required([:name, :url])
end
end

View file

@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do
field(:context, :string)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -39,7 +39,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
|> apply_action(:insert)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()
@ -71,11 +71,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
data = fix(data)
struct
|> cast(data, __schema__(:fields) -- [:anyOf, :oneOf, :attachment, :tag])
|> cast(data, __schema__(:fields) -- [:anyOf, :oneOf, :attachment, :tag, :generator])
|> cast_embed(:attachment)
|> cast_embed(:anyOf)
|> cast_embed(:oneOf)
|> cast_embed(:tag)
|> cast_embed(:generator)
end
defp validate_data(data_cng) do

View file

@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
field(:id, ObjectValidators.Uri)
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
end

View file

@ -23,7 +23,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator do
end
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data()
|> validate_data()

View file

@ -39,7 +39,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator do
|> validate_updating_rights()
end
def cast_and_validate(data) do
def cast_and_validate(data, _meta \\ []) do
data
|> cast_data
|> validate_data

View file

@ -195,7 +195,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
# - Increase the user note count
# - Increase the reply count
# - Increase replies count
# - Set up ActivityExpiration
# - Set up notifications
# - Index incoming posts for search (if needed)
@impl true

View file

@ -691,7 +691,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Create-related helpers
def make_create_data(params, additional) do
published = params.published || make_date()
published = Map.get(params, :published) || make_date()
%{
"type" => "Create",
@ -702,6 +702,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"context" => params.context
}
|> Map.merge(additional)
|> Maps.put_if_present("expires_at", additional["expires_at"], &{:ok, DateTime.to_iso8601(&1)})
end
#### Listen-related helpers

View file

@ -425,8 +425,27 @@ defmodule Pleroma.Web.CommonAPI do
end
def post(user, %{status: _} = data) do
with {:ok, draft} <- ActivityDraft.create(user, data) do
ActivityPub.create(draft.changes, draft.preview?)
published = Utils.make_date()
with {:ok, %{changes: changes, preview?: fake} = _draft} <- ActivityDraft.create(user, data),
changes <- changes
|> Map.put_new(:published, published)
|> Map.put("object",
changes.object
|> Map.put_new("id", Utils.generate_object_id())
|> Map.put_new("published", published)
|> Map.merge(changes.additional)
),
create_data <- changes
|> Utils.make_create_data(changes.additional),
{:fake, false, _data} <- {:fake, fake, create_data},
{:ok, create, _} <- Pipeline.common_pipeline(create_data, local: true) do
{:ok, create}
else
{:fake, true, activity} -> {:ok, activity}
{:error, _} = e -> e
e -> {:error, e}
end
end