logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

object_validator_test.exs (21845B)


      1 defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
      2   use Pleroma.DataCase
      3 
      4   alias Pleroma.Object
      5   alias Pleroma.Web.ActivityPub.ActivityPub
      6   alias Pleroma.Web.ActivityPub.Builder
      7   alias Pleroma.Web.ActivityPub.ObjectValidator
      8   alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
      9   alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
     10   alias Pleroma.Web.ActivityPub.Utils
     11   alias Pleroma.Web.CommonAPI
     12 
     13   import Pleroma.Factory
     14 
     15   describe "attachments" do
     16     test "works with honkerific attachments" do
     17       attachment = %{
     18         "mediaType" => "",
     19         "name" => "",
     20         "summary" => "298p3RG7j27tfsZ9RQ.jpg",
     21         "type" => "Document",
     22         "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
     23       }
     24 
     25       assert {:ok, attachment} =
     26                AttachmentValidator.cast_and_validate(attachment)
     27                |> Ecto.Changeset.apply_action(:insert)
     28 
     29       assert attachment.mediaType == "application/octet-stream"
     30     end
     31 
     32     test "it turns mastodon attachments into our attachments" do
     33       attachment = %{
     34         "url" =>
     35           "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
     36         "type" => "Document",
     37         "name" => nil,
     38         "mediaType" => "image/jpeg"
     39       }
     40 
     41       {:ok, attachment} =
     42         AttachmentValidator.cast_and_validate(attachment)
     43         |> Ecto.Changeset.apply_action(:insert)
     44 
     45       assert [
     46                %{
     47                  href:
     48                    "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
     49                  type: "Link",
     50                  mediaType: "image/jpeg"
     51                }
     52              ] = attachment.url
     53 
     54       assert attachment.mediaType == "image/jpeg"
     55     end
     56 
     57     test "it handles our own uploads" do
     58       user = insert(:user)
     59 
     60       file = %Plug.Upload{
     61         content_type: "image/jpg",
     62         path: Path.absname("test/fixtures/image.jpg"),
     63         filename: "an_image.jpg"
     64       }
     65 
     66       {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
     67 
     68       {:ok, attachment} =
     69         attachment.data
     70         |> AttachmentValidator.cast_and_validate()
     71         |> Ecto.Changeset.apply_action(:insert)
     72 
     73       assert attachment.mediaType == "image/jpeg"
     74     end
     75   end
     76 
     77   describe "chat message create activities" do
     78     test "it is invalid if the object already exists" do
     79       user = insert(:user)
     80       recipient = insert(:user)
     81       {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey")
     82       object = Object.normalize(activity, false)
     83 
     84       {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id])
     85 
     86       {:error, cng} = ObjectValidator.validate(create_data, [])
     87 
     88       assert {:object, {"The object to create already exists", []}} in cng.errors
     89     end
     90 
     91     test "it is invalid if the object data has a different `to` or `actor` field" do
     92       user = insert(:user)
     93       recipient = insert(:user)
     94       {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey")
     95 
     96       {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id])
     97 
     98       {:error, cng} = ObjectValidator.validate(create_data, [])
     99 
    100       assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors
    101       assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors
    102     end
    103   end
    104 
    105   describe "chat messages" do
    106     setup do
    107       clear_config([:instance, :remote_limit])
    108       user = insert(:user)
    109       recipient = insert(:user, local: false)
    110 
    111       {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:")
    112 
    113       %{user: user, recipient: recipient, valid_chat_message: valid_chat_message}
    114     end
    115 
    116     test "let's through some basic html", %{user: user, recipient: recipient} do
    117       {:ok, valid_chat_message, _} =
    118         Builder.chat_message(
    119           user,
    120           recipient.ap_id,
    121           "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>"
    122         )
    123 
    124       assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
    125 
    126       assert object["content"] ==
    127                "hey <a href=\"https://example.org\">example</a> alert(&#39;uguu&#39;)"
    128     end
    129 
    130     test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do
    131       assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
    132 
    133       assert Map.put(valid_chat_message, "attachment", nil) == object
    134     end
    135 
    136     test "validates for a basic object with an attachment", %{
    137       valid_chat_message: valid_chat_message,
    138       user: user
    139     } do
    140       file = %Plug.Upload{
    141         content_type: "image/jpg",
    142         path: Path.absname("test/fixtures/image.jpg"),
    143         filename: "an_image.jpg"
    144       }
    145 
    146       {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
    147 
    148       valid_chat_message =
    149         valid_chat_message
    150         |> Map.put("attachment", attachment.data)
    151 
    152       assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
    153 
    154       assert object["attachment"]
    155     end
    156 
    157     test "validates for a basic object with an attachment in an array", %{
    158       valid_chat_message: valid_chat_message,
    159       user: user
    160     } do
    161       file = %Plug.Upload{
    162         content_type: "image/jpg",
    163         path: Path.absname("test/fixtures/image.jpg"),
    164         filename: "an_image.jpg"
    165       }
    166 
    167       {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
    168 
    169       valid_chat_message =
    170         valid_chat_message
    171         |> Map.put("attachment", [attachment.data])
    172 
    173       assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
    174 
    175       assert object["attachment"]
    176     end
    177 
    178     test "validates for a basic object with an attachment but without content", %{
    179       valid_chat_message: valid_chat_message,
    180       user: user
    181     } do
    182       file = %Plug.Upload{
    183         content_type: "image/jpg",
    184         path: Path.absname("test/fixtures/image.jpg"),
    185         filename: "an_image.jpg"
    186       }
    187 
    188       {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
    189 
    190       valid_chat_message =
    191         valid_chat_message
    192         |> Map.put("attachment", attachment.data)
    193         |> Map.delete("content")
    194 
    195       assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
    196 
    197       assert object["attachment"]
    198     end
    199 
    200     test "does not validate if the message has no content", %{
    201       valid_chat_message: valid_chat_message
    202     } do
    203       contentless =
    204         valid_chat_message
    205         |> Map.delete("content")
    206 
    207       refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, []))
    208     end
    209 
    210     test "does not validate if the message is longer than the remote_limit", %{
    211       valid_chat_message: valid_chat_message
    212     } do
    213       Pleroma.Config.put([:instance, :remote_limit], 2)
    214       refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
    215     end
    216 
    217     test "does not validate if the recipient is blocking the actor", %{
    218       valid_chat_message: valid_chat_message,
    219       user: user,
    220       recipient: recipient
    221     } do
    222       Pleroma.User.block(recipient, user)
    223       refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
    224     end
    225 
    226     test "does not validate if the actor or the recipient is not in our system", %{
    227       valid_chat_message: valid_chat_message
    228     } do
    229       chat_message =
    230         valid_chat_message
    231         |> Map.put("actor", "https://raymoo.com/raymoo")
    232 
    233       {:error, _} = ObjectValidator.validate(chat_message, [])
    234 
    235       chat_message =
    236         valid_chat_message
    237         |> Map.put("to", ["https://raymoo.com/raymoo"])
    238 
    239       {:error, _} = ObjectValidator.validate(chat_message, [])
    240     end
    241 
    242     test "does not validate for a message with multiple recipients", %{
    243       valid_chat_message: valid_chat_message,
    244       user: user,
    245       recipient: recipient
    246     } do
    247       chat_message =
    248         valid_chat_message
    249         |> Map.put("to", [user.ap_id, recipient.ap_id])
    250 
    251       assert {:error, _} = ObjectValidator.validate(chat_message, [])
    252     end
    253 
    254     test "does not validate if it doesn't concern local users" do
    255       user = insert(:user, local: false)
    256       recipient = insert(:user, local: false)
    257 
    258       {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey")
    259       assert {:error, _} = ObjectValidator.validate(valid_chat_message, [])
    260     end
    261   end
    262 
    263   describe "EmojiReacts" do
    264     setup do
    265       user = insert(:user)
    266       {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
    267 
    268       object = Pleroma.Object.get_by_ap_id(post_activity.data["object"])
    269 
    270       {:ok, valid_emoji_react, []} = Builder.emoji_react(user, object, "👌")
    271 
    272       %{user: user, post_activity: post_activity, valid_emoji_react: valid_emoji_react}
    273     end
    274 
    275     test "it validates a valid EmojiReact", %{valid_emoji_react: valid_emoji_react} do
    276       assert {:ok, _, _} = ObjectValidator.validate(valid_emoji_react, [])
    277     end
    278 
    279     test "it is not valid without a 'content' field", %{valid_emoji_react: valid_emoji_react} do
    280       without_content =
    281         valid_emoji_react
    282         |> Map.delete("content")
    283 
    284       {:error, cng} = ObjectValidator.validate(without_content, [])
    285 
    286       refute cng.valid?
    287       assert {:content, {"can't be blank", [validation: :required]}} in cng.errors
    288     end
    289 
    290     test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do
    291       without_emoji_content =
    292         valid_emoji_react
    293         |> Map.put("content", "x")
    294 
    295       {:error, cng} = ObjectValidator.validate(without_emoji_content, [])
    296 
    297       refute cng.valid?
    298 
    299       assert {:content, {"must be a single character emoji", []}} in cng.errors
    300     end
    301   end
    302 
    303   describe "Undos" do
    304     setup do
    305       user = insert(:user)
    306       {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
    307       {:ok, like} = CommonAPI.favorite(user, post_activity.id)
    308       {:ok, valid_like_undo, []} = Builder.undo(user, like)
    309 
    310       %{user: user, like: like, valid_like_undo: valid_like_undo}
    311     end
    312 
    313     test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do
    314       assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, [])
    315     end
    316 
    317     test "it does not validate if the actor of the undo is not the actor of the object", %{
    318       valid_like_undo: valid_like_undo
    319     } do
    320       other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo")
    321 
    322       bad_actor =
    323         valid_like_undo
    324         |> Map.put("actor", other_user.ap_id)
    325 
    326       {:error, cng} = ObjectValidator.validate(bad_actor, [])
    327 
    328       assert {:actor, {"not the same as object actor", []}} in cng.errors
    329     end
    330 
    331     test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do
    332       missing_object =
    333         valid_like_undo
    334         |> Map.put("object", "https://gensokyo.2hu/objects/1")
    335 
    336       {:error, cng} = ObjectValidator.validate(missing_object, [])
    337 
    338       assert {:object, {"can't find object", []}} in cng.errors
    339       assert length(cng.errors) == 1
    340     end
    341   end
    342 
    343   describe "deletes" do
    344     setup do
    345       user = insert(:user)
    346       {:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"})
    347 
    348       {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
    349       {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
    350 
    351       %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete}
    352     end
    353 
    354     test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do
    355       {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, [])
    356 
    357       assert valid_post_delete["deleted_activity_id"]
    358     end
    359 
    360     test "it is invalid if the object isn't in a list of certain types", %{
    361       valid_post_delete: valid_post_delete
    362     } do
    363       object = Object.get_by_ap_id(valid_post_delete["object"])
    364 
    365       data =
    366         object.data
    367         |> Map.put("type", "Like")
    368 
    369       {:ok, _object} =
    370         object
    371         |> Ecto.Changeset.change(%{data: data})
    372         |> Object.update_and_set_cache()
    373 
    374       {:error, cng} = ObjectValidator.validate(valid_post_delete, [])
    375       assert {:object, {"object not in allowed types", []}} in cng.errors
    376     end
    377 
    378     test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do
    379       assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, []))
    380     end
    381 
    382     test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do
    383       no_id =
    384         valid_post_delete
    385         |> Map.delete("id")
    386 
    387       {:error, cng} = ObjectValidator.validate(no_id, [])
    388 
    389       assert {:id, {"can't be blank", [validation: :required]}} in cng.errors
    390     end
    391 
    392     test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do
    393       missing_object =
    394         valid_post_delete
    395         |> Map.put("object", "http://does.not/exist")
    396 
    397       {:error, cng} = ObjectValidator.validate(missing_object, [])
    398 
    399       assert {:object, {"can't find object", []}} in cng.errors
    400     end
    401 
    402     test "it's invalid if the actor of the object and the actor of delete are from different domains",
    403          %{valid_post_delete: valid_post_delete} do
    404       valid_user = insert(:user)
    405 
    406       valid_other_actor =
    407         valid_post_delete
    408         |> Map.put("actor", valid_user.ap_id)
    409 
    410       assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, []))
    411 
    412       invalid_other_actor =
    413         valid_post_delete
    414         |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
    415 
    416       {:error, cng} = ObjectValidator.validate(invalid_other_actor, [])
    417 
    418       assert {:actor, {"is not allowed to delete object", []}} in cng.errors
    419     end
    420 
    421     test "it's valid if the actor of the object is a local superuser",
    422          %{valid_post_delete: valid_post_delete} do
    423       user =
    424         insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo")
    425 
    426       valid_other_actor =
    427         valid_post_delete
    428         |> Map.put("actor", user.ap_id)
    429 
    430       {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, [])
    431       assert meta[:do_not_federate]
    432     end
    433   end
    434 
    435   describe "likes" do
    436     setup do
    437       user = insert(:user)
    438       {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
    439 
    440       valid_like = %{
    441         "to" => [user.ap_id],
    442         "cc" => [],
    443         "type" => "Like",
    444         "id" => Utils.generate_activity_id(),
    445         "object" => post_activity.data["object"],
    446         "actor" => user.ap_id,
    447         "context" => "a context"
    448       }
    449 
    450       %{valid_like: valid_like, user: user, post_activity: post_activity}
    451     end
    452 
    453     test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do
    454       {:ok, object, _meta} = ObjectValidator.validate(valid_like, [])
    455 
    456       assert "id" in Map.keys(object)
    457     end
    458 
    459     test "is valid for a valid object", %{valid_like: valid_like} do
    460       assert LikeValidator.cast_and_validate(valid_like).valid?
    461     end
    462 
    463     test "sets the 'to' field to the object actor if no recipients are given", %{
    464       valid_like: valid_like,
    465       user: user
    466     } do
    467       without_recipients =
    468         valid_like
    469         |> Map.delete("to")
    470 
    471       {:ok, object, _meta} = ObjectValidator.validate(without_recipients, [])
    472 
    473       assert object["to"] == [user.ap_id]
    474     end
    475 
    476     test "sets the context field to the context of the object if no context is given", %{
    477       valid_like: valid_like,
    478       post_activity: post_activity
    479     } do
    480       without_context =
    481         valid_like
    482         |> Map.delete("context")
    483 
    484       {:ok, object, _meta} = ObjectValidator.validate(without_context, [])
    485 
    486       assert object["context"] == post_activity.data["context"]
    487     end
    488 
    489     test "it errors when the actor is missing or not known", %{valid_like: valid_like} do
    490       without_actor = Map.delete(valid_like, "actor")
    491 
    492       refute LikeValidator.cast_and_validate(without_actor).valid?
    493 
    494       with_invalid_actor = Map.put(valid_like, "actor", "invalidactor")
    495 
    496       refute LikeValidator.cast_and_validate(with_invalid_actor).valid?
    497     end
    498 
    499     test "it errors when the object is missing or not known", %{valid_like: valid_like} do
    500       without_object = Map.delete(valid_like, "object")
    501 
    502       refute LikeValidator.cast_and_validate(without_object).valid?
    503 
    504       with_invalid_object = Map.put(valid_like, "object", "invalidobject")
    505 
    506       refute LikeValidator.cast_and_validate(with_invalid_object).valid?
    507     end
    508 
    509     test "it errors when the actor has already like the object", %{
    510       valid_like: valid_like,
    511       user: user,
    512       post_activity: post_activity
    513     } do
    514       _like = CommonAPI.favorite(user, post_activity.id)
    515 
    516       refute LikeValidator.cast_and_validate(valid_like).valid?
    517     end
    518 
    519     test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do
    520       wrapped_like =
    521         valid_like
    522         |> Map.put("actor", %{"id" => valid_like["actor"]})
    523         |> Map.put("object", %{"id" => valid_like["object"]})
    524 
    525       validated = LikeValidator.cast_and_validate(wrapped_like)
    526 
    527       assert validated.valid?
    528 
    529       assert {:actor, valid_like["actor"]} in validated.changes
    530       assert {:object, valid_like["object"]} in validated.changes
    531     end
    532   end
    533 
    534   describe "announces" do
    535     setup do
    536       user = insert(:user)
    537       announcer = insert(:user)
    538       {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
    539 
    540       object = Object.normalize(post_activity, false)
    541       {:ok, valid_announce, []} = Builder.announce(announcer, object)
    542 
    543       %{
    544         valid_announce: valid_announce,
    545         user: user,
    546         post_activity: post_activity,
    547         announcer: announcer
    548       }
    549     end
    550 
    551     test "returns ok for a valid announce", %{valid_announce: valid_announce} do
    552       assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, [])
    553     end
    554 
    555     test "returns an error if the object can't be found", %{valid_announce: valid_announce} do
    556       without_object =
    557         valid_announce
    558         |> Map.delete("object")
    559 
    560       {:error, cng} = ObjectValidator.validate(without_object, [])
    561 
    562       assert {:object, {"can't be blank", [validation: :required]}} in cng.errors
    563 
    564       nonexisting_object =
    565         valid_announce
    566         |> Map.put("object", "https://gensokyo.2hu/objects/99999999")
    567 
    568       {:error, cng} = ObjectValidator.validate(nonexisting_object, [])
    569 
    570       assert {:object, {"can't find object", []}} in cng.errors
    571     end
    572 
    573     test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do
    574       nonexisting_actor =
    575         valid_announce
    576         |> Map.put("actor", "https://gensokyo.2hu/users/raymoo")
    577 
    578       {:error, cng} = ObjectValidator.validate(nonexisting_actor, [])
    579 
    580       assert {:actor, {"can't find user", []}} in cng.errors
    581     end
    582 
    583     test "returns an error if the actor already announced the object", %{
    584       valid_announce: valid_announce,
    585       announcer: announcer,
    586       post_activity: post_activity
    587     } do
    588       _announce = CommonAPI.repeat(post_activity.id, announcer)
    589 
    590       {:error, cng} = ObjectValidator.validate(valid_announce, [])
    591 
    592       assert {:actor, {"already announced this object", []}} in cng.errors
    593       assert {:object, {"already announced by this actor", []}} in cng.errors
    594     end
    595 
    596     test "returns an error if the actor can't announce the object", %{
    597       announcer: announcer,
    598       user: user
    599     } do
    600       {:ok, post_activity} =
    601         CommonAPI.post(user, %{status: "a secret post", visibility: "private"})
    602 
    603       object = Object.normalize(post_activity, false)
    604 
    605       # Another user can't announce it
    606       {:ok, announce, []} = Builder.announce(announcer, object, public: false)
    607 
    608       {:error, cng} = ObjectValidator.validate(announce, [])
    609 
    610       assert {:actor, {"can not announce this object", []}} in cng.errors
    611 
    612       # The actor of the object can announce it
    613       {:ok, announce, []} = Builder.announce(user, object, public: false)
    614 
    615       assert {:ok, _, _} = ObjectValidator.validate(announce, [])
    616 
    617       # The actor of the object can not announce it publicly
    618       {:ok, announce, []} = Builder.announce(user, object, public: true)
    619 
    620       {:error, cng} = ObjectValidator.validate(announce, [])
    621 
    622       assert {:actor, {"can not announce this object publicly", []}} in cng.errors
    623     end
    624   end
    625 
    626   describe "updates" do
    627     setup do
    628       user = insert(:user)
    629 
    630       object = %{
    631         "id" => user.ap_id,
    632         "name" => "A new name",
    633         "summary" => "A new bio"
    634       }
    635 
    636       {:ok, valid_update, []} = Builder.update(user, object)
    637 
    638       %{user: user, valid_update: valid_update}
    639     end
    640 
    641     test "validates a basic object", %{valid_update: valid_update} do
    642       assert {:ok, _update, []} = ObjectValidator.validate(valid_update, [])
    643     end
    644 
    645     test "returns an error if the object can't be updated by the actor", %{
    646       valid_update: valid_update
    647     } do
    648       other_user = insert(:user)
    649 
    650       update =
    651         valid_update
    652         |> Map.put("actor", other_user.ap_id)
    653 
    654       assert {:error, _cng} = ObjectValidator.validate(update, [])
    655     end
    656   end
    657 
    658   describe "blocks" do
    659     setup do
    660       user = insert(:user, local: false)
    661       blocked = insert(:user)
    662 
    663       {:ok, valid_block, []} = Builder.block(user, blocked)
    664 
    665       %{user: user, valid_block: valid_block}
    666     end
    667 
    668     test "validates a basic object", %{
    669       valid_block: valid_block
    670     } do
    671       assert {:ok, _block, []} = ObjectValidator.validate(valid_block, [])
    672     end
    673 
    674     test "returns an error if we don't know the blocked user", %{
    675       valid_block: valid_block
    676     } do
    677       block =
    678         valid_block
    679         |> Map.put("object", "https://gensokyo.2hu/users/raymoo")
    680 
    681       assert {:error, _cng} = ObjectValidator.validate(block, [])
    682     end
    683   end
    684 end