From 30ede299b859b96a34f32747f498d479a476af9c Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 11:50:33 +0200 Subject: [PATCH 01/22] Optimize peer storing in SQLite --- management/server/sqlite_store.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index e6a9c8467..166b6e899 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -141,6 +141,22 @@ func (s *SqliteStore) SaveAccount(account *Account) error { account.SetupKeysG = append(account.SetupKeysG, *key) } + const batchSize = 500 + + // Function to batch insert peers + batchInsertPeers := func(peers []nbpeer.Peer, tx *gorm.DB) error { + for i := 0; i < len(peers); i += batchSize { + end := i + batchSize + if end > len(peers) { + end = len(peers) + } + if err := tx.CreateInBatches(peers[i:end], batchSize).Error; err != nil { + return err + } + } + return nil + } + for id, peer := range account.Peers { peer.ID = id account.PeersG = append(account.PeersG, *peer) @@ -188,18 +204,21 @@ func (s *SqliteStore) SaveAccount(account *Account) error { result = tx. Session(&gorm.Session{FullSaveAssociations: true}). - Clauses(clause.OnConflict{UpdateAll: true}).Create(account) + Clauses(clause.OnConflict{UpdateAll: true}). + Omit("PeersG"). + Create(account) if result.Error != nil { return result.Error } - return nil + + return batchInsertPeers(account.PeersG, tx) }) took := time.Since(start) if s.metrics != nil { s.metrics.StoreMetrics().CountPersistenceDuration(took) } - log.Debugf("took %d ms to persist an account to the SQLite", took.Milliseconds()) + log.Debugf("took %d ms to persist an account %s to the SQLite store", took.Milliseconds(), account.Id) return err } From e7a64839123f141ce792c235a34ce2aec922e645 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 12:35:41 +0200 Subject: [PATCH 02/22] Optimize all other objects storing in SQLite --- management/server/sqlite_store.go | 60 +++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 166b6e899..e9a3d2362 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "path/filepath" + "reflect" "runtime" "strings" "sync" @@ -134,6 +135,28 @@ func (s *SqliteStore) AcquireAccountLock(accountID string) (unlock func()) { return unlock } +func batchInsert(records interface{}, batchSize int, tx *gorm.DB) error { + // Get the reflect.Value of the records slice + v := reflect.ValueOf(records) + if v.Kind() != reflect.Slice { + return fmt.Errorf("provided input is not a slice") + } + + // Insert records in batches + for i := 0; i < v.Len(); i += batchSize { + end := i + batchSize + if end > v.Len() { + end = v.Len() + } + // Use reflect.Slice to get a slice of the records for the current batch + batch := v.Slice(i, end).Interface() + if err := tx.CreateInBatches(batch, end-i).Error; err != nil { + return err + } + } + return nil +} + func (s *SqliteStore) SaveAccount(account *Account) error { start := time.Now() @@ -141,22 +164,6 @@ func (s *SqliteStore) SaveAccount(account *Account) error { account.SetupKeysG = append(account.SetupKeysG, *key) } - const batchSize = 500 - - // Function to batch insert peers - batchInsertPeers := func(peers []nbpeer.Peer, tx *gorm.DB) error { - for i := 0; i < len(peers); i += batchSize { - end := i + batchSize - if end > len(peers) { - end = len(peers) - } - if err := tx.CreateInBatches(peers[i:end], batchSize).Error; err != nil { - return err - } - } - return nil - } - for id, peer := range account.Peers { peer.ID = id account.PeersG = append(account.PeersG, *peer) @@ -205,13 +212,30 @@ func (s *SqliteStore) SaveAccount(account *Account) error { result = tx. Session(&gorm.Session{FullSaveAssociations: true}). Clauses(clause.OnConflict{UpdateAll: true}). - Omit("PeersG"). + Omit("PeersG", "GroupsG", "UsersG", "SetupKeysG", "RoutesG"). Create(account) if result.Error != nil { return result.Error } - return batchInsertPeers(account.PeersG, tx) + const batchSize = 500 + err := batchInsert(account.PeersG, batchSize, tx) + if err != nil { + return err + } + err = batchInsert(account.UsersG, batchSize, tx) + if err != nil { + return err + } + err = batchInsert(account.GroupsG, batchSize, tx) + if err != nil { + return err + } + err = batchInsert(account.RoutesG, batchSize, tx) + if err != nil { + return err + } + return batchInsert(account.SetupKeysG, batchSize, tx) }) took := time.Since(start) From a75f982fcd80b351642733eee5c40bfb425bf1be Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 17:03:21 +0200 Subject: [PATCH 03/22] Copy account when storing to avoid reference issues --- management/server/sqlite_store.go | 60 +++++++++++++++++++------------ 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index e9a3d2362..53526a980 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -150,7 +150,7 @@ func batchInsert(records interface{}, batchSize int, tx *gorm.DB) error { } // Use reflect.Slice to get a slice of the records for the current batch batch := v.Slice(i, end).Interface() - if err := tx.CreateInBatches(batch, end-i).Error; err != nil { + if err := tx.CreateInBatches(batch, end-i).Debug().Error; err != nil { return err } } @@ -160,51 +160,65 @@ func batchInsert(records interface{}, batchSize int, tx *gorm.DB) error { func (s *SqliteStore) SaveAccount(account *Account) error { start := time.Now() - for _, key := range account.SetupKeys { - account.SetupKeysG = append(account.SetupKeysG, *key) + // operate over a fresh copy as we will modify its fields + accCopy := account.Copy() + accCopy.SetupKeysG = make([]SetupKey, 0, len(accCopy.SetupKeys)) + for _, key := range accCopy.SetupKeys { + accCopy.SetupKeysG = append(accCopy.SetupKeysG, *key) } - for id, peer := range account.Peers { + accCopy.PeersG = make([]nbpeer.Peer, 0, len(accCopy.Peers)) + for id, peer := range accCopy.Peers { peer.ID = id - account.PeersG = append(account.PeersG, *peer) + peer.AccountID = account.Id + accCopy.PeersG = append(accCopy.PeersG, *peer) } - for id, user := range account.Users { + accCopy.UsersG = make([]User, 0, len(accCopy.Users)) + for id, user := range accCopy.Users { user.Id = id + user.AccountID = accCopy.Id + user.PATsG = make([]PersonalAccessToken, 0, len(user.PATs)) for id, pat := range user.PATs { pat.ID = id user.PATsG = append(user.PATsG, *pat) } - account.UsersG = append(account.UsersG, *user) + accCopy.UsersG = append(accCopy.UsersG, *user) } - for id, group := range account.Groups { + accCopy.GroupsG = make([]nbgroup.Group, 0, len(accCopy.Groups)) + for id, group := range accCopy.Groups { group.ID = id - account.GroupsG = append(account.GroupsG, *group) + group.AccountID = accCopy.Id + accCopy.GroupsG = append(accCopy.GroupsG, *group) } - for id, route := range account.Routes { + accCopy.RoutesG = make([]route.Route, 0, len(accCopy.Routes)) + for id, route := range accCopy.Routes { route.ID = id - account.RoutesG = append(account.RoutesG, *route) + route.AccountID = accCopy.Id + accCopy.RoutesG = append(accCopy.RoutesG, *route) } - for id, ns := range account.NameServerGroups { + accCopy.NameServerGroupsG = make([]nbdns.NameServerGroup, 0, len(accCopy.NameServerGroups)) + for id, ns := range accCopy.NameServerGroups { ns.ID = id - account.NameServerGroupsG = append(account.NameServerGroupsG, *ns) + ns.AccountID = accCopy.Id + accCopy.NameServerGroupsG = append(accCopy.NameServerGroupsG, *ns) } err := s.db.Transaction(func(tx *gorm.DB) error { - result := tx.Select(clause.Associations).Delete(account.Policies, "account_id = ?", account.Id) + result := tx.Select(clause.Associations).Delete(accCopy.Policies, "account_id = ?", accCopy.Id) if result.Error != nil { return result.Error } - result = tx.Select(clause.Associations).Delete(account.UsersG, "account_id = ?", account.Id) + result = tx.Select(clause.Associations).Delete(accCopy.UsersG, "account_id = ?", accCopy.Id) if result.Error != nil { return result.Error } - result = tx.Select(clause.Associations).Delete(account) + result = tx.Select(clause.Associations).Delete(accCopy) if result.Error != nil { return result.Error } @@ -213,36 +227,36 @@ func (s *SqliteStore) SaveAccount(account *Account) error { Session(&gorm.Session{FullSaveAssociations: true}). Clauses(clause.OnConflict{UpdateAll: true}). Omit("PeersG", "GroupsG", "UsersG", "SetupKeysG", "RoutesG"). - Create(account) + Create(accCopy) if result.Error != nil { return result.Error } const batchSize = 500 - err := batchInsert(account.PeersG, batchSize, tx) + err := batchInsert(accCopy.PeersG, batchSize, tx) if err != nil { return err } - err = batchInsert(account.UsersG, batchSize, tx) + err = batchInsert(accCopy.UsersG, batchSize, tx) if err != nil { return err } - err = batchInsert(account.GroupsG, batchSize, tx) + err = batchInsert(accCopy.GroupsG, batchSize, tx) if err != nil { return err } - err = batchInsert(account.RoutesG, batchSize, tx) + err = batchInsert(accCopy.RoutesG, batchSize, tx) if err != nil { return err } - return batchInsert(account.SetupKeysG, batchSize, tx) + return batchInsert(accCopy.SetupKeysG, batchSize, tx) }) took := time.Since(start) if s.metrics != nil { s.metrics.StoreMetrics().CountPersistenceDuration(took) } - log.Debugf("took %d ms to persist an account %s to the SQLite store", took.Milliseconds(), account.Id) + log.Debugf("took %d ms to persist an account %s to the SQLite store", took.Milliseconds(), accCopy.Id) return err } From 99854a126a65c1f907de143b0a6487c68dbbaf6d Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 17:08:01 +0200 Subject: [PATCH 04/22] Add comments --- management/server/sqlite_store.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 53526a980..0da980885 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -170,13 +170,15 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.PeersG = make([]nbpeer.Peer, 0, len(accCopy.Peers)) for id, peer := range accCopy.Peers { peer.ID = id - peer.AccountID = account.Id + //we need an explicit reference to the account as it is missing for some reason + peer.AccountID = accCopy.Id accCopy.PeersG = append(accCopy.PeersG, *peer) } accCopy.UsersG = make([]User, 0, len(accCopy.Users)) for id, user := range accCopy.Users { user.Id = id + //we need an explicit reference to an account as it is missing for some reason user.AccountID = accCopy.Id user.PATsG = make([]PersonalAccessToken, 0, len(user.PATs)) for id, pat := range user.PATs { @@ -189,6 +191,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.GroupsG = make([]nbgroup.Group, 0, len(accCopy.Groups)) for id, group := range accCopy.Groups { group.ID = id + //we need an explicit reference to the account as it is missing for some reason group.AccountID = accCopy.Id accCopy.GroupsG = append(accCopy.GroupsG, *group) } @@ -196,6 +199,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.RoutesG = make([]route.Route, 0, len(accCopy.Routes)) for id, route := range accCopy.Routes { route.ID = id + //we need an explicit reference to the account as it is missing for some reason route.AccountID = accCopy.Id accCopy.RoutesG = append(accCopy.RoutesG, *route) } @@ -203,6 +207,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.NameServerGroupsG = make([]nbdns.NameServerGroup, 0, len(accCopy.NameServerGroups)) for id, ns := range accCopy.NameServerGroups { ns.ID = id + //we need an explicit reference to the account as it is missing for some reason ns.AccountID = accCopy.Id accCopy.NameServerGroupsG = append(accCopy.NameServerGroupsG, *ns) } From 38e10af2d90b3c22e41a264ecf730d411df7a63c Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 17:16:56 +0200 Subject: [PATCH 05/22] Add accountID reference --- management/server/account.go | 11 ++++++----- management/server/user.go | 26 ++++++++++++++++---------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/management/server/account.go b/management/server/account.go index c3ba0c86c..8096d185d 100644 --- a/management/server/account.go +++ b/management/server/account.go @@ -1473,7 +1473,7 @@ func (am *DefaultAccountManager) handleNewUserAccount(domainAcc *Account, claims // if domain already has a primary account, add regular user if domainAcc != nil { account = domainAcc - account.Users[claims.UserId] = NewRegularUser(claims.UserId) + account.Users[claims.UserId] = NewRegularUser(claims.UserId, account.Id) err = am.Store.SaveAccount(account) if err != nil { return nil, err @@ -1862,9 +1862,10 @@ func (am *DefaultAccountManager) onPeersInvalidated(accountID string) { func addAllGroup(account *Account) error { if len(account.Groups) == 0 { allGroup := &nbgroup.Group{ - ID: xid.New().String(), - Name: "All", - Issued: nbgroup.GroupIssuedAPI, + ID: xid.New().String(), + Name: "All", + Issued: nbgroup.GroupIssuedAPI, + AccountID: account.Id, } for _, peer := range account.Peers { allGroup.Peers = append(allGroup.Peers, peer.ID) @@ -1908,7 +1909,7 @@ func newAccountWithId(accountID, userID, domain string) *Account { routes := make(map[string]*route.Route) setupKeys := map[string]*SetupKey{} nameServersGroups := make(map[string]*nbdns.NameServerGroup) - users[userID] = NewOwnerUser(userID) + users[userID] = NewOwnerUser(userID, accountID) dnsSettings := DNSSettings{ DisabledManagementGroups: make([]string, 0), } diff --git a/management/server/user.go b/management/server/user.go index b955c4058..9d3055262 100644 --- a/management/server/user.go +++ b/management/server/user.go @@ -180,9 +180,11 @@ func (u *User) Copy() *User { } // NewUser creates a new user -func NewUser(id string, role UserRole, isServiceUser bool, nonDeletable bool, serviceUserName string, autoGroups []string, issued string) *User { +func NewUser(ID string, role UserRole, isServiceUser bool, nonDeletable bool, serviceUserName string, autoGroups []string, issued string, + accountID string) *User { return &User{ - Id: id, + Id: ID, + AccountID: accountID, Role: role, IsServiceUser: isServiceUser, NonDeletable: nonDeletable, @@ -194,22 +196,26 @@ func NewUser(id string, role UserRole, isServiceUser bool, nonDeletable bool, se } // NewRegularUser creates a new user with role UserRoleUser -func NewRegularUser(id string) *User { - return NewUser(id, UserRoleUser, false, false, "", []string{}, UserIssuedAPI) +func NewRegularUser(ID, accountID string) *User { + return NewUser(ID, UserRoleUser, false, false, "", []string{}, UserIssuedAPI, + accountID) } // NewAdminUser creates a new user with role UserRoleAdmin -func NewAdminUser(id string) *User { - return NewUser(id, UserRoleAdmin, false, false, "", []string{}, UserIssuedAPI) +func NewAdminUser(ID, accountID string) *User { + return NewUser(ID, UserRoleAdmin, false, false, "", []string{}, UserIssuedAPI, + accountID) } // NewOwnerUser creates a new user with role UserRoleOwner -func NewOwnerUser(id string) *User { - return NewUser(id, UserRoleOwner, false, false, "", []string{}, UserIssuedAPI) +func NewOwnerUser(ID, accountID string) *User { + return NewUser(ID, UserRoleOwner, false, false, "", []string{}, UserIssuedAPI, + accountID) } // createServiceUser creates a new service user under the given account. -func (am *DefaultAccountManager) createServiceUser(accountID string, initiatorUserID string, role UserRole, serviceUserName string, nonDeletable bool, autoGroups []string) (*UserInfo, error) { +func (am *DefaultAccountManager) createServiceUser(accountID string, initiatorUserID string, role UserRole, + serviceUserName string, nonDeletable bool, autoGroups []string) (*UserInfo, error) { unlock := am.Store.AcquireAccountLock(accountID) defer unlock() @@ -231,7 +237,7 @@ func (am *DefaultAccountManager) createServiceUser(accountID string, initiatorUs } newUserID := uuid.New().String() - newUser := NewUser(newUserID, role, true, nonDeletable, serviceUserName, autoGroups, UserIssuedAPI) + newUser := NewUser(newUserID, role, true, nonDeletable, serviceUserName, autoGroups, UserIssuedAPI, accountID) log.Debugf("New User: %v", newUser) account.Users[newUserID] = newUser From 83dfe8e3a3ad84a09f41e825c0ff5eefcc9c3951 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 17:27:23 +0200 Subject: [PATCH 06/22] Fix test compilation errors --- management/server/http/accounts_handler_test.go | 2 +- management/server/http/dns_settings_handler_test.go | 2 +- management/server/http/events_handler_test.go | 2 +- management/server/http/geolocation_handler_test.go | 2 +- management/server/http/groups_handler_test.go | 6 +++--- management/server/http/nameservers_handler_test.go | 2 +- management/server/http/peers_handler_test.go | 2 +- management/server/http/policies_handler_test.go | 2 +- management/server/http/posture_checks_handler_test.go | 2 +- management/server/http/routes_handler_test.go | 2 +- management/server/http/setupkeys_handler_test.go | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/management/server/http/accounts_handler_test.go b/management/server/http/accounts_handler_test.go index 9d174d0be..1c4d6518b 100644 --- a/management/server/http/accounts_handler_test.go +++ b/management/server/http/accounts_handler_test.go @@ -54,7 +54,7 @@ func initAccountsTestData(account *server.Account, admin *server.User) *Accounts func TestAccounts_AccountsHandler(t *testing.T) { accountID := "test_account" - adminUser := server.NewAdminUser("test_user") + adminUser := server.NewAdminUser("test_user", "account_id") sr := func(v string) *string { return &v } br := func(v bool) *bool { return &v } diff --git a/management/server/http/dns_settings_handler_test.go b/management/server/http/dns_settings_handler_test.go index a2f65a521..1018bb080 100644 --- a/management/server/http/dns_settings_handler_test.go +++ b/management/server/http/dns_settings_handler_test.go @@ -34,7 +34,7 @@ var testingDNSSettingsAccount = &server.Account{ Id: testDNSSettingsAccountID, Domain: "hotmail.com", Users: map[string]*server.User{ - testDNSSettingsUserID: server.NewAdminUser("test_user"), + testDNSSettingsUserID: server.NewAdminUser("test_user", "account_id"), }, DNSSettings: baseExistingDNSSettings, } diff --git a/management/server/http/events_handler_test.go b/management/server/http/events_handler_test.go index 4cfad922b..46fe2989f 100644 --- a/management/server/http/events_handler_test.go +++ b/management/server/http/events_handler_test.go @@ -196,7 +196,7 @@ func TestEvents_GetEvents(t *testing.T) { }, } accountID := "test_account" - adminUser := server.NewAdminUser("test_user") + adminUser := server.NewAdminUser("test_user", "account_id") events := generateEvents(accountID, adminUser.Id) handler := initEventsTestData(accountID, adminUser, events...) diff --git a/management/server/http/geolocation_handler_test.go b/management/server/http/geolocation_handler_test.go index 226711002..37406ec24 100644 --- a/management/server/http/geolocation_handler_test.go +++ b/management/server/http/geolocation_handler_test.go @@ -42,7 +42,7 @@ func initGeolocationTestData(t *testing.T) *GeolocationsHandler { return &GeolocationsHandler{ accountManager: &mock_server.MockAccountManager{ GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) { - user := server.NewAdminUser("test_user") + user := server.NewAdminUser("test_user", "account_id") return &server.Account{ Id: claims.AccountId, Users: map[string]*server.User{ diff --git a/management/server/http/groups_handler_test.go b/management/server/http/groups_handler_test.go index 3d74b848c..88ba95931 100644 --- a/management/server/http/groups_handler_test.go +++ b/management/server/http/groups_handler_test.go @@ -124,7 +124,7 @@ func TestGetGroup(t *testing.T) { Name: "Group", } - adminUser := server.NewAdminUser("test_user") + adminUser := server.NewAdminUser("test_user", "account_id") p := initGroupTestData(adminUser, group) for _, tc := range tt { @@ -246,7 +246,7 @@ func TestWriteGroup(t *testing.T) { }, } - adminUser := server.NewAdminUser("test_user") + adminUser := server.NewAdminUser("test_user", "account_id") p := initGroupTestData(adminUser) for _, tc := range tt { @@ -324,7 +324,7 @@ func TestDeleteGroup(t *testing.T) { }, } - adminUser := server.NewAdminUser("test_user") + adminUser := server.NewAdminUser("test_user", "account_id") p := initGroupTestData(adminUser) for _, tc := range tt { diff --git a/management/server/http/nameservers_handler_test.go b/management/server/http/nameservers_handler_test.go index e1fabb198..2797a192b 100644 --- a/management/server/http/nameservers_handler_test.go +++ b/management/server/http/nameservers_handler_test.go @@ -32,7 +32,7 @@ var testingNSAccount = &server.Account{ Id: testNSGroupAccountID, Domain: "hotmail.com", Users: map[string]*server.User{ - "test_user": server.NewAdminUser("test_user"), + "test_user": server.NewAdminUser("test_user", "account_id"), }, } diff --git a/management/server/http/peers_handler_test.go b/management/server/http/peers_handler_test.go index e43c4375e..1f3909f55 100644 --- a/management/server/http/peers_handler_test.go +++ b/management/server/http/peers_handler_test.go @@ -59,7 +59,7 @@ func initTestMetaData(peers ...*nbpeer.Peer) *PeersHandler { return "netbird.selfhosted" }, GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) { - user := server.NewAdminUser("test_user") + user := server.NewAdminUser("test_user", "account_id") return &server.Account{ Id: claims.AccountId, Domain: "hotmail.com", diff --git a/management/server/http/policies_handler_test.go b/management/server/http/policies_handler_test.go index 74e682854..904ca25fa 100644 --- a/management/server/http/policies_handler_test.go +++ b/management/server/http/policies_handler_test.go @@ -45,7 +45,7 @@ func initPoliciesTestData(policies ...*server.Policy) *Policies { return nil }, GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) { - user := server.NewAdminUser("test_user") + user := server.NewAdminUser("test_user", "account_id") return &server.Account{ Id: claims.AccountId, Domain: "hotmail.com", diff --git a/management/server/http/posture_checks_handler_test.go b/management/server/http/posture_checks_handler_test.go index 70e803214..397b53b12 100644 --- a/management/server/http/posture_checks_handler_test.go +++ b/management/server/http/posture_checks_handler_test.go @@ -62,7 +62,7 @@ func initPostureChecksTestData(postureChecks ...*posture.Checks) *PostureChecksH return accountPostureChecks, nil }, GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) { - user := server.NewAdminUser("test_user") + user := server.NewAdminUser("test_user", "account_id") return &server.Account{ Id: claims.AccountId, Users: map[string]*server.User{ diff --git a/management/server/http/routes_handler_test.go b/management/server/http/routes_handler_test.go index c02292f2a..81bdf7d0e 100644 --- a/management/server/http/routes_handler_test.go +++ b/management/server/http/routes_handler_test.go @@ -75,7 +75,7 @@ var testingAccount = &server.Account{ }, }, Users: map[string]*server.User{ - "test_user": server.NewAdminUser("test_user"), + "test_user": server.NewAdminUser("test_user", "account_id"), }, } diff --git a/management/server/http/setupkeys_handler_test.go b/management/server/http/setupkeys_handler_test.go index ebbd5954f..e42b0b669 100644 --- a/management/server/http/setupkeys_handler_test.go +++ b/management/server/http/setupkeys_handler_test.go @@ -97,7 +97,7 @@ func TestSetupKeysHandlers(t *testing.T) { defaultSetupKey := server.GenerateDefaultSetupKey() defaultSetupKey.Id = existingSetupKeyID - adminUser := server.NewAdminUser("test_user") + adminUser := server.NewAdminUser("test_user", "account_id") newSetupKey := server.GenerateSetupKey(newSetupKeyName, server.SetupKeyReusable, 0, []string{"group-1"}, server.SetupKeyUnlimitedUsage, true) From 48aff7a26ef6a6de71716e1bd57e74137fdc0f82 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 17:39:28 +0200 Subject: [PATCH 07/22] Fix test compilation errors --- management/server/sqlite_store_test.go | 2 +- management/server/user_test.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/management/server/sqlite_store_test.go b/management/server/sqlite_store_test.go index e43a0cd9a..92e7e8b83 100644 --- a/management/server/sqlite_store_test.go +++ b/management/server/sqlite_store_test.go @@ -110,7 +110,7 @@ func TestSqlite_DeleteAccount(t *testing.T) { store := newSqliteStore(t) testUserID := "testuser" - user := NewAdminUser(testUserID) + user := NewAdminUser(testUserID, "account_id") user.PATs = map[string]*PersonalAccessToken{"testtoken": { ID: "testtoken", Name: "test token", diff --git a/management/server/user_test.go b/management/server/user_test.go index c92f87e6c..82869ad09 100644 --- a/management/server/user_test.go +++ b/management/server/user_test.go @@ -679,8 +679,8 @@ func TestDefaultAccountManager_GetUser(t *testing.T) { func TestDefaultAccountManager_ListUsers(t *testing.T) { store := newStore(t) account := newAccountWithId(mockAccountID, mockUserID, "") - account.Users["normal_user1"] = NewRegularUser("normal_user1") - account.Users["normal_user2"] = NewRegularUser("normal_user2") + account.Users["normal_user1"] = NewRegularUser("normal_user1", mockAccountID) + account.Users["normal_user2"] = NewRegularUser("normal_user2", mockAccountID) err := store.SaveAccount(account) if err != nil { @@ -760,7 +760,7 @@ func TestDefaultAccountManager_ListUsers_DashboardPermissions(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { store := newStore(t) account := newAccountWithId(mockAccountID, mockUserID, "") - account.Users["normal_user1"] = NewUser("normal_user1", testCase.role, false, false, "", []string{}, UserIssuedAPI) + account.Users["normal_user1"] = NewUser("normal_user1", testCase.role, false, false, "", []string{}, UserIssuedAPI, mockAccountID) account.Settings.RegularUsersViewBlocked = testCase.limitedViewSettings delete(account.Users, mockUserID) @@ -844,10 +844,10 @@ func TestDefaultAccountManager_ExternalCache(t *testing.T) { func TestUser_IsAdmin(t *testing.T) { - user := NewAdminUser(mockUserID) + user := NewAdminUser(mockUserID, mockAccountID) assert.True(t, user.HasAdminPower()) - user = NewRegularUser(mockUserID) + user = NewRegularUser(mockUserID, mockAccountID) assert.False(t, user.HasAdminPower()) } @@ -1055,8 +1055,8 @@ func TestDefaultAccountManager_SaveUser(t *testing.T) { } // create other users - account.Users[regularUserID] = NewRegularUser(regularUserID) - account.Users[adminUserID] = NewAdminUser(adminUserID) + account.Users[regularUserID] = NewRegularUser(regularUserID, account.Id) + account.Users[adminUserID] = NewAdminUser(adminUserID, account.Id) account.Users[serviceUserID] = &User{IsServiceUser: true, Id: serviceUserID, Role: UserRoleAdmin, ServiceUserName: "service"} err = manager.Store.SaveAccount(account) if err != nil { From fd3c1dea8e4d7ee86183d37b870da73f07c2b01d Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 18:02:10 +0200 Subject: [PATCH 08/22] Add save large account test --- management/server/sqlite_store_test.go | 134 +++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/management/server/sqlite_store_test.go b/management/server/sqlite_store_test.go index 92e7e8b83..db59a6cc1 100644 --- a/management/server/sqlite_store_test.go +++ b/management/server/sqlite_store_test.go @@ -2,7 +2,12 @@ package server import ( "fmt" + nbdns "github.com/netbirdio/netbird/dns" + nbgroup "github.com/netbirdio/netbird/management/server/group" + route2 "github.com/netbirdio/netbird/route" + "math/rand" "net" + "net/netip" "path/filepath" "runtime" "testing" @@ -29,6 +34,126 @@ func TestSqlite_NewStore(t *testing.T) { t.Errorf("expected to create a new empty Accounts map when creating a new FileStore") } } +func TestSqlite_SaveAccount_Large(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("The SQLite store is not properly supported by Windows yet") + } + + store := newSqliteStore(t) + + account := newAccountWithId("account_id", "testuser", "") + groupALL, err := account.GetGroupAll() + if err != nil { + t.Fatal(err) + } + setupKey := GenerateDefaultSetupKey() + account.SetupKeys[setupKey.Key] = setupKey + const numPerAccount = 2000 + for n := 0; n < numPerAccount; n++ { + netIP := randomIPv4() + peerID := fmt.Sprintf("%s-peer-%d", account.Id, n) + + peer := &nbpeer.Peer{ + ID: peerID, + Key: peerID, + SetupKey: "", + IP: netIP, + Name: peerID, + DNSLabel: peerID, + UserID: userID, + Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()}, + SSHEnabled: false, + } + account.Peers[peerID] = peer + group, _ := account.GetGroupAll() + group.Peers = append(group.Peers, peerID) + user := &User{ + Id: fmt.Sprintf("%s-user-%d", account.Id, n), + AccountID: account.Id, + } + account.Users[user.Id] = user + route := &route2.Route{ + ID: fmt.Sprintf("network-id-%d", n), + Description: "base route", + NetID: fmt.Sprintf("network-id-%d", n), + Network: netip.MustParsePrefix(netIP.String() + "/24"), + NetworkType: route2.IPv4Network, + Metric: 9999, + Masquerade: false, + Enabled: true, + Groups: []string{groupALL.ID}, + } + account.Routes[route.ID] = route + + group = &nbgroup.Group{ + ID: fmt.Sprintf("group-id-%d", n), + AccountID: account.Id, + Name: fmt.Sprintf("group-id-%d", n), + Issued: "api", + Peers: nil, + } + account.Groups[group.ID] = group + + nameserver := &nbdns.NameServerGroup{ + ID: fmt.Sprintf("nameserver-id-%d", n), + AccountID: account.Id, + Name: fmt.Sprintf("nameserver-id-%d", n), + Description: "", + NameServers: []nbdns.NameServer{{IP: netip.MustParseAddr(netIP.String()), NSType: nbdns.UDPNameServerType}}, + Groups: []string{group.ID}, + Primary: false, + Domains: nil, + Enabled: false, + SearchDomainsEnabled: false, + } + account.NameServerGroups[nameserver.ID] = nameserver + } + + err = store.SaveAccount(account) + require.NoError(t, err) + + if len(store.GetAllAccounts()) != 1 { + t.Errorf("expecting 1 Accounts to be stored after SaveAccount()") + } + + a, err := store.GetAccount(account.Id) + if a == nil { + t.Errorf("expecting Account to be stored after SaveAccount(): %v", err) + } + + if a != nil && len(a.Policies) != 1 { + t.Errorf("expecting Account to have one policy stored after SaveAccount(), got %d", len(a.Policies)) + } + + if a != nil && len(a.Policies[0].Rules) != 1 { + t.Errorf("expecting Account to have one policy rule stored after SaveAccount(), got %d", len(a.Policies[0].Rules)) + return + } + + if a != nil && len(a.Peers) != numPerAccount { + t.Errorf("expecting Account to have %d peers stored after SaveAccount(), got %d", + numPerAccount, len(a.Peers)) + return + } + + if a != nil && len(a.Users) != numPerAccount+1 { + t.Errorf("expecting Account to have %d users stored after SaveAccount(), got %d", + numPerAccount+1, len(a.Users)) + return + } + + if a != nil && len(a.Routes) != numPerAccount { + t.Errorf("expecting Account to have %d routes stored after SaveAccount(), got %d", + numPerAccount, len(a.Routes)) + return + } + + if a != nil && len(a.NameServerGroups) != numPerAccount { + t.Errorf("expecting Account to have %d NameServerGroups stored after SaveAccount(), got %d", + numPerAccount, len(a.NameServerGroups)) + return + } +} func TestSqlite_SaveAccount(t *testing.T) { if runtime.GOOS == "windows" { @@ -393,3 +518,12 @@ func newAccount(store Store, id int) error { return store.SaveAccount(account) } + +func randomIPv4() net.IP { + rand.Seed(time.Now().UnixNano()) + b := make([]byte, 4) + for i := range b { + b[i] = byte(rand.Intn(256)) + } + return net.IP(b) +} From 93045f3e3ad202e06add8add95284c22178ee12c Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 18:07:02 +0200 Subject: [PATCH 09/22] Fix rand lint issue --- management/server/sqlite_store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store_test.go b/management/server/sqlite_store_test.go index db59a6cc1..eb21be977 100644 --- a/management/server/sqlite_store_test.go +++ b/management/server/sqlite_store_test.go @@ -520,7 +520,7 @@ func newAccount(store Store, id int) error { } func randomIPv4() net.IP { - rand.Seed(time.Now().UnixNano()) + rand.New(rand.NewSource(time.Now().UnixNano())) b := make([]byte, 4) for i := range b { b[i] = byte(rand.Intn(256)) From 3b3aa18148d72aa8eaa1c31e33ef0abd7629b60c Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 18:32:13 +0200 Subject: [PATCH 10/22] Store setup keys and ns groups in a batch --- management/server/sqlite_store.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 0da980885..68c809da4 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -212,6 +212,14 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.NameServerGroupsG = append(accCopy.NameServerGroupsG, *ns) } + accCopy.SetupKeysG = make([]SetupKey, 0, len(accCopy.SetupKeys)) + for id, key := range accCopy.SetupKeys { + key.Id = id + //we need an explicit reference to the account as it is missing for some reason + key.AccountID = accCopy.Id + accCopy.SetupKeysG = append(accCopy.SetupKeysG, *key) + } + err := s.db.Transaction(func(tx *gorm.DB) error { result := tx.Select(clause.Associations).Delete(accCopy.Policies, "account_id = ?", accCopy.Id) if result.Error != nil { @@ -231,7 +239,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { result = tx. Session(&gorm.Session{FullSaveAssociations: true}). Clauses(clause.OnConflict{UpdateAll: true}). - Omit("PeersG", "GroupsG", "UsersG", "SetupKeysG", "RoutesG"). + Omit("PeersG", "GroupsG", "UsersG", "SetupKeysG", "RoutesG", "NameServerGroupsG"). Create(accCopy) if result.Error != nil { return result.Error @@ -254,7 +262,11 @@ func (s *SqliteStore) SaveAccount(account *Account) error { if err != nil { return err } - return batchInsert(accCopy.SetupKeysG, batchSize, tx) + err = batchInsert(accCopy.SetupKeysG, batchSize, tx) + if err != nil { + return err + } + return batchInsert(accCopy.NameServerGroupsG, batchSize, tx) }) took := time.Since(start) From 6960b68322dae45bfa35a8f11c007aab76709234 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 19:07:17 +0200 Subject: [PATCH 11/22] Add pats to test save account --- management/server/sqlite_store_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/management/server/sqlite_store_test.go b/management/server/sqlite_store_test.go index eb21be977..f54aeee8d 100644 --- a/management/server/sqlite_store_test.go +++ b/management/server/sqlite_store_test.go @@ -173,6 +173,12 @@ func TestSqlite_SaveAccount(t *testing.T) { Name: "peer name", Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()}, } + admin := account.Users["testuser"] + admin.PATs = map[string]*PersonalAccessToken{"testtoken": { + ID: "testtoken", + Name: "test token", + HashedToken: "hashed token", + }} err := store.SaveAccount(account) require.NoError(t, err) From 30bed5771196ba818a2cdfd53ebff009d09bbee6 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 19:12:53 +0200 Subject: [PATCH 12/22] Fix account deletion --- management/server/sqlite_store.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 68c809da4..cf1eb3f85 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -281,6 +281,19 @@ func (s *SqliteStore) SaveAccount(account *Account) error { func (s *SqliteStore) DeleteAccount(account *Account) error { start := time.Now() + account.UsersG = make([]User, 0, len(account.Users)) + for id, user := range account.Users { + user.Id = id + //we need an explicit reference to an account as it is missing for some reason + user.AccountID = account.Id + user.PATsG = make([]PersonalAccessToken, 0, len(user.PATs)) + for id, pat := range user.PATs { + pat.ID = id + user.PATsG = append(user.PATsG, *pat) + } + account.UsersG = append(account.UsersG, *user) + } + err := s.db.Transaction(func(tx *gorm.DB) error { result := tx.Select(clause.Associations).Delete(account.Policies, "account_id = ?", account.Id) if result.Error != nil { From 41d4dd2aff3071976e6a32d183ffc46d445cd570 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 19:34:59 +0200 Subject: [PATCH 13/22] reduce log level of scheduler to trace --- management/server/scheduler.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/management/server/scheduler.go b/management/server/scheduler.go index 356348056..224441d9e 100644 --- a/management/server/scheduler.go +++ b/management/server/scheduler.go @@ -95,18 +95,18 @@ func (wm *DefaultScheduler) Schedule(in time.Duration, ID string, job func() (ne case <-ticker.C: select { case <-cancel: - log.Debugf("scheduled job %s was canceled, stop timer", ID) + log.Tracef("scheduled job %s was canceled, stop timer", ID) ticker.Stop() return default: - log.Debugf("time to do a scheduled job %s", ID) + log.Tracef("time to do a scheduled job %s", ID) } runIn, reschedule := job() if !reschedule { wm.mu.Lock() defer wm.mu.Unlock() delete(wm.jobs, ID) - log.Debugf("job %s is not scheduled to run again", ID) + log.Tracef("job %s is not scheduled to run again", ID) ticker.Stop() return } @@ -115,7 +115,7 @@ func (wm *DefaultScheduler) Schedule(in time.Duration, ID string, job func() (ne ticker.Reset(runIn) } case <-cancel: - log.Debugf("job %s was canceled, stopping timer", ID) + log.Tracef("job %s was canceled, stopping timer", ID) ticker.Stop() return } From e6628ec231105cd4ac9ade5c978b108d4fe9e3e2 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 19:48:09 +0200 Subject: [PATCH 14/22] Fix setup keys --- management/server/sqlite_store.go | 5 ++++- management/server/sqlite_store_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index cf1eb3f85..15761080a 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -163,7 +163,10 @@ func (s *SqliteStore) SaveAccount(account *Account) error { // operate over a fresh copy as we will modify its fields accCopy := account.Copy() accCopy.SetupKeysG = make([]SetupKey, 0, len(accCopy.SetupKeys)) - for _, key := range accCopy.SetupKeys { + for id, key := range accCopy.SetupKeys { + key.Id = id + //we need an explicit reference to the account as it is missing for some reason + key.AccountID = accCopy.Id accCopy.SetupKeysG = append(accCopy.SetupKeysG, *key) } diff --git a/management/server/sqlite_store_test.go b/management/server/sqlite_store_test.go index f54aeee8d..668e40665 100644 --- a/management/server/sqlite_store_test.go +++ b/management/server/sqlite_store_test.go @@ -107,6 +107,9 @@ func TestSqlite_SaveAccount_Large(t *testing.T) { SearchDomainsEnabled: false, } account.NameServerGroups[nameserver.ID] = nameserver + + setupKey := GenerateDefaultSetupKey() + account.SetupKeys[setupKey.Id] = setupKey } err = store.SaveAccount(account) @@ -153,6 +156,18 @@ func TestSqlite_SaveAccount_Large(t *testing.T) { numPerAccount, len(a.NameServerGroups)) return } + + if a != nil && len(a.NameServerGroups) != numPerAccount { + t.Errorf("expecting Account to have %d NameServerGroups stored after SaveAccount(), got %d", + numPerAccount, len(a.NameServerGroups)) + return + } + + if a != nil && len(a.SetupKeys) != numPerAccount+1 { + t.Errorf("expecting Account to have %d SetupKeys stored after SaveAccount(), got %d", + numPerAccount+1, len(a.SetupKeys)) + return + } } func TestSqlite_SaveAccount(t *testing.T) { From 543731df4595ef68f4f5839bdf80ead79180a423 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 19:58:24 +0200 Subject: [PATCH 15/22] Fix setup keys test --- management/server/sqlite_store.go | 3 +-- management/server/sqlite_store_test.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 15761080a..109f4cbdc 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -163,8 +163,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { // operate over a fresh copy as we will modify its fields accCopy := account.Copy() accCopy.SetupKeysG = make([]SetupKey, 0, len(accCopy.SetupKeys)) - for id, key := range accCopy.SetupKeys { - key.Id = id + for _, key := range accCopy.SetupKeys { //we need an explicit reference to the account as it is missing for some reason key.AccountID = accCopy.Id accCopy.SetupKeysG = append(accCopy.SetupKeysG, *key) diff --git a/management/server/sqlite_store_test.go b/management/server/sqlite_store_test.go index 668e40665..88ab54913 100644 --- a/management/server/sqlite_store_test.go +++ b/management/server/sqlite_store_test.go @@ -109,7 +109,7 @@ func TestSqlite_SaveAccount_Large(t *testing.T) { account.NameServerGroups[nameserver.ID] = nameserver setupKey := GenerateDefaultSetupKey() - account.SetupKeys[setupKey.Id] = setupKey + account.SetupKeys[setupKey.Key] = setupKey } err = store.SaveAccount(account) From 9d1cb005706fef57693c13b88cd16b3d1f9a4712 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 17 Apr 2024 20:27:55 +0200 Subject: [PATCH 16/22] Fix setup keys test --- management/server/sqlite_store.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 109f4cbdc..6698b826b 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -214,14 +214,6 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.NameServerGroupsG = append(accCopy.NameServerGroupsG, *ns) } - accCopy.SetupKeysG = make([]SetupKey, 0, len(accCopy.SetupKeys)) - for id, key := range accCopy.SetupKeys { - key.Id = id - //we need an explicit reference to the account as it is missing for some reason - key.AccountID = accCopy.Id - accCopy.SetupKeysG = append(accCopy.SetupKeysG, *key) - } - err := s.db.Transaction(func(tx *gorm.DB) error { result := tx.Select(clause.Associations).Delete(accCopy.Policies, "account_id = ?", accCopy.Id) if result.Error != nil { From 05993af7bf88e8537dca3e1026ced9153e8f9364 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 17 Apr 2024 20:53:11 +0200 Subject: [PATCH 17/22] Update management/server/sqlite_store.go --- management/server/sqlite_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index 6698b826b..cd707d881 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -164,7 +164,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy := account.Copy() accCopy.SetupKeysG = make([]SetupKey, 0, len(accCopy.SetupKeys)) for _, key := range accCopy.SetupKeys { - //we need an explicit reference to the account as it is missing for some reason + //we need an explicit reference to the account for gorm key.AccountID = accCopy.Id accCopy.SetupKeysG = append(accCopy.SetupKeysG, *key) } From 4e1b95a4c66f460ebeced5145c406123f5748ec2 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 17 Apr 2024 20:53:24 +0200 Subject: [PATCH 18/22] Update management/server/sqlite_store.go --- management/server/sqlite_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index cd707d881..f7de2d55c 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -172,7 +172,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.PeersG = make([]nbpeer.Peer, 0, len(accCopy.Peers)) for id, peer := range accCopy.Peers { peer.ID = id - //we need an explicit reference to the account as it is missing for some reason + //we need an explicit reference to the account for gorm peer.AccountID = accCopy.Id accCopy.PeersG = append(accCopy.PeersG, *peer) } From bd761e2177876c084859d73a8e5aafd2cf042300 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 17 Apr 2024 20:53:32 +0200 Subject: [PATCH 19/22] Update management/server/sqlite_store.go --- management/server/sqlite_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index f7de2d55c..f0d63b7cf 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -180,7 +180,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.UsersG = make([]User, 0, len(accCopy.Users)) for id, user := range accCopy.Users { user.Id = id - //we need an explicit reference to an account as it is missing for some reason + //we need an explicit reference to the account for gorm user.AccountID = accCopy.Id user.PATsG = make([]PersonalAccessToken, 0, len(user.PATs)) for id, pat := range user.PATs { From db341627337271c5b68876b49fd3677a3233d2cf Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 17 Apr 2024 20:54:14 +0200 Subject: [PATCH 20/22] Update management/server/sqlite_store.go --- management/server/sqlite_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index f0d63b7cf..d2708f531 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -193,7 +193,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.GroupsG = make([]nbgroup.Group, 0, len(accCopy.Groups)) for id, group := range accCopy.Groups { group.ID = id - //we need an explicit reference to the account as it is missing for some reason + //we need an explicit reference to the account for gorm group.AccountID = accCopy.Id accCopy.GroupsG = append(accCopy.GroupsG, *group) } From 89383b7f018f5bf00ce7b1f7379267a8c30c3030 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 17 Apr 2024 20:55:01 +0200 Subject: [PATCH 21/22] Update management/server/sqlite_store.go --- management/server/sqlite_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index d2708f531..c4eab79ee 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -201,7 +201,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.RoutesG = make([]route.Route, 0, len(accCopy.Routes)) for id, route := range accCopy.Routes { route.ID = id - //we need an explicit reference to the account as it is missing for some reason + //we need an explicit reference to the account for gorm route.AccountID = accCopy.Id accCopy.RoutesG = append(accCopy.RoutesG, *route) } From 515ce9e3af85018b69d5b2793c42b12f171f2fcd Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 17 Apr 2024 20:55:32 +0200 Subject: [PATCH 22/22] Update management/server/sqlite_store.go --- management/server/sqlite_store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/server/sqlite_store.go b/management/server/sqlite_store.go index c4eab79ee..5b4fc92d7 100644 --- a/management/server/sqlite_store.go +++ b/management/server/sqlite_store.go @@ -209,7 +209,7 @@ func (s *SqliteStore) SaveAccount(account *Account) error { accCopy.NameServerGroupsG = make([]nbdns.NameServerGroup, 0, len(accCopy.NameServerGroups)) for id, ns := range accCopy.NameServerGroups { ns.ID = id - //we need an explicit reference to the account as it is missing for some reason + //we need an explicit reference to the account for gorm ns.AccountID = accCopy.Id accCopy.NameServerGroupsG = append(accCopy.NameServerGroupsG, *ns) }