[management] Add managers to link networks API with store (#3022)

This commit is contained in:
Pascal Fischer
2024-12-12 11:51:44 +01:00
committed by GitHub
parent 7944b8e843
commit d1d6875953
20 changed files with 582 additions and 54 deletions

View File

@@ -2,11 +2,14 @@ package networks
import (
"context"
"errors"
"github.com/rs/xid"
"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"
"github.com/netbirdio/netbird/management/server/store"
)
@@ -21,37 +24,81 @@ type Manager interface {
}
type managerImpl struct {
store store.Store
routersManager routers.Manager
resourcesManager resources.Manager
store store.Store
permissionsManager permissions.Manager
routersManager routers.Manager
resourcesManager resources.Manager
}
func NewManager(store store.Store) Manager {
func NewManager(store store.Store, permissionsManager permissions.Manager) Manager {
return &managerImpl{
store: store,
routersManager: routers.NewManager(store),
resourcesManager: resources.NewManager(store),
store: store,
permissionsManager: permissionsManager,
routersManager: routers.NewManager(store, permissionsManager),
resourcesManager: resources.NewManager(store, permissionsManager),
}
}
func (m *managerImpl) GetAllNetworks(ctx context.Context, accountID, userID string) ([]*types.Network, error) {
return nil, errors.New("not implemented")
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.GetAccountNetworks(ctx, store.LockingStrengthShare, accountID)
}
func (m *managerImpl) CreateNetwork(ctx context.Context, userID string, network *types.Network) (*types.Network, error) {
return nil, errors.New("not implemented")
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return nil, status.NewPermissionValidationError(err)
}
if !ok {
return nil, status.NewPermissionDeniedError()
}
network.ID = xid.New().String()
return network, m.store.SaveNetwork(ctx, store.LockingStrengthUpdate, network)
}
func (m *managerImpl) GetNetwork(ctx context.Context, accountID, userID, networkID string) (*types.Network, error) {
return nil, errors.New("not implemented")
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.GetNetworkByID(ctx, store.LockingStrengthShare, accountID, networkID)
}
func (m *managerImpl) UpdateNetwork(ctx context.Context, userID string, network *types.Network) (*types.Network, error) {
return nil, errors.New("not implemented")
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return nil, status.NewPermissionValidationError(err)
}
if !ok {
return nil, status.NewPermissionDeniedError()
}
return network, m.store.SaveNetwork(ctx, store.LockingStrengthUpdate, network)
}
func (m *managerImpl) DeleteNetwork(ctx context.Context, accountID, userID, networkID string) error {
return errors.New("not implemented")
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return status.NewPermissionValidationError(err)
}
if !ok {
return status.NewPermissionDeniedError()
}
return m.store.DeleteNetwork(ctx, store.LockingStrengthUpdate, accountID, networkID)
}
func (m *managerImpl) GetResourceManager() resources.Manager {

View File

@@ -3,45 +3,147 @@ package resources
import (
"context"
"errors"
"fmt"
"github.com/netbirdio/netbird/management/server/networks/resources/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 {
GetAllResources(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkResource, error)
CreateResource(ctx context.Context, accountID string, resource *types.NetworkResource) (*types.NetworkResource, error)
GetAllResourcesInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkResource, error)
GetAllResourcesInAccount(ctx context.Context, accountID, userID string) ([]*types.NetworkResource, error)
GetAllResourceIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, error)
CreateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error)
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
}
type managerImpl struct {
store store.Store
store store.Store
permissionsManager permissions.Manager
}
func NewManager(store store.Store) Manager {
func NewManager(store store.Store, permissionsManager permissions.Manager) Manager {
return &managerImpl{
store: store,
store: store,
permissionsManager: permissionsManager,
}
}
func (m *managerImpl) GetAllResources(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkResource, error) {
return nil, errors.New("not implemented")
func (m *managerImpl) GetAllResourcesInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkResource, 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.GetNetworkResourcesByNetID(ctx, store.LockingStrengthShare, accountID, networkID)
}
func (m *managerImpl) CreateResource(ctx context.Context, accountID string, resource *types.NetworkResource) (*types.NetworkResource, error) {
return nil, errors.New("not implemented")
func (m *managerImpl) GetAllResourcesInAccount(ctx context.Context, accountID, userID string) ([]*types.NetworkResource, 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.GetNetworkResourcesByAccountID(ctx, store.LockingStrengthShare, accountID)
}
func (m *managerImpl) GetAllResourceIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, 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()
}
resources, err := m.store.GetNetworkResourcesByAccountID(ctx, store.LockingStrengthShare, accountID)
if err != nil {
return nil, fmt.Errorf("failed to get network resources: %w", err)
}
resourceMap := make(map[string][]string)
for _, resource := range resources {
resourceMap[resource.NetworkID] = append(resourceMap[resource.NetworkID], resource.ID)
}
return resourceMap, nil
}
func (m *managerImpl) CreateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error) {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, resource.AccountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return nil, status.NewPermissionValidationError(err)
}
if !ok {
return nil, status.NewPermissionDeniedError()
}
resource, err = types.NewNetworkResource(resource.AccountID, resource.NetworkID, resource.Name, resource.Description, resource.Address)
if err != nil {
return nil, fmt.Errorf("failed to create new network resource: %w", err)
}
return resource, m.store.SaveNetworkResource(ctx, store.LockingStrengthUpdate, resource)
}
func (m *managerImpl) GetResource(ctx context.Context, accountID, userID, networkID, resourceID string) (*types.NetworkResource, error) {
return nil, errors.New("not implemented")
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()
}
resource, err := m.store.GetNetworkResourceByID(ctx, store.LockingStrengthShare, accountID, resourceID)
if err != nil {
return nil, fmt.Errorf("failed to get network resource: %w", err)
}
if resource.NetworkID != networkID {
return nil, errors.New("resource not part of network")
}
return resource, nil
}
func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resource *types.NetworkResource) (*types.NetworkResource, error) {
return nil, errors.New("not implemented")
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, resource.AccountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return nil, status.NewPermissionValidationError(err)
}
if !ok {
return nil, status.NewPermissionDeniedError()
}
resourceType, err := types.GetResourceType(resource.Address)
if err != nil {
return nil, fmt.Errorf("failed to get resource type: %w", err)
}
resource.Type = resourceType
return resource, m.store.SaveNetworkResource(ctx, store.LockingStrengthUpdate, resource)
}
func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, networkID, resourceID string) error {
return errors.New("not implemented")
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return status.NewPermissionValidationError(err)
}
if !ok {
return status.NewPermissionDeniedError()
}
return m.store.DeleteNetworkResource(ctx, store.LockingStrengthUpdate, accountID, resourceID)
}

View File

@@ -35,7 +35,7 @@ type NetworkResource struct {
}
func NewNetworkResource(accountID, networkID, name, description, address string) (*NetworkResource, error) {
resourceType, err := getResourceType(address)
resourceType, err := GetResourceType(address)
if err != nil {
return nil, fmt.Errorf("invalid address: %w", err)
}
@@ -63,7 +63,7 @@ func (n *NetworkResource) ToAPIResponse() *api.NetworkResource {
func (n *NetworkResource) FromAPIRequest(req *api.NetworkResourceRequest) {
n.Name = req.Name
n.Description = ""
if req.Description != nil {
n.Description = *req.Description
}
@@ -82,8 +82,8 @@ func (n *NetworkResource) Copy() *NetworkResource {
}
}
// getResourceType returns the type of the resource based on the address
func getResourceType(address string) (NetworkResourceType, error) {
// GetResourceType returns the type of the resource based on the address
func GetResourceType(address string) (NetworkResourceType, error) {
if ip, cidr, err := net.ParseCIDR(address); err == nil {
ones, _ := cidr.Mask.Size()
if strings.HasSuffix(address, "/32") || (ip != nil && ones == 32) {

View File

@@ -28,7 +28,7 @@ func TestGetResourceType(t *testing.T) {
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
result, err := getResourceType(tt.input)
result, err := GetResourceType(tt.input)
if result != tt.expectedType {
t.Errorf("Expected type %v, got %v", tt.expectedType, result)
}

View File

@@ -3,13 +3,19 @@ package routers
import (
"context"
"errors"
"fmt"
"github.com/rs/xid"
"github.com/netbirdio/netbird/management/server/networks/routers/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 {
GetAllRouters(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error)
GetAllRoutersInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error)
GetAllRouterIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, 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)
@@ -17,31 +23,106 @@ type Manager interface {
}
type managerImpl struct {
store store.Store
store store.Store
permissionsManager permissions.Manager
}
func NewManager(store store.Store) Manager {
func NewManager(store store.Store, permissionsManager permissions.Manager) Manager {
return &managerImpl{
store: store,
store: store,
permissionsManager: permissionsManager,
}
}
func (m *managerImpl) GetAllRouters(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error) {
return nil, errors.New("not implemented")
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) GetAllRouterIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, 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][]string)
for _, router := range routers {
routersMap[router.NetworkID] = append(routersMap[router.NetworkID], router.ID)
}
return routersMap, nil
}
func (m *managerImpl) CreateRouter(ctx context.Context, userID string, router *types.NetworkRouter) (*types.NetworkRouter, error) {
return nil, errors.New("not implemented")
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()
}
router.ID = xid.New().String()
return router, m.store.SaveNetworkRouter(ctx, store.LockingStrengthUpdate, router)
}
func (m *managerImpl) GetRouter(ctx context.Context, accountID, userID, networkID, routerID string) (*types.NetworkRouter, error) {
return nil, errors.New("not implemented")
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) {
return nil, errors.New("not implemented")
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()
}
return router, m.store.SaveNetworkRouter(ctx, store.LockingStrengthUpdate, router)
}
func (m *managerImpl) DeleteRouter(ctx context.Context, accountID, userID, networkID, routerID string) error {
return errors.New("not implemented")
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Networks, permissions.Write)
if err != nil {
return status.NewPermissionValidationError(err)
}
if !ok {
return status.NewPermissionDeniedError()
}
return m.store.DeleteNetworkRouter(ctx, store.LockingStrengthUpdate, accountID, routerID)
}

View File

@@ -45,8 +45,14 @@ func (n *NetworkRouter) ToAPIResponse() *api.NetworkRouter {
}
func (n *NetworkRouter) FromAPIRequest(req *api.NetworkRouterRequest) {
n.Peer = *req.Peer
n.PeerGroups = *req.PeerGroups
if req.Peer != nil {
n.Peer = *req.Peer
}
if req.PeerGroups != nil {
n.PeerGroups = *req.PeerGroups
}
n.Masquerade = req.Masquerade
n.Metric = req.Metric
}

View File

@@ -22,17 +22,21 @@ func NewNetwork(accountId, name, description string) *Network {
}
}
func (n *Network) ToAPIResponse() *api.Network {
func (n *Network) ToAPIResponse(routerIDs []string, resourceIDs []string) *api.Network {
return &api.Network{
Id: n.ID,
Name: n.Name,
Description: &n.Description,
Routers: routerIDs,
Resources: resourceIDs,
}
}
func (n *Network) FromAPIRequest(req *api.NetworkRequest) {
n.Name = req.Name
n.Description = *req.Description
if req.Description != nil {
n.Description = *req.Description
}
}
// Copy returns a copy of a posture checks.