Browse Source

added error on attempt to update NetID

Matthew R Kasun 4 years ago
parent
commit
66fb590be2
2 changed files with 389 additions and 388 deletions
  1. 384 383
      controllers/networkHttpController.go
  2. 5 5
      test/group_test.go

+ 384 - 383
controllers/networkHttpController.go

@@ -1,34 +1,35 @@
 package controller
 
 import (
-    "gopkg.in/go-playground/validator.v9"
-    "github.com/gravitl/netmaker/models"
-    "errors"
-    "encoding/base64"
-    "github.com/gravitl/netmaker/functions"
-    "github.com/gravitl/netmaker/mongoconn"
-    "time"
-    "strings"
-    "fmt"
-    "context"
-    "encoding/json"
-    "net/http"
-    "github.com/gorilla/mux"
-    "go.mongodb.org/mongo-driver/bson"
-    "go.mongodb.org/mongo-driver/mongo/options"
-    "github.com/gravitl/netmaker/config"
+	"context"
+	"encoding/base64"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/gorilla/mux"
+	"github.com/gravitl/netmaker/config"
+	"github.com/gravitl/netmaker/functions"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mongoconn"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"gopkg.in/go-playground/validator.v9"
 )
 
 func networkHandlers(r *mux.Router) {
-    r.HandleFunc("/api/networks", securityCheck(http.HandlerFunc(getNetworks))).Methods("GET")
-    r.HandleFunc("/api/networks", securityCheck(http.HandlerFunc(createNetwork))).Methods("POST")
-    r.HandleFunc("/api/networks/{networkname}", securityCheck(http.HandlerFunc(getNetwork))).Methods("GET")
-    r.HandleFunc("/api/networks/{networkname}", securityCheck(http.HandlerFunc(updateNetwork))).Methods("PUT")
-    r.HandleFunc("/api/networks/{networkname}", securityCheck(http.HandlerFunc(deleteNetwork))).Methods("DELETE")
-    r.HandleFunc("/api/networks/{networkname}/keyupdate", securityCheck(http.HandlerFunc(keyUpdate))).Methods("POST")
-    r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(http.HandlerFunc(createAccessKey))).Methods("POST")
-    r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(http.HandlerFunc(getAccessKeys))).Methods("GET")
-    r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
+	r.HandleFunc("/api/networks", securityCheck(http.HandlerFunc(getNetworks))).Methods("GET")
+	r.HandleFunc("/api/networks", securityCheck(http.HandlerFunc(createNetwork))).Methods("POST")
+	r.HandleFunc("/api/networks/{networkname}", securityCheck(http.HandlerFunc(getNetwork))).Methods("GET")
+	r.HandleFunc("/api/networks/{networkname}", securityCheck(http.HandlerFunc(updateNetwork))).Methods("PUT")
+	r.HandleFunc("/api/networks/{networkname}", securityCheck(http.HandlerFunc(deleteNetwork))).Methods("DELETE")
+	r.HandleFunc("/api/networks/{networkname}/keyupdate", securityCheck(http.HandlerFunc(keyUpdate))).Methods("POST")
+	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(http.HandlerFunc(createAccessKey))).Methods("POST")
+	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(http.HandlerFunc(getAccessKeys))).Methods("GET")
+	r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
 }
 
 //Security check is middleware for every function and just checks to make sure that its the master calling
@@ -43,48 +44,49 @@ func securityCheck(next http.Handler) http.HandlerFunc {
 		var params = mux.Vars(r)
 		hasnetwork := params["networkname"] != ""
 		networkexists, err := functions.NetworkExists(params["networkname"])
-                if err != nil {
+		if err != nil {
 			returnErrorResponse(w, r, formatError(err, "internal"))
 			return
 		} else if hasnetwork && !networkexists {
-                        errorResponse = models.ErrorResponse{
-                                Code: http.StatusNotFound, Message: "W1R3: This network does not exist.",
-                        }
-                        returnErrorResponse(w, r, errorResponse)
-			return
-                } else {
-
-		bearerToken := r.Header.Get("Authorization")
-
-		var hasBearer = true
-		var tokenSplit = strings.Split(bearerToken, " ")
-		var  authToken = ""
-
-		if len(tokenSplit) < 2 {
-			hasBearer = false
-		} else {
-			authToken = tokenSplit[1]
-		}
-		//all endpoints here require master so not as complicated
-		//still might not be a good  way of doing this
-		if !hasBearer || !authenticateMaster(authToken) {
 			errorResponse = models.ErrorResponse{
-				Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
+				Code: http.StatusNotFound, Message: "W1R3: This network does not exist.",
 			}
 			returnErrorResponse(w, r, errorResponse)
 			return
 		} else {
-			next.ServeHTTP(w, r)
-		}
+
+			bearerToken := r.Header.Get("Authorization")
+
+			var hasBearer = true
+			var tokenSplit = strings.Split(bearerToken, " ")
+			var authToken = ""
+
+			if len(tokenSplit) < 2 {
+				hasBearer = false
+			} else {
+				authToken = tokenSplit[1]
+			}
+			//all endpoints here require master so not as complicated
+			//still might not be a good  way of doing this
+			if !hasBearer || !authenticateMaster(authToken) {
+				errorResponse = models.ErrorResponse{
+					Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
+				}
+				returnErrorResponse(w, r, errorResponse)
+				return
+			} else {
+				next.ServeHTTP(w, r)
+			}
 		}
 	}
 }
+
 //Consider a more secure way of setting master key
 func authenticateMaster(tokenString string) bool {
-    if tokenString == config.Config.Server.MasterKey {
-        return true
-    }
-    return false
+	if tokenString == config.Config.Server.MasterKey {
+		return true
+	}
+	return false
 }
 
 //simple get all networks function
@@ -104,168 +106,168 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
 
 func validateNetwork(operation string, network models.Network) error {
 
-        v := validator.New()
+	v := validator.New()
 
-        _ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool {
+	_ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool {
 		isvalid := functions.IsIpv4CIDR(fl.Field().String())
-                return isvalid
-        })
+		return isvalid
+	})
 
-        _ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool {
-                isvalid := !*network.IsLocal || functions.IsIpv4CIDR(fl.Field().String())
-                return isvalid
-        })
+	_ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool {
+		isvalid := !*network.IsLocal || functions.IsIpv4CIDR(fl.Field().String())
+		return isvalid
+	})
 
-        _ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
+	_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
 		isFieldUnique := false
 		inCharSet := false
-		if operation == "update" { isFieldUnique = true } else{
+		if operation == "update" {
+			isFieldUnique = true
+		} else {
 			isFieldUnique, _ = functions.IsNetworkNameUnique(fl.Field().String())
-			inCharSet        = functions.NameInNetworkCharSet(fl.Field().String())
+			inCharSet = functions.NameInNetworkCharSet(fl.Field().String())
 		}
 		return isFieldUnique && inCharSet
-        })
+	})
 
-        _ = v.RegisterValidation("displayname_unique", func(fl validator.FieldLevel) bool {
-                isFieldUnique, _ := functions.IsNetworkDisplayNameUnique(fl.Field().String())
-                return isFieldUnique ||  operation == "update"
-        })
+	_ = v.RegisterValidation("displayname_unique", func(fl validator.FieldLevel) bool {
+		isFieldUnique, _ := functions.IsNetworkDisplayNameUnique(fl.Field().String())
+		return isFieldUnique || operation == "update"
+	})
 
-        err := v.Struct(network)
+	err := v.Struct(network)
 
-        if err != nil {
-                for _, e := range err.(validator.ValidationErrors) {
-                        fmt.Println(e)
-                }
-        }
-        return err
+	if err != nil {
+		for _, e := range err.(validator.ValidationErrors) {
+			fmt.Println(e)
+		}
+	}
+	return err
 }
 
 //Simple get network function
 func getNetwork(w http.ResponseWriter, r *http.Request) {
 
-        // set header.
-        w.Header().Set("Content-Type", "application/json")
+	// set header.
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
-        var network models.Network
+	var network models.Network
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        filter := bson.M{"netid": params["networkname"]}
-        err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
+	filter := bson.M{"netid": params["networkname"]}
+	err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
 
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-		returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 	w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(network)
+	json.NewEncoder(w).Encode(network)
 }
 
 func keyUpdate(w http.ResponseWriter, r *http.Request) {
 
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
-        var network models.Network
+	var network models.Network
 
-        network, err := functions.GetParentNetwork(params["networkname"])
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
+	network, err := functions.GetParentNetwork(params["networkname"])
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
 	}
 
-
 	network.KeyUpdateTimeStamp = time.Now().Unix()
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        filter := bson.M{"netid": params["networkname"]}
-        // prepare update model.
-        update := bson.D{
-                {"$set", bson.D{
-                        {"addressrange", network.AddressRange},
-                        {"displayname", network.DisplayName},
-                        {"defaultlistenport", network.DefaultListenPort},
-                        {"defaultpostup", network.DefaultPostUp},
-                        {"defaultpreup", network.DefaultPostDown},
+	filter := bson.M{"netid": params["networkname"]}
+	// prepare update model.
+	update := bson.D{
+		{"$set", bson.D{
+			{"addressrange", network.AddressRange},
+			{"displayname", network.DisplayName},
+			{"defaultlistenport", network.DefaultListenPort},
+			{"defaultpostup", network.DefaultPostUp},
+			{"defaultpreup", network.DefaultPostDown},
 			{"defaultkeepalive", network.DefaultKeepalive},
-                        {"keyupdatetimestamp", network.KeyUpdateTimeStamp},
-                        {"defaultsaveconfig", network.DefaultSaveConfig},
-                        {"defaultinterface", network.DefaultInterface},
-                        {"nodeslastmodified", network.NodesLastModified},
-                        {"networklastmodified", network.NetworkLastModified},
-                        {"allowmanualsignup", network.AllowManualSignUp},
+			{"keyupdatetimestamp", network.KeyUpdateTimeStamp},
+			{"defaultsaveconfig", network.DefaultSaveConfig},
+			{"defaultinterface", network.DefaultInterface},
+			{"nodeslastmodified", network.NodesLastModified},
+			{"networklastmodified", network.NetworkLastModified},
+			{"allowmanualsignup", network.AllowManualSignUp},
 			{"defaultcheckininterval", network.DefaultCheckInInterval},
-                }},
-        }
+		}},
+	}
 
-        err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
+	err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
 
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(network)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(network)
 }
 
 //Update a network
-func AlertNetwork(netid string) error{
-
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-        filter := bson.M{"netid": netid}
+func AlertNetwork(netid string) error {
 
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	filter := bson.M{"netid": netid}
 
-        var network models.Network
+	var network models.Network
 
-        network, err := functions.GetParentNetwork(netid)
-        if err != nil {
-                return err
-        }
+	network, err := functions.GetParentNetwork(netid)
+	if err != nil {
+		return err
+	}
 	updatetime := time.Now().Unix()
-        update := bson.D{
-                {"$set", bson.D{
-                        {"nodeslastmodified", updatetime},
-                        {"networklastmodified", updatetime},
-                }},
-        }
+	update := bson.D{
+		{"$set", bson.D{
+			{"nodeslastmodified", updatetime},
+			{"networklastmodified", updatetime},
+		}},
+	}
 
-        err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
-        defer cancel()
+	err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
+	defer cancel()
 
-        return err
+	return err
 }
 
 //Update a network
 func updateNetwork(w http.ResponseWriter, r *http.Request) {
 
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
-        var network models.Network
+	var network models.Network
 
 	network, err := functions.GetParentNetwork(params["networkname"])
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        var networkChange models.Network
+	var networkChange models.Network
 
 	haschange := false
 	hasrangeupdate := false
@@ -277,44 +279,47 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
 		networkChange.AddressRange = network.AddressRange
 	}
 	if networkChange.NetID == "" {
-		networkChange.NetID =  network.NetID
+		networkChange.NetID = network.NetID
 	}
 
+	//err = validateNetwork("update", networkChange)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        //err = validateNetwork("update", networkChange)
-        if err != nil {
-		returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
-
-	//NOTE: Network.NetID is intentionally NOT editable. It acts as a static ID for the network. 
+	//NOTE: Network.NetID is intentionally NOT editable. It acts as a static ID for the network.
 	//DisplayName can be changed instead, which is what shows on the front end
+	if networkChange.NetID != network.NetID {
+		returnErrorResponse(w, r, formatError(errors.New("NetID is not editable"), "badrequest"))
+		return
+	}
 
-        if networkChange.AddressRange != "" {
+	if networkChange.AddressRange != "" {
 
-            network.AddressRange = networkChange.AddressRange
+		network.AddressRange = networkChange.AddressRange
 
-	    var isAddressOK bool = functions.IsIpv4CIDR(networkChange.AddressRange)
-            if !isAddressOK {
-		    err := errors.New("Invalid Range of " +  networkChange.AddressRange + " for addresses.")
-		    returnErrorResponse(w,r,formatError(err, "internal"))
-                    return
-            }
-             haschange = true
-	     hasrangeupdate = true
+		var isAddressOK bool = functions.IsIpv4CIDR(networkChange.AddressRange)
+		if !isAddressOK {
+			err := errors.New("Invalid Range of " + networkChange.AddressRange + " for addresses.")
+			returnErrorResponse(w, r, formatError(err, "internal"))
+			return
+		}
+		haschange = true
+		hasrangeupdate = true
 
-        }
+	}
 	if networkChange.LocalRange != "" {
-            network.LocalRange = networkChange.LocalRange
+		network.LocalRange = networkChange.LocalRange
 
-            var isAddressOK bool = functions.IsIpv4CIDR(networkChange.LocalRange)
-            if !isAddressOK {
-		    err := errors.New("Invalid Range of " +  networkChange.LocalRange + " for internal addresses.")
-                    returnErrorResponse(w,r,formatError(err, "internal"))
-                    return
-            }
-             haschange = true
-             haslocalrangeupdate = true
+		var isAddressOK bool = functions.IsIpv4CIDR(networkChange.LocalRange)
+		if !isAddressOK {
+			err := errors.New("Invalid Range of " + networkChange.LocalRange + " for internal addresses.")
+			returnErrorResponse(w, r, formatError(err, "internal"))
+			return
+		}
+		haschange = true
+		haslocalrangeupdate = true
 	}
 	if networkChange.IsLocal != nil {
 		network.IsLocal = networkChange.IsLocal
@@ -322,234 +327,231 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
 	if networkChange.DefaultListenPort != 0 {
 		network.DefaultListenPort = networkChange.DefaultListenPort
 		haschange = true
-        }
-        if networkChange.DefaultPostDown != "" {
+	}
+	if networkChange.DefaultPostDown != "" {
 		network.DefaultPostDown = networkChange.DefaultPostDown
 		haschange = true
-        }
-        if networkChange.DefaultInterface != "" {
+	}
+	if networkChange.DefaultInterface != "" {
 		network.DefaultInterface = networkChange.DefaultInterface
 		haschange = true
-        }
-        if networkChange.DefaultPostUp != "" {
+	}
+	if networkChange.DefaultPostUp != "" {
 		network.DefaultPostUp = networkChange.DefaultPostUp
 		haschange = true
-        }
-        if networkChange.DefaultKeepalive != 0 {
+	}
+	if networkChange.DefaultKeepalive != 0 {
 		network.DefaultKeepalive = networkChange.DefaultKeepalive
 		haschange = true
-        }
-        if networkChange.DisplayName != "" {
+	}
+	if networkChange.DisplayName != "" {
 		network.DisplayName = networkChange.DisplayName
 		haschange = true
-        }
-        if networkChange.DefaultCheckInInterval != 0 {
+	}
+	if networkChange.DefaultCheckInInterval != 0 {
 		network.DefaultCheckInInterval = networkChange.DefaultCheckInInterval
 		haschange = true
-        }
-        if networkChange.AllowManualSignUp != nil {
+	}
+	if networkChange.AllowManualSignUp != nil {
 		network.AllowManualSignUp = networkChange.AllowManualSignUp
 		haschange = true
-        }
+	}
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-        filter := bson.M{"netid": params["networkname"]}
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	filter := bson.M{"netid": params["networkname"]}
 
 	if haschange {
 		network.SetNetworkLastModified()
 	}
 
-        // prepare update model.
-        update := bson.D{
-                {"$set", bson.D{
-                        {"addressrange", network.AddressRange},
-                        {"displayname", network.DisplayName},
-                        {"defaultlistenport", network.DefaultListenPort},
-                        {"defaultpostup", network.DefaultPostUp},
-                        {"defaultpreup", network.DefaultPostDown},
-                        {"defaultkeepalive", network.DefaultKeepalive},
-                        {"defaultsaveconfig", network.DefaultSaveConfig},
-                        {"defaultinterface", network.DefaultInterface},
-                        {"nodeslastmodified", network.NodesLastModified},
-                        {"networklastmodified", network.NetworkLastModified},
-                        {"allowmanualsignup", network.AllowManualSignUp},
-                        {"localrange", network.LocalRange},
-                        {"islocal", network.IsLocal},
-                        {"defaultcheckininterval", network.DefaultCheckInInterval},
+	// prepare update model.
+	update := bson.D{
+		{"$set", bson.D{
+			{"addressrange", network.AddressRange},
+			{"displayname", network.DisplayName},
+			{"defaultlistenport", network.DefaultListenPort},
+			{"defaultpostup", network.DefaultPostUp},
+			{"defaultpreup", network.DefaultPostDown},
+			{"defaultkeepalive", network.DefaultKeepalive},
+			{"defaultsaveconfig", network.DefaultSaveConfig},
+			{"defaultinterface", network.DefaultInterface},
+			{"nodeslastmodified", network.NodesLastModified},
+			{"networklastmodified", network.NetworkLastModified},
+			{"allowmanualsignup", network.AllowManualSignUp},
+			{"localrange", network.LocalRange},
+			{"islocal", network.IsLocal},
+			{"defaultcheckininterval", network.DefaultCheckInInterval},
 		}},
-        }
+	}
 
 	err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 	//Cycles through nodes and gives them new IP's based on the new range
 	//Pretty cool, but also pretty inefficient currently
-        if hasrangeupdate {
+	if hasrangeupdate {
 		err = functions.UpdateNetworkNodeAddresses(params["networkname"])
 		if err != nil {
-			returnErrorResponse(w,r,formatError(err, "internal"))
+			returnErrorResponse(w, r, formatError(err, "internal"))
 			return
 		}
 	}
 	if haslocalrangeupdate {
-                err = functions.UpdateNetworkPrivateAddresses(params["networkname"])
-                if err != nil {
-                        returnErrorResponse(w,r,formatError(err, "internal"))
-                        return
-                }
+		err = functions.UpdateNetworkPrivateAddresses(params["networkname"])
+		if err != nil {
+			returnErrorResponse(w, r, formatError(err, "internal"))
+			return
+		}
 	}
 	returnnetwork, err := functions.GetParentNetwork(network.NetID)
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(returnnetwork)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(returnnetwork)
 }
 
 //Delete a network
 //Will stop you if  there's any nodes associated
 func deleteNetwork(w http.ResponseWriter, r *http.Request) {
-        // Set header
-        w.Header().Set("Content-Type", "application/json")
+	// Set header
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
 	nodecount, err := functions.GetNetworkNodeNumber(params["networkname"])
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
-	} else if nodecount > 0  {
+	} else if nodecount > 0 {
 		errorResponse := models.ErrorResponse{
-                        Code: http.StatusForbidden, Message: "W1R3: Node check failed. All nodes must be deleted before deleting network.",
-                }
-                returnErrorResponse(w, r, errorResponse)
-                return
-        }
+			Code: http.StatusForbidden, Message: "W1R3: Node check failed. All nodes must be deleted before deleting network.",
+		}
+		returnErrorResponse(w, r, errorResponse)
+		return
+	}
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
 
-        filter := bson.M{"netid": params["networkname"]}
+	filter := bson.M{"netid": params["networkname"]}
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        deleteResult, err := collection.DeleteOne(ctx, filter)
+	deleteResult, err := collection.DeleteOne(ctx, filter)
 
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(deleteResult)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(deleteResult)
 }
 
 //Create a network
 //Pretty simple
 func createNetwork(w http.ResponseWriter, r *http.Request) {
 
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        var network models.Network
+	var network models.Network
 
-        // we decode our body request params
+	// we decode our body request params
 	err := json.NewDecoder(r.Body).Decode(&network)
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 	//TODO: Not really doing good validation here. Same as createNode, updateNode, and updateNetwork
 	//Need to implement some better validation across the board
-        if network.IsLocal == nil {
-                falsevar := false
-                network.IsLocal = &falsevar
-        }
-
-        //err = validateNetwork("create", network)
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
-	network.SetDefaults()
-        network.SetNodesLastModified()
-        network.SetNetworkLastModified()
-        network.KeyUpdateTimeStamp = time.Now().Unix()
+	if network.IsLocal == nil {
+		falsevar := false
+		network.IsLocal = &falsevar
+	}
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	//err = validateNetwork("create", network)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	network.SetDefaults()
+	network.SetNodesLastModified()
+	network.SetNetworkLastModified()
+	network.KeyUpdateTimeStamp = time.Now().Unix()
 
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        // insert our network into the network table
-        result, err := collection.InsertOne(ctx, network)
+	// insert our network into the network table
+	result, err := collection.InsertOne(ctx, network)
 
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(result)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(result)
 }
 
 // BEGIN KEY MANAGEMENT SECTION
 
-
 //TODO: Very little error handling
 //accesskey is created as a json string inside the Network collection item in mongo
 func createAccessKey(w http.ResponseWriter, r *http.Request) {
 
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
-        var network models.Network
-        var accesskey models.AccessKey
+	var network models.Network
+	var accesskey models.AccessKey
 
-        //start here
+	//start here
 	network, err := functions.GetParentNetwork(params["networkname"])
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        err = json.NewDecoder(r.Body).Decode(&accesskey)
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	err = json.NewDecoder(r.Body).Decode(&accesskey)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 	if accesskey.Name == "" {
-                accesskey.Name = functions.GenKeyName()
-        }
+		accesskey.Name = functions.GenKeyName()
+	}
 	if accesskey.Value == "" {
 		accesskey.Value = functions.GenKey()
 	}
-        if accesskey.Uses == 0 {
-                accesskey.Uses = 1
-        }
+	if accesskey.Uses == 0 {
+		accesskey.Uses = 1
+	}
 	gconf, err := functions.GetGlobalConfig()
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 	privAddr := ""
 	if *network.IsLocal {
 		privAddr = network.LocalRange
 	}
 
-
 	netID := params["networkname"]
 	address := gconf.ServerGRPC + gconf.PortGRPC
 
@@ -558,33 +560,33 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
 
 	network.AccessKeys = append(network.AccessKeys, accesskey)
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        // Create filter
-        filter := bson.M{"netid": params["networkname"]}
+	// Create filter
+	filter := bson.M{"netid": params["networkname"]}
 
-        // Read update model from body request
-        fmt.Println("Adding key to " + network.NetID)
+	// Read update model from body request
+	fmt.Println("Adding key to " + network.NetID)
 
-        // prepare update model.
-        update := bson.D{
-                {"$set", bson.D{
-                        {"accesskeys", network.AccessKeys},
-                }},
-        }
+	// prepare update model.
+	update := bson.D{
+		{"$set", bson.D{
+			{"accesskeys", network.AccessKeys},
+		}},
+	}
 
-        err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
+	err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
 
-        defer cancel()
+	defer cancel()
 
 	if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(accesskey)
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(accesskey)
 	//w.Write([]byte(accesskey.AccessString))
 }
 
@@ -592,98 +594,97 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
 func getAccessKeys(w http.ResponseWriter, r *http.Request) {
 
 	// set header.
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
-        var network models.Network
-        //var keys []models.DisplayKey
+	var network models.Network
+	//var keys []models.DisplayKey
 	var keys []models.AccessKey
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        filter := bson.M{"netid": params["networkname"]}
-        err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
+	filter := bson.M{"netid": params["networkname"]}
+	err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
 
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 	keydata, err := json.Marshal(network.AccessKeys)
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 	json.Unmarshal(keydata, &keys)
 
 	w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(keys)
+	json.NewEncoder(w).Encode(keys)
 }
 
-
 //delete key. Has to do a little funky logic since it's not a collection item
 func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
 
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        var params = mux.Vars(r)
+	var params = mux.Vars(r)
 
-        var network models.Network
+	var network models.Network
 	keyname := params["name"]
 
-        //start here
+	//start here
 	network, err := functions.GetParentNetwork(params["networkname"])
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 	//basically, turn the list of access keys into the list of access keys before and after the item
 	//have not done any error handling for if there's like...1 item. I think it works? need to test.
 	for i := len(network.AccessKeys) - 1; i >= 0; i-- {
 
-		currentkey:= network.AccessKeys[i]
+		currentkey := network.AccessKeys[i]
 		if currentkey.Name == keyname {
 			network.AccessKeys = append(network.AccessKeys[:i],
 				network.AccessKeys[i+1:]...)
 		}
 	}
 
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
-        // Create filter
-        filter := bson.M{"netid": params["networkname"]}
+	// Create filter
+	filter := bson.M{"netid": params["networkname"]}
 
-        // prepare update model.
-        update := bson.D{
-                {"$set", bson.D{
-                        {"accesskeys", network.AccessKeys},
-                }},
-        }
+	// prepare update model.
+	update := bson.D{
+		{"$set", bson.D{
+			{"accesskeys", network.AccessKeys},
+		}},
+	}
 
-        err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
+	err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
 
-        defer cancel()
+	defer cancel()
 
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
-        var keys []models.AccessKey
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	var keys []models.AccessKey
 	keydata, err := json.Marshal(network.AccessKeys)
-        if err != nil {
-                returnErrorResponse(w,r,formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
-        json.Unmarshal(keydata, &keys)
+	json.Unmarshal(keydata, &keys)
 
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(keys)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(keys)
 }

+ 5 - 5
test/group_test.go

@@ -341,13 +341,13 @@ func TestUpdatenetwork(t *testing.T) {
 		network.NetID = "wirecat"
 		response, err := api(t, network, http.MethodPut, baseURL+"/api/networks/skynet", "secretkey")
 		assert.Nil(t, err, err)
-		assert.Equal(t, http.StatusOK, response.StatusCode)
+		assert.Equal(t, http.StatusBadRequest, response.StatusCode)
 		defer response.Body.Close()
-		err = json.NewDecoder(response.Body).Decode(&returnedNetwork)
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
 		assert.Nil(t, err, err)
-		//returns previous value not the updated value
-		// ----- needs fixing -----
-		//assert.Equal(t, network.NetID, returnedNetwork.NetID)
+		assert.Equal(t, http.StatusBadRequest, message.Code)
+		assert.Equal(t, "NetID is not editable", message.message)
 	})
 	t.Run("NetIDInvalidCredentials", func(t *testing.T) {
 		type Network struct {