[management] Add routing peer counter (#3036)

This commit is contained in:
Pascal Fischer 2024-12-13 11:57:07 +01:00 committed by GitHub
parent 86352f00fc
commit e436c39a86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 344 additions and 88 deletions

View File

@ -29,6 +29,7 @@ import (
"github.com/netbirdio/netbird/management/domain"
"github.com/netbirdio/netbird/management/server/activity"
"github.com/netbirdio/netbird/management/server/geolocation"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/idp"
"github.com/netbirdio/netbird/management/server/integrated_validator"
"github.com/netbirdio/netbird/management/server/jwtclaims"
@ -152,6 +153,7 @@ type AccountManager interface {
DeleteSetupKey(ctx context.Context, accountID, userID, keyID string) error
GetNetworksManager() networks.Manager
GetUserManager() users.Manager
GetGroupsManager() groups.Manager
}
type DefaultAccountManager struct {
@ -189,6 +191,7 @@ type DefaultAccountManager struct {
metrics telemetry.AppMetrics
groupsManager groups.Manager
networksManager networks.Manager
userManager users.Manager
settingsManager settings.Manager
@ -268,6 +271,7 @@ func BuildManager(
peersUpdateManager: peersUpdateManager,
idpManager: idpManager,
networksManager: networks.NewManager(store, permissionsManager),
groupsManager: groups.NewManager(store, permissionsManager),
userManager: userManager,
settingsManager: settingsManager,
permissionsManager: permissionsManager,
@ -1737,6 +1741,10 @@ func (am *DefaultAccountManager) GetUserManager() users.Manager {
return am.userManager
}
func (am *DefaultAccountManager) GetGroupsManager() groups.Manager {
return am.groupsManager
}
// addAllGroup to account object if it doesn't exist
func addAllGroup(account *types.Account) error {
if len(account.Groups) == 0 {

View File

@ -0,0 +1,99 @@
package groups
import (
"context"
"fmt"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/permissions"
"github.com/netbirdio/netbird/management/server/store"
"github.com/netbirdio/netbird/management/server/types"
)
type Manager interface {
GetAllGroups(ctx context.Context, accountID, userID string) (map[string]*types.Group, error)
AddResourceToGroup(ctx context.Context, accountID, userID, groupID string, resourceID *types.Resource) error
}
type managerImpl struct {
store store.Store
permissionsManager permissions.Manager
}
func NewManager(store store.Store, permissionsManager permissions.Manager) Manager {
return &managerImpl{
store: store,
permissionsManager: permissionsManager,
}
}
func (m *managerImpl) GetAllGroups(ctx context.Context, accountID, userID string) (map[string]*types.Group, error) {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Groups, permissions.Read)
if err != nil {
return nil, err
}
if !ok {
return nil, err
}
groups, err := m.store.GetAccountGroups(ctx, store.LockingStrengthShare, accountID)
if err != nil {
return nil, fmt.Errorf("error getting account groups: %w", err)
}
groupsMap := make(map[string]*types.Group)
for _, group := range groups {
groupsMap[group.ID] = group
}
return groupsMap, nil
}
func (m *managerImpl) AddResourceToGroup(ctx context.Context, accountID, userID, groupID string, resource *types.Resource) error {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, permissions.Groups, permissions.Write)
if err != nil {
return err
}
if !ok {
return err
}
return m.store.AddResourceToGroup(ctx, accountID, groupID, resource)
}
func ToGroupsInfo(groups map[string]*types.Group, id string) []api.GroupMinimum {
groupsInfo := []api.GroupMinimum{}
groupsChecked := make(map[string]struct{})
for _, group := range groups {
_, ok := groupsChecked[group.ID]
if ok {
continue
}
groupsChecked[group.ID] = struct{}{}
for _, pk := range group.Peers {
if pk == id {
info := api.GroupMinimum{
Id: group.ID,
Name: group.Name,
PeersCount: len(group.Peers),
ResourcesCount: len(group.Resources),
}
groupsInfo = append(groupsInfo, info)
break
}
}
for _, rk := range group.Resources {
if rk.ID == id {
info := api.GroupMinimum{
Id: group.ID,
Name: group.Name,
PeersCount: len(group.Peers),
ResourcesCount: len(group.Resources),
}
groupsInfo = append(groupsInfo, info)
break
}
}
}
return groupsInfo
}

View File

@ -1241,6 +1241,10 @@ components:
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
routing_peers_count:
description: Count of routing peers associated with the network
type: integer
example: 2
resources:
description: List of network resource IDs associated with the network
type: array
@ -1251,8 +1255,9 @@ components:
- id
- routers
- resources
- routing_peers_count
- $ref: '#/components/schemas/NetworkRequest'
NetworkResourceRequest:
NetworkResourceMinimum:
type: object
properties:
name:
@ -1270,6 +1275,19 @@ components:
required:
- name
- address
NetworkResourceRequest:
allOf:
- $ref: '#/components/schemas/NetworkResourceMinimum'
- type: object
properties:
groups:
description: Group IDs containing the resource
type: array
items:
type: string
example: "chacdk86lnnboviihd70"
required:
- groups
NetworkResource:
allOf:
- type: object
@ -1280,10 +1298,16 @@ components:
example: chacdk86lnnboviihd7g
type:
$ref: '#/components/schemas/NetworkResourceType'
groups:
description: Groups that the resource belongs to
type: array
items:
$ref: '#/components/schemas/GroupMinimum'
required:
- id
- type
- $ref: '#/components/schemas/NetworkResourceRequest'
- groups
- $ref: '#/components/schemas/NetworkResourceMinimum'
NetworkResourceType:
description: Network resource type based of the address
type: string

View File

@ -532,6 +532,9 @@ type Network struct {
// Routers List of router IDs associated with the network
Routers []string `json:"routers"`
// RoutingPeersCount Count of routing peers associated with the network
RoutingPeersCount int `json:"routing_peers_count"`
}
// NetworkRequest defines model for NetworkRequest.
@ -551,6 +554,9 @@ type NetworkResource struct {
// Description Network resource description
Description *string `json:"description,omitempty"`
// Groups Groups that the resource belongs to
Groups []GroupMinimum `json:"groups"`
// Id Network Resource ID
Id string `json:"id"`
@ -561,6 +567,18 @@ type NetworkResource struct {
Type NetworkResourceType `json:"type"`
}
// NetworkResourceMinimum defines model for NetworkResourceMinimum.
type NetworkResourceMinimum struct {
// Address Network resource address (either a direct host like 1.1.1.1 or 1.1.1.1/32, or a subnet like 192.168.178.0/24, or a domain like example.com)
Address string `json:"address"`
// Description Network resource description
Description *string `json:"description,omitempty"`
// Name Network resource name
Name string `json:"name"`
}
// NetworkResourceRequest defines model for NetworkResourceRequest.
type NetworkResourceRequest struct {
// Address Network resource address (either a direct host like 1.1.1.1 or 1.1.1.1/32, or a subnet like 192.168.178.0/24, or a domain like example.com)
@ -569,6 +587,9 @@ type NetworkResourceRequest struct {
// Description Network resource description
Description *string `json:"description,omitempty"`
// Groups Group IDs containing the resource
Groups []string `json:"groups"`
// Name Network resource name
Name string `json:"name"`
}

View File

@ -94,7 +94,7 @@ func APIHandler(ctx context.Context, accountManager s.AccountManager, LocationMa
routes.AddEndpoints(api.AccountManager, authCfg, router)
dns.AddEndpoints(api.AccountManager, authCfg, router)
events.AddEndpoints(api.AccountManager, authCfg, router)
networks.AddEndpoints(api.AccountManager.GetNetworksManager(), api.AccountManager.GetAccountIDFromToken, authCfg, router)
networks.AddEndpoints(api.AccountManager.GetNetworksManager(), api.AccountManager.GetGroupsManager(), api.AccountManager.GetAccountIDFromToken, authCfg, router)
return rootRouter, nil
}

View File

@ -287,13 +287,7 @@ func toGroupResponse(peers []*nbpeer.Peer, group *types.Group) *api.Group {
peersMap[peer.ID] = peer
}
resMap := make(map[string]types.Resource, len(peers))
for _, peer := range peers {
peersMap[peer.ID] = peer
}
peerCache := make(map[string]api.PeerMinimum)
resCache := make(map[string]api.Resource)
gr := api.Group{
Id: group.ID,
Name: group.Name,
@ -319,16 +313,8 @@ func toGroupResponse(peers []*nbpeer.Peer, group *types.Group) *api.Group {
gr.PeersCount = len(gr.Peers)
for _, res := range group.Resources {
_, ok := resCache[res.ID]
if !ok {
resource, ok := resMap[res.ID]
if !ok {
continue
}
resResp := resource.ToAPIResponse()
resCache[res.ID] = *resResp
gr.Resources = append(gr.Resources, *resResp)
}
resResp := res.ToAPIResponse()
gr.Resources = append(gr.Resources, *resResp)
}
gr.ResourcesCount = len(gr.Resources)

View File

@ -8,36 +8,42 @@ import (
"github.com/gorilla/mux"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/http/configs"
"github.com/netbirdio/netbird/management/server/http/util"
"github.com/netbirdio/netbird/management/server/jwtclaims"
"github.com/netbirdio/netbird/management/server/networks"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
"github.com/netbirdio/netbird/management/server/networks/types"
"github.com/netbirdio/netbird/management/server/status"
nbtypes "github.com/netbirdio/netbird/management/server/types"
)
// handler is a handler that returns networks of the account
type handler struct {
networksManager networks.Manager
groupsManager groups.Manager
extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error)
claimsExtractor *jwtclaims.ClaimsExtractor
}
func AddEndpoints(networksManager networks.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
networksHandler := newHandler(networksManager, extractFromToken, authCfg)
func AddEndpoints(networksManager networks.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
addRouterEndpoints(networksManager.GetRouterManager(), extractFromToken, authCfg, router)
addResourceEndpoints(networksManager.GetResourceManager(), groupsManager, extractFromToken, authCfg, router)
networksHandler := newHandler(networksManager, groupsManager, extractFromToken, authCfg)
router.HandleFunc("/networks", networksHandler.getAllNetworks).Methods("GET", "OPTIONS")
router.HandleFunc("/networks", networksHandler.createNetwork).Methods("POST", "OPTIONS")
router.HandleFunc("/networks/{networkId}", networksHandler.getNetwork).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}", networksHandler.updateNetwork).Methods("PUT", "OPTIONS")
router.HandleFunc("/networks/{networkId}", networksHandler.deleteNetwork).Methods("DELETE", "OPTIONS")
addRouterEndpoints(networksManager.GetRouterManager(), extractFromToken, authCfg, router)
addResourceEndpoints(networksManager.GetResourceManager(), extractFromToken, authCfg, router)
}
func newHandler(networksManager networks.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *handler {
func newHandler(networksManager networks.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *handler {
return &handler{
networksManager: networksManager,
groupsManager: groupsManager,
extractFromToken: extractFromToken,
claimsExtractor: jwtclaims.NewClaimsExtractor(
jwtclaims.WithAudience(authCfg.Audience),
@ -60,24 +66,25 @@ func (h *handler) getAllNetworks(w http.ResponseWriter, r *http.Request) {
return
}
routers, err := h.networksManager.GetRouterManager().GetAllRouterIDsInAccount(r.Context(), accountID, userID)
resourceIDs, err := h.networksManager.GetResourceManager().GetAllResourceIDsInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
resources, err := h.networksManager.GetResourceManager().GetAllResourceIDsInAccount(r.Context(), accountID, userID)
groups, err := h.groupsManager.GetAllGroups(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(routers[network.ID], resources[network.ID]))
routers, err := h.networksManager.GetRouterManager().GetAllRoutersInAccount(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
util.WriteJSONObject(r.Context(), w, networkResponse)
util.WriteJSONObject(r.Context(), w, h.generateNetworkResponse(networks, routers, resourceIDs, groups))
}
func (h *handler) createNetwork(w http.ResponseWriter, r *http.Request) {
@ -105,7 +112,7 @@ func (h *handler) createNetwork(w http.ResponseWriter, r *http.Request) {
return
}
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse([]string{}, []string{}))
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse([]string{}, []string{}, 0))
}
func (h *handler) getNetwork(w http.ResponseWriter, r *http.Request) {
@ -129,13 +136,13 @@ func (h *handler) getNetwork(w http.ResponseWriter, r *http.Request) {
return
}
routerIDs, resourceIDs, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
routerIDs, resourceIDs, peerCount, 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))
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs, peerCount))
}
func (h *handler) updateNetwork(w http.ResponseWriter, r *http.Request) {
@ -171,13 +178,13 @@ func (h *handler) updateNetwork(w http.ResponseWriter, r *http.Request) {
return
}
routerIDs, resourceIDs, err := h.collectIDsInNetwork(r.Context(), accountID, userID, networkID)
routerIDs, resourceIDs, peerCount, 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))
util.WriteJSONObject(r.Context(), w, network.ToAPIResponse(routerIDs, resourceIDs, peerCount))
}
func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request) {
@ -204,10 +211,10 @@ 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) {
func (h *handler) collectIDsInNetwork(ctx context.Context, accountID, userID, networkID string) ([]string, []string, int, 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)
return nil, nil, 0, fmt.Errorf("failed to get resources in network: %w", err)
}
var resourceIDs []string
@ -217,13 +224,48 @@ func (h *handler) collectIDsInNetwork(ctx context.Context, accountID, userID, ne
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)
return nil, nil, 0, fmt.Errorf("failed to get routers in network: %w", err)
}
groups, err := h.groupsManager.GetAllGroups(ctx, accountID, userID)
if err != nil {
return nil, nil, 0, fmt.Errorf("failed to get groups: %w", err)
}
peerCounter := 0
var routerIDs []string
for _, router := range routers {
routerIDs = append(routerIDs, router.ID)
if router.Peer != "" {
peerCounter++
}
if len(router.PeerGroups) > 0 {
for _, groupID := range router.PeerGroups {
peerCounter += len(groups[groupID].Peers)
}
}
}
return routerIDs, resourceIDs, nil
return routerIDs, resourceIDs, peerCounter, nil
}
func (h *handler) generateNetworkResponse(networks []*types.Network, routers map[string][]*routerTypes.NetworkRouter, resourceIDs map[string][]string, groups map[string]*nbtypes.Group) []*api.Network {
var networkResponse []*api.Network
for _, network := range networks {
routerIDs := []string{}
peerCounter := 0
for _, router := range routers[network.ID] {
routerIDs = append(routerIDs, router.ID)
if router.Peer != "" {
peerCounter++
}
if len(router.PeerGroups) > 0 {
for _, groupID := range router.PeerGroups {
peerCounter += len(groups[groupID].Peers)
}
}
}
networkResponse = append(networkResponse, network.ToAPIResponse(routerIDs, resourceIDs[network.ID], peerCounter))
}
return networkResponse
}

View File

@ -7,33 +7,37 @@ import (
"github.com/gorilla/mux"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/http/configs"
"github.com/netbirdio/netbird/management/server/http/util"
"github.com/netbirdio/netbird/management/server/jwtclaims"
"github.com/netbirdio/netbird/management/server/networks/resources"
"github.com/netbirdio/netbird/management/server/networks/resources/types"
nbtypes "github.com/netbirdio/netbird/management/server/types"
)
type resourceHandler struct {
resourceManager resources.Manager
groupsManager groups.Manager
extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error)
claimsExtractor *jwtclaims.ClaimsExtractor
}
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)
func addResourceEndpoints(resourcesManager resources.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg, router *mux.Router) {
resourceHandler := newResourceHandler(resourcesManager, groupsManager, extractFromToken, authCfg)
router.HandleFunc("/networks/resources", resourceHandler.getAllResourcesInAccount).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 {
func newResourceHandler(resourceManager resources.Manager, groupsManager groups.Manager, extractFromToken func(ctx context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error), authCfg configs.AuthCfg) *resourceHandler {
return &resourceHandler{
resourceManager: resourceManager,
groupsManager: groupsManager,
extractFromToken: extractFromToken,
claimsExtractor: jwtclaims.NewClaimsExtractor(
jwtclaims.WithAudience(authCfg.Audience),
@ -57,9 +61,16 @@ func (h *resourceHandler) getAllResourcesInNetwork(w http.ResponseWriter, r *htt
return
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
var resourcesResponse []*api.NetworkResource
for _, resource := range resources {
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse())
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse(groupMinimumInfo))
}
util.WriteJSONObject(r.Context(), w, resourcesResponse)
@ -78,9 +89,16 @@ func (h *resourceHandler) getAllResourcesInAccount(w http.ResponseWriter, r *htt
return
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
var resourcesResponse []*api.NetworkResource
for _, resource := range resources {
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse())
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
resourcesResponse = append(resourcesResponse, resource.ToAPIResponse(groupMinimumInfo))
}
util.WriteJSONObject(r.Context(), w, resourcesResponse)
@ -112,7 +130,26 @@ func (h *resourceHandler) createResource(w http.ResponseWriter, r *http.Request)
return
}
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse())
res := nbtypes.Resource{
ID: resource.ID,
Type: resource.Type.String(),
}
for _, groupID := range req.Groups {
err = h.groupsManager.AddResourceToGroup(r.Context(), accountID, userID, groupID, &res)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse(groupMinimumInfo))
}
func (h *resourceHandler) getResource(w http.ResponseWriter, r *http.Request) {
@ -131,7 +168,14 @@ func (h *resourceHandler) getResource(w http.ResponseWriter, r *http.Request) {
return
}
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse())
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse(groupMinimumInfo))
}
func (h *resourceHandler) updateResource(w http.ResponseWriter, r *http.Request) {
@ -161,7 +205,26 @@ func (h *resourceHandler) updateResource(w http.ResponseWriter, r *http.Request)
return
}
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse())
res := nbtypes.Resource{
ID: resource.ID,
Type: resource.Type.String(),
}
for _, groupID := range req.Groups {
err = h.groupsManager.AddResourceToGroup(r.Context(), accountID, userID, groupID, &res)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
}
grps, err := h.groupsManager.GetAllGroups(r.Context(), accountID, userID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := groups.ToGroupsInfo(grps, resource.ID)
util.WriteJSONObject(r.Context(), w, resource.ToAPIResponse(groupMinimumInfo))
}
func (h *resourceHandler) deleteResource(w http.ResponseWriter, r *http.Request) {

View File

@ -10,6 +10,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/management/server"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/http/api"
"github.com/netbirdio/netbird/management/server/http/configs"
"github.com/netbirdio/netbird/management/server/http/util"
@ -71,7 +72,7 @@ func (h *Handler) getPeer(ctx context.Context, account *types.Account, peerID, u
}
dnsDomain := h.accountManager.GetDNSDomain()
groupsInfo := toGroupsInfo(account.Groups, peer.ID)
groupsInfo := groups.ToGroupsInfo(account.Groups, peer.ID)
validPeers, err := h.accountManager.GetValidatedPeers(account)
if err != nil {
@ -115,7 +116,7 @@ func (h *Handler) updatePeer(ctx context.Context, account *types.Account, userID
}
dnsDomain := h.accountManager.GetDNSDomain()
groupMinimumInfo := toGroupsInfo(account.Groups, peer.ID)
groupMinimumInfo := groups.ToGroupsInfo(account.Groups, peer.ID)
validPeers, err := h.accountManager.GetValidatedPeers(account)
if err != nil {
@ -200,8 +201,8 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
}
groupsMap := map[string]*types.Group{}
groups, _ := h.accountManager.GetAllGroups(r.Context(), accountID, userID)
for _, group := range groups {
grps, _ := h.accountManager.GetAllGroups(r.Context(), accountID, userID)
for _, group := range grps {
groupsMap[group.ID] = group
}
@ -212,7 +213,7 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
util.WriteError(r.Context(), err, w)
return
}
groupMinimumInfo := toGroupsInfo(groupsMap, peer.ID)
groupMinimumInfo := groups.ToGroupsInfo(groupsMap, peer.ID)
respBody = append(respBody, toPeerListItemResponse(peerToReturn, groupMinimumInfo, dnsDomain, 0))
}
@ -324,30 +325,6 @@ func peerToAccessiblePeer(peer *nbpeer.Peer, dnsDomain string) api.AccessiblePee
}
}
func toGroupsInfo(groups map[string]*types.Group, peerID string) []api.GroupMinimum {
groupsInfo := []api.GroupMinimum{}
groupsChecked := make(map[string]struct{})
for _, group := range groups {
_, ok := groupsChecked[group.ID]
if ok {
continue
}
groupsChecked[group.ID] = struct{}{}
for _, pk := range group.Peers {
if pk == peerID {
info := api.GroupMinimum{
Id: group.ID,
Name: group.Name,
PeersCount: len(group.Peers),
}
groupsInfo = append(groupsInfo, info)
break
}
}
}
return groupsInfo
}
func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsDomain string, approved bool) *api.Peer {
osVersion := peer.Meta.OSVersion
if osVersion == "" {

View File

@ -13,6 +13,7 @@ import (
"github.com/netbirdio/netbird/management/domain"
"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/idp"
"github.com/netbirdio/netbird/management/server/jwtclaims"
"github.com/netbirdio/netbird/management/server/networks"
@ -123,6 +124,11 @@ func (am *MockAccountManager) GetNetworksManager() networks.Manager {
panic("implement me")
}
func (am *MockAccountManager) GetGroupsManager() groups.Manager {
// TODO implement me
panic("implement me")
}
func (am *MockAccountManager) DeleteSetupKey(ctx context.Context, accountID, userID, keyID string) error {
if am.DeleteSetupKeyFunc != nil {
return am.DeleteSetupKeyFunc(ctx, accountID, userID, keyID)

View File

@ -51,13 +51,14 @@ func NewNetworkResource(accountID, networkID, name, description, address string)
}, nil
}
func (n *NetworkResource) ToAPIResponse() *api.NetworkResource {
func (n *NetworkResource) ToAPIResponse(groups []api.GroupMinimum) *api.NetworkResource {
return &api.NetworkResource{
Id: n.ID,
Name: n.Name,
Description: &n.Description,
Type: api.NetworkResourceType(n.Type.String()),
Address: n.Address,
Groups: groups,
}
}

View File

@ -15,7 +15,7 @@ import (
type Manager interface {
GetAllRoutersInNetwork(ctx context.Context, accountID, userID, networkID string) ([]*types.NetworkRouter, error)
GetAllRouterIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, 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)
@ -46,7 +46,7 @@ func (m *managerImpl) GetAllRoutersInNetwork(ctx context.Context, accountID, use
return m.store.GetNetworkRoutersByNetID(ctx, store.LockingStrengthShare, accountID, networkID)
}
func (m *managerImpl) GetAllRouterIDsInAccount(ctx context.Context, accountID, userID string) (map[string][]string, error) {
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)
@ -60,9 +60,9 @@ func (m *managerImpl) GetAllRouterIDsInAccount(ctx context.Context, accountID, u
return nil, fmt.Errorf("failed to get network routers: %w", err)
}
routersMap := make(map[string][]string)
routersMap := make(map[string][]*types.NetworkRouter)
for _, router := range routers {
routersMap[router.NetworkID] = append(routersMap[router.NetworkID], router.ID)
routersMap[router.NetworkID] = append(routersMap[router.NetworkID], router)
}
return routersMap, nil

View File

@ -22,13 +22,14 @@ func NewNetwork(accountId, name, description string) *Network {
}
}
func (n *Network) ToAPIResponse(routerIDs []string, resourceIDs []string) *api.Network {
func (n *Network) ToAPIResponse(routerIDs []string, resourceIDs []string, routingPeersCount int) *api.Network {
return &api.Network{
Id: n.ID,
Name: n.Name,
Description: &n.Description,
Routers: routerIDs,
Resources: resourceIDs,
Id: n.ID,
Name: n.Name,
Description: &n.Description,
Routers: routerIDs,
Resources: resourceIDs,
RoutingPeersCount: routingPeersCount,
}
}

View File

@ -15,6 +15,7 @@ type Module string
const (
Networks Module = "networks"
Peers Module = "peers"
Groups Module = "groups"
)
type Operation string

View File

@ -1070,6 +1070,32 @@ func (s *SqlStore) AddPeerToGroup(ctx context.Context, accountId string, peerId
return nil
}
func (s *SqlStore) AddResourceToGroup(ctx context.Context, accountId string, groupID string, resource *types.Resource) error {
var group types.Group
result := s.db.Where(accountAndIDQueryCondition, accountId, groupID).First(&group)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return status.NewGroupNotFoundError(groupID)
}
return status.Errorf(status.Internal, "issue finding group: %s", result.Error)
}
for _, res := range group.Resources {
if res.ID == resource.ID {
return nil
}
}
group.Resources = append(group.Resources, *resource)
if err := s.db.Save(&group).Error; err != nil {
return status.Errorf(status.Internal, "issue updating group: %s", err)
}
return nil
}
// GetUserPeers retrieves peers for a user.
func (s *SqlStore) GetUserPeers(ctx context.Context, lockStrength LockingStrength, accountID, userID string) ([]*nbpeer.Peer, error) {
return getRecords[*nbpeer.Peer](s.db.Where("user_id = ?", userID), lockStrength, accountID)

View File

@ -98,6 +98,7 @@ type Store interface {
GetPeerLabelsInAccount(ctx context.Context, lockStrength LockingStrength, accountId string) ([]string, error)
AddPeerToAllGroup(ctx context.Context, accountID string, peerID string) error
AddPeerToGroup(ctx context.Context, accountId string, peerId string, groupID string) error
AddResourceToGroup(ctx context.Context, accountId string, groupID string, resource *types.Resource) error
AddPeerToAccount(ctx context.Context, peer *nbpeer.Peer) error
GetPeerByPeerPubKey(ctx context.Context, lockStrength LockingStrength, peerKey string) (*nbpeer.Peer, error)
GetUserPeers(ctx context.Context, lockStrength LockingStrength, accountID, userID string) ([]*nbpeer.Peer, error)