From 4e9bd7334a40e53d19e5ad8ff6cd45b98d291805 Mon Sep 17 00:00:00 2001 From: Brian Manifold Date: Tue, 13 Aug 2024 15:07:00 -0700 Subject: [PATCH] fix(portal): Fix Resource show error on API created Resource (#6284) Viewing a Resource created by an API client was crashing the view due to the function creating the link to the actor not accounting for the API client case. Closes #6267 --- .../domain/test/support/fixtures/tokens.ex | 17 ++++--- .../web/lib/web/components/core_components.ex | 26 ++++++++++ .../apps/web/lib/web/live/resources/show.ex | 2 +- .../web/test/web/live/resources/show_test.exs | 48 +++++++++++++++++++ 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/elixir/apps/domain/test/support/fixtures/tokens.ex b/elixir/apps/domain/test/support/fixtures/tokens.ex index 11e02872e..94321ad02 100644 --- a/elixir/apps/domain/test/support/fixtures/tokens.ex +++ b/elixir/apps/domain/test/support/fixtures/tokens.ex @@ -92,12 +92,17 @@ defmodule Domain.Fixtures.Tokens do {identity, attrs} = pop_assoc_fixture(attrs, :identity, fn assoc_attrs -> - if actor.type == :service_account do - %{id: nil} - else - assoc_attrs - |> Enum.into(%{account: account, actor: actor}) - |> Fixtures.Auth.create_identity() + case actor.type do + :service_account -> + %{id: nil} + + :api_client -> + %{id: nil} + + _ -> + assoc_attrs + |> Enum.into(%{account: account, actor: actor}) + |> Fixtures.Auth.create_identity() end end) diff --git a/elixir/apps/web/lib/web/components/core_components.ex b/elixir/apps/web/lib/web/components/core_components.ex index ba24e49fc..27691044e 100644 --- a/elixir/apps/web/lib/web/components/core_components.ex +++ b/elixir/apps/web/lib/web/components/core_components.ex @@ -904,6 +904,13 @@ defmodule Web.CoreComponents do """ end + def created_by(%{schema: %{created_by: :actor}} = assigns) do + ~H""" + <.relative_datetime datetime={@schema.inserted_at} /> by + <.actor_link account={@account} actor={@schema.created_by_actor} /> + """ + end + def created_by(%{schema: %{created_by: :identity}} = assigns) do ~H""" <.relative_datetime datetime={@schema.inserted_at} /> by @@ -928,6 +935,25 @@ defmodule Web.CoreComponents do """ end + attr :account, :any, required: true + attr :actor, :any, required: true + + def actor_link(%{actor: %Domain.Actors.Actor{type: :api_client}} = assigns) do + ~H""" + <.link class={link_style()} navigate={~p"/#{@account}/settings/api_clients/#{@actor}"}> + <%= assigns.actor.name %> + + """ + end + + def actor_link(assigns) do + ~H""" + <.link class={link_style()} navigate={~p"/#{@account}/actors/#{@actor}"}> + <%= assigns.actor.name %> + + """ + end + attr :account, :any, required: true attr :identity, :any, required: true diff --git a/elixir/apps/web/lib/web/live/resources/show.ex b/elixir/apps/web/lib/web/live/resources/show.ex index c676b96b9..505dced31 100644 --- a/elixir/apps/web/lib/web/live/resources/show.ex +++ b/elixir/apps/web/lib/web/live/resources/show.ex @@ -7,7 +7,7 @@ defmodule Web.Resources.Show do def mount(%{"id" => id} = params, _session, socket) do with {:ok, resource} <- Resources.fetch_resource_by_id(id, socket.assigns.subject, - preload: [:gateway_groups, created_by_identity: [:actor]] + preload: [:gateway_groups, :created_by_actor, created_by_identity: [:actor]] ), {:ok, actor_groups_peek} <- Resources.peek_resource_actor_groups([resource], 3, socket.assigns.subject) do diff --git a/elixir/apps/web/test/web/live/resources/show_test.exs b/elixir/apps/web/test/web/live/resources/show_test.exs index 6bb402fff..87e2a5102 100644 --- a/elixir/apps/web/test/web/live/resources/show_test.exs +++ b/elixir/apps/web/test/web/live/resources/show_test.exs @@ -324,4 +324,52 @@ defmodule Web.Live.Resources.ShowTest do assert Repo.get(Domain.Resources.Resource, resource.id).deleted_at end + + test "renders created_by link when created by Identity", %{ + account: account, + identity: identity, + conn: conn + } do + resource = + Fixtures.Resources.create_resource( + account: account, + address_description: "http://example.com" + ) + + {:ok, _lv, html} = + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/resources/#{resource}") + + assert Floki.find( + html, + "a[href='#{~p"/#{account}/actors/#{resource.created_by_actor_id}"}']" + ) + end + + test "renders created_by link when created by API client", %{ + account: account, + identity: identity, + conn: conn + } do + actor = Fixtures.Actors.create_actor(type: :api_client, account: account) + subject = Fixtures.Auth.create_subject(account: account, actor: actor) + + resource = + Fixtures.Resources.create_resource( + account: account, + subject: subject, + address_description: "http://example.com" + ) + + {:ok, _lv, html} = + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/resources/#{resource}") + + assert Floki.find( + html, + "a[href='#{~p"/#{account}/settings/api_clients/#{resource.created_by_actor_id}"}']" + ) + end end