forked from YokaiRick/akkoma
validator renaming & add validation for target
This commit is contained in:
parent
17f28c0507
commit
ff612750b1
6 changed files with 28 additions and 8 deletions
|
@ -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}
|
||||
|
|
|
@ -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
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue