mirror of
https://github.com/gravitl/netmaker.git
synced 2026-04-23 00:17:10 +08:00
edda2868fc
* feat(go): add user schema; * feat(go): migrate to user schema; * feat(go): add audit fields; * feat(go): remove unused fields from the network model; * feat(go): add network schema; * feat(go): migrate to network schema; * refactor(go): add comment to clarify migration logic; * fix(go): test failures; * fix(go): test failures; * feat(go): change membership table to store memberships at all scopes; * feat(go): add schema for access grants; * feat(go): remove nameservers from new networks table; ensure db passed for schema functions; * feat(go): set max conns for sqlite to 1; * fix(go): issues updating user account status; * refactor(go): remove converters and access grants; * refactor(go): add json tags in schema models; * refactor(go): rename file to migrate_v1_6_0.go; * refactor(go): add user groups and user roles tables; use schema tables; * refactor(go): inline get and list from schema package; * refactor(go): inline get network and list users from schema package; * fix(go): staticcheck issues; * fix(go): remove test not in use; fix test case; * fix(go): validate network; * fix(go): resolve static checks; * fix(go): new models errors; * fix(go): test errors; * fix(go): handle no records; * fix(go): add validations for user object; * fix(go): set correct extclient status; * fix(go): test error; * feat(go): make schema the base package; * feat(go): add host schema; * feat(go): use schema host everywhere; * feat(go): inline get host, list hosts and delete host; * feat(go): use non-ptr value; * feat(go): use save to upsert all fields; * feat(go): use save to upsert all fields; * feat(go): save turn endpoint as string; * feat(go): check for gorm error record not found; * fix(go): test failures; * fix(go): update all network fields; * fix(go): update all network fields; * feat(go): add paginated list networks api; * feat(go): add paginated list users api; * feat(go): add paginated list hosts api; * feat(go): add pagination to list groups api; * fix(go): comment; * fix(go): implement marshal and unmarshal text for custom types; * fix(go): implement marshal and unmarshal json for custom types; * fix(go): just use the old model for unmarshalling; * fix(go): implement marshal and unmarshal json for custom types; * feat(go): remove paginated list networks api; * feat(go): use custom paginated response object; * fix(go): ensure default values for page and per_page are used when not passed; * fix(go): rename v1.6.0 to v1.5.1; * fix(go): check for gorm.ErrRecordNotFound instead of database.IsEmptyRecord; * fix(go): use host id, not pending host id; * feat(go): add filters to paginated apis; * feat(go): add filters to paginated apis; * feat(go): remove check for max username length; * feat(go): add filters to count as well; * feat(go): use library to check email address validity; * feat(go): ignore pagination if params not passed; * fix(go): pagination issues; * fix(go): check exists before using; * fix(go): remove debug log; * fix(go): use gorm err record not found; * fix(go): use gorm err record not found; * fix(go): use user principal name when creating pending user; * fix(go): use schema package for consts; * fix(go): prevent disabling superadmin user; Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * fix(go): swap is admin and is superadmin; Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * fix(go): remove dead code block; https://github.com/gravitl/netmaker/pull/3910#discussion_r2928837937 * fix(go): incorrect message when trying to disable self; https://github.com/gravitl/netmaker/pull/3910#discussion_r2928837934 * fix(go): use correct header; Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * fix(go): return after error response; Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * fix(go): use correct order of params; https://github.com/gravitl/netmaker/pull/3910#discussion_r2929593036 * fix(go): set default values for page and page size; use v2 instead of /list; * Update logic/auth.go Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * Update schema/user_roles.go Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * fix(go): syntax error; * fix(go): set default values when page and per_page are not passed or 0; * fix(go): use uuid.parse instead of uuid.must parse; * fix(go): review errors; * fix(go): review errors; * Update controllers/user.go Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * Update controllers/user.go Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * NM-163: fix errors: * Update db/types/options.go Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * fix(go): persist return user in event; * Update db/types/options.go Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com> * NM-163: duplicate lines of code * NM-163: fix(go): fix missing return and filter parsing in user controller - Add missing return after error response in updateUserAccountStatus to prevent double-response and spurious ext-client side-effects - Use switch statements in listUsers to skip unrecognized account_status and mfa_status filter values * fix(go): check for both min and max page size; * fix(go): enclose transfer superadmin in transaction; * fix(go): review errors; * fix(go): remove free tier checks; * fix(go): review fixes; --------- Co-authored-by: VishalDalwadi <dalwadivishal26@gmail.com> Co-authored-by: Vishal Dalwadi <51291657+VishalDalwadi@users.noreply.github.com> Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com>
254 lines
6.4 KiB
Go
254 lines
6.4 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/gravitl/netmaker/db"
|
|
"github.com/gravitl/netmaker/schema"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/gravitl/netmaker/database"
|
|
"github.com/gravitl/netmaker/logger"
|
|
"github.com/gravitl/netmaker/logic"
|
|
"github.com/gravitl/netmaker/models"
|
|
"github.com/stretchr/testify/assert"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
)
|
|
|
|
type NetworkValidationTestCase struct {
|
|
testname string
|
|
network schema.Network
|
|
errMessage string
|
|
}
|
|
|
|
var netHost schema.Host
|
|
|
|
func TestMain(m *testing.M) {
|
|
db.InitializeDB(schema.ListModels()...)
|
|
defer db.CloseDB()
|
|
|
|
database.InitializeDatabase()
|
|
defer database.CloseDB()
|
|
logic.CreateSuperAdmin(&schema.User{
|
|
Username: "admin",
|
|
Password: "password",
|
|
PlatformRoleID: schema.SuperAdminRole,
|
|
})
|
|
peerUpdate := make(chan *models.Node)
|
|
go logic.ManageZombies(context.Background())
|
|
go func() {
|
|
for update := range peerUpdate {
|
|
//do nothing
|
|
logger.Log(3, "received node update", update.Action)
|
|
}
|
|
}()
|
|
os.Exit(m.Run())
|
|
|
|
}
|
|
|
|
func TestCreateNetwork(t *testing.T) {
|
|
deleteAllNetworks()
|
|
|
|
var network schema.Network
|
|
network.Name = "skynet1"
|
|
network.AddressRange = "10.10.0.1/24"
|
|
// if tests break - check here (removed displayname)
|
|
//network.DisplayName = "mynetwork"
|
|
|
|
err := logic.CreateNetwork(&network)
|
|
assert.Nil(t, err)
|
|
}
|
|
func TestGetNetwork(t *testing.T) {
|
|
createNet()
|
|
|
|
t.Run("GetExistingNetwork", func(t *testing.T) {
|
|
network := &schema.Network{Name: "skynet"}
|
|
err := network.Get(db.WithContext(context.TODO()))
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "skynet", network.Name)
|
|
})
|
|
t.Run("GetNonExistantNetwork", func(t *testing.T) {
|
|
network := &schema.Network{Name: "doesnotexist"}
|
|
err := network.Get(db.WithContext(context.TODO()))
|
|
assert.EqualError(t, err, gorm.ErrRecordNotFound.Error())
|
|
assert.Equal(t, "", network.ID)
|
|
})
|
|
}
|
|
|
|
func TestDeleteNetwork(t *testing.T) {
|
|
createNet()
|
|
//create nodes
|
|
t.Run("NetworkwithNodes", func(t *testing.T) {
|
|
})
|
|
t.Run("DeleteExistingNetwork", func(t *testing.T) {
|
|
doneCh := make(chan struct{}, 1)
|
|
err := logic.DeleteNetwork("skynet", false, doneCh)
|
|
assert.Nil(t, err)
|
|
})
|
|
t.Run("NonExistentNetwork", func(t *testing.T) {
|
|
doneCh := make(chan struct{}, 1)
|
|
err := logic.DeleteNetwork("skynet", false, doneCh)
|
|
assert.Nil(t, err)
|
|
})
|
|
createNetv1("test")
|
|
t.Run("ForceDeleteNetwork", func(t *testing.T) {
|
|
doneCh := make(chan struct{}, 1)
|
|
err := logic.DeleteNetwork("test", true, doneCh)
|
|
assert.Nil(t, err)
|
|
})
|
|
}
|
|
|
|
func TestSecurityCheck(t *testing.T) {
|
|
//these seem to work but not sure it the tests are really testing the functionality
|
|
|
|
os.Setenv("MASTER_KEY", "secretkey")
|
|
t.Run("NoNetwork", func(t *testing.T) {
|
|
username, err := logic.UserPermissions(false, "Bearer secretkey")
|
|
assert.Nil(t, err)
|
|
t.Log(username)
|
|
})
|
|
|
|
t.Run("BadToken", func(t *testing.T) {
|
|
username, err := logic.UserPermissions(false, "Bearer badkey")
|
|
assert.NotNil(t, err)
|
|
t.Log(err)
|
|
t.Log(username)
|
|
})
|
|
}
|
|
|
|
func TestValidateNetwork(t *testing.T) {
|
|
//t.Skip()
|
|
//This functions is not called by anyone
|
|
//it panics as validation function 'display_name_valid' is not defined
|
|
//yes := true
|
|
//no := false
|
|
//deleteNet(t)
|
|
|
|
//DeleteNetworks
|
|
cases := []NetworkValidationTestCase{
|
|
{
|
|
testname: "InvalidAddress",
|
|
network: schema.Network{
|
|
Name: "skynet",
|
|
AddressRange: "10.0.0.256",
|
|
},
|
|
errMessage: "invalid CIDR address: 10.0.0.256",
|
|
},
|
|
{
|
|
testname: "InvalidAddress6",
|
|
network: schema.Network{
|
|
Name: "skynet1",
|
|
AddressRange6: "2607::ffff/130",
|
|
},
|
|
errMessage: "invalid CIDR address: 2607::ffff/130",
|
|
},
|
|
{
|
|
testname: "InvalidNetID",
|
|
network: schema.Network{
|
|
Name: "with spaces",
|
|
},
|
|
errMessage: "invalid character(s) in network name",
|
|
},
|
|
{
|
|
testname: "NetIDTooLong",
|
|
network: schema.Network{
|
|
Name: "LongNetIDNameForMaxCharactersTest",
|
|
},
|
|
errMessage: "network name cannot be longer than 32 characters",
|
|
},
|
|
{
|
|
testname: "KeepAliveTooBig",
|
|
network: schema.Network{
|
|
Name: "skynet",
|
|
DefaultKeepAlive: 1010,
|
|
},
|
|
errMessage: "default keep alive must be less than 1000",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.testname, func(t *testing.T) {
|
|
t.Log(tc.testname)
|
|
network := tc.network
|
|
err := logic.ValidateNetwork(&network, false)
|
|
|
|
assert.NotNil(t, err)
|
|
assert.Contains(t, err.Error(), tc.errMessage) // test passes if err.Error() contains the expected errMessage.
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIpv6Network(t *testing.T) {
|
|
//these seem to work but not sure it the tests are really testing the functionality
|
|
|
|
os.Setenv("MASTER_KEY", "secretkey")
|
|
deleteAllNetworks()
|
|
createNet()
|
|
createNetDualStack()
|
|
network := &schema.Network{Name: "skynet6"}
|
|
err := network.Get(db.WithContext(context.TODO()))
|
|
t.Run("Test Network Create IPv6", func(t *testing.T) {
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, network.AddressRange6, "fde6:be04:fa5e:d076::/64")
|
|
})
|
|
node1 := createNodeWithParams("skynet6", "")
|
|
createNetHost()
|
|
nodeErr := logic.AssociateNodeToHost(node1, &netHost)
|
|
t.Run("Test node on network IPv6", func(t *testing.T) {
|
|
assert.Nil(t, nodeErr)
|
|
assert.Equal(t, "fde6:be04:fa5e:d076::1", node1.Address6.IP.String())
|
|
})
|
|
}
|
|
|
|
func deleteAllNetworks() {
|
|
deleteAllNodes()
|
|
_networks, _ := (&schema.Network{}).ListAll(db.WithContext(context.TODO()))
|
|
for _, _network := range _networks {
|
|
_ = _network.Delete(db.WithContext(context.TODO()))
|
|
}
|
|
}
|
|
|
|
func createNet() {
|
|
var network schema.Network
|
|
network.Name = "skynet"
|
|
network.AddressRange = "10.0.0.1/24"
|
|
err := (&schema.Network{Name: "skynet"}).Get(db.WithContext(context.TODO()))
|
|
if err != nil {
|
|
logic.CreateNetwork(&network)
|
|
}
|
|
}
|
|
func createNetv1(netId string) {
|
|
var network schema.Network
|
|
network.Name = netId
|
|
network.AddressRange = "100.0.0.1/24"
|
|
err := (&schema.Network{Name: netId}).Get(db.WithContext(context.TODO()))
|
|
if err != nil {
|
|
logic.CreateNetwork(&network)
|
|
}
|
|
}
|
|
|
|
func createNetDualStack() {
|
|
var network schema.Network
|
|
network.Name = "skynet6"
|
|
network.AddressRange = "10.1.2.0/24"
|
|
network.AddressRange6 = "fde6:be04:fa5e:d076::/64"
|
|
err := (&schema.Network{Name: "skynet6"}).Get(db.WithContext(context.TODO()))
|
|
if err != nil {
|
|
logic.CreateNetwork(&network)
|
|
}
|
|
}
|
|
|
|
func createNetHost() {
|
|
k, _ := wgtypes.ParseKey("DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=")
|
|
netHost = schema.Host{
|
|
ID: uuid.New(),
|
|
PublicKey: schema.WgKey{Key: k.PublicKey()},
|
|
HostPass: "password",
|
|
OS: "linux",
|
|
Name: "nethost",
|
|
}
|
|
_ = logic.CreateHost(&netHost)
|
|
}
|