Browse Source

began transition

0xdcarns 3 years ago
parent
commit
de4e317aea
5 changed files with 209 additions and 427 deletions
  1. 1 8
      go.mod
  2. 21 209
      logic/nodes.go
  3. 87 72
      logic/server.go
  4. 91 94
      logic/util.go
  5. 9 44
      models/node.go

+ 1 - 8
go.mod

@@ -3,11 +3,9 @@ module github.com/gravitl/netmaker
 go 1.17
 
 require (
-	github.com/eclipse/paho.mqtt.golang v1.3.5
 	github.com/go-playground/validator/v10 v10.10.0
 	github.com/golang-jwt/jwt/v4 v4.2.0
 	github.com/golang/protobuf v1.5.2 // indirect
-	github.com/google/uuid v1.3.0
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
 	github.com/lib/pq v1.10.4
@@ -27,7 +25,6 @@ require (
 	google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
 	google.golang.org/grpc v1.43.0
 	google.golang.org/protobuf v1.27.1
-	gopkg.in/ini.v1 v1.66.2
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 )
 
@@ -35,13 +32,11 @@ require (
 	cloud.google.com/go v0.34.0 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect
 	github.com/felixge/httpsnoop v1.0.1 // indirect
-	github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect
 	github.com/go-playground/locales v0.14.0 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect
 	github.com/google/go-cmp v0.5.5 // indirect
-	github.com/gorilla/websocket v1.4.2 // indirect
+	github.com/google/uuid v1.3.0 // indirect
 	github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
 	github.com/mdlayher/genetlink v1.0.0 // indirect
@@ -49,7 +44,5 @@ require (
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/russross/blackfriday/v2 v2.0.1 // indirect
 	github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
-	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
 	google.golang.org/appengine v1.4.0 // indirect
-	gopkg.in/ini.v1 v1.66.2 // indirect
 )

+ 21 - 209
logic/nodes.go

@@ -5,26 +5,32 @@ import (
 	"errors"
 	"fmt"
 	"sort"
-	"strings"
 	"time"
 
 	"github.com/go-playground/validator/v10"
-	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
-	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/validation"
-	"golang.org/x/crypto/bcrypt"
 )
 
 // GetNetworkNodes - gets the nodes of a network
 func GetNetworkNodes(network string) ([]models.Node, error) {
-	var nodes, err = GetAllNodes()
+	var nodes []models.Node
+	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
 	if err != nil {
-		return []models.Node{}, err
+		if database.IsEmptyRecord(err) {
+			return []models.Node{}, nil
+		}
+		return nodes, err
 	}
-	for _, node := range nodes {
+	for _, value := range collection {
+
+		var node models.Node
+		err := json.Unmarshal([]byte(value), &node)
+		if err != nil {
+			continue
+		}
 		if node.Network == network {
 			nodes = append(nodes, node)
 		}
@@ -58,8 +64,8 @@ func GetSortedNetworkServerNodes(network string) ([]models.Node, error) {
 }
 
 // UncordonNode - approves a node to join a network
-func UncordonNode(nodeid string) (models.Node, error) {
-	node, err := GetNodeByID(nodeid)
+func UncordonNode(network, macaddress string) (models.Node, error) {
+	node, err := GetNodeByMacAddress(network, macaddress)
 	if err != nil {
 		return models.Node{}, err
 	}
@@ -70,15 +76,19 @@ func UncordonNode(nodeid string) (models.Node, error) {
 	if err != nil {
 		return node, err
 	}
+	key, err := GetRecordKey(node.MacAddress, node.Network)
+	if err != nil {
+		return node, err
+	}
 
-	err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)
+	err = database.Insert(key, string(data), database.NODES_TABLE_NAME)
 	return node, err
 }
 
 // GetPeers - gets the peers of a given node
 func GetPeers(node *models.Node) ([]models.Node, error) {
 	if IsLeader(node) {
-		setNetworkServerPeers(node)
+		SetNetworkServerPeers(node)
 	}
 	excludeIsRelayed := node.IsRelay != "yes"
 	var relayedNode string
@@ -111,13 +121,6 @@ func IsLeader(node *models.Node) bool {
 
 // UpdateNode - takes a node and updates another node with it's values
 func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
-	if newNode.Address != currentNode.Address {
-		if network, err := GetParentNetwork(newNode.Network); err == nil {
-			if !IsAddressInCIDR(newNode.Address, network.AddressRange) {
-				return fmt.Errorf("invalid address provided; out of network range for node %s", newNode.ID)
-			}
-		}
-	}
 	newNode.Fill(currentNode)
 	if err := ValidateNode(newNode, true); err != nil {
 		return err
@@ -165,128 +168,6 @@ func ValidateNode(node *models.Node, isUpdate bool) error {
 	return err
 }
 
-// CreateNode - creates a node in database
-func CreateNode(node *models.Node) error {
-
-	//encrypt that password so we never see it
-	hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
-	if err != nil {
-		return err
-	}
-	//set password to encrypted password
-	node.Password = string(hash)
-	if node.Name == models.NODE_SERVER_NAME {
-		node.IsServer = "yes"
-	}
-	if node.DNSOn == "" {
-		if servercfg.IsDNSMode() {
-			node.DNSOn = "yes"
-		} else {
-			node.DNSOn = "no"
-		}
-	}
-	SetNodeDefaults(node)
-	node.Address, err = UniqueAddress(node.Network)
-	if err != nil {
-		return err
-	}
-	node.Address6, err = UniqueAddress6(node.Network)
-	if err != nil {
-		return err
-	}
-
-	// TODO: This covers legacy nodes, eventually want to remove legacy check
-	if node.IsServer == "yes" {
-		node.ID = uuid.NewString()
-	} else if node.IsServer != "yes" || (node.ID == "" || strings.Contains(node.ID, "###")) {
-		node.ID = uuid.NewString()
-	}
-
-	//Create a JWT for the node
-	tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network)
-	if tokenString == "" {
-		//returnErrorResponse(w, r, errorResponse)
-		return err
-	}
-	err = ValidateNode(node, false)
-	if err != nil {
-		return err
-	}
-
-	nodebytes, err := json.Marshal(&node)
-	if err != nil {
-		return err
-	}
-	err = database.Insert(node.ID, string(nodebytes), database.NODES_TABLE_NAME)
-	if err != nil {
-		return err
-	}
-	if node.IsPending != "yes" {
-		DecrimentKey(node.Network, node.AccessKey)
-	}
-	SetNetworkNodesLastModified(node.Network)
-	if servercfg.IsDNSMode() {
-		err = SetDNS()
-	}
-	return err
-}
-
-// ShouldPeersUpdate - takes old node and sees if certain fields changing would trigger a peer update
-func ShouldPeersUpdate(currentNode *models.Node, newNode *models.Node) bool {
-	SetNodeDefaults(newNode)
-	// single comparison statements
-	if newNode.Endpoint != currentNode.Endpoint ||
-		newNode.LocalAddress != currentNode.LocalAddress ||
-		newNode.PublicKey != currentNode.PublicKey ||
-		newNode.Address != currentNode.Address ||
-		newNode.IsEgressGateway != currentNode.IsEgressGateway ||
-		newNode.IsIngressGateway != currentNode.IsIngressGateway ||
-		newNode.IsRelay != currentNode.IsRelay ||
-		newNode.UDPHolePunch != currentNode.UDPHolePunch ||
-		newNode.IsPending != currentNode.IsPending ||
-		len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) ||
-		len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
-		return true
-	}
-
-	// multi-comparison statements
-	if newNode.IsDualStack == "yes" {
-		if newNode.Address6 != currentNode.Address6 {
-			return true
-		}
-	}
-
-	if newNode.IsEgressGateway == "yes" {
-		if len(currentNode.EgressGatewayRanges) != len(newNode.EgressGatewayRanges) {
-			return true
-		}
-		for _, address := range newNode.EgressGatewayRanges {
-			if !StringSliceContains(currentNode.EgressGatewayRanges, address) {
-				return true
-			}
-		}
-	}
-
-	if newNode.IsRelay == "yes" {
-		if len(currentNode.RelayAddrs) != len(newNode.RelayAddrs) {
-			return true
-		}
-		for _, address := range newNode.RelayAddrs {
-			if !StringSliceContains(currentNode.RelayAddrs, address) {
-				return true
-			}
-		}
-	}
-
-	for _, address := range newNode.AllowedIPs {
-		if !StringSliceContains(currentNode.AllowedIPs, address) {
-			return true
-		}
-	}
-
-	return false
-}
-
 // GetAllNodes - returns all nodes in the DB
 func GetAllNodes() ([]models.Node, error) {
 	var nodes []models.Node
@@ -415,7 +296,6 @@ func SetNodeDefaults(node *models.Node) {
 }
 
 // GetRecordKey - get record key
-// depricated
 func GetRecordKey(id string, network string) (string, error) {
 	if id == "" || network == "" {
 		return "", errors.New("unable to get record key")
@@ -499,30 +379,6 @@ func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) {
 	return relay, errors.New("could not find relay for node " + relayedNodeAddr)
 }
 
-// GetNodeByIDorMacAddress - gets the node, if a mac address exists, but not id, then it should delete it and recreate in DB with new ID
-func GetNodeByIDorMacAddress(uuid string, macaddress string, network string) (models.Node, error) {
-	var node models.Node
-	var err error
-	node, err = GetNodeByID(uuid)
-	if err != nil && macaddress != "" && network != "" {
-		node, err = GetNodeByMacAddress(network, macaddress)
-		if err != nil {
-			return models.Node{}, err
-		}
-		err = DeleteNodeByMacAddress(&node, true) // remove node
-		if err != nil {
-			return models.Node{}, err
-		}
-		err = CreateNode(&node)
-		if err != nil {
-			return models.Node{}, err
-		}
-		logger.Log(2, "rewriting legacy node data; node now has id,", node.ID)
-		node.PullChanges = "yes"
-	}
-	return node, err
-}
-
 // GetNodeByID - get node by uuid, should have been set by create
 func GetNodeByID(uuid string) (models.Node, error) {
 	var record, err = database.FetchRecord(database.NODES_TABLE_NAME, uuid)
@@ -535,47 +391,3 @@ func GetNodeByID(uuid string) (models.Node, error) {
 	}
 	return node, nil
 }
-
-// GetDeletedNodeByID - get a deleted node
-func GetDeletedNodeByID(uuid string) (models.Node, error) {
-
-	var node models.Node
-
-	record, err := database.FetchRecord(database.DELETED_NODES_TABLE_NAME, uuid)
-	if err != nil {
-		return models.Node{}, err
-	}
-
-	if err = json.Unmarshal([]byte(record), &node); err != nil {
-		return models.Node{}, err
-	}
-
-	SetNodeDefaults(&node)
-
-	return node, nil
-}
-
-// GetNetworkServerNodeID - get network server node ID if exists
-func GetNetworkServerNodeID(network string) (string, error) {
-	var nodes, err = GetNetworkNodes(network)
-	if err != nil {
-		return "", err
-	}
-	for _, node := range nodes {
-		if node.IsServer == "yes" {
-			if servercfg.GetNodeID() != "" {
-				if servercfg.GetNodeID() == node.MacAddress {
-					if strings.Contains(node.ID, "###") {
-						DeleteNodeByMacAddress(&node, true)
-						logger.Log(1, "deleted legacy server node on network "+node.Network)
-						return "", errors.New("deleted legacy server node on network " + node.Network)
-					}
-					return node.ID, nil
-				}
-				continue
-			}
-			return node.ID, nil
-		}
-	}
-	return "", errors.New("could not find server node")
-}

+ 87 - 72
logic/server.go

@@ -17,7 +17,6 @@ import (
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 
-// == Public ==
 // == Join, Checkin, and Leave for Server ==
 
 // KUBERNETES_LISTEN_PORT - starting port for Kubernetes in order to use NodePort range
@@ -27,26 +26,23 @@ const KUBERNETES_LISTEN_PORT = 31821
 const KUBERNETES_SERVER_MTU = 1024
 
 // ServerJoin - responsible for joining a server to a network
-func ServerJoin(networkSettings *models.Network) error {
+func ServerJoin(networkSettings *models.Network, serverID string) error {
 
 	if networkSettings == nil || networkSettings.NetID == "" {
 		return errors.New("no network provided")
 	}
 
 	var err error
-
 	var node = &models.Node{
 		IsServer:     "yes",
 		DNSOn:        "no",
 		IsStatic:     "yes",
 		Name:         models.NODE_SERVER_NAME,
-		MacAddress:   servercfg.GetNodeID(),
-		ID:           "", // will be set to new uuid
+		MacAddress:   serverID,
 		UDPHolePunch: "no",
 		IsLocal:      networkSettings.IsLocal,
 		LocalRange:   networkSettings.LocalRange,
 	}
-
 	SetNodeDefaults(node)
 
 	if servercfg.GetPlatform() == "Kubernetes" {
@@ -120,7 +116,7 @@ func ServerJoin(networkSettings *models.Network) error {
 	if err = StorePrivKey(node.ID, privateKey); err != nil {
 		return err
 	}
-	if err = serverPush(node); err != nil {
+	if err = ServerPush(node); err != nil {
 		return err
 	}
 
@@ -138,12 +134,18 @@ func ServerJoin(networkSettings *models.Network) error {
 	return nil
 }
 
-// ServerUpdate - updates the server
-// replaces legacy Checkin code
-func ServerUpdate(serverNode *models.Node, shouldPeerUpdate bool) error {
-	var err = serverPull(serverNode, shouldPeerUpdate)
+// ServerCheckin - runs pulls and pushes for server
+func ServerCheckin(mac string, network string) error {
+	var serverNode = &models.Node{}
+	var currentNode, err = GetNode(mac, network)
+	if err != nil {
+		return err
+	}
+	serverNode = &currentNode
+
+	err = ServerPull(serverNode, false)
 	if isDeleteError(err) {
-		return DeleteNodeByID(serverNode, true)
+		return ServerLeave(mac, network)
 	} else if err != nil {
 		return err
 	}
@@ -153,7 +155,66 @@ func ServerUpdate(serverNode *models.Node, shouldPeerUpdate bool) error {
 		return errors.New("node has been removed")
 	}
 
-	return serverPush(serverNode)
+	return ServerPush(serverNode)
+}
+
+// ServerPull - pulls current config/peers for server
+func ServerPull(serverNode *models.Node, onErr bool) error {
+
+	var err error
+	if serverNode.IPForwarding == "yes" {
+		if err = setIPForwardingLinux(); err != nil {
+			return err
+		}
+	}
+	serverNode.OS = runtime.GOOS
+
+	if serverNode.PullChanges == "yes" || onErr {
+		// check for interface change
+		// checks if address is in use by another interface
+		var oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address)
+		if !isIfacePresent {
+			if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil {
+				logger.Log(1, "could not delete old interface", oldIfaceName)
+			}
+			logger.Log(1, "removed old interface", oldIfaceName)
+		}
+		serverNode.PullChanges = "no"
+		if err = setWGConfig(serverNode, false); err != nil {
+			return err
+		}
+		// handle server side update
+		if err = UpdateNode(serverNode, serverNode); err != nil {
+			return err
+		}
+	} else {
+		if err = setWGConfig(serverNode, true); err != nil {
+			if errors.Is(err, os.ErrNotExist) {
+				return ServerPull(serverNode, true)
+			} else {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+// ServerPush - pushes config changes for server checkins/join
+func ServerPush(serverNode *models.Node) error {
+	serverNode.OS = runtime.GOOS
+	serverNode.SetLastCheckIn()
+	return UpdateNode(serverNode, serverNode)
+}
+
+// ServerLeave - removes a server node
+func ServerLeave(mac string, network string) error {
+
+	var serverNode, err = GetNode(mac, network)
+	if err != nil {
+		return err
+	}
+	return DeleteNode(&serverNode, true)
 }
 
 /**
@@ -167,14 +228,17 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
 	var gateways []string
 	var peers []wgtypes.PeerConfig
 	var nodes []models.Node // fill above fields from server or client
-	var err error
 
-	nodes, err = GetPeers(serverNode)
+	var nodecfg, err = GetNode(serverNode.MacAddress, serverNode.Network)
+	if err != nil {
+		return nil, hasGateway, gateways, err
+	}
+	nodes, err = GetPeers(&nodecfg)
 	if err != nil {
 		return nil, hasGateway, gateways, err
 	}
 
-	keepalive := serverNode.PersistentKeepalive
+	keepalive := nodecfg.PersistentKeepalive
 	keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
 	if err != nil {
 		logger.Log(1, "Issue with format of keepalive duration value, Please view server config:", err.Error())
@@ -188,11 +252,11 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
 			return peers, hasGateway, gateways, err
 		}
 
-		if serverNode.PublicKey == node.PublicKey {
+		if nodecfg.PublicKey == node.PublicKey {
 			continue
 		}
-		if serverNode.Endpoint == node.Endpoint {
-			if serverNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
+		if nodecfg.Endpoint == node.Endpoint {
+			if nodecfg.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
 				node.Endpoint = node.LocalAddress
 			} else {
 				continue
@@ -237,8 +301,8 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
 					logger.Log(2, "egress IP range of", iprange, "overlaps with", node.Endpoint, ", omitting")
 					continue // skip adding egress range if overlaps with node's ip
 				}
-				if ipnet.Contains(net.ParseIP(serverNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node
-					logger.Log(2, "egress IP range of", iprange, "overlaps with", serverNode.LocalAddress, ", omitting")
+				if ipnet.Contains(net.ParseIP(nodecfg.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node
+					logger.Log(2, "egress IP range of", iprange, "overlaps with", nodecfg.LocalAddress, ", omitting")
 					continue // skip adding egress range if overlaps with node's local ip
 				}
 				gateways = append(gateways, iprange)
@@ -284,7 +348,7 @@ func GetServerExtPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, error) {
 	var err error
 	var tempPeers []models.ExtPeersResponse
 
-	tempPeers, err = GetExtPeersList(serverNode)
+	tempPeers, err = GetExtPeersList(serverNode.MacAddress, serverNode.Network)
 	if err != nil {
 		return nil, err
 	}
@@ -355,7 +419,7 @@ func checkNodeActions(node *models.Node) string {
 		}
 	}
 	if node.Action == models.NODE_DELETE {
-		err := DeleteNodeByID(node, true)
+		err := ServerLeave(node.MacAddress, node.Network)
 		if err != nil {
 			logger.Log(1, "error deleting locally:", err.Error())
 		}
@@ -364,49 +428,6 @@ func checkNodeActions(node *models.Node) string {
 	return ""
 }
 
-// == Private ==
-
-func serverPull(serverNode *models.Node, onErr bool) error {
-
-	var err error
-	if serverNode.IPForwarding == "yes" {
-		if err = setIPForwardingLinux(); err != nil {
-			return err
-		}
-	}
-	serverNode.OS = runtime.GOOS
-
-	if serverNode.PullChanges == "yes" || onErr {
-		// check for interface change
-		// checks if address is in use by another interface
-		var oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address)
-		if !isIfacePresent {
-			if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil {
-				logger.Log(1, "could not delete old interface", oldIfaceName)
-			}
-			logger.Log(1, "removed old interface", oldIfaceName)
-		}
-		serverNode.PullChanges = "no"
-		if err = setWGConfig(serverNode, false); err != nil {
-			return err
-		}
-		// handle server side update
-		if err = UpdateNode(serverNode, serverNode); err != nil {
-			return err
-		}
-	} else {
-		if err = setWGConfig(serverNode, true); err != nil {
-			if errors.Is(err, os.ErrNotExist) {
-				return serverPull(serverNode, true)
-			} else {
-				return err
-			}
-		}
-	}
-
-	return nil
-}
-
 func getServerLocalIP(networkSettings *models.Network) (string, error) {
 
 	var networkCIDR = networkSettings.LocalRange
@@ -428,9 +449,3 @@ func getServerLocalIP(networkSettings *models.Network) (string, error) {
 	}
 	return "", errors.New("could not find a local ip for server")
 }
-
-func serverPush(serverNode *models.Node) error {
-	serverNode.OS = runtime.GOOS
-	serverNode.SetLastCheckIn()
-	return UpdateNode(serverNode, serverNode)
-}

+ 91 - 94
logic/util.go

@@ -4,19 +4,18 @@ package logic
 import (
 	"encoding/base64"
 	"encoding/json"
-	"fmt"
 	"math/rand"
-	"net"
-	"os"
 	"strconv"
 	"strings"
 	"time"
 
+	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/crypto/bcrypt"
 )
 
 // IsBase64 - checks if a string is in base64 format
@@ -32,45 +31,24 @@ func CheckEndpoint(endpoint string) bool {
 	return len(endpointarr) == 2
 }
 
-// FileExists - checks if local file exists
-func FileExists(f string) bool {
-	info, err := os.Stat(f)
-	if os.IsNotExist(err) {
-		return false
-	}
-	return !info.IsDir()
-}
-
-// IsAddressInCIDR - util to see if an address is in a cidr or not
-func IsAddressInCIDR(address, cidr string) bool {
-	var _, currentCIDR, cidrErr = net.ParseCIDR(cidr)
-	if cidrErr != nil {
-		return false
-	}
-	var addrParts = strings.Split(address, ".")
-	var addrPartLength = len(addrParts)
-	if addrPartLength != 4 {
-		return false
-	} else {
-		if addrParts[addrPartLength-1] == "0" ||
-			addrParts[addrPartLength-1] == "255" {
-			return false
+// SetNetworkServerPeers - sets the network server peers of a given node
+func SetNetworkServerPeers(node *models.Node) {
+	if currentPeersList, err := GetSystemPeers(node); err == nil {
+		if database.SetPeers(currentPeersList, node.Network) {
+			logger.Log(1, "set new peers on network", node.Network)
 		}
+	} else {
+		logger.Log(1, "could not set peers on network", node.Network, ":", err.Error())
 	}
-	ip, _, err := net.ParseCIDR(fmt.Sprintf("%s/32", address))
-	if err != nil {
-		return false
-	}
-	return currentCIDR.Contains(ip)
 }
 
-// DeleteNodeByMacAddress - deletes a node from database or moves into delete nodes table
-func DeleteNodeByMacAddress(node *models.Node, exterminate bool) error {
+// DeleteNode - deletes a node from database or moves into delete nodes table
+func DeleteNode(node *models.Node, exterminate bool) error {
 	var err error
 	var key = node.ID
 	if !exterminate {
 		args := strings.Split(key, "###")
-		node, err := GetNodeByMacAddress(args[0], args[1])
+		node, err := GetNode(args[0], args[1])
 		if err != nil {
 			return err
 		}
@@ -97,6 +75,66 @@ func DeleteNodeByMacAddress(node *models.Node, exterminate bool) error {
 	return removeLocalServer(node)
 }
 
+// CreateNode - creates a node in database
+func CreateNode(node *models.Node) error {
+
+	//encrypt that password so we never see it
+	hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
+	if err != nil {
+		return err
+	}
+	//set password to encrypted password
+	node.Password = string(hash)
+	if node.Name == models.NODE_SERVER_NAME {
+		node.IsServer = "yes"
+	}
+	if node.DNSOn == "" {
+		if servercfg.IsDNSMode() {
+			node.DNSOn = "yes"
+		} else {
+			node.DNSOn = "no"
+		}
+	}
+	SetNodeDefaults(node)
+	node.Address, err = UniqueAddress(node.Network)
+	if err != nil {
+		return err
+	}
+	node.Address6, err = UniqueAddress6(node.Network)
+	if err != nil {
+		return err
+	}
+	//Create a JWT for the node
+	tokenString, _ := CreateJWT(node.MacAddress, node.Network)
+	if tokenString == "" {
+		//returnErrorResponse(w, r, errorResponse)
+		return err
+	}
+	err = ValidateNode(node, false)
+	if err != nil {
+		return err
+	}
+
+	node.ID = uuid.NewString()
+
+	nodebytes, err := json.Marshal(&node)
+	if err != nil {
+		return err
+	}
+	err = database.Insert(node.ID, string(nodebytes), database.NODES_TABLE_NAME)
+	if err != nil {
+		return err
+	}
+	if node.IsPending != "yes" {
+		DecrimentKey(node.Network, node.AccessKey)
+	}
+	SetNetworkNodesLastModified(node.Network)
+	if servercfg.IsDNSMode() {
+		err = SetDNS()
+	}
+	return err
+}
+
 // SetNetworkNodesLastModified - sets the network nodes last modified
 func SetNetworkNodesLastModified(networkName string) error {
 
@@ -118,56 +156,28 @@ func SetNetworkNodesLastModified(networkName string) error {
 	return nil
 }
 
-// // GetNode - fetches a node from database
-// func GetNode(macaddress string, network string) (models.Node, error) {
-// 	var node models.Node
-
-// 	key, err := GetRecordKey(macaddress, network)
-// 	if err != nil {
-// 		return node, err
-// 	}
-// 	data, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
-// 	if err != nil {
-// 		if data == "" {
-// 			data, _ = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key)
-// 			err = json.Unmarshal([]byte(data), &node)
-// 		}
-// 		return node, err
-// 	}
-// 	if err = json.Unmarshal([]byte(data), &node); err != nil {
-// 		return node, err
-// 	}
-// 	SetNodeDefaults(&node)
-
-// 	return node, err
-// }
-
-// DeleteNodeByID - deletes a node from database or moves into delete nodes table
-func DeleteNodeByID(node *models.Node, exterminate bool) error {
-	var err error
-	var key = node.ID
-	if !exterminate {
-		node.Action = models.NODE_DELETE
-		nodedata, err := json.Marshal(&node)
-		if err != nil {
-			return err
-		}
-		err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME)
-		if err != nil {
-			return err
-		}
-	} else {
-		if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil {
-			logger.Log(2, err.Error())
-		}
+// GetNode - fetches a node from database
+func GetNode(macaddress string, network string) (models.Node, error) {
+	var node models.Node
+
+	key, err := GetRecordKey(macaddress, network)
+	if err != nil {
+		return node, err
 	}
-	if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
-		return err
+	data, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
+	if err != nil {
+		if data == "" {
+			data, _ = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key)
+			err = json.Unmarshal([]byte(data), &node)
+		}
+		return node, err
 	}
-	if servercfg.IsDNSMode() {
-		SetDNS()
+	if err = json.Unmarshal([]byte(data), &node); err != nil {
+		return node, err
 	}
-	return removeLocalServer(node)
+	SetNodeDefaults(&node)
+
+	return node, err
 }
 
 // GetNodePeers - fetches peers for a given node
@@ -358,16 +368,3 @@ func StringSliceContains(slice []string, item string) bool {
 	}
 	return false
 }
-
-// == private ==
-
-// sets the network server peers of a given node
-func setNetworkServerPeers(serverNode *models.Node) {
-	if currentPeersList, err := getSystemPeers(serverNode); err == nil {
-		if database.SetPeers(currentPeersList, serverNode.Network) {
-			logger.Log(1, "set new peers on network", serverNode.Network)
-		}
-	} else {
-		logger.Log(1, "could not set peers on network", serverNode.Network, ":", err.Error())
-	}
-}

+ 9 - 44
models/node.go

@@ -23,9 +23,9 @@ const NODE_NOOP = "noop"
 var seededRand *rand.Rand = rand.New(
 	rand.NewSource(time.Now().UnixNano()))
 
-// Node - struct for node model
+// node struct
 type Node struct {
-	ID                  string   `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5"`
+	ID                  string   `json:"id,omitempty" bson:"id,omitempty"`
 	Address             string   `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
 	Address6            string   `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
 	LocalAddress        string   `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
@@ -46,7 +46,7 @@ type Node struct {
 	ExpirationDateTime  int64    `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
 	LastPeerUpdate      int64    `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
 	LastCheckIn         int64    `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
-	MacAddress          string   `json:"macaddress" bson:"macaddress" yaml:"macaddress"`
+	MacAddress          string   `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"required,min=5,macaddress_unique"`
 	// checkin interval is depreciated at the network level. Set on server with CHECKIN_INTERVAL
 	CheckInInterval     int32    `json:"checkininterval" bson:"checkininterval" yaml:"checkininterval"`
 	Password            string   `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
@@ -72,8 +72,6 @@ type Node struct {
 	IPForwarding        string   `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"`
 	OS                  string   `json:"os" bson:"os" yaml:"os"`
 	MTU                 int32    `json:"mtu" bson:"mtu" yaml:"mtu"`
-	Version             string   `json:"version" bson:"version" yaml:"version"`
-	ExcludedAddrs       []string `json:"excludedaddrs" bson:"excludedaddrs" yaml:"excludedaddrs"`
 }
 
 // NodesArray - used for node sorting
@@ -108,91 +106,78 @@ func (node *Node) SetDefaulIsPending() {
 	}
 }
 
-// Node.SetDefaultIsRelayed - set default is relayed
 func (node *Node) SetDefaultIsRelayed() {
 	if node.IsRelayed == "" {
 		node.IsRelayed = "no"
 	}
 }
 
-// Node.SetDefaultIsRelay - set default isrelay
 func (node *Node) SetDefaultIsRelay() {
 	if node.IsRelay == "" {
 		node.IsRelay = "no"
 	}
 }
 
-// Node.SetDefaultEgressGateway - sets default egress gateway status
 func (node *Node) SetDefaultEgressGateway() {
 	if node.IsEgressGateway == "" {
 		node.IsEgressGateway = "no"
 	}
 }
 
-// Node.SetDefaultIngressGateway - sets default ingress gateway status
 func (node *Node) SetDefaultIngressGateway() {
 	if node.IsIngressGateway == "" {
 		node.IsIngressGateway = "no"
 	}
 }
 
-// Node.SetDefaultAction - sets default action status
 func (node *Node) SetDefaultAction() {
 	if node.Action == "" {
 		node.Action = NODE_NOOP
 	}
 }
 
-// Node.SetRoamingDefault - sets default roaming status
 func (node *Node) SetRoamingDefault() {
 	if node.Roaming == "" {
 		node.Roaming = "yes"
 	}
 }
 
-// Node.SetPullChangesDefault - sets default pull changes status
 func (node *Node) SetPullChangesDefault() {
 	if node.PullChanges == "" {
 		node.PullChanges = "no"
 	}
 }
 
-// Node.SetIPForwardingDefault - set ip forwarding default
 func (node *Node) SetIPForwardingDefault() {
 	if node.IPForwarding == "" {
 		node.IPForwarding = "yes"
 	}
 }
 
-// Node.SetIsLocalDefault - set is local default
 func (node *Node) SetIsLocalDefault() {
 	if node.IsLocal == "" {
 		node.IsLocal = "no"
 	}
 }
 
-// Node.SetDNSOnDefault - sets dns on default
 func (node *Node) SetDNSOnDefault() {
 	if node.DNSOn == "" {
 		node.DNSOn = "yes"
 	}
 }
 
-// Node.SetIsDualStackDefault - set is dual stack default status
 func (node *Node) SetIsDualStackDefault() {
 	if node.IsDualStack == "" {
 		node.IsDualStack = "no"
 	}
 }
 
-// Node.SetIsServerDefault - sets node isserver default
 func (node *Node) SetIsServerDefault() {
 	if node.IsServer != "yes" {
 		node.IsServer = "no"
 	}
 }
 
-// Node.SetIsStaticDefault - set is static default
 func (node *Node) SetIsStaticDefault() {
 	if node.IsServer == "yes" {
 		node.IsStatic = "yes"
@@ -201,44 +186,32 @@ func (node *Node) SetIsStaticDefault() {
 	}
 }
 
-// Node.SetLastModified - set last modified initial time
 func (node *Node) SetLastModified() {
 	node.LastModified = time.Now().Unix()
 }
 
-// Node.SetLastCheckIn - time.Now().Unix()
 func (node *Node) SetLastCheckIn() {
 	node.LastCheckIn = time.Now().Unix()
 }
 
-// Node.SetLastPeerUpdate - sets last peer update time
 func (node *Node) SetLastPeerUpdate() {
 	node.LastPeerUpdate = time.Now().Unix()
 }
 
-// Node.SetExpirationDateTime - sets node expiry time
 func (node *Node) SetExpirationDateTime() {
 	node.ExpirationDateTime = time.Now().Unix() + TEN_YEARS_IN_SECONDS
 }
 
-// Node.SetDefaultName - sets a random name to node
 func (node *Node) SetDefaultName() {
 	if node.Name == "" {
 		node.Name = GenerateNodeName()
 	}
 }
 
-// Node.SetDefaultExcludedAddrs - sets ExcludedAddrs to empty array if nil
-func (node *Node) SetDefaultExcludedAddrs() {
-	if node.ExcludedAddrs == nil {
-		node.ExcludedAddrs = make([]string, 0)
-	}
-}
-
-// Node.Fill - fills other node data into calling node data if not set on calling node
 func (newNode *Node) Fill(currentNode *Node) {
-	newNode.ID = currentNode.ID
-
+	if newNode.ID == "" {
+		newNode.ID = currentNode.ID
+	}
 	if newNode.Address == "" && newNode.IsStatic != "yes" {
 		newNode.Address = currentNode.Address
 	}
@@ -381,15 +354,8 @@ func (newNode *Node) Fill(currentNode *Node) {
 	if newNode.IsRelayed == "" {
 		newNode.IsRelayed = currentNode.IsRelayed
 	}
-	if newNode.Version == "" {
-		newNode.Version = currentNode.Version
-	}
-	if newNode.ExcludedAddrs == nil || len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) {
-		newNode.ExcludedAddrs = currentNode.ExcludedAddrs
-	}
 }
 
-// StringWithCharset - returns random string inside defined charset
 func StringWithCharset(length int, charset string) string {
 	b := make([]byte, length)
 	for i := range b {
@@ -398,14 +364,13 @@ func StringWithCharset(length int, charset string) string {
 	return string(b)
 }
 
-// IsIpv4Net - check for valid IPv4 address
-// Note: We dont handle IPv6 AT ALL!!!!! This definitely is needed at some point
-// But for iteration 1, lets just stick to IPv4. Keep it simple stupid.
+//Check for valid IPv4 address
+//Note: We dont handle IPv6 AT ALL!!!!! This definitely is needed at some point
+//But for iteration 1, lets just stick to IPv4. Keep it simple stupid.
 func IsIpv4Net(host string) bool {
 	return net.ParseIP(host) != nil
 }
 
-// Node.NameInNodeCharset - returns if name is in charset below or not
 func (node *Node) NameInNodeCharSet() bool {
 
 	charset := "abcdefghijklmnopqrstuvwxyz1234567890-"