validator renaming & add validation for target

This commit is contained in:
Alexander Strizhakov 2021-03-02 17:24:06 +03:00
parent 17f28c0507
commit ff612750b1
No known key found for this signature in database
GPG key ID: 022896A53AEF1381
6 changed files with 28 additions and 8 deletions

View file

@ -17,6 +17,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Object.Containment
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator
@ -30,7 +31,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.PinValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
@ -238,7 +238,7 @@ def validate(%{"type" => "Announce"} = object, meta) do
def validate(%{"type" => type} = object, meta) when type in ~w(Add Remove) do
with {:ok, object} <-
object
|> PinValidator.cast_and_validate()
|> AddRemoveValidator.cast_and_validate()
|> Ecto.Changeset.apply_action(:insert) do
object = stringify_keys(object)
{:ok, object, meta}

View file

@ -2,7 +2,7 @@
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.PinValidator do
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
use Ecto.Schema
import Ecto.Changeset
@ -37,6 +37,17 @@ defp validate_data(changeset) do
|> validate_required([:id, :target, :object, :actor, :type, :to, :cc])
|> validate_inclusion(:type, ~w(Add Remove))
|> validate_actor_presence()
|> validate_collection_belongs_to_actor()
|> validate_object_presence()
end
defp validate_collection_belongs_to_actor(changeset) do
validate_change(changeset, :target, fn :target, target ->
if String.starts_with?(target, changeset.changes[:actor]) do
[]
else
[target: "collection doesn't belong to actor"]
end
end)
end
end

View file

@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do
alias Pleroma.Object
alias Pleroma.User
@spec validate_any_presence(Ecto.Changeset.t(), [atom()]) :: Ecto.Changeset.t()
def validate_any_presence(cng, fields) do
non_empty =
fields
@ -29,6 +30,7 @@ def validate_any_presence(cng, fields) do
end
end
@spec validate_actor_presence(Ecto.Changeset.t(), keyword()) :: Ecto.Changeset.t()
def validate_actor_presence(cng, options \\ []) do
field_name = Keyword.get(options, :field_name, :actor)
@ -47,6 +49,7 @@ def validate_actor_presence(cng, options \\ []) do
end)
end
@spec validate_object_presence(Ecto.Changeset.t(), keyword()) :: Ecto.Changeset.t()
def validate_object_presence(cng, options \\ []) do
field_name = Keyword.get(options, :field_name, :object)
allowed_types = Keyword.get(options, :allowed_types, false)
@ -68,6 +71,7 @@ def validate_object_presence(cng, options \\ []) do
end)
end
@spec validate_object_or_user_presence(Ecto.Changeset.t(), keyword()) :: Ecto.Changeset.t()
def validate_object_or_user_presence(cng, options \\ []) do
field_name = Keyword.get(options, :field_name, :object)
options = Keyword.put(options, :field_name, field_name)
@ -83,6 +87,7 @@ def validate_object_or_user_presence(cng, options \\ []) do
if actor_cng.valid?, do: actor_cng, else: object_cng
end
@spec validate_host_match(Ecto.Changeset.t(), [atom()]) :: Ecto.Changeset.t()
def validate_host_match(cng, fields \\ [:id, :actor]) do
if same_domain?(cng, fields) do
cng
@ -95,6 +100,7 @@ def validate_host_match(cng, fields \\ [:id, :actor]) do
end
end
@spec validate_fields_match(Ecto.Changeset.t(), [atom()]) :: Ecto.Changeset.t()
def validate_fields_match(cng, fields) do
if map_unique?(cng, fields) do
cng
@ -122,12 +128,14 @@ defp map_unique?(cng, fields, func \\ & &1) do
end)
end
@spec same_domain?(Ecto.Changeset.t(), [atom()]) :: boolean()
def same_domain?(cng, fields \\ [:actor, :object]) do
map_unique?(cng, fields, fn value -> URI.parse(value).host end)
end
# This figures out if a user is able to create, delete or modify something
# based on the domain and superuser status
@spec validate_modification_rights(Ecto.Changeset.t()) :: Ecto.Changeset.t()
def validate_modification_rights(cng) do
actor = User.get_cached_by_ap_id(get_field(cng, :actor))

View file

@ -168,7 +168,7 @@ test "it accepts Add/Remove activities" do
"id" => "http://localhost:400/objects/d61d6733-e256-4fe1-ab13-1e369789423d",
"actor" => actor,
"object" => object_url,
"target" => "http://example.com/users/lain/collections/featured",
"target" => "https://example.com/users/lain/collections/featured",
"type" => "Remove",
"to" => [Pleroma.Constants.as_public()],
"cc" => ["https://example.com/users/lain/followers"]

View file

@ -1209,15 +1209,15 @@ test "returns 404 error for a wrong id", %{conn: conn} do
setup do: clear_config([:instance, :max_pinned_statuses], 1)
test "pin status", %{conn: conn, user: user, activity: activity} do
id_str = to_string(activity.id)
id = activity.id
assert %{"id" => ^id_str, "pinned" => true} =
assert %{"id" => ^id, "pinned" => true} =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/#{activity.id}/pin")
|> json_response_and_validate_schema(200)
assert [%{"id" => ^id_str, "pinned" => true}] =
assert [%{"id" => ^id, "pinned" => true}] =
conn
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
|> json_response_and_validate_schema(200)

View file

@ -924,7 +924,8 @@ def get("https://mastodon.social/users/lambadalambda/collections/featured", _, _
body:
File.read!("test/fixtures/users_mock/masto_featured.json")
|> String.replace("{{domain}}", "mastodon.social")
|> String.replace("{{nickname}}", "lambadalambda")
|> String.replace("{{nickname}}", "lambadalambda"),
headers: activitypub_object_headers()
}}
end