mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-22 21:39:08 +02:00
* use libopenapi OpenAPI generator Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * added a handler for v1alpha1/peers Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * wire up request validator Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * wired up spec-based validation Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * use sync validation; set base url to v1alpha1 Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * moved stuff around, extracted runtime libopenapu deps into runtime_tooling Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * testing /peers path params Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * fixed tests Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * added user schemas and paths Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * use api validation in tests Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * post-merge fixes Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * deleted tmp command used to test validator integration Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * require request body in post/put requests in order to force validation Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * making linter happy Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * switch to api/v1alpha1 Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * go mod tidy Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * keep the original order of middleware: metrics, cors, then auth Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * return 422 on validation errors Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * cleanups Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * more cleanups Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * v1alpha1 spec cleanups Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * no need for a double-pointer Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * more linter fixes Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * removed more double pointers Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * use di to inject api_v0 and api_v1 http routers Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * do not re-add middleware on repeated call to ApiHandler Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * support for pagination and filtering in /peers call Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * calling ApiRouter() now also calls ApiV1Router() Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * adding peer filters Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * introduced paginated GetAllPeers call Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * wire up pagination Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * convert pagination state to query scope Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * peer filter wip Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * implemented peer filter Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * test for filtering by os Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * support for sorting of peers Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * support for ordering + tests Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * more tests Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * wire up total number of records in paginated GetAllPeers call Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * cleaned up GetAllPeers response Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * pacify linter Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * cleanups and fixes Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * moar cleanups Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * pacify linter Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * remove duplicated test Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * make linter happy Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * moving GetAllPeersPaginated to peer manager, p. 1 Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * moving GetAllPeersPaginated to peer manager, p. 2 Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * added peer manager tests for GetPeersPaginated Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * order peers in GetAccountPeersPaginated by their ids by default Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * always order by peer_id, filter out proxies Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * fixed broken tests Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * support for filtering of peers by peer_id in GetAllPeers() Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * filtering by peer_ids Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * use lowercase in 'like' queries, drop ordering by ip Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * drop sort_by ip key Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * drop forced_approve filter Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * replace mac with darwin in peer os filter Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * fix peers query parameter: use peer_ids Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * fixed broken peer_test Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> * responded to feedback Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io> --------- Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
192 lines
7.0 KiB
Go
192 lines
7.0 KiB
Go
package peers
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gorilla/mux"
|
|
peersmodule "github.com/netbirdio/netbird/management/internals/modules/peers"
|
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
"github.com/netbirdio/netbird/management/server/store"
|
|
"github.com/netbirdio/netbird/shared/auth"
|
|
"github.com/netbirdio/netbird/shared/management/http/apiv1alpha1"
|
|
"github.com/stretchr/testify/assert"
|
|
"go.uber.org/mock/gomock"
|
|
)
|
|
|
|
func TestGetPeersPagination(t *testing.T) {
|
|
peer := &nbpeer.Peer{
|
|
ID: testPeerID,
|
|
Status: &nbpeer.PeerStatus{Connected: true},
|
|
Meta: nbpeer.PeerSystemMeta{},
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
expectedStatus int
|
|
requestPath string
|
|
setExpectations func(p *Handler)
|
|
}{
|
|
{
|
|
name: "GetPeers default paging, filtering, and sorting",
|
|
requestPath: "/peers",
|
|
expectedStatus: http.StatusOK,
|
|
setExpectations: func(p *Handler) {
|
|
p.peersManager.(*peersmodule.MockManager).EXPECT().GetPeersPaginated(gomock.Any(), gomock.Any(), gomock.Any(),
|
|
gomock.Eq(store.PaginationState{Page: 1, PageSize: 100}), gomock.Any(), gomock.Any()).Return(make([]*nbpeer.Peer, 0), 0, nil).AnyTimes()
|
|
},
|
|
},
|
|
{
|
|
name: "GetPeers paging",
|
|
requestPath: "/peers?page=10&page_size=250",
|
|
expectedStatus: http.StatusOK,
|
|
setExpectations: func(p *Handler) {
|
|
p.peersManager.(*peersmodule.MockManager).EXPECT().GetPeersPaginated(gomock.Any(), gomock.Any(), gomock.Any(),
|
|
gomock.Eq(store.PaginationState{Page: 10, PageSize: 250}),
|
|
gomock.Any(), gomock.Any()).Return(make([]*nbpeer.Peer, 0), 0, nil).AnyTimes()
|
|
},
|
|
},
|
|
{
|
|
name: "GetPeers paging with invalid page",
|
|
requestPath: "/peers?page=aaa&page_size=250",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers paging with invalid page size",
|
|
requestPath: "/peers?page=10&page_size=aaa",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers filtering all valid params",
|
|
requestPath: "/peers?user_id=test-user&group_ids=1&group_ids=2&group_ids=3&group_ids=4&peer_ids=peer-1&peer_ids=peer-2&connected=true&approval_required=false&os=linux&os=windows&os=darwin&os=android&os=ios&os=js&ip=10.10.10.10&mac=00:11:22:33:44:55&name=test&hostname=test-host&kind=user_device",
|
|
expectedStatus: http.StatusOK,
|
|
setExpectations: func(p *Handler) {
|
|
p.peersManager.(*peersmodule.MockManager).EXPECT().GetPeersPaginated(gomock.Any(), gomock.Any(), gomock.Any(),
|
|
gomock.Eq(store.PaginationState{Page: 1, PageSize: 100}),
|
|
gomock.Eq(store.PeerFilters{
|
|
UserId: "test-user",
|
|
GroupIds: []string{"1", "2", "3", "4"},
|
|
Connected: new(true),
|
|
ApprovalRequired: new(false),
|
|
Os: []string{"linux", "windows", "darwin", "android", "ios", "js"},
|
|
IP: "10.10.10.10",
|
|
MAC: "00:11:22:33:44:55",
|
|
Name: "test",
|
|
Hostname: "test-host",
|
|
IsServer: new(false),
|
|
PeersIds: []string{"peer-1", "peer-2"},
|
|
}),
|
|
gomock.Any()).Return(make([]*nbpeer.Peer, 0), 0, nil).AnyTimes()
|
|
},
|
|
},
|
|
{
|
|
name: "GetPeers filtering with kind server",
|
|
requestPath: "/peers?kind=server",
|
|
expectedStatus: http.StatusOK,
|
|
setExpectations: func(p *Handler) {
|
|
p.peersManager.(*peersmodule.MockManager).EXPECT().GetPeersPaginated(gomock.Any(), gomock.Any(), gomock.Any(),
|
|
gomock.Eq(store.PaginationState{Page: 1, PageSize: 100}),
|
|
gomock.Eq(store.PeerFilters{IsServer: new(true)}),
|
|
gomock.Any()).Return(make([]*nbpeer.Peer, 0), 0, nil).AnyTimes()
|
|
},
|
|
},
|
|
{
|
|
name: "GetPeers filtering with invalid connected value",
|
|
requestPath: "/peers?connected=aaa",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers filtering with invalid approval_required value",
|
|
requestPath: "/peers?approval_required=aaa",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers filtering with invalid os value",
|
|
requestPath: "/peers?os=nosuchos",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers filtering with invalid kind value",
|
|
requestPath: "/peers?kind=nosuchkind",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers filtering with conflicting user_id and kind",
|
|
requestPath: "/peers?user_id=test-user&kind=server",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers sorting preserves field ordering",
|
|
requestPath: "/peers?sort_by=last_seen&sort_by=name&sort_by=version",
|
|
expectedStatus: http.StatusOK,
|
|
setExpectations: func(p *Handler) {
|
|
p.peersManager.(*peersmodule.MockManager).EXPECT().GetPeersPaginated(gomock.Any(), gomock.Any(), gomock.Any(),
|
|
gomock.Eq(store.PaginationState{Page: 1, PageSize: 100}),
|
|
gomock.Any(),
|
|
gomock.Eq(store.PeerSorting{
|
|
Fields: []store.PeerSortingKey{
|
|
{Field: store.PeerSortByLastSeen, Order: store.AscOrderBy},
|
|
{Field: store.PeerSortByName, Order: store.AscOrderBy},
|
|
{Field: store.PeerSortByVersion, Order: store.AscOrderBy},
|
|
},
|
|
})).Return(make([]*nbpeer.Peer, 0), 0, nil).AnyTimes()
|
|
},
|
|
},
|
|
{
|
|
name: "GetPeers sorting with invalid field",
|
|
requestPath: "/peers?sort_by=nosuchfield,asc",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers sorting with invalid field",
|
|
requestPath: "/peers?sort_by=nosuchfield,asc",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
{
|
|
name: "GetPeers sorting with invalid sorting order",
|
|
requestPath: "/peers?sort_by=name,nosuchorder&sort_by=version",
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
setExpectations: func(p *Handler) {},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
p := initTestMetaData(t, peer)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, tc.requestPath, nil)
|
|
req = nbcontext.SetUserAuthInRequest(req, auth.UserAuth{
|
|
UserId: "admin_user",
|
|
Domain: "hotmail.com",
|
|
AccountId: "test_id",
|
|
})
|
|
|
|
v1validator, err := apiv1alpha1.CreateV1ApiValidatingMiddleware()
|
|
assert.NoError(t, err)
|
|
router := mux.NewRouter()
|
|
router.Use(v1validator.Handler)
|
|
router = p.WithEndpointsForRouter(router)
|
|
|
|
tc.setExpectations(p)
|
|
router.ServeHTTP(recorder, req)
|
|
|
|
res := recorder.Result()
|
|
defer res.Body.Close()
|
|
|
|
assert.Equal(t, tc.expectedStatus, recorder.Code)
|
|
})
|
|
}
|
|
}
|