mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-22 13:29:08 +02:00
[management] Clean up after account deletion (#7812)
Deleting an account left state behind that DeleteAccount's store associations don't reach. The Agent Network tables outlived the account, keeping its gateway domain claimed and its provider API keys stored. The proxies kept serving its gateway until they next resynced. Cloud-side state, such as managed proxy deployments, had no way to be cleaned up at all. Account deletion now runs registered hooks after the permission check and before any users or data are removed. A failing hook aborts the deletion. Agent Network registers one that tells the proxies to drop the account's gateway mappings. The account's settings, providers, policies, guardrails and budget rules are deleted in the account's transaction. Consumption counters, and the access logs of deleted accounts, are left to the background cleanup; usage records are kept.
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
agentNetworkTypes "github.com/netbirdio/netbird/management/internals/modules/agentnetwork/types"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
@@ -162,6 +163,10 @@ func (s *SqlStore) DeleteAccount(ctx context.Context, account *types.Account) er
|
||||
return result.Error
|
||||
}
|
||||
|
||||
if err := deleteAgentNetworkAccountConfig(tx, account.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result = tx.Select(clause.Associations).Delete(account)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
@@ -179,6 +184,29 @@ func (s *SqlStore) DeleteAccount(ctx context.Context, account *types.Account) er
|
||||
return err
|
||||
}
|
||||
|
||||
// deleteAgentNetworkAccountConfig removes the account's agent network configuration. These
|
||||
// tables are not account associations, so deleting the account does not reach them. The
|
||||
// settings row holds the account's globally unique gateway domain and the provider rows
|
||||
// hold its upstream API keys. Tables that grow with traffic are left out: consumption
|
||||
// counters and access logs are swept in the background, and usage records are kept.
|
||||
func deleteAgentNetworkAccountConfig(tx *gorm.DB, accountID string) error {
|
||||
// Dependents first: policies point at providers and guardrails, and settings
|
||||
// go last, as DeleteSettings refuses while providers exist.
|
||||
models := []any{
|
||||
&agentNetworkTypes.Policy{},
|
||||
&agentNetworkTypes.Provider{},
|
||||
&agentNetworkTypes.Guardrail{},
|
||||
&agentNetworkTypes.AccountBudgetRule{},
|
||||
&agentNetworkTypes.Settings{},
|
||||
}
|
||||
for _, model := range models {
|
||||
if err := tx.Delete(model, "account_id = ?", accountID).Error; err != nil {
|
||||
return fmt.Errorf("delete %T rows: %w", model, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) UpdateAccountDomainAttributes(ctx context.Context, accountID string, domain string, category string, isPrimaryDomain bool) error {
|
||||
accountCopy := types.Account{
|
||||
Domain: domain,
|
||||
|
||||
Reference in New Issue
Block a user