diff --git a/lib/nulla/models/actor.ex b/lib/nulla/models/actor.ex index 8db516e..f1c58a1 100644 --- a/lib/nulla/models/actor.ex +++ b/lib/nulla/models/actor.ex @@ -25,12 +25,12 @@ defmodule Nulla.Models.Actor do field :indexable, :boolean, default: true field :published, :utc_datetime field :memorial, :boolean, default: false - field :publicKey, {:array, :map} - field :tag, {:array, :map} - field :attachment, {:array, :map} + field :publicKey, :map + field :tag, {:array, :map}, default: [] + field :attachment, {:array, :map}, default: [] field :endpoints, :map - field :icon, :map - field :image, :map + field :icon, :map, default: %{} + field :image, :map, default: %{} field :vcard_bday, :date field :vcard_Address, :string @@ -71,7 +71,6 @@ defmodule Nulla.Models.Actor do :vcard_Address ]) |> validate_required([ - :id, :domain, :ap_id, :type, @@ -82,8 +81,6 @@ defmodule Nulla.Models.Actor do :featured, :featuredTags, :preferredUsername, - :name, - :summary, :url, :manuallyApprovesFollowers, :discoverable, @@ -91,13 +88,7 @@ defmodule Nulla.Models.Actor do :published, :memorial, :publicKey, - :tag, - :attachment, - :endpoints, - :icon, - :image, - :vcard_bday, - :vcard_Address + :endpoints ]) end diff --git a/priv/repo/migrations/20250615130714_create_actors.exs b/priv/repo/migrations/20250615130714_create_actors.exs index d94ca47..da2ff37 100644 --- a/priv/repo/migrations/20250615130714_create_actors.exs +++ b/priv/repo/migrations/20250615130714_create_actors.exs @@ -23,11 +23,11 @@ defmodule Nulla.Repo.Migrations.CreateActors do add :published, :utc_datetime add :memorial, :boolean, default: false add :publicKey, :map - add :tag, {:array, :map} - add :attachment, {:array, :map} + add :tag, {:array, :map}, default: [] + add :attachment, {:array, :map}, default: [] add :endpoints, :map - add :icon, :map - add :image, :map + add :icon, :map, default: %{} + add :image, :map, default: %{} add :vcard_bday, :date add :vcard_Address, :string end diff --git a/test/nulla_web/controllers/actor_controller_test.exs b/test/nulla_web/controllers/actor_controller_test.exs new file mode 100644 index 0000000..01cc610 --- /dev/null +++ b/test/nulla_web/controllers/actor_controller_test.exs @@ -0,0 +1,88 @@ +defmodule NullaWeb.ActorControllerTest do + use NullaWeb.ConnCase + alias Nulla.Models.Actor + + setup do + Actor.create_actor(%{ + domain: "localhost", + ap_id: "http://localhost/users/test", + type: "Person", + following: "http://localhost/users/test/following", + followers: "http://localhost/users/test/followers", + inbox: "http://localhost/users/test/inbox", + outbox: "http://localhost/users/test/outbox", + featured: "http://localhost/users/test/collections/featured", + featuredTags: "http://localhost/users/test/collections/tags", + preferredUsername: "test", + name: "Test", + summary: "Test User", + url: "http://localhost/@test", + manuallyApprovesFollowers: false, + discoverable: true, + indexable: true, + published: DateTime.utc_now(), + memorial: false, + publicKey: + Jason.OrderedObject.new( + id: "http://localhost/users/test#main-key", + owner: "http://localhost/users/test", + publicKeyPem: "PUBLIC KEY" + ), + endpoints: Jason.OrderedObject.new(sharedInbox: "http://localhost/inbox") + }) + + :ok + end + + describe "GET /@username" do + test "renders ActivityPub JSON if Accept header is activity+json", %{conn: conn} do + conn = + conn + |> put_req_header("accept", "application/activity+json") + |> get(~p"/@test") + + assert response = json_response(conn, 200) + + assert is_list(response["@context"]) + assert is_binary(response["id"]) + assert is_binary(response["type"]) + assert is_binary(response["following"]) + assert is_binary(response["followers"]) + assert is_binary(response["inbox"]) + assert is_binary(response["outbox"]) + assert is_binary(response["featured"]) + assert is_binary(response["featuredTags"]) + assert is_binary(response["preferredUsername"]) + assert is_binary(response["name"]) or is_nil(response["name"]) + assert is_binary(response["summary"]) or is_nil(response["summary"]) + assert is_binary(response["url"]) + assert is_boolean(response["manuallyApprovesFollowers"]) + assert is_boolean(response["discoverable"]) + assert is_boolean(response["indexable"]) + assert {:ok, _dt, _offset} = DateTime.from_iso8601(response["published"]) + assert is_boolean(response["memorial"]) + assert is_map(response["publicKey"]) + assert is_list(response["tag"]) + assert is_list(response["attachment"]) + assert is_map(response["endpoints"]) + assert is_map(response["icon"]) + assert is_map(response["image"]) + assert is_binary(response["vcard:bday"]) or is_nil(response["vcard:bday"]) + assert is_binary(response["vcard:Address"]) or is_nil(response["vcard:Address"]) + end + + test "renders HTML if Accept header is regular", %{conn: conn} do + conn = get(conn, ~p"/@test") + + assert html_response(conn, 200) =~ "test" + assert html_response(conn, 200) =~ "Test" + assert html_response(conn, 200) =~ "test@localhost" + end + + test "returns 404 if actor not found", %{conn: conn} do + conn = get(conn, ~p"/@nonexistent") + + assert json_response(conn, 404)["error"] == "Not Found" + end + end +end