mirror of
https://github.com/netbirdio/netbird.git
synced 2025-02-02 03:19:34 +01:00
[management] add activity events for networks (#3069)
This commit is contained in:
parent
b53935065b
commit
e40eb91e54
@ -276,10 +276,10 @@ var (
|
||||
userManager := users.NewManager(store)
|
||||
settingsManager := settings.NewManager(store)
|
||||
permissionsManager := permissions.NewManager(userManager, settingsManager)
|
||||
groupsManager := groups.NewManager(store, permissionsManager)
|
||||
groupsManager := groups.NewManager(store, permissionsManager, accountManager)
|
||||
resourcesManager := resources.NewManager(store, permissionsManager, groupsManager, accountManager)
|
||||
routersManager := routers.NewManager(store, permissionsManager, accountManager)
|
||||
networksManager := networks.NewManager(store, permissionsManager, resourcesManager)
|
||||
networksManager := networks.NewManager(store, permissionsManager, resourcesManager, routersManager, accountManager)
|
||||
|
||||
httpAPIHandler, err := httpapi.APIHandler(ctx, accountManager, networksManager, resourcesManager, routersManager, groupsManager, geo, *jwtValidator, appMetrics, httpAPIAuthCfg, integratedPeerValidator)
|
||||
if err != nil {
|
||||
|
@ -154,6 +154,21 @@ const (
|
||||
|
||||
AccountRoutingPeerDNSResolutionEnabled Activity = 71
|
||||
AccountRoutingPeerDNSResolutionDisabled Activity = 72
|
||||
|
||||
NetworkCreated Activity = 73
|
||||
NetworkUpdated Activity = 74
|
||||
NetworkDeleted Activity = 75
|
||||
|
||||
NetworkResourceCreated Activity = 76
|
||||
NetworkResourceUpdated Activity = 77
|
||||
NetworkResourceDeleted Activity = 78
|
||||
|
||||
NetworkRouterCreated Activity = 79
|
||||
NetworkRouterUpdated Activity = 80
|
||||
NetworkRouterDeleted Activity = 81
|
||||
|
||||
ResourceAddedToGroup Activity = 82
|
||||
ResourceRemovedFromGroup Activity = 83
|
||||
)
|
||||
|
||||
var activityMap = map[Activity]Code{
|
||||
@ -234,6 +249,21 @@ var activityMap = map[Activity]Code{
|
||||
|
||||
AccountRoutingPeerDNSResolutionEnabled: {"Account routing peer DNS resolution enabled", "account.setting.routing.peer.dns.resolution.enable"},
|
||||
AccountRoutingPeerDNSResolutionDisabled: {"Account routing peer DNS resolution disabled", "account.setting.routing.peer.dns.resolution.disable"},
|
||||
|
||||
NetworkCreated: {"Network created", "network.create"},
|
||||
NetworkUpdated: {"Network updated", "network.update"},
|
||||
NetworkDeleted: {"Network deleted", "network.delete"},
|
||||
|
||||
NetworkResourceCreated: {"Network resource created", "network.resource.create"},
|
||||
NetworkResourceUpdated: {"Network resource updated", "network.resource.update"},
|
||||
NetworkResourceDeleted: {"Network resource deleted", "network.resource.delete"},
|
||||
|
||||
NetworkRouterCreated: {"Network router created", "network.router.create"},
|
||||
NetworkRouterUpdated: {"Network router updated", "network.router.update"},
|
||||
NetworkRouterDeleted: {"Network router deleted", "network.router.delete"},
|
||||
|
||||
ResourceAddedToGroup: {"Resource added to group", "resource.group.add"},
|
||||
ResourceRemovedFromGroup: {"Resource removed from group", "resource.group.delete"},
|
||||
}
|
||||
|
||||
// StringCode returns a string code of the activity
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
s "github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
@ -14,22 +16,24 @@ type Manager interface {
|
||||
GetAllGroups(ctx context.Context, accountID, userID string) (map[string]*types.Group, error)
|
||||
GetResourceGroupsInTransaction(ctx context.Context, transaction store.Store, lockingStrength store.LockingStrength, accountID, resourceID string) ([]*types.Group, error)
|
||||
AddResourceToGroup(ctx context.Context, accountID, userID, groupID string, resourceID *types.Resource) error
|
||||
AddResourceToGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID string, resourceID *types.Resource) error
|
||||
RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID, resourceID string) error
|
||||
AddResourceToGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID string, resourceID *types.Resource) (func(), error)
|
||||
RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID, resourceID string) (func(), error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
store store.Store
|
||||
permissionsManager permissions.Manager
|
||||
accountManager s.AccountManager
|
||||
}
|
||||
|
||||
type mockManager struct {
|
||||
}
|
||||
|
||||
func NewManager(store store.Store, permissionsManager permissions.Manager) Manager {
|
||||
func NewManager(store store.Store, permissionsManager permissions.Manager, accountManager s.AccountManager) Manager {
|
||||
return &managerImpl{
|
||||
store: store,
|
||||
permissionsManager: permissionsManager,
|
||||
accountManager: accountManager,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,15 +68,40 @@ func (m *managerImpl) AddResourceToGroup(ctx context.Context, accountID, userID,
|
||||
return err
|
||||
}
|
||||
|
||||
return m.AddResourceToGroupInTransaction(ctx, m.store, accountID, groupID, resource)
|
||||
event, err := m.AddResourceToGroupInTransaction(ctx, m.store, accountID, groupID, resource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding resource to group: %w", err)
|
||||
}
|
||||
|
||||
event()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) AddResourceToGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID string, resource *types.Resource) error {
|
||||
return transaction.AddResourceToGroup(ctx, accountID, groupID, resource)
|
||||
func (m *managerImpl) AddResourceToGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID string, resource *types.Resource) (func(), error) {
|
||||
err := transaction.AddResourceToGroup(ctx, accountID, groupID, resource)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error adding resource to group: %w", err)
|
||||
}
|
||||
|
||||
event := func() {
|
||||
m.accountManager.StoreEvent(ctx, accountID, groupID, accountID, activity.ResourceAddedToGroup, nil)
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID, resourceID string) error {
|
||||
return transaction.RemoveResourceFromGroup(ctx, accountID, groupID, resourceID)
|
||||
func (m *managerImpl) RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID, resourceID string) (func(), error) {
|
||||
err := transaction.RemoveResourceFromGroup(ctx, accountID, groupID, resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error removing resource from group: %w", err)
|
||||
}
|
||||
|
||||
event := func() {
|
||||
m.accountManager.StoreEvent(ctx, accountID, groupID, accountID, activity.ResourceRemovedFromGroup, nil)
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetResourceGroupsInTransaction(ctx context.Context, transaction store.Store, lockingStrength store.LockingStrength, accountID, resourceID string) ([]*types.Group, error) {
|
||||
@ -128,12 +157,16 @@ func (m *mockManager) AddResourceToGroup(ctx context.Context, accountID, userID,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockManager) AddResourceToGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID string, resourceID *types.Resource) error {
|
||||
return nil
|
||||
func (m *mockManager) AddResourceToGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID string, resourceID *types.Resource) (func(), error) {
|
||||
return func() {
|
||||
// noop
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockManager) RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID, resourceID string) error {
|
||||
return nil
|
||||
func (m *mockManager) RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, groupID, resourceID string) (func(), error) {
|
||||
return func() {
|
||||
// noop
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewManagerMock() Manager {
|
||||
|
@ -6,7 +6,10 @@ import (
|
||||
|
||||
"github.com/rs/xid"
|
||||
|
||||
s "github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers"
|
||||
"github.com/netbirdio/netbird/management/server/networks/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
@ -23,15 +26,19 @@ type Manager interface {
|
||||
|
||||
type managerImpl struct {
|
||||
store store.Store
|
||||
accountManager s.AccountManager
|
||||
permissionsManager permissions.Manager
|
||||
resourcesManager resources.Manager
|
||||
routersManager routers.Manager
|
||||
}
|
||||
|
||||
func NewManager(store store.Store, permissionsManager permissions.Manager, manager resources.Manager) Manager {
|
||||
func NewManager(store store.Store, permissionsManager permissions.Manager, resourceManager resources.Manager, routersManager routers.Manager, accountManager s.AccountManager) Manager {
|
||||
return &managerImpl{
|
||||
store: store,
|
||||
permissionsManager: permissionsManager,
|
||||
resourcesManager: manager,
|
||||
resourcesManager: resourceManager,
|
||||
routersManager: routersManager,
|
||||
accountManager: accountManager,
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +65,14 @@ func (m *managerImpl) CreateNetwork(ctx context.Context, userID string, network
|
||||
|
||||
network.ID = xid.New().String()
|
||||
|
||||
return network, m.store.SaveNetwork(ctx, store.LockingStrengthUpdate, network)
|
||||
err = m.store.SaveNetwork(ctx, store.LockingStrengthUpdate, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save network: %w", err)
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, network.ID, network.AccountID, activity.NetworkCreated, network.EventMeta())
|
||||
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetNetwork(ctx context.Context, accountID, userID, networkID string) (*types.Network, error) {
|
||||
@ -82,6 +96,13 @@ func (m *managerImpl) UpdateNetwork(ctx context.Context, userID string, network
|
||||
return nil, status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
_, err = m.store.GetNetworkByID(ctx, store.LockingStrengthUpdate, network.AccountID, network.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, network.ID, network.AccountID, activity.NetworkUpdated, network.EventMeta())
|
||||
|
||||
return network, m.store.SaveNetwork(ctx, store.LockingStrengthUpdate, network)
|
||||
}
|
||||
|
||||
@ -94,20 +115,24 @@ func (m *managerImpl) DeleteNetwork(ctx context.Context, accountID, userID, netw
|
||||
return status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
unlock := m.store.AcquireWriteLockByUID(ctx, accountID)
|
||||
defer unlock()
|
||||
network, err := m.store.GetNetworkByID(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
return m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
var eventsToStore []func()
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
resources, err := transaction.GetNetworkResourcesByNetID(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get resources in network: %w", err)
|
||||
}
|
||||
|
||||
for _, resource := range resources {
|
||||
err = m.resourcesManager.DeleteResourceInTransaction(ctx, transaction, accountID, networkID, resource.ID)
|
||||
event, err := m.resourcesManager.DeleteResourceInTransaction(ctx, transaction, accountID, networkID, resource.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete resource: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event...)
|
||||
}
|
||||
|
||||
routers, err := transaction.GetNetworkRoutersByNetID(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
@ -116,12 +141,33 @@ func (m *managerImpl) DeleteNetwork(ctx context.Context, accountID, userID, netw
|
||||
}
|
||||
|
||||
for _, router := range routers {
|
||||
err = transaction.DeleteNetworkRouter(ctx, store.LockingStrengthUpdate, accountID, router.ID)
|
||||
event, err := m.routersManager.DeleteRouterInTransaction(ctx, transaction, accountID, networkID, router.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete router: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
}
|
||||
|
||||
return transaction.DeleteNetwork(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
err = transaction.DeleteNetwork(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete network: %w", err)
|
||||
}
|
||||
|
||||
eventsToStore = append(eventsToStore, func() {
|
||||
m.accountManager.StoreEvent(ctx, userID, networkID, accountID, activity.NetworkDeleted, network.EventMeta())
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete network: %w", err)
|
||||
}
|
||||
|
||||
for _, event := range eventsToStore {
|
||||
event()
|
||||
}
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers"
|
||||
"github.com/netbirdio/netbird/management/server/networks/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
@ -27,8 +28,9 @@ func Test_GetAllNetworksReturnsNetworks(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
networks, err := manager.GetAllNetworks(ctx, accountID, userID)
|
||||
require.NoError(t, err)
|
||||
@ -49,8 +51,9 @@ func Test_GetAllNetworksReturnsPermissionDenied(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
networks, err := manager.GetAllNetworks(ctx, accountID, userID)
|
||||
require.Error(t, err)
|
||||
@ -71,8 +74,9 @@ func Test_GetNetworkReturnsNetwork(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
networks, err := manager.GetNetwork(ctx, accountID, userID, networkID)
|
||||
require.NoError(t, err)
|
||||
@ -93,8 +97,9 @@ func Test_GetNetworkReturnsPermissionDenied(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
network, err := manager.GetNetwork(ctx, accountID, userID, networkID)
|
||||
require.Error(t, err)
|
||||
@ -117,8 +122,9 @@ func Test_CreateNetworkSuccessfully(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
createdNetwork, err := manager.CreateNetwork(ctx, userID, network)
|
||||
require.NoError(t, err)
|
||||
@ -141,8 +147,9 @@ func Test_CreateNetworkFailsWithPermissionDenied(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
createdNetwork, err := manager.CreateNetwork(ctx, userID, network)
|
||||
require.Error(t, err)
|
||||
@ -163,8 +170,9 @@ func Test_DeleteNetworkSuccessfully(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
err = manager.DeleteNetwork(ctx, accountID, userID, networkID)
|
||||
require.NoError(t, err)
|
||||
@ -184,8 +192,9 @@ func Test_DeleteNetworkFailsWithPermissionDenied(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
err = manager.DeleteNetwork(ctx, accountID, userID, networkID)
|
||||
require.Error(t, err)
|
||||
@ -208,8 +217,9 @@ func Test_UpdateNetworkSuccessfully(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
updatedNetwork, err := manager.UpdateNetwork(ctx, userID, network)
|
||||
require.NoError(t, err)
|
||||
@ -234,8 +244,9 @@ func Test_UpdateNetworkFailsWithPermissionDenied(t *testing.T) {
|
||||
am := mock_server.MockAccountManager{}
|
||||
permissionsManager := permissions.NewManagerMock()
|
||||
groupsManager := groups.NewManagerMock()
|
||||
routerManager := routers.NewManagerMock()
|
||||
resourcesManager := resources.NewManager(s, permissionsManager, groupsManager, &am)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager)
|
||||
manager := NewManager(s, permissionsManager, resourcesManager, routerManager, &am)
|
||||
|
||||
updatedNetwork, err := manager.UpdateNetwork(ctx, userID, network)
|
||||
require.Error(t, err)
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
s "github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
@ -23,7 +24,7 @@ type Manager interface {
|
||||
GetResource(ctx context.Context, accountID, userID, networkID, resourceID string) (*types.NetworkResource, error)
|
||||
UpdateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error)
|
||||
DeleteResource(ctx context.Context, accountID, userID, networkID, resourceID string) error
|
||||
DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, resourceID string) error
|
||||
DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, resourceID string) ([]func(), error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
@ -102,26 +103,38 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc
|
||||
return nil, fmt.Errorf("failed to create new network resource: %w", err)
|
||||
}
|
||||
|
||||
var eventsToStore []func()
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
_, err = transaction.GetNetworkResourceByName(ctx, store.LockingStrengthShare, resource.AccountID, resource.Name)
|
||||
if err == nil {
|
||||
return errors.New("resource already exists")
|
||||
}
|
||||
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, resource.AccountID, resource.NetworkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
err = transaction.SaveNetworkResource(ctx, store.LockingStrengthUpdate, resource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save network resource: %w", err)
|
||||
}
|
||||
|
||||
event := func() {
|
||||
m.accountManager.StoreEvent(ctx, userID, resource.ID, resource.AccountID, activity.NetworkResourceCreated, resource.EventMeta(network.Name))
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
|
||||
res := nbtypes.Resource{
|
||||
ID: resource.ID,
|
||||
Type: resource.Type.String(),
|
||||
}
|
||||
for _, groupID := range resource.GroupIDs {
|
||||
err = m.groupsManager.AddResourceToGroupInTransaction(ctx, transaction, resource.AccountID, groupID, &res)
|
||||
event, err := m.groupsManager.AddResourceToGroupInTransaction(ctx, transaction, resource.AccountID, groupID, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add resource to group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -130,6 +143,10 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc
|
||||
return nil, fmt.Errorf("failed to create network resource: %w", err)
|
||||
}
|
||||
|
||||
for _, event := range eventsToStore {
|
||||
event()
|
||||
}
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, resource.AccountID)
|
||||
|
||||
return resource, nil
|
||||
@ -174,7 +191,17 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
resource.Domain = domain
|
||||
resource.Prefix = prefix
|
||||
|
||||
var eventsToStore []func()
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, resource.AccountID, resource.NetworkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
if network.ID != resource.NetworkID {
|
||||
return status.NewResourceNotPartOfNetworkError(resource.ID, resource.NetworkID)
|
||||
}
|
||||
|
||||
_, err = transaction.GetNetworkResourceByID(ctx, store.LockingStrengthShare, resource.AccountID, resource.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network resource: %w", err)
|
||||
@ -195,8 +222,19 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
return fmt.Errorf("failed to save network resource: %w", err)
|
||||
}
|
||||
|
||||
return m.updateResourceGroups(ctx, transaction, resource, oldResource)
|
||||
events, err := m.updateResourceGroups(ctx, transaction, resource, oldResource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update resource groups: %w", err)
|
||||
}
|
||||
|
||||
eventsToStore = append(eventsToStore, events...)
|
||||
eventsToStore = append(eventsToStore, func() {
|
||||
m.accountManager.StoreEvent(ctx, userID, resource.ID, resource.AccountID, activity.NetworkResourceUpdated, resource.EventMeta(network.Name))
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update network resource: %w", err)
|
||||
}
|
||||
@ -206,7 +244,7 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) updateResourceGroups(ctx context.Context, transaction store.Store, newResource, oldResource *types.NetworkResource) error {
|
||||
func (m *managerImpl) updateResourceGroups(ctx context.Context, transaction store.Store, newResource, oldResource *types.NetworkResource) ([]func(), error) {
|
||||
res := nbtypes.Resource{
|
||||
ID: newResource.ID,
|
||||
Type: newResource.Type.String(),
|
||||
@ -214,7 +252,7 @@ func (m *managerImpl) updateResourceGroups(ctx context.Context, transaction stor
|
||||
|
||||
oldResourceGroups, err := m.groupsManager.GetResourceGroupsInTransaction(ctx, transaction, store.LockingStrengthUpdate, oldResource.AccountID, oldResource.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get resource groups: %w", err)
|
||||
return nil, fmt.Errorf("failed to get resource groups: %w", err)
|
||||
}
|
||||
|
||||
oldGroupsIds := make([]string, 0)
|
||||
@ -222,23 +260,26 @@ func (m *managerImpl) updateResourceGroups(ctx context.Context, transaction stor
|
||||
oldGroupsIds = append(oldGroupsIds, group.ID)
|
||||
}
|
||||
|
||||
var eventsToStore []func()
|
||||
groupsToAdd := util.Difference(newResource.GroupIDs, oldGroupsIds)
|
||||
for _, groupID := range groupsToAdd {
|
||||
err = m.groupsManager.AddResourceToGroupInTransaction(ctx, transaction, newResource.AccountID, groupID, &res)
|
||||
events, err := m.groupsManager.AddResourceToGroupInTransaction(ctx, transaction, newResource.AccountID, groupID, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add resource to group: %w", err)
|
||||
return nil, fmt.Errorf("failed to add resource to group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, events)
|
||||
}
|
||||
|
||||
groupsToRemove := util.Difference(oldGroupsIds, newResource.GroupIDs)
|
||||
for _, groupID := range groupsToRemove {
|
||||
err = m.groupsManager.RemoveResourceFromGroupInTransaction(ctx, transaction, newResource.AccountID, groupID, res.ID)
|
||||
events, err := m.groupsManager.RemoveResourceFromGroupInTransaction(ctx, transaction, newResource.AccountID, groupID, res.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add resource to group: %w", err)
|
||||
return nil, fmt.Errorf("failed to add resource to group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, events)
|
||||
}
|
||||
|
||||
return nil
|
||||
return eventsToStore, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, networkID, resourceID string) error {
|
||||
@ -253,44 +294,68 @@ func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, net
|
||||
unlock := m.store.AcquireWriteLockByUID(ctx, accountID)
|
||||
defer unlock()
|
||||
|
||||
var events []func()
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
return m.DeleteResourceInTransaction(ctx, transaction, accountID, networkID, resourceID)
|
||||
events, err = m.DeleteResourceInTransaction(ctx, transaction, accountID, networkID, resourceID)
|
||||
return err
|
||||
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete network resource: %w", err)
|
||||
}
|
||||
|
||||
for _, event := range events {
|
||||
event()
|
||||
}
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, resourceID string) error {
|
||||
func (m *managerImpl) DeleteResourceInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, resourceID string) ([]func(), error) {
|
||||
resource, err := transaction.GetNetworkResourceByID(ctx, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network resource: %w", err)
|
||||
return nil, fmt.Errorf("failed to get network resource: %w", err)
|
||||
}
|
||||
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, accountID, networkID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
if resource.NetworkID != networkID {
|
||||
return errors.New("resource not part of network")
|
||||
return nil, errors.New("resource not part of network")
|
||||
}
|
||||
|
||||
groups, err := m.groupsManager.GetResourceGroupsInTransaction(ctx, transaction, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get resource groups: %w", err)
|
||||
return nil, fmt.Errorf("failed to get resource groups: %w", err)
|
||||
}
|
||||
|
||||
var eventsToStore []func()
|
||||
|
||||
for _, group := range groups {
|
||||
err = m.groupsManager.RemoveResourceFromGroupInTransaction(ctx, transaction, accountID, group.ID, resourceID)
|
||||
event, err := m.groupsManager.RemoveResourceFromGroupInTransaction(ctx, transaction, accountID, group.ID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to remove resource from group: %w", err)
|
||||
return nil, fmt.Errorf("failed to remove resource from group: %w", err)
|
||||
}
|
||||
eventsToStore = append(eventsToStore, event)
|
||||
}
|
||||
|
||||
err = transaction.IncrementNetworkSerial(ctx, store.LockingStrengthUpdate, accountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to increment network serial: %w", err)
|
||||
return nil, fmt.Errorf("failed to increment network serial: %w", err)
|
||||
}
|
||||
|
||||
return transaction.DeleteNetworkResource(ctx, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
err = transaction.DeleteNetworkResource(ctx, store.LockingStrengthUpdate, accountID, resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to delete network resource: %w", err)
|
||||
}
|
||||
|
||||
eventsToStore = append(eventsToStore, func() {
|
||||
m.accountManager.StoreEvent(ctx, accountID, resourceID, accountID, activity.NetworkResourceDeleted, resource.EventMeta(network.Name))
|
||||
})
|
||||
|
||||
return eventsToStore, nil
|
||||
}
|
||||
|
@ -142,6 +142,10 @@ func (n *NetworkResource) ToRoute(peer *nbpeer.Peer, router *routerTypes.Network
|
||||
return r
|
||||
}
|
||||
|
||||
func (n *NetworkResource) EventMeta(networkName string) map[string]any {
|
||||
return map[string]any{"name": n.Name, "type": n.Type, "network_name": networkName}
|
||||
}
|
||||
|
||||
// GetResourceType returns the type of the resource based on the address
|
||||
func GetResourceType(address string) (NetworkResourceType, string, netip.Prefix, error) {
|
||||
if prefix, err := netip.ParsePrefix(address); err == nil {
|
||||
|
@ -8,7 +8,9 @@ import (
|
||||
"github.com/rs/xid"
|
||||
|
||||
s "github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
@ -21,6 +23,7 @@ type Manager interface {
|
||||
GetRouter(ctx context.Context, accountID, userID, networkID, routerID string) (*types.NetworkRouter, error)
|
||||
UpdateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error)
|
||||
DeleteRouter(ctx context.Context, accountID, userID, networkID, routerID string) error
|
||||
DeleteRouterInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, routerID string) (func(), error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
@ -29,6 +32,9 @@ type managerImpl struct {
|
||||
accountManager s.AccountManager
|
||||
}
|
||||
|
||||
type mockManager struct {
|
||||
}
|
||||
|
||||
func NewManager(store store.Store, permissionsManager permissions.Manager, accountManager s.AccountManager) Manager {
|
||||
return &managerImpl{
|
||||
store: store,
|
||||
@ -80,13 +86,32 @@ func (m *managerImpl) CreateRouter(ctx context.Context, userID string, router *t
|
||||
return nil, status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
router.ID = xid.New().String()
|
||||
var network *networkTypes.Network
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
network, err = transaction.GetNetworkByID(ctx, store.LockingStrengthShare, router.AccountID, router.NetworkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
err = m.store.SaveNetworkRouter(ctx, store.LockingStrengthUpdate, router)
|
||||
if network.ID != router.NetworkID {
|
||||
return status.NewNetworkNotFoundError(router.NetworkID)
|
||||
}
|
||||
|
||||
router.ID = xid.New().String()
|
||||
|
||||
err = transaction.SaveNetworkRouter(ctx, store.LockingStrengthUpdate, router)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create network router: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create network router: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, router.ID, router.AccountID, activity.NetworkRouterCreated, router.EventMeta(network.Name))
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, router.AccountID)
|
||||
|
||||
return router, nil
|
||||
@ -122,11 +147,30 @@ func (m *managerImpl) UpdateRouter(ctx context.Context, userID string, router *t
|
||||
return nil, status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
err = m.store.SaveNetworkRouter(ctx, store.LockingStrengthUpdate, router)
|
||||
var network *networkTypes.Network
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
network, err = transaction.GetNetworkByID(ctx, store.LockingStrengthShare, router.AccountID, router.NetworkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
if network.ID != router.NetworkID {
|
||||
return status.NewRouterNotPartOfNetworkError(router.ID, router.NetworkID)
|
||||
}
|
||||
|
||||
err = transaction.SaveNetworkRouter(ctx, store.LockingStrengthUpdate, router)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update network router: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update network router: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, router.ID, router.AccountID, activity.NetworkRouterUpdated, router.EventMeta(network.Name))
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, router.AccountID)
|
||||
|
||||
return router, nil
|
||||
@ -141,12 +185,77 @@ func (m *managerImpl) DeleteRouter(ctx context.Context, accountID, userID, netwo
|
||||
return status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
err = m.store.DeleteNetworkRouter(ctx, store.LockingStrengthUpdate, accountID, routerID)
|
||||
var event func()
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
event, err = m.DeleteRouterInTransaction(ctx, transaction, accountID, networkID, routerID)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete network router: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
event()
|
||||
|
||||
go m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) DeleteRouterInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, routerID string) (func(), error) {
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthShare, accountID, networkID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
router, err := transaction.GetNetworkRouterByID(ctx, store.LockingStrengthUpdate, accountID, routerID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network router: %w", err)
|
||||
}
|
||||
|
||||
if router.NetworkID != networkID {
|
||||
return nil, status.NewRouterNotPartOfNetworkError(routerID, networkID)
|
||||
}
|
||||
|
||||
err = transaction.DeleteNetworkRouter(ctx, store.LockingStrengthUpdate, accountID, routerID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to delete network router: %w", err)
|
||||
}
|
||||
|
||||
event := func() {
|
||||
m.accountManager.StoreEvent(ctx, "", routerID, accountID, activity.NetworkRouterDeleted, router.EventMeta(network.Name))
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func NewManagerMock() Manager {
|
||||
return &mockManager{}
|
||||
}
|
||||
|
||||
func (m *mockManager) GetAllRoutersInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error) {
|
||||
return []*types.NetworkRouter{}, nil
|
||||
}
|
||||
|
||||
func (m *mockManager) GetAllRoutersInAccount(ctx context.Context, accountID, userID string) (map[string][]*types.NetworkRouter, error) {
|
||||
return map[string][]*types.NetworkRouter{}, nil
|
||||
}
|
||||
|
||||
func (m *mockManager) CreateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) {
|
||||
return router, nil
|
||||
}
|
||||
|
||||
func (m *mockManager) GetRouter(ctx context.Context, accountID, userID, networkID, routerID string) (*types.NetworkRouter, error) {
|
||||
return &types.NetworkRouter{}, nil
|
||||
}
|
||||
|
||||
func (m *mockManager) UpdateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) {
|
||||
return router, nil
|
||||
}
|
||||
|
||||
func (m *mockManager) DeleteRouter(ctx context.Context, accountID, userID, networkID, routerID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockManager) DeleteRouterInTransaction(ctx context.Context, transaction store.Store, accountID, networkID, routerID string) (func(), error) {
|
||||
return func() {}, nil
|
||||
}
|
||||
|
@ -68,3 +68,7 @@ func (n *NetworkRouter) Copy() *NetworkRouter {
|
||||
Metric: n.Metric,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NetworkRouter) EventMeta(networkName string) map[string]any {
|
||||
return map[string]any{"network_name": networkName}
|
||||
}
|
||||
|
@ -49,3 +49,7 @@ func (n *Network) Copy() *Network {
|
||||
Description: n.Description,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) EventMeta() map[string]any {
|
||||
return map[string]any{"name": n.Name}
|
||||
}
|
||||
|
@ -178,3 +178,11 @@ func NewPermissionDeniedError() error {
|
||||
func NewPermissionValidationError(err error) error {
|
||||
return Errorf(PermissionDenied, "failed to vlidate user permissions: %s", err)
|
||||
}
|
||||
|
||||
func NewResourceNotPartOfNetworkError(resourceID, networkID string) error {
|
||||
return Errorf(BadRequest, "resource %s is not part of the network %s", resourceID, networkID)
|
||||
}
|
||||
|
||||
func NewRouterNotPartOfNetworkError(routerID, networkID string) error {
|
||||
return Errorf(BadRequest, "router %s is not part of the network %s", routerID, networkID)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user