DeleteValidator: Only allow deletion of certain types.
This commit is contained in:
parent
32b8386ede
commit
5f42e6629d
|
@ -28,7 +28,9 @@ def validate_recipients_presence(cng, fields \\ [:to, :cc]) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_actor_presence(cng, field_name \\ :actor) do
|
def validate_actor_presence(cng, options \\ []) do
|
||||||
|
field_name = Keyword.get(options, :field_name, :actor)
|
||||||
|
|
||||||
cng
|
cng
|
||||||
|> validate_change(field_name, fn field_name, actor ->
|
|> validate_change(field_name, fn field_name, actor ->
|
||||||
if User.get_cached_by_ap_id(actor) do
|
if User.get_cached_by_ap_id(actor) do
|
||||||
|
@ -39,25 +41,39 @@ def validate_actor_presence(cng, field_name \\ :actor) do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_object_presence(cng, field_name \\ :object) do
|
def validate_object_presence(cng, options \\ []) do
|
||||||
|
field_name = Keyword.get(options, :field_name, :object)
|
||||||
|
allowed_types = Keyword.get(options, :allowed_types, false)
|
||||||
|
|
||||||
cng
|
cng
|
||||||
|> validate_change(field_name, fn field_name, object ->
|
|> validate_change(field_name, fn field_name, object_id ->
|
||||||
if Object.get_cached_by_ap_id(object) do
|
object = Object.get_cached_by_ap_id(object_id)
|
||||||
[]
|
|
||||||
else
|
cond do
|
||||||
|
!object ->
|
||||||
[{field_name, "can't find object"}]
|
[{field_name, "can't find object"}]
|
||||||
|
|
||||||
|
object && allowed_types && object.data["type"] not in allowed_types ->
|
||||||
|
[{field_name, "object not in allowed types"}]
|
||||||
|
|
||||||
|
true ->
|
||||||
|
[]
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_object_or_user_presence(cng, field_name \\ :object) do
|
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)
|
||||||
|
|
||||||
|
actor_cng =
|
||||||
cng
|
cng
|
||||||
|> validate_change(field_name, fn field_name, object ->
|
|> validate_actor_presence(options)
|
||||||
if Object.get_cached_by_ap_id(object) || User.get_cached_by_ap_id(object) do
|
|
||||||
[]
|
object_cng =
|
||||||
else
|
cng
|
||||||
[{field_name, "can't find object"}]
|
|> validate_object_presence(options)
|
||||||
end
|
|
||||||
end)
|
if actor_cng.valid?, do: actor_cng, else: object_cng
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,13 +42,23 @@ def add_deleted_activity_id(cng) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@deletable_types ~w{
|
||||||
|
Answer
|
||||||
|
Article
|
||||||
|
Audio
|
||||||
|
Event
|
||||||
|
Note
|
||||||
|
Page
|
||||||
|
Question
|
||||||
|
Video
|
||||||
|
}
|
||||||
def validate_data(cng) do
|
def validate_data(cng) do
|
||||||
cng
|
cng
|
||||||
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
||||||
|> validate_inclusion(:type, ["Delete"])
|
|> validate_inclusion(:type, ["Delete"])
|
||||||
|> validate_actor_presence()
|
|> validate_actor_presence()
|
||||||
|> validate_deletion_rights()
|
|> validate_deletion_rights()
|
||||||
|> validate_object_or_user_presence()
|
|> validate_object_or_user_presence(allowed_types: @deletable_types)
|
||||||
|> add_deleted_activity_id()
|
|> add_deleted_activity_id()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
|
||||||
# - Set up notification
|
# - Set up notification
|
||||||
# - Reduce the user note count
|
# - Reduce the user note count
|
||||||
# - Reduce the reply count
|
# - Reduce the reply count
|
||||||
|
# - Stream out the activity
|
||||||
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
|
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
|
||||||
deleted_object =
|
deleted_object =
|
||||||
Object.normalize(deleted_object, false) || User.get_cached_by_ap_id(deleted_object)
|
Object.normalize(deleted_object, false) || User.get_cached_by_ap_id(deleted_object)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
|
defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
alias Pleroma.Object
|
||||||
alias Pleroma.Web.ActivityPub.Builder
|
alias Pleroma.Web.ActivityPub.Builder
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidator
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
|
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
|
||||||
|
@ -26,6 +27,24 @@ test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete}
|
||||||
assert valid_post_delete["deleted_activity_id"]
|
assert valid_post_delete["deleted_activity_id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it is invalid if the object isn't in a list of certain types", %{
|
||||||
|
valid_post_delete: valid_post_delete
|
||||||
|
} do
|
||||||
|
object = Object.get_by_ap_id(valid_post_delete["object"])
|
||||||
|
|
||||||
|
data =
|
||||||
|
object.data
|
||||||
|
|> Map.put("type", "Like")
|
||||||
|
|
||||||
|
{:ok, _object} =
|
||||||
|
object
|
||||||
|
|> Ecto.Changeset.change(%{data: data})
|
||||||
|
|> Object.update_and_set_cache()
|
||||||
|
|
||||||
|
{:error, cng} = ObjectValidator.validate(valid_post_delete, [])
|
||||||
|
assert {:object, {"object not in allowed types", []}} in cng.errors
|
||||||
|
end
|
||||||
|
|
||||||
test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do
|
test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do
|
||||||
assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, []))
|
assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, []))
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue