mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-25 19:56:46 +00:00
184 lines
6.6 KiB
Go
184 lines
6.6 KiB
Go
//go:build integration
|
|
|
|
package integration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/netbirdio/netbird/management/server/http/testing/testing_tools"
|
|
"github.com/netbirdio/netbird/management/server/http/testing/testing_tools/channel"
|
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
|
)
|
|
|
|
// Test_Instance_GetStatus tests the unauthenticated GET /api/instance endpoint.
|
|
// This endpoint bypasses auth middleware. With nil idpManager (no embedded IDP),
|
|
// SetupRequired should be false.
|
|
func Test_Instance_GetStatus(t *testing.T) {
|
|
apiHandler, _, _ := channel.BuildApiBlackBoxWithDBState(t, "../testdata/accounts.sql", nil, false)
|
|
|
|
// The /api/instance endpoint is unauthenticated (bypass path).
|
|
// We still pass a token via BuildRequest but the bypass middleware skips auth.
|
|
req := testing_tools.BuildRequest(t, []byte{}, http.MethodGet, "/api/instance", testing_tools.TestAdminId)
|
|
recorder := httptest.NewRecorder()
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
res := recorder.Result()
|
|
defer res.Body.Close()
|
|
|
|
content, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read response body: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, http.StatusOK, recorder.Code, "Expected 200 OK for instance status endpoint, got %d: %s", recorder.Code, string(content))
|
|
|
|
got := &api.InstanceStatus{}
|
|
if err := json.Unmarshal(content, got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
// With nil idpManager (no embedded IDP configured), setup is not required.
|
|
assert.Equal(t, false, got.SetupRequired, "Expected SetupRequired to be false when embedded IDP is not configured")
|
|
}
|
|
|
|
// Test_Instance_GetStatus_Unauthenticated verifies the endpoint works without any
|
|
// valid user token, since it is on the bypass path.
|
|
func Test_Instance_GetStatus_Unauthenticated(t *testing.T) {
|
|
apiHandler, _, _ := channel.BuildApiBlackBoxWithDBState(t, "../testdata/accounts.sql", nil, false)
|
|
|
|
// Use an invalid token to confirm the bypass middleware skips auth
|
|
req := testing_tools.BuildRequest(t, []byte{}, http.MethodGet, "/api/instance", testing_tools.InvalidToken)
|
|
recorder := httptest.NewRecorder()
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
res := recorder.Result()
|
|
defer res.Body.Close()
|
|
|
|
content, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read response body: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, http.StatusOK, recorder.Code, "Expected 200 OK for unauthenticated instance status endpoint, got %d: %s", recorder.Code, string(content))
|
|
|
|
got := &api.InstanceStatus{}
|
|
if err := json.Unmarshal(content, got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
assert.Equal(t, false, got.SetupRequired)
|
|
}
|
|
|
|
// Test_Instance_GetVersionInfo tests the authenticated GET /api/instance/version endpoint.
|
|
func Test_Instance_GetVersionInfo(t *testing.T) {
|
|
users := []struct {
|
|
name string
|
|
userId string
|
|
expectResponse bool
|
|
}{
|
|
{"Regular user", testing_tools.TestUserId, false},
|
|
{"Admin user", testing_tools.TestAdminId, true},
|
|
{"Owner user", testing_tools.TestOwnerId, true},
|
|
{"Regular service user", testing_tools.TestServiceUserId, false},
|
|
{"Admin service user", testing_tools.TestServiceAdminId, true},
|
|
{"Blocked user", testing_tools.BlockedUserId, false},
|
|
{"Other user", testing_tools.OtherUserId, false},
|
|
{"Invalid token", testing_tools.InvalidToken, false},
|
|
}
|
|
|
|
for _, user := range users {
|
|
t.Run(user.name+" - Get version info", func(t *testing.T) {
|
|
apiHandler, _, _ := channel.BuildApiBlackBoxWithDBState(t, "../testdata/accounts.sql", nil, false)
|
|
|
|
req := testing_tools.BuildRequest(t, []byte{}, http.MethodGet, "/api/instance/version", user.userId)
|
|
recorder := httptest.NewRecorder()
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
content, expectResponse := testing_tools.ReadResponse(t, recorder, http.StatusOK, user.expectResponse)
|
|
if !expectResponse {
|
|
return
|
|
}
|
|
|
|
got := &api.InstanceVersionInfo{}
|
|
if err := json.Unmarshal(content, got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
assert.NotEmpty(t, got.ManagementCurrentVersion, "Expected non-empty current version")
|
|
})
|
|
}
|
|
}
|
|
|
|
// Test_Instance_Setup tests the unauthenticated POST /api/setup endpoint.
|
|
// Since embedded IDP is not configured in the test environment, the setup
|
|
// endpoint should return an error (500 Internal Server Error) because the
|
|
// instance manager's CreateOwnerUser returns "embedded IDP is not enabled".
|
|
func Test_Instance_Setup(t *testing.T) {
|
|
apiHandler, _, _ := channel.BuildApiBlackBoxWithDBState(t, "../testdata/accounts.sql", nil, false)
|
|
|
|
body, err := json.Marshal(&api.SetupRequest{
|
|
Email: "admin@test.com",
|
|
Password: "securepassword123",
|
|
Name: "Admin User",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to marshal request body: %v", err)
|
|
}
|
|
|
|
// The /api/setup endpoint is unauthenticated (bypass path).
|
|
req := testing_tools.BuildRequest(t, body, http.MethodPost, "/api/setup", testing_tools.TestAdminId)
|
|
recorder := httptest.NewRecorder()
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
res := recorder.Result()
|
|
defer res.Body.Close()
|
|
|
|
content, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read response body: %v", err)
|
|
}
|
|
|
|
// Without embedded IDP, CreateOwnerUser returns a plain error (not a status error),
|
|
// which the handler maps to 500 Internal Server Error.
|
|
assert.Equal(t, http.StatusInternalServerError, recorder.Code,
|
|
"Expected 500 when embedded IDP is not configured, got %d: %s", recorder.Code, string(content))
|
|
}
|
|
|
|
// Test_Instance_Setup_Unauthenticated verifies the setup endpoint works (reaches
|
|
// the handler) even with an invalid token, since it is on the bypass path.
|
|
func Test_Instance_Setup_Unauthenticated(t *testing.T) {
|
|
apiHandler, _, _ := channel.BuildApiBlackBoxWithDBState(t, "../testdata/accounts.sql", nil, false)
|
|
|
|
body, err := json.Marshal(&api.SetupRequest{
|
|
Email: "admin@test.com",
|
|
Password: "securepassword123",
|
|
Name: "Admin User",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to marshal request body: %v", err)
|
|
}
|
|
|
|
req := testing_tools.BuildRequest(t, body, http.MethodPost, "/api/setup", testing_tools.InvalidToken)
|
|
recorder := httptest.NewRecorder()
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
res := recorder.Result()
|
|
defer res.Body.Close()
|
|
|
|
content, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read response body: %v", err)
|
|
}
|
|
|
|
// Even with an invalid token, the bypass middleware skips auth and the handler runs.
|
|
// Without embedded IDP, it returns 500.
|
|
assert.Equal(t, http.StatusInternalServerError, recorder.Code,
|
|
"Expected 500 when embedded IDP is not configured, got %d: %s", recorder.Code, string(content))
|
|
}
|