Jelajahi Sumber

move relevant acl and tag code to CE and Pro pkgs

abhishek9686 3 bulan lalu
induk
melakukan
5a16abf91b
13 mengubah file dengan 2501 tambahan dan 1025 penghapusan
  1. 2 2
      controllers/controller.go
  2. 339 628
      logic/acls.go
  3. 34 88
      logic/egress.go
  4. 0 204
      logic/nodes.go
  5. 0 19
      logic/user_mgmt.go
  6. 1 46
      migrate/migrate.go
  7. 19 18
      pro/controllers/tags.go
  8. 1 0
      pro/initialize.go
  9. 1813 0
      pro/logic/acls.go
  10. 47 0
      pro/logic/migrate.go
  11. 204 0
      pro/logic/nodes.go
  12. 18 17
      pro/logic/tags.go
  13. 23 3
      pro/logic/user_mgmt.go

+ 2 - 2
controllers/controller.go

@@ -3,13 +3,14 @@ package controller
 import (
 	"context"
 	"fmt"
-	"github.com/gravitl/netmaker/db"
 	"net/http"
 	"os"
 	"strings"
 	"sync"
 	"time"
 
+	"github.com/gravitl/netmaker/db"
+
 	"github.com/gorilla/handlers"
 	"github.com/gorilla/mux"
 	"github.com/gravitl/netmaker/logger"
@@ -37,7 +38,6 @@ var HttpHandlers = []interface{}{
 	loggerHandlers,
 	hostHandlers,
 	enrollmentKeyHandlers,
-	tagHandlers,
 	aclHandlers,
 	egressHandlers,
 	legacyHandlers,

File diff ditekan karena terlalu besar
+ 339 - 628
logic/acls.go


+ 34 - 88
logic/egress.go

@@ -63,93 +63,6 @@ func ValidateEgressReq(e *schema.Egress) error {
 	return nil
 }
 
-func GetInetClientsFromAclPolicies(eID string) (inetClientIDs []string) {
-	e := schema.Egress{ID: eID}
-	err := e.Get(db.WithContext(context.TODO()))
-	if err != nil || !e.Status {
-		return
-	}
-	acls, _ := ListAclsByNetwork(models.NetworkID(e.Network))
-	for _, acl := range acls {
-		for _, dstI := range acl.Dst {
-			if dstI.ID == models.EgressID {
-				if dstI.Value != eID {
-					continue
-				}
-				for _, srcI := range acl.Src {
-					if srcI.Value == "*" {
-						continue
-					}
-					if srcI.ID == models.NodeID {
-						inetClientIDs = append(inetClientIDs, srcI.Value)
-					}
-					if srcI.ID == models.NodeTagID {
-						inetClientIDs = append(inetClientIDs, GetNodeIDsWithTag(models.TagID(srcI.Value))...)
-					}
-				}
-			}
-		}
-	}
-	return
-}
-
-func isNodeUsingInternetGw(node *models.Node) {
-	host, err := GetHost(node.HostID.String())
-	if err != nil {
-		return
-	}
-	if host.IsDefault || node.IsFailOver {
-		return
-	}
-	nodeTags := maps.Clone(node.Tags)
-	nodeTags[models.TagID(node.ID.String())] = struct{}{}
-	acls, _ := ListAclsByNetwork(models.NetworkID(node.Network))
-	var isUsing bool
-	for _, acl := range acls {
-		if !acl.Enabled {
-			continue
-		}
-		srcVal := convAclTagToValueMap(acl.Src)
-		for _, dstI := range acl.Dst {
-			if dstI.ID == models.EgressID {
-				e := schema.Egress{ID: dstI.Value}
-				err := e.Get(db.WithContext(context.TODO()))
-				if err != nil || !e.Status {
-					continue
-				}
-
-				if e.IsInetGw {
-					if _, ok := srcVal[node.ID.String()]; ok {
-						for nodeID := range e.Nodes {
-							if nodeID == node.ID.String() {
-								continue
-							}
-							node.EgressDetails.InternetGwID = nodeID
-							isUsing = true
-							return
-						}
-					}
-					for tagID := range nodeTags {
-						if _, ok := srcVal[tagID.String()]; ok {
-							for nodeID := range e.Nodes {
-								if nodeID == node.ID.String() {
-									continue
-								}
-								node.EgressDetails.InternetGwID = nodeID
-								isUsing = true
-								return
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	if !isUsing {
-		node.EgressDetails.InternetGwID = ""
-	}
-}
-
 func DoesNodeHaveAccessToEgress(node *models.Node, e *schema.Egress) bool {
 	nodeTags := maps.Clone(node.Tags)
 	nodeTags[models.TagID(node.ID.String())] = struct{}{}
@@ -167,7 +80,7 @@ func DoesNodeHaveAccessToEgress(node *models.Node, e *schema.Egress) bool {
 		if !acl.Enabled {
 			continue
 		}
-		srcVal := convAclTagToValueMap(acl.Src)
+		srcVal := ConvAclTagToValueMap(acl.Src)
 		if !e.IsInetGw && acl.AllowedDirection == models.TrafficDirectionBi {
 			if _, ok := srcVal["*"]; ok {
 				return true
@@ -364,3 +277,36 @@ func RemoveNodeFromEgress(node models.Node) {
 	}
 
 }
+
+func GetEgressRanges(netID models.NetworkID) (map[string][]string, map[string]struct{}, error) {
+
+	resultMap := make(map[string]struct{})
+	nodeEgressMap := make(map[string][]string)
+	networkNodes, err := GetNetworkNodes(netID.String())
+	if err != nil {
+		return nil, nil, err
+	}
+	for _, currentNode := range networkNodes {
+		if currentNode.Network != netID.String() {
+			continue
+		}
+		if currentNode.EgressDetails.IsEgressGateway { // add the egress gateway range(s) to the result
+			if len(currentNode.EgressDetails.EgressGatewayRanges) > 0 {
+				nodeEgressMap[currentNode.ID.String()] = currentNode.EgressDetails.EgressGatewayRanges
+				for _, egressRangeI := range currentNode.EgressDetails.EgressGatewayRanges {
+					resultMap[egressRangeI] = struct{}{}
+				}
+			}
+		}
+	}
+	extclients, _ := GetNetworkExtClients(netID.String())
+	for _, extclient := range extclients {
+		if len(extclient.ExtraAllowedIPs) > 0 {
+			nodeEgressMap[extclient.ClientID] = extclient.ExtraAllowedIPs
+			for _, extraAllowedIP := range extclient.ExtraAllowedIPs {
+				resultMap[extraAllowedIP] = struct{}{}
+			}
+		}
+	}
+	return nodeEgressMap, resultMap, nil
+}

+ 0 - 204
logic/nodes.go

@@ -832,207 +832,3 @@ func GetAllFailOvers() ([]models.Node, error) {
 	}
 	return igs, nil
 }
-
-func GetTagMapWithNodes() (tagNodesMap map[models.TagID][]models.Node) {
-	tagNodesMap = make(map[models.TagID][]models.Node)
-	nodes, _ := GetAllNodes()
-	for _, nodeI := range nodes {
-		if nodeI.Tags == nil {
-			continue
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Lock()
-		}
-		for nodeTagID := range nodeI.Tags {
-			tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Unlock()
-		}
-
-	}
-	return
-}
-
-func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (tagNodesMap map[models.TagID][]models.Node) {
-	tagNodesMap = make(map[models.TagID][]models.Node)
-	nodes, _ := GetNetworkNodes(netID.String())
-	for _, nodeI := range nodes {
-		tagNodesMap[models.TagID(nodeI.ID.String())] = []models.Node{
-			nodeI,
-		}
-		if nodeI.Tags == nil {
-			continue
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Lock()
-		}
-		for nodeTagID := range nodeI.Tags {
-			if nodeTagID == models.TagID(nodeI.ID.String()) {
-				continue
-			}
-			tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Unlock()
-		}
-	}
-	tagNodesMap["*"] = nodes
-	if !withStaticNodes {
-		return
-	}
-	return AddTagMapWithStaticNodes(netID, tagNodesMap)
-}
-
-func AddTagMapWithStaticNodes(netID models.NetworkID,
-	tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
-	extclients, err := GetNetworkExtClients(netID.String())
-	if err != nil {
-		return tagNodesMap
-	}
-	for _, extclient := range extclients {
-		if extclient.RemoteAccessClientID != "" {
-			continue
-		}
-		tagNodesMap[models.TagID(extclient.ClientID)] = []models.Node{
-			{
-				IsStatic:   true,
-				StaticNode: extclient,
-			},
-		}
-		if extclient.Tags == nil {
-			continue
-		}
-
-		if extclient.Mutex != nil {
-			extclient.Mutex.Lock()
-		}
-		for tagID := range extclient.Tags {
-			if tagID == models.TagID(extclient.ClientID) {
-				continue
-			}
-			tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
-			tagNodesMap["*"] = append(tagNodesMap["*"], extclient.ConvertToStaticNode())
-		}
-		if extclient.Mutex != nil {
-			extclient.Mutex.Unlock()
-		}
-	}
-	return tagNodesMap
-}
-
-func AddTagMapWithStaticNodesWithUsers(netID models.NetworkID,
-	tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
-	extclients, err := GetNetworkExtClients(netID.String())
-	if err != nil {
-		return tagNodesMap
-	}
-	for _, extclient := range extclients {
-		tagNodesMap[models.TagID(extclient.ClientID)] = []models.Node{
-			{
-				IsStatic:   true,
-				StaticNode: extclient,
-			},
-		}
-		if extclient.Tags == nil {
-			continue
-		}
-		if extclient.Mutex != nil {
-			extclient.Mutex.Lock()
-		}
-		for tagID := range extclient.Tags {
-			tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
-		}
-		if extclient.Mutex != nil {
-			extclient.Mutex.Unlock()
-		}
-
-	}
-	return tagNodesMap
-}
-
-func GetNodeIDsWithTag(tagID models.TagID) (ids []string) {
-
-	tag, err := GetTag(tagID)
-	if err != nil {
-		return
-	}
-	nodes, _ := GetNetworkNodes(tag.Network.String())
-	for _, nodeI := range nodes {
-		if nodeI.Tags == nil {
-			continue
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Lock()
-		}
-		if _, ok := nodeI.Tags[tagID]; ok {
-			ids = append(ids, nodeI.ID.String())
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Unlock()
-		}
-	}
-	return
-}
-
-func GetNodesWithTag(tagID models.TagID) map[string]models.Node {
-	nMap := make(map[string]models.Node)
-	tag, err := GetTag(tagID)
-	if err != nil {
-		return nMap
-	}
-	nodes, _ := GetNetworkNodes(tag.Network.String())
-	for _, nodeI := range nodes {
-		if nodeI.Tags == nil {
-			continue
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Lock()
-		}
-		if _, ok := nodeI.Tags[tagID]; ok {
-			nMap[nodeI.ID.String()] = nodeI
-		}
-		if nodeI.Mutex != nil {
-			nodeI.Mutex.Unlock()
-		}
-	}
-	return AddStaticNodesWithTag(tag, nMap)
-}
-
-func AddStaticNodesWithTag(tag models.Tag, nMap map[string]models.Node) map[string]models.Node {
-	extclients, err := GetNetworkExtClients(tag.Network.String())
-	if err != nil {
-		return nMap
-	}
-	for _, extclient := range extclients {
-		if extclient.RemoteAccessClientID != "" {
-			continue
-		}
-		if extclient.Mutex != nil {
-			extclient.Mutex.Lock()
-		}
-		if _, ok := extclient.Tags[tag.ID]; ok {
-			nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
-		}
-		if extclient.Mutex != nil {
-			extclient.Mutex.Unlock()
-		}
-	}
-	return nMap
-}
-
-func GetStaticNodeWithTag(tagID models.TagID) map[string]models.Node {
-	nMap := make(map[string]models.Node)
-	tag, err := GetTag(tagID)
-	if err != nil {
-		return nMap
-	}
-	extclients, err := GetNetworkExtClients(tag.Network.String())
-	if err != nil {
-		return nMap
-	}
-	for _, extclient := range extclients {
-		nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
-	}
-	return nMap
-}

+ 0 - 19
logic/user_mgmt.go

@@ -102,25 +102,6 @@ func ListPlatformRoles() ([]models.UserRolePermissionTemplate, error) {
 	return userRoles, nil
 }
 
-func GetUserGrpMap() map[models.UserGroupID]map[string]struct{} {
-	grpUsersMap := make(map[models.UserGroupID]map[string]struct{})
-	users, _ := GetUsersDB()
-	for _, user := range users {
-		for gID := range user.UserGroups {
-			if grpUsers, ok := grpUsersMap[gID]; ok {
-				grpUsers[user.UserName] = struct{}{}
-				grpUsersMap[gID] = grpUsers
-			} else {
-				grpUsersMap[gID] = make(map[string]struct{})
-				grpUsersMap[gID][user.UserName] = struct{}{}
-			}
-		}
-
-	}
-
-	return grpUsersMap
-}
-
 func userRolesInit() {
 	d, _ := json.Marshal(SuperAdminPermissionTemplate)
 	database.Insert(SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)

+ 1 - 46
migrate/migrate.go

@@ -34,7 +34,7 @@ func Run() {
 	updateHosts()
 	updateNodes()
 	updateAcls()
-	migrateToGws()
+	logic.MigrateToGws()
 	migrateToEgressV1()
 }
 
@@ -465,51 +465,6 @@ func createDefaultTagsAndPolicies() {
 	logic.MigrateAclPolicies()
 }
 
-func migrateToGws() {
-	nodes, err := logic.GetAllNodes()
-	if err != nil {
-		return
-	}
-	for _, node := range nodes {
-		if node.IsIngressGateway || node.IsRelay {
-			node.IsGw = true
-			node.IsIngressGateway = true
-			node.IsRelay = true
-			if node.Tags == nil {
-				node.Tags = make(map[models.TagID]struct{})
-			}
-			node.Tags[models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName))] = struct{}{}
-			delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.OldRemoteAccessTagName)))
-			logic.UpsertNode(&node)
-		}
-	}
-	acls := logic.ListAcls()
-	for _, acl := range acls {
-		upsert := false
-		for i, srcI := range acl.Src {
-			if srcI.ID == models.NodeTagID && srcI.Value == fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.OldRemoteAccessTagName) {
-				srcI.Value = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
-				acl.Src[i] = srcI
-				upsert = true
-			}
-		}
-		for i, dstI := range acl.Dst {
-			if dstI.ID == models.NodeTagID && dstI.Value == fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.OldRemoteAccessTagName) {
-				dstI.Value = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
-				acl.Dst[i] = dstI
-				upsert = true
-			}
-		}
-		if upsert {
-			logic.UpsertAcl(acl)
-		}
-	}
-	nets, _ := logic.GetNetworks()
-	for _, netI := range nets {
-		logic.DeleteTag(models.TagID(fmt.Sprintf("%s.%s", netI.NetID, models.OldRemoteAccessTagName)), true)
-	}
-}
-
 func migrateToEgressV1() {
 	nodes, _ := logic.GetAllNodes()
 	user, err := logic.GetSuperAdmin()

+ 19 - 18
controllers/tags.go → pro/controllers/tags.go

@@ -1,4 +1,4 @@
-package controller
+package controllers
 
 import (
 	"encoding/json"
@@ -14,9 +14,10 @@ import (
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
+	proLogic "github.com/gravitl/netmaker/pro/logic"
 )
 
-func tagHandlers(r *mux.Router) {
+func TagHandlers(r *mux.Router) {
 	r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(getTags))).
 		Methods(http.MethodGet)
 	r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(createTag))).
@@ -46,13 +47,13 @@ func getTags(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
-	tags, err := logic.ListTagsWithNodes(models.NetworkID(netID))
+	tags, err := proLogic.ListTagsWithNodes(models.NetworkID(netID))
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"), "failed to get all network tag entries: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
-	logic.SortTagEntrys(tags[:])
+	proLogic.SortTagEntrys(tags[:])
 	logic.ReturnSuccessResponseWithJson(w, r, tags, "fetched all tags in the network "+netID)
 }
 
@@ -91,18 +92,18 @@ func createTag(w http.ResponseWriter, r *http.Request) {
 		ColorCode: req.ColorCode,
 		CreatedAt: time.Now().UTC(),
 	}
-	_, err = logic.GetTag(tag.ID)
+	_, err = proLogic.GetTag(tag.ID)
 	if err == nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("tag with id %s exists already", tag.TagName), "badrequest"))
 		return
 	}
 	// validate name
-	err = logic.CheckIDSyntax(tag.TagName)
+	err = proLogic.CheckIDSyntax(tag.TagName)
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
-	err = logic.InsertTag(tag)
+	err = proLogic.InsertTag(tag)
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
@@ -174,7 +175,7 @@ func updateTag(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	tag, err := logic.GetTag(updateTag.ID)
+	tag, err := proLogic.GetTag(updateTag.ID)
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
@@ -202,7 +203,7 @@ func updateTag(w http.ResponseWriter, r *http.Request) {
 	var newID models.TagID
 	if updateTag.NewName != "" {
 		// validate name
-		err = logic.CheckIDSyntax(updateTag.NewName)
+		err = proLogic.CheckIDSyntax(updateTag.NewName)
 		if err != nil {
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 			return
@@ -210,26 +211,26 @@ func updateTag(w http.ResponseWriter, r *http.Request) {
 		newID = models.TagID(fmt.Sprintf("%s.%s", tag.Network, updateTag.NewName))
 		tag.ID = newID
 		tag.TagName = updateTag.NewName
-		err = logic.InsertTag(tag)
+		err = proLogic.InsertTag(tag)
 		if err != nil {
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 			return
 		}
 		// delete old Tag entry
-		logic.DeleteTag(updateTag.ID, false)
+		proLogic.DeleteTag(updateTag.ID, false)
 	}
 	if updateTag.ColorCode != "" && updateTag.ColorCode != tag.ColorCode {
 		tag.ColorCode = updateTag.ColorCode
-		err = logic.UpsertTag(tag)
+		err = proLogic.UpsertTag(tag)
 		if err != nil {
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 			return
 		}
 	}
 	go func() {
-		logic.UpdateTag(updateTag, newID)
+		proLogic.UpdateTag(updateTag, newID)
 		if updateTag.NewName != "" {
-			logic.UpdateDeviceTag(updateTag.ID, newID, tag.Network)
+			proLogic.UpdateDeviceTag(updateTag.ID, newID, tag.Network)
 		}
 		mq.PublishPeerUpdate(false)
 	}()
@@ -256,24 +257,24 @@ func deleteTag(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("role is required"), "badrequest"))
 		return
 	}
-	tag, err := logic.GetTag(models.TagID(tagID))
+	tag, err := proLogic.GetTag(models.TagID(tagID))
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
 	// check if active policy is using the tag
-	if logic.CheckIfTagAsActivePolicy(tag.ID, tag.Network) {
+	if proLogic.CheckIfTagAsActivePolicy(tag.ID, tag.Network) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("tag is currently in use by an active policy"), "badrequest"))
 		return
 	}
-	err = logic.DeleteTag(models.TagID(tagID), true)
+	err = proLogic.DeleteTag(models.TagID(tagID), true)
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
 
 	go func() {
-		logic.RemoveDeviceTagFromAclPolicies(tag.ID, tag.Network)
+		proLogic.RemoveDeviceTagFromAclPolicies(tag.ID, tag.Network)
 		logic.RemoveTagFromEnrollmentKeys(tag.ID)
 		mq.PublishPeerUpdate(false)
 	}()

+ 1 - 0
pro/initialize.go

@@ -35,6 +35,7 @@ func InitPro() {
 		proControllers.InetHandlers,
 		proControllers.RacHandlers,
 		proControllers.EventHandlers,
+		proControllers.TagHandlers,
 	)
 	controller.ListRoles = proControllers.ListRoles
 	logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {

+ 1813 - 0
pro/logic/acls.go

@@ -0,0 +1,1813 @@
+package logic
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"maps"
+	"net"
+	"sort"
+	"time"
+
+	"github.com/google/uuid"
+	"github.com/gravitl/netmaker/db"
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/schema"
+)
+
+/*
+TODO: EGRESS
+1. allow only selection of egress ranges in a policy
+ranges should be replaced by egress identifier
+
+2. check logic required for MAC exit node
+
+3.
+
+*/
+
+func checkIfAclTagisValid(a models.Acl, t models.AclPolicyTag, isSrc bool) (err error) {
+	switch t.ID {
+	case models.NodeTagID:
+		if a.RuleType == models.UserPolicy && isSrc {
+			return errors.New("user policy source mismatch")
+		}
+		// check if tag is valid
+		_, err := GetTag(models.TagID(t.Value))
+		if err != nil {
+			return errors.New("invalid tag " + t.Value)
+		}
+	case models.NodeID:
+		if a.RuleType == models.UserPolicy && isSrc {
+			return errors.New("user policy source mismatch")
+		}
+		_, nodeErr := logic.GetNodeByID(t.Value)
+		if nodeErr != nil {
+			_, staticNodeErr := logic.GetExtClient(t.Value, a.NetworkID.String())
+			if staticNodeErr != nil {
+				return errors.New("invalid node " + t.Value)
+			}
+		}
+	case models.EgressID, models.EgressRange:
+		e := schema.Egress{
+			ID: t.Value,
+		}
+		err := e.Get(db.WithContext(context.TODO()))
+		if err != nil {
+			return errors.New("invalid egress")
+		}
+		if e.IsInetGw {
+			req := models.InetNodeReq{}
+			for _, srcI := range a.Src {
+				if srcI.ID == models.NodeTagID {
+					nodesMap := GetNodesWithTag(models.TagID(srcI.Value))
+					for _, node := range nodesMap {
+						req.InetNodeClientIDs = append(req.InetNodeClientIDs, node.ID.String())
+					}
+				} else if srcI.ID == models.NodeID {
+					req.InetNodeClientIDs = append(req.InetNodeClientIDs, srcI.Value)
+				}
+			}
+			if len(e.Nodes) > 0 {
+				for k := range e.Nodes {
+					inetNode, err := logic.GetNodeByID(k)
+					if err != nil {
+						return errors.New("invalid node " + t.Value)
+					}
+					if err = ValidateInetGwReq(inetNode, req, false); err != nil {
+						return err
+					}
+				}
+
+			}
+
+		}
+
+	case models.UserAclID:
+		if a.RuleType == models.DevicePolicy {
+			return errors.New("device policy source mismatch")
+		}
+		if !isSrc {
+			return errors.New("user cannot be added to destination")
+		}
+		_, err := logic.GetUser(t.Value)
+		if err != nil {
+			return errors.New("invalid user " + t.Value)
+		}
+	case models.UserGroupAclID:
+		if a.RuleType == models.DevicePolicy {
+			return errors.New("device policy source mismatch")
+		}
+		if !isSrc {
+			return errors.New("user cannot be added to destination")
+		}
+		err := IsGroupValid(models.UserGroupID(t.Value))
+		if err != nil {
+			return errors.New("invalid user group " + t.Value)
+		}
+		// check if group belongs to this network
+		netGrps := GetUserGroupsInNetwork(a.NetworkID)
+		if _, ok := netGrps[models.UserGroupID(t.Value)]; !ok {
+			return errors.New("invalid user group " + t.Value)
+		}
+	default:
+		return errors.New("invalid policy")
+	}
+	return nil
+}
+
+// IsAclPolicyValid - validates if acl policy is valid
+func IsAclPolicyValid(acl models.Acl) (err error) {
+	//check if src and dst are valid
+	if acl.AllowedDirection != models.TrafficDirectionBi &&
+		acl.AllowedDirection != models.TrafficDirectionUni {
+		return errors.New("invalid traffic direction")
+	}
+	switch acl.RuleType {
+	case models.UserPolicy:
+		// src list should only contain users
+		for _, srcI := range acl.Src {
+
+			if srcI.Value == "*" {
+				continue
+			}
+			// check if user group is valid
+			if err = checkIfAclTagisValid(acl, srcI, true); err != nil {
+				return
+			}
+		}
+		for _, dstI := range acl.Dst {
+
+			if dstI.Value == "*" {
+				continue
+			}
+
+			// check if user group is valid
+			if err = checkIfAclTagisValid(acl, dstI, false); err != nil {
+				return
+			}
+		}
+	case models.DevicePolicy:
+		for _, srcI := range acl.Src {
+			if srcI.Value == "*" {
+				continue
+			}
+			// check if user group is valid
+			if err = checkIfAclTagisValid(acl, srcI, true); err != nil {
+				return err
+			}
+		}
+		for _, dstI := range acl.Dst {
+
+			if dstI.Value == "*" {
+				continue
+			}
+			// check if user group is valid
+			if err = checkIfAclTagisValid(acl, dstI, false); err != nil {
+				return
+			}
+		}
+	}
+	return nil
+}
+
+// CreateDefaultAclNetworkPolicies - create default acl network policies
+func CreateDefaultAclNetworkPolicies(netID models.NetworkID) {
+	if netID.String() == "" {
+		return
+	}
+	_, _ = logic.ListAclsByNetwork(netID)
+	if !logic.IsAclExists(fmt.Sprintf("%s.%s", netID, "all-nodes")) {
+		defaultDeviceAcl := models.Acl{
+			ID:          fmt.Sprintf("%s.%s", netID, "all-nodes"),
+			Name:        "All Nodes",
+			MetaData:    "This Policy allows all nodes in the network to communicate with each other",
+			Default:     true,
+			NetworkID:   netID,
+			Proto:       models.ALL,
+			ServiceType: models.Any,
+			Port:        []string{},
+			RuleType:    models.DevicePolicy,
+			Src: []models.AclPolicyTag{
+				{
+					ID:    models.NodeTagID,
+					Value: "*",
+				}},
+			Dst: []models.AclPolicyTag{
+				{
+					ID:    models.NodeTagID,
+					Value: "*",
+				}},
+			AllowedDirection: models.TrafficDirectionBi,
+			Enabled:          true,
+			CreatedBy:        "auto",
+			CreatedAt:        time.Now().UTC(),
+		}
+		logic.InsertAcl(defaultDeviceAcl)
+	}
+	if !logic.IsAclExists(fmt.Sprintf("%s.%s", netID, "all-users")) {
+		defaultUserAcl := models.Acl{
+			ID:          fmt.Sprintf("%s.%s", netID, "all-users"),
+			Default:     true,
+			Name:        "All Users",
+			MetaData:    "This policy gives access to everything in the network for an user",
+			NetworkID:   netID,
+			Proto:       models.ALL,
+			ServiceType: models.Any,
+			Port:        []string{},
+			RuleType:    models.UserPolicy,
+			Src: []models.AclPolicyTag{
+				{
+					ID:    models.UserAclID,
+					Value: "*",
+				},
+			},
+			Dst: []models.AclPolicyTag{{
+				ID:    models.NodeTagID,
+				Value: "*",
+			}},
+			AllowedDirection: models.TrafficDirectionUni,
+			Enabled:          true,
+			CreatedBy:        "auto",
+			CreatedAt:        time.Now().UTC(),
+		}
+		logic.InsertAcl(defaultUserAcl)
+	}
+
+	if !logic.IsAclExists(fmt.Sprintf("%s.%s", netID, "all-gateways")) {
+		defaultUserAcl := models.Acl{
+			ID:          fmt.Sprintf("%s.%s", netID, "all-gateways"),
+			Default:     true,
+			Name:        "All Gateways",
+			NetworkID:   netID,
+			Proto:       models.ALL,
+			ServiceType: models.Any,
+			Port:        []string{},
+			RuleType:    models.DevicePolicy,
+			Src: []models.AclPolicyTag{
+				{
+					ID:    models.NodeTagID,
+					Value: fmt.Sprintf("%s.%s", netID, models.GwTagName),
+				},
+			},
+			Dst: []models.AclPolicyTag{
+				{
+					ID:    models.NodeTagID,
+					Value: "*",
+				},
+			},
+			AllowedDirection: models.TrafficDirectionBi,
+			Enabled:          true,
+			CreatedBy:        "auto",
+			CreatedAt:        time.Now().UTC(),
+		}
+		logic.InsertAcl(defaultUserAcl)
+	}
+	CreateDefaultUserPolicies(netID)
+}
+
+// ListUserPolicies - lists all acl policies enforced on an user
+func ListUserPolicies(u models.User) []models.Acl {
+	allAcls := logic.ListAcls()
+	userAcls := []models.Acl{}
+	for _, acl := range allAcls {
+
+		if acl.RuleType == models.UserPolicy {
+			srcMap := logic.ConvAclTagToValueMap(acl.Src)
+			if _, ok := srcMap[u.UserName]; ok {
+				userAcls = append(userAcls, acl)
+			} else {
+				// check for user groups
+				for gID := range u.UserGroups {
+					if _, ok := srcMap[gID.String()]; ok {
+						userAcls = append(userAcls, acl)
+						break
+					}
+				}
+			}
+
+		}
+	}
+	return userAcls
+}
+
+// listPoliciesOfUser - lists all user acl policies applied to user in an network
+func listPoliciesOfUser(user models.User, netID models.NetworkID) []models.Acl {
+	allAcls := logic.ListAcls()
+	userAcls := []models.Acl{}
+	for _, acl := range allAcls {
+		if acl.NetworkID == netID && acl.RuleType == models.UserPolicy {
+			srcMap := logic.ConvAclTagToValueMap(acl.Src)
+			if _, ok := srcMap[user.UserName]; ok {
+				userAcls = append(userAcls, acl)
+				continue
+			}
+			for netRole := range user.NetworkRoles {
+				if _, ok := srcMap[netRole.String()]; ok {
+					userAcls = append(userAcls, acl)
+					continue
+				}
+			}
+			for userG := range user.UserGroups {
+				if _, ok := srcMap[userG.String()]; ok {
+					userAcls = append(userAcls, acl)
+					continue
+				}
+			}
+
+		}
+	}
+	return userAcls
+}
+
+// listUserPolicies - lists all user policies in a network
+func listUserPolicies(netID models.NetworkID) []models.Acl {
+	allAcls := logic.ListAcls()
+	deviceAcls := []models.Acl{}
+	for _, acl := range allAcls {
+		if acl.NetworkID == netID && acl.RuleType == models.UserPolicy {
+			deviceAcls = append(deviceAcls, acl)
+		}
+	}
+	return deviceAcls
+}
+
+// IsUserAllowedToCommunicate - check if user is allowed to communicate with peer
+func IsUserAllowedToCommunicate(userName string, peer models.Node) (bool, []models.Acl) {
+	var peerId string
+	if peer.IsStatic {
+		peerId = peer.StaticNode.ClientID
+		peer = peer.StaticNode.ConvertToStaticNode()
+	} else {
+		peerId = peer.ID.String()
+	}
+
+	var peerTags map[models.TagID]struct{}
+	if peer.Mutex != nil {
+		peer.Mutex.Lock()
+		peerTags = maps.Clone(peer.Tags)
+		peer.Mutex.Unlock()
+	} else {
+		peerTags = peer.Tags
+	}
+	peerTags[models.TagID(peerId)] = struct{}{}
+	acl, _ := logic.GetDefaultPolicy(models.NetworkID(peer.Network), models.UserPolicy)
+	if acl.Enabled {
+		return true, []models.Acl{acl}
+	}
+	user, err := logic.GetUser(userName)
+	if err != nil {
+		return false, []models.Acl{}
+	}
+	allowedPolicies := []models.Acl{}
+	policies := listPoliciesOfUser(*user, models.NetworkID(peer.Network))
+	for _, policy := range policies {
+		if !policy.Enabled {
+			continue
+		}
+		dstMap := logic.ConvAclTagToValueMap(policy.Dst)
+		for _, dst := range policy.Dst {
+			if dst.ID == models.EgressID {
+				e := schema.Egress{ID: dst.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err == nil && e.Status {
+					for nodeID := range e.Nodes {
+						dstMap[nodeID] = struct{}{}
+					}
+				}
+			}
+		}
+		if _, ok := dstMap["*"]; ok {
+			allowedPolicies = append(allowedPolicies, policy)
+			continue
+		}
+		if _, ok := dstMap[peer.ID.String()]; ok {
+			allowedPolicies = append(allowedPolicies, policy)
+			continue
+		}
+		for tagID := range peerTags {
+			if _, ok := dstMap[tagID.String()]; ok {
+				allowedPolicies = append(allowedPolicies, policy)
+				break
+			}
+		}
+
+	}
+	if len(allowedPolicies) > 0 {
+		return true, allowedPolicies
+	}
+	return false, []models.Acl{}
+}
+
+// IsPeerAllowed - checks if peer needs to be added to the interface
+func IsPeerAllowed(node, peer models.Node, checkDefaultPolicy bool) bool {
+	var nodeId, peerId string
+	if peer.IsFailOver && node.FailedOverBy != uuid.Nil && node.FailedOverBy == peer.ID {
+		return true
+	}
+	if node.IsFailOver && peer.FailedOverBy != uuid.Nil && peer.FailedOverBy == node.ID {
+		return true
+	}
+	if node.IsStatic {
+		nodeId = node.StaticNode.ClientID
+		node = node.StaticNode.ConvertToStaticNode()
+	} else {
+		nodeId = node.ID.String()
+	}
+	if peer.IsStatic {
+		peerId = peer.StaticNode.ClientID
+		peer = peer.StaticNode.ConvertToStaticNode()
+	} else {
+		peerId = peer.ID.String()
+	}
+
+	var nodeTags, peerTags map[models.TagID]struct{}
+	if node.Mutex != nil {
+		node.Mutex.Lock()
+		nodeTags = maps.Clone(node.Tags)
+		node.Mutex.Unlock()
+	} else {
+		nodeTags = node.Tags
+	}
+	if peer.Mutex != nil {
+		peer.Mutex.Lock()
+		peerTags = maps.Clone(peer.Tags)
+		peer.Mutex.Unlock()
+	} else {
+		peerTags = peer.Tags
+	}
+	if nodeTags == nil {
+		nodeTags = make(map[models.TagID]struct{})
+	}
+	if peerTags == nil {
+		peerTags = make(map[models.TagID]struct{})
+	}
+	nodeTags[models.TagID(nodeId)] = struct{}{}
+	peerTags[models.TagID(peerId)] = struct{}{}
+	if checkDefaultPolicy {
+		// check default policy if all allowed return true
+		defaultPolicy, err := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
+		if err == nil {
+			if defaultPolicy.Enabled {
+				return true
+			}
+		}
+
+	}
+	// list device policies
+	policies := logic.ListDevicePolicies(models.NetworkID(peer.Network))
+	srcMap := make(map[string]struct{})
+	dstMap := make(map[string]struct{})
+	defer func() {
+		srcMap = nil
+		dstMap = nil
+	}()
+	for _, policy := range policies {
+		if !policy.Enabled {
+			continue
+		}
+
+		srcMap = logic.ConvAclTagToValueMap(policy.Src)
+		dstMap = logic.ConvAclTagToValueMap(policy.Dst)
+		for _, dst := range policy.Dst {
+			if dst.ID == models.EgressID {
+				e := schema.Egress{ID: dst.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err == nil && e.Status {
+					for nodeID := range e.Nodes {
+						dstMap[nodeID] = struct{}{}
+					}
+				}
+			}
+		}
+		if checkTagGroupPolicy(srcMap, dstMap, node, peer, nodeTags, peerTags) {
+			return true
+		}
+
+	}
+	return false
+}
+
+func RemoveUserFromAclPolicy(userName string) {
+	acls := logic.ListAcls()
+	for _, acl := range acls {
+		delete := false
+		update := false
+		if acl.RuleType == models.UserPolicy {
+			for i := len(acl.Src) - 1; i >= 0; i-- {
+				if acl.Src[i].ID == models.UserAclID && acl.Src[i].Value == userName {
+					if len(acl.Src) == 1 {
+						// delete policy
+						delete = true
+						break
+					} else {
+						acl.Src = append(acl.Src[:i], acl.Src[i+1:]...)
+						update = true
+					}
+				}
+			}
+			if delete {
+				logic.DeleteAcl(acl)
+				continue
+			}
+			if update {
+				logic.UpsertAcl(acl)
+			}
+		}
+	}
+}
+
+func checkTagGroupPolicy(srcMap, dstMap map[string]struct{}, node, peer models.Node,
+	nodeTags, peerTags map[models.TagID]struct{}) bool {
+	// check for node ID
+	if _, ok := srcMap[node.ID.String()]; ok {
+		if _, ok = dstMap[peer.ID.String()]; ok {
+			return true
+		}
+
+	}
+	if _, ok := dstMap[node.ID.String()]; ok {
+		if _, ok = srcMap[peer.ID.String()]; ok {
+			return true
+		}
+	}
+
+	for tagID := range nodeTags {
+		if _, ok := dstMap[tagID.String()]; ok {
+			if _, ok := srcMap["*"]; ok {
+				return true
+			}
+			for tagID := range peerTags {
+				if _, ok := srcMap[tagID.String()]; ok {
+					return true
+				}
+			}
+		}
+		if _, ok := srcMap[tagID.String()]; ok {
+			if _, ok := dstMap["*"]; ok {
+				return true
+			}
+			for tagID := range peerTags {
+				if _, ok := dstMap[tagID.String()]; ok {
+					return true
+				}
+			}
+		}
+	}
+	for tagID := range peerTags {
+		if _, ok := dstMap[tagID.String()]; ok {
+			if _, ok := srcMap["*"]; ok {
+				return true
+			}
+			for tagID := range nodeTags {
+
+				if _, ok := srcMap[tagID.String()]; ok {
+					return true
+				}
+			}
+		}
+		if _, ok := srcMap[tagID.String()]; ok {
+			if _, ok := dstMap["*"]; ok {
+				return true
+			}
+			for tagID := range nodeTags {
+				if _, ok := dstMap[tagID.String()]; ok {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+// IsNodeAllowedToCommunicate - check node is allowed to communicate with the peer // ADD ALLOWED DIRECTION - 0 => node -> peer, 1 => peer-> node,
+func IsNodeAllowedToCommunicateV1(node, peer models.Node, checkDefaultPolicy bool) (bool, []models.Acl) {
+	var nodeId, peerId string
+	if peer.IsFailOver && node.FailedOverBy != uuid.Nil && node.FailedOverBy == peer.ID {
+		return true, []models.Acl{}
+	}
+	if node.IsFailOver && peer.FailedOverBy != uuid.Nil && peer.FailedOverBy == node.ID {
+		return true, []models.Acl{}
+	}
+	if node.IsStatic {
+		nodeId = node.StaticNode.ClientID
+		node = node.StaticNode.ConvertToStaticNode()
+	} else {
+		nodeId = node.ID.String()
+	}
+	if peer.IsStatic {
+		peerId = peer.StaticNode.ClientID
+		peer = peer.StaticNode.ConvertToStaticNode()
+	} else {
+		peerId = peer.ID.String()
+	}
+
+	var nodeTags, peerTags map[models.TagID]struct{}
+	if node.Mutex != nil {
+		node.Mutex.Lock()
+		nodeTags = maps.Clone(node.Tags)
+		node.Mutex.Unlock()
+	} else {
+		nodeTags = node.Tags
+	}
+	if peer.Mutex != nil {
+		peer.Mutex.Lock()
+		peerTags = maps.Clone(peer.Tags)
+		peer.Mutex.Unlock()
+	} else {
+		peerTags = peer.Tags
+	}
+	if nodeTags == nil {
+		nodeTags = make(map[models.TagID]struct{})
+	}
+	if peerTags == nil {
+		peerTags = make(map[models.TagID]struct{})
+	}
+	nodeTags[models.TagID(nodeId)] = struct{}{}
+	peerTags[models.TagID(peerId)] = struct{}{}
+	if checkDefaultPolicy {
+		// check default policy if all allowed return true
+		defaultPolicy, err := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
+		if err == nil {
+			if defaultPolicy.Enabled {
+				return true, []models.Acl{defaultPolicy}
+			}
+		}
+	}
+	allowedPolicies := []models.Acl{}
+	defer func() {
+		allowedPolicies = logic.UniquePolicies(allowedPolicies)
+	}()
+	// list device policies
+	policies := logic.ListDevicePolicies(models.NetworkID(peer.Network))
+	srcMap := make(map[string]struct{})
+	dstMap := make(map[string]struct{})
+	defer func() {
+		srcMap = nil
+		dstMap = nil
+	}()
+	for _, policy := range policies {
+		if !policy.Enabled {
+			continue
+		}
+		allowed := false
+		srcMap = logic.ConvAclTagToValueMap(policy.Src)
+		dstMap = logic.ConvAclTagToValueMap(policy.Dst)
+		for _, dst := range policy.Dst {
+			if dst.ID == models.EgressID {
+				e := schema.Egress{ID: dst.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err == nil && e.Status {
+					for nodeID := range e.Nodes {
+						dstMap[nodeID] = struct{}{}
+					}
+				}
+			}
+		}
+		_, srcAll := srcMap["*"]
+		_, dstAll := dstMap["*"]
+		if policy.AllowedDirection == models.TrafficDirectionBi {
+			if _, ok := srcMap[nodeId]; ok || srcAll {
+				if _, ok := dstMap[peerId]; ok || dstAll {
+					allowedPolicies = append(allowedPolicies, policy)
+					continue
+				}
+
+			}
+			if _, ok := dstMap[nodeId]; ok || dstAll {
+				if _, ok := srcMap[peerId]; ok || srcAll {
+					allowedPolicies = append(allowedPolicies, policy)
+					continue
+				}
+			}
+		}
+		if _, ok := dstMap[peerId]; ok || dstAll {
+			if _, ok := srcMap[nodeId]; ok || srcAll {
+				allowedPolicies = append(allowedPolicies, policy)
+				continue
+			}
+		}
+		if policy.AllowedDirection == models.TrafficDirectionBi {
+
+			for tagID := range nodeTags {
+
+				if _, ok := dstMap[tagID.String()]; ok || dstAll {
+					if srcAll {
+						allowed = true
+						break
+					}
+					for tagID := range peerTags {
+						if _, ok := srcMap[tagID.String()]; ok {
+							allowed = true
+							break
+						}
+					}
+				}
+				if allowed {
+					allowedPolicies = append(allowedPolicies, policy)
+					break
+				}
+				if _, ok := srcMap[tagID.String()]; ok || srcAll {
+					if dstAll {
+						allowed = true
+						break
+					}
+					for tagID := range peerTags {
+						if _, ok := dstMap[tagID.String()]; ok {
+							allowed = true
+							break
+						}
+					}
+				}
+				if allowed {
+					break
+				}
+			}
+			if allowed {
+				allowedPolicies = append(allowedPolicies, policy)
+				continue
+			}
+		}
+		for tagID := range peerTags {
+			if _, ok := dstMap[tagID.String()]; ok || dstAll {
+				if srcAll {
+					allowed = true
+					break
+				}
+				for tagID := range nodeTags {
+					if _, ok := srcMap[tagID.String()]; ok {
+						allowed = true
+						break
+					}
+				}
+			}
+			if allowed {
+				break
+			}
+		}
+		if allowed {
+			allowedPolicies = append(allowedPolicies, policy)
+		}
+	}
+
+	if len(allowedPolicies) > 0 {
+		return true, allowedPolicies
+	}
+	return false, allowedPolicies
+}
+
+// UpdateDeviceTag - updates device tag on acl policies
+func UpdateDeviceTag(OldID, newID models.TagID, netID models.NetworkID) {
+	acls := logic.ListDevicePolicies(netID)
+	update := false
+	for _, acl := range acls {
+		for i, srcTagI := range acl.Src {
+			if srcTagI.ID == models.NodeTagID {
+				if OldID.String() == srcTagI.Value {
+					acl.Src[i].Value = newID.String()
+					update = true
+				}
+			}
+		}
+		for i, dstTagI := range acl.Dst {
+			if dstTagI.ID == models.NodeTagID {
+				if OldID.String() == dstTagI.Value {
+					acl.Dst[i].Value = newID.String()
+					update = true
+				}
+			}
+		}
+		if update {
+			logic.UpsertAcl(acl)
+		}
+	}
+}
+
+func CheckIfTagAsActivePolicy(tagID models.TagID, netID models.NetworkID) bool {
+	acls := logic.ListDevicePolicies(netID)
+	for _, acl := range acls {
+		for _, srcTagI := range acl.Src {
+			if srcTagI.ID == models.NodeTagID {
+				if tagID.String() == srcTagI.Value {
+					return true
+				}
+			}
+		}
+		for _, dstTagI := range acl.Dst {
+			if dstTagI.ID == models.NodeTagID {
+				if tagID.String() == dstTagI.Value {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+// RemoveDeviceTagFromAclPolicies - remove device tag from acl policies
+func RemoveDeviceTagFromAclPolicies(tagID models.TagID, netID models.NetworkID) error {
+	acls := logic.ListDevicePolicies(netID)
+	update := false
+	for _, acl := range acls {
+		for i := len(acl.Src) - 1; i >= 0; i-- {
+			if acl.Src[i].ID == models.NodeTagID {
+				if tagID.String() == acl.Src[i].Value {
+					acl.Src = append(acl.Src[:i], acl.Src[i+1:]...)
+					update = true
+				}
+			}
+		}
+		for i := len(acl.Dst) - 1; i >= 0; i-- {
+			if acl.Dst[i].ID == models.NodeTagID {
+				if tagID.String() == acl.Dst[i].Value {
+					acl.Dst = append(acl.Dst[:i], acl.Dst[i+1:]...)
+					update = true
+				}
+			}
+		}
+		if update {
+			logic.UpsertAcl(acl)
+		}
+	}
+	return nil
+}
+
+func getEgressUserRulesForNode(targetnode *models.Node,
+	rules map[string]models.AclRule) map[string]models.AclRule {
+	userNodes := logic.GetStaticUserNodesByNetwork(models.NetworkID(targetnode.Network))
+	userGrpMap := GetUserGrpMap()
+	allowedUsers := make(map[string][]models.Acl)
+	acls := listUserPolicies(models.NetworkID(targetnode.Network))
+	var targetNodeTags = make(map[models.TagID]struct{})
+	targetNodeTags["*"] = struct{}{}
+	for _, rangeI := range targetnode.EgressDetails.EgressGatewayRanges {
+		targetNodeTags[models.TagID(rangeI)] = struct{}{}
+	}
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		for _, dst := range acl.Dst {
+			if dst.ID == models.EgressID {
+				e := schema.Egress{ID: dst.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err == nil && e.Status {
+					for nodeID := range e.Nodes {
+						dstTags[nodeID] = struct{}{}
+					}
+					dstTags[e.Range] = struct{}{}
+				}
+			}
+		}
+		_, all := dstTags["*"]
+		addUsers := false
+		if !all {
+			for nodeTag := range targetNodeTags {
+				if _, ok := dstTags[nodeTag.String()]; ok {
+					addUsers = true
+					break
+				}
+			}
+		} else {
+			addUsers = true
+		}
+
+		if addUsers {
+			// get all src tags
+			for _, srcAcl := range acl.Src {
+				if srcAcl.ID == models.UserAclID {
+					allowedUsers[srcAcl.Value] = append(allowedUsers[srcAcl.Value], acl)
+				} else if srcAcl.ID == models.UserGroupAclID {
+					// fetch all users in the group
+					if usersMap, ok := userGrpMap[models.UserGroupID(srcAcl.Value)]; ok {
+						for userName := range usersMap {
+							allowedUsers[userName] = append(allowedUsers[userName], acl)
+						}
+					}
+				}
+			}
+		}
+
+	}
+
+	for _, userNode := range userNodes {
+		if !userNode.StaticNode.Enabled {
+			continue
+		}
+		acls, ok := allowedUsers[userNode.StaticNode.OwnerID]
+		if !ok {
+			continue
+		}
+		for _, acl := range acls {
+
+			if !acl.Enabled {
+				continue
+			}
+			r := models.AclRule{
+				ID:              acl.ID,
+				AllowedProtocol: acl.Proto,
+				AllowedPorts:    acl.Port,
+				Direction:       acl.AllowedDirection,
+				Allowed:         true,
+			}
+			// Get peers in the tags and add allowed rules
+			if userNode.StaticNode.Address != "" {
+				r.IPList = append(r.IPList, userNode.StaticNode.AddressIPNet4())
+			}
+			if userNode.StaticNode.Address6 != "" {
+				r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
+			}
+			for _, dstI := range acl.Dst {
+				if dstI.ID == models.EgressID {
+					e := schema.Egress{ID: dstI.Value}
+					err := e.Get(db.WithContext(context.TODO()))
+					if err != nil {
+						continue
+					}
+					if e.IsInetGw {
+						r.Dst = append(r.Dst, net.IPNet{
+							IP:   net.IPv4zero,
+							Mask: net.CIDRMask(0, 32),
+						})
+						r.Dst6 = append(r.Dst6, net.IPNet{
+							IP:   net.IPv6zero,
+							Mask: net.CIDRMask(0, 128),
+						})
+
+					} else {
+						ip, cidr, err := net.ParseCIDR(e.Range)
+						if err == nil {
+							if ip.To4() != nil {
+								r.Dst = append(r.Dst, *cidr)
+							} else {
+								r.Dst6 = append(r.Dst6, *cidr)
+							}
+
+						}
+					}
+
+				}
+
+			}
+			if aclRule, ok := rules[acl.ID]; ok {
+				aclRule.IPList = append(aclRule.IPList, r.IPList...)
+				aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
+				rules[acl.ID] = aclRule
+			} else {
+				rules[acl.ID] = r
+			}
+		}
+	}
+	return rules
+}
+
+func getUserAclRulesForNode(targetnode *models.Node,
+	rules map[string]models.AclRule) map[string]models.AclRule {
+	userNodes := logic.GetStaticUserNodesByNetwork(models.NetworkID(targetnode.Network))
+	userGrpMap := GetUserGrpMap()
+	allowedUsers := make(map[string][]models.Acl)
+	acls := listUserPolicies(models.NetworkID(targetnode.Network))
+	var targetNodeTags = make(map[models.TagID]struct{})
+	if targetnode.Mutex != nil {
+		targetnode.Mutex.Lock()
+		targetNodeTags = maps.Clone(targetnode.Tags)
+		targetnode.Mutex.Unlock()
+	} else {
+		targetNodeTags = maps.Clone(targetnode.Tags)
+	}
+	if targetNodeTags == nil {
+		targetNodeTags = make(map[models.TagID]struct{})
+	}
+	targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		_, all := dstTags["*"]
+		addUsers := false
+		if !all {
+			for nodeTag := range targetNodeTags {
+				if _, ok := dstTags[nodeTag.String()]; ok {
+					addUsers = true
+					break
+				}
+			}
+		} else {
+			addUsers = true
+		}
+
+		if addUsers {
+			// get all src tags
+			for _, srcAcl := range acl.Src {
+				if srcAcl.ID == models.UserAclID {
+					allowedUsers[srcAcl.Value] = append(allowedUsers[srcAcl.Value], acl)
+				} else if srcAcl.ID == models.UserGroupAclID {
+					// fetch all users in the group
+					if usersMap, ok := userGrpMap[models.UserGroupID(srcAcl.Value)]; ok {
+						for userName := range usersMap {
+							allowedUsers[userName] = append(allowedUsers[userName], acl)
+						}
+					}
+				}
+			}
+		}
+
+	}
+
+	for _, userNode := range userNodes {
+		if !userNode.StaticNode.Enabled {
+			continue
+		}
+		acls, ok := allowedUsers[userNode.StaticNode.OwnerID]
+		if !ok {
+			continue
+		}
+		for _, acl := range acls {
+
+			if !acl.Enabled {
+				continue
+			}
+			r := models.AclRule{
+				ID:              acl.ID,
+				AllowedProtocol: acl.Proto,
+				AllowedPorts:    acl.Port,
+				Direction:       acl.AllowedDirection,
+				Allowed:         true,
+			}
+			// Get peers in the tags and add allowed rules
+			if userNode.StaticNode.Address != "" {
+				r.IPList = append(r.IPList, userNode.StaticNode.AddressIPNet4())
+			}
+			if userNode.StaticNode.Address6 != "" {
+				r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
+			}
+			if aclRule, ok := rules[acl.ID]; ok {
+				aclRule.IPList = append(aclRule.IPList, r.IPList...)
+				aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
+				aclRule.IPList = UniqueIPNetList(aclRule.IPList)
+				aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
+				rules[acl.ID] = aclRule
+			} else {
+				r.IPList = UniqueIPNetList(r.IPList)
+				r.IP6List = UniqueIPNetList(r.IP6List)
+				rules[acl.ID] = r
+			}
+		}
+	}
+	return rules
+}
+
+func checkIfAnyActiveEgressPolicy(targetNode models.Node) bool {
+	if !targetNode.EgressDetails.IsEgressGateway {
+		return false
+	}
+	var targetNodeTags = make(map[models.TagID]struct{})
+	if targetNode.Mutex != nil {
+		targetNode.Mutex.Lock()
+		targetNodeTags = maps.Clone(targetNode.Tags)
+		targetNode.Mutex.Unlock()
+	} else {
+		targetNodeTags = maps.Clone(targetNode.Tags)
+	}
+	if targetNodeTags == nil {
+		targetNodeTags = make(map[models.TagID]struct{})
+	}
+	targetNodeTags[models.TagID(targetNode.ID.String())] = struct{}{}
+	targetNodeTags["*"] = struct{}{}
+	acls, _ := logic.ListAclsByNetwork(models.NetworkID(targetNode.Network))
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		srcTags := logic.ConvAclTagToValueMap(acl.Src)
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		for _, dst := range acl.Dst {
+			if dst.ID == models.EgressID {
+				e := schema.Egress{ID: dst.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err == nil && e.Status {
+					for nodeID := range e.Nodes {
+						dstTags[nodeID] = struct{}{}
+					}
+					dstTags[e.Range] = struct{}{}
+				}
+			}
+		}
+		for nodeTag := range targetNodeTags {
+			if acl.RuleType == models.DevicePolicy && acl.AllowedDirection == models.TrafficDirectionBi {
+				if _, ok := srcTags[nodeTag.String()]; ok {
+					return true
+				}
+				if _, ok := srcTags[targetNode.ID.String()]; ok {
+					return true
+				}
+			}
+
+			if _, ok := dstTags[nodeTag.String()]; ok {
+				return true
+			}
+			if _, ok := dstTags[targetNode.ID.String()]; ok {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+func checkIfAnyPolicyisUniDirectional(targetNode models.Node) bool {
+	var targetNodeTags = make(map[models.TagID]struct{})
+	if targetNode.Mutex != nil {
+		targetNode.Mutex.Lock()
+		targetNodeTags = maps.Clone(targetNode.Tags)
+		targetNode.Mutex.Unlock()
+	} else {
+		targetNodeTags = maps.Clone(targetNode.Tags)
+	}
+	if targetNodeTags == nil {
+		targetNodeTags = make(map[models.TagID]struct{})
+	}
+	targetNodeTags[models.TagID(targetNode.ID.String())] = struct{}{}
+	targetNodeTags["*"] = struct{}{}
+	acls, _ := logic.ListAclsByNetwork(models.NetworkID(targetNode.Network))
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		if acl.AllowedDirection == models.TrafficDirectionBi && acl.Proto == models.ALL && acl.ServiceType == models.Any {
+			continue
+		}
+		if acl.Proto != models.ALL || acl.ServiceType != models.Any {
+			return true
+		}
+		srcTags := logic.ConvAclTagToValueMap(acl.Src)
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		for nodeTag := range targetNodeTags {
+			if acl.RuleType == models.DevicePolicy {
+				if _, ok := srcTags[nodeTag.String()]; ok {
+					return true
+				}
+				if _, ok := srcTags[targetNode.ID.String()]; ok {
+					return true
+				}
+			}
+
+			if _, ok := dstTags[nodeTag.String()]; ok {
+				return true
+			}
+			if _, ok := dstTags[targetNode.ID.String()]; ok {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+func checkIfNodeHasAccessToAllResources(targetnode *models.Node) bool {
+	acls := logic.ListDevicePolicies(models.NetworkID(targetnode.Network))
+	var targetNodeTags = make(map[models.TagID]struct{})
+	if targetnode.Mutex != nil {
+		targetnode.Mutex.Lock()
+		targetNodeTags = maps.Clone(targetnode.Tags)
+		targetnode.Mutex.Unlock()
+	} else {
+		targetNodeTags = maps.Clone(targetnode.Tags)
+	}
+	if targetNodeTags == nil {
+		targetNodeTags = make(map[models.TagID]struct{})
+	}
+	targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
+	targetNodeTags["*"] = struct{}{}
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		srcTags := logic.ConvAclTagToValueMap(acl.Src)
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		_, srcAll := srcTags["*"]
+		_, dstAll := dstTags["*"]
+		for nodeTag := range targetNodeTags {
+
+			var existsInSrcTag bool
+			var existsInDstTag bool
+
+			if _, ok := srcTags[nodeTag.String()]; ok {
+				existsInSrcTag = true
+			}
+			if _, ok := srcTags[targetnode.ID.String()]; ok {
+				existsInSrcTag = true
+			}
+			if _, ok := dstTags[nodeTag.String()]; ok {
+				existsInDstTag = true
+			}
+			if _, ok := dstTags[targetnode.ID.String()]; ok {
+				existsInDstTag = true
+			}
+			if acl.AllowedDirection == models.TrafficDirectionBi {
+				if existsInSrcTag && dstAll || existsInDstTag && srcAll {
+					return true
+				}
+			} else {
+				if existsInDstTag && srcAll {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRule) {
+	targetnode := *targetnodeI
+	defer func() {
+		if !targetnode.IsIngressGateway {
+			rules = getUserAclRulesForNode(&targetnode, rules)
+		}
+	}()
+	rules = make(map[string]models.AclRule)
+	var taggedNodes map[models.TagID][]models.Node
+	if targetnode.IsIngressGateway {
+		taggedNodes = GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), false)
+	} else {
+		taggedNodes = GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), true)
+	}
+	acls := logic.ListDevicePolicies(models.NetworkID(targetnode.Network))
+	var targetNodeTags = make(map[models.TagID]struct{})
+	if targetnode.Mutex != nil {
+		targetnode.Mutex.Lock()
+		targetNodeTags = maps.Clone(targetnode.Tags)
+		targetnode.Mutex.Unlock()
+	} else {
+		targetNodeTags = maps.Clone(targetnode.Tags)
+	}
+	if targetNodeTags == nil {
+		targetNodeTags = make(map[models.TagID]struct{})
+	}
+	targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
+	targetNodeTags["*"] = struct{}{}
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		srcTags := logic.ConvAclTagToValueMap(acl.Src)
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		for _, dst := range acl.Dst {
+			if dst.ID == models.EgressID {
+				e := schema.Egress{ID: dst.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err == nil && e.Status {
+					for nodeID := range e.Nodes {
+						dstTags[nodeID] = struct{}{}
+					}
+				}
+			}
+		}
+		_, srcAll := srcTags["*"]
+		_, dstAll := dstTags["*"]
+		aclRule := models.AclRule{
+			ID:              acl.ID,
+			AllowedProtocol: acl.Proto,
+			AllowedPorts:    acl.Port,
+			Direction:       acl.AllowedDirection,
+			Allowed:         true,
+		}
+		for nodeTag := range targetNodeTags {
+			if acl.AllowedDirection == models.TrafficDirectionBi {
+				var existsInSrcTag bool
+				var existsInDstTag bool
+
+				if _, ok := srcTags[nodeTag.String()]; ok || srcAll {
+					existsInSrcTag = true
+				}
+				if _, ok := srcTags[targetnode.ID.String()]; ok || srcAll {
+					existsInSrcTag = true
+				}
+				if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
+					existsInDstTag = true
+				}
+				if _, ok := dstTags[targetnode.ID.String()]; ok || dstAll {
+					existsInDstTag = true
+				}
+
+				if existsInSrcTag /* && !existsInDstTag*/ {
+					// get all dst tags
+					for dst := range dstTags {
+						if dst == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(dst)]
+						if dst != targetnode.ID.String() {
+							node, err := logic.GetNodeByID(dst)
+							if err == nil {
+								nodes = append(nodes, node)
+							}
+						}
+
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.IsStatic && node.StaticNode.IngressGatewayID == targetnode.ID.String() {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+				if existsInDstTag /*&& !existsInSrcTag*/ {
+					// get all src tags
+					for src := range srcTags {
+						if src == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(src)]
+						if src != targetnode.ID.String() {
+							node, err := logic.GetNodeByID(src)
+							if err == nil {
+								nodes = append(nodes, node)
+							}
+						}
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.IsStatic && node.StaticNode.IngressGatewayID == targetnode.ID.String() {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+				// if existsInDstTag && existsInSrcTag {
+				// 	nodes := taggedNodes[nodeTag]
+				// 	for srcID := range srcTags {
+				// 		if srcID == targetnode.ID.String() {
+				// 			continue
+				// 		}
+				// 		node, err := GetNodeByID(srcID)
+				// 		if err == nil {
+				// 			nodes = append(nodes, node)
+				// 		}
+				// 	}
+				// 	for dstID := range dstTags {
+				// 		if dstID == targetnode.ID.String() {
+				// 			continue
+				// 		}
+				// 		node, err := GetNodeByID(dstID)
+				// 		if err == nil {
+				// 			nodes = append(nodes, node)
+				// 		}
+				// 	}
+				// 	for _, node := range nodes {
+				// 		if node.ID == targetnode.ID {
+				// 			continue
+				// 		}
+				// 		if node.IsStatic && node.StaticNode.IngressGatewayID == targetnode.ID.String() {
+				// 			continue
+				// 		}
+				// 		if node.Address.IP != nil {
+				// 			aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+				// 		}
+				// 		if node.Address6.IP != nil {
+				// 			aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+				// 		}
+				// 		if node.IsStatic && node.StaticNode.Address != "" {
+				// 			aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+				// 		}
+				// 		if node.IsStatic && node.StaticNode.Address6 != "" {
+				// 			aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+				// 		}
+				// 	}
+				// }
+			} else {
+				_, all := dstTags["*"]
+				if _, ok := dstTags[nodeTag.String()]; ok || all {
+					// get all src tags
+					for src := range srcTags {
+						if src == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(src)]
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.IsStatic && node.StaticNode.IngressGatewayID == targetnode.ID.String() {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+			}
+
+		}
+
+		if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
+			aclRule.IPList = UniqueIPNetList(aclRule.IPList)
+			aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
+			rules[acl.ID] = aclRule
+		}
+	}
+	return rules
+}
+
+func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclRule) {
+	rules = make(map[string]models.AclRule)
+	defer func() {
+		rules = getEgressUserRulesForNode(&targetnode, rules)
+	}()
+	taggedNodes := GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), true)
+
+	acls := logic.ListDevicePolicies(models.NetworkID(targetnode.Network))
+	var targetNodeTags = make(map[models.TagID]struct{})
+	targetNodeTags["*"] = struct{}{}
+
+	/*
+		 if target node is egress gateway
+			if acl policy has egress route and it is present in target node egress ranges
+			fetch all the nodes in that policy and add rules
+	*/
+	egs, _ := (&schema.Egress{Network: targetnode.Network}).ListByNetwork(db.WithContext(context.TODO()))
+	if len(egs) == 0 {
+		return
+	}
+	for _, egI := range egs {
+		if !egI.Status {
+			continue
+		}
+		if _, ok := egI.Nodes[targetnode.ID.String()]; ok {
+			if egI.Range == "*" {
+				targetNodeTags[models.TagID("0.0.0.0/0")] = struct{}{}
+				targetNodeTags[models.TagID("::/0")] = struct{}{}
+			} else {
+				targetNodeTags[models.TagID(egI.Range)] = struct{}{}
+			}
+			targetNodeTags[models.TagID(egI.ID)] = struct{}{}
+		}
+	}
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		srcTags := logic.ConvAclTagToValueMap(acl.Src)
+		dstTags := logic.ConvAclTagToValueMap(acl.Dst)
+		_, srcAll := srcTags["*"]
+		_, dstAll := dstTags["*"]
+		aclRule := models.AclRule{
+			ID:              acl.ID,
+			AllowedProtocol: acl.Proto,
+			AllowedPorts:    acl.Port,
+			Direction:       acl.AllowedDirection,
+			Allowed:         true,
+		}
+		for nodeTag := range targetNodeTags {
+
+			if nodeTag != "*" {
+				ip, cidr, err := net.ParseCIDR(nodeTag.String())
+				if err == nil {
+					if ip.To4() != nil {
+						aclRule.Dst = append(aclRule.Dst, *cidr)
+					} else {
+						aclRule.Dst6 = append(aclRule.Dst6, *cidr)
+					}
+				}
+			}
+			if acl.AllowedDirection == models.TrafficDirectionBi {
+				var existsInSrcTag bool
+				var existsInDstTag bool
+				if _, ok := srcTags[nodeTag.String()]; ok || srcAll {
+					existsInSrcTag = true
+				}
+				if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
+					existsInDstTag = true
+				}
+				if srcAll || dstAll {
+					if targetnode.NetworkRange.IP != nil {
+						aclRule.IPList = append(aclRule.IPList, targetnode.NetworkRange)
+					}
+					if targetnode.NetworkRange6.IP != nil {
+						aclRule.IP6List = append(aclRule.IP6List, targetnode.NetworkRange6)
+					}
+					break
+				}
+				if existsInSrcTag && !existsInDstTag {
+					// get all dst tags
+					for dst := range dstTags {
+						if dst == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(dst)]
+						if dst != targetnode.ID.String() {
+							node, err := logic.GetNodeByID(dst)
+							if err == nil {
+								nodes = append(nodes, node)
+							}
+						}
+
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+				if existsInDstTag && !existsInSrcTag {
+					// get all src tags
+					for src := range srcTags {
+						if src == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(src)]
+						if src != targetnode.ID.String() {
+							node, err := logic.GetNodeByID(src)
+							if err == nil {
+								nodes = append(nodes, node)
+							}
+						}
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+				if existsInDstTag && existsInSrcTag {
+					nodes := taggedNodes[nodeTag]
+					for srcID := range srcTags {
+						if srcID == targetnode.ID.String() {
+							continue
+						}
+						node, err := logic.GetNodeByID(srcID)
+						if err == nil {
+							nodes = append(nodes, node)
+						}
+					}
+					for dstID := range dstTags {
+						if dstID == targetnode.ID.String() {
+							continue
+						}
+						node, err := logic.GetNodeByID(dstID)
+						if err == nil {
+							nodes = append(nodes, node)
+						}
+					}
+					for _, node := range nodes {
+						if node.ID == targetnode.ID {
+							continue
+						}
+						if node.Address.IP != nil {
+							aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+						}
+						if node.Address6.IP != nil {
+							aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+						}
+						if node.IsStatic && node.StaticNode.Address != "" {
+							aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+						}
+						if node.IsStatic && node.StaticNode.Address6 != "" {
+							aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+						}
+					}
+				}
+			} else {
+				if dstAll {
+					if targetnode.NetworkRange.IP != nil {
+						aclRule.IPList = append(aclRule.IPList, targetnode.NetworkRange)
+					}
+					if targetnode.NetworkRange6.IP != nil {
+						aclRule.IP6List = append(aclRule.IP6List, targetnode.NetworkRange6)
+					}
+					break
+				}
+				if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
+					// get all src tags
+					for src := range srcTags {
+						if src == nodeTag.String() {
+							continue
+						}
+						// Get peers in the tags and add allowed rules
+						nodes := taggedNodes[models.TagID(src)]
+						for _, node := range nodes {
+							if node.ID == targetnode.ID {
+								continue
+							}
+							if node.Address.IP != nil {
+								aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
+							}
+							if node.Address6.IP != nil {
+								aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
+							}
+							if node.IsStatic && node.StaticNode.Address != "" {
+								aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
+							}
+							if node.IsStatic && node.StaticNode.Address6 != "" {
+								aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
+							}
+						}
+					}
+				}
+			}
+
+		}
+		if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
+			aclRule.IPList = UniqueIPNetList(aclRule.IPList)
+			aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
+			rules[acl.ID] = aclRule
+		}
+
+	}
+	return
+}
+
+// Compare two IPs and return true if ip1 < ip2
+func lessIP(ip1, ip2 net.IP) bool {
+	ip1 = ip1.To16() // Ensure IPv4 is converted to IPv6-mapped format
+	ip2 = ip2.To16()
+	return string(ip1) < string(ip2)
+}
+
+// Sort by IP first, then by prefix length
+func sortIPNets(ipNets []net.IPNet) {
+	sort.Slice(ipNets, func(i, j int) bool {
+		ip1, ip2 := ipNets[i].IP, ipNets[j].IP
+		mask1, _ := ipNets[i].Mask.Size()
+		mask2, _ := ipNets[j].Mask.Size()
+
+		// Compare IPs first
+		if ip1.Equal(ip2) {
+			return mask1 < mask2 // If same IP, sort by subnet mask size
+		}
+		return lessIP(ip1, ip2)
+	})
+}
+
+func UniqueIPNetList(ipnets []net.IPNet) []net.IPNet {
+	uniqueMap := make(map[string]net.IPNet)
+
+	for _, ipnet := range ipnets {
+		key := ipnet.String() // Uses CIDR notation as a unique key
+		if _, exists := uniqueMap[key]; !exists {
+			uniqueMap[key] = ipnet
+		}
+	}
+
+	// Convert map back to slice
+	uniqueList := make([]net.IPNet, 0, len(uniqueMap))
+	for _, ipnet := range uniqueMap {
+		uniqueList = append(uniqueList, ipnet)
+	}
+	sortIPNets(uniqueList)
+	return uniqueList
+}
+
+func GetInetClientsFromAclPolicies(eID string) (inetClientIDs []string) {
+	e := schema.Egress{ID: eID}
+	err := e.Get(db.WithContext(context.TODO()))
+	if err != nil || !e.Status {
+		return
+	}
+	acls, _ := logic.ListAclsByNetwork(models.NetworkID(e.Network))
+	for _, acl := range acls {
+		for _, dstI := range acl.Dst {
+			if dstI.ID == models.EgressID {
+				if dstI.Value != eID {
+					continue
+				}
+				for _, srcI := range acl.Src {
+					if srcI.Value == "*" {
+						continue
+					}
+					if srcI.ID == models.NodeID {
+						inetClientIDs = append(inetClientIDs, srcI.Value)
+					}
+					if srcI.ID == models.NodeTagID {
+						inetClientIDs = append(inetClientIDs, GetNodeIDsWithTag(models.TagID(srcI.Value))...)
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+func isNodeUsingInternetGw(node *models.Node) {
+	host, err := logic.GetHost(node.HostID.String())
+	if err != nil {
+		return
+	}
+	if host.IsDefault || node.IsFailOver {
+		return
+	}
+	nodeTags := maps.Clone(node.Tags)
+	nodeTags[models.TagID(node.ID.String())] = struct{}{}
+	acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network))
+	var isUsing bool
+	for _, acl := range acls {
+		if !acl.Enabled {
+			continue
+		}
+		srcVal := logic.ConvAclTagToValueMap(acl.Src)
+		for _, dstI := range acl.Dst {
+			if dstI.ID == models.EgressID {
+				e := schema.Egress{ID: dstI.Value}
+				err := e.Get(db.WithContext(context.TODO()))
+				if err != nil || !e.Status {
+					continue
+				}
+
+				if e.IsInetGw {
+					if _, ok := srcVal[node.ID.String()]; ok {
+						for nodeID := range e.Nodes {
+							if nodeID == node.ID.String() {
+								continue
+							}
+							node.EgressDetails.InternetGwID = nodeID
+							isUsing = true
+							return
+						}
+					}
+					for tagID := range nodeTags {
+						if _, ok := srcVal[tagID.String()]; ok {
+							for nodeID := range e.Nodes {
+								if nodeID == node.ID.String() {
+									continue
+								}
+								node.EgressDetails.InternetGwID = nodeID
+								isUsing = true
+								return
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	if !isUsing {
+		node.EgressDetails.InternetGwID = ""
+	}
+}

+ 47 - 0
pro/logic/migrate.go

@@ -2,6 +2,8 @@ package logic
 
 import (
 	"encoding/json"
+	"fmt"
+
 	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
 
@@ -122,3 +124,48 @@ func MigrateUserRoleAndGroups(user models.User) {
 	}
 	logic.UpsertUser(user)
 }
+
+func MigrateToGws() {
+	nodes, err := logic.GetAllNodes()
+	if err != nil {
+		return
+	}
+	for _, node := range nodes {
+		if node.IsIngressGateway || node.IsRelay {
+			node.IsGw = true
+			node.IsIngressGateway = true
+			node.IsRelay = true
+			if node.Tags == nil {
+				node.Tags = make(map[models.TagID]struct{})
+			}
+			node.Tags[models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName))] = struct{}{}
+			delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.OldRemoteAccessTagName)))
+			logic.UpsertNode(&node)
+		}
+	}
+	acls := logic.ListAcls()
+	for _, acl := range acls {
+		upsert := false
+		for i, srcI := range acl.Src {
+			if srcI.ID == models.NodeTagID && srcI.Value == fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.OldRemoteAccessTagName) {
+				srcI.Value = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
+				acl.Src[i] = srcI
+				upsert = true
+			}
+		}
+		for i, dstI := range acl.Dst {
+			if dstI.ID == models.NodeTagID && dstI.Value == fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.OldRemoteAccessTagName) {
+				dstI.Value = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
+				acl.Dst[i] = dstI
+				upsert = true
+			}
+		}
+		if upsert {
+			logic.UpsertAcl(acl)
+		}
+	}
+	nets, _ := logic.GetNetworks()
+	for _, netI := range nets {
+		DeleteTag(models.TagID(fmt.Sprintf("%s.%s", netI.NetID, models.OldRemoteAccessTagName)), true)
+	}
+}

+ 204 - 0
pro/logic/nodes.go

@@ -184,3 +184,207 @@ func GetAllowedIpForInetNodeClient(node, peer *models.Node) []net.IPNet {
 
 	return allowedips
 }
+
+func GetTagMapWithNodes() (tagNodesMap map[models.TagID][]models.Node) {
+	tagNodesMap = make(map[models.TagID][]models.Node)
+	nodes, _ := logic.GetAllNodes()
+	for _, nodeI := range nodes {
+		if nodeI.Tags == nil {
+			continue
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Lock()
+		}
+		for nodeTagID := range nodeI.Tags {
+			tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Unlock()
+		}
+
+	}
+	return
+}
+
+func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (tagNodesMap map[models.TagID][]models.Node) {
+	tagNodesMap = make(map[models.TagID][]models.Node)
+	nodes, _ := logic.GetNetworkNodes(netID.String())
+	for _, nodeI := range nodes {
+		tagNodesMap[models.TagID(nodeI.ID.String())] = []models.Node{
+			nodeI,
+		}
+		if nodeI.Tags == nil {
+			continue
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Lock()
+		}
+		for nodeTagID := range nodeI.Tags {
+			if nodeTagID == models.TagID(nodeI.ID.String()) {
+				continue
+			}
+			tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Unlock()
+		}
+	}
+	tagNodesMap["*"] = nodes
+	if !withStaticNodes {
+		return
+	}
+	return AddTagMapWithStaticNodes(netID, tagNodesMap)
+}
+
+func AddTagMapWithStaticNodes(netID models.NetworkID,
+	tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
+	extclients, err := logic.GetNetworkExtClients(netID.String())
+	if err != nil {
+		return tagNodesMap
+	}
+	for _, extclient := range extclients {
+		if extclient.RemoteAccessClientID != "" {
+			continue
+		}
+		tagNodesMap[models.TagID(extclient.ClientID)] = []models.Node{
+			{
+				IsStatic:   true,
+				StaticNode: extclient,
+			},
+		}
+		if extclient.Tags == nil {
+			continue
+		}
+
+		if extclient.Mutex != nil {
+			extclient.Mutex.Lock()
+		}
+		for tagID := range extclient.Tags {
+			if tagID == models.TagID(extclient.ClientID) {
+				continue
+			}
+			tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
+			tagNodesMap["*"] = append(tagNodesMap["*"], extclient.ConvertToStaticNode())
+		}
+		if extclient.Mutex != nil {
+			extclient.Mutex.Unlock()
+		}
+	}
+	return tagNodesMap
+}
+
+func AddTagMapWithStaticNodesWithUsers(netID models.NetworkID,
+	tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
+	extclients, err := logic.GetNetworkExtClients(netID.String())
+	if err != nil {
+		return tagNodesMap
+	}
+	for _, extclient := range extclients {
+		tagNodesMap[models.TagID(extclient.ClientID)] = []models.Node{
+			{
+				IsStatic:   true,
+				StaticNode: extclient,
+			},
+		}
+		if extclient.Tags == nil {
+			continue
+		}
+		if extclient.Mutex != nil {
+			extclient.Mutex.Lock()
+		}
+		for tagID := range extclient.Tags {
+			tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
+		}
+		if extclient.Mutex != nil {
+			extclient.Mutex.Unlock()
+		}
+
+	}
+	return tagNodesMap
+}
+
+func GetNodeIDsWithTag(tagID models.TagID) (ids []string) {
+
+	tag, err := GetTag(tagID)
+	if err != nil {
+		return
+	}
+	nodes, _ := logic.GetNetworkNodes(tag.Network.String())
+	for _, nodeI := range nodes {
+		if nodeI.Tags == nil {
+			continue
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Lock()
+		}
+		if _, ok := nodeI.Tags[tagID]; ok {
+			ids = append(ids, nodeI.ID.String())
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Unlock()
+		}
+	}
+	return
+}
+
+func GetNodesWithTag(tagID models.TagID) map[string]models.Node {
+	nMap := make(map[string]models.Node)
+	tag, err := GetTag(tagID)
+	if err != nil {
+		return nMap
+	}
+	nodes, _ := logic.GetNetworkNodes(tag.Network.String())
+	for _, nodeI := range nodes {
+		if nodeI.Tags == nil {
+			continue
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Lock()
+		}
+		if _, ok := nodeI.Tags[tagID]; ok {
+			nMap[nodeI.ID.String()] = nodeI
+		}
+		if nodeI.Mutex != nil {
+			nodeI.Mutex.Unlock()
+		}
+	}
+	return AddStaticNodesWithTag(tag, nMap)
+}
+
+func AddStaticNodesWithTag(tag models.Tag, nMap map[string]models.Node) map[string]models.Node {
+	extclients, err := logic.GetNetworkExtClients(tag.Network.String())
+	if err != nil {
+		return nMap
+	}
+	for _, extclient := range extclients {
+		if extclient.RemoteAccessClientID != "" {
+			continue
+		}
+		if extclient.Mutex != nil {
+			extclient.Mutex.Lock()
+		}
+		if _, ok := extclient.Tags[tag.ID]; ok {
+			nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
+		}
+		if extclient.Mutex != nil {
+			extclient.Mutex.Unlock()
+		}
+	}
+	return nMap
+}
+
+func GetStaticNodeWithTag(tagID models.TagID) map[string]models.Node {
+	nMap := make(map[string]models.Node)
+	tag, err := GetTag(tagID)
+	if err != nil {
+		return nMap
+	}
+	extclients, err := logic.GetNetworkExtClients(tag.Network.String())
+	if err != nil {
+		return nMap
+	}
+	for _, extclient := range extclients {
+		nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
+	}
+	return nMap
+}

+ 18 - 17
logic/tags.go → pro/logic/tags.go

@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"golang.org/x/exp/slog"
 )
@@ -62,7 +63,7 @@ func DeleteTag(tagID models.TagID, removeFromPolicy bool) error {
 	if err != nil {
 		return err
 	}
-	nodes, err := GetNetworkNodes(tag.Network.String())
+	nodes, err := logic.GetNetworkNodes(tag.Network.String())
 	if err != nil {
 		return err
 	}
@@ -70,18 +71,18 @@ func DeleteTag(tagID models.TagID, removeFromPolicy bool) error {
 		nodeI := nodeI
 		if _, ok := nodeI.Tags[tagID]; ok {
 			delete(nodeI.Tags, tagID)
-			UpsertNode(&nodeI)
+			logic.UpsertNode(&nodeI)
 		}
 	}
 	if removeFromPolicy {
 		// remove tag used on acl policy
 		go RemoveDeviceTagFromAclPolicies(tagID, tag.Network)
 	}
-	extclients, _ := GetNetworkExtClients(tag.Network.String())
+	extclients, _ := logic.GetNetworkExtClients(tag.Network.String())
 	for _, extclient := range extclients {
 		if _, ok := extclient.Tags[tagID]; ok {
 			delete(extclient.Tags, tagID)
-			SaveExtClient(&extclient)
+			logic.SaveExtClient(&extclient)
 		}
 	}
 	return database.DeleteRecord(database.TAG_TABLE_NAME, tagID.String())
@@ -99,7 +100,7 @@ func ListTagsWithNodes(netID models.NetworkID) ([]models.TagListResp, error) {
 		tagRespI := models.TagListResp{
 			Tag:         tagI,
 			UsedByCnt:   len(tagsNodeMap[tagI.ID]),
-			TaggedNodes: GetAllNodesAPI(tagsNodeMap[tagI.ID]),
+			TaggedNodes: logic.GetAllNodesAPI(tagsNodeMap[tagI.ID]),
 		}
 		resp = append(resp, tagRespI)
 	}
@@ -168,7 +169,7 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
 			if apiNode.StaticNode.RemoteAccessClientID != "" {
 				continue
 			}
-			extclient, err := GetExtClient(apiNode.StaticNode.ClientID, apiNode.StaticNode.Network)
+			extclient, err := logic.GetExtClient(apiNode.StaticNode.ClientID, apiNode.StaticNode.Network)
 			if err != nil {
 				continue
 			}
@@ -176,7 +177,7 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
 			nodeID = extclient.ClientID
 			node.StaticNode = extclient
 		} else {
-			node, err = GetNodeByID(apiNode.ID)
+			node, err = logic.GetNodeByID(apiNode.ID)
 			if err != nil {
 				continue
 			}
@@ -193,19 +194,19 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
 			if newID != "" {
 				if node.IsStatic {
 					node.StaticNode.Tags[newID] = struct{}{}
-					SaveExtClient(&node.StaticNode)
+					logic.SaveExtClient(&node.StaticNode)
 				} else {
 					node.Tags[newID] = struct{}{}
-					UpsertNode(&node)
+					logic.UpsertNode(&node)
 				}
 
 			} else {
 				if node.IsStatic {
 					node.StaticNode.Tags[req.ID] = struct{}{}
-					SaveExtClient(&node.StaticNode)
+					logic.SaveExtClient(&node.StaticNode)
 				} else {
 					node.Tags[req.ID] = struct{}{}
-					UpsertNode(&node)
+					logic.UpsertNode(&node)
 				}
 			}
 		} else {
@@ -214,10 +215,10 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
 				delete(node.StaticNode.Tags, req.ID)
 				if node.IsStatic {
 					node.StaticNode.Tags[newID] = struct{}{}
-					SaveExtClient(&node.StaticNode)
+					logic.SaveExtClient(&node.StaticNode)
 				} else {
 					node.Tags[newID] = struct{}{}
-					UpsertNode(&node)
+					logic.UpsertNode(&node)
 				}
 			}
 			delete(tagNodesMap, nodeID)
@@ -228,9 +229,9 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
 		delete(deletedTaggedNode.Tags, req.ID)
 		delete(deletedTaggedNode.StaticNode.Tags, req.ID)
 		if deletedTaggedNode.IsStatic {
-			SaveExtClient(&deletedTaggedNode.StaticNode)
+			logic.SaveExtClient(&deletedTaggedNode.StaticNode)
 		} else {
-			UpsertNode(&deletedTaggedNode)
+			logic.UpsertNode(&deletedTaggedNode)
 		}
 	}
 	go func(req models.UpdateTagReq) {
@@ -249,9 +250,9 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
 				nodeI.Tags[newID] = struct{}{}
 				nodeI.StaticNode.Tags[newID] = struct{}{}
 				if nodeI.IsStatic {
-					SaveExtClient(&nodeI.StaticNode)
+					logic.SaveExtClient(&nodeI.StaticNode)
 				} else {
-					UpsertNode(&nodeI)
+					logic.UpsertNode(&nodeI)
 				}
 			}
 		}

+ 23 - 3
pro/logic/user_mgmt.go

@@ -4,9 +4,10 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/google/uuid"
 	"time"
 
+	"github.com/google/uuid"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
@@ -660,8 +661,8 @@ func GetUserRAGNodesV1(user models.User) (gws map[string]models.Node) {
 
 		}
 	}
-	tagNodesMap := logic.GetTagMapWithNodes()
-	accessPolices := logic.ListUserPolicies(user)
+	tagNodesMap := GetTagMapWithNodes()
+	accessPolices := ListUserPolicies(user)
 	for _, policyI := range accessPolices {
 		if !policyI.Enabled {
 			continue
@@ -1237,3 +1238,22 @@ func AddGlobalNetRolesToAdmins(u *models.User) {
 
 	u.UserGroups[globalNetworksAdminGroupID] = struct{}{}
 }
+
+func GetUserGrpMap() map[models.UserGroupID]map[string]struct{} {
+	grpUsersMap := make(map[models.UserGroupID]map[string]struct{})
+	users, _ := logic.GetUsersDB()
+	for _, user := range users {
+		for gID := range user.UserGroups {
+			if grpUsers, ok := grpUsersMap[gID]; ok {
+				grpUsers[user.UserName] = struct{}{}
+				grpUsersMap[gID] = grpUsers
+			} else {
+				grpUsersMap[gID] = make(map[string]struct{})
+				grpUsersMap[gID][user.UserName] = struct{}{}
+			}
+		}
+
+	}
+
+	return grpUsersMap
+}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini