diff --git a/elixir/README.md b/elixir/README.md
index 7f8ffc2dc..49655cd2d 100644
--- a/elixir/README.md
+++ b/elixir/README.md
@@ -65,7 +65,7 @@ Now you can verify that it's working by connecting to a websocket:
# Note: The token value below is an example. The token value you will need is generated and printed out when seeding the database, as described earlier in the document.
❯ export GATEWAY_TOKEN_FROM_SEEDS="SFMyNTY.g2gDaAJtAAAAJDNjZWYwNTY2LWFkZmQtNDhmZS1hMGYxLTU4MDY3OTYwOGY2Zm0AAABAamp0enhSRkpQWkdCYy1vQ1o5RHkyRndqd2FIWE1BVWRwenVScjJzUnJvcHg3NS16bmhfeHBfNWJUNU9uby1yYm4GAJXr4emIAWIAAVGA.jz0s-NohxgdAXeRMjIQ9kLBOyd7CmKXWi2FHY-Op8GM"
-❯ websocat --header="User-Agent: iOS/12.7 (iPhone) connlib/0.7.412" "ws://127.0.0.1:13000/gateway/websocket?token=${GATEWAY_TOKEN_FROM_SEEDS}&external_id=thisisrandomandpersistent&name_suffix=kkX1&public_key=kceI60D6PrwOIiGoVz6hD7VYCgD1H57IVQlPJTTieUE="
+❯ websocat --header="User-Agent: iOS/12.7 (iPhone) connlib/0.7.412" "ws://127.0.0.1:13000/gateway/websocket?token=${GATEWAY_TOKEN_FROM_SEEDS}&external_id=thisisrandomandpersistent&name=kkX1&public_key=kceI60D6PrwOIiGoVz6hD7VYCgD1H57IVQlPJTTieUE="
# After this you need to join the `gateway` topic.
# For details on this structure see https://hexdocs.pm/phoenix/Phoenix.Socket.Message.html
@@ -107,10 +107,10 @@ Now you can verify that it's working by connecting to a websocket:
# Panel will only accept token if it's coming with this User-Agent header and from IP 172.28.0.1
❯ export CLIENT_USER_AGENT="iOS/12.5 (iPhone) connlib/0.7.412"
-❯ websocat --header="User-Agent: ${CLIENT_USER_AGENT}" "ws://127.0.0.1:8081/client/websocket?token=${CLIENT_TOKEN_FROM_SEEDS}&external_id=thisisrandomandpersistent&name_suffix=kkX1&public_key=kceI60D6PrwOIiGoVz6hD7VYCgD1H57IVQlPJTTieUE="
+❯ websocat --header="User-Agent: ${CLIENT_USER_AGENT}" "ws://127.0.0.1:8081/client/websocket?token=${CLIENT_TOKEN_FROM_SEEDS}&external_id=thisisrandomandpersistent&name=kkX1&public_key=kceI60D6PrwOIiGoVz6hD7VYCgD1H57IVQlPJTTieUE="
# Here is what you will see in docker logs firezone-api-1
-# firezone-api-1 | {"domain":["elixir"],"erl_level":"info","logging.googleapis.com/sourceLocation":{"file":"lib/phoenix/logger.ex","line":306,"function":"Elixir.Phoenix.Logger.phoenix_socket_connected/4"},"message":"CONNECTED TO API.Client.Socket in 83ms\n Transport: :websocket\n Serializer: Phoenix.Socket.V1.JSONSerializer\n Parameters: %{\"external_id\" => \"thisisrandomandpersistent\", \"name_suffix\" => \"kkX1\", \"public_key\" => \"[FILTERED]\", \"token\" => \"[FILTERED]\"}","severity":"INFO","time":"2023-06-23T21:01:49.566Z"}
+# firezone-api-1 | {"domain":["elixir"],"erl_level":"info","logging.googleapis.com/sourceLocation":{"file":"lib/phoenix/logger.ex","line":306,"function":"Elixir.Phoenix.Logger.phoenix_socket_connected/4"},"message":"CONNECTED TO API.Client.Socket in 83ms\n Transport: :websocket\n Serializer: Phoenix.Socket.V1.JSONSerializer\n Parameters: %{\"external_id\" => \"thisisrandomandpersistent\", \"name\" => \"kkX1\", \"public_key\" => \"[FILTERED]\", \"token\" => \"[FILTERED]\"}","severity":"INFO","time":"2023-06-23T21:01:49.566Z"}
# After this you need to join the `client` topic and pass a `stamp_secret` in the payload.
# For details on this structure see https://hexdocs.pm/phoenix/Phoenix.Socket.Message.html
diff --git a/elixir/apps/api/lib/api/gateway/socket.ex b/elixir/apps/api/lib/api/gateway/socket.ex
index dc820c1bc..4086d98e0 100644
--- a/elixir/apps/api/lib/api/gateway/socket.ex
+++ b/elixir/apps/api/lib/api/gateway/socket.ex
@@ -28,7 +28,7 @@ defmodule API.Gateway.Socket do
attrs =
attrs
- |> Map.take(~w[external_id name_suffix public_key])
+ |> Map.take(~w[external_id name public_key])
|> Map.put("last_seen_user_agent", user_agent)
|> Map.put("last_seen_remote_ip", real_ip)
|> Map.put("last_seen_remote_ip_location_region", location_region)
diff --git a/elixir/apps/domain/lib/domain/accounts.ex b/elixir/apps/domain/lib/domain/accounts.ex
index 616a61cb7..b058fa9be 100644
--- a/elixir/apps/domain/lib/domain/accounts.ex
+++ b/elixir/apps/domain/lib/domain/accounts.ex
@@ -3,6 +3,15 @@ defmodule Domain.Accounts do
alias Domain.Auth
alias Domain.Accounts.{Authorizer, Account}
+ def list_accounts_by_ids(ids) do
+ if Enum.all?(ids, &Validator.valid_uuid?/1) do
+ Account.Query.by_id({:in, ids})
+ |> Repo.list()
+ else
+ {:ok, []}
+ end
+ end
+
def fetch_account_by_id(id, %Auth.Subject{} = subject) do
with :ok <- Auth.ensure_has_permissions(subject, Authorizer.view_accounts_permission()),
true <- Validator.valid_uuid?(id) do
diff --git a/elixir/apps/domain/lib/domain/accounts/account/query.ex b/elixir/apps/domain/lib/domain/accounts/account/query.ex
index 8e308b5fa..18d44ba11 100644
--- a/elixir/apps/domain/lib/domain/accounts/account/query.ex
+++ b/elixir/apps/domain/lib/domain/accounts/account/query.ex
@@ -6,7 +6,13 @@ defmodule Domain.Accounts.Account.Query do
# |> where([account: account], is_nil(account.deleted_at))
end
- def by_id(queryable \\ all(), id) do
+ def by_id(queryable \\ all(), id)
+
+ def by_id(queryable, {:in, ids}) do
+ where(queryable, [account: account], account.id in ^ids)
+ end
+
+ def by_id(queryable, id) do
where(queryable, [account: account], account.id == ^id)
end
diff --git a/elixir/apps/domain/lib/domain/flows.ex b/elixir/apps/domain/lib/domain/flows.ex
index f03b450da..12c5bca03 100644
--- a/elixir/apps/domain/lib/domain/flows.ex
+++ b/elixir/apps/domain/lib/domain/flows.ex
@@ -1,6 +1,6 @@
defmodule Domain.Flows do
alias Domain.{Repo, Validator}
- alias Domain.{Auth, Accounts, Clients, Gateways, Resources, Policies}
+ alias Domain.{Auth, Accounts, Actors, Clients, Gateways, Resources, Policies}
alias Domain.Flows.{Authorizer, Flow, Activity}
require Ecto.Query
@@ -84,6 +84,11 @@ defmodule Domain.Flows do
|> list_flows(subject, opts)
end
+ def list_flows_for(%Actors.Actor{} = actor, %Auth.Subject{} = subject, opts) do
+ Flow.Query.by_actor_id(actor.id)
+ |> list_flows(subject, opts)
+ end
+
def list_flows_for(%Gateways.Gateway{} = gateway, %Auth.Subject{} = subject, opts) do
Flow.Query.by_gateway_id(gateway.id)
|> list_flows(subject, opts)
diff --git a/elixir/apps/domain/lib/domain/flows/flow/query.ex b/elixir/apps/domain/lib/domain/flows/flow/query.ex
index 0b8d00a19..7b404fda7 100644
--- a/elixir/apps/domain/lib/domain/flows/flow/query.ex
+++ b/elixir/apps/domain/lib/domain/flows/flow/query.ex
@@ -25,7 +25,19 @@ defmodule Domain.Flows.Flow.Query do
where(queryable, [flows: flows], flows.client_id == ^client_id)
end
+ def by_actor_id(queryable \\ all(), actor_id) do
+ queryable
+ |> with_joined_client()
+ |> where([client: client], client.actor_id == ^actor_id)
+ end
+
def by_gateway_id(queryable \\ all(), gateway_id) do
where(queryable, [flows: flows], flows.gateway_id == ^gateway_id)
end
+
+ def with_joined_client(queryable \\ all()) do
+ with_named_binding(queryable, :client, fn queryable, binding ->
+ join(queryable, :inner, [flows: flows], client in assoc(flows, ^binding), as: ^binding)
+ end)
+ end
end
diff --git a/elixir/apps/domain/lib/domain/gateways/gateway.ex b/elixir/apps/domain/lib/domain/gateways/gateway.ex
index 2831b3f28..b4bd6f96c 100644
--- a/elixir/apps/domain/lib/domain/gateways/gateway.ex
+++ b/elixir/apps/domain/lib/domain/gateways/gateway.ex
@@ -4,8 +4,7 @@ defmodule Domain.Gateways.Gateway do
schema "gateways" do
field :external_id, :string
- # TODO: hostname
- field :name_suffix, :string
+ field :name, :string
field :public_key, :string
diff --git a/elixir/apps/domain/lib/domain/gateways/gateway/changeset.ex b/elixir/apps/domain/lib/domain/gateways/gateway/changeset.ex
index 029adf9e1..a15597878 100644
--- a/elixir/apps/domain/lib/domain/gateways/gateway/changeset.ex
+++ b/elixir/apps/domain/lib/domain/gateways/gateway/changeset.ex
@@ -3,7 +3,7 @@ defmodule Domain.Gateways.Gateway.Changeset do
alias Domain.Version
alias Domain.Gateways
- @upsert_fields ~w[external_id name_suffix public_key
+ @upsert_fields ~w[external_id name public_key
last_seen_user_agent
last_seen_remote_ip
last_seen_remote_ip_location_region
@@ -20,8 +20,8 @@ defmodule Domain.Gateways.Gateway.Changeset do
last_seen_version
last_seen_at
updated_at]a
- @update_fields ~w[name_suffix]a
- @required_fields ~w[external_id name_suffix public_key
+ @update_fields ~w[name]a
+ @required_fields ~w[external_id name public_key
last_seen_user_agent last_seen_remote_ip]a
# WireGuard base64-encoded string length
@@ -35,7 +35,7 @@ defmodule Domain.Gateways.Gateway.Changeset do
def upsert(%Gateways.Token{} = token, attrs) do
%Gateways.Gateway{}
|> cast(attrs, @upsert_fields)
- |> put_default_value(:name_suffix, fn ->
+ |> put_default_value(:name, fn ->
Domain.Crypto.random_token(5, encoder: :user_friendly)
end)
|> changeset()
@@ -43,7 +43,6 @@ defmodule Domain.Gateways.Gateway.Changeset do
|> validate_base64(:public_key)
|> validate_length(:public_key, is: @key_length)
|> unique_constraint(:public_key, name: :gateways_account_id_public_key_index)
- |> unique_constraint(:name_suffix, name: :gateways_account_id_group_id_name_suffix_index)
|> unique_constraint(:ipv4)
|> unique_constraint(:ipv6)
|> put_change(:last_seen_at, DateTime.utc_now())
@@ -76,9 +75,9 @@ defmodule Domain.Gateways.Gateway.Changeset do
defp changeset(changeset) do
changeset
- |> trim_change(:name_suffix)
- |> validate_length(:name_suffix, min: 1, max: 8)
- |> unique_constraint(:name_suffix, name: :gateways_group_id_name_suffix_index)
+ |> trim_change(:name)
+ |> validate_length(:name, min: 1, max: 8)
+ |> unique_constraint(:name, name: :gateways_group_id_name_index)
|> unique_constraint([:public_key])
|> unique_constraint(:external_id)
end
diff --git a/elixir/apps/domain/lib/domain/gateways/group.ex b/elixir/apps/domain/lib/domain/gateways/group.ex
index d1ab90e32..901f6bd17 100644
--- a/elixir/apps/domain/lib/domain/gateways/group.ex
+++ b/elixir/apps/domain/lib/domain/gateways/group.ex
@@ -2,8 +2,7 @@ defmodule Domain.Gateways.Group do
use Domain, :schema
schema "gateway_groups" do
- # TODO: name
- field :name_prefix, :string
+ field :name, :string
belongs_to :account, Domain.Accounts.Account
has_many :gateways, Domain.Gateways.Gateway, foreign_key: :group_id, where: [deleted_at: nil]
diff --git a/elixir/apps/domain/lib/domain/gateways/group/changeset.ex b/elixir/apps/domain/lib/domain/gateways/group/changeset.ex
index 12b9b5199..518b71ed8 100644
--- a/elixir/apps/domain/lib/domain/gateways/group/changeset.ex
+++ b/elixir/apps/domain/lib/domain/gateways/group/changeset.ex
@@ -3,7 +3,7 @@ defmodule Domain.Gateways.Group.Changeset do
alias Domain.{Auth, Accounts}
alias Domain.Gateways
- @fields ~w[name_prefix]a
+ @fields ~w[name]a
def create(%Accounts.Account{} = account, attrs, %Auth.Subject{} = subject) do
%Gateways.Group{account: account}
@@ -35,11 +35,11 @@ defmodule Domain.Gateways.Group.Changeset do
defp changeset(%Gateways.Group{} = group, attrs) do
group
|> cast(attrs, @fields)
- |> trim_change(:name_prefix)
- |> put_default_value(:name_prefix, &Domain.NameGenerator.generate/0)
+ |> trim_change(:name)
+ |> put_default_value(:name, &Domain.NameGenerator.generate/0)
|> validate_required(@fields)
- |> validate_length(:name_prefix, min: 1, max: 64)
- |> unique_constraint(:name_prefix, name: :gateway_groups_account_id_name_prefix_index)
+ |> validate_length(:name, min: 1, max: 64)
+ |> unique_constraint(:name, name: :gateway_groups_account_id_name_index)
end
def delete(%Gateways.Group{} = group) do
diff --git a/elixir/apps/domain/lib/domain/policies/policy.ex b/elixir/apps/domain/lib/domain/policies/policy.ex
index c4babba2f..7b94adf1a 100644
--- a/elixir/apps/domain/lib/domain/policies/policy.ex
+++ b/elixir/apps/domain/lib/domain/policies/policy.ex
@@ -4,8 +4,8 @@ defmodule Domain.Policies.Policy do
schema "policies" do
field :description, :string
- belongs_to :actor_group, Domain.Actors.Group
- belongs_to :resource, Domain.Resources.Resource
+ belongs_to :actor_group, Domain.Actors.Group, where: [deleted_at: nil]
+ belongs_to :resource, Domain.Resources.Resource, where: [deleted_at: nil]
belongs_to :account, Domain.Accounts.Account
field :created_by, Ecto.Enum, values: ~w[identity]a
diff --git a/elixir/apps/domain/lib/domain/policies/policy/query.ex b/elixir/apps/domain/lib/domain/policies/policy/query.ex
index 312a90b0d..72b14b288 100644
--- a/elixir/apps/domain/lib/domain/policies/policy/query.ex
+++ b/elixir/apps/domain/lib/domain/policies/policy/query.ex
@@ -4,6 +4,10 @@ defmodule Domain.Policies.Policy.Query do
def all do
from(policies in Domain.Policies.Policy, as: :policies)
|> where([policies: policies], is_nil(policies.deleted_at))
+ |> with_joined_actor_group()
+ |> where([actor_group: actor_group], is_nil(actor_group.deleted_at))
+ |> with_joined_resource()
+ |> where([resource: resource], is_nil(resource.deleted_at))
end
def by_id(queryable \\ all(), id) do
@@ -45,6 +49,14 @@ defmodule Domain.Policies.Policy.Query do
end)
end
+ def with_joined_resource(queryable \\ all()) do
+ with_named_binding(queryable, :resource, fn queryable, binding ->
+ join(queryable, :inner, [policies: policies], resource in assoc(policies, ^binding),
+ as: ^binding
+ )
+ end)
+ end
+
def with_joined_memberships(queryable \\ all()) do
queryable
|> with_joined_actor_group()
diff --git a/elixir/apps/domain/priv/repo/migrations/20231113213333_rename_gateway_groups_name_prefix.exs b/elixir/apps/domain/priv/repo/migrations/20231113213333_rename_gateway_groups_name_prefix.exs
new file mode 100644
index 000000000..ef4870415
--- /dev/null
+++ b/elixir/apps/domain/priv/repo/migrations/20231113213333_rename_gateway_groups_name_prefix.exs
@@ -0,0 +1,12 @@
+defmodule Domain.Repo.Migrations.RenameGatewayGroupsNamePrefix do
+ use Ecto.Migration
+
+ def change do
+ rename(table(:gateway_groups), :name_prefix, to: :name)
+
+ execute("""
+ ALTER INDEX gateway_groups_account_id_name_prefix_index
+ RENAME TO gateway_groups_account_id_name_index
+ """)
+ end
+end
diff --git a/elixir/apps/domain/priv/repo/migrations/20231113214017_rename_gateway_name_suffix_to_name.exs b/elixir/apps/domain/priv/repo/migrations/20231113214017_rename_gateway_name_suffix_to_name.exs
new file mode 100644
index 000000000..b815fb073
--- /dev/null
+++ b/elixir/apps/domain/priv/repo/migrations/20231113214017_rename_gateway_name_suffix_to_name.exs
@@ -0,0 +1,14 @@
+defmodule Domain.Repo.Migrations.RenameGatewayNameSuffixToName do
+ use Ecto.Migration
+
+ def change do
+ rename(table(:gateways), :name_suffix, to: :name)
+
+ drop(
+ index(:gateways, [:account_id, :group_id, :name_suffix],
+ unique: true,
+ where: "deleted_at IS NULL"
+ )
+ )
+ end
+end
diff --git a/elixir/apps/domain/priv/repo/seeds.exs b/elixir/apps/domain/priv/repo/seeds.exs
index 8da5da533..e2a6eb57b 100644
--- a/elixir/apps/domain/priv/repo/seeds.exs
+++ b/elixir/apps/domain/priv/repo/seeds.exs
@@ -342,7 +342,7 @@ IO.puts("")
gateway_group =
account
|> Gateways.Group.Changeset.create(
- %{name_prefix: "mycro-aws-gws", tokens: [%{}]},
+ %{name: "mycro-aws-gws", tokens: [%{}]},
admin_subject
)
|> Repo.insert!()
@@ -359,13 +359,13 @@ gateway_group_token =
)
IO.puts("Created gateway groups:")
-IO.puts(" #{gateway_group.name_prefix} token: #{Gateways.encode_token!(gateway_group_token)}")
+IO.puts(" #{gateway_group.name} token: #{Gateways.encode_token!(gateway_group_token)}")
IO.puts("")
{:ok, gateway1} =
Gateways.upsert_gateway(gateway_group_token, %{
external_id: Ecto.UUID.generate(),
- name_suffix: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
+ name: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
public_key: :crypto.strong_rand_bytes(32) |> Base.encode64(),
last_seen_user_agent: "iOS/12.7 (iPhone) connlib/0.7.412",
last_seen_remote_ip: %Postgrex.INET{address: {189, 172, 73, 153}}
@@ -374,7 +374,7 @@ IO.puts("")
{:ok, gateway2} =
Gateways.upsert_gateway(gateway_group_token, %{
external_id: Ecto.UUID.generate(),
- name_suffix: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
+ name: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
public_key: :crypto.strong_rand_bytes(32) |> Base.encode64(),
last_seen_user_agent: "iOS/12.7 (iPhone) connlib/0.7.412",
last_seen_remote_ip: %Postgrex.INET{address: {164, 112, 78, 62}}
@@ -384,7 +384,7 @@ for i <- 1..10 do
{:ok, _gateway} =
Gateways.upsert_gateway(gateway_group_token, %{
external_id: Ecto.UUID.generate(),
- name_suffix: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
+ name: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
public_key: :crypto.strong_rand_bytes(32) |> Base.encode64(),
last_seen_user_agent: "iOS/12.7 (iPhone) connlib/0.7.412",
last_seen_remote_ip: %Postgrex.INET{address: {164, 112, 78, 62 + i}}
@@ -392,14 +392,14 @@ for i <- 1..10 do
end
IO.puts("Created gateways:")
-gateway_name = "#{gateway_group.name_prefix}-#{gateway1.name_suffix}"
+gateway_name = "#{gateway_group.name}-#{gateway1.name}"
IO.puts(" #{gateway_name}:")
IO.puts(" External UUID: #{gateway1.external_id}")
IO.puts(" Public Key: #{gateway1.public_key}")
IO.puts(" IPv4: #{gateway1.ipv4} IPv6: #{gateway1.ipv6}")
IO.puts("")
-gateway_name = "#{gateway_group.name_prefix}-#{gateway2.name_suffix}"
+gateway_name = "#{gateway_group.name}-#{gateway2.name}"
IO.puts(" #{gateway_name}:")
IO.puts(" External UUID: #{gateway1.external_id}")
IO.puts(" Public Key: #{gateway2.public_key}")
diff --git a/elixir/apps/domain/test/domain/flows_test.exs b/elixir/apps/domain/test/domain/flows_test.exs
index 95c2d722a..809416b95 100644
--- a/elixir/apps/domain/test/domain/flows_test.exs
+++ b/elixir/apps/domain/test/domain/flows_test.exs
@@ -273,6 +273,7 @@ defmodule Domain.FlowsTest do
describe "list_flows_for/2" do
test "returns empty list when there are no flows", %{
+ actor: actor,
client: client,
gateway: gateway,
resource: resource,
@@ -281,11 +282,13 @@ defmodule Domain.FlowsTest do
} do
assert list_flows_for(policy, subject) == {:ok, []}
assert list_flows_for(resource, subject) == {:ok, []}
+ assert list_flows_for(actor, subject) == {:ok, []}
assert list_flows_for(client, subject) == {:ok, []}
assert list_flows_for(gateway, subject) == {:ok, []}
end
test "does not list flows from other accounts", %{
+ actor: actor,
client: client,
gateway: gateway,
resource: resource,
@@ -296,12 +299,14 @@ defmodule Domain.FlowsTest do
assert list_flows_for(policy, subject) == {:ok, []}
assert list_flows_for(resource, subject) == {:ok, []}
+ assert list_flows_for(actor, subject) == {:ok, []}
assert list_flows_for(client, subject) == {:ok, []}
assert list_flows_for(gateway, subject) == {:ok, []}
end
- test "returns all authorized flows", %{
+ test "returns all authorized flows for a given entity", %{
account: account,
+ actor: actor,
client: client,
gateway: gateway,
resource: resource,
@@ -320,12 +325,33 @@ defmodule Domain.FlowsTest do
assert list_flows_for(policy, subject) == {:ok, [flow]}
assert list_flows_for(resource, subject) == {:ok, [flow]}
+ assert list_flows_for(actor, subject) == {:ok, [flow]}
assert list_flows_for(client, subject) == {:ok, [flow]}
assert list_flows_for(gateway, subject) == {:ok, [flow]}
end
+ test "does not return authorized flow of other entities", %{
+ account: account,
+ actor: actor,
+ client: client,
+ gateway: gateway,
+ resource: resource,
+ policy: policy,
+ subject: subject
+ } do
+ other_client = Fixtures.Clients.create_client(account: account)
+ Fixtures.Flows.create_flow(account: account, client: other_client, subject: subject)
+
+ assert list_flows_for(policy, subject) == {:ok, []}
+ assert list_flows_for(resource, subject) == {:ok, []}
+ assert list_flows_for(actor, subject) == {:ok, []}
+ assert list_flows_for(client, subject) == {:ok, []}
+ assert list_flows_for(gateway, subject) == {:ok, []}
+ end
+
test "returns error when subject has no permission to view flows", %{
client: client,
+ actor: actor,
gateway: gateway,
resource: resource,
policy: policy,
@@ -340,6 +366,7 @@ defmodule Domain.FlowsTest do
assert list_flows_for(policy, subject) == expected_error
assert list_flows_for(resource, subject) == expected_error
assert list_flows_for(client, subject) == expected_error
+ assert list_flows_for(actor, subject) == expected_error
assert list_flows_for(gateway, subject) == expected_error
end
end
diff --git a/elixir/apps/domain/test/domain/gateways_test.exs b/elixir/apps/domain/test/domain/gateways_test.exs
index a2b7206bd..7cd7eb352 100644
--- a/elixir/apps/domain/test/domain/gateways_test.exs
+++ b/elixir/apps/domain/test/domain/gateways_test.exs
@@ -121,7 +121,7 @@ defmodule Domain.GatewaysTest do
describe "new_group/0" do
test "returns group changeset" do
assert %Ecto.Changeset{data: %Gateways.Group{}, changes: changes} = new_group()
- assert Map.has_key?(changes, :name_prefix)
+ assert Map.has_key?(changes, :name)
assert Enum.count(changes) == 1
end
end
@@ -134,31 +134,31 @@ defmodule Domain.GatewaysTest do
test "returns error on invalid attrs", %{account: account, subject: subject} do
attrs = %{
- name_prefix: String.duplicate("A", 65)
+ name: String.duplicate("A", 65)
}
assert {:error, changeset} = create_group(attrs, subject)
assert errors_on(changeset) == %{
tokens: ["can't be blank"],
- name_prefix: ["should be at most 64 character(s)"]
+ name: ["should be at most 64 character(s)"]
}
- Fixtures.Gateways.create_group(account: account, name_prefix: "foo")
- attrs = %{name_prefix: "foo", tokens: [%{}]}
+ Fixtures.Gateways.create_group(account: account, name: "foo")
+ attrs = %{name: "foo", tokens: [%{}]}
assert {:error, changeset} = create_group(attrs, subject)
- assert "has already been taken" in errors_on(changeset).name_prefix
+ assert "has already been taken" in errors_on(changeset).name
end
test "creates a group", %{subject: subject} do
attrs = %{
- name_prefix: "foo",
+ name: "foo",
tokens: [%{}]
}
assert {:ok, group} = create_group(attrs, subject)
assert group.id
- assert group.name_prefix == "foo"
+ assert group.name == "foo"
assert group.created_by == :identity
assert group.created_by_identity_id == subject.identity.id
@@ -190,7 +190,7 @@ defmodule Domain.GatewaysTest do
assert changeset = change_group(group, group_attrs)
assert changeset.valid?
- assert changeset.changes == %{name_prefix: group_attrs.name_prefix}
+ assert changeset.changes == %{name: group_attrs.name}
end
end
@@ -199,41 +199,41 @@ defmodule Domain.GatewaysTest do
subject: subject
} do
group = Fixtures.Gateways.create_group()
- attrs = %{name_prefix: nil}
+ attrs = %{name: nil}
assert {:error, changeset} = update_group(group, attrs, subject)
- assert errors_on(changeset) == %{name_prefix: ["can't be blank"]}
+ assert errors_on(changeset) == %{name: ["can't be blank"]}
end
test "returns error on invalid attrs", %{account: account, subject: subject} do
group = Fixtures.Gateways.create_group(account: account)
attrs = %{
- name_prefix: String.duplicate("A", 65)
+ name: String.duplicate("A", 65)
}
assert {:error, changeset} = update_group(group, attrs, subject)
assert errors_on(changeset) == %{
- name_prefix: ["should be at most 64 character(s)"]
+ name: ["should be at most 64 character(s)"]
}
- Fixtures.Gateways.create_group(account: account, name_prefix: "foo")
- attrs = %{name_prefix: "foo"}
+ Fixtures.Gateways.create_group(account: account, name: "foo")
+ attrs = %{name: "foo"}
assert {:error, changeset} = update_group(group, attrs, subject)
- assert "has already been taken" in errors_on(changeset).name_prefix
+ assert "has already been taken" in errors_on(changeset).name
end
test "updates a group", %{account: account, subject: subject} do
group = Fixtures.Gateways.create_group(account: account)
attrs = %{
- name_prefix: "foo"
+ name: "foo"
}
assert {:ok, group} = update_group(group, attrs, subject)
- assert group.name_prefix == "foo"
+ assert group.name == "foo"
end
test "returns error when subject has no permission to manage groups", %{
@@ -536,7 +536,7 @@ defmodule Domain.GatewaysTest do
assert changeset = change_gateway(gateway, gateway_attrs)
assert %Ecto.Changeset{data: %Domain.Gateways.Gateway{}} = changeset
- assert changeset.changes == %{name_suffix: gateway_attrs.name_suffix}
+ assert changeset.changes == %{name: gateway_attrs.name}
end
end
@@ -585,7 +585,7 @@ defmodule Domain.GatewaysTest do
assert {:ok, gateway} = upsert_gateway(token, attrs)
- assert gateway.name_suffix
+ assert gateway.name
assert gateway.public_key == attrs.public_key
assert gateway.token_id == token.id
@@ -627,7 +627,7 @@ defmodule Domain.GatewaysTest do
assert Repo.aggregate(Gateways.Gateway, :count, :id) == 1
- assert updated_gateway.name_suffix
+ assert updated_gateway.name
assert updated_gateway.last_seen_remote_ip.address == attrs.last_seen_remote_ip
assert updated_gateway.last_seen_remote_ip != gateway.last_seen_remote_ip
assert updated_gateway.last_seen_user_agent == attrs.last_seen_user_agent
@@ -710,11 +710,11 @@ defmodule Domain.GatewaysTest do
describe "update_gateway/3" do
test "updates gateways", %{account: account, subject: subject} do
gateway = Fixtures.Gateways.create_gateway(account: account)
- attrs = %{name_suffix: "Foo"}
+ attrs = %{name: "Foo"}
assert {:ok, gateway} = update_gateway(gateway, attrs, subject)
- assert gateway.name_suffix == attrs.name_suffix
+ assert gateway.name == attrs.name
end
test "does not allow to reset required fields to empty values", %{
@@ -722,24 +722,24 @@ defmodule Domain.GatewaysTest do
subject: subject
} do
gateway = Fixtures.Gateways.create_gateway(account: account)
- attrs = %{name_suffix: nil}
+ attrs = %{name: nil}
assert {:error, changeset} = update_gateway(gateway, attrs, subject)
- assert errors_on(changeset) == %{name_suffix: ["can't be blank"]}
+ assert errors_on(changeset) == %{name: ["can't be blank"]}
end
test "returns error on invalid attrs", %{account: account, subject: subject} do
gateway = Fixtures.Gateways.create_gateway(account: account)
attrs = %{
- name_suffix: String.duplicate("a", 256)
+ name: String.duplicate("a", 256)
}
assert {:error, changeset} = update_gateway(gateway, attrs, subject)
assert errors_on(changeset) == %{
- name_suffix: ["should be at most 8 character(s)"]
+ name: ["should be at most 8 character(s)"]
}
end
@@ -749,7 +749,7 @@ defmodule Domain.GatewaysTest do
} do
gateway = Fixtures.Gateways.create_gateway(account: account)
- fields = Gateways.Gateway.__schema__(:fields) -- [:name_suffix]
+ fields = Gateways.Gateway.__schema__(:fields) -- [:name]
value = -1
for field <- fields do
diff --git a/elixir/apps/domain/test/domain/policies_test.exs b/elixir/apps/domain/test/domain/policies_test.exs
index 1bf805950..2976d2d3c 100644
--- a/elixir/apps/domain/test/domain/policies_test.exs
+++ b/elixir/apps/domain/test/domain/policies_test.exs
@@ -91,6 +91,38 @@ defmodule Domain.PoliciesTest do
assert list_policies(subject) == {:ok, []}
end
+ test "does not list policies for deleted resources", %{account: account, subject: subject} do
+ resource =
+ Fixtures.Resources.create_resource(account: account)
+ |> Fixtures.Resources.delete_resource()
+
+ actor_group = Fixtures.Actors.create_group(account: account)
+
+ Fixtures.Policies.create_policy(
+ account: account,
+ resource: resource,
+ actor_group: actor_group
+ )
+
+ assert list_policies(subject) == {:ok, []}
+ end
+
+ test "does not list policies for deleted actor groups", %{account: account, subject: subject} do
+ resource = Fixtures.Resources.create_resource(account: account)
+
+ actor_group =
+ Fixtures.Actors.create_group(account: account)
+ |> Fixtures.Actors.delete_group()
+
+ Fixtures.Policies.create_policy(
+ account: account,
+ resource: resource,
+ actor_group: actor_group
+ )
+
+ assert list_policies(subject) == {:ok, []}
+ end
+
test "returns all policies for account admin subject", %{account: account} do
actor = Fixtures.Actors.create_actor(type: :account_admin_user, account: account)
identity = Fixtures.Auth.create_identity(account: account, actor: actor)
diff --git a/elixir/apps/domain/test/support/fixtures/gateways.ex b/elixir/apps/domain/test/support/fixtures/gateways.ex
index 388f1153a..c0acca920 100644
--- a/elixir/apps/domain/test/support/fixtures/gateways.ex
+++ b/elixir/apps/domain/test/support/fixtures/gateways.ex
@@ -4,7 +4,7 @@ defmodule Domain.Fixtures.Gateways do
def group_attrs(attrs \\ %{}) do
Enum.into(attrs, %{
- name_prefix: "group-#{unique_integer()}",
+ name: "group-#{unique_integer()}",
tokens: [%{}]
})
end
@@ -71,7 +71,7 @@ defmodule Domain.Fixtures.Gateways do
def gateway_attrs(attrs \\ %{}) do
Enum.into(attrs, %{
external_id: Ecto.UUID.generate(),
- name_suffix: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
+ name: "gw-#{Domain.Crypto.random_token(5, encoder: :user_friendly)}",
public_key: unique_public_key(),
last_seen_user_agent: "iOS/12.7 (iPhone) connlib/0.7.412",
last_seen_remote_ip: %Postgrex.INET{address: {189, 172, 73, 153}},
diff --git a/elixir/apps/web/assets/js/hooks.js b/elixir/apps/web/assets/js/hooks.js
index 4cffbcb91..3c806dc1c 100644
--- a/elixir/apps/web/assets/js/hooks.js
+++ b/elixir/apps/web/assets/js/hooks.js
@@ -13,14 +13,22 @@ Hooks.Copy = {
let doc = new DOMParser().parseFromString(inner_html, "text/html");
let text = doc.documentElement.textContent;
- let cl = ev.currentTarget.querySelector("[data-icon]").classList
+ let content = ev.currentTarget.querySelector("[data-content]")
+ let icon_cl = ev.currentTarget.querySelector("[data-icon]").classList
navigator.clipboard.writeText(text).then(() => {
- cl.add("hero-clipboard-document-check");
- cl.add("text-green-500");
- cl.remove("hero-clipboard-document");
- cl.remove("text-gray-500");
- })
+ icon_cl.add("hero-clipboard-document-check");
+ icon_cl.add("text-green-500");
+ icon_cl.remove("hero-clipboard-document");
+ content.innerHTML = "Copied"
+ });
+
+ setTimeout(() => {
+ icon_cl.remove("hero-clipboard-document-check");
+ icon_cl.remove("text-green-500");
+ icon_cl.add("hero-clipboard-document");
+ content.innerHTML = "Copy"
+ }, 2000);
});
},
}
diff --git a/elixir/apps/web/lib/web/auth.ex b/elixir/apps/web/lib/web/auth.ex
index c4a9ceaff..7ff426ab1 100644
--- a/elixir/apps/web/lib/web/auth.ex
+++ b/elixir/apps/web/lib/web/auth.ex
@@ -2,6 +2,18 @@ defmodule Web.Auth do
use Web, :verified_routes
alias Domain.{Auth, Accounts}
+ # This is the cookie which will store recent account ids
+ # that the user has signed in to.
+ @remember_me_cookie_name "fz_recent_account_ids"
+ @remember_me_cookie_options [
+ sign: true,
+ max_age: 365 * 24 * 60 * 60,
+ same_site: "Lax",
+ secure: true,
+ http_only: true
+ ]
+ @remember_last_account_ids 5
+
def signed_in_path(%Auth.Subject{actor: %{type: :account_admin_user}} = subject) do
~p"/#{subject.account}/sites"
end
@@ -132,6 +144,37 @@ defmodule Web.Auth do
|> Plug.Conn.put_session(:preferred_locale, preferred_locale)
end
+ ###########################
+ ## Controller Helpers
+ ###########################
+
+ def list_recent_account_ids(conn) do
+ conn = Plug.Conn.fetch_cookies(conn, signed: [@remember_me_cookie_name])
+
+ if recent_account_ids = Map.get(conn.cookies, @remember_me_cookie_name) do
+ {:ok, :erlang.binary_to_term(recent_account_ids, [:safe]), conn}
+ else
+ {:ok, [], conn}
+ end
+ end
+
+ def update_recent_account_ids(conn, callback) when is_function(callback, 1) do
+ {:ok, recent_account_ids, conn} = list_recent_account_ids(conn)
+
+ recent_account_ids =
+ recent_account_ids
+ |> callback.()
+ |> Enum.take(@remember_last_account_ids)
+ |> :erlang.term_to_binary()
+
+ Plug.Conn.put_resp_cookie(
+ conn,
+ @remember_me_cookie_name,
+ recent_account_ids,
+ @remember_me_cookie_options
+ )
+ end
+
###########################
## Plugs
###########################
diff --git a/elixir/apps/web/lib/web/components/core_components.ex b/elixir/apps/web/lib/web/components/core_components.ex
index f25c7043c..b7f1bf3d2 100644
--- a/elixir/apps/web/lib/web/components/core_components.ex
+++ b/elixir/apps/web/lib/web/components/core_components.ex
@@ -70,12 +70,23 @@ defmodule Web.CoreComponents do
data-copy
phx-no-format
><%= render_slot(@inner_block) %>
- <.icon name="hero-clipboard-document" data-icon class={~w[
+
+
+ cursor-pointer
+ rounded
+ px-2
+ focus:ring-4 focus:outline-none
+ text-white
+ bg-accent-400
+ hover:bg-accent-500
+ focus:ring-accent-300
+ ]}>
+ <.icon name="hero-clipboard-document" data-icon class="h-4 w-4" />
+ Copy
+
"""
end
@@ -486,6 +497,27 @@ defmodule Web.CoreComponents do
"""
end
+ def icon(%{name: "spinner"} = assigns) do
+ ~H"""
+
+ """
+ end
+
@doc """
Renders Gravatar img tag.
"""
@@ -717,6 +749,40 @@ defmodule Web.CoreComponents do
"""
end
+ attr :navigate, :string, required: true
+ attr :connected?, :boolean, required: true
+ attr :type, :string, required: true
+
+ def initial_connection_status(assigns) do
+ ~H"""
+ <.link
+ class={[
+ "mx-4 my-6 h-8",
+ "flex items-center justify-center",
+ "font-medium text-sm text-white",
+ "rounded-full",
+ (@connected? && "bg-green-500") || "bg-orange-400 cursor-progress"
+ ]}
+ navigate={@navigate}
+ {
+ if @connected? do
+ %{}
+ else
+ %{"data-confirm" => "Do you want to skip waiting for #{@type} to be connected?"}
+ end
+ }
+ >
+
+ <.icon name="spinner" class="animate-spin h-3.5 w-3.5 mr-1" /> Waiting for connection...
+
+
+
+ <.icon name="hero-check" class="h-3.5 w-3.5" /> Connected, click to continue
+
+
+ """
+ end
+
@doc """
Renders creation timestamp and entity.
"""
diff --git a/elixir/apps/web/lib/web/controllers/auth_controller.ex b/elixir/apps/web/lib/web/controllers/auth_controller.ex
index 7f31db845..0617b34c6 100644
--- a/elixir/apps/web/lib/web/controllers/auth_controller.ex
+++ b/elixir/apps/web/lib/web/controllers/auth_controller.ex
@@ -3,17 +3,6 @@ defmodule Web.AuthController do
alias Web.Auth
alias Domain.Auth.Adapters.OpenIDConnect
- # This is the cookie which will store recent account ids
- # that the user has signed in to.
- @remember_me_cookie_name "fz_recent_account_ids"
- @remember_me_cookie_options [
- sign: true,
- max_age: 365 * 24 * 60 * 60,
- same_site: "Lax",
- secure: true,
- http_only: true
- ]
-
# This is the cookie which will be used to store the
# state and code verifier for OpenID Connect IdP's
@state_cookie_key_prefix "fz_auth_state_"
@@ -306,7 +295,6 @@ defmodule Web.AuthController do
Domain.Auth.sign_out(subject.identity, url(~p"/#{account_id_or_slug}?#{redirect_params}"))
conn
- |> delete_recent_account()
|> Auth.sign_out()
|> redirect(external: redirect_url)
end
@@ -319,42 +307,12 @@ defmodule Web.AuthController do
|> redirect(to: ~p"/#{account_id_or_slug}?#{redirect_params}")
end
- defp delete_recent_account(%{assigns: %{subject: subject}} = conn) do
- update_recent_accounts(conn, fn recent_account_ids ->
- recent_account_ids -- [subject.account.id]
- end)
- end
-
defp persist_recent_account(conn, %Domain.Accounts.Account{} = account) do
- update_recent_accounts(conn, fn recent_account_ids ->
+ Auth.update_recent_account_ids(conn, fn recent_account_ids ->
[account.id] ++ recent_account_ids
end)
end
- defp update_recent_accounts(conn, callback) when is_function(callback, 1) do
- conn = fetch_cookies(conn, signed: [@remember_me_cookie_name])
-
- recent_account_ids =
- if recent_account_ids = Map.get(conn.cookies, @remember_me_cookie_name) do
- :erlang.binary_to_term(recent_account_ids, [:safe])
- else
- []
- end
-
- recent_account_ids =
- recent_account_ids
- |> callback.()
- |> Enum.take(5)
- |> :erlang.term_to_binary()
-
- put_resp_cookie(
- conn,
- @remember_me_cookie_name,
- recent_account_ids,
- @remember_me_cookie_options
- )
- end
-
defp take_non_empty_params(map, keys) do
map |> Map.take(keys) |> Map.reject(fn {_key, value} -> value in ["", nil] end)
end
diff --git a/elixir/apps/web/lib/web/controllers/home_controller.ex b/elixir/apps/web/lib/web/controllers/home_controller.ex
new file mode 100644
index 000000000..7e4754e3a
--- /dev/null
+++ b/elixir/apps/web/lib/web/controllers/home_controller.ex
@@ -0,0 +1,27 @@
+defmodule Web.HomeController do
+ use Web, :controller
+ alias Domain.Accounts
+
+ def home(conn, _params) do
+ {accounts, conn} =
+ with {:ok, recent_account_ids, conn} <- Web.Auth.list_recent_account_ids(conn),
+ {:ok, accounts} <- Accounts.list_accounts_by_ids(recent_account_ids) do
+ conn =
+ Web.Auth.update_recent_account_ids(conn, fn _recent_account_ids ->
+ Enum.map(accounts, & &1.id)
+ end)
+
+ {accounts, conn}
+ else
+ _other -> {[], conn}
+ end
+
+ conn
+ |> put_layout(html: {Web.Layouts, :public})
+ |> render("home.html", accounts: accounts)
+ end
+
+ def redirect_to_sign_in(conn, %{"account_id_or_slug" => account_id_or_slug}) do
+ redirect(conn, to: ~p"/#{account_id_or_slug}")
+ end
+end
diff --git a/elixir/apps/web/lib/web/controllers/home_html.ex b/elixir/apps/web/lib/web/controllers/home_html.ex
new file mode 100644
index 000000000..1395ab07a
--- /dev/null
+++ b/elixir/apps/web/lib/web/controllers/home_html.ex
@@ -0,0 +1,81 @@
+defmodule Web.HomeHTML do
+ use Web, :html
+
+ def home(assigns) do
+ ~H"""
+
+ Don't have an account?
+
+ Sign up here.
+
+
+ Welcome to Firezone
+
+
+
+ Recently used accounts
+
+
+
<%= @gateway.name_suffix %>
+ Gateway: <%= @gateway.name %>
<:content>
<.vertical_table id="gateway">
@@ -54,13 +54,13 @@ defmodule Web.Gateways.Show do
navigate={~p"/#{@account}/sites/#{@gateway.group}"}
class="font-bold text-blue-600 dark:text-blue-500 hover:underline"
>
- <%= @gateway.group.name_prefix %>
+ <%= @gateway.group.name %>
<.vertical_table_row>
- <:label>Instance Name
- <:value><%= @gateway.name_suffix %>
+ <:label>Name
+ <:value><%= @gateway.name %>
<.vertical_table_row :if={@todos_enabled?}>
<:label>Connectivity
@@ -203,7 +203,7 @@ defmodule Web.Gateways.Show do
{:ok, _gateway} = Gateways.delete_gateway(socket.assigns.gateway, socket.assigns.subject)
socket =
- redirect(socket,
+ push_navigate(socket,
to: ~p"/#{socket.assigns.account}/sites/#{socket.assigns.gateway.group}"
)
diff --git a/elixir/apps/web/lib/web/live/groups/edit.ex b/elixir/apps/web/lib/web/live/groups/edit.ex
index 3d4d8d52a..39643ba30 100644
--- a/elixir/apps/web/lib/web/live/groups/edit.ex
+++ b/elixir/apps/web/lib/web/live/groups/edit.ex
@@ -58,7 +58,7 @@ defmodule Web.Groups.Edit do
def handle_event("submit", %{"group" => attrs}, socket) do
with {:ok, group} <-
Actors.update_group(socket.assigns.group, attrs, socket.assigns.subject) do
- socket = redirect(socket, to: ~p"/#{socket.assigns.account}/groups/#{group}")
+ socket = push_navigate(socket, to: ~p"/#{socket.assigns.account}/groups/#{group}")
{:noreply, socket}
else
{:error, changeset} ->
diff --git a/elixir/apps/web/lib/web/live/groups/edit_actors.ex b/elixir/apps/web/lib/web/live/groups/edit_actors.ex
index bd7c4bf86..d70280093 100644
--- a/elixir/apps/web/lib/web/live/groups/edit_actors.ex
+++ b/elixir/apps/web/lib/web/live/groups/edit_actors.ex
@@ -143,7 +143,7 @@ defmodule Web.Groups.EditActors do
with {:ok, group} <-
Actors.update_group(socket.assigns.group, attrs, socket.assigns.subject) do
- socket = redirect(socket, to: ~p"/#{socket.assigns.account}/groups/#{group}")
+ socket = push_navigate(socket, to: ~p"/#{socket.assigns.account}/groups/#{group}")
{:noreply, socket}
else
{:error, changeset} ->
diff --git a/elixir/apps/web/lib/web/live/groups/new.ex b/elixir/apps/web/lib/web/live/groups/new.ex
index b421608c9..75bafff32 100644
--- a/elixir/apps/web/lib/web/live/groups/new.ex
+++ b/elixir/apps/web/lib/web/live/groups/new.ex
@@ -51,7 +51,9 @@ defmodule Web.Groups.New do
def handle_event("submit", %{"group" => attrs}, socket) do
with {:ok, group} <-
Actors.create_group(attrs, socket.assigns.subject) do
- socket = redirect(socket, to: ~p"/#{socket.assigns.account}/groups/#{group}/edit_actors")
+ socket =
+ push_navigate(socket, to: ~p"/#{socket.assigns.account}/groups/#{group}/edit_actors")
+
{:noreply, socket}
else
{:error, changeset} ->
diff --git a/elixir/apps/web/lib/web/live/groups/show.ex b/elixir/apps/web/lib/web/live/groups/show.ex
index dc985a131..d1c86ce7c 100644
--- a/elixir/apps/web/lib/web/live/groups/show.ex
+++ b/elixir/apps/web/lib/web/live/groups/show.ex
@@ -116,6 +116,6 @@ defmodule Web.Groups.Show do
def handle_event("delete", _params, socket) do
{:ok, _group} = Actors.delete_group(socket.assigns.group, socket.assigns.subject)
- {:noreply, redirect(socket, to: ~p"/#{socket.assigns.account}/groups")}
+ {:noreply, push_navigate(socket, to: ~p"/#{socket.assigns.account}/groups")}
end
end
diff --git a/elixir/apps/web/lib/web/live/policies/edit.ex b/elixir/apps/web/lib/web/live/policies/edit.ex
index e8862f00e..4318afb14 100644
--- a/elixir/apps/web/lib/web/live/policies/edit.ex
+++ b/elixir/apps/web/lib/web/live/policies/edit.ex
@@ -69,7 +69,7 @@ defmodule Web.Policies.Edit do
def handle_event("submit", %{"policy" => policy_params}, socket) do
with {:ok, policy} <-
Policies.update_policy(socket.assigns.policy, policy_params, socket.assigns.subject) do
- {:noreply, redirect(socket, to: ~p"/#{socket.assigns.account}/policies/#{policy}")}
+ {:noreply, push_navigate(socket, to: ~p"/#{socket.assigns.account}/policies/#{policy}")}
else
{:error, changeset} ->
{:noreply, assign(socket, form: to_form(changeset))}
diff --git a/elixir/apps/web/lib/web/live/policies/new.ex b/elixir/apps/web/lib/web/live/policies/new.ex
index c1b7ea000..5ad32ef7d 100644
--- a/elixir/apps/web/lib/web/live/policies/new.ex
+++ b/elixir/apps/web/lib/web/live/policies/new.ex
@@ -53,7 +53,7 @@ defmodule Web.Policies.New do
type="select"
options={
Enum.map(@resources, fn resource ->
- group_names = resource.gateway_groups |> Enum.map(& &1.name_prefix)
+ group_names = resource.gateway_groups |> Enum.map(& &1.name)
[
key: "#{resource.name} - #{Enum.join(group_names, ",")}",
@@ -103,7 +103,7 @@ defmodule Web.Policies.New do
{:noreply,
push_navigate(socket, to: ~p"/#{socket.assigns.account}/sites/#{site_id}?#resources")}
else
- {:noreply, redirect(socket, to: ~p"/#{socket.assigns.account}/policies/#{policy}")}
+ {:noreply, push_navigate(socket, to: ~p"/#{socket.assigns.account}/policies/#{policy}")}
end
else
{:error, %Ecto.Changeset{} = changeset} ->
diff --git a/elixir/apps/web/lib/web/live/policies/show.ex b/elixir/apps/web/lib/web/live/policies/show.ex
index ad988c150..ef109d962 100644
--- a/elixir/apps/web/lib/web/live/policies/show.ex
+++ b/elixir/apps/web/lib/web/live/policies/show.ex
@@ -124,7 +124,7 @@ defmodule Web.Policies.Show do
<:col :let={flow} label="GATEWAY (IP)">
<.link navigate={~p"/#{@account}/gateways/#{flow.gateway_id}"} class={link_style()}>
- <%= flow.gateway.group.name_prefix %>-<%= flow.gateway.name_suffix %>
+ <%= flow.gateway.group.name %>-<%= flow.gateway.name %>
(<%= flow.gateway_remote_ip %>)
diff --git a/elixir/apps/web/lib/web/live/relay_groups/edit.ex b/elixir/apps/web/lib/web/live/relay_groups/edit.ex
index b0265d033..f825758eb 100644
--- a/elixir/apps/web/lib/web/live/relay_groups/edit.ex
+++ b/elixir/apps/web/lib/web/live/relay_groups/edit.ex
@@ -59,7 +59,7 @@ defmodule Web.RelayGroups.Edit do
def handle_event("submit", %{"group" => attrs}, socket) do
with {:ok, group} <-
Relays.update_group(socket.assigns.group, attrs, socket.assigns.subject) do
- socket = redirect(socket, to: ~p"/#{socket.assigns.account}/relay_groups/#{group}")
+ socket = push_navigate(socket, to: ~p"/#{socket.assigns.account}/relay_groups/#{group}")
{:noreply, socket}
else
{:error, changeset} ->
diff --git a/elixir/apps/web/lib/web/live/relay_groups/new.ex b/elixir/apps/web/lib/web/live/relay_groups/new.ex
index 934a4e231..adbafad90 100644
--- a/elixir/apps/web/lib/web/live/relay_groups/new.ex
+++ b/elixir/apps/web/lib/web/live/relay_groups/new.ex
@@ -4,7 +4,7 @@ defmodule Web.RelayGroups.New do
def mount(_params, _session, socket) do
changeset = Relays.new_group()
- {:ok, assign(socket, form: to_form(changeset), group: nil)}
+ {:ok, assign(socket, form: to_form(changeset))}
end
def render(assigns) do
@@ -14,15 +14,12 @@ defmodule Web.RelayGroups.New do
<.breadcrumb path={~p"/#{@account}/relay_groups/new"}>Add
<.section>
- <:title :if={is_nil(@group)}>
+ <:title>
Add a new Relay Instance Group
- <:title :if={not is_nil(@group)}>
- Deploy your Relay Instance
-
<:content>
- Copy-paste this command to your server and replace PUBLIC_IP4_ADDR
- and PUBLIC_IP6_ADDR
- with your public IP addresses:
-
- 1. Create a systemd unit file with the following content: -
- - <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo nano /etc/systemd/system/firezone-relay.service - -
- 2. Copy-paste the following content into the file and replace
- PUBLIC_IP4_ADDR
- and PUBLIC_IP6_ADDR
- with your public IP addresses::
-
- 3. Save by pressing Ctrl+X, then Y, then Enter. -
- -- 4. Reload systemd configuration: -
- - <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo systemctl daemon-reload - -- 5. Start the service: -
- - <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo systemctl start firezone-relay - -- 6. Enable the service to start on boot: -
- - <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo systemctl enable firezone-relay - -- 7. Check the status of the service: -
- - <.code_block id="code-sample-systemd" class="w-full rounded-b" phx-no-format>sudo systemctl status firezone-relay - - - -
+ Copy-paste this command to your server and replace PUBLIC_IP4_ADDR
+ and PUBLIC_IP6_ADDR
+ with your public IP addresses:
+
+ Troubleshooting +
+ ++ Check the container status: +
+ + <.code_block id="code-sample-docker2" class="w-full" phx-no-format>docker ps --filter "name=firezone-relay" + ++ Check the container logs: +
+ + <.code_block id="code-sample-docker3" class="w-full rounded-b" phx-no-format>docker logs firezone-relay + + <:tab id="systemd-instructions" label="Systemd"> ++ 1. Create a systemd unit file with the following content: +
+ + <.code_block id="code-sample-systemd1" class="w-full" phx-no-format>sudo nano /etc/systemd/system/firezone-relay.service + +
+ 2. Copy-paste the following content into the file and replace
+ PUBLIC_IP4_ADDR
+ and PUBLIC_IP6_ADDR
+ with your public IP addresses::
+
+ 3. Save by pressing Ctrl+X, then Y, then Enter. +
+ ++ 4. Reload systemd configuration: +
+ + <.code_block id="code-sample-systemd4" class="w-full" phx-no-format>sudo systemctl daemon-reload + ++ 5. Start the service: +
+ + <.code_block id="code-sample-systemd5" class="w-full" phx-no-format>sudo systemctl start firezone-relay + ++ 6. Enable the service to start on boot: +
+ + <.code_block id="code-sample-systemd6" class="w-full" phx-no-format>sudo systemctl enable firezone-relay + + <.initial_connection_status + :if={@env} + type="relay" + navigate={~p"/#{@account}/sites/#{@group}"} + connected?={@connected?} + /> + ++ Troubleshooting +
+ ++ Check the status of the service: +
+ + <.code_block id="code-sample-systemd7" class="w-full rounded-b" phx-no-format>sudo systemctl status firezone-relay + ++ Check the logs: +
+ + <.code_block id="code-sample-systemd8" class="w-full rounded-b" phx-no-format>sudo journalctl -u firezone-relay.service + + +
- <%= relay.ipv4 %>
-
-
- <%= relay.ipv6 %>
-
-
-
- <:col :let={relay} label="TOKEN CREATED AT">
- <.created_by account={@account} schema={relay.token} />
-
- <:col :let={relay} label="STATUS">
- <.connection_status schema={relay} />
-
- <:empty>
-
+ <%= relay.name %>
+
+
+ <%= relay.ipv4 %>
+
+
+ <%= relay.ipv6 %>
+
+
+
+ <:col :let={relay} label="TOKEN CREATED AT">
+ <.created_by account={@account} schema={relay.token} />
+
+ <:col :let={relay} label="STATUS">
+ <.connection_status schema={relay} />
+
+ <:empty>
+ <%= @group.name_prefix %>
+ <:title>Edit Site: <%= @group.name %>
<:content>
+ Troubleshooting +
+ ++ Check the container status: +
+ + <.code_block id="code-sample-docker2" class="w-full" phx-no-format>docker ps --filter "name=firezone-gateway" + ++ Check the container logs: +
+ + <.code_block id="code-sample-docker3" class="w-full rounded-b" phx-no-format>docker logs firezone-gateway <:tab id="systemd-instructions" label="Systemd">1. Create a systemd unit file with the following content:
- <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo nano /etc/systemd/system/firezone-gateway.service + <.code_block id="code-sample-systemd1" class="w-full" phx-no-format>sudo nano /etc/systemd/system/firezone-gateway.service2. Copy-paste the following content into the file:
- <.code_block id="code-sample-systemd" class="w-full rounded-b" phx-no-format><%= systemd_command(@env) %> + <.code_block id="code-sample-systemd2" class="w-full rounded-b" phx-no-format><%= systemd_command(@env) %>3. Save by pressing Ctrl+X, then Y, then Enter. @@ -74,31 +96,46 @@ defmodule Web.Sites.NewToken do 4. Reload systemd configuration:
- <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo systemctl daemon-reload + <.code_block id="code-sample-systemd4" class="w-full" phx-no-format>sudo systemctl daemon-reload5. Start the service:
- <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo systemctl start firezone-gateway + <.code_block id="code-sample-systemd5" class="w-full" phx-no-format>sudo systemctl start firezone-gateway6. Enable the service to start on boot:
- <.code_block id="code-sample-systemd" class="w-full" phx-no-format>sudo systemctl enable firezone-gateway + <.code_block id="code-sample-systemd6" class="w-full" phx-no-format>sudo systemctl enable firezone-gateway -- 7. Check the status of the service: + <.initial_connection_status + :if={@env} + type="gateway" + navigate={~p"/#{@account}/sites/#{@group}"} + connected?={@connected?} + /> + +
+ Troubleshooting
- <.code_block id="code-sample-systemd" class="w-full rounded-b" phx-no-format>sudo systemctl status firezone-gateway ++ Check the status of the service: +
+ + <.code_block id="code-sample-systemd7" class="w-full rounded-b" phx-no-format>sudo systemctl status firezone-gateway + ++ Check the logs: +
+ + <.code_block id="code-sample-systemd8" class="w-full rounded-b" phx-no-format>sudo journalctl -u firezone-gateway.service - -<%= @group.name_prefix %>
+ Site: <%= @group.name %>
<:action>
<.edit_button navigate={~p"/#{@account}/sites/#{@group}/edit"}>
@@ -49,7 +52,7 @@ defmodule Web.Sites.Show do
<.vertical_table id="group">
<.vertical_table_row>
<:label>Name
- <:value><%= @group.name_prefix %>
+ <:value><%= @group.name %>
<.vertical_table_row>
<:label>Created
@@ -76,7 +79,7 @@ defmodule Web.Sites.Show do
navigate={~p"/#{@account}/gateways/#{gateway.id}"}
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>
- <%= gateway.name_suffix %>
+ <%= gateway.name %>
<:col :let={gateway} label="REMOTE IP">
@@ -217,7 +220,7 @@ defmodule Web.Sites.Show do
def handle_info(%Phoenix.Socket.Broadcast{topic: "gateway_groups:" <> _account_id}, socket) do
socket =
- redirect(socket, to: ~p"/#{socket.assigns.account}/sites/#{socket.assigns.group}")
+ push_navigate(socket, to: ~p"/#{socket.assigns.account}/sites/#{socket.assigns.group}")
{:noreply, socket}
end
@@ -225,6 +228,6 @@ defmodule Web.Sites.Show do
def handle_event("delete", _params, socket) do
# TODO: make sure tokens are all deleted too!
{:ok, _group} = Gateways.delete_group(socket.assigns.group, socket.assigns.subject)
- {:noreply, redirect(socket, to: ~p"/#{socket.assigns.account}/sites")}
+ {:noreply, push_navigate(socket, to: ~p"/#{socket.assigns.account}/sites")}
end
end
diff --git a/elixir/apps/web/lib/web/router.ex b/elixir/apps/web/lib/web/router.ex
index b97a80cdc..85906b484 100644
--- a/elixir/apps/web/lib/web/router.ex
+++ b/elixir/apps/web/lib/web/router.ex
@@ -22,6 +22,14 @@ defmodule Web.Router do
plug :accepts, ["html", "xml"]
end
+ pipeline :home do
+ plug :accepts, ["html", "xml"]
+ plug :fetch_session
+ plug :protect_from_forgery
+ plug :fetch_live_flash
+ plug :put_root_layout, {Web.Layouts, :root}
+ end
+
pipeline :ensure_authenticated_admin do
plug :ensure_authenticated
plug :ensure_authenticated_actor_type, :account_admin_user
@@ -33,10 +41,16 @@ defmodule Web.Router do
get "/config.xml", BrowserController, :config
end
+ scope "/", Web do
+ pipe_through :home
+
+ get "/", HomeController, :home
+ post "/", HomeController, :redirect_to_sign_in
+ end
+
scope "/", Web do
pipe_through :public
- get "/", RedirectController, :home
get "/healthz", HealthController, :healthz
end
@@ -61,11 +75,11 @@ defmodule Web.Router do
Web.Sandbox,
{Web.Auth, :redirect_if_user_is_authenticated}
] do
- live "/", Auth.SignIn
+ live "/", SignIn
# Adapter-specific routes
## Email
- live "/sign_in/providers/email/:provider_id", Auth.Email
+ live "/sign_in/providers/email/:provider_id", SignIn.Email
end
scope "/sign_in/providers/:provider_id" do
@@ -137,6 +151,7 @@ defmodule Web.Router do
live "/", Index
live "/new", New
live "/:id/edit", Edit
+ live "/:id/new_token", NewToken
live "/:id", Show
end
diff --git a/elixir/apps/web/test/web/acceptance/auth/email_test.exs b/elixir/apps/web/test/web/acceptance/auth/email_test.exs
index 84d5f2f9e..96d35bbc0 100644
--- a/elixir/apps/web/test/web/acceptance/auth/email_test.exs
+++ b/elixir/apps/web/test/web/acceptance/auth/email_test.exs
@@ -1,4 +1,4 @@
-defmodule Web.Acceptance.Auth.EmailTest do
+defmodule Web.Acceptance.SignIn.EmailTest do
use Web.AcceptanceCase, async: true
feature "renders success on invalid email to prevent enumeration attacks", %{session: session} do
diff --git a/elixir/apps/web/test/web/auth_test.exs b/elixir/apps/web/test/web/auth_test.exs
index ba0f78cd5..26beb2192 100644
--- a/elixir/apps/web/test/web/auth_test.exs
+++ b/elixir/apps/web/test/web/auth_test.exs
@@ -52,10 +52,12 @@ defmodule Web.AuthTest do
describe "signed_in_redirect/4" do
test "redirects regular users to the platform url", %{conn: conn, user_subject: subject} do
redirected_to = conn |> signed_in_redirect(subject, "apple", "foo") |> redirected_to()
- assert redirected_to =~ "firezone://handle_client_auth_callback?client_csrf_token=foo"
+ assert redirected_to =~ "firezone://handle_client_auth_callback"
+ assert redirected_to =~ "client_csrf_token=foo"
redirected_to = conn |> signed_in_redirect(subject, "android", "foo") |> redirected_to()
- assert redirected_to =~ "/handle_client_auth_callback?client_csrf_token=foo"
+ assert redirected_to =~ "/handle_client_auth_callback?"
+ assert redirected_to =~ "client_csrf_token=foo"
end
test "redirects regular users to sign in if platform url is missing", %{
@@ -73,10 +75,12 @@ defmodule Web.AuthTest do
test "redirects admin user to the platform url", %{conn: conn, admin_subject: subject} do
redirected_to = conn |> signed_in_redirect(subject, "apple", "foo") |> redirected_to()
- assert redirected_to =~ "firezone://handle_client_auth_callback?client_csrf_token=foo"
+ assert redirected_to =~ "firezone://handle_client_auth_callback?"
+ assert redirected_to =~ "client_csrf_token=foo"
redirected_to = conn |> signed_in_redirect(subject, "android", "foo") |> redirected_to()
- assert redirected_to =~ "/handle_client_auth_callback?client_csrf_token=foo"
+ assert redirected_to =~ "/handle_client_auth_callback?"
+ assert redirected_to =~ "client_csrf_token=foo"
end
test "redirects admin user to the post-login path if platform url is missing", %{
diff --git a/elixir/apps/web/test/web/controllers/auth_controller_test.exs b/elixir/apps/web/test/web/controllers/auth_controller_test.exs
index fa96047d7..f149ade99 100644
--- a/elixir/apps/web/test/web/controllers/auth_controller_test.exs
+++ b/elixir/apps/web/test/web/controllers/auth_controller_test.exs
@@ -1182,9 +1182,6 @@ defmodule Web.AuthControllerTest do
assert redirected_to(conn) == url(~p"/#{account}")
assert conn.private.plug_session == %{"preferred_locale" => "en_US"}
-
- assert %{"fz_recent_account_ids" => fz_recent_account_ids} = conn.cookies
- assert :erlang.binary_to_term(fz_recent_account_ids) == []
end
test "redirects to the IdP sign out page", %{conn: conn} do
@@ -1229,7 +1226,7 @@ defmodule Web.AuthControllerTest do
assert_receive %Phoenix.Socket.Broadcast{event: "disconnect", topic: ^live_socket_id}
end
- test "removes current account id from list of recent ones", %{conn: conn} do
+ test "does not remove current account id from list of recent ones", %{conn: conn} do
Domain.Config.put_system_env_override(:outbound_email_adapter, Swoosh.Adapters.Postmark)
account = Fixtures.Accounts.create_account()
@@ -1270,8 +1267,7 @@ defmodule Web.AuthControllerTest do
assert redirected_to(conn) == url(~p"/#{account}")
assert conn.private.plug_session == %{"preferred_locale" => "en_US"}
- assert %{"fz_recent_account_ids" => fz_recent_account_ids} = conn.cookies
- assert :erlang.binary_to_term(fz_recent_account_ids) == []
+ assert %{"fz_recent_account_ids" => ^signed_state} = conn.cookies
end
test "works even if user is already logged out", %{conn: conn} do
diff --git a/elixir/apps/web/test/web/controllers/home_controller_test.exs b/elixir/apps/web/test/web/controllers/home_controller_test.exs
new file mode 100644
index 000000000..939fbcd3b
--- /dev/null
+++ b/elixir/apps/web/test/web/controllers/home_controller_test.exs
@@ -0,0 +1,57 @@
+defmodule Web.HomeControllerTest do
+ use Web.ConnCase, async: true
+
+ describe "home/2" do
+ test "renders the form to find the account sign in page", %{conn: conn} do
+ conn = get(conn, ~p"/")
+ html = response(conn, 200)
+
+ assert html =~ "Account ID or Slug"
+ assert html =~ "Go to Sign In page"
+ end
+
+ test "renders recently used account", %{conn: conn} do
+ accounts = [
+ Fixtures.Accounts.create_account(),
+ Fixtures.Accounts.create_account()
+ ]
+
+ conn = get(conn, ~p"/")
+ html = response(conn, 200)
+
+ for account <- accounts do
+ refute html =~ account.name
+ refute html =~ ~p"/#{account.slug}"
+ end
+
+ account_ids =
+ accounts
+ |> Enum.map(& &1.id)
+ |> :erlang.term_to_binary()
+
+ %{resp_cookies: %{"fz_recent_account_ids" => %{value: value}}} =
+ %{build_conn() | secret_key_base: Web.Endpoint.config(:secret_key_base)}
+ |> put_resp_cookie("fz_recent_account_ids", account_ids, sign: true, secure: true)
+
+ conn =
+ build_conn()
+ |> put_req_cookie("fz_recent_account_ids", value)
+ |> get(~p"/")
+
+ html = response(conn, 200)
+
+ for account <- accounts do
+ assert html =~ account.name
+ assert html =~ ~p"/#{account.slug}"
+ end
+ end
+ end
+
+ describe "redirect_to_sign_in/2" do
+ test "redirects to the sign in page", %{conn: conn} do
+ id = Ecto.UUID.generate()
+ conn = post(conn, ~p"/", %{"account_id_or_slug" => id})
+ assert redirected_to(conn) == ~p"/#{id}"
+ end
+ end
+end
diff --git a/elixir/apps/web/test/web/live/actors/edit_test.exs b/elixir/apps/web/test/web/live/actors/edit_test.exs
index 2a9966990..33e0a6e06 100644
--- a/elixir/apps/web/test/web/live/actors/edit_test.exs
+++ b/elixir/apps/web/test/web/live/actors/edit_test.exs
@@ -197,10 +197,11 @@ defmodule Web.Live.Actors.EditTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/actors/#{actor}/edit")
- assert lv
- |> form("form", actor: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/actors/#{actor}"}}}
+ lv
+ |> form("form", actor: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/actors/#{actor}")
assert actor = Repo.get_by(Domain.Actors.Actor, id: actor.id) |> Repo.preload(:memberships)
assert actor.name == attrs.name
@@ -375,10 +376,11 @@ defmodule Web.Live.Actors.EditTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/actors/#{actor}/edit")
- assert lv
- |> form("form", actor: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/actors/#{actor}"}}}
+ lv
+ |> form("form", actor: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/actors/#{actor}")
assert actor = Repo.get_by(Domain.Actors.Actor, id: actor.id) |> Repo.preload(:memberships)
assert actor.name == attrs.name
diff --git a/elixir/apps/web/test/web/live/actors/show_test.exs b/elixir/apps/web/test/web/live/actors/show_test.exs
index 6cef3f6fe..6058acf9f 100644
--- a/elixir/apps/web/test/web/live/actors/show_test.exs
+++ b/elixir/apps/web/test/web/live/actors/show_test.exs
@@ -46,6 +46,45 @@ defmodule Web.Live.Actors.ShowTest do
assert breadcrumbs =~ actor.name
end
+ test "renders logs table", %{
+ conn: conn
+ } do
+ account = Fixtures.Accounts.create_account()
+ actor = Fixtures.Actors.create_actor(type: :account_admin_user, account: account)
+ identity = Fixtures.Auth.create_identity(account: account, actor: actor)
+ client = Fixtures.Clients.create_client(account: account, actor: actor)
+
+ flow =
+ Fixtures.Flows.create_flow(
+ account: account,
+ client: client
+ )
+
+ flow = Repo.preload(flow, [:client, gateway: [:group], policy: [:actor_group, :resource]])
+
+ {:ok, lv, _html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/actors/#{actor}")
+
+ [row] =
+ lv
+ |> element("#flows")
+ |> render()
+ |> table_to_map()
+
+ assert row["authorized at"]
+ assert row["expires at"]
+ assert row["policy"] =~ flow.policy.actor_group.name
+ assert row["policy"] =~ flow.policy.resource.name
+
+ assert row["client (ip)"] ==
+ "#{flow.client.name} (#{client.last_seen_remote_ip})"
+
+ assert row["gateway (ip)"] ==
+ "#{flow.gateway.group.name}-#{flow.gateway.name} (189.172.73.153)"
+ end
+
describe "users" do
setup do
account = Fixtures.Accounts.create_account()
@@ -59,6 +98,30 @@ defmodule Web.Live.Actors.ShowTest do
}
end
+ test "renders (you) next to subject actor title", %{
+ account: account,
+ actor: actor,
+ identity: identity,
+ conn: conn
+ } do
+ {:ok, _lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/actors/#{actor}")
+
+ assert html =~ "(you)"
+
+ other_actor = Fixtures.Actors.create_actor(type: :account_admin_user, account: account)
+ identity = Fixtures.Auth.create_identity(account: account, actor: other_actor)
+
+ {:ok, _lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/actors/#{actor}")
+
+ refute html =~ "(you)"
+ end
+
test "renders actor details", %{
account: account,
actor: actor,
@@ -73,6 +136,7 @@ defmodule Web.Live.Actors.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/actors/#{actor}")
+ assert html =~ actor.name
assert html =~ "User"
table =
diff --git a/elixir/apps/web/test/web/live/clients/edit_test.exs b/elixir/apps/web/test/web/live/clients/edit_test.exs
index 04adc59e2..b770a8a3d 100644
--- a/elixir/apps/web/test/web/live/clients/edit_test.exs
+++ b/elixir/apps/web/test/web/live/clients/edit_test.exs
@@ -144,10 +144,11 @@ defmodule Web.Live.Clients.EditTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/clients/#{client}/edit")
- assert lv
- |> form("form", client: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/clients/#{client}"}}}
+ lv
+ |> form("form", client: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/clients/#{client}")
assert client = Repo.get_by(Domain.Clients.Client, id: client.id)
assert client.name == attrs.name
diff --git a/elixir/apps/web/test/web/live/clients/show_test.exs b/elixir/apps/web/test/web/live/clients/show_test.exs
index 9394a4bf6..f1c151089 100644
--- a/elixir/apps/web/test/web/live/clients/show_test.exs
+++ b/elixir/apps/web/test/web/live/clients/show_test.exs
@@ -144,7 +144,7 @@ defmodule Web.Live.Clients.ShowTest do
assert row["policy"] =~ flow.policy.resource.name
assert row["gateway (ip)"] ==
- "#{flow.gateway.group.name_prefix}-#{flow.gateway.name_suffix} (189.172.73.153)"
+ "#{flow.gateway.group.name}-#{flow.gateway.name} (189.172.73.153)"
end
test "allows editing clients", %{
@@ -176,10 +176,11 @@ defmodule Web.Live.Clients.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/clients/#{client}")
- assert lv
- |> element("button", "Delete Client")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/clients"}}}
+ lv
+ |> element("button", "Delete Client")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/clients")
assert Repo.get(Domain.Clients.Client, client.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/gateways/show_test.exs b/elixir/apps/web/test/web/live/gateways/show_test.exs
index 06a564fa6..381141d57 100644
--- a/elixir/apps/web/test/web/live/gateways/show_test.exs
+++ b/elixir/apps/web/test/web/live/gateways/show_test.exs
@@ -62,8 +62,8 @@ defmodule Web.Live.Gateways.ShowTest do
assert item = Floki.find(html, "[aria-label='Breadcrumb']")
breadcrumbs = String.trim(Floki.text(item))
assert breadcrumbs =~ "Sites"
- assert breadcrumbs =~ gateway.group.name_prefix
- assert breadcrumbs =~ gateway.name_suffix
+ assert breadcrumbs =~ gateway.group.name
+ assert breadcrumbs =~ gateway.name
end
test "renders gateway details", %{
@@ -83,8 +83,8 @@ defmodule Web.Live.Gateways.ShowTest do
|> render()
|> vertical_table_to_map()
- assert table["site"] =~ gateway.group.name_prefix
- assert table["instance name"] =~ gateway.name_suffix
+ assert table["site"] =~ gateway.group.name
+ assert table["name"] =~ gateway.name
assert table["last seen"]
assert table["last seen remote ip"] =~ to_string(gateway.last_seen_remote_ip)
assert table["status"] =~ "Offline"
@@ -162,10 +162,11 @@ defmodule Web.Live.Gateways.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/gateways/#{gateway}")
- assert lv
- |> element("button", "Delete Gateway")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/sites/#{gateway.group}"}}}
+ lv
+ |> element("button", "Delete Gateway")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/sites/#{gateway.group}")
assert Repo.get(Domain.Gateways.Gateway, gateway.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/groups/edit_actors_test.exs b/elixir/apps/web/test/web/live/groups/edit_actors_test.exs
index cb87bfc09..a16ebdb6b 100644
--- a/elixir/apps/web/test/web/live/groups/edit_actors_test.exs
+++ b/elixir/apps/web/test/web/live/groups/edit_actors_test.exs
@@ -211,9 +211,11 @@ defmodule Web.Live.Groups.EditActorsTest do
|> element("#actor-#{service_account.id} button", "Add")
|> render_click()
- assert lv
- |> element("button", "Save")
- |> render_click() == {:error, {:redirect, %{to: ~p"/#{account}/groups/#{group}"}}}
+ lv
+ |> element("button", "Save")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/groups/#{group}")
group = Repo.preload(group, :actors, force: true)
group_actor_ids = Enum.map(group.actors, & &1.id)
diff --git a/elixir/apps/web/test/web/live/groups/edit_test.exs b/elixir/apps/web/test/web/live/groups/edit_test.exs
index aba88110e..ecbc2d725 100644
--- a/elixir/apps/web/test/web/live/groups/edit_test.exs
+++ b/elixir/apps/web/test/web/live/groups/edit_test.exs
@@ -167,10 +167,11 @@ defmodule Web.Live.Groups.EditTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/groups/#{group}/edit")
- assert lv
- |> form("form", group: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/groups/#{group}"}}}
+ lv
+ |> form("form", group: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/groups/#{group}")
assert group = Repo.get_by(Domain.Actors.Group, id: group.id)
assert group.name == attrs.name
diff --git a/elixir/apps/web/test/web/live/groups/new_test.exs b/elixir/apps/web/test/web/live/groups/new_test.exs
index eb61e8b16..901f163a1 100644
--- a/elixir/apps/web/test/web/live/groups/new_test.exs
+++ b/elixir/apps/web/test/web/live/groups/new_test.exs
@@ -118,14 +118,13 @@ defmodule Web.Live.Groups.NewTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/groups/new")
- result =
- lv
- |> form("form", group: attrs)
- |> render_submit()
+ lv
+ |> form("form", group: attrs)
+ |> render_submit()
assert group = Repo.get_by(Domain.Actors.Group, name: attrs.name)
- assert result == {:error, {:redirect, %{to: ~p"/#{account}/groups/#{group}/edit_actors"}}}
+ assert_redirected(lv, ~p"/#{account}/groups/#{group}/edit_actors")
assert group.name == attrs.name
refute group.provider_id
diff --git a/elixir/apps/web/test/web/live/groups/show_test.exs b/elixir/apps/web/test/web/live/groups/show_test.exs
index 57efb11f8..eecc8e018 100644
--- a/elixir/apps/web/test/web/live/groups/show_test.exs
+++ b/elixir/apps/web/test/web/live/groups/show_test.exs
@@ -275,10 +275,11 @@ defmodule Web.Live.Groups.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/groups/#{group}")
- assert lv
- |> element("button", "Delete Group")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/groups"}}}
+ lv
+ |> element("button", "Delete Group")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/groups")
assert Repo.get(Domain.Actors.Group, group.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/policies/edit_test.exs b/elixir/apps/web/test/web/live/policies/edit_test.exs
index 3b4d45a2d..f87321241 100644
--- a/elixir/apps/web/test/web/live/policies/edit_test.exs
+++ b/elixir/apps/web/test/web/live/policies/edit_test.exs
@@ -146,10 +146,11 @@ defmodule Web.Live.Policies.EditTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/policies/#{policy}/edit")
- assert lv
- |> form("form", policy: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/policies/#{policy}"}}}
+ lv
+ |> form("form", policy: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/policies/#{policy}")
assert policy = Repo.get_by(Domain.Policies.Policy, id: policy.id)
assert policy.description == attrs.description
diff --git a/elixir/apps/web/test/web/live/policies/show_test.exs b/elixir/apps/web/test/web/live/policies/show_test.exs
index 743571a1d..0a9775bd4 100644
--- a/elixir/apps/web/test/web/live/policies/show_test.exs
+++ b/elixir/apps/web/test/web/live/policies/show_test.exs
@@ -157,7 +157,7 @@ defmodule Web.Live.Policies.ShowTest do
assert row["client, actor (ip)"] =~ to_string(flow.client_remote_ip)
assert row["gateway (ip)"] =~
- "#{flow.gateway.group.name_prefix}-#{flow.gateway.name_suffix} (189.172.73.153)"
+ "#{flow.gateway.group.name}-#{flow.gateway.name} (189.172.73.153)"
end
test "allows deleting policy", %{
diff --git a/elixir/apps/web/test/web/live/relay_groups/edit_test.exs b/elixir/apps/web/test/web/live/relay_groups/edit_test.exs
index 7375e644a..7b1594abb 100644
--- a/elixir/apps/web/test/web/live/relay_groups/edit_test.exs
+++ b/elixir/apps/web/test/web/live/relay_groups/edit_test.exs
@@ -143,10 +143,11 @@ defmodule Web.Live.RelayGroups.EditTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/relay_groups/#{group}/edit")
- assert lv
- |> form("form", group: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/relay_groups/#{group}"}}}
+ lv
+ |> form("form", group: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/relay_groups/#{group}")
assert group = Repo.get_by(Domain.Relays.Group, id: group.id)
assert group.name == attrs.name
diff --git a/elixir/apps/web/test/web/live/relay_groups/new_test.exs b/elixir/apps/web/test/web/live/relay_groups/new_test.exs
index 9105b6511..14a5a9937 100644
--- a/elixir/apps/web/test/web/live/relay_groups/new_test.exs
+++ b/elixir/apps/web/test/web/live/relay_groups/new_test.exs
@@ -113,22 +113,11 @@ defmodule Web.Live.RelayGroups.NewTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/relay_groups/new")
- html =
- lv
- |> form("form", group: attrs)
- |> render_submit()
+ lv
+ |> form("form", group: attrs)
+ |> render_submit()
- assert html =~ "Select deployment method"
- assert html =~ "FIREZONE_TOKEN="
- assert html =~ "docker run"
- assert html =~ "Waiting for relay connection..."
-
- token = Regex.run(~r/FIREZONE_TOKEN="([^ ]+)"/, html) |> List.last()
- assert {:ok, _token} = Domain.Relays.authorize_relay(token)
-
- group = Repo.get_by(Domain.Relays.Group, name: attrs.name) |> Repo.preload(:tokens)
- relay = Fixtures.Relays.create_relay(account: account, group: group)
- Domain.Relays.connect_relay(relay, "foo")
+ group = Repo.get_by(Domain.Relays.Group, name: attrs.name)
assert assert_redirect(lv, ~p"/#{account}/relay_groups/#{group}")
end
diff --git a/elixir/apps/web/test/web/live/relay_groups/new_token_test.exs b/elixir/apps/web/test/web/live/relay_groups/new_token_test.exs
new file mode 100644
index 000000000..036def1a1
--- /dev/null
+++ b/elixir/apps/web/test/web/live/relay_groups/new_token_test.exs
@@ -0,0 +1,49 @@
+defmodule Web.Live.RelayGroups.NewTokenTest do
+ use Web.ConnCase, async: true
+
+ setup do
+ account = Fixtures.Accounts.create_account()
+ actor = Fixtures.Actors.create_actor(type: :account_admin_user, account: account)
+ identity = Fixtures.Auth.create_identity(account: account, actor: actor)
+ group = Fixtures.Relays.create_group(account: account)
+
+ %{
+ account: account,
+ actor: actor,
+ identity: identity,
+ group: group
+ }
+ end
+
+ test "creates a new group on valid attrs and redirects when relay is connected", %{
+ account: account,
+ identity: identity,
+ group: group,
+ conn: conn
+ } do
+ {:ok, lv, html} =
+ conn
+ |> authorize_conn(identity)
+ |> live(~p"/#{account}/relay_groups/#{group}/new_token")
+
+ assert html =~ "Select deployment method"
+ assert html =~ "FIREZONE_TOKEN="
+ assert html =~ "PUBLIC_IP4_ADDR="
+ assert html =~ "PUBLIC_IP6_ADDR="
+ assert html =~ "docker run"
+ assert html =~ "Waiting for connection..."
+
+ assert Regex.run(~r/FIREZONE_ID=([^ ]+)/, html) |> List.last()
+ token = Regex.run(~r/FIREZONE_TOKEN=([^ ]+)/, html) |> List.last() |> String.trim(""")
+
+ :ok = Domain.Relays.subscribe_for_relays_presence_in_group(group)
+ relay = Fixtures.Relays.create_relay(account: account, group: group)
+ assert {:ok, _token} = Domain.Relays.authorize_relay(token)
+ Domain.Relays.connect_relay(relay, "foo")
+
+ assert_receive %Phoenix.Socket.Broadcast{topic: "relay_groups:" <> _group_id}
+
+ assert element(lv, "#deployment-instructions")
+ |> render() =~ "Connected, click to continue"
+ end
+end
diff --git a/elixir/apps/web/test/web/live/relay_groups/show_test.exs b/elixir/apps/web/test/web/live/relay_groups/show_test.exs
index 50bb1d57e..22bf347f9 100644
--- a/elixir/apps/web/test/web/live/relay_groups/show_test.exs
+++ b/elixir/apps/web/test/web/live/relay_groups/show_test.exs
@@ -164,10 +164,11 @@ defmodule Web.Live.RelayGroups.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/relay_groups/#{group}")
- assert lv
- |> element("button", "Delete")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/relay_groups"}}}
+ lv
+ |> element("button", "Delete")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/relay_groups")
assert Repo.get(Domain.Relays.Group, group.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/relays/show_test.exs b/elixir/apps/web/test/web/live/relays/show_test.exs
index b33546ddb..7d617d2cb 100644
--- a/elixir/apps/web/test/web/live/relays/show_test.exs
+++ b/elixir/apps/web/test/web/live/relays/show_test.exs
@@ -126,10 +126,11 @@ defmodule Web.Live.Relays.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/relays/#{relay}")
- assert lv
- |> element("button", "Delete Relay")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/relay_groups/#{relay.group}"}}}
+ lv
+ |> element("button", "Delete Relay")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/relay_groups/#{relay.group}")
assert Repo.get(Domain.Relays.Relay, relay.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/resources/index_test.exs b/elixir/apps/web/test/web/live/resources/index_test.exs
index cfc0c5d63..86a4a7077 100644
--- a/elixir/apps/web/test/web/live/resources/index_test.exs
+++ b/elixir/apps/web/test/web/live/resources/index_test.exs
@@ -77,7 +77,7 @@ defmodule Web.Live.Resources.IndexTest do
Enum.each(resource_rows, fn row ->
assert row["name"] =~ resource.name
assert row["address"] =~ resource.address
- assert row["sites"] =~ group.name_prefix
+ assert row["sites"] =~ group.name
assert row["authorized groups"] == "None, create a Policy to grant access."
end)
end
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 a2a4fcbe5..46ae27de4 100644
--- a/elixir/apps/web/test/web/live/resources/show_test.exs
+++ b/elixir/apps/web/test/web/live/resources/show_test.exs
@@ -197,7 +197,7 @@ defmodule Web.Live.Resources.ShowTest do
|> table_to_map()
for gateway_group <- gateway_groups do
- assert gateway_group["name"] =~ group.name_prefix
+ assert gateway_group["name"] =~ group.name
# TODO: check that status is being rendered
end
end
@@ -234,7 +234,7 @@ defmodule Web.Live.Resources.ShowTest do
assert row["policy"] =~ flow.policy.resource.name
assert row["gateway (ip)"] ==
- "#{flow.gateway.group.name_prefix}-#{flow.gateway.name_suffix} (189.172.73.153)"
+ "#{flow.gateway.group.name}-#{flow.gateway.name} (189.172.73.153)"
assert row["client, actor (ip)"] =~ flow.client.name
assert row["client, actor (ip)"] =~ "owned by #{flow.client.actor.name}"
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/edit_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/edit_test.exs
index 50843e4ea..29b98df85 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/edit_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/edit_test.exs
@@ -99,16 +99,13 @@ defmodule Web.Live.Settings.IdentityProviders.GoogleWorkspace.EditTest do
}
)
- result = render_submit(form)
+ render_submit(form)
assert provider = Repo.get_by(Domain.Auth.Provider, name: provider_attrs.name)
- assert result ==
- {:error,
- {:redirect,
- %{
- to:
- ~p"/#{account.id}/settings/identity_providers/google_workspace/#{provider}/redirect"
- }}}
+ assert_redirected(
+ lv,
+ ~p"/#{account.id}/settings/identity_providers/google_workspace/#{provider}/redirect"
+ )
assert provider.name == provider_attrs.name
assert provider.adapter == :google_workspace
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/new_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/new_test.exs
index b3ac69eda..512958649 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/new_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/new_test.exs
@@ -86,16 +86,13 @@ defmodule Web.Live.Settings.IdentityProviders.GoogleWorkspace.NewTest do
}
)
- result = render_submit(form)
+ render_submit(form)
assert provider = Repo.get_by(Domain.Auth.Provider, name: provider_attrs.name)
- assert result ==
- {:error,
- {:redirect,
- %{
- to:
- ~p"/#{account.id}/settings/identity_providers/google_workspace/#{provider}/redirect"
- }}}
+ assert_redirected(
+ lv,
+ ~p"/#{account.id}/settings/identity_providers/google_workspace/#{provider}/redirect"
+ )
assert provider.name == provider_attrs.name
assert provider.adapter == :google_workspace
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/show_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/show_test.exs
index 166746ab3..74b41f4dd 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/show_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/google_workspace/show_test.exs
@@ -215,10 +215,11 @@ defmodule Web.Live.Settings.IdentityProviders.GoogleWorkspace.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/settings/identity_providers/google_workspace/#{provider}")
- assert lv
- |> element("button", "Delete Identity Provider")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/settings/identity_providers"}}}
+ lv
+ |> element("button", "Delete Identity Provider")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/settings/identity_providers")
assert Repo.get(Domain.Auth.Provider, provider.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/edit_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/edit_test.exs
index 2c06c48f4..00eab3a35 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/edit_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/edit_test.exs
@@ -94,16 +94,13 @@ defmodule Web.Live.Settings.IdentityProviders.OpenIDConnect.EditTest do
}
)
- result = render_submit(form)
+ render_submit(form)
assert provider = Repo.get_by(Domain.Auth.Provider, name: provider_attrs.name)
- assert result ==
- {:error,
- {:redirect,
- %{
- to:
- ~p"/#{account.id}/settings/identity_providers/openid_connect/#{provider}/redirect"
- }}}
+ assert_redirected(
+ lv,
+ ~p"/#{account.id}/settings/identity_providers/openid_connect/#{provider}/redirect"
+ )
assert provider.name == provider_attrs.name
assert provider.adapter == :openid_connect
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/new_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/new_test.exs
index 214d33555..4d8b92e74 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/new_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/new_test.exs
@@ -88,16 +88,13 @@ defmodule Web.Live.Settings.IdentityProviders.OpenIDConnect.NewTest do
}
)
- result = render_submit(form)
+ render_submit(form)
assert provider = Repo.get_by(Domain.Auth.Provider, name: provider_attrs.name)
- assert result ==
- {:error,
- {:redirect,
- %{
- to:
- ~p"/#{account.id}/settings/identity_providers/openid_connect/#{provider}/redirect"
- }}}
+ assert_redirected(
+ lv,
+ ~p"/#{account.id}/settings/identity_providers/openid_connect/#{provider}/redirect"
+ )
assert provider.name == provider_attrs.name
assert provider.adapter == :openid_connect
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/show_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/show_test.exs
index 6e365f51f..dd0df3e45 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/show_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/openid_connect/show_test.exs
@@ -154,10 +154,11 @@ defmodule Web.Live.Settings.IdentityProviders.OpenIDConnect.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/settings/identity_providers/openid_connect/#{provider}")
- assert lv
- |> element("button", "Delete Identity Provider")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/settings/identity_providers"}}}
+ lv
+ |> element("button", "Delete Identity Provider")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/settings/identity_providers")
assert Repo.get(Domain.Auth.Provider, provider.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/settings/identity_providers/system/show_test.exs b/elixir/apps/web/test/web/live/settings/identity_providers/system/show_test.exs
index d3c210395..488bf5858 100644
--- a/elixir/apps/web/test/web/live/settings/identity_providers/system/show_test.exs
+++ b/elixir/apps/web/test/web/live/settings/identity_providers/system/show_test.exs
@@ -145,10 +145,11 @@ defmodule Web.Live.Settings.IdentityProviders.System.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/settings/identity_providers/system/#{provider}")
- assert lv
- |> element("button", "Delete Identity Provider")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/settings/identity_providers"}}}
+ lv
+ |> element("button", "Delete Identity Provider")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/settings/identity_providers")
assert Repo.get(Domain.Auth.Provider, provider.id).deleted_at
end
diff --git a/elixir/apps/web/test/web/live/auth/email_test.exs b/elixir/apps/web/test/web/live/sign_in/email_test.exs
similarity index 99%
rename from elixir/apps/web/test/web/live/auth/email_test.exs
rename to elixir/apps/web/test/web/live/sign_in/email_test.exs
index 2755a3d8e..35ab3016b 100644
--- a/elixir/apps/web/test/web/live/auth/email_test.exs
+++ b/elixir/apps/web/test/web/live/sign_in/email_test.exs
@@ -1,4 +1,4 @@
-defmodule Web.Auth.EmailTest do
+defmodule Web.SignIn.EmailTest do
use Web.ConnCase, async: true
setup do
diff --git a/elixir/apps/web/test/web/live/auth/sign_in_test.exs b/elixir/apps/web/test/web/live/sign_in_test.exs
similarity index 98%
rename from elixir/apps/web/test/web/live/auth/sign_in_test.exs
rename to elixir/apps/web/test/web/live/sign_in_test.exs
index e2cc86dc9..bcecadc48 100644
--- a/elixir/apps/web/test/web/live/auth/sign_in_test.exs
+++ b/elixir/apps/web/test/web/live/sign_in_test.exs
@@ -1,4 +1,4 @@
-defmodule Web.Auth.SignInTest do
+defmodule Web.SignInTest do
use Web.ConnCase, async: true
test "renders active providers on the page", %{conn: conn} do
diff --git a/elixir/apps/web/test/web/live/sign_up/sign_up_test.exs b/elixir/apps/web/test/web/live/sign_up_test.exs
similarity index 100%
rename from elixir/apps/web/test/web/live/sign_up/sign_up_test.exs
rename to elixir/apps/web/test/web/live/sign_up_test.exs
diff --git a/elixir/apps/web/test/web/live/sites/edit_test.exs b/elixir/apps/web/test/web/live/sites/edit_test.exs
index 8f2a34f94..600b4cfec 100644
--- a/elixir/apps/web/test/web/live/sites/edit_test.exs
+++ b/elixir/apps/web/test/web/live/sites/edit_test.exs
@@ -59,7 +59,7 @@ defmodule Web.Live.Sites.EditTest do
assert item = Floki.find(html, "[aria-label='Breadcrumb']")
breadcrumbs = String.trim(Floki.text(item))
assert breadcrumbs =~ "Sites"
- assert breadcrumbs =~ group.name_prefix
+ assert breadcrumbs =~ group.name
assert breadcrumbs =~ "Edit"
end
@@ -77,7 +77,7 @@ defmodule Web.Live.Sites.EditTest do
form = form(lv, "form")
assert find_inputs(form) == [
- "group[name_prefix]"
+ "group[name]"
]
end
@@ -96,14 +96,14 @@ defmodule Web.Live.Sites.EditTest do
lv
|> form("form", group: attrs)
- |> validate_change(%{group: %{name_prefix: String.duplicate("a", 256)}}, fn form, _html ->
+ |> validate_change(%{group: %{name: String.duplicate("a", 256)}}, fn form, _html ->
assert form_validation_errors(form) == %{
- "group[name_prefix]" => ["should be at most 64 character(s)"]
+ "group[name]" => ["should be at most 64 character(s)"]
}
end)
- |> validate_change(%{group: %{name_prefix: ""}}, fn form, _html ->
+ |> validate_change(%{group: %{name: ""}}, fn form, _html ->
assert form_validation_errors(form) == %{
- "group[name_prefix]" => ["can't be blank"]
+ "group[name]" => ["can't be blank"]
}
end)
end
@@ -115,7 +115,7 @@ defmodule Web.Live.Sites.EditTest do
conn: conn
} do
other_group = Fixtures.Gateways.create_group(account: account)
- attrs = %{name_prefix: other_group.name_prefix}
+ attrs = %{name: other_group.name}
{:ok, lv, _html} =
conn
@@ -126,7 +126,7 @@ defmodule Web.Live.Sites.EditTest do
|> form("form", group: attrs)
|> render_submit()
|> form_validation_errors() == %{
- "group[name_prefix]" => ["has already been taken"]
+ "group[name]" => ["has already been taken"]
}
end
@@ -136,19 +136,20 @@ defmodule Web.Live.Sites.EditTest do
group: group,
conn: conn
} do
- attrs = Fixtures.Gateways.group_attrs() |> Map.take([:name_prefix])
+ attrs = Fixtures.Gateways.group_attrs() |> Map.take([:name])
{:ok, lv, _html} =
conn
|> authorize_conn(identity)
|> live(~p"/#{account}/sites/#{group}/edit")
- assert lv
- |> form("form", group: attrs)
- |> render_submit() ==
- {:error, {:redirect, %{to: ~p"/#{account}/sites/#{group}"}}}
+ lv
+ |> form("form", group: attrs)
+ |> render_submit()
+
+ assert_redirected(lv, ~p"/#{account}/sites/#{group}")
assert group = Repo.get_by(Domain.Gateways.Group, id: group.id)
- assert group.name_prefix == attrs.name_prefix
+ assert group.name == attrs.name
end
end
diff --git a/elixir/apps/web/test/web/live/sites/index_test.exs b/elixir/apps/web/test/web/live/sites/index_test.exs
index 89b5221fb..085bc911b 100644
--- a/elixir/apps/web/test/web/live/sites/index_test.exs
+++ b/elixir/apps/web/test/web/live/sites/index_test.exs
@@ -76,8 +76,8 @@ defmodule Web.Live.Sites.IndexTest do
|> table_to_map()
assert row == %{
- "site" => group.name_prefix,
- "gateways" => gateway.name_suffix,
+ "site" => group.name,
+ "gateways" => gateway.name,
"resources" => resource.name
}
end
diff --git a/elixir/apps/web/test/web/live/sites/new_test.exs b/elixir/apps/web/test/web/live/sites/new_test.exs
index e4986fe15..88d218b4e 100644
--- a/elixir/apps/web/test/web/live/sites/new_test.exs
+++ b/elixir/apps/web/test/web/live/sites/new_test.exs
@@ -55,7 +55,7 @@ defmodule Web.Live.Sites.NewTest do
form = form(lv, "form")
assert find_inputs(form) == [
- "group[name_prefix]"
+ "group[name]"
]
end
@@ -64,7 +64,7 @@ defmodule Web.Live.Sites.NewTest do
identity: identity,
conn: conn
} do
- attrs = Fixtures.Gateways.group_attrs() |> Map.take([:name_prefix])
+ attrs = Fixtures.Gateways.group_attrs() |> Map.take([:name])
{:ok, lv, _html} =
conn
@@ -73,9 +73,9 @@ defmodule Web.Live.Sites.NewTest do
lv
|> form("form", group: attrs)
- |> validate_change(%{group: %{name_prefix: String.duplicate("a", 256)}}, fn form, _html ->
+ |> validate_change(%{group: %{name: String.duplicate("a", 256)}}, fn form, _html ->
assert form_validation_errors(form) == %{
- "group[name_prefix]" => ["should be at most 64 character(s)"]
+ "group[name]" => ["should be at most 64 character(s)"]
}
end)
end
@@ -86,7 +86,7 @@ defmodule Web.Live.Sites.NewTest do
conn: conn
} do
other_gateway = Fixtures.Gateways.create_group(account: account)
- attrs = %{name_prefix: other_gateway.name_prefix}
+ attrs = %{name: other_gateway.name}
{:ok, lv, _html} =
conn
@@ -97,7 +97,7 @@ defmodule Web.Live.Sites.NewTest do
|> form("form", group: attrs)
|> render_submit()
|> form_validation_errors() == %{
- "group[name_prefix]" => ["has already been taken"]
+ "group[name]" => ["has already been taken"]
}
end
@@ -106,7 +106,7 @@ defmodule Web.Live.Sites.NewTest do
identity: identity,
conn: conn
} do
- attrs = Fixtures.Gateways.group_attrs() |> Map.take([:name_prefix])
+ attrs = Fixtures.Gateways.group_attrs() |> Map.take([:name])
{:ok, lv, _html} =
conn
@@ -118,7 +118,7 @@ defmodule Web.Live.Sites.NewTest do
|> render_submit()
group =
- Repo.get_by(Domain.Gateways.Group, name_prefix: attrs.name_prefix)
+ Repo.get_by(Domain.Gateways.Group, name: attrs.name)
|> Repo.preload(:tokens)
assert assert_redirect(lv, ~p"/#{account}/sites/#{group}")
diff --git a/elixir/apps/web/test/web/live/sites/new_token_test.exs b/elixir/apps/web/test/web/live/sites/new_token_test.exs
index e3d654f2b..8097619a7 100644
--- a/elixir/apps/web/test/web/live/sites/new_token_test.exs
+++ b/elixir/apps/web/test/web/live/sites/new_token_test.exs
@@ -29,15 +29,19 @@ defmodule Web.Live.Sites.NewTokenTest do
assert html =~ "Select deployment method"
assert html =~ "FIREZONE_TOKEN="
assert html =~ "docker run"
- assert html =~ "Waiting for gateway connection..."
+ assert html =~ "Waiting for connection..."
assert Regex.run(~r/FIREZONE_ID=([^ ]+)/, html) |> List.last()
token = Regex.run(~r/FIREZONE_TOKEN=([^ ]+)/, html) |> List.last() |> String.trim(""")
- assert {:ok, _token} = Domain.Gateways.authorize_gateway(token)
+ :ok = Domain.Gateways.subscribe_for_gateways_presence_in_group(group)
gateway = Fixtures.Gateways.create_gateway(account: account, group: group)
+ assert {:ok, _token} = Domain.Gateways.authorize_gateway(token)
Domain.Gateways.connect_gateway(gateway)
- assert assert_redirect(lv, ~p"/#{account}/sites/#{group}")
+ assert_receive %Phoenix.Socket.Broadcast{topic: "gateway_groups:" <> _group_id}
+
+ assert element(lv, "#deployment-instructions")
+ |> render() =~ "Connected, click to continue"
end
end
diff --git a/elixir/apps/web/test/web/live/sites/show_test.exs b/elixir/apps/web/test/web/live/sites/show_test.exs
index 7a39aca35..6f183bac2 100644
--- a/elixir/apps/web/test/web/live/sites/show_test.exs
+++ b/elixir/apps/web/test/web/live/sites/show_test.exs
@@ -64,7 +64,7 @@ defmodule Web.Live.Sites.ShowTest do
assert item = Floki.find(html, "[aria-label='Breadcrumb']")
breadcrumbs = String.trim(Floki.text(item))
assert breadcrumbs =~ "Sites"
- assert breadcrumbs =~ group.name_prefix
+ assert breadcrumbs =~ group.name
end
test "allows editing gateway groups", %{
@@ -102,7 +102,7 @@ defmodule Web.Live.Sites.ShowTest do
|> render()
|> vertical_table_to_map()
- assert table["name"] =~ group.name_prefix
+ assert table["name"] =~ group.name
assert table["created"] =~ actor.name
end
@@ -123,7 +123,7 @@ defmodule Web.Live.Sites.ShowTest do
|> element("#gateways")
|> render()
|> table_to_map()
- |> with_table_row("instance", gateway.name_suffix, fn row ->
+ |> with_table_row("instance", gateway.name, fn row ->
assert row["token created at"] =~ actor.name
assert row["status"] =~ "Offline"
end)
@@ -147,7 +147,7 @@ defmodule Web.Live.Sites.ShowTest do
|> element("#gateways")
|> render()
|> table_to_map()
- |> with_table_row("instance", gateway.name_suffix, fn row ->
+ |> with_table_row("instance", gateway.name, fn row ->
assert gateway.last_seen_remote_ip
assert row["remote ip"] =~ to_string(gateway.last_seen_remote_ip)
assert row["status"] =~ "Online"
@@ -181,7 +181,7 @@ defmodule Web.Live.Sites.ShowTest do
Enum.each(resource_rows, fn row ->
assert row["name"] =~ resource.name
assert row["address"] =~ resource.address
- assert row["sites"] =~ group.name_prefix
+ assert row["sites"] =~ group.name
assert row["authorized groups"] == "None, create a Policy to grant access."
end)
end
@@ -264,10 +264,11 @@ defmodule Web.Live.Sites.ShowTest do
|> authorize_conn(identity)
|> live(~p"/#{account}/sites/#{group}")
- assert lv
- |> element("button", "Delete")
- |> render_click() ==
- {:error, {:redirect, %{to: ~p"/#{account}/sites"}}}
+ lv
+ |> element("button", "Delete")
+ |> render_click()
+
+ assert_redirected(lv, ~p"/#{account}/sites")
assert Repo.get(Domain.Gateways.Group, group.id).deleted_at
end
diff --git a/rust/connlib/shared/src/lib.rs b/rust/connlib/shared/src/lib.rs
index 06e9733d5..dc039b8c9 100644
--- a/rust/connlib/shared/src/lib.rs
+++ b/rust/connlib/shared/src/lib.rs
@@ -36,7 +36,8 @@ pub fn login_url(
device_id: String,
) -> Result<(Url, StaticSecret)> {
let private_key = StaticSecret::random_from_rng(rand::rngs::OsRng);
- let name_suffix: String = thread_rng()
+ // FIXME: read FIREZONE_NAME from env (eg. for gateways) and use system hostname by default
+ let name: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(8)
.map(char::from)
@@ -52,7 +53,7 @@ pub fn login_url(
},
&Key(PublicKey::from(&private_key).to_bytes()),
&external_id,
- &name_suffix,
+ &name,
)?;
Ok((url, private_key))
@@ -103,7 +104,7 @@ fn get_websocket_path(
mode: &str,
public_key: &Key,
external_id: &str,
- name_suffix: &str,
+ name: &str,
) -> Result