AnnounceValidator: Check for announcability

This commit is contained in:
lain 2020-05-21 13:58:18 +02:00
parent c76267afb9
commit cdc6ba8d7b
2 changed files with 61 additions and 0 deletions

View file

@ -5,12 +5,17 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
use Ecto.Schema use Ecto.Schema
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.Types alias Pleroma.Web.ActivityPub.ObjectValidators.Types
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
import Ecto.Changeset import Ecto.Changeset
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
require Pleroma.Constants
@primary_key false @primary_key false
embedded_schema do embedded_schema do
@ -52,6 +57,33 @@ def validate_data(data_cng) do
|> validate_actor_presence() |> validate_actor_presence()
|> validate_object_presence() |> validate_object_presence()
|> validate_existing_announce() |> validate_existing_announce()
|> validate_announcable()
end
def validate_announcable(cng) do
with actor when is_binary(actor) <- get_field(cng, :actor),
object when is_binary(object) <- get_field(cng, :object),
%User{} = actor <- User.get_cached_by_ap_id(actor),
%Object{} = object <- Object.get_cached_by_ap_id(object),
false <- Visibility.is_public?(object) do
same_actor = object.data["actor"] == actor.ap_id
is_public = Pleroma.Constants.as_public() in (get_field(cng, :to) ++ get_field(cng, :cc))
cond do
same_actor && is_public ->
cng
|> add_error(:actor, "can not announce this object publicly")
!same_actor ->
cng
|> add_error(:actor, "can not announce this object")
true ->
cng
end
else
_ -> cng
end
end end
def validate_existing_announce(cng) do def validate_existing_announce(cng) do

View file

@ -342,5 +342,34 @@ test "returns an error if the actor already announced the object", %{
assert {:actor, {"already announced this object", []}} in cng.errors assert {:actor, {"already announced this object", []}} in cng.errors
assert {:object, {"already announced by this actor", []}} in cng.errors assert {:object, {"already announced by this actor", []}} in cng.errors
end end
test "returns an error if the actor can't announce the object", %{
announcer: announcer,
user: user
} do
{:ok, post_activity} =
CommonAPI.post(user, %{status: "a secret post", visibility: "private"})
object = Object.normalize(post_activity, false)
# Another user can't announce it
{:ok, announce, []} = Builder.announce(announcer, object, public: false)
{:error, cng} = ObjectValidator.validate(announce, [])
assert {:actor, {"can not announce this object", []}} in cng.errors
# The actor of the object can announce it
{:ok, announce, []} = Builder.announce(user, object, public: false)
assert {:ok, _, _} = ObjectValidator.validate(announce, [])
# The actor of the object can not announce it publicly
{:ok, announce, []} = Builder.announce(user, object, public: true)
{:error, cng} = ObjectValidator.validate(announce, [])
assert {:actor, {"can not announce this object publicly", []}} in cng.errors
end
end end
end end