mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-20 17:26:40 +00:00
[management] Allow resources in groups (#3030)
This commit is contained in:
@@ -668,6 +668,10 @@ components:
|
||||
description: Count of peers associated to the group
|
||||
type: integer
|
||||
example: 2
|
||||
resources_count:
|
||||
description: Count of resources associated to the group
|
||||
type: integer
|
||||
example: 5
|
||||
issued:
|
||||
description: How the group was issued (api, integration, jwt)
|
||||
type: string
|
||||
@@ -677,6 +681,7 @@ components:
|
||||
- id
|
||||
- name
|
||||
- peers_count
|
||||
- resources_count
|
||||
GroupRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -690,6 +695,10 @@ components:
|
||||
items:
|
||||
type: string
|
||||
example: "ch8i4ug6lnn4g9hqv7m1"
|
||||
resources:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Resource'
|
||||
required:
|
||||
- name
|
||||
Group:
|
||||
@@ -702,8 +711,13 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PeerMinimum'
|
||||
resources:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Resource'
|
||||
required:
|
||||
- peers
|
||||
- resources
|
||||
PolicyRuleMinimum:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -379,7 +379,11 @@ type Group struct {
|
||||
Peers []PeerMinimum `json:"peers"`
|
||||
|
||||
// PeersCount Count of peers associated to the group
|
||||
PeersCount int `json:"peers_count"`
|
||||
PeersCount int `json:"peers_count"`
|
||||
Resources []Resource `json:"resources"`
|
||||
|
||||
// ResourcesCount Count of resources associated to the group
|
||||
ResourcesCount int `json:"resources_count"`
|
||||
}
|
||||
|
||||
// GroupIssued How the group was issued (api, integration, jwt)
|
||||
@@ -398,6 +402,9 @@ type GroupMinimum struct {
|
||||
|
||||
// PeersCount Count of peers associated to the group
|
||||
PeersCount int `json:"peers_count"`
|
||||
|
||||
// ResourcesCount Count of resources associated to the group
|
||||
ResourcesCount int `json:"resources_count"`
|
||||
}
|
||||
|
||||
// GroupMinimumIssued How the group was issued (api, integration, jwt)
|
||||
@@ -409,7 +416,8 @@ type GroupRequest struct {
|
||||
Name string `json:"name"`
|
||||
|
||||
// Peers List of peers ids
|
||||
Peers *[]string `json:"peers,omitempty"`
|
||||
Peers *[]string `json:"peers,omitempty"`
|
||||
Resources *[]Resource `json:"resources,omitempty"`
|
||||
}
|
||||
|
||||
// Location Describe geographical location information
|
||||
@@ -1068,7 +1076,7 @@ type ProcessCheck struct {
|
||||
|
||||
// Resource defines model for Resource.
|
||||
type Resource struct {
|
||||
// Id Resource ID
|
||||
// Id ID of the resource
|
||||
Id string `json:"id"`
|
||||
Type ResourceType `json:"type"`
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/http/configs"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
@@ -129,10 +129,21 @@ func (h *handler) updateGroup(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
peers = *req.Peers
|
||||
}
|
||||
group := nbgroup.Group{
|
||||
|
||||
resources := make([]types.Resource, 0)
|
||||
if req.Resources != nil {
|
||||
for _, res := range *req.Resources {
|
||||
resource := types.Resource{}
|
||||
resource.FromAPIRequest(&res)
|
||||
resources = append(resources, resource)
|
||||
}
|
||||
}
|
||||
|
||||
group := types.Group{
|
||||
ID: groupID,
|
||||
Name: req.Name,
|
||||
Peers: peers,
|
||||
Resources: resources,
|
||||
Issued: existingGroup.Issued,
|
||||
IntegrationReference: existingGroup.IntegrationReference,
|
||||
}
|
||||
@@ -179,10 +190,21 @@ func (h *handler) createGroup(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
peers = *req.Peers
|
||||
}
|
||||
group := nbgroup.Group{
|
||||
Name: req.Name,
|
||||
Peers: peers,
|
||||
Issued: nbgroup.GroupIssuedAPI,
|
||||
|
||||
resources := make([]types.Resource, 0)
|
||||
if req.Resources != nil {
|
||||
for _, res := range *req.Resources {
|
||||
resource := types.Resource{}
|
||||
resource.FromAPIRequest(&res)
|
||||
resources = append(resources, resource)
|
||||
}
|
||||
}
|
||||
|
||||
group := types.Group{
|
||||
Name: req.Name,
|
||||
Peers: peers,
|
||||
Resources: resources,
|
||||
Issued: types.GroupIssuedAPI,
|
||||
}
|
||||
|
||||
err = h.accountManager.SaveGroup(r.Context(), accountID, userID, &group)
|
||||
@@ -259,13 +281,19 @@ func (h *handler) getGroup(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
func toGroupResponse(peers []*nbpeer.Peer, group *nbgroup.Group) *api.Group {
|
||||
func toGroupResponse(peers []*nbpeer.Peer, group *types.Group) *api.Group {
|
||||
peersMap := make(map[string]*nbpeer.Peer, len(peers))
|
||||
for _, peer := range peers {
|
||||
peersMap[peer.ID] = peer
|
||||
}
|
||||
|
||||
cache := make(map[string]api.PeerMinimum)
|
||||
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,
|
||||
@@ -273,7 +301,7 @@ func toGroupResponse(peers []*nbpeer.Peer, group *nbgroup.Group) *api.Group {
|
||||
}
|
||||
|
||||
for _, pid := range group.Peers {
|
||||
_, ok := cache[pid]
|
||||
_, ok := peerCache[pid]
|
||||
if !ok {
|
||||
peer, ok := peersMap[pid]
|
||||
if !ok {
|
||||
@@ -283,12 +311,27 @@ func toGroupResponse(peers []*nbpeer.Peer, group *nbgroup.Group) *api.Group {
|
||||
Id: peer.ID,
|
||||
Name: peer.Name,
|
||||
}
|
||||
cache[pid] = peerResp
|
||||
peerCache[pid] = peerResp
|
||||
gr.Peers = append(gr.Peers, peerResp)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
gr.ResourcesCount = len(gr.Resources)
|
||||
|
||||
return &gr
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ import (
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
)
|
||||
|
||||
var TestPeers = map[string]*nbpeer.Peer{
|
||||
@@ -31,20 +31,20 @@ var TestPeers = map[string]*nbpeer.Peer{
|
||||
"B": {Key: "B", ID: "peer-B-ID", IP: net.ParseIP("200.200.200.200")},
|
||||
}
|
||||
|
||||
func initGroupTestData(initGroups ...*nbgroup.Group) *handler {
|
||||
func initGroupTestData(initGroups ...*types.Group) *handler {
|
||||
return &handler{
|
||||
accountManager: &mock_server.MockAccountManager{
|
||||
SaveGroupFunc: func(_ context.Context, accountID, userID string, group *nbgroup.Group) error {
|
||||
SaveGroupFunc: func(_ context.Context, accountID, userID string, group *types.Group) error {
|
||||
if !strings.HasPrefix(group.ID, "id-") {
|
||||
group.ID = "id-was-set"
|
||||
}
|
||||
return nil
|
||||
},
|
||||
GetGroupFunc: func(_ context.Context, _, groupID, _ string) (*nbgroup.Group, error) {
|
||||
groups := map[string]*nbgroup.Group{
|
||||
"id-jwt-group": {ID: "id-jwt-group", Name: "From JWT", Issued: nbgroup.GroupIssuedJWT},
|
||||
"id-existed": {ID: "id-existed", Peers: []string{"A", "B"}, Issued: nbgroup.GroupIssuedAPI},
|
||||
"id-all": {ID: "id-all", Name: "All", Issued: nbgroup.GroupIssuedAPI},
|
||||
GetGroupFunc: func(_ context.Context, _, groupID, _ string) (*types.Group, error) {
|
||||
groups := map[string]*types.Group{
|
||||
"id-jwt-group": {ID: "id-jwt-group", Name: "From JWT", Issued: types.GroupIssuedJWT},
|
||||
"id-existed": {ID: "id-existed", Peers: []string{"A", "B"}, Issued: types.GroupIssuedAPI},
|
||||
"id-all": {ID: "id-all", Name: "All", Issued: types.GroupIssuedAPI},
|
||||
}
|
||||
|
||||
for _, group := range initGroups {
|
||||
@@ -61,9 +61,9 @@ func initGroupTestData(initGroups ...*nbgroup.Group) *handler {
|
||||
GetAccountIDFromTokenFunc: func(_ context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error) {
|
||||
return claims.AccountId, claims.UserId, nil
|
||||
},
|
||||
GetGroupByNameFunc: func(ctx context.Context, groupName, _ string) (*nbgroup.Group, error) {
|
||||
GetGroupByNameFunc: func(ctx context.Context, groupName, _ string) (*types.Group, error) {
|
||||
if groupName == "All" {
|
||||
return &nbgroup.Group{ID: "id-all", Name: "All", Issued: nbgroup.GroupIssuedAPI}, nil
|
||||
return &types.Group{ID: "id-all", Name: "All", Issued: types.GroupIssuedAPI}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown group name")
|
||||
@@ -120,7 +120,7 @@ func TestGetGroup(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
group := &nbgroup.Group{
|
||||
group := &types.Group{
|
||||
ID: "idofthegroup",
|
||||
Name: "Group",
|
||||
}
|
||||
@@ -154,7 +154,7 @@ func TestGetGroup(t *testing.T) {
|
||||
t.Fatalf("I don't know what I expected; %v", err)
|
||||
}
|
||||
|
||||
got := &nbgroup.Group{}
|
||||
got := &types.Group{}
|
||||
if err = json.Unmarshal(content, &got); err != nil {
|
||||
t.Fatalf("Sent content is not in correct json format; %v", err)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/http/configs"
|
||||
"github.com/netbirdio/netbird/management/server/http/util"
|
||||
@@ -200,7 +199,7 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
groupsMap := map[string]*nbgroup.Group{}
|
||||
groupsMap := map[string]*types.Group{}
|
||||
groups, _ := h.accountManager.GetAllGroups(r.Context(), accountID, userID)
|
||||
for _, group := range groups {
|
||||
groupsMap[group.ID] = group
|
||||
@@ -325,7 +324,7 @@ func peerToAccessiblePeer(peer *nbpeer.Peer, dnsDomain string) api.AccessiblePee
|
||||
}
|
||||
}
|
||||
|
||||
func toGroupsInfo(groups map[string]*nbgroup.Group, peerID string) []api.GroupMinimum {
|
||||
func toGroupsInfo(groups map[string]*types.Group, peerID string) []api.GroupMinimum {
|
||||
groupsInfo := []api.GroupMinimum{}
|
||||
groupsChecked := make(map[string]struct{})
|
||||
for _, group := range groups {
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
@@ -111,7 +110,7 @@ func initTestMetaData(peers ...*nbpeer.Peer) *Handler {
|
||||
regularUser: types.NewRegularUser(regularUser),
|
||||
serviceUser: srvUser,
|
||||
},
|
||||
Groups: map[string]*nbgroup.Group{
|
||||
Groups: map[string]*types.Group{
|
||||
"group1": {
|
||||
ID: "group1",
|
||||
AccountID: accountID,
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/http/configs"
|
||||
"github.com/netbirdio/netbird/management/server/http/util"
|
||||
@@ -361,8 +360,8 @@ func (h *handler) getPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
util.WriteJSONObject(r.Context(), w, resp)
|
||||
}
|
||||
|
||||
func toPolicyResponse(groups []*nbgroup.Group, policy *types.Policy) *api.Policy {
|
||||
groupsMap := make(map[string]*nbgroup.Group)
|
||||
func toPolicyResponse(groups []*types.Group, policy *types.Policy) *api.Policy {
|
||||
groupsMap := make(map[string]*types.Group)
|
||||
for _, group := range groups {
|
||||
groupsMap[group.ID] = group
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
"github.com/netbirdio/netbird/management/server/types"
|
||||
@@ -45,8 +44,8 @@ func initPoliciesTestData(policies ...*types.Policy) *handler {
|
||||
}
|
||||
return policy, nil
|
||||
},
|
||||
GetAllGroupsFunc: func(ctx context.Context, accountID, userID string) ([]*nbgroup.Group, error) {
|
||||
return []*nbgroup.Group{{ID: "F"}, {ID: "G"}}, nil
|
||||
GetAllGroupsFunc: func(ctx context.Context, accountID, userID string) ([]*types.Group, error) {
|
||||
return []*types.Group{{ID: "F"}, {ID: "G"}}, nil
|
||||
},
|
||||
GetAccountIDFromTokenFunc: func(_ context.Context, claims jwtclaims.AuthorizationClaims) (string, string, error) {
|
||||
return claims.AccountId, claims.UserId, nil
|
||||
@@ -59,7 +58,7 @@ func initPoliciesTestData(policies ...*types.Policy) *handler {
|
||||
Policies: []*types.Policy{
|
||||
{ID: "id-existed"},
|
||||
},
|
||||
Groups: map[string]*nbgroup.Group{
|
||||
Groups: map[string]*types.Group{
|
||||
"F": {ID: "F"},
|
||||
"G": {ID: "G"},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user