mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-05 16:57:51 +08:00
refactored nodes model
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
@@ -70,143 +69,6 @@ func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersRe
|
|||||||
return peers, err
|
return peers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateNodeCreate(networkName string, node models.Node) error {
|
|
||||||
v := validator.New()
|
|
||||||
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
|
|
||||||
isFieldUnique, _ := functions.IsMacAddressUnique(node.MacAddress, networkName)
|
|
||||||
return isFieldUnique
|
|
||||||
})
|
|
||||||
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
|
||||||
_, err := node.GetNetwork()
|
|
||||||
return err == nil
|
|
||||||
})
|
|
||||||
_ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {
|
|
||||||
isgood := functions.NameInNodeCharSet(node.Name)
|
|
||||||
return isgood
|
|
||||||
})
|
|
||||||
err := v.Struct(node)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
for _, e := range err.(validator.ValidationErrors) {
|
|
||||||
fmt.Println(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateNodeUpdate(networkName string, node models.NodeUpdate) error {
|
|
||||||
v := validator.New()
|
|
||||||
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
|
||||||
_, err := functions.GetParentNetwork(networkName)
|
|
||||||
return err == nil
|
|
||||||
})
|
|
||||||
_ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {
|
|
||||||
isgood := functions.NameInNodeCharSet(node.Name)
|
|
||||||
return isgood
|
|
||||||
})
|
|
||||||
err := v.Struct(node)
|
|
||||||
if err != nil {
|
|
||||||
for _, e := range err.(validator.ValidationErrors) {
|
|
||||||
fmt.Println(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateNode(nodechange models.NodeUpdate, node models.Node) (models.Node, error) {
|
|
||||||
//Question: Is there a better way of doing this than a bunch of "if" statements? probably...
|
|
||||||
//Eventually, lets have a better way to check if any of the fields are filled out...
|
|
||||||
oldkey, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
|
|
||||||
notifynetwork := false
|
|
||||||
|
|
||||||
if nodechange.Address != "" {
|
|
||||||
node.Address = nodechange.Address
|
|
||||||
notifynetwork = true
|
|
||||||
}
|
|
||||||
if nodechange.Address6 != "" {
|
|
||||||
node.Address6 = nodechange.Address6
|
|
||||||
notifynetwork = true
|
|
||||||
}
|
|
||||||
if nodechange.Name != "" {
|
|
||||||
node.Name = nodechange.Name
|
|
||||||
}
|
|
||||||
if nodechange.LocalAddress != "" {
|
|
||||||
node.LocalAddress = nodechange.LocalAddress
|
|
||||||
}
|
|
||||||
if nodechange.ListenPort != 0 {
|
|
||||||
node.ListenPort = nodechange.ListenPort
|
|
||||||
}
|
|
||||||
if nodechange.ExpirationDateTime != 0 {
|
|
||||||
node.ExpirationDateTime = nodechange.ExpirationDateTime
|
|
||||||
}
|
|
||||||
if nodechange.PostDown != "" {
|
|
||||||
node.PostDown = nodechange.PostDown
|
|
||||||
}
|
|
||||||
if nodechange.Interface != "" {
|
|
||||||
node.Interface = nodechange.Interface
|
|
||||||
}
|
|
||||||
if nodechange.PostUp != "" {
|
|
||||||
node.PostUp = nodechange.PostUp
|
|
||||||
}
|
|
||||||
if nodechange.AccessKey != "" {
|
|
||||||
node.AccessKey = nodechange.AccessKey
|
|
||||||
}
|
|
||||||
if nodechange.Endpoint != "" {
|
|
||||||
node.Endpoint = nodechange.Endpoint
|
|
||||||
notifynetwork = true
|
|
||||||
}
|
|
||||||
if nodechange.SaveConfig != nil {
|
|
||||||
node.SaveConfig = nodechange.SaveConfig
|
|
||||||
}
|
|
||||||
if nodechange.PersistentKeepalive != 0 {
|
|
||||||
node.PersistentKeepalive = nodechange.PersistentKeepalive
|
|
||||||
}
|
|
||||||
if nodechange.Password != "" {
|
|
||||||
err := bcrypt.CompareHashAndPassword([]byte(nodechange.Password), []byte(node.Password))
|
|
||||||
if err != nil && nodechange.Password != node.Password {
|
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(nodechange.Password), 5)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
nodechange.Password = string(hash)
|
|
||||||
node.Password = nodechange.Password
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if nodechange.MacAddress != "" {
|
|
||||||
node.MacAddress = nodechange.MacAddress
|
|
||||||
}
|
|
||||||
if nodechange.PublicKey != "" {
|
|
||||||
node.PublicKey = nodechange.PublicKey
|
|
||||||
node.KeyUpdateTimeStamp = time.Now().Unix()
|
|
||||||
notifynetwork = true
|
|
||||||
}
|
|
||||||
newkey, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
if oldkey != newkey {
|
|
||||||
if err := database.DeleteRecord(database.NODES_TABLE_NAME, oldkey); err != nil {
|
|
||||||
return models.Node{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value, err := json.Marshal(&node)
|
|
||||||
if err != nil {
|
|
||||||
return models.Node{}, err
|
|
||||||
}
|
|
||||||
err = database.Insert(newkey, string(value), database.NODES_TABLE_NAME)
|
|
||||||
if notifynetwork {
|
|
||||||
err = SetNetworkNodesLastModified(node.Network)
|
|
||||||
}
|
|
||||||
if servercfg.IsDNSMode() {
|
|
||||||
err = SetDNS()
|
|
||||||
}
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteNode(macaddress string, network string) error {
|
func DeleteNode(macaddress string, network string) error {
|
||||||
|
|
||||||
key, err := functions.GetRecordKey(macaddress, network)
|
key, err := functions.GetRecordKey(macaddress, network)
|
||||||
@@ -270,7 +132,7 @@ func GetIntClient(clientid string) (models.IntClient, error) {
|
|||||||
|
|
||||||
func CreateNode(node models.Node, networkName string) (models.Node, error) {
|
func CreateNode(node models.Node, networkName string) (models.Node, error) {
|
||||||
|
|
||||||
//encrypt that password so we never see it again
|
//encrypt that password so we never see it
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
|
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -281,37 +143,17 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
|
|||||||
|
|
||||||
node.Network = networkName
|
node.Network = networkName
|
||||||
|
|
||||||
//node.SetDefaults()
|
|
||||||
//Umm, why am I doing this again?
|
|
||||||
//TODO: Why am I using a local function instead of the struct function? I really dont know.
|
|
||||||
//I think I thought it didn't work but uhhh...idk
|
|
||||||
node.SetDefaults()
|
node.SetDefaults()
|
||||||
|
|
||||||
//Another DB call here...Inefficient
|
|
||||||
//Anyways, this scrolls through all the IP Addresses in the network range and checks against nodes
|
|
||||||
//until one is open and then returns it
|
|
||||||
node.Address, err = functions.UniqueAddress(networkName)
|
node.Address, err = functions.UniqueAddress(networkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
node.Address6, err = functions.UniqueAddress6(networkName)
|
node.Address6, err = functions.UniqueAddress6(networkName)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//IDK why these aren't a part of "set defaults. Pretty dumb.
|
|
||||||
//TODO: This is dumb. Consolidate and fix.
|
|
||||||
node.SetLastModified()
|
|
||||||
node.SetDefaultName()
|
|
||||||
node.SetLastCheckIn()
|
|
||||||
node.SetLastPeerUpdate()
|
|
||||||
node.KeyUpdateTimeStamp = time.Now().Unix()
|
|
||||||
|
|
||||||
//Create a JWT for the node
|
//Create a JWT for the node
|
||||||
tokenString, _ := functions.CreateJWT(node.MacAddress, networkName)
|
tokenString, _ := functions.CreateJWT(node.MacAddress, networkName)
|
||||||
|
|
||||||
if tokenString == "" {
|
if tokenString == "" {
|
||||||
//returnErrorResponse(w, r, errorResponse)
|
//returnErrorResponse(w, r, errorResponse)
|
||||||
return node, err
|
return node, err
|
||||||
@@ -324,18 +166,13 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = database.Insert(key, string(nodebytes), database.NODES_TABLE_NAME)
|
err = database.Insert(key, string(nodebytes), database.NODES_TABLE_NAME)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
//return response for if node is pending
|
|
||||||
if !node.IsPending {
|
if !node.IsPending {
|
||||||
|
|
||||||
functions.DecrimentKey(node.Network, node.AccessKey)
|
functions.DecrimentKey(node.Network, node.AccessKey)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetNetworkNodesLastModified(node.Network)
|
SetNetworkNodesLastModified(node.Network)
|
||||||
if servercfg.IsDNSMode() {
|
if servercfg.IsDNSMode() {
|
||||||
err = SetDNS()
|
err = SetDNS()
|
||||||
|
@@ -275,14 +275,12 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var newNetwork models.Network
|
var newNetwork models.Network
|
||||||
err = json.NewDecoder(r.Body).Decode(&newNetwork)
|
err = json.NewDecoder(r.Body).Decode(&newNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rangeupdate, localrangeupdate, err := network.Update(&newNetwork)
|
rangeupdate, localrangeupdate, err := network.Update(&newNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
@@ -405,7 +403,7 @@ func CreateNetwork(network models.Network) error {
|
|||||||
network.SetNetworkLastModified()
|
network.SetNetworkLastModified()
|
||||||
network.KeyUpdateTimeStamp = time.Now().Unix()
|
network.KeyUpdateTimeStamp = time.Now().Unix()
|
||||||
|
|
||||||
err := network.Validate()
|
err := network.Validate(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//returnErrorResponse(w, r, formatError(err, "badrequest"))
|
//returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
return err
|
return err
|
||||||
|
@@ -139,7 +139,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
|
|||||||
ListenPort: data.GetListenport(),
|
ListenPort: data.GetListenport(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ValidateNodeCreate(node.Network, node)
|
err := node.Validate(false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// return internal gRPC error to be handled later
|
// return internal gRPC error to be handled later
|
||||||
@@ -257,7 +257,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
|
|||||||
// Get the node data from the request
|
// Get the node data from the request
|
||||||
data := req.GetNode()
|
data := req.GetNode()
|
||||||
// Now we have to convert this into a NodeItem type to convert into BSON
|
// Now we have to convert this into a NodeItem type to convert into BSON
|
||||||
nodechange := models.NodeUpdate{
|
newnode := models.Node{
|
||||||
// ID: primitive.NilObjectID,
|
// ID: primitive.NilObjectID,
|
||||||
MacAddress: data.GetMacaddress(),
|
MacAddress: data.GetMacaddress(),
|
||||||
Name: data.GetName(),
|
Name: data.GetName(),
|
||||||
@@ -277,11 +277,11 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the Id string to a MongoDB ObjectId
|
// Convert the Id string to a MongoDB ObjectId
|
||||||
macaddress := nodechange.MacAddress
|
macaddress := newnode.MacAddress
|
||||||
networkName := nodechange.Network
|
networkName := newnode.Network
|
||||||
network, _ := functions.GetParentNetwork(networkName)
|
network, _ := functions.GetParentNetwork(networkName)
|
||||||
|
|
||||||
err := ValidateNodeUpdate(networkName, nodechange)
|
err := newnode.Validate(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
newnode, err := UpdateNode(nodechange, node)
|
err = node.Update(&newnode)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(
|
return nil, status.Errorf(
|
||||||
|
@@ -3,6 +3,7 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -12,6 +13,7 @@ import (
|
|||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -310,23 +312,34 @@ func GetNetworkNodes(network string) ([]models.Node, error) {
|
|||||||
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
|
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
|
||||||
func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
nodes, err := getUsersNodes(r.Header.Get("user"))
|
user, err := functions.GetUser(r.Header.Get("user"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var nodes []models.Node
|
||||||
|
if user.IsAdmin {
|
||||||
|
nodes, err = models.GetAllNodes()
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nodes, err = getUsersNodes(user)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
//Return all the nodes in JSON format
|
//Return all the nodes in JSON format
|
||||||
functions.PrintUserLog(r.Header.Get("user"), "fetched nodes", 2)
|
functions.PrintUserLog(r.Header.Get("user"), "fetched nodes", 2)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(nodes)
|
json.NewEncoder(w).Encode(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUsersNodes(username string) ([]models.Node, error) {
|
func getUsersNodes(user models.User) ([]models.Node, error) {
|
||||||
var nodes []models.Node
|
var nodes []models.Node
|
||||||
user, err := functions.GetUser(username)
|
var err error
|
||||||
if err != nil {
|
|
||||||
return nodes, err
|
|
||||||
}
|
|
||||||
for _, networkName := range user.Networks {
|
for _, networkName := range user.Networks {
|
||||||
tmpNodes, err := GetNetworkNodes(networkName)
|
tmpNodes, err := GetNetworkNodes(networkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -416,9 +429,6 @@ func getLastModified(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(network.NodesLastModified)
|
json.NewEncoder(w).Encode(network.NodesLastModified)
|
||||||
}
|
}
|
||||||
|
|
||||||
//This one's a doozy
|
|
||||||
//To create a node
|
|
||||||
//Must have valid key and be unique
|
|
||||||
func createNode(w http.ResponseWriter, r *http.Request) {
|
func createNode(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
@@ -427,12 +437,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
var errorResponse = models.ErrorResponse{
|
var errorResponse = models.ErrorResponse{
|
||||||
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
||||||
}
|
}
|
||||||
|
|
||||||
networkName := params["network"]
|
networkName := params["network"]
|
||||||
|
|
||||||
//Check if network exists first
|
|
||||||
//TODO: This is inefficient. Let's find a better way.
|
|
||||||
//Just a few rows down we grab the network anyway
|
|
||||||
networkexists, err := functions.NetworkExists(networkName)
|
networkexists, err := functions.NetworkExists(networkName)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -481,7 +486,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ValidateNodeCreate(networkName, node)
|
err = node.Validate(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
@@ -759,16 +764,11 @@ func DeleteIngressGateway(network, macaddress string) (models.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateNode(w http.ResponseWriter, r *http.Request) {
|
func updateNode(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("update reached.")
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
//Get id from parameters
|
|
||||||
//id, _ := primitive.ObjectIDFromHex(params["id"])
|
|
||||||
|
|
||||||
var node models.Node
|
var node models.Node
|
||||||
log.Println("Called", params["network"], params["macaddress"])
|
|
||||||
//start here
|
//start here
|
||||||
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -776,29 +776,32 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodechange models.NodeUpdate
|
var newNode models.Node
|
||||||
|
|
||||||
// we decode our body request params
|
// we decode our body request params
|
||||||
_ = json.NewDecoder(r.Body).Decode(&nodechange)
|
err = json.NewDecoder(r.Body).Decode(&newNode)
|
||||||
if nodechange.Network == "" {
|
|
||||||
nodechange.Network = node.Network
|
|
||||||
}
|
|
||||||
if nodechange.MacAddress == "" {
|
|
||||||
nodechange.MacAddress = node.MacAddress
|
|
||||||
}
|
|
||||||
err = ValidateNodeUpdate(params["network"], nodechange)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
err = node.Update(&newNode)
|
||||||
node, err = UpdateNode(nodechange, node)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = SetNetworkNodesLastModified(node.Network); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if servercfg.IsDNSMode() {
|
||||||
|
err = SetDNS()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
functions.PrintUserLog(r.Header.Get("user"), "updated node "+node.MacAddress+" on network "+node.Network, 1)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(newNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete a node
|
//Delete a node
|
||||||
|
@@ -732,23 +732,3 @@ func Inc(ip net.IP) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllNodes() ([]models.Node, error) {
|
|
||||||
var nodes []models.Node
|
|
||||||
|
|
||||||
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
return []models.Node{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, value := range collection {
|
|
||||||
var node models.Node
|
|
||||||
if err := json.Unmarshal([]byte(value), &node); err != nil {
|
|
||||||
return []models.Node{}, err
|
|
||||||
}
|
|
||||||
// add node to our array
|
|
||||||
nodes = append(nodes, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodes, nil
|
|
||||||
}
|
|
||||||
|
@@ -3,6 +3,8 @@ package models
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -26,49 +28,56 @@ type Network struct {
|
|||||||
DefaultPostDown string `json:"defaultpostdown" bson:"defaultpostdown"`
|
DefaultPostDown string `json:"defaultpostdown" bson:"defaultpostdown"`
|
||||||
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
|
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
|
||||||
DefaultKeepalive int32 `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"`
|
DefaultKeepalive int32 `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"`
|
||||||
DefaultSaveConfig string `json:"defaultsaveconfig" bson:"defaultsaveconfig" validate:"regexp=^(yes|no)$"`
|
DefaultSaveConfig string `json:"defaultsaveconfig" bson:"defaultsaveconfig" validate:"checkyesorno"`
|
||||||
AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"`
|
AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"`
|
||||||
AllowManualSignUp string `json:"allowmanualsignup" bson:"allowmanualsignup" validate:"regexp=^(yes|no)$"`
|
AllowManualSignUp string `json:"allowmanualsignup" bson:"allowmanualsignup" validate:"checkyesorno"`
|
||||||
IsLocal string `json:"islocal" bson:"islocal" validate:"regexp=^(yes|no)$"`
|
IsLocal string `json:"islocal" bson:"islocal" validate:"checkyesorno"`
|
||||||
IsDualStack string `json:"isdualstack" bson:"isdualstack" validate:"regexp=^(yes|no)$"`
|
IsDualStack string `json:"isdualstack" bson:"isdualstack" validate:"checkyesorno"`
|
||||||
IsIPv4 string `json:"isipv4" bson:"isipv4" validate:"regexp=^(yes|no)$"`
|
IsIPv4 string `json:"isipv4" bson:"isipv4" validate:"checkyesorno"`
|
||||||
IsIPv6 string `json:"isipv6" bson:"isipv6" validate:"regexp=^(yes|no)$"`
|
IsIPv6 string `json:"isipv6" bson:"isipv6" validate:"checkyesorno"`
|
||||||
IsGRPCHub string `json:"isgrpchub" bson:"isgrpchub" validate:"regexp=^(yes|no)$"`
|
IsGRPCHub string `json:"isgrpchub" bson:"isgrpchub" validate:"checkyesorno"`
|
||||||
LocalRange string `json:"localrange" bson:"localrange" validate:"omitempty,cidr"`
|
LocalRange string `json:"localrange" bson:"localrange" validate:"omitempty,cidr"`
|
||||||
DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"`
|
DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"`
|
||||||
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"regexp=^(yes|no)$"`
|
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SaveData struct { // put sensitive fields here
|
type SaveData struct { // put sensitive fields here
|
||||||
NetID string `json:"netid" bson:"netid" validate:"required,min=1,max=12,netid_valid"`
|
NetID string `json:"netid" bson:"netid" validate:"required,min=1,max=12,netid_valid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const STRING_FIELD_TYPE = "string"
|
||||||
|
const INT64_FIELD_TYPE = "int64"
|
||||||
|
const INT32_FIELD_TYPE = "int32"
|
||||||
|
const ACCESS_KEY_TYPE = "[]AccessKey"
|
||||||
|
|
||||||
|
var FIELD_TYPES = []string{STRING_FIELD_TYPE, INT64_FIELD_TYPE, INT32_FIELD_TYPE, ACCESS_KEY_TYPE}
|
||||||
|
|
||||||
var FIELDS = map[string][]string{
|
var FIELDS = map[string][]string{
|
||||||
// "id": {"ID", "string"},
|
// "id": {"ID", "string"},
|
||||||
"addressrange": {"AddressRange", "string"},
|
"addressrange": {"AddressRange", STRING_FIELD_TYPE},
|
||||||
"addressrange6": {"AddressRange6", "string"},
|
"addressrange6": {"AddressRange6", STRING_FIELD_TYPE},
|
||||||
"displayname": {"DisplayName", "string"},
|
"displayname": {"DisplayName", STRING_FIELD_TYPE},
|
||||||
"netid": {"NetID", "string"},
|
"netid": {"NetID", STRING_FIELD_TYPE},
|
||||||
"nodeslastmodified": {"NodesLastModified", "int64"},
|
"nodeslastmodified": {"NodesLastModified", INT64_FIELD_TYPE},
|
||||||
"networklastmodified": {"NetworkLastModified", "int64"},
|
"networklastmodified": {"NetworkLastModified", INT64_FIELD_TYPE},
|
||||||
"defaultinterface": {"DefaultInterface", "string"},
|
"defaultinterface": {"DefaultInterface", STRING_FIELD_TYPE},
|
||||||
"defaultlistenport": {"DefaultListenPort", "int32"},
|
"defaultlistenport": {"DefaultListenPort", INT32_FIELD_TYPE},
|
||||||
"nodelimit": {"NodeLimit", "int32"},
|
"nodelimit": {"NodeLimit", INT32_FIELD_TYPE},
|
||||||
"defaultpostup": {"DefaultPostUp", "string"},
|
"defaultpostup": {"DefaultPostUp", STRING_FIELD_TYPE},
|
||||||
"defaultpostdown": {"DefaultPostDown", "string"},
|
"defaultpostdown": {"DefaultPostDown", STRING_FIELD_TYPE},
|
||||||
"keyupdatetimestamp": {"KeyUpdateTimeStamp", "int64"},
|
"keyupdatetimestamp": {"KeyUpdateTimeStamp", INT64_FIELD_TYPE},
|
||||||
"defaultkeepalive": {"DefaultKeepalive", "int32"},
|
"defaultkeepalive": {"DefaultKeepalive", INT32_FIELD_TYPE},
|
||||||
"defaultsaveconfig": {"DefaultSaveConfig", "string"},
|
"defaultsaveconfig": {"DefaultSaveConfig", STRING_FIELD_TYPE},
|
||||||
"accesskeys": {"AccessKeys", "[]AccessKey"},
|
"accesskeys": {"AccessKeys", ACCESS_KEY_TYPE},
|
||||||
"allowmanualsignup": {"AllowManualSignUp", "string"},
|
"allowmanualsignup": {"AllowManualSignUp", STRING_FIELD_TYPE},
|
||||||
"islocal": {"IsLocal", "string"},
|
"islocal": {"IsLocal", STRING_FIELD_TYPE},
|
||||||
"isdualstack": {"IsDualStack", "string"},
|
"isdualstack": {"IsDualStack", STRING_FIELD_TYPE},
|
||||||
"isipv4": {"IsIPv4", "string"},
|
"isipv4": {"IsIPv4", STRING_FIELD_TYPE},
|
||||||
"isipv6": {"IsIPv6", "string"},
|
"isipv6": {"IsIPv6", STRING_FIELD_TYPE},
|
||||||
"isgrpchub": {"IsGRPCHub", "string"},
|
"isgrpchub": {"IsGRPCHub", STRING_FIELD_TYPE},
|
||||||
"localrange": {"LocalRange", "string"},
|
"localrange": {"LocalRange", STRING_FIELD_TYPE},
|
||||||
"checkininterval": {"DefaultCheckInInterval", "int32"},
|
"checkininterval": {"DefaultCheckInInterval", INT32_FIELD_TYPE},
|
||||||
"defaultudpholepunch": {"DefaultUDPHolePunch", "string"},
|
"defaultudpholepunch": {"DefaultUDPHolePunch", STRING_FIELD_TYPE},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (network *Network) FieldExists(field string) bool {
|
func (network *Network) FieldExists(field string) bool {
|
||||||
@@ -162,21 +171,35 @@ func (network *Network) IsNetworkNameUnique() (bool, error) {
|
|||||||
return isunique, nil
|
return isunique, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (network *Network) Validate() error {
|
func (network *Network) Validate(isUpdate bool) error {
|
||||||
v := validator.New()
|
v := validator.New()
|
||||||
_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
|
_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
|
||||||
isFieldUnique, _ := network.IsNetworkNameUnique()
|
|
||||||
inCharSet := network.NetIDInNetworkCharSet()
|
inCharSet := network.NetIDInNetworkCharSet()
|
||||||
|
if isUpdate {
|
||||||
|
return inCharSet
|
||||||
|
}
|
||||||
|
isFieldUnique, _ := network.IsNetworkNameUnique()
|
||||||
return isFieldUnique && inCharSet
|
return isFieldUnique && inCharSet
|
||||||
})
|
})
|
||||||
//
|
//
|
||||||
_ = v.RegisterValidation("displayname_valid", func(fl validator.FieldLevel) bool {
|
_ = v.RegisterValidation("displayname_valid", func(fl validator.FieldLevel) bool {
|
||||||
isFieldUnique, _ := network.IsNetworkDisplayNameUnique()
|
isFieldUnique, _ := network.IsNetworkDisplayNameUnique()
|
||||||
inCharSet := network.DisplayNameInNetworkCharSet()
|
inCharSet := network.DisplayNameInNetworkCharSet()
|
||||||
|
if isUpdate {
|
||||||
|
return inCharSet
|
||||||
|
}
|
||||||
return isFieldUnique && inCharSet
|
return isFieldUnique && inCharSet
|
||||||
})
|
})
|
||||||
|
_ = v.RegisterValidation("checkyesorno", func(fl validator.FieldLevel) bool {
|
||||||
|
return CheckYesOrNo(fl)
|
||||||
|
})
|
||||||
err := v.Struct(network)
|
err := v.Struct(network)
|
||||||
|
if err != nil {
|
||||||
|
for _, e := range err.(validator.ValidationErrors) {
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,8 +264,22 @@ func (network *Network) SetDefaults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (network *Network) CopyValues(newNetwork *Network, fieldName string) {
|
||||||
|
reflection := reflect.ValueOf(newNetwork)
|
||||||
|
value := reflect.Indirect(reflection).FieldByName(FIELDS[fieldName][0])
|
||||||
|
if value.IsValid() && len(FIELDS[fieldName]) == 2 {
|
||||||
|
fieldData := FIELDS[fieldName]
|
||||||
|
for _, indexVal := range FIELD_TYPES {
|
||||||
|
if indexVal == fieldData[1] {
|
||||||
|
currentReflection := reflect.ValueOf(network)
|
||||||
|
reflect.Indirect(currentReflection).FieldByName(FIELDS[fieldName][0]).Set(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (currentNetwork *Network) Update(newNetwork *Network) (bool, bool, error) {
|
func (currentNetwork *Network) Update(newNetwork *Network) (bool, bool, error) {
|
||||||
if err := newNetwork.Validate(); err != nil {
|
if err := newNetwork.Validate(true); err != nil {
|
||||||
return false, false, err
|
return false, false, err
|
||||||
}
|
}
|
||||||
if newNetwork.NetID == currentNetwork.NetID {
|
if newNetwork.NetID == currentNetwork.NetID {
|
||||||
|
213
models/node.go
213
models/node.go
@@ -2,12 +2,14 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
@@ -17,74 +19,39 @@ var seededRand *rand.Rand = rand.New(
|
|||||||
|
|
||||||
//node struct
|
//node struct
|
||||||
type Node struct {
|
type Node struct {
|
||||||
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
|
ID string `json:"id,omitempty" bson:"id,omitempty"`
|
||||||
Address string `json:"address" bson:"address" validate:"omitempty,ipv4"`
|
Address string `json:"address" bson:"address" validate:"omitempty,ipv4"`
|
||||||
Address6 string `json:"address6" bson:"address6" validate:"omitempty,ipv6"`
|
Address6 string `json:"address6" bson:"address6" validate:"omitempty,ipv6"`
|
||||||
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`
|
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`
|
||||||
Name string `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`
|
Name string `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`
|
||||||
ListenPort int32 `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
|
ListenPort int32 `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
|
||||||
PublicKey string `json:"publickey" bson:"publickey" validate:"required,base64"`
|
PublicKey string `json:"publickey" bson:"publickey" validate:"required,base64"`
|
||||||
Endpoint string `json:"endpoint" bson:"endpoint" validate:"required,ip"`
|
Endpoint string `json:"endpoint" bson:"endpoint" validate:"required,ip"`
|
||||||
PostUp string `json:"postup" bson:"postup"`
|
PostUp string `json:"postup" bson:"postup"`
|
||||||
PostDown string `json:"postdown" bson:"postdown"`
|
PostDown string `json:"postdown" bson:"postdown"`
|
||||||
AllowedIPs []string `json:"allowedips" bson:"allowedips"`
|
AllowedIPs []string `json:"allowedips" bson:"allowedips"`
|
||||||
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
|
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
|
||||||
SaveConfig *bool `json:"saveconfig" bson:"saveconfig"`
|
SaveConfig string `json:"saveconfig" bson:"saveconfig" validate:"checkyesorno"`
|
||||||
AccessKey string `json:"accesskey" bson:"accesskey"`
|
AccessKey string `json:"accesskey" bson:"accesskey"`
|
||||||
Interface string `json:"interface" bson:"interface"`
|
Interface string `json:"interface" bson:"interface"`
|
||||||
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
||||||
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
|
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
|
||||||
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"`
|
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"`
|
||||||
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate"`
|
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate"`
|
||||||
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin"`
|
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin"`
|
||||||
MacAddress string `json:"macaddress" bson:"macaddress" validate:"required,mac,macaddress_unique"`
|
MacAddress string `json:"macaddress" bson:"macaddress" validate:"required,mac,macaddress_unique"`
|
||||||
CheckInInterval int32 `json:"checkininterval" bson:"checkininterval"`
|
CheckInInterval int32 `json:"checkininterval" bson:"checkininterval"`
|
||||||
Password string `json:"password" bson:"password" validate:"required,min=6"`
|
Password string `json:"password" bson:"password" validate:"required,min=6"`
|
||||||
Network string `json:"network" bson:"network" validate:"network_exists"`
|
Network string `json:"network" bson:"network" validate:"network_exists"`
|
||||||
IsPending bool `json:"ispending" bson:"ispending"`
|
IsPending bool `json:"ispending" bson:"ispending"`
|
||||||
IsEgressGateway bool `json:"isegressgateway" bson:"isegressgateway"`
|
IsEgressGateway bool `json:"isegressgateway" bson:"isegressgateway"`
|
||||||
IsIngressGateway bool `json:"isingressgateway" bson:"isingressgateway"`
|
IsIngressGateway bool `json:"isingressgateway" bson:"isingressgateway"`
|
||||||
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
|
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
|
||||||
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
|
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
|
||||||
PostChanges string `json:"postchanges" bson:"postchanges"`
|
PostChanges string `json:"postchanges" bson:"postchanges"`
|
||||||
StaticIP string `json:"staticip" bson:"staticip"`
|
StaticIP string `json:"staticip" bson:"staticip"`
|
||||||
StaticPubKey string `json:"staticpubkey" bson:"staticpubkey"`
|
StaticPubKey string `json:"staticpubkey" bson:"staticpubkey"`
|
||||||
}
|
UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" validate:"checkyesorno"`
|
||||||
|
|
||||||
//node update struct --- only validations are different
|
|
||||||
type NodeUpdate struct {
|
|
||||||
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
|
|
||||||
Address string `json:"address" bson:"address" validate:"omitempty,ip"`
|
|
||||||
Address6 string `json:"address6" bson:"address6" validate:"omitempty,ipv6"`
|
|
||||||
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`
|
|
||||||
Name string `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`
|
|
||||||
ListenPort int32 `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
|
|
||||||
PublicKey string `json:"publickey" bson:"publickey" validate:"omitempty,base64"`
|
|
||||||
Endpoint string `json:"endpoint" bson:"endpoint" validate:"omitempty,ip"`
|
|
||||||
PostUp string `json:"postup" bson:"postup"`
|
|
||||||
PostDown string `json:"postdown" bson:"postdown"`
|
|
||||||
AllowedIPs []string `json:"allowedips" bson:"allowedips"`
|
|
||||||
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
|
|
||||||
SaveConfig *bool `json:"saveconfig" bson:"saveconfig"`
|
|
||||||
AccessKey string `json:"accesskey" bson:"accesskey"`
|
|
||||||
Interface string `json:"interface" bson:"interface"`
|
|
||||||
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
|
||||||
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
|
|
||||||
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"`
|
|
||||||
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate"`
|
|
||||||
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin"`
|
|
||||||
MacAddress string `json:"macaddress" bson:"macaddress" validate:"required,mac"`
|
|
||||||
CheckInInterval int32 `json:"checkininterval" bson:"checkininterval"`
|
|
||||||
Password string `json:"password" bson:"password" validate:"omitempty,min=5"`
|
|
||||||
Network string `json:"network" bson:"network" validate:"network_exists"`
|
|
||||||
IsPending bool `json:"ispending" bson:"ispending"`
|
|
||||||
IsIngressGateway bool `json:"isingressgateway" bson:"isingressgateway"`
|
|
||||||
IsEgressGateway bool `json:"isegressgateway" bson:"isegressgateway"`
|
|
||||||
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
|
|
||||||
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
|
|
||||||
PostChanges string `json:"postchanges" bson:"postchanges"`
|
|
||||||
StaticIP string `json:"staticip" bson:"staticip"`
|
|
||||||
StaticPubKey string `json:"staticpubkey" bson:"staticpubkey"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:
|
//TODO:
|
||||||
@@ -101,6 +68,10 @@ func (node *Node) SetLastPeerUpdate() {
|
|||||||
node.LastPeerUpdate = time.Now().Unix()
|
node.LastPeerUpdate = time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (node *Node) SetID() {
|
||||||
|
node.ID = node.MacAddress + "###" + node.Network
|
||||||
|
}
|
||||||
|
|
||||||
func (node *Node) SetExpirationDateTime() {
|
func (node *Node) SetExpirationDateTime() {
|
||||||
node.ExpirationDateTime = time.Unix(33174902665, 0).Unix()
|
node.ExpirationDateTime = time.Unix(33174902665, 0).Unix()
|
||||||
}
|
}
|
||||||
@@ -138,16 +109,9 @@ func (node *Node) SetDefaults() {
|
|||||||
if node.ListenPort == 0 {
|
if node.ListenPort == 0 {
|
||||||
node.ListenPort = parentNetwork.DefaultListenPort
|
node.ListenPort = parentNetwork.DefaultListenPort
|
||||||
}
|
}
|
||||||
if node.PostDown == "" {
|
if node.SaveConfig == "" {
|
||||||
//Empty because we dont set it
|
|
||||||
//may want to set it to something in the future
|
|
||||||
}
|
|
||||||
//TODO: This is dumb and doesn't work
|
|
||||||
//Need to change
|
|
||||||
if node.SaveConfig == nil {
|
|
||||||
if parentNetwork.DefaultSaveConfig != "" {
|
if parentNetwork.DefaultSaveConfig != "" {
|
||||||
defaultsave := parentNetwork.DefaultSaveConfig == "yes"
|
node.SaveConfig = parentNetwork.DefaultSaveConfig
|
||||||
node.SaveConfig = &defaultsave
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.Interface == "" {
|
if node.Interface == "" {
|
||||||
@@ -166,9 +130,35 @@ func (node *Node) SetDefaults() {
|
|||||||
if node.StaticPubKey == "" {
|
if node.StaticPubKey == "" {
|
||||||
node.StaticPubKey = "no"
|
node.StaticPubKey = "no"
|
||||||
}
|
}
|
||||||
|
if node.UDPHolePunch == "" {
|
||||||
|
node.UDPHolePunch = parentNetwork.DefaultUDPHolePunch
|
||||||
|
}
|
||||||
node.CheckInInterval = parentNetwork.DefaultCheckInInterval
|
node.CheckInInterval = parentNetwork.DefaultCheckInInterval
|
||||||
|
|
||||||
|
node.SetLastModified()
|
||||||
|
node.SetDefaultName()
|
||||||
|
node.SetLastCheckIn()
|
||||||
|
node.SetLastPeerUpdate()
|
||||||
|
node.SetID()
|
||||||
|
node.KeyUpdateTimeStamp = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (currentNode *Node) Update(newNode *Node) error {
|
||||||
|
if err := newNode.Validate(true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newNode.SetID()
|
||||||
|
if newNode.ID == currentNode.ID {
|
||||||
|
if data, err := json.Marshal(newNode); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
newNode.SetLastModified()
|
||||||
|
err = database.Insert(newNode.ID, string(data), database.NODES_TABLE_NAME)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// copy values
|
||||||
|
return errors.New("failed to update node " + newNode.MacAddress + ", cannot change macaddress.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func StringWithCharset(length int, charset string) string {
|
func StringWithCharset(length int, charset string) string {
|
||||||
@@ -185,3 +175,68 @@ func StringWithCharset(length int, charset string) string {
|
|||||||
func IsIpv4Net(host string) bool {
|
func IsIpv4Net(host string) bool {
|
||||||
return net.ParseIP(host) != nil
|
return net.ParseIP(host) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (node *Node) Validate(isUpdate bool) error {
|
||||||
|
v := validator.New()
|
||||||
|
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
|
||||||
|
if isUpdate {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
isFieldUnique, _ := node.IsIDUnique()
|
||||||
|
return isFieldUnique
|
||||||
|
})
|
||||||
|
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
||||||
|
_, err := node.GetNetwork()
|
||||||
|
return err == nil
|
||||||
|
})
|
||||||
|
_ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {
|
||||||
|
isgood := node.NameInNodeCharSet()
|
||||||
|
return isgood
|
||||||
|
})
|
||||||
|
_ = v.RegisterValidation("checkyesorno", func(fl validator.FieldLevel) bool {
|
||||||
|
return CheckYesOrNo(fl)
|
||||||
|
})
|
||||||
|
err := v.Struct(node)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) IsIDUnique() (bool, error) {
|
||||||
|
record, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return record == "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *Node) NameInNodeCharSet() bool {
|
||||||
|
|
||||||
|
charset := "abcdefghijklmnopqrstuvwxyz1234567890-"
|
||||||
|
|
||||||
|
for _, char := range node.Name {
|
||||||
|
if !strings.Contains(charset, strings.ToLower(string(char))) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllNodes() ([]Node, error) {
|
||||||
|
var nodes []Node
|
||||||
|
|
||||||
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return []Node{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range collection {
|
||||||
|
var node Node
|
||||||
|
if err := json.Unmarshal([]byte(value), &node); err != nil {
|
||||||
|
return []Node{}, err
|
||||||
|
}
|
||||||
|
// add node to our array
|
||||||
|
nodes = append(nodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
16
models/validation.go
Normal file
16
models/validation.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckYesOrNo(fl validator.FieldLevel) bool {
|
||||||
|
return fl.Field().String() == "yes" || fl.Field().String() == "no"
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckRegex(fl validator.FieldLevel) bool {
|
||||||
|
re := regexp.MustCompile(fl.Param())
|
||||||
|
return re.MatchString(fl.Field().String())
|
||||||
|
}
|
@@ -15,12 +15,12 @@ generate_post_json ()
|
|||||||
"macaddress": "$MACADDRESS",
|
"macaddress": "$MACADDRESS",
|
||||||
"password": "$PASSWORD",
|
"password": "$PASSWORD",
|
||||||
"localaddress": "172.123.123.3",
|
"localaddress": "172.123.123.3",
|
||||||
"accesskey": "$ACCESSKEY"
|
"accesskey": "HskQMAoHVplC3l7E"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
POST_JSON=$(generate_post_json)
|
POST_JSON=$(generate_post_json)
|
||||||
|
|
||||||
curl --max-time 5.0 -d "$POST_JSON" -H 'Content-Type: application/json' -H "authorization: Bearer secretkey" localhost:8081/api/nodes/my-net
|
curl --max-time 5.0 -d "$POST_JSON" -H 'Content-Type: application/json' -H "authorization: Bearer secretkey" localhost:8081/api/nodes/network
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user