diff --git a/docker-compose.yml b/docker-compose.yml index 26532681a..ffb3ca804 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -101,7 +101,6 @@ services: # Seeds STATIC_SEEDS: "true" # Feature flags - FEATURE_FLOW_ACTIVITIES_ENABLED: "true" FEATURE_POLICY_CONDITIONS_ENABLED: "true" FEATURE_MULTI_SITE_RESOURCES_ENABLED: "true" FEATURE_SELF_HOSTED_RELAYS_ENABLED: "true" @@ -174,7 +173,6 @@ services: # Seeds STATIC_SEEDS: "true" # Feature flags - FEATURE_FLOW_ACTIVITIES_ENABLED: "true" FEATURE_POLICY_CONDITIONS_ENABLED: "true" FEATURE_MULTI_SITE_RESOURCES_ENABLED: "true" FEATURE_SELF_HOSTED_RELAYS_ENABLED: "true" @@ -239,7 +237,6 @@ services: # Seeds STATIC_SEEDS: "true" # Feature flags - FEATURE_FLOW_ACTIVITIES_ENABLED: "true" FEATURE_POLICY_CONDITIONS_ENABLED: "true" FEATURE_MULTI_SITE_RESOURCES_ENABLED: "true" FEATURE_SELF_HOSTED_RELAYS_ENABLED: "true" @@ -311,7 +308,6 @@ services: # Seeds STATIC_SEEDS: "true" # Feature flags - FEATURE_FLOW_ACTIVITIES_ENABLED: "true" FEATURE_POLICY_CONDITIONS_ENABLED: "true" FEATURE_MULTI_SITE_RESOURCES_ENABLED: "true" FEATURE_SELF_HOSTED_RELAYS_ENABLED: "true" diff --git a/elixir/apps/api/lib/api/gateway/channel.ex b/elixir/apps/api/lib/api/gateway/channel.ex index 21091bde2..a46e45a53 100644 --- a/elixir/apps/api/lib/api/gateway/channel.ex +++ b/elixir/apps/api/lib/api/gateway/channel.ex @@ -1,7 +1,7 @@ defmodule API.Gateway.Channel do use API, :channel alias API.Gateway.Views - alias Domain.{Clients, Gateways, PubSub, Resources, Relays, Flows} + alias Domain.{Clients, Gateways, PubSub, Resources, Relays} alias Domain.Relays.Presence.Debouncer require Logger require OpenTelemetry.Tracer @@ -648,52 +648,6 @@ defmodule API.Gateway.Channel do end end - def handle_in( - "metrics", - %{ - "started_at" => started_at, - "ended_at" => ended_at, - "metrics" => metrics - }, - socket - ) do - OpenTelemetry.Ctx.attach(socket.assigns.opentelemetry_ctx) - OpenTelemetry.Tracer.set_current_span(socket.assigns.opentelemetry_span_ctx) - - OpenTelemetry.Tracer.with_span "gateway.metrics" do - window_started_at = DateTime.from_unix!(started_at, :second) - window_ended_at = DateTime.from_unix!(ended_at, :second) - - activities = - Enum.map(metrics, fn metric -> - %{ - "flow_id" => flow_id, - "destination" => destination, - "connectivity_type" => connectivity_type, - "rx_bytes" => rx_bytes, - "tx_bytes" => tx_bytes, - "blocked_tx_bytes" => blocked_tx_bytes - } = metric - - %{ - flow_id: flow_id, - account_id: socket.assigns.gateway.account_id, - window_started_at: window_started_at, - window_ended_at: window_ended_at, - connectivity_type: String.to_existing_atom(connectivity_type), - destination: destination, - rx_bytes: rx_bytes, - tx_bytes: tx_bytes, - blocked_tx_bytes: blocked_tx_bytes - } - end) - - {:ok, _num} = Flows.upsert_activities(activities) - - {:reply, :ok, socket} - end - end - # Catch-all for unknown messages def handle_in(message, payload, socket) do Logger.error("Unknown gateway message", message: message, payload: payload) diff --git a/elixir/apps/api/test/api/gateway/channel_test.exs b/elixir/apps/api/test/api/gateway/channel_test.exs index c099907a4..8460535fa 100644 --- a/elixir/apps/api/test/api/gateway/channel_test.exs +++ b/elixir/apps/api/test/api/gateway/channel_test.exs @@ -1189,58 +1189,6 @@ defmodule API.Gateway.ChannelTest do end end - describe "handle_in/3 metrics" do - test "inserts activities", %{ - account: account, - subject: subject, - client: client, - gateway: gateway, - resource: resource, - socket: socket - } do - flow = - Fixtures.Flows.create_flow( - account: account, - subject: subject, - client: client, - resource: resource, - gateway: gateway - ) - - now = DateTime.utc_now() |> DateTime.truncate(:second) - one_minute_ago = DateTime.add(now, -1, :minute) - - {:ok, destination} = Domain.Types.ProtocolIPPort.cast("tcp://127.0.0.1:80") - - attrs = %{ - "started_at" => DateTime.to_unix(one_minute_ago), - "ended_at" => DateTime.to_unix(now), - "metrics" => [ - %{ - "flow_id" => flow.id, - "destination" => destination, - "connectivity_type" => "direct", - "rx_bytes" => 100, - "tx_bytes" => 200, - "blocked_tx_bytes" => 0 - } - ] - } - - push_ref = push(socket, "metrics", attrs) - assert_reply push_ref, :ok - - assert upserted_activity = Repo.one(Domain.Flows.Activity) - assert upserted_activity.window_started_at == one_minute_ago - assert upserted_activity.window_ended_at == now - assert upserted_activity.destination == destination - assert upserted_activity.rx_bytes == 100 - assert upserted_activity.tx_bytes == 200 - assert upserted_activity.flow_id == flow.id - assert upserted_activity.account_id == account.id - end - end - # Debouncer tests describe "handle_info/3 :push_leave" do test "cancels leave if reconnecting with the same stamp secret" do diff --git a/elixir/apps/domain/lib/domain/accounts/features.ex b/elixir/apps/domain/lib/domain/accounts/features.ex index 2e2e2aee0..b66b6fa43 100644 --- a/elixir/apps/domain/lib/domain/accounts/features.ex +++ b/elixir/apps/domain/lib/domain/accounts/features.ex @@ -3,7 +3,6 @@ defmodule Domain.Accounts.Features do @primary_key false embedded_schema do - field :flow_activities, :boolean field :policy_conditions, :boolean field :multi_site_resources, :boolean field :traffic_filters, :boolean diff --git a/elixir/apps/domain/lib/domain/accounts/features/changeset.ex b/elixir/apps/domain/lib/domain/accounts/features/changeset.ex index c6d36c88e..84a4d461c 100644 --- a/elixir/apps/domain/lib/domain/accounts/features/changeset.ex +++ b/elixir/apps/domain/lib/domain/accounts/features/changeset.ex @@ -3,7 +3,6 @@ defmodule Domain.Accounts.Features.Changeset do alias Domain.Accounts.Features @fields ~w[ - flow_activities policy_conditions multi_site_resources traffic_filters diff --git a/elixir/apps/domain/lib/domain/config/definitions.ex b/elixir/apps/domain/lib/domain/config/definitions.ex index 6b5370f72..eb5ad398e 100644 --- a/elixir/apps/domain/lib/domain/config/definitions.ex +++ b/elixir/apps/domain/lib/domain/config/definitions.ex @@ -699,11 +699,6 @@ defmodule Domain.Config.Definitions do """ defconfig(:feature_idp_sync_enabled, :boolean, default: true) - @doc """ - Boolean flag to turn UI flow activities on/off for all accounts. - """ - defconfig(:feature_flow_activities_enabled, :boolean, default: false) - @doc """ Boolean flag to turn Account relays admin functionality on/off for all accounts. """ diff --git a/elixir/apps/domain/lib/domain/events/hooks/flow_activities.ex b/elixir/apps/domain/lib/domain/events/hooks/flow_activities.ex deleted file mode 100644 index e813ec64c..000000000 --- a/elixir/apps/domain/lib/domain/events/hooks/flow_activities.ex +++ /dev/null @@ -1,12 +0,0 @@ -defmodule Domain.Events.Hooks.FlowActivities do - @behaviour Domain.Events.Hooks - - @impl true - def on_insert(_data), do: :ok - - @impl true - def on_update(_old_data, _data), do: :ok - - @impl true - def on_delete(_old_data), do: :ok -end diff --git a/elixir/apps/domain/lib/domain/events/replication_connection.ex b/elixir/apps/domain/lib/domain/events/replication_connection.ex index 78731dcbc..48428764e 100644 --- a/elixir/apps/domain/lib/domain/events/replication_connection.ex +++ b/elixir/apps/domain/lib/domain/events/replication_connection.ex @@ -18,7 +18,6 @@ defmodule Domain.Events.ReplicationConnection do "auth_identities" => Hooks.AuthIdentities, "auth_providers" => Hooks.AuthProviders, "clients" => Hooks.Clients, - "flow_activities" => Hooks.FlowActivities, "gateway_groups" => Hooks.GatewayGroups, "gateways" => Hooks.Gateways, "policies" => Hooks.Policies, diff --git a/elixir/apps/domain/lib/domain/flows.ex b/elixir/apps/domain/lib/domain/flows.ex index c71a3ee32..92bc0ec80 100644 --- a/elixir/apps/domain/lib/domain/flows.ex +++ b/elixir/apps/domain/lib/domain/flows.ex @@ -1,7 +1,7 @@ defmodule Domain.Flows do alias Domain.Repo - alias Domain.{Auth, Accounts, Actors, Clients, Gateways, Resources, Policies, Tokens} - alias Domain.Flows.{Authorizer, Flow, Activity} + alias Domain.{Auth, Actors, Clients, Gateways, Resources, Policies, Tokens} + alias Domain.Flows.{Authorizer, Flow} require Ecto.Query require Logger @@ -125,43 +125,6 @@ defmodule Domain.Flows do end end - def upsert_activities(activities) do - {num, _} = Repo.insert_all(Activity, activities, on_conflict: :nothing) - {:ok, num} - end - - def fetch_last_activity_for(%Flow{} = flow, %Auth.Subject{} = subject, opts \\ []) do - with :ok <- Auth.ensure_has_permissions(subject, Authorizer.manage_flows_permission()) do - Activity.Query.all() - |> Activity.Query.by_flow_id(flow.id) - |> Activity.Query.first() - |> Ecto.Query.order_by([activities: activities], desc: activities.window_ended_at) - |> Repo.fetch(Activity.Query, opts) - end - end - - def list_flow_activities_for(assoc, subject, opts \\ []) - - def list_flow_activities_for(%Flow{} = flow, %Auth.Subject{} = subject, opts) do - Activity.Query.all() - |> Activity.Query.by_flow_id(flow.id) - |> list_activities(subject, opts) - end - - def list_flow_activities_for(%Accounts.Account{} = account, %Auth.Subject{} = subject, opts) do - Activity.Query.all() - |> Activity.Query.by_account_id(account.id) - |> list_activities(subject, opts) - end - - defp list_activities(queryable, subject, opts) do - with :ok <- Auth.ensure_has_permissions(subject, Authorizer.manage_flows_permission()) do - queryable - |> Authorizer.for_subject(Activity, subject) - |> Repo.list(Activity.Query, opts) - end - end - # TODO: WAL # Remove all of the indexes used for these after flow expiration is moved to state # broadcasts diff --git a/elixir/apps/domain/lib/domain/flows/activity.ex b/elixir/apps/domain/lib/domain/flows/activity.ex deleted file mode 100644 index fc46a8e0c..000000000 --- a/elixir/apps/domain/lib/domain/flows/activity.ex +++ /dev/null @@ -1,18 +0,0 @@ -defmodule Domain.Flows.Activity do - use Domain, :schema - - schema "flow_activities" do - field :window_started_at, :utc_datetime - field :window_ended_at, :utc_datetime - - field :destination, Domain.Types.ProtocolIPPort - field :rx_bytes, :integer - field :tx_bytes, :integer - field :blocked_tx_bytes, :integer - - field :connectivity_type, Ecto.Enum, values: [:relayed, :direct] - - belongs_to :flow, Domain.Flows.Flow - belongs_to :account, Domain.Accounts.Account - end -end diff --git a/elixir/apps/domain/lib/domain/flows/activity/query.ex b/elixir/apps/domain/lib/domain/flows/activity/query.ex deleted file mode 100644 index a181a45fb..000000000 --- a/elixir/apps/domain/lib/domain/flows/activity/query.ex +++ /dev/null @@ -1,63 +0,0 @@ -defmodule Domain.Flows.Activity.Query do - use Domain, :query - - def all do - from(activities in Domain.Flows.Activity, as: :activities) - end - - def by_account_id(queryable, account_id) do - where(queryable, [activities: activities], activities.account_id == ^account_id) - end - - def by_flow_id(queryable, flow_id) do - where(queryable, [activities: activities], activities.flow_id == ^flow_id) - end - - def by_window_started_at(queryable, {:less_than, datetime}) do - where(queryable, [activities: activities], activities.window_started_at < ^datetime) - end - - def by_window_ended_at(queryable, {:greater_than, datetime}) do - where(queryable, [activities: activities], activities.window_ended_at > ^datetime) - end - - def first(queryable) do - limit(queryable, 1) - end - - # Pagination - - @impl Domain.Repo.Query - def cursor_fields, - do: [ - {:activities, :asc, :window_started_at}, - {:activities, :asc, :id} - ] - - @impl Domain.Repo.Query - def filters, - do: [ - %Domain.Repo.Filter{ - name: :window_within, - title: "Window", - type: {:range, :datetime}, - fun: &filter_by_window/2 - } - ] - - def filter_by_window(queryable, %Domain.Repo.Filter.Range{from: from, to: nil}) do - {queryable, dynamic([activities: activities], ^from <= activities.window_started_at)} - end - - def filter_by_window(queryable, %Domain.Repo.Filter.Range{from: nil, to: to}) do - {queryable, dynamic([activities: activities], activities.window_ended_at <= ^to)} - end - - def filter_by_window(queryable, %Domain.Repo.Filter.Range{from: from, to: to}) do - {queryable, - dynamic( - [activities: activities], - ^from <= activities.window_started_at and activities.window_ended_at <= ^to - )} - end -end diff --git a/elixir/apps/domain/lib/domain/flows/authorizer.ex b/elixir/apps/domain/lib/domain/flows/authorizer.ex index f28df64a3..06d1589e6 100644 --- a/elixir/apps/domain/lib/domain/flows/authorizer.ex +++ b/elixir/apps/domain/lib/domain/flows/authorizer.ex @@ -2,7 +2,7 @@ # When this is renamed, "PolicyAuthorizations Authorizer" makes no sense, remove this module defmodule Domain.Flows.Authorizer do use Domain.Auth.Authorizer - alias Domain.Flows.{Flow, Activity} + alias Domain.Flows.Flow def manage_flows_permission, do: build(Flow, :manage) def create_flows_permission, do: build(Flow, :create) @@ -49,11 +49,4 @@ defmodule Domain.Flows.Authorizer do |> Flow.Query.by_actor_id(subject.actor.id) end end - - def for_subject(queryable, Activity, %Subject{} = subject) do - cond do - has_permission?(subject, manage_flows_permission()) -> - Activity.Query.by_account_id(queryable, subject.account.id) - end - end end diff --git a/elixir/apps/domain/priv/repo/manual_migrations/20250627040131_drop_flow_activities.exs b/elixir/apps/domain/priv/repo/manual_migrations/20250627040131_drop_flow_activities.exs new file mode 100644 index 000000000..0b2de3a1e --- /dev/null +++ b/elixir/apps/domain/priv/repo/manual_migrations/20250627040131_drop_flow_activities.exs @@ -0,0 +1,9 @@ +defmodule Domain.Repo.Migrations.DropFlowActivities do + use Ecto.Migration + + # Flow activities is completely unused at the time of this migration, + # so we don't expect to ever need to roll back this migration. + def change do + drop(table(:flow_activities)) + end +end diff --git a/elixir/apps/domain/priv/repo/manual_migrations/20250627040310_remove_flow_activities_feature.exs b/elixir/apps/domain/priv/repo/manual_migrations/20250627040310_remove_flow_activities_feature.exs new file mode 100644 index 000000000..4abf8a56c --- /dev/null +++ b/elixir/apps/domain/priv/repo/manual_migrations/20250627040310_remove_flow_activities_feature.exs @@ -0,0 +1,13 @@ +defmodule Domain.Repo.Migrations.RemoveFlowActivitiesFeature do + use Ecto.Migration + + # The flow_activities feature is completely unused at the time of this + # migration, so we don't support re-adding this JSONB embedded field. + def change do + execute(""" + UPDATE accounts + SET features = features - 'flow_activities' + WHERE features ? 'flow_activities'; + """) + end +end diff --git a/elixir/apps/domain/priv/repo/seeds.exs b/elixir/apps/domain/priv/repo/seeds.exs index 19d25f0c9..f8c0e7476 100644 --- a/elixir/apps/domain/priv/repo/seeds.exs +++ b/elixir/apps/domain/priv/repo/seeds.exs @@ -47,7 +47,6 @@ defmodule Domain.Repo.Seeds do account |> Ecto.Changeset.change( features: %{ - flow_activities: true, policy_conditions: true, multi_site_resources: true, traffic_filters: true, @@ -1191,35 +1190,6 @@ defmodule Domain.Repo.Seeds do {:ok, destination1} = Domain.Types.ProtocolIPPort.cast("tcp://142.250.217.142:443") {:ok, destination2} = Domain.Types.ProtocolIPPort.cast("udp://142.250.217.142:111") - - random_integer = fn -> - :math.pow(10, 10) - |> round() - |> :rand.uniform() - |> floor() - |> Kernel.-(1) - end - - activities = - for i <- 1..200 do - offset = i * 15 - started_at = DateTime.add(started_at, offset, :minute) - ended_at = DateTime.add(started_at, 15, :minute) - - %{ - window_started_at: started_at, - window_ended_at: ended_at, - destination: Enum.random([destination1, destination2]), - connectivity_type: :direct, - rx_bytes: random_integer.(), - tx_bytes: random_integer.(), - blocked_tx_bytes: 0, - flow_id: flow.id, - account_id: account.id - } - end - - {:ok, 200} = Flows.upsert_activities(activities) end end diff --git a/elixir/apps/domain/test/domain/billing_test.exs b/elixir/apps/domain/test/domain/billing_test.exs index fdc9e333d..9cf604662 100644 --- a/elixir/apps/domain/test/domain/billing_test.exs +++ b/elixir/apps/domain/test/domain/billing_test.exs @@ -445,7 +445,6 @@ defmodule Domain.BillingTest do Domain.Accounts.update_account(account, %{ metadata: %{stripe: %{customer_id: customer_id}}, features: %{ - flow_activities: nil, multi_site_resources: nil, traffic_filters: nil, self_hosted_relays: nil, @@ -775,7 +774,6 @@ defmodule Domain.BillingTest do service_accounts_count: 10101 }, features: %{ - flow_activities: true, traffic_filters: true } }) @@ -835,7 +833,6 @@ defmodule Domain.BillingTest do } assert account.features == %Domain.Accounts.Features{ - flow_activities: nil, idp_sync: true, multi_site_resources: true, self_hosted_relays: true, @@ -885,7 +882,6 @@ defmodule Domain.BillingTest do service_accounts_count: 10101 }, features: %{ - flow_activities: true, traffic_filters: true } }) @@ -946,7 +942,6 @@ defmodule Domain.BillingTest do } assert account.features == %Domain.Accounts.Features{ - flow_activities: nil, idp_sync: true, multi_site_resources: true, self_hosted_relays: false, diff --git a/elixir/apps/domain/test/domain/events/hooks/flow_activities_test.exs b/elixir/apps/domain/test/domain/events/hooks/flow_activities_test.exs deleted file mode 100644 index d77d58671..000000000 --- a/elixir/apps/domain/test/domain/events/hooks/flow_activities_test.exs +++ /dev/null @@ -1,26 +0,0 @@ -defmodule Domain.Events.Hooks.FlowActivitiesTest do - use ExUnit.Case, async: true - import Domain.Events.Hooks.FlowActivities - - setup do - %{old_data: %{}, data: %{}} - end - - describe "insert/1" do - test "returns :ok", %{data: data} do - assert :ok == on_insert(data) - end - end - - describe "update/2" do - test "returns :ok", %{old_data: old_data, data: data} do - assert :ok == on_update(old_data, data) - end - end - - describe "delete/1" do - test "returns :ok", %{data: data} do - assert :ok == on_delete(data) - end - end -end diff --git a/elixir/apps/domain/test/domain/flows_test.exs b/elixir/apps/domain/test/domain/flows_test.exs index 928f87c76..5ca338ad5 100644 --- a/elixir/apps/domain/test/domain/flows_test.exs +++ b/elixir/apps/domain/test/domain/flows_test.exs @@ -572,336 +572,6 @@ defmodule Domain.FlowsTest do end end - describe "upsert_activities/1" do - test "inserts new activities", %{ - account: account, - client: client, - gateway: gateway, - resource: resource, - policy: policy, - subject: subject - } do - flow = - Fixtures.Flows.create_flow( - account: account, - subject: subject, - client: client, - policy: policy, - resource: resource, - gateway: gateway - ) - - now = DateTime.utc_now() |> DateTime.truncate(:second) - - {:ok, destination} = Domain.Types.ProtocolIPPort.cast("tcp://127.0.0.1:80") - - activity = %{ - window_started_at: DateTime.add(now, -1, :minute), - window_ended_at: now, - destination: destination, - rx_bytes: 100, - tx_bytes: 200, - blocked_tx_bytes: 0, - connectivity_type: :direct, - flow_id: flow.id, - account_id: account.id - } - - assert upsert_activities([activity]) == {:ok, 1} - - assert upserted_activity = Repo.one(Flows.Activity) - assert upserted_activity.window_started_at == activity.window_started_at - assert upserted_activity.window_ended_at == activity.window_ended_at - assert upserted_activity.destination == destination - assert upserted_activity.rx_bytes == activity.rx_bytes - assert upserted_activity.tx_bytes == activity.tx_bytes - assert upserted_activity.flow_id == flow.id - assert upserted_activity.account_id == account.id - end - - test "ignores upsert conflicts", %{ - account: account, - client: client, - gateway: gateway, - resource: resource, - policy: policy, - subject: subject - } do - flow = - Fixtures.Flows.create_flow( - account: account, - subject: subject, - client: client, - policy: policy, - resource: resource, - gateway: gateway - ) - - activity = Fixtures.Flows.activity_attrs(flow_id: flow.id, account_id: account.id) - - assert upsert_activities([activity]) == {:ok, 1} - assert upsert_activities([activity]) == {:ok, 0} - - assert Repo.one(Flows.Activity) - end - end - - describe "fetch_last_activity_for/3" do - setup %{ - account: account, - client: client, - gateway: gateway, - resource: resource, - policy: policy, - subject: subject - } do - flow = - Fixtures.Flows.create_flow( - account: account, - subject: subject, - client: client, - policy: policy, - resource: resource, - gateway: gateway - ) - - %{flow: flow} - end - - test "returns error when flow has no activities", %{subject: subject, flow: flow} do - assert fetch_last_activity_for(flow, subject) == {:error, :not_found} - end - - test "returns last activity for a flow", %{subject: subject, flow: flow} do - now = DateTime.utc_now() |> DateTime.truncate(:second) - thirty_minutes_ago = DateTime.add(now, -30, :minute) - five_minutes_ago = DateTime.add(now, -5, :minute) - four_minutes_ago = DateTime.add(now, -4, :minute) - - Fixtures.Flows.create_activity( - flow: flow, - window_started_at: thirty_minutes_ago, - window_ended_at: five_minutes_ago - ) - - activity = - Fixtures.Flows.create_activity( - flow: flow, - window_started_at: five_minutes_ago, - window_ended_at: four_minutes_ago - ) - - assert {:ok, fetched_activity} = fetch_last_activity_for(flow, subject) - assert fetched_activity.id == activity.id - end - - test "returns error when subject has no permission to view flows", %{ - flow: flow, - subject: subject - } do - subject = Fixtures.Auth.remove_permissions(subject) - - assert fetch_last_activity_for(flow, subject) == - {:error, - {:unauthorized, - reason: :missing_permissions, - missing_permissions: [Flows.Authorizer.manage_flows_permission()]}} - end - end - - describe "list_flow_activities_for/4" do - setup %{ - account: account, - client: client, - gateway: gateway, - resource: resource, - policy: policy, - subject: subject - } do - flow = - Fixtures.Flows.create_flow( - account: account, - subject: subject, - client: client, - policy: policy, - resource: resource, - gateway: gateway - ) - - %{flow: flow} - end - - test "returns empty list when there are no flow activities", %{ - account: account, - flow: flow, - subject: subject - } do - assert {:ok, [], _metadata} = - list_flow_activities_for(account, subject) - - assert {:ok, [], _metadata} = - list_flow_activities_for(flow, subject) - end - - test "does not list flow activities from other accounts", %{ - account: account, - subject: subject - } do - flow = Fixtures.Flows.create_flow() - Fixtures.Flows.create_activity(flow: flow) - - assert {:ok, [], _metadata} = - list_flow_activities_for(account, subject) - - assert {:ok, [], _metadata} = - list_flow_activities_for(flow, subject) - end - - test "returns ordered by window start time flow activities within a time window", %{ - account: account, - flow: flow, - subject: subject - } do - now = DateTime.utc_now() |> DateTime.truncate(:second) - thirty_minutes_ago = DateTime.add(now, -30, :minute) - five_minutes_ago = DateTime.add(now, -5, :minute) - four_minutes_ago = DateTime.add(now, -4, :minute) - three_minutes_ago = DateTime.add(now, -4, :minute) - thirty_minutes_in_future = DateTime.add(now, 30, :minute) - sixty_minutes_in_future = DateTime.add(now, 60, :minute) - - activity1 = - Fixtures.Flows.create_activity( - flow: flow, - window_started_at: four_minutes_ago, - window_ended_at: three_minutes_ago - ) - - assert {:ok, [], _metadata} = - list_flow_activities_for( - account, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: thirty_minutes_in_future, - to: sixty_minutes_in_future - } - ] - ) - - assert {:ok, [], _metadata} = - list_flow_activities_for( - flow, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: thirty_minutes_in_future, - to: sixty_minutes_in_future - } - ] - ) - - assert {:ok, [], _metadata} = - list_flow_activities_for( - account, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: thirty_minutes_ago, - to: five_minutes_ago - } - ] - ) - - assert {:ok, [], _metadata} = - list_flow_activities_for( - flow, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: thirty_minutes_ago, - to: five_minutes_ago - } - ] - ) - - assert {:ok, [^activity1], _metadata} = - list_flow_activities_for( - account, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: five_minutes_ago, - to: now - } - ] - ) - - assert {:ok, [^activity1], _metadata} = - list_flow_activities_for( - flow, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: five_minutes_ago, - to: now - } - ] - ) - - activity2 = - Fixtures.Flows.create_activity( - flow: flow, - window_started_at: five_minutes_ago, - window_ended_at: four_minutes_ago - ) - - assert {:ok, [^activity2, ^activity1], _metadata} = - list_flow_activities_for( - account, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: thirty_minutes_ago, - to: now - } - ] - ) - - assert {:ok, [^activity2, ^activity1], _metadata} = - list_flow_activities_for( - flow, - subject, - filter: [ - window_within: %Domain.Repo.Filter.Range{ - from: thirty_minutes_ago, - to: now - } - ] - ) - end - - test "returns error when subject has no permission to view flows", %{ - account: account, - flow: flow, - subject: subject - } do - subject = Fixtures.Auth.remove_permissions(subject) - - assert list_flow_activities_for(account, subject) == - {:error, - {:unauthorized, - reason: :missing_permissions, - missing_permissions: [Flows.Authorizer.manage_flows_permission()]}} - - assert list_flow_activities_for(flow, subject) == - {:error, - {:unauthorized, - reason: :missing_permissions, - missing_permissions: [Flows.Authorizer.manage_flows_permission()]}} - end - end - describe "expire_flows_for/1" do setup %{ account: account, diff --git a/elixir/apps/domain/test/domain/ops_test.exs b/elixir/apps/domain/test/domain/ops_test.exs index c3e234450..406bfcc8c 100644 --- a/elixir/apps/domain/test/domain/ops_test.exs +++ b/elixir/apps/domain/test/domain/ops_test.exs @@ -96,7 +96,6 @@ defmodule Domain.OpsTest do Fixtures.Actors.create_actor(account: account) Fixtures.Auth.create_identity(account: account) Fixtures.Clients.create_client(account: account) - Fixtures.Flows.create_activity(account: account) Fixtures.Gateways.create_gateway(account: account) Fixtures.Policies.create_policy(account: account) Fixtures.Relays.create_relay(account: account) diff --git a/elixir/apps/domain/test/support/fixtures/accounts.ex b/elixir/apps/domain/test/support/fixtures/accounts.ex index e18aaea4c..148702f89 100644 --- a/elixir/apps/domain/test/support/fixtures/accounts.ex +++ b/elixir/apps/domain/test/support/fixtures/accounts.ex @@ -18,7 +18,6 @@ defmodule Domain.Fixtures.Accounts do ] }, features: %{ - flow_activities: true, policy_conditions: true, multi_site_resources: true, traffic_filters: true, diff --git a/elixir/apps/domain/test/support/fixtures/flows.ex b/elixir/apps/domain/test/support/fixtures/flows.ex index c463bc60d..324fe7e41 100644 --- a/elixir/apps/domain/test/support/fixtures/flows.ex +++ b/elixir/apps/domain/test/support/fixtures/flows.ex @@ -86,48 +86,4 @@ defmodule Domain.Fixtures.Flows do }) |> Repo.insert!() end - - def activity_attrs(attrs \\ %{}) do - now = DateTime.utc_now() |> DateTime.truncate(:second) - unique_ipv4 = :inet.ntoa(unique_ipv4()) - {:ok, destination} = Domain.Types.ProtocolIPPort.cast("tcp://#{unique_ipv4}:80") - - Enum.into(attrs, %{ - window_started_at: DateTime.add(now, -1, :minute), - window_ended_at: now, - destination: destination, - connectivity_type: :relayed, - rx_bytes: 100, - tx_bytes: 200, - blocked_tx_bytes: 0 - }) - end - - def create_activity(attrs) do - attrs = activity_attrs(attrs) - - {account, attrs} = - pop_assoc_fixture(attrs, :account, fn assoc_attrs -> - if relation = attrs[:flow] do - Repo.get!(Domain.Accounts.Account, relation.account_id) - else - Fixtures.Accounts.create_account(assoc_attrs) - end - end) - - {flow, attrs} = - pop_assoc_fixture(attrs, :flow, fn assoc_attrs -> - assoc_attrs - |> Enum.into(%{account: account}) - |> create_flow() - end) - - attrs = - attrs - |> Map.put(:flow_id, flow.id) - |> Map.put(:account_id, account.id) - - struct(Flows.Activity, attrs) - |> Repo.insert!() - end end diff --git a/elixir/apps/web/lib/web/components/core_components.ex b/elixir/apps/web/lib/web/components/core_components.ex index 1b5d19559..a2bc6d69b 100644 --- a/elixir/apps/web/lib/web/components/core_components.ex +++ b/elixir/apps/web/lib/web/components/core_components.ex @@ -1578,12 +1578,6 @@ defmodule Web.CoreComponents do """ end - def feature_name(%{feature: :flow_activities} = assigns) do - ~H""" - See detailed Resource access logs - """ - end - def feature_name(%{feature: :policy_conditions} = assigns) do ~H""" Specify access-time conditions when creating policies diff --git a/elixir/apps/web/lib/web/live/actors/show.ex b/elixir/apps/web/lib/web/live/actors/show.ex index f6359adaa..0fc2f2b30 100644 --- a/elixir/apps/web/lib/web/live/actors/show.ex +++ b/elixir/apps/web/lib/web/live/actors/show.ex @@ -2,7 +2,7 @@ defmodule Web.Actors.Show do use Web, :live_view import Web.Actors.Components import Web.Clients.Components - alias Domain.{Accounts, Auth, Tokens, Flows, Clients} + alias Domain.{Auth, Tokens, Flows, Clients} alias Domain.Actors def mount(%{"id" => id}, _session, socket) do @@ -32,7 +32,6 @@ defmodule Web.Actors.Show do |> assign( available_providers: available_providers, page_title: "Actor #{actor.name}", - flow_activities_enabled?: Accounts.flow_activities_enabled?(socket.assigns.account), actor: actor ) |> assign_live_table("identities", diff --git a/elixir/apps/web/lib/web/live/clients/show.ex b/elixir/apps/web/lib/web/live/clients/show.ex index 7531df302..b58916cd4 100644 --- a/elixir/apps/web/lib/web/live/clients/show.ex +++ b/elixir/apps/web/lib/web/live/clients/show.ex @@ -2,7 +2,7 @@ defmodule Web.Clients.Show do use Web, :live_view import Web.Policies.Components import Web.Clients.Components - alias Domain.{Accounts, Clients, Flows} + alias Domain.{Clients, Flows} def mount(%{"id" => id}, _session, socket) do with {:ok, client} <- @@ -21,7 +21,6 @@ defmodule Web.Clients.Show do assign( socket, client: client, - flow_activities_enabled?: Accounts.flow_activities_enabled?(socket.assigns.account), page_title: "Client #{client.name}" ) |> assign_live_table("flows", diff --git a/elixir/apps/web/lib/web/live/policies/show.ex b/elixir/apps/web/lib/web/live/policies/show.ex index 44751af53..236d16715 100644 --- a/elixir/apps/web/lib/web/live/policies/show.ex +++ b/elixir/apps/web/lib/web/live/policies/show.ex @@ -1,7 +1,7 @@ defmodule Web.Policies.Show do use Web, :live_view import Web.Policies.Components - alias Domain.{Accounts, Policies, PubSub, Flows, Auth} + alias Domain.{Policies, PubSub, Flows, Auth} def mount(%{"id" => id}, _session, socket) do with {:ok, policy} <- @@ -23,8 +23,7 @@ defmodule Web.Policies.Show do assign(socket, page_title: "Policy #{policy.id}", policy: policy, - providers: providers, - flow_activities_enabled?: Accounts.flow_activities_enabled?(socket.assigns.account) + providers: providers ) |> assign_live_table("flows", query_module: Flows.Flow.Query, diff --git a/elixir/apps/web/lib/web/live/resources/show.ex b/elixir/apps/web/lib/web/live/resources/show.ex index faa9ecf14..b12afd45a 100644 --- a/elixir/apps/web/lib/web/live/resources/show.ex +++ b/elixir/apps/web/lib/web/live/resources/show.ex @@ -2,7 +2,7 @@ defmodule Web.Resources.Show do use Web, :live_view import Web.Policies.Components import Web.Resources.Components - alias Domain.{Accounts, PubSub, Resources, Policies, Flows} + alias Domain.{PubSub, Resources, Policies, Flows} def mount(%{"id" => id} = params, _session, socket) do with {:ok, resource} <- fetch_resource(id, socket.assigns.subject), @@ -16,7 +16,6 @@ defmodule Web.Resources.Show do assign( socket, page_title: "Resource #{resource.name}", - flow_activities_enabled?: Accounts.flow_activities_enabled?(socket.assigns.account), resource: resource, actor_groups_peek: Map.fetch!(actor_groups_peek, resource.id), params: Map.take(params, ["site_id"]) diff --git a/elixir/apps/web/test/web/live/settings/api_clients/beta_test.exs b/elixir/apps/web/test/web/live/settings/api_clients/beta_test.exs index 8f46677a3..6352d9a07 100644 --- a/elixir/apps/web/test/web/live/settings/api_clients/beta_test.exs +++ b/elixir/apps/web/test/web/live/settings/api_clients/beta_test.exs @@ -68,7 +68,6 @@ defmodule Web.Live.Settings.ApiClients.BetaTest do features: %{ rest_api: false, traffic_filters: true, - flow_activities: true, policy_conditions: true, multi_site_resources: true, idp_sync: true diff --git a/elixir/config/config.exs b/elixir/config/config.exs index 84b133d8d..7a522b0ef 100644 --- a/elixir/config/config.exs +++ b/elixir/config/config.exs @@ -58,7 +58,6 @@ config :domain, Domain.ChangeLogs.ReplicationConnection, auth_identities auth_providers clients - flow_activities gateway_groups gateways policies @@ -93,7 +92,6 @@ config :domain, Domain.Events.ReplicationConnection, auth_identities auth_providers clients - flow_activities gateway_groups gateways policies @@ -176,7 +174,6 @@ config :domain, :enabled_features, idp_sync: true, traffic_filters: true, sign_up: true, - flow_activities: true, self_hosted_relays: true, policy_conditions: true, multi_site_resources: true, diff --git a/elixir/config/runtime.exs b/elixir/config/runtime.exs index 600bb3a8f..05d1d450e 100644 --- a/elixir/config/runtime.exs +++ b/elixir/config/runtime.exs @@ -101,7 +101,6 @@ if config_env() == :prod do config :domain, :enabled_features, idp_sync: env_var_to_config!(:feature_idp_sync_enabled), sign_up: env_var_to_config!(:feature_sign_up_enabled), - flow_activities: env_var_to_config!(:feature_flow_activities_enabled), self_hosted_relays: env_var_to_config!(:feature_self_hosted_relays_enabled), policy_conditions: env_var_to_config!(:feature_policy_conditions_enabled), multi_site_resources: env_var_to_config!(:feature_multi_site_resources_enabled),