Skip to content

Commit

Permalink
[management] Add managers to link networks API with store (#3022)
Browse files Browse the repository at this point in the history
  • Loading branch information
pascal-fischer authored Dec 12, 2024
1 parent 7944b8e commit d1d6875
Show file tree
Hide file tree
Showing 20 changed files with 582 additions and 54 deletions.
21 changes: 19 additions & 2 deletions management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ import (
"github.com/netbirdio/netbird/management/server/jwtclaims"
"github.com/netbirdio/netbird/management/server/networks"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/management/server/permissions"
"github.com/netbirdio/netbird/management/server/posture"
"github.com/netbirdio/netbird/management/server/settings"
"github.com/netbirdio/netbird/management/server/status"
"github.com/netbirdio/netbird/management/server/store"
"github.com/netbirdio/netbird/management/server/telemetry"
"github.com/netbirdio/netbird/management/server/types"
"github.com/netbirdio/netbird/management/server/users"
"github.com/netbirdio/netbird/management/server/util"
"github.com/netbirdio/netbird/route"
)
Expand Down Expand Up @@ -149,6 +152,7 @@ type AccountManager interface {
GetAccountSettings(ctx context.Context, accountID string, userID string) (*types.Settings, error)
DeleteSetupKey(ctx context.Context, accountID, userID, keyID string) error
GetNetworksManager() networks.Manager
GetUserManager() users.Manager
}

type DefaultAccountManager struct {
Expand Down Expand Up @@ -186,7 +190,10 @@ type DefaultAccountManager struct {

metrics telemetry.AppMetrics

networksManager networks.Manager
networksManager networks.Manager
userManager users.Manager
settingsManager settings.Manager
permissionsManager permissions.Manager
}

// getJWTGroupsChanges calculates the changes needed to sync a user's JWT groups.
Expand Down Expand Up @@ -253,12 +260,18 @@ func BuildManager(
integratedPeerValidator integrated_validator.IntegratedValidator,
metrics telemetry.AppMetrics,
) (*DefaultAccountManager, error) {
userManager := users.NewManager(store)
settingsManager := settings.NewManager(store)
permissionsManager := permissions.NewManager(userManager, settingsManager)
am := &DefaultAccountManager{
Store: store,
geo: geo,
peersUpdateManager: peersUpdateManager,
idpManager: idpManager,
networksManager: networks.NewManager(store),
networksManager: networks.NewManager(store, permissionsManager),
userManager: userManager,
settingsManager: settingsManager,
permissionsManager: permissionsManager,
ctx: context.Background(),
cacheMux: sync.Mutex{},
cacheLoading: map[string]chan struct{}{},
Expand Down Expand Up @@ -1721,6 +1734,10 @@ func (am *DefaultAccountManager) GetNetworksManager() networks.Manager {
return am.networksManager
}

func (am *DefaultAccountManager) GetUserManager() users.Manager {
return am.userManager
}

// addAllGroup to account object if it doesn't exist
func addAllGroup(account *types.Account) error {
if len(account.Groups) == 0 {
Expand Down
14 changes: 14 additions & 0 deletions management/server/http/api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1221,8 +1221,22 @@ components:
description: Network ID
type: string
example: chacdk86lnnboviihd7g
routers:
description: List of router IDs associated with the network
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
resources:
description: List of network resource IDs associated with the network
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m1
required:
- id
- routers
- resources
- $ref: '#/components/schemas/NetworkRequest'
NetworkResourceRequest:
type: object
Expand Down
6 changes: 6 additions & 0 deletions management/server/http/api/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 53 additions & 4 deletions management/server/http/handlers/networks/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package networks
import (
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/gorilla/mux"
Expand Down Expand Up @@ -59,9 +60,21 @@ func (h *handler) getAllNetworks(w http.ResponseWriter, r *http.Request) {
return
}

routers, err := h.networksManager.GetRouterManager().GetAllRouterIDsInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

resources, err := h.networksManager.GetResourceManager().GetAllResourceIDsInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

var networkResponse []*api.Network
for _, network := range networks {
networkResponse = append(networkResponse, network.ToAPIResponse())
networkResponse = append(networkResponse, network.ToAPIResponse(routers[network.ID], resources[network.ID]))
}

util.WriteJSONObject(r.Context(), w, networkResponse)
Expand Down Expand Up @@ -92,7 +105,7 @@ func (h *handler) createNetwork(w http.ResponseWriter, r *http.Request) {
return
}

util.WriteJSONObject(r.Context(), w, network.ToAPIResponse())
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse([]string{}, []string{}))
}

func (h *handler) getNetwork(w http.ResponseWriter, r *http.Request) {
Expand All @@ -116,7 +129,13 @@ func (h *handler) getNetwork(w http.ResponseWriter, r *http.Request) {
return
}

util.WriteJSONObject(r.Context(), w, network.ToAPIResponse())
routerIDs, resourceIDs, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs))
}

func (h *handler) updateNetwork(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -152,7 +171,13 @@ func (h *handler) updateNetwork(w http.ResponseWriter, r *http.Request) {
return
}

util.WriteJSONObject(r.Context(), w, network.ToAPIResponse())
routerIDs, resourceIDs, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs))
}

func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request) {
Expand All @@ -178,3 +203,27 @@ func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request) {

util.WriteJSONObject(r.Context(), w, util.EmptyObject{})
}

func (h *handler) collectIDsInNetwork(ctx context.Context, accountID, userID, networkID string) ([]string, []string, error) {
resources, err := h.networksManager.GetResourceManager().GetAllResourcesInNetwork(ctx, accountID, userID, networkID)
if err != nil {
return nil, nil, fmt.Errorf("failed to get resources in network: %w", err)
}

var resourceIDs []string
for _, resource := range resources {
resourceIDs = append(resourceIDs, resource.ID)
}

routers, err := h.networksManager.GetRouterManager().GetAllRoutersInNetwork(ctx, accountID, userID, networkID)
if err != nil {
return nil, nil, fmt.Errorf("failed to get routers in network: %w", err)
}

var routerIDs []string
for _, router := range routers {
routerIDs = append(routerIDs, router.ID)
}

return routerIDs, resourceIDs, nil
}
28 changes: 25 additions & 3 deletions management/server/http/handlers/networks/resources_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ type resourceHandler struct {

func addResourceEndpoints(resourcesManager resources.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
resourceHandler := newResourceHandler(resourcesManager, extractFromToken, authCfg)
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.getAllResources).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.getAllResourcesInNetwork).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.createResource).Methods("POST", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.getResource).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.updateResource).Methods("PUT", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.deleteResource).Methods("DELETE", "OPTIONS")
router.HandleFunc("/networks/resources", resourceHandler.getAllResourcesInAccount).Methods("GET", "OPTIONS")
}

func newResourceHandler(resourceManager resources.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *resourceHandler {
Expand All @@ -41,7 +42,7 @@ func newResourceHandler(resourceManager resources.Manager, extractFromToken func
}
}

func (h *resourceHandler) getAllResources(w http.ResponseWriter, r *http.Request) {
func (h *resourceHandler) getAllResourcesInNetwork(w http.ResponseWriter, r *http.Request) {
claims := h.claimsExtractor.FromRequestContext(r)
accountID, userID, err := h.extractFromToken(r.Context(), claims)
if err != nil {
Expand All @@ -50,7 +51,28 @@ func (h *resourceHandler) getAllResources(w http.ResponseWriter, r *http.Request
}

networkID := mux.Vars(r)["networkId"]
resources, err := h.resourceManager.GetAllResources(r.Context(), accountID, userID, networkID)
resources, err := h.resourceManager.GetAllResourcesInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

var resourcesResponse []*api.NetworkResource
for _, resource := range resources {
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse())
}

util.WriteJSONObject(r.Context(), w, resourcesResponse)
}
func (h *resourceHandler) getAllResourcesInAccount(w http.ResponseWriter, r *http.Request) {
claims := h.claimsExtractor.FromRequestContext(r)
accountID, userID, err := h.extractFromToken(r.Context(), claims)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

resources, err := h.resourceManager.GetAllResourcesInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (h *routersHandler) getAllRouters(w http.ResponseWriter, r *http.Request) {
}

networkID := mux.Vars(r)["networkId"]
routers, err := h.routersManager.GetAllRouters(r.Context(), accountID, userID, networkID)
routers, err := h.routersManager.GetAllRoutersInNetwork(r.Context(), accountID, userID, networkID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
Expand Down
6 changes: 6 additions & 0 deletions management/server/mock_server/account_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/management/server/posture"
"github.com/netbirdio/netbird/management/server/types"
"github.com/netbirdio/netbird/management/server/users"
"github.com/netbirdio/netbird/route"
)

Expand Down Expand Up @@ -113,6 +114,11 @@ type MockAccountManager struct {
DeleteSetupKeyFunc func(ctx context.Context, accountID, userID, keyID string) error
}

func (am *MockAccountManager) GetUserManager() users.Manager {
// TODO implement me
panic("implement me")
}

func (am *MockAccountManager) GetNetworksManager() networks.Manager {
// TODO implement me
panic("implement me")
Expand Down
73 changes: 60 additions & 13 deletions management/server/networks/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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 {
Expand Down
Loading

0 comments on commit d1d6875

Please sign in to comment.