fix(ux): Redirect to policies/new after creating Resource (#5938)

Fixes a UX issue somewhat introduced by
https://github.com/firezone/firezone/pull/5870 where we changed behavior
to make the redirect consistent with other CRUD operations.

The behavior we had prior to
https://github.com/firezone/firezone/pull/5870 was to redirect to
Resource show, but feedback from customer (which makes sense) is that
you almost _always_ create a Policy after creating a Resource, so this
PR streamlines the hot path flow there.

This has occurred to a couple users in Discord as well, so by taking
them directly to policies/new it hopefully make clear the user needs to
create a Policy after creating a Resource.

This papercut occurred while customer was demo'ing Firezone to another
potential customer.

Fixes #5929 

cc @jameswinegar
This commit is contained in:
Jamil
2024-07-24 15:43:31 -07:00
committed by GitHub
parent 40748306ca
commit 881377cbe2
25 changed files with 235 additions and 149 deletions

View File

@@ -43,7 +43,7 @@ defmodule Domain.Policies.Policy.Changeset do
|> unique_constraint(
:base,
name: :policies_account_id_resource_id_actor_group_id_index,
message: "Policy with Group and Resource already exists"
message: "Policy for the selected Group and Resource already exists"
)
|> assoc_constraint(:resource)
|> assoc_constraint(:actor_group)

View File

@@ -74,6 +74,11 @@ defmodule Web.Actors.Components do
placeholder="Role"
required
/>
<p class="mt-2 text-xs text-gray-500">
Select <strong>Admin</strong>
to grant this user access to the admin portal. Otherwise, select <strong>User</strong>
to limit access to the Client apps only.
</p>
</div>
"""
end
@@ -160,29 +165,6 @@ defmodule Web.Actors.Components do
"""
end
def option(assigns) do
~H"""
<div>
<div class="flex items-center mb-4">
<input
id={"idp-option-#{@type}"}
type="radio"
name="next"
value={next_step_path(@type, @account)}
class={~w[w-4 h-4 border-neutral-300]}
required
/>
<label for={"idp-option-#{@type}"} class="block ml-2 text-lg text-neutral-900">
<%= @name %>
</label>
</div>
<p class="ml-6 mb-6 text-sm text-neutral-500">
<%= @description %>
</p>
</div>
"""
end
def next_step_path(:service_account, account) do
~p"/#{account}/actors/service_accounts/new"
end

View File

@@ -18,9 +18,7 @@ defmodule Web.Actors.New do
<.breadcrumb path={~p"/#{@account}/actors/new"}>Add</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add Actor
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">Choose type</h2>
@@ -29,22 +27,65 @@ defmodule Web.Actors.New do
<fieldset>
<legend class="sr-only">Choose Actor Type</legend>
<.option
account={@account}
type={:user}
name="User"
description="Admin or regular user accounts can be used to sign in to Firezone and access private resources."
/>
<.option
account={@account}
type={:service_account}
name="Service Account"
description="Service accounts can be used for headless clients or to access Firezone APIs."
/>
<ul class="grid w-full gap-6 md:grid-cols-2">
<li>
<.input
id="idp-option-user"
type="radio_button_group"
name="next"
value={next_step_path(:user, @account)}
checked={false}
required
/>
<label for="idp-option-user" class={~w[
inline-flex items-center justify-between w-full
p-5 text-gray-500 bg-white border border-gray-200
rounded cursor-pointer peer-checked:border-accent-500
peer-checked:text-accent-500 hover:text-gray-600 hover:bg-gray-100
]}>
<div class="block">
<div class="w-full font-semibold mb-3">
<.icon name="hero-user" class="w-5 h-5 mr-1" /> User
</div>
<div class="w-full text-sm">
User accounts can sign in to the Firezone Client apps or to
the admin portal depending on their role.
</div>
</div>
</label>
</li>
<li>
<.input
id="idp-option-service_account"
type="radio_button_group"
name="next"
value={next_step_path(:service_account, @account)}
checked={false}
required
/>
<label for="idp-option-service_account" class={~w[
inline-flex items-center justify-between w-full
p-5 text-gray-500 bg-white border border-gray-200
rounded cursor-pointer peer-checked:border-accent-500
peer-checked:text-accent-500 hover:text-gray-600 hover:bg-gray-100
]}>
<div class="block">
<div class="w-full font-semibold mb-3">
<.icon name="hero-server" class="w-5 h-5 mr-1" /> Service Account
</div>
<div class="w-full text-sm">
Service accounts are used to authenticate headless Clients on
machines where a user isn't physically present.
</div>
</div>
</label>
</li>
</ul>
</fieldset>
</div>
<.submit_button>
Next: Create Actor
Next: Actor Details
</.submit_button>
</.form>
</div>

View File

@@ -24,13 +24,11 @@ defmodule Web.Actors.ServiceAccounts.New do
</.breadcrumbs>
<.section>
<:title>
Create Actor
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">
Create a Service Account
Service Account details
</h2>
<.flash kind={:error} flash={@flash} />
<.form for={@form} phx-change={:change} phx-submit={:submit}>
@@ -38,7 +36,7 @@ defmodule Web.Actors.ServiceAccounts.New do
<.actor_form form={@form} type={:service_account} subject={@subject} />
</div>
<.submit_button>
Create
Next: Create Token
</.submit_button>
</.form>
</div>

View File

@@ -1,6 +1,5 @@
defmodule Web.Actors.ServiceAccounts.NewIdentity do
use Web, :live_view
import Web.Actors.Components
alias Domain.{Auth, Actors, Tokens}
def mount(%{"id" => id}, _session, socket) do
@@ -41,12 +40,10 @@ defmodule Web.Actors.ServiceAccounts.NewIdentity do
</.breadcrumbs>
<.section>
<:title>
Create <%= actor_type(@actor.type) %> Token
</:title>
<:title><%= @page_title %></:title>
<:content>
<div :if={is_nil(@encoded_token)} class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">Create a Token</h2>
<h2 class="mb-4 text-xl text-neutral-900">Token details</h2>
<.flash kind={:error} flash={@flash} />
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
@@ -75,14 +72,20 @@ defmodule Web.Actors.ServiceAccounts.NewIdentity do
<div :if={not is_nil(@encoded_token)} class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div class="text-xl mb-2">
Your API token (will be shown only once):
Your Service Account token
</div>
<div>
<.code_block id="code-sample-docker" class="w-full mw-1/2 rounded" phx-no-format><%= @encoded_token %></.code_block>
<p class="mt-2 text-xs text-gray-500">
Store this in a safe place. <strong>It won't be shown again.</strong>
</p>
</div>
<.code_block id="code-sample-docker" class="w-full mw-1/2 rounded" phx-no-format><%= @encoded_token %></.code_block>
<.button icon="hero-arrow-uturn-left" navigate={~p"/#{@account}/actors/#{@actor}"}>
Back to Actor
</.button>
<div class="flex justify-start">
<.button icon="hero-arrow-uturn-left" navigate={~p"/#{@account}/actors/#{@actor}"}>
Back to Service Account
</.button>
</div>
</div>
</div>
</:content>

View File

@@ -24,19 +24,17 @@ defmodule Web.Actors.Users.New do
</.breadcrumbs>
<.section>
<:title>
Create Actor
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">Create a User</h2>
<h2 class="mb-4 text-xl text-neutral-900">User details</h2>
<.flash kind={:error} flash={@flash} />
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<.actor_form form={@form} type={:user} subject={@subject} />
</div>
<.submit_button>
Create
Next: Add an Identity
</.submit_button>
</.form>
</div>

View File

@@ -51,12 +51,10 @@ defmodule Web.Actors.Users.NewIdentity do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Create <%= actor_type(@actor.type) %> Identity
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">Create an Identity</h2>
<h2 class="mb-4 text-xl text-neutral-900">Identity details</h2>
<.flash kind={:error} flash={@flash} />
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
@@ -74,11 +72,18 @@ defmodule Web.Actors.Users.NewIdentity do
placeholder="Provider"
required
/>
<p class="mt-2 text-xs text-gray-500">
Select the provider to use for signing in.
</p>
</div>
<.provider_form :if={@provider} form={@form} provider={@provider} />
</div>
<.submit_button>
Save
<%= if @next_step == "edit_groups" do %>
Next: Select Group Memberships
<% else %>
Create Identity
<% end %>
</.submit_button>
</.form>
</div>

View File

@@ -21,25 +21,24 @@ defmodule Web.Groups.New do
<.breadcrumb path={~p"/#{@account}/groups/new"}>Add</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Create Group
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="py-8 px-4 mx-auto max-w-2xl lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">
Group details
</h2>
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<.input type="hidden" field={@form[:type]} value="static" />
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div>
<.input
label="Group name"
field={@form[:name]}
placeholder="Enter a name for this Group, e.g. Engineering"
required
/>
<.input label="Name" field={@form[:name]} placeholder="E.g. Engineering" required />
<p class="text-sm mt-2 text-neutral-600">
Enter a name for this Group.
</p>
</div>
</div>
<.submit_button>
Save
Next: Select Members
</.submit_button>
</.form>
</div>

View File

@@ -34,12 +34,10 @@ defmodule Web.Policies.New do
<.breadcrumb path={~p"/#{@account}/policies/new"}>Add Policy</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add Policy
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">Details</h2>
<h2 class="mb-4 text-xl text-neutral-900">Policy details</h2>
<div
:if={@actor_groups == []}
class={[
@@ -107,9 +105,11 @@ defmodule Web.Policies.New do
/>
</div>
<.submit_button phx-disable-with="Creating Policy..." class="w-full">
Create Policy
</.submit_button>
<div class="flex justify-end">
<.submit_button phx-disable-with="Creating Policy..." class="w-full">
Create Policy
</.submit_button>
</div>
</.form>
</div>
</:content>
@@ -141,12 +141,29 @@ defmodule Web.Policies.New do
Map.delete(params, "conditions")
end
with {:ok, policy} <- Policies.create_policy(params, socket.assigns.subject) do
if site_id = socket.assigns.params["site_id"] do
{:noreply,
push_navigate(socket, to: ~p"/#{socket.assigns.account}/sites/#{site_id}?#resources")}
else
{:noreply, push_navigate(socket, to: ~p"/#{socket.assigns.account}/policies/#{policy}")}
with {:ok, _policy} <- Policies.create_policy(params, socket.assigns.subject) do
cond do
site_id = socket.assigns.params["site_id"] ->
# Created from Add Resource from Site
{:noreply,
push_navigate(socket, to: ~p"/#{socket.assigns.account}/sites/#{site_id}?#resources")}
resource_id = socket.assigns.resource_id ->
# Created from Add Resource from Resources
{:noreply,
push_navigate(socket, to: ~p"/#{socket.assigns.account}/resources/#{resource_id}")}
actor_group_id = socket.assigns.actor_group_id ->
# Created from Add Policy from Actor Group
{:noreply,
push_navigate(socket, to: ~p"/#{socket.assigns.account}/groups/#{actor_group_id}")}
true ->
# Created from Add Policy from Policies
{:noreply,
socket
|> put_flash(:info, "Policy created successfully.")
|> push_navigate(to: ~p"/#{socket.assigns.account}/policies")}
end
else
{:error, %Ecto.Changeset{} = changeset} ->

View File

@@ -26,9 +26,7 @@ defmodule Web.RelayGroups.New do
<.breadcrumb path={~p"/#{@account}/relay_groups/new"}>Add</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add Relay Instance Group
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="py-8 px-4 mx-auto max-w-2xl lg:py-16">
<.form for={@form} phx-change={:change} phx-submit={:submit}>

View File

@@ -28,9 +28,7 @@ defmodule Web.Resources.New do
<.breadcrumb path={~p"/#{@account}/resources/new"}>Add Resource</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add Resource
</:title>
<:title><%= @page_title %></:title>
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
@@ -236,11 +234,16 @@ defmodule Web.Resources.New do
if site_id = socket.assigns.params["site_id"] do
{:noreply,
socket
|> push_navigate(to: ~p"/#{socket.assigns.account}/sites/#{site_id}")}
|> push_navigate(
to:
~p"/#{socket.assigns.account}/policies/new?resource_id=#{resource}&site_id=#{site_id}"
)}
else
{:noreply,
socket
|> push_navigate(to: ~p"/#{socket.assigns.account}/resources")}
|> push_navigate(
to: ~p"/#{socket.assigns.account}/policies/new?resource_id=#{resource}"
)}
end
{:error, changeset} ->

View File

@@ -50,14 +50,24 @@ defmodule Web.Settings.ApiClients.Components do
~H"""
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div class="text-xl mb-2">
Your API token (will be shown only once):
Your API Token:
</div>
<.code_block id="code-api-token" class="w-full mw-1/2 rounded" phx-no-format><%= @encoded_token %></.code_block>
<div>
<.code_block id="code-api-token" class="w-full mw-1/2 rounded" phx-no-format><%= @encoded_token %></.code_block>
<p class="mt-2 text-xs text-gray-500">
Store this in a safe place. <strong>It won't be shown again.</strong>
</p>
</div>
<.button icon="hero-arrow-uturn-left" navigate={~p"/#{@account}/settings/api_clients/#{@actor}"}>
Back to API Client
</.button>
<div class="flex justify-start">
<.button
icon="hero-arrow-uturn-left"
navigate={~p"/#{@account}/settings/api_clients/#{@actor}"}
>
Back to API Client
</.button>
</div>
</div>
"""
end

View File

@@ -54,9 +54,11 @@ defmodule Web.Settings.ApiClients.Index do
<.section>
<:title><%= @page_title %></:title>
<:help>
API Clients are used to manage Firezone configuration through a REST API. See the
<a class={link_style()} href="https://firezone.dev/kb/reference/rest-api">REST API docs</a>
for more info.
API Clients are used to manage Firezone configuration through a REST API. See our
<.link navigate="https://api.firezone.dev/swaggerui" class={link_style()}>
OpenAPI-powered docs
</.link>
for more information.
</:help>
<:action>

View File

@@ -12,7 +12,7 @@ defmodule Web.Settings.ApiClients.New do
socket =
assign(socket,
form: to_form(changeset),
page_title: "New API Client"
page_title: "Add an API Client"
)
{:ok, socket, temporary_assigns: [form: %Phoenix.HTML.Form{}]}
@@ -30,7 +30,7 @@ defmodule Web.Settings.ApiClients.New do
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<h2 class="mb-4 text-xl text-neutral-900">
Create API Client
API Client details
</h2>
<.flash kind={:error} flash={@flash} />
<.form for={@form} phx-change={:change} phx-submit={:submit}>
@@ -38,7 +38,7 @@ defmodule Web.Settings.ApiClients.New do
<.api_client_form form={@form} type={:api_client} subject={@subject} />
</div>
<.submit_button>
Create
Next: Add a token
</.submit_button>
</.form>
</div>

View File

@@ -16,7 +16,7 @@ defmodule Web.Settings.ApiClients.NewToken do
actor: actor,
encoded_token: nil,
form: to_form(changeset),
page_title: "Create API Token"
page_title: "Add an API Token"
)
{:ok, socket, temporary_assigns: [form: %Phoenix.HTML.Form{}]}
@@ -42,14 +42,14 @@ defmodule Web.Settings.ApiClients.NewToken do
<:content>
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<div :if={is_nil(@encoded_token)}>
<h2 class="mb-4 text-xl text-neutral-900">Create Token</h2>
<h2 class="mb-4 text-xl text-neutral-900">API Token details</h2>
<.flash kind={:error} flash={@flash} />
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<.api_token_form form={@form} />
</div>
<.submit_button>
Create
Create API Token
</.submit_button>
</.form>
</div>

View File

@@ -17,7 +17,7 @@ defmodule Web.Settings.IdentityProviders.GoogleWorkspace.New do
assign(socket,
id: id,
form: to_form(changeset),
page_title: "New Identity Provider"
page_title: "New Identity Provider: Google Workspace"
)
{:ok, socket, temporary_assigns: [form: %Phoenix.HTML.Form{}]}
@@ -37,9 +37,7 @@ defmodule Web.Settings.IdentityProviders.GoogleWorkspace.New do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add a new Google Workspace Identity Provider
</:title>
<:title><%= @page_title %></:title>
<:help>
For a more detailed guide on setting up Firezone with Google Workspace, please <.link
href="https://www.firezone.dev/kb/authenticate/google"

View File

@@ -17,7 +17,7 @@ defmodule Web.Settings.IdentityProviders.JumpCloud.New do
assign(socket,
id: id,
form: to_form(changeset),
page_title: "New Identity Provider"
page_title: "New Identity Provider: JumpCloud"
)
{:ok, socket, temporary_assigns: [form: %Phoenix.HTML.Form{}]}
@@ -37,9 +37,7 @@ defmodule Web.Settings.IdentityProviders.JumpCloud.New do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add a new JumpCloud Identity Provider
</:title>
<:title><%= @page_title %></:title>
<:help>
For a more detailed guide on setting up Firezone with JumpCloud, please <.link
href="https://www.firezone.dev/kb/authenticate/jumpcloud"

View File

@@ -17,7 +17,7 @@ defmodule Web.Settings.IdentityProviders.MicrosoftEntra.New do
assign(socket,
id: id,
form: to_form(changeset),
page_title: "New Identity Provider"
page_title: "New Identity Provider: Microsoft Entra"
)
{:ok, socket, temporary_assigns: [form: %Phoenix.HTML.Form{}]}
@@ -37,9 +37,7 @@ defmodule Web.Settings.IdentityProviders.MicrosoftEntra.New do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add a new Microsoft Entra ID Identity Provider
</:title>
<:title><%= @page_title %></:title>
<:help>
For a more detailed guide on setting up Firezone with Microsoft Entra ID, please <.link
href="https://www.firezone.dev/kb/authenticate/entra"

View File

@@ -33,9 +33,7 @@ defmodule Web.Settings.IdentityProviders.New do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add a new Identity Provider
</:title>
<:title><%= @page_title %></:title>
<:help>
Set up SSO authentication using your own identity provider. Directory sync
also available for certain providers. <br /> Learn more about

View File

@@ -17,7 +17,7 @@ defmodule Web.Settings.IdentityProviders.Okta.New do
assign(socket,
id: id,
form: to_form(changeset),
page_title: "New Identity Provider"
page_title: "New Identity Provider: Okta"
)
{:ok, socket, temporary_assigns: [form: %Phoenix.HTML.Form{}]}
@@ -37,9 +37,7 @@ defmodule Web.Settings.IdentityProviders.Okta.New do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add a new Okta Identity Provider
</:title>
<:title><%= @page_title %></:title>
<:help>
For a more detailed guide on setting up Firezone with Okta, please <.link
href="https://www.firezone.dev/kb/authenticate/okta"

View File

@@ -17,7 +17,7 @@ defmodule Web.Settings.IdentityProviders.OpenIDConnect.New do
assign(socket,
id: id,
form: to_form(changeset),
page_title: "New Identity Provider",
page_title: "New Identity Provider: OpenID Connect",
provider: params["provider"]
)
@@ -38,9 +38,7 @@ defmodule Web.Settings.IdentityProviders.OpenIDConnect.New do
</.breadcrumb>
</.breadcrumbs>
<.section>
<:title>
Add a new OpenID Connect Identity Provider
</:title>
<:title><%= @page_title %></:title>
<:content>
<.provider_form account={@account} id={@id} form={@form} show_sync_msg={!!@provider} />
</:content>

View File

@@ -16,15 +16,21 @@ defmodule Web.Sites.New do
</.breadcrumbs>
<.section>
<:title>
Add a new Site
</:title>
<:title><%= @page_title %></:title>
<:content>
<.flash kind={:error} flash={@flash} />
<div class="py-8 px-4 mx-auto max-w-2xl lg:py-16">
<h2 class="mb-6 text-xl text-neutral-900">
Site details
</h2>
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<.input label="Name" field={@form[:name]} placeholder="Name of this Site" required />
<div>
<.input label="Name" field={@form[:name]} placeholder="Name of this Site" required />
<p class="mt-2 text-xs text-neutral-500">
Enter a name for this Site.
</p>
</div>
</div>
<.submit_button>
Create

View File

@@ -210,11 +210,11 @@ defmodule Web.Live.Policies.NewTest do
|> form("form", policy: attrs)
|> render_submit()
|> form_validation_errors() == %{
"policy[base]" => ["Policy with Group and Resource already exists"]
"policy[base]" => ["Policy for the selected Group and Resource already exists"]
}
end
test "creates a new policy on valid attrs and redirects to policy page", %{
test "creates a new policy on valid attrs and redirects to policies page", %{
account: account,
identity: identity,
conn: conn
@@ -236,9 +236,10 @@ defmodule Web.Live.Policies.NewTest do
|> form("form", policy: attrs)
|> render_submit()
assert policy = Repo.get_by(Domain.Policies.Policy, attrs)
assert Repo.get_by(Domain.Policies.Policy, attrs)
assert assert_redirect(lv, ~p"/#{account}/policies/#{policy}")
flash = assert_redirect(lv, ~p"/#{account}/policies")
assert flash["info"] == "Policy created successfully."
end
test "creates a new policy with conditions", %{
@@ -301,7 +302,7 @@ defmodule Web.Live.Policies.NewTest do
}
]
assert assert_redirect(lv, ~p"/#{account}/policies/#{policy}")
assert assert_redirect(lv, ~p"/#{account}/resources/#{resource}")
end
test "creates a new policy on valid attrs and pre-set resource_id", %{
@@ -327,7 +328,7 @@ defmodule Web.Live.Policies.NewTest do
policy = Repo.get_by(Domain.Policies.Policy, attrs)
assert policy.resource_id == resource.id
assert assert_redirect(lv, ~p"/#{account}/policies/#{policy}")
assert assert_redirect(lv, ~p"/#{account}/resources/#{resource}")
end
test "removes conditions in the backend when policy_conditions is false", %{
@@ -368,7 +369,35 @@ defmodule Web.Live.Policies.NewTest do
assert policy.resource_id == resource.id
assert policy.conditions == []
assert assert_redirect(lv, ~p"/#{account}/policies/#{policy}")
assert_redirect(lv, ~p"/#{account}/resources/#{resource}")
end
test "redirects back to actor group when a new policy is created with pre-set actor_group_id",
%{
account: account,
identity: identity,
conn: conn
} do
group = Fixtures.Actors.create_group(account: account)
resource = Fixtures.Resources.create_resource(account: account)
Fixtures.Gateways.create_group(account: account)
attrs = %{actor_group_id: group.id}
{:ok, lv, _html} =
conn
|> authorize_conn(identity)
|> live(~p"/#{account}/policies/new?actor_group_id=#{group}")
assert lv
|> form("form", policy: attrs)
|> render_submit()
policy = Repo.get_by(Domain.Policies.Policy, attrs)
assert policy.resource_id == resource.id
assert assert_redirect(lv, ~p"/#{account}/groups/#{group}")
end
test "redirects back to site when a new policy is created with pre-set site_id", %{

View File

@@ -407,7 +407,7 @@ defmodule Web.Live.Resources.NewTest do
resource = Repo.get_by(Domain.Resources.Resource, %{name: attrs.name, address: attrs.address})
flash = assert_redirect(lv, ~p"/#{account}/resources")
flash = assert_redirect(lv, ~p"/#{account}/policies/new?resource_id=#{resource}")
assert flash["info"] == "Resource #{resource.name} created successfully."
end
@@ -449,7 +449,9 @@ defmodule Web.Live.Resources.NewTest do
resource = Repo.get_by(Domain.Resources.Resource, %{name: attrs.name, address: attrs.address})
flash = assert_redirect(lv, ~p"/#{account}/sites/#{group}")
flash =
assert_redirect(lv, ~p"/#{account}/policies/new?resource_id=#{resource}&site_id=#{group}")
assert flash["info"] == "Resource #{resource.name} created successfully."
end
@@ -516,7 +518,10 @@ defmodule Web.Live.Resources.NewTest do
assert %{connections: [connection]} = Repo.preload(resource, :connections)
assert connection.gateway_group_id == group.id
assert assert_redirect(lv, ~p"/#{account}/sites/#{group}")
assert assert_redirect(
lv,
~p"/#{account}/policies/new?resource_id=#{resource}&site_id=#{group}"
)
end
test "prevents saving resource if traffic filters set when traffic filters disabled", %{

View File

@@ -137,7 +137,9 @@ defmodule Web.Live.Settings.ApiClient.NewTokenTest do
|> form("form", token: attrs)
|> render_submit()
assert html =~ "Your API token (will be shown only once)"
assert html =~ "Your API Token"
assert html =~ "Store this in a safe place."
assert html =~ "It won&#39;t be shown again."
assert Floki.find(html, "code")
|> element_to_text()