mirror of
https://github.com/netbirdio/netbird.git
synced 2025-02-09 23:09:38 +01:00
--------- Co-authored-by: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Co-authored-by: bcmmbaga <bethuelmbaga12@gmail.com> Co-authored-by: Maycon Santos <mlsmaycon@gmail.com> Co-authored-by: Zoltan Papp <zoltan.pmail@gmail.com>
290 lines
9.8 KiB
Go
290 lines
9.8 KiB
Go
package routers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"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"
|
|
)
|
|
|
|
type Manager interface {
|
|
GetAllRoutersInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error)
|
|
GetAllRoutersInAccount(ctx context.Context, accountID, userID string) (map[string][]*types.NetworkRouter, error)
|
|
CreateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error)
|
|
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, userID, networkID, routerID 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, accountManager s.AccountManager) Manager {
|
|
return &managerImpl{
|
|
store: store,
|
|
permissionsManager: permissionsManager,
|
|
accountManager: accountManager,
|
|
}
|
|
}
|
|
|
|
func (m *managerImpl) GetAllRoutersInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
return m.store.GetNetworkRoutersByNetID(ctx, store.LockingStrengthShare, accountID, networkID)
|
|
}
|
|
|
|
func (m *managerImpl) GetAllRoutersInAccount(ctx context.Context, accountID, userID string) (map[string][]*types.NetworkRouter, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
routers, err := m.store.GetNetworkRoutersByAccountID(ctx, store.LockingStrengthShare, accountID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get network routers: %w", err)
|
|
}
|
|
|
|
routersMap := make(map[string][]*types.NetworkRouter)
|
|
for _, router := range routers {
|
|
routersMap[router.NetworkID] = append(routersMap[router.NetworkID], router)
|
|
}
|
|
|
|
return routersMap, nil
|
|
}
|
|
|
|
func (m *managerImpl) CreateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, router.AccountID, userID, permissions.Networks, permissions.Write)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
unlock := m.store.AcquireWriteLockByUID(ctx, router.AccountID)
|
|
defer unlock()
|
|
|
|
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.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)
|
|
}
|
|
|
|
err = transaction.IncrementNetworkSerial(ctx, store.LockingStrengthUpdate, router.AccountID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to increment network serial: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.accountManager.StoreEvent(ctx, userID, router.ID, router.AccountID, activity.NetworkRouterCreated, router.EventMeta(network))
|
|
|
|
go m.accountManager.UpdateAccountPeers(ctx, router.AccountID)
|
|
|
|
return router, nil
|
|
}
|
|
|
|
func (m *managerImpl) GetRouter(ctx context.Context, accountID, userID, networkID, routerID string) (*types.NetworkRouter, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Read)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
router, err := m.store.GetNetworkRouterByID(ctx, store.LockingStrengthShare, accountID, routerID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get network router: %w", err)
|
|
}
|
|
|
|
if router.NetworkID != networkID {
|
|
return nil, errors.New("router not part of network")
|
|
}
|
|
|
|
return router, nil
|
|
}
|
|
|
|
func (m *managerImpl) UpdateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, router.AccountID, userID, permissions.Networks, permissions.Write)
|
|
if err != nil {
|
|
return nil, status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return nil, status.NewPermissionDeniedError()
|
|
}
|
|
|
|
unlock := m.store.AcquireWriteLockByUID(ctx, router.AccountID)
|
|
defer unlock()
|
|
|
|
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)
|
|
}
|
|
|
|
err = transaction.IncrementNetworkSerial(ctx, store.LockingStrengthUpdate, router.AccountID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to increment network serial: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m.accountManager.StoreEvent(ctx, userID, router.ID, router.AccountID, activity.NetworkRouterUpdated, router.EventMeta(network))
|
|
|
|
go m.accountManager.UpdateAccountPeers(ctx, router.AccountID)
|
|
|
|
return router, nil
|
|
}
|
|
|
|
func (m *managerImpl) DeleteRouter(ctx context.Context, accountID, userID, networkID, routerID string) error {
|
|
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write)
|
|
if err != nil {
|
|
return status.NewPermissionValidationError(err)
|
|
}
|
|
if !ok {
|
|
return status.NewPermissionDeniedError()
|
|
}
|
|
|
|
unlock := m.store.AcquireWriteLockByUID(ctx, accountID)
|
|
defer unlock()
|
|
|
|
var event func()
|
|
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
|
event, err = m.DeleteRouterInTransaction(ctx, transaction, accountID, userID, networkID, routerID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete network router: %w", err)
|
|
}
|
|
|
|
err = transaction.IncrementNetworkSerial(ctx, store.LockingStrengthUpdate, accountID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to increment network serial: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
event()
|
|
|
|
go m.accountManager.UpdateAccountPeers(ctx, accountID)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *managerImpl) DeleteRouterInTransaction(ctx context.Context, transaction store.Store, accountID, userID, 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, userID, routerID, accountID, activity.NetworkRouterDeleted, router.EventMeta(network))
|
|
}
|
|
|
|
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, userID, networkID, routerID string) (func(), error) {
|
|
return func() {}, nil
|
|
}
|