mirror of
https://github.com/netbirdio/netbird.git
synced 2025-01-20 21:08:45 +01:00
[management] Add managers to link networks API with store (#3022)
This commit is contained in:
parent
7944b8e843
commit
d1d6875953
@ -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"
|
||||
)
|
||||
@ -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 {
|
||||
@ -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.
|
||||
@ -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{}{},
|
||||
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -518,6 +518,12 @@ type Network struct {
|
||||
|
||||
// Name Network name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Resources List of network resource IDs associated with the network
|
||||
Resources []string `json:"resources"`
|
||||
|
||||
// Routers List of router IDs associated with the network
|
||||
Routers []string `json:"routers"`
|
||||
}
|
||||
|
||||
// NetworkRequest defines model for NetworkRequest.
|
||||
|
@ -3,6 +3,7 @@ package networks
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
@ -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)
|
||||
@ -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) {
|
||||
@ -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) {
|
||||
@ -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) {
|
||||
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
@ -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 {
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
)
|
||||
|
||||
@ -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")
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
|
87
management/server/permissions/manager.go
Normal file
87
management/server/permissions/manager.go
Normal file
@ -0,0 +1,87 @@
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/settings"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
"github.com/netbirdio/netbird/management/server/users"
|
||||
)
|
||||
|
||||
type Module string
|
||||
|
||||
const (
|
||||
Networks Module = "networks"
|
||||
Peers Module = "peers"
|
||||
)
|
||||
|
||||
type Operation string
|
||||
|
||||
const (
|
||||
Read Operation = "read"
|
||||
Write Operation = "write"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
userManager users.Manager
|
||||
settingsManager settings.Manager
|
||||
}
|
||||
|
||||
func NewManager(userManager users.Manager, settingsManager settings.Manager) Manager {
|
||||
return &managerImpl{
|
||||
userManager: userManager,
|
||||
settingsManager: settingsManager,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *managerImpl) ValidateUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) {
|
||||
user, err := m.userManager.GetUser(ctx, userID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
return false, errors.New("user not found")
|
||||
}
|
||||
|
||||
if user.AccountID != accountID {
|
||||
return false, errors.New("user does not belong to account")
|
||||
}
|
||||
|
||||
switch user.Role {
|
||||
case types.UserRoleAdmin, types.UserRoleOwner:
|
||||
return true, nil
|
||||
case types.UserRoleUser:
|
||||
return m.validateRegularUserPermissions(ctx, accountID, userID, module, operation)
|
||||
case types.UserRoleBillingAdmin:
|
||||
return false, nil
|
||||
default:
|
||||
return false, errors.New("invalid role")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *managerImpl) validateRegularUserPermissions(ctx context.Context, accountID, userID string, module Module, operation Operation) (bool, error) {
|
||||
settings, err := m.settingsManager.GetSettings(ctx, accountID, userID)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get settings: %w", err)
|
||||
}
|
||||
if settings.RegularUsersViewBlocked {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if operation == Write {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if module == Peers {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
26
management/server/settings/manager.go
Normal file
26
management/server/settings/manager.go
Normal file
@ -0,0 +1,26 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
GetSettings(ctx context.Context, accountID string, userID string) (*types.Settings, error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
func NewManager(store store.Store) Manager {
|
||||
return &managerImpl{
|
||||
store: store,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetSettings(ctx context.Context, accountID string, userID string) (*types.Settings, error) {
|
||||
return m.store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
||||
}
|
@ -169,3 +169,12 @@ func NewNetworkRouterNotFoundError(routerID string) error {
|
||||
func NewNetworkResourceNotFoundError(resourceID string) error {
|
||||
return Errorf(NotFound, "network resource: %s not found", resourceID)
|
||||
}
|
||||
|
||||
// NewPermissionDeniedError creates a new Error with PermissionDenied type for a permission denied error.
|
||||
func NewPermissionDeniedError() error {
|
||||
return Errorf(PermissionDenied, "permission denied")
|
||||
}
|
||||
|
||||
func NewPermissionValidationError(err error) error {
|
||||
return Errorf(PermissionDenied, "failed to vlidate user permissions: %s", err)
|
||||
}
|
||||
|
@ -1667,6 +1667,18 @@ func (s *SqlStore) GetNetworkRoutersByNetID(ctx context.Context, lockStrength Lo
|
||||
return netRouters, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetNetworkRoutersByAccountID(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*routerTypes.NetworkRouter, error) {
|
||||
var netRouters []*routerTypes.NetworkRouter
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Find(&netRouters, accountIDCondition, accountID)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to get network routers from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get network routers from store")
|
||||
}
|
||||
|
||||
return netRouters, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetNetworkRouterByID(ctx context.Context, lockStrength LockingStrength, accountID, routerID string) (*routerTypes.NetworkRouter, error) {
|
||||
var netRouter *routerTypes.NetworkRouter
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
@ -1719,6 +1731,18 @@ func (s *SqlStore) GetNetworkResourcesByNetID(ctx context.Context, lockStrength
|
||||
return netResources, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetNetworkResourcesByAccountID(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*resourceTypes.NetworkResource, error) {
|
||||
var netResources []*resourceTypes.NetworkResource
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Find(&netResources, accountIDCondition, accountID)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to get network resources from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get network resources from store")
|
||||
}
|
||||
|
||||
return netResources, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetNetworkResourceByID(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) (*resourceTypes.NetworkResource, error) {
|
||||
var netResources *resourceTypes.NetworkResource
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
|
@ -151,11 +151,13 @@ type Store interface {
|
||||
DeleteNetwork(ctx context.Context, lockStrength LockingStrength, accountID, networkID string) error
|
||||
|
||||
GetNetworkRoutersByNetID(ctx context.Context, lockStrength LockingStrength, accountID, netID string) ([]*routerTypes.NetworkRouter, error)
|
||||
GetNetworkRoutersByAccountID(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*routerTypes.NetworkRouter, error)
|
||||
GetNetworkRouterByID(ctx context.Context, lockStrength LockingStrength, accountID, routerID string) (*routerTypes.NetworkRouter, error)
|
||||
SaveNetworkRouter(ctx context.Context, lockStrength LockingStrength, router *routerTypes.NetworkRouter) error
|
||||
DeleteNetworkRouter(ctx context.Context, lockStrength LockingStrength, accountID, routerID string) error
|
||||
|
||||
GetNetworkResourcesByNetID(ctx context.Context, lockStrength LockingStrength, accountID, netID string) ([]*resourceTypes.NetworkResource, error)
|
||||
GetNetworkResourcesByAccountID(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*resourceTypes.NetworkResource, error)
|
||||
GetNetworkResourceByID(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) (*resourceTypes.NetworkResource, error)
|
||||
SaveNetworkResource(ctx context.Context, lockStrength LockingStrength, resource *resourceTypes.NetworkResource) error
|
||||
DeleteNetworkResource(ctx context.Context, lockStrength LockingStrength, accountID, resourceID string) error
|
||||
|
26
management/server/users/manager.go
Normal file
26
management/server/users/manager.go
Normal file
@ -0,0 +1,26 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
GetUser(ctx context.Context, userID string) (*types.User, error)
|
||||
}
|
||||
|
||||
type managerImpl struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
func NewManager(store store.Store) Manager {
|
||||
return &managerImpl{
|
||||
store: store,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetUser(ctx context.Context, userID string) (*types.User, error) {
|
||||
return m.store.GetUserByUserID(ctx, store.LockingStrengthShare, userID)
|
||||
}
|
Loading…
Reference in New Issue
Block a user