Merge branch 'release-v1.5.0' into NM-258

This commit is contained in:
Abhishek Kondur
2026-03-03 13:29:41 +04:00
committed by GitHub
29 changed files with 492 additions and 209 deletions
+86 -53
View File
@@ -18,6 +18,7 @@ import (
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
)
const (
@@ -36,77 +37,63 @@ var ResetIDPSyncHook = func() {}
// HasSuperAdmin - checks if server has an superadmin/owner
func HasSuperAdmin() (bool, error) {
collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
users, err := GetUsersDB()
if err != nil {
if database.IsEmptyRecord(err) {
return false, nil
} else {
return true, err
}
return true, err
}
for _, user := range users {
if user.PlatformRoleID == models.SuperAdminRole {
return true, nil
}
}
for _, value := range collection { // filter for isadmin true
return false, nil
}
// GetUsersDB - gets users
func GetUsersDB() ([]models.User, error) {
if servercfg.CacheEnabled() {
users := getUsersFromCache()
if len(users) != 0 {
return users, nil
}
}
var users []models.User
collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
if err != nil {
return users, err
}
cacheMap := make(map[string]models.User, len(collection))
for _, value := range collection {
var user models.User
err = json.Unmarshal([]byte(value), &user)
if err != nil {
continue
}
if user.PlatformRoleID == models.SuperAdminRole {
return true, nil
}
}
return false, err
}
// GetUsersDB - gets users
func GetUsersDB() ([]models.User, error) {
var users []models.User
collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
if err != nil {
return users, err
}
for _, value := range collection {
var user models.User
err = json.Unmarshal([]byte(value), &user)
if err != nil {
continue // get users
}
users = append(users, user)
cacheMap[user.UserName] = user
}
return users, err
if servercfg.CacheEnabled() {
loadUsersIntoCache(cacheMap)
}
return users, nil
}
// GetUsers - gets users
func GetUsers() ([]models.ReturnUser, error) {
var users []models.ReturnUser
collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
dbUsers, err := GetUsersDB()
if err != nil {
return users, err
return nil, err
}
for _, value := range collection {
var user models.ReturnUser
err = json.Unmarshal([]byte(value), &user)
if err != nil {
continue // get users
}
user.IsSuperAdmin = user.PlatformRoleID == models.SuperAdminRole
user.IsAdmin = user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole
users = append(users, user)
users := make([]models.ReturnUser, 0, len(dbUsers))
for _, u := range dbUsers {
users = append(users, ToReturnUser(u))
}
return users, err
return users, nil
}
// IsOauthUser - returns
@@ -192,6 +179,9 @@ func CreateUser(user *models.User) error {
logger.Log(0, "failed to insert user", err.Error())
return err
}
if servercfg.CacheEnabled() {
storeUserInCache(*user)
}
return nil
}
@@ -273,7 +263,9 @@ func UpsertUser(user models.User) error {
slog.Error("error inserting user", "user", user.UserName, "error", err.Error())
return err
}
if servercfg.CacheEnabled() {
storeUserInCache(user)
}
return nil
}
@@ -407,6 +399,12 @@ func UpdateUser(userchange, user *models.User) (*models.User, error) {
if err = database.Insert(user.UserName, string(data), database.USERS_TABLE_NAME); err != nil {
return &models.User{}, err
}
if servercfg.CacheEnabled() {
if queryUser != user.UserName {
deleteUserFromCache(queryUser)
}
storeUserInCache(*user)
}
logger.Log(1, "updated user", queryUser)
return user, nil
}
@@ -446,6 +444,9 @@ func DeleteUser(user string) error {
if err != nil {
return err
}
if servercfg.CacheEnabled() {
deleteUserFromCache(user)
}
go RemoveUserFromAclPolicy(user)
return (&schema.UserAccessToken{UserName: user}).DeleteAllUserTokens(db.WithContext(context.TODO()))
}
@@ -535,3 +536,35 @@ func IsStateValid(state string) (string, bool) {
func delState(state string) error {
return database.DeleteRecord(database.SSO_STATE_CACHE, state)
}
// CleanExpiredSSOStates removes expired SSO state entries from the database
// to prevent unbounded table growth that degrades FetchRecord performance.
func CleanExpiredSSOStates() error {
records, err := database.FetchRecords(database.SSO_STATE_CACHE)
if err != nil {
if database.IsEmptyRecord(err) {
return nil
}
return err
}
for key, value := range records {
var s models.SsoState
if err := json.Unmarshal([]byte(value), &s); err != nil {
_ = database.DeleteRecord(database.SSO_STATE_CACHE, key)
continue
}
if s.IsExpired() {
_ = database.DeleteRecord(database.SSO_STATE_CACHE, key)
}
}
return nil
}
// AddSSOStateCleanupHook registers a periodic cleanup of expired SSO states
func AddSSOStateCleanupHook() {
HookManagerCh <- models.HookDetails{
ID: "sso-state-cleanup",
Hook: WrapHook(CleanExpiredSSOStates),
Interval: 15 * time.Minute,
}
}
+4
View File
@@ -566,6 +566,7 @@ func getNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
IPs: filteredIps,
MatchDomain: domain.Domain,
IsSearchDomain: domain.IsSearchDomain,
IsADDomain: domain.IsADDomain,
})
}
}
@@ -584,6 +585,7 @@ func getNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
IPs: filteredIps,
MatchDomain: domain.Domain,
IsSearchDomain: domain.IsSearchDomain,
IsADDomain: domain.IsADDomain,
})
}
}
@@ -639,6 +641,7 @@ func getNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
IPs: filteredIps,
MatchDomain: domain.Domain,
IsSearchDomain: domain.IsSearchDomain,
IsADDomain: domain.IsADDomain,
})
}
}
@@ -657,6 +660,7 @@ func getNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
IPs: filteredIps,
MatchDomain: domain.Domain,
IsSearchDomain: domain.IsSearchDomain,
IsADDomain: domain.IsADDomain,
})
}
}
+1 -1
View File
@@ -745,7 +745,7 @@ func getExtpeersExtraRoutes(node models.Node) (egressRoutes []models.EgressNetwo
return
}
for _, extPeer := range extPeers {
if len(extPeer.ExtraAllowedIPs) == 0 {
if len(extPeer.ExtraAllowedIPs) == 0 || !extPeer.Enabled {
continue
}
if ok, _ := IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true); !ok {
+61 -21
View File
@@ -4,14 +4,62 @@ import (
"encoding/json"
"errors"
"sort"
"sync"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
)
var (
userCacheMutex = &sync.RWMutex{}
usersCacheMap = make(map[string]models.User)
)
func getUserFromCache(username string) (models.User, bool) {
userCacheMutex.RLock()
user, ok := usersCacheMap[username]
userCacheMutex.RUnlock()
return user, ok
}
func getUsersFromCache() []models.User {
userCacheMutex.RLock()
users := make([]models.User, 0, len(usersCacheMap))
for _, user := range usersCacheMap {
users = append(users, user)
}
userCacheMutex.RUnlock()
return users
}
func storeUserInCache(user models.User) {
userCacheMutex.Lock()
usersCacheMap[user.UserName] = user
userCacheMutex.Unlock()
}
func deleteUserFromCache(username string) {
userCacheMutex.Lock()
delete(usersCacheMap, username)
userCacheMutex.Unlock()
}
func loadUsersIntoCache(users map[string]models.User) {
userCacheMutex.Lock()
usersCacheMap = users
userCacheMutex.Unlock()
}
// GetUser - gets a user
// TODO support "masteradmin"
func GetUser(username string) (*models.User, error) {
if servercfg.CacheEnabled() {
if user, ok := getUserFromCache(username); ok {
user.IsSuperAdmin = user.PlatformRoleID == models.SuperAdminRole
user.IsAdmin = user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole
return &user, nil
}
}
var user models.User
record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
if err != nil {
@@ -23,23 +71,19 @@ func GetUser(username string) (*models.User, error) {
user.IsSuperAdmin = user.PlatformRoleID == models.SuperAdminRole
user.IsAdmin = user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole
if servercfg.CacheEnabled() {
storeUserInCache(user)
}
return &user, err
}
// GetReturnUser - gets a user
func GetReturnUser(username string) (models.ReturnUser, error) {
var user models.ReturnUser
record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
u, err := GetUser(username)
if err != nil {
return user, err
}
if err = json.Unmarshal([]byte(record), &user); err != nil {
return models.ReturnUser{}, err
}
user.IsSuperAdmin = user.PlatformRoleID == models.SuperAdminRole
user.IsAdmin = user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole
return user, err
return ToReturnUser(*u), nil
}
// ToReturnUser - gets a user as a return user
@@ -160,19 +204,15 @@ func ListPendingUsers() ([]models.User, error) {
}
func GetUserMap() (map[string]models.User, error) {
userMap := make(map[string]models.User)
records, err := database.FetchRecords(database.USERS_TABLE_NAME)
users, err := GetUsersDB()
if err != nil && !database.IsEmptyRecord(err) {
return userMap, err
return nil, err
}
for _, record := range records {
user := models.User{}
err = json.Unmarshal([]byte(record), &user)
if err == nil {
user.IsSuperAdmin = user.PlatformRoleID == models.SuperAdminRole
user.IsAdmin = user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole
userMap[user.UserName] = user
}
userMap := make(map[string]models.User, len(users))
for _, user := range users {
user.IsSuperAdmin = user.PlatformRoleID == models.SuperAdminRole
user.IsAdmin = user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole
userMap[user.UserName] = user
}
return userMap, nil
}