From 67c14c02edee5e6a1828b873e64c3ef0c8a71e89 Mon Sep 17 00:00:00 2001 From: bmanifold Date: Wed, 29 Nov 2023 17:02:50 -0500 Subject: [PATCH] Add Relay admin feature flag (#2736) Why: * Self-hosted Relays are not going to be apart of the beta release, so hiding the functionality in the portal will allow the user not to get confused about a feature they aren't able to use. Closes #2178 --- elixir/apps/domain/lib/domain/config.ex | 4 ++++ .../domain/lib/domain/config/definitions.ex | 5 +++++ .../lib/web/components/layouts/app.html.heex | 1 + .../apps/web/lib/web/live/relay_groups/edit.ex | 5 +++-- .../web/lib/web/live/relay_groups/index.ex | 6 +++--- .../apps/web/lib/web/live/relay_groups/new.ex | 8 ++++++-- .../web/lib/web/live/relay_groups/new_token.ex | 5 +++-- .../apps/web/lib/web/live/relay_groups/show.ex | 5 +++-- elixir/apps/web/lib/web/live/relays/show.ex | 5 +++-- .../test/web/live/relay_groups/edit_test.exs | 15 +++++++++++++++ .../test/web/live/relay_groups/index_test.exs | 14 ++++++++++++++ .../test/web/live/relay_groups/new_test.exs | 14 ++++++++++++++ .../web/live/relay_groups/new_token_test.exs | 15 +++++++++++++++ .../test/web/live/relay_groups/show_test.exs | 15 +++++++++++++++ .../web/test/web/live/relays/show_test.exs | 15 +++++++++++++++ elixir/config/config.exs | 3 ++- elixir/config/runtime.exs | 3 ++- terraform/environments/staging/main.tf | 18 ++++++++++++++++++ 18 files changed, 141 insertions(+), 15 deletions(-) diff --git a/elixir/apps/domain/lib/domain/config.ex b/elixir/apps/domain/lib/domain/config.ex index d22c4b0a4..cc8eb5ccf 100644 --- a/elixir/apps/domain/lib/domain/config.ex +++ b/elixir/apps/domain/lib/domain/config.ex @@ -136,6 +136,10 @@ defmodule Domain.Config do feature_enabled?(:traffic_filters) end + def self_hosted_relays_enabled? do + feature_enabled?(:self_hosted_relays) + end + ## Test helpers if Mix.env() != :test do diff --git a/elixir/apps/domain/lib/domain/config/definitions.ex b/elixir/apps/domain/lib/domain/config/definitions.ex index 15fc2a695..b582a6516 100644 --- a/elixir/apps/domain/lib/domain/config/definitions.ex +++ b/elixir/apps/domain/lib/domain/config/definitions.ex @@ -635,4 +635,9 @@ defmodule Domain.Config.Definitions do Boolean flag to turn Resource traffic filters on/off. """ defconfig(:feature_traffic_filters_enabled, :boolean, default: false) + + @doc """ + Boolean flag to turn Relay Admin functionality on/off. + """ + defconfig(:feature_self_hosted_relays_enabled, :boolean, default: false) end diff --git a/elixir/apps/web/lib/web/components/layouts/app.html.heex b/elixir/apps/web/lib/web/components/layouts/app.html.heex index 2ab0235cf..82ea02eba 100644 --- a/elixir/apps/web/lib/web/components/layouts/app.html.heex +++ b/elixir/apps/web/lib/web/components/layouts/app.html.heex @@ -42,6 +42,7 @@ <.sidebar_item + :if={Domain.Config.self_hosted_relays_enabled?()} current_path={@current_path} navigate={~p"/#{@account}/relay_groups"} icon="hero-arrows-right-left" 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 f825758eb..7a21e2f7f 100644 --- a/elixir/apps/web/lib/web/live/relay_groups/edit.ex +++ b/elixir/apps/web/lib/web/live/relay_groups/edit.ex @@ -3,11 +3,12 @@ defmodule Web.RelayGroups.Edit do alias Domain.Relays def mount(%{"id" => id}, _session, socket) do - with {:ok, group} <- Relays.fetch_group_by_id(id, socket.assigns.subject) do + with true <- Domain.Config.self_hosted_relays_enabled?(), + {:ok, group} <- Relays.fetch_group_by_id(id, socket.assigns.subject) do changeset = Relays.change_group(group) {:ok, assign(socket, group: group, form: to_form(changeset))} else - {:error, _reason} -> raise Web.LiveErrors.NotFoundError + _other -> raise Web.LiveErrors.NotFoundError end end diff --git a/elixir/apps/web/lib/web/live/relay_groups/index.ex b/elixir/apps/web/lib/web/live/relay_groups/index.ex index 647e9638b..e4318770d 100644 --- a/elixir/apps/web/lib/web/live/relay_groups/index.ex +++ b/elixir/apps/web/lib/web/live/relay_groups/index.ex @@ -5,12 +5,12 @@ defmodule Web.RelayGroups.Index do def mount(_params, _session, socket) do subject = socket.assigns.subject - with {:ok, groups} <- - Relays.list_groups(subject, preload: [:relays]) do + with true <- Domain.Config.self_hosted_relays_enabled?(), + {:ok, groups} <- Relays.list_groups(subject, preload: [:relays]) do :ok = Relays.subscribe_for_relays_presence_in_account(socket.assigns.account) {:ok, assign(socket, groups: groups)} else - {:error, _reason} -> raise Web.LiveErrors.NotFoundError + _other -> raise Web.LiveErrors.NotFoundError end end 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 adbafad90..0eed35c8d 100644 --- a/elixir/apps/web/lib/web/live/relay_groups/new.ex +++ b/elixir/apps/web/lib/web/live/relay_groups/new.ex @@ -3,8 +3,12 @@ defmodule Web.RelayGroups.New do alias Domain.Relays def mount(_params, _session, socket) do - changeset = Relays.new_group() - {:ok, assign(socket, form: to_form(changeset))} + with true <- Domain.Config.self_hosted_relays_enabled?() do + changeset = Relays.new_group() + {:ok, assign(socket, form: to_form(changeset))} + else + _other -> raise Web.LiveErrors.NotFoundError + end end def render(assigns) do diff --git a/elixir/apps/web/lib/web/live/relay_groups/new_token.ex b/elixir/apps/web/lib/web/live/relay_groups/new_token.ex index 4703ab5ea..456e216c7 100644 --- a/elixir/apps/web/lib/web/live/relay_groups/new_token.ex +++ b/elixir/apps/web/lib/web/live/relay_groups/new_token.ex @@ -3,7 +3,8 @@ defmodule Web.RelayGroups.NewToken do alias Domain.Relays def mount(%{"id" => id}, _session, socket) do - with {:ok, group} <- Relays.fetch_group_by_id(id, socket.assigns.subject) do + with true <- Domain.Config.self_hosted_relays_enabled?(), + {:ok, group} <- Relays.fetch_group_by_id(id, socket.assigns.subject) do {group, env} = if connected?(socket) do {:ok, group} = @@ -25,7 +26,7 @@ defmodule Web.RelayGroups.NewToken do selected_tab: "docker-instructions" )} else - {:error, _reason} -> raise Web.LiveErrors.NotFoundError + _other -> raise Web.LiveErrors.NotFoundError end end diff --git a/elixir/apps/web/lib/web/live/relay_groups/show.ex b/elixir/apps/web/lib/web/live/relay_groups/show.ex index 2cb84fc81..41e01451b 100644 --- a/elixir/apps/web/lib/web/live/relay_groups/show.ex +++ b/elixir/apps/web/lib/web/live/relay_groups/show.ex @@ -3,7 +3,8 @@ defmodule Web.RelayGroups.Show do alias Domain.Relays def mount(%{"id" => id}, _session, socket) do - with {:ok, group} <- + with true <- Domain.Config.self_hosted_relays_enabled?(), + {:ok, group} <- Relays.fetch_group_by_id(id, socket.assigns.subject, preload: [ relays: [token: [created_by_identity: [:actor]]], @@ -13,7 +14,7 @@ defmodule Web.RelayGroups.Show do :ok = Relays.subscribe_for_relays_presence_in_group(group) {:ok, assign(socket, group: group)} else - {:error, _reason} -> raise Web.LiveErrors.NotFoundError + _other -> raise Web.LiveErrors.NotFoundError end end diff --git a/elixir/apps/web/lib/web/live/relays/show.ex b/elixir/apps/web/lib/web/live/relays/show.ex index 6ecb64050..54a587a4c 100644 --- a/elixir/apps/web/lib/web/live/relays/show.ex +++ b/elixir/apps/web/lib/web/live/relays/show.ex @@ -3,7 +3,8 @@ defmodule Web.Relays.Show do alias Domain.{Relays, Config} def mount(%{"id" => id}, _session, socket) do - with {:ok, relay} <- + with true <- Domain.Config.self_hosted_relays_enabled?(), + {:ok, relay} <- Relays.fetch_relay_by_id(id, socket.assigns.subject, preload: :group) do :ok = Relays.subscribe_for_relays_presence_in_group(relay.group) @@ -16,7 +17,7 @@ defmodule Web.Relays.Show do {:ok, assign(socket, relay: relay)} else - {:error, _reason} -> raise Web.LiveErrors.NotFoundError + _other -> raise Web.LiveErrors.NotFoundError end end 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 7b1594abb..b71e81a73 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 @@ -152,4 +152,19 @@ defmodule Web.Live.RelayGroups.EditTest do assert group = Repo.get_by(Domain.Relays.Group, id: group.id) assert group.name == attrs.name end + + test "renders not found error when self_hosted_relays feature flag is false", %{ + account: account, + identity: identity, + group: group, + conn: conn + } do + Domain.Config.feature_flag_override(:self_hosted_relays, false) + + assert_raise Web.LiveErrors.NotFoundError, fn -> + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/relay_groups/#{group}/edit") + end + end end diff --git a/elixir/apps/web/test/web/live/relay_groups/index_test.exs b/elixir/apps/web/test/web/live/relay_groups/index_test.exs index e95470a6a..1249519be 100644 --- a/elixir/apps/web/test/web/live/relay_groups/index_test.exs +++ b/elixir/apps/web/test/web/live/relay_groups/index_test.exs @@ -99,4 +99,18 @@ defmodule Web.Live.RelayGroups.IndexTest do assert row["status"] =~ "Online" end) end + + test "renders not found error when self_hosted_relays feature flag is false", %{ + account: account, + identity: identity, + conn: conn + } do + Domain.Config.feature_flag_override(:self_hosted_relays, false) + + assert_raise Web.LiveErrors.NotFoundError, fn -> + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/relay_groups") + end + end end 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 14a5a9937..6614d71a1 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 @@ -121,4 +121,18 @@ defmodule Web.Live.RelayGroups.NewTest do assert assert_redirect(lv, ~p"/#{account}/relay_groups/#{group}") end + + test "renders not found error when self_hosted_relays feature flag is false", %{ + account: account, + identity: identity, + conn: conn + } do + Domain.Config.feature_flag_override(:self_hosted_relays, false) + + assert_raise Web.LiveErrors.NotFoundError, fn -> + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/relay_groups/new") + end + end 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 index 036def1a1..8b7698cfb 100644 --- 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 @@ -46,4 +46,19 @@ defmodule Web.Live.RelayGroups.NewTokenTest do assert element(lv, "#deployment-instructions") |> render() =~ "Connected, click to continue" end + + test "renders not found error when self_hosted_relays feature flag is false", %{ + account: account, + identity: identity, + group: group, + conn: conn + } do + Domain.Config.feature_flag_override(:self_hosted_relays, false) + + assert_raise Web.LiveErrors.NotFoundError, fn -> + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/relay_groups/#{group}/new_token") + end + 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 22bf347f9..dc36af13a 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 @@ -172,4 +172,19 @@ defmodule Web.Live.RelayGroups.ShowTest do assert Repo.get(Domain.Relays.Group, group.id).deleted_at end + + test "renders not found error when self_hosted_relays feature flag is false", %{ + account: account, + identity: identity, + group: group, + conn: conn + } do + Domain.Config.feature_flag_override(:self_hosted_relays, false) + + assert_raise Web.LiveErrors.NotFoundError, fn -> + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/relay_groups/#{group}") + end + end 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 7d617d2cb..63a905db1 100644 --- a/elixir/apps/web/test/web/live/relays/show_test.exs +++ b/elixir/apps/web/test/web/live/relays/show_test.exs @@ -134,4 +134,19 @@ defmodule Web.Live.Relays.ShowTest do assert Repo.get(Domain.Relays.Relay, relay.id).deleted_at end + + test "renders not found error when self_hosted_relays feature flag is false", %{ + account: account, + identity: identity, + relay: relay, + conn: conn + } do + Domain.Config.feature_flag_override(:self_hosted_relays, false) + + assert_raise Web.LiveErrors.NotFoundError, fn -> + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/relays/#{relay}") + end + end end diff --git a/elixir/config/config.exs b/elixir/config/config.exs index 93bc5befd..36a03a9eb 100644 --- a/elixir/config/config.exs +++ b/elixir/config/config.exs @@ -75,7 +75,8 @@ config :domain, :enabled_features, traffic_filters: true, signups: true, flow_activities: true, - todos: true + todos: true, + self_hosted_relays: true config :domain, docker_registry: "us-east1-docker.pkg.dev/firezone-staging/firezone" diff --git a/elixir/config/runtime.exs b/elixir/config/runtime.exs index 7ca45f837..d8c456237 100644 --- a/elixir/config/runtime.exs +++ b/elixir/config/runtime.exs @@ -69,7 +69,8 @@ if config_env() == :prod do traffic_filters: compile_config!(:feature_traffic_filters_enabled), signups: compile_config!(:feature_sign_up_enabled), flow_activities: compile_config!(:feature_flow_activities_enabled), - todos: compile_config!(:feature_todos_enabled) + todos: compile_config!(:feature_todos_enabled), + relay_admin: compile_config!(:feature_self_hosted_relays_enabled) config :domain, docker_registry: compile_config!(:docker_registry) diff --git a/terraform/environments/staging/main.tf b/terraform/environments/staging/main.tf index 9d92f6c59..9f59eb59c 100644 --- a/terraform/environments/staging/main.tf +++ b/terraform/environments/staging/main.tf @@ -420,7 +420,25 @@ locals { value = jsonencode({ api_key = var.postmark_server_api_token }) + }, + # Feature Flags + { + name = "FEATURE_FLOW_ACTIVITIES_ENABLED" + value = true + }, + { + name = "FEATURE_TRAFFIC_FILTERS_ENABLED" + value = true + }, + { + name = "FEATURE_TODOS_ENABLED" + value = true + }, + { + name = "FEATURE_RELAY_ADMIN_ENABLED" + value = true } + ] }