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

View File

@ -2,7 +2,7 @@
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.PinValidator do defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
@ -37,6 +37,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.PinValidator do
|> validate_required([:id, :target, :object, :actor, :type, :to, :cc]) |> validate_required([:id, :target, :object, :actor, :type, :to, :cc])
|> validate_inclusion(:type, ~w(Add Remove)) |> validate_inclusion(:type, ~w(Add Remove))
|> validate_actor_presence() |> validate_actor_presence()
|> validate_collection_belongs_to_actor()
|> validate_object_presence() |> validate_object_presence()
end 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 end

View File

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

View File

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

View File

@ -1209,15 +1209,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
setup do: clear_config([:instance, :max_pinned_statuses], 1) setup do: clear_config([:instance, :max_pinned_statuses], 1)
test "pin status", %{conn: conn, user: user, activity: activity} do 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 conn
|> put_req_header("content-type", "application/json") |> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses/#{activity.id}/pin") |> post("/api/v1/statuses/#{activity.id}/pin")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id_str, "pinned" => true}] = assert [%{"id" => ^id, "pinned" => true}] =
conn conn
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true") |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)

View File

@ -924,7 +924,8 @@ defmodule HttpRequestMock do
body: body:
File.read!("test/fixtures/users_mock/masto_featured.json") File.read!("test/fixtures/users_mock/masto_featured.json")
|> String.replace("{{domain}}", "mastodon.social") |> String.replace("{{domain}}", "mastodon.social")
|> String.replace("{{nickname}}", "lambadalambda") |> String.replace("{{nickname}}", "lambadalambda"),
headers: activitypub_object_headers()
}} }}
end end