refactor(portal): remove flow_activities (#9693)

This has been dead code for a long time. The feature this was meant to
support, #8353, will require a different domain model, views, and user
flows.

Related: #8353
This commit is contained in:
Jamil
2025-06-27 13:40:25 -07:00
committed by GitHub
parent 9655dacc04
commit dddd1b57fc
29 changed files with 31 additions and 708 deletions

View File

@@ -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"

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.
"""

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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)

View File

@@ -18,7 +18,6 @@ defmodule Domain.Fixtures.Accounts do
]
},
features: %{
flow_activities: true,
policy_conditions: true,
multi_site_resources: true,
traffic_filters: true,

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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,

View File

@@ -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"])

View File

@@ -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

View File

@@ -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,

View File

@@ -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),