# Pleroma: A lightweight social networking server # Copyright © 2017-2022 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do use Pleroma.DataCase alias Pleroma.Object alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.CommonAPI import Mox import Pleroma.Factory describe "chat message create activities" do test "it is invalid if the object already exists" do user = insert(:user) recipient = insert(:user) {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey") object = Object.normalize(activity, fetch: false) {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id]) {:error, cng} = ObjectValidator.validate(create_data, []) assert {:object, {"The object to create already exists", []}} in cng.errors end test "it is invalid if the object data has a different `to` or `actor` field" do user = insert(:user) recipient = insert(:user) {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey") {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id]) {:error, cng} = ObjectValidator.validate(create_data, []) assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors end end describe "chat messages" do setup do clear_config([:instance, :remote_limit]) user = insert(:user) recipient = insert(:user, local: false) {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:") %{user: user, recipient: recipient, valid_chat_message: valid_chat_message} end test "let's through some basic html", %{user: user, recipient: recipient} do {:ok, valid_chat_message, _} = Builder.chat_message( user, recipient.ap_id, "hey example " ) assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert object["content"] == "hey example alert('uguu')" end test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert valid_chat_message == object assert match?(%{"firefox" => _}, object["emoji"]) end test "validates for a basic object with an attachment", %{ valid_chat_message: valid_chat_message, user: user } do file = %Plug.Upload{ content_type: "image/jpeg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg" } ConfigMock |> stub_with(Pleroma.Test.StaticConfig) {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) valid_chat_message = valid_chat_message |> Map.put("attachment", attachment.data) assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert object["attachment"] end test "validates for a basic object with an attachment in an array", %{ valid_chat_message: valid_chat_message, user: user } do file = %Plug.Upload{ content_type: "image/jpeg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg" } ConfigMock |> stub_with(Pleroma.Test.StaticConfig) {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) valid_chat_message = valid_chat_message |> Map.put("attachment", [attachment.data]) assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert object["attachment"] end test "validates for a basic object with an attachment but without content", %{ valid_chat_message: valid_chat_message, user: user } do file = %Plug.Upload{ content_type: "image/jpeg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg" } ConfigMock |> stub_with(Pleroma.Test.StaticConfig) {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id) valid_chat_message = valid_chat_message |> Map.put("attachment", attachment.data) |> Map.delete("content") assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert object["attachment"] end test "validates for a basic object with content but attachment set to empty array", %{ user: user, recipient: recipient } do {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "Hello!") valid_chat_message = valid_chat_message |> Map.put("attachment", []) assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) assert object == Map.drop(valid_chat_message, ["attachment"]) end test "does not validate if the message has no content", %{ valid_chat_message: valid_chat_message } do contentless = valid_chat_message |> Map.delete("content") refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, [])) end test "does not validate if the message is longer than the remote_limit", %{ valid_chat_message: valid_chat_message } do clear_config([:instance, :remote_limit], 2) refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) end test "does not validate if the recipient is blocking the actor", %{ valid_chat_message: valid_chat_message, user: user, recipient: recipient } do Pleroma.User.block(recipient, user) refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) end test "does not validate if the recipient is not accepting chat messages", %{ valid_chat_message: valid_chat_message, recipient: recipient } do recipient |> Ecto.Changeset.change(%{accepts_chat_messages: false}) |> Pleroma.Repo.update!() refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, [])) end test "does not validate if the actor or the recipient is not in our system", %{ valid_chat_message: valid_chat_message } do chat_message = valid_chat_message |> Map.put("actor", "https://raymoo.com/raymoo") {:error, _} = ObjectValidator.validate(chat_message, []) chat_message = valid_chat_message |> Map.put("to", ["https://raymoo.com/raymoo"]) {:error, _} = ObjectValidator.validate(chat_message, []) end test "does not validate for a message with multiple recipients", %{ valid_chat_message: valid_chat_message, user: user, recipient: recipient } do chat_message = valid_chat_message |> Map.put("to", [user.ap_id, recipient.ap_id]) assert {:error, _} = ObjectValidator.validate(chat_message, []) end test "does not validate if it doesn't concern local users" do user = insert(:user, local: false) recipient = insert(:user, local: false) {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey") assert {:error, _} = ObjectValidator.validate(valid_chat_message, []) end end end