Browse Source

Added logging and user specific requests

afeiszli 4 years ago
parent
commit
d41207172c

+ 3 - 2
compose/docker-compose.nodns.yml

@@ -20,7 +20,7 @@ services:
     container_name: netmaker
     container_name: netmaker
     depends_on:
     depends_on:
       - mongodb
       - mongodb
-    image: gravitl/netmaker:v0.5
+    image: gravitl/netmaker:v0.5.7
     volumes:
     volumes:
       - ./:/local
       - ./:/local
       - /etc/netclient:/etc/netclient
       - /etc/netclient:/etc/netclient
@@ -37,6 +37,7 @@ services:
     network_mode: host
     network_mode: host
     environment:
     environment:
       DNS_MODE: "off"
       DNS_MODE: "off"
+      SERVER_HOST: "192.168.50.149"
   netmaker-ui:
   netmaker-ui:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
@@ -47,7 +48,7 @@ services:
     ports:
     ports:
       - "80:80"
       - "80:80"
     environment:
     environment:
-      BACKEND_URL: "http://HOST_IP:8081"
+      BACKEND_URL: "http://192.168.50.149:8081"
 volumes:
 volumes:
   mongovol: {}
   mongovol: {}
   dnsconfig: {}
   dnsconfig: {}

+ 63 - 62
config/config.go

@@ -6,22 +6,23 @@
 package config
 package config
 
 
 import (
 import (
-  "os"
-  "fmt"
-  "log"
-  "gopkg.in/yaml.v3"
+	"fmt"
+	"log"
+	"os"
+
+	"gopkg.in/yaml.v3"
 )
 )
 
 
 //setting dev by default
 //setting dev by default
 func getEnv() string {
 func getEnv() string {
 
 
-  env := os.Getenv("NETMAKER_ENV")
+	env := os.Getenv("NETMAKER_ENV")
 
 
-  if len(env) == 0 {
-    return "dev"
-  }
+	if len(env) == 0 {
+		return "dev"
+	}
 
 
-  return env
+	return env
 }
 }
 
 
 // Config : application config stored as global variable
 // Config : application config stored as global variable
@@ -29,76 +30,76 @@ var Config *EnvironmentConfig
 
 
 // EnvironmentConfig :
 // EnvironmentConfig :
 type EnvironmentConfig struct {
 type EnvironmentConfig struct {
-  Server ServerConfig `yaml:"server"`
-  MongoConn MongoConnConfig `yaml:"mongoconn"`
-  WG WG `yaml:"wg"`
+	Server    ServerConfig    `yaml:"server"`
+	MongoConn MongoConnConfig `yaml:"mongoconn"`
+	WG        WG              `yaml:"wg"`
 }
 }
 
 
 // ServerConfig :
 // ServerConfig :
 type ServerConfig struct {
 type ServerConfig struct {
-  APIConnString string `yaml:"apiconn"`
-  APIHost   string  `yaml:"apihost"`
-  APIPort   string `yaml:"apiport"`
-  GRPCConnString string `yaml:"grpcconn"`
-  GRPCHost   string `yaml:"grpchost"`
-  GRPCPort   string `yaml:"grpcport"`
-  GRPCSecure   string `yaml:"grpcsecure"`
-  DefaultNodeLimit   int32 `yaml:"defaultnodelimit"`
-  MasterKey	string `yaml:"masterkey"`
-  AllowedOrigin	string `yaml:"allowedorigin"`
-  RestBackend string `yaml:"restbackend"`
-  AgentBackend string `yaml:"agentbackend"`
-  ClientMode string `yaml:"clientmode"`
-  DNSMode string `yaml:"dnsmode"`
-  DisableRemoteIPCheck string `yaml:"disableremoteipcheck"`
-  DisableDefaultNet string `yaml:"disabledefaultnet"`
-  GRPCSSL   string `yaml:"grpcssl"`
+	APIConnString        string `yaml:"apiconn"`
+	APIHost              string `yaml:"apihost"`
+	APIPort              string `yaml:"apiport"`
+	GRPCConnString       string `yaml:"grpcconn"`
+	GRPCHost             string `yaml:"grpchost"`
+	GRPCPort             string `yaml:"grpcport"`
+	GRPCSecure           string `yaml:"grpcsecure"`
+	DefaultNodeLimit     int32  `yaml:"defaultnodelimit"`
+	MasterKey            string `yaml:"masterkey"`
+	AllowedOrigin        string `yaml:"allowedorigin"`
+	RestBackend          string `yaml:"restbackend"`
+	AgentBackend         string `yaml:"agentbackend"`
+	ClientMode           string `yaml:"clientmode"`
+	DNSMode              string `yaml:"dnsmode"`
+	DisableRemoteIPCheck string `yaml:"disableremoteipcheck"`
+	DisableDefaultNet    string `yaml:"disabledefaultnet"`
+	GRPCSSL              string `yaml:"grpcssl"`
+	Verbosity            int32  `yaml:"verbosity"`
 }
 }
 
 
 type WG struct {
 type WG struct {
-  RegisterKeyRequired  string  `yaml:"keyrequired"`
-  GRPCWireGuard  string  `yaml:"grpcwg"`
-  GRPCWGInterface  string `yaml:"grpciface"`
-  GRPCWGAddress  string `yaml:"grpcaddr"`
-  GRPCWGAddressRange  string `yaml:"grpcaddrrange"`
-  GRPCWGPort  string  `yaml:"grpcport"`
-  GRPCWGPubKey  string  `yaml:"pubkey"`
-  GRPCWGPrivKey  string  `yaml:"privkey"`
+	RegisterKeyRequired string `yaml:"keyrequired"`
+	GRPCWireGuard       string `yaml:"grpcwg"`
+	GRPCWGInterface     string `yaml:"grpciface"`
+	GRPCWGAddress       string `yaml:"grpcaddr"`
+	GRPCWGAddressRange  string `yaml:"grpcaddrrange"`
+	GRPCWGPort          string `yaml:"grpcport"`
+	GRPCWGPubKey        string `yaml:"pubkey"`
+	GRPCWGPrivKey       string `yaml:"privkey"`
 }
 }
 
 
 type MongoConnConfig struct {
 type MongoConnConfig struct {
-  User   string  `yaml:"user"`
-  Pass   string  `yaml:"pass"`
-  Host   string  `yaml:"host"`
-  Port   string  `yaml:"port"`
-  Opts   string  `yaml:"opts"`
+	User string `yaml:"user"`
+	Pass string `yaml:"pass"`
+	Host string `yaml:"host"`
+	Port string `yaml:"port"`
+	Opts string `yaml:"opts"`
 }
 }
 
 
-
 //reading in the env file
 //reading in the env file
 func readConfig() *EnvironmentConfig {
 func readConfig() *EnvironmentConfig {
-  file := fmt.Sprintf("config/environments/%s.yaml", getEnv())
-  f, err := os.Open(file)
-  var cfg EnvironmentConfig
-  if err != nil {
-    //log.Fatal(err)
-    //os.Exit(2)
-    //log.Println("Unable to open config file at config/environments/" + getEnv())
-    //log.Println("Will proceed with defaults or enironment variables (no config file).")
-    return &cfg
-  }
-  defer f.Close()
+	file := fmt.Sprintf("config/environments/%s.yaml", getEnv())
+	f, err := os.Open(file)
+	var cfg EnvironmentConfig
+	if err != nil {
+		//log.Fatal(err)
+		//os.Exit(2)
+		//log.Println("Unable to open config file at config/environments/" + getEnv())
+		//log.Println("Will proceed with defaults or enironment variables (no config file).")
+		return &cfg
+	}
+	defer f.Close()
 
 
-  decoder := yaml.NewDecoder(f)
-  err = decoder.Decode(&cfg)
-  if err != nil {
-    log.Fatal(err)
-    os.Exit(2)
-  }
-  return &cfg
+	decoder := yaml.NewDecoder(f)
+	err = decoder.Decode(&cfg)
+	if err != nil {
+		log.Fatal(err)
+		os.Exit(2)
+	}
+	return &cfg
 
 
 }
 }
 
 
 func init() {
 func init() {
-  Config = readConfig()
+	Config = readConfig()
 }
 }

+ 176 - 130
controllers/networkHttpController.go

@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
 	"time"
 	"time"
+
 	"github.com/go-playground/validator/v10"
 	"github.com/go-playground/validator/v10"
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/functions"
@@ -20,8 +21,11 @@ import (
 	"go.mongodb.org/mongo-driver/mongo/options"
 	"go.mongodb.org/mongo-driver/mongo/options"
 )
 )
 
 
+const ALL_NETWORK_ACCESS = "THIS_USER_HAS_ALL"
+const NO_NETWORKS_PRESENT = "THIS_USER_HAS_NONE"
+
 func networkHandlers(r *mux.Router) {
 func networkHandlers(r *mux.Router) {
-	r.HandleFunc("/api/networks", securityCheck(true, http.HandlerFunc(getNetworks))).Methods("GET")
+	r.HandleFunc("/api/networks", securityCheck(false, http.HandlerFunc(getNetworks))).Methods("GET")
 	r.HandleFunc("/api/networks", securityCheck(true, http.HandlerFunc(createNetwork))).Methods("POST")
 	r.HandleFunc("/api/networks", securityCheck(true, http.HandlerFunc(createNetwork))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}", securityCheck(false, http.HandlerFunc(getNetwork))).Methods("GET")
 	r.HandleFunc("/api/networks/{networkname}", securityCheck(false, http.HandlerFunc(getNetwork))).Methods("GET")
 	r.HandleFunc("/api/networks/{networkname}", securityCheck(false, http.HandlerFunc(updateNetwork))).Methods("PUT")
 	r.HandleFunc("/api/networks/{networkname}", securityCheck(false, http.HandlerFunc(updateNetwork))).Methods("PUT")
@@ -30,7 +34,7 @@ func networkHandlers(r *mux.Router) {
 	r.HandleFunc("/api/networks/{networkname}/keyupdate", securityCheck(false, http.HandlerFunc(keyUpdate))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}/keyupdate", securityCheck(false, http.HandlerFunc(keyUpdate))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(createAccessKey))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(createAccessKey))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(getAccessKeys))).Methods("GET")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(getAccessKeys))).Methods("GET")
-        r.HandleFunc("/api/networks/{networkname}/signuptoken", securityCheck(false, http.HandlerFunc(getSignupToken))).Methods("GET")
+	r.HandleFunc("/api/networks/{networkname}/signuptoken", securityCheck(false, http.HandlerFunc(getSignupToken))).Methods("GET")
 	r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
 	r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
 }
 }
 
 
@@ -45,7 +49,7 @@ func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
 
 
 		var params = mux.Vars(r)
 		var params = mux.Vars(r)
 		bearerToken := r.Header.Get("Authorization")
 		bearerToken := r.Header.Get("Authorization")
-		err := SecurityCheck(reqAdmin, params["networkname"], bearerToken)
+		err, networks, username := SecurityCheck(reqAdmin, params["networkname"], bearerToken)
 		if err != nil {
 		if err != nil {
 			if strings.Contains(err.Error(), "does not exist") {
 			if strings.Contains(err.Error(), "does not exist") {
 				errorResponse.Code = http.StatusNotFound
 				errorResponse.Code = http.StatusNotFound
@@ -54,18 +58,26 @@ func securityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
 			returnErrorResponse(w, r, errorResponse)
 			returnErrorResponse(w, r, errorResponse)
 			return
 			return
 		}
 		}
+		networksJson, err := json.Marshal(&networks)
+		if err != nil {
+			errorResponse.Message = err.Error()
+			returnErrorResponse(w, r, errorResponse)
+			return
+		}
+		r.Header.Set("user", username)
+		r.Header.Set("networks", string(networksJson))
 		next.ServeHTTP(w, r)
 		next.ServeHTTP(w, r)
 	}
 	}
 }
 }
 
 
-func SecurityCheck(reqAdmin bool, netname, token string) error {
-	hasnetwork := netname != ""
+func SecurityCheck(reqAdmin bool, netname, token string) (error, []string, string) {
+
 	networkexists, err := functions.NetworkExists(netname)
 	networkexists, err := functions.NetworkExists(netname)
 	if err != nil {
 	if err != nil {
-		return err
+		return err, nil, ""
 	}
 	}
-	if hasnetwork && !networkexists {
-		return errors.New("This network does not exist")
+	if netname != "" && !networkexists {
+		return errors.New("This network does not exist"), nil, ""
 	}
 	}
 
 
 	var hasBearer = true
 	var hasBearer = true
@@ -77,23 +89,30 @@ func SecurityCheck(reqAdmin bool, netname, token string) error {
 	} else {
 	} else {
 		authToken = tokenSplit[1]
 		authToken = tokenSplit[1]
 	}
 	}
+	userNetworks := []string{}
 	//all endpoints here require master so not as complicated
 	//all endpoints here require master so not as complicated
-	if !hasBearer || !authenticateMaster(authToken) {
-		_, networks, isadmin, err := functions.VerifyUserToken(authToken)
+	isMasterAuthenticated := authenticateMaster(authToken)
+	username := ""
+	if !hasBearer || !isMasterAuthenticated {
+		userName, networks, isadmin, err := functions.VerifyUserToken(authToken)
+		username = userName
 		if err != nil {
 		if err != nil {
-                        return errors.New("Error verifying user token")
+			return errors.New("Error verifying user token"), nil, username
 		}
 		}
 		if !isadmin && reqAdmin {
 		if !isadmin && reqAdmin {
-                                return errors.New("You are unauthorized to access this endpoint")
-		} else if !isadmin && netname != ""{
-			if !functions.SliceContains(networks, netname){
-				return errors.New("You are unauthorized to access this endpoint")
-			}
-		} else if !isadmin {
-			return errors.New("You are unauthorized to access this endpoint")
+			return errors.New("You are unauthorized to access this endpoint"), nil, username
+		}
+		userNetworks = networks
+		if isadmin {
+			userNetworks = []string{ALL_NETWORK_ACCESS}
 		}
 		}
+	} else if isMasterAuthenticated {
+		userNetworks = []string{ALL_NETWORK_ACCESS}
 	}
 	}
-	return nil
+	if len(userNetworks) == 0 {
+		userNetworks = append(userNetworks, NO_NETWORKS_PRESENT)
+	}
+	return nil, userNetworks, username
 }
 }
 
 
 //Consider a more secure way of setting master key
 //Consider a more secure way of setting master key
@@ -107,16 +126,33 @@ func authenticateMaster(tokenString string) bool {
 //simple get all networks function
 //simple get all networks function
 func getNetworks(w http.ResponseWriter, r *http.Request) {
 func getNetworks(w http.ResponseWriter, r *http.Request) {
 
 
-	allnetworks, err := functions.ListNetworks()
-	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
+	headerNetworks := r.Header.Get("networks")
+	networksSlice := []string{}
+	marshalErr := json.Unmarshal([]byte(headerNetworks), &networksSlice)
+	if marshalErr != nil {
+		returnErrorResponse(w, r, formatError(marshalErr, "internal"))
 		return
 		return
 	}
 	}
+	allnetworks := []models.Network{}
+	err := errors.New("Networks Error")
+	if networksSlice[0] == ALL_NETWORK_ACCESS {
+		allnetworks, err = functions.ListNetworks()
+		if err != nil {
+			returnErrorResponse(w, r, formatError(err, "internal"))
+			return
+		}
+	} else {
+		for _, network := range networksSlice {
+			netObject, parentErr := functions.GetParentNetwork(network)
+			if parentErr == nil {
+				allnetworks = append(allnetworks, netObject)
+			}
+		}
+	}
 	networks := RemoveComms(allnetworks)
 	networks := RemoveComms(allnetworks)
-
+	functions.PrintUserLog(r.Header.Get("user"), "fetched networks.", 2)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(networks)
 	json.NewEncoder(w).Encode(networks)
-	return
 }
 }
 
 
 func RemoveComms(networks []models.Network) []models.Network {
 func RemoveComms(networks []models.Network) []models.Network {
@@ -137,13 +173,13 @@ func RemoveComms(networks []models.Network) []models.Network {
 func ValidateNetworkUpdate(network models.NetworkUpdate) error {
 func ValidateNetworkUpdate(network models.NetworkUpdate) error {
 	v := validator.New()
 	v := validator.New()
 
 
-        _ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
-                if fl.Field().String() == "" {
+	_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
+		if fl.Field().String() == "" {
 			return true
 			return true
 		}
 		}
-                inCharSet := functions.NameInNetworkCharSet(fl.Field().String())
-                return inCharSet
-        })
+		inCharSet := functions.NameInNetworkCharSet(fl.Field().String())
+		return inCharSet
+	})
 
 
 	//	_ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool {
 	//	_ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool {
 	//		isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
 	//		isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
@@ -231,6 +267,7 @@ func getNetwork(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "fetched network "+netname, 2)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(network)
 	json.NewEncoder(w).Encode(network)
 }
 }
@@ -257,6 +294,7 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "updated key on network "+netname, 2)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(network)
 	json.NewEncoder(w).Encode(network)
 }
 }
@@ -329,7 +367,8 @@ 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"])
+	netname := params["networkname"]
+	network, err := functions.GetParentNetwork(netname)
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
@@ -359,45 +398,47 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
+	functions.PrintUserLog(r.Header.Get("user"), "updated network "+netname, 1)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(returnednetwork)
 	json.NewEncoder(w).Encode(returnednetwork)
 }
 }
 
 
 func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
 func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
-        w.Header().Set("Content-Type", "application/json")
-        var params = mux.Vars(r)
-        var network models.Network
-        network, err := functions.GetParentNetwork(params["networkname"])
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "internal"))
-                return
-        }
-
-        var networkChange models.NetworkUpdate
-
-        _ = json.NewDecoder(r.Body).Decode(&networkChange)
-
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-        filter := bson.M{"netid": network.NetID}
-
-	if networkChange.NodeLimit !=0 {
-	        update := bson.D{
-	                {"$set", bson.D{
-	                        {"nodelimit", networkChange.NodeLimit},
-	                }},
-	        }
-	        err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
-	        defer cancel()
-	        if err != nil {
-	                returnErrorResponse(w, r, formatError(err, "badrequest"))
-	                return
-	        }
-	}
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(network)
-}
+	w.Header().Set("Content-Type", "application/json")
+	var params = mux.Vars(r)
+	var network models.Network
+	netname := params["networkname"]
+	network, err := functions.GetParentNetwork(netname)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 
+	var networkChange models.NetworkUpdate
+
+	_ = json.NewDecoder(r.Body).Decode(&networkChange)
+
+	collection := mongoconn.Client.Database("netmaker").Collection("networks")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	filter := bson.M{"netid": network.NetID}
+
+	if networkChange.NodeLimit != 0 {
+		update := bson.D{
+			{"$set", bson.D{
+				{"nodelimit", networkChange.NodeLimit},
+			}},
+		}
+		err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
+		defer cancel()
+		if err != nil {
+			returnErrorResponse(w, r, formatError(err, "badrequest"))
+			return
+		}
+	}
+	functions.PrintUserLog(r.Header.Get("user"), "updated network node limit on, "+netname, 1)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(network)
+}
 
 
 func UpdateNetwork(networkChange models.NetworkUpdate, network models.Network) (models.Network, error) {
 func UpdateNetwork(networkChange models.NetworkUpdate, network models.Network) (models.Network, error) {
 	//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.
@@ -528,12 +569,13 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
 
 
 	if err != nil {
 	if err != nil {
 		errtype := "badrequest"
 		errtype := "badrequest"
-		if strings.Contains(err.Error(), "Node check failed"){
+		if strings.Contains(err.Error(), "Node check failed") {
 			errtype = "forbidden"
 			errtype = "forbidden"
 		}
 		}
 		returnErrorResponse(w, r, formatError(err, errtype))
 		returnErrorResponse(w, r, formatError(err, errtype))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "deleted network "+network, 1)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(count)
 	json.NewEncoder(w).Encode(count)
 }
 }
@@ -585,6 +627,7 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "created network "+network.NetID, 1)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	//json.NewEncoder(w).Encode(result)
 	//json.NewEncoder(w).Encode(result)
 }
 }
@@ -633,7 +676,8 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
 	var params = mux.Vars(r)
 	var params = mux.Vars(r)
 	var accesskey models.AccessKey
 	var accesskey models.AccessKey
 	//start here
 	//start here
-	network, err := functions.GetParentNetwork(params["networkname"])
+	netname := params["networkname"]
+	network, err := functions.GetParentNetwork(netname)
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
@@ -648,6 +692,7 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "created access key "+netname, 1)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(key)
 	json.NewEncoder(w).Encode(key)
 	//w.Write([]byte(accesskey.AccessString))
 	//w.Write([]byte(accesskey.AccessString))
@@ -666,10 +711,10 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
 		accesskey.Uses = 1
 		accesskey.Uses = 1
 	}
 	}
 
 
-        checkkeys, err := GetKeys(network.NetID)
-        if err != nil {
-                return models.AccessKey{}, errors.New("could not retrieve network keys")
-        }
+	checkkeys, err := GetKeys(network.NetID)
+	if err != nil {
+		return models.AccessKey{}, errors.New("could not retrieve network keys")
+	}
 
 
 	for _, key := range checkkeys {
 	for _, key := range checkkeys {
 		if key.Name == accesskey.Name {
 		if key.Name == accesskey.Name {
@@ -685,38 +730,38 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
 
 
 	netID := network.NetID
 	netID := network.NetID
 
 
-        var accessToken models.AccessToken
-        s := servercfg.GetServerConfig()
-        w := servercfg.GetWGConfig()
+	var accessToken models.AccessToken
+	s := servercfg.GetServerConfig()
+	w := servercfg.GetWGConfig()
 	servervals := models.ServerConfig{
 	servervals := models.ServerConfig{
-			APIConnString: s.APIConnString,
-			APIHost: s.APIHost,
-			APIPort: s.APIPort,
-			GRPCConnString: s.GRPCConnString,
-			GRPCHost: s.GRPCHost,
-			GRPCPort: s.GRPCPort,
-			GRPCSSL: s.GRPCSSL,
-			}
+		APIConnString:  s.APIConnString,
+		APIHost:        s.APIHost,
+		APIPort:        s.APIPort,
+		GRPCConnString: s.GRPCConnString,
+		GRPCHost:       s.GRPCHost,
+		GRPCPort:       s.GRPCPort,
+		GRPCSSL:        s.GRPCSSL,
+	}
 	wgvals := models.WG{
 	wgvals := models.WG{
-			GRPCWireGuard: w.GRPCWireGuard,
-			GRPCWGAddress: w.GRPCWGAddress,
-			GRPCWGPort: w.GRPCWGPort,
-			GRPCWGPubKey: w.GRPCWGPubKey,
-			GRPCWGEndpoint: s.APIHost,
-		}
+		GRPCWireGuard:  w.GRPCWireGuard,
+		GRPCWGAddress:  w.GRPCWGAddress,
+		GRPCWGPort:     w.GRPCWGPort,
+		GRPCWGPubKey:   w.GRPCWGPubKey,
+		GRPCWGEndpoint: s.APIHost,
+	}
 
 
-        accessToken.ServerConfig = servervals
-        accessToken.WG = wgvals
+	accessToken.ServerConfig = servervals
+	accessToken.WG = wgvals
 	accessToken.ClientConfig.Network = netID
 	accessToken.ClientConfig.Network = netID
 	accessToken.ClientConfig.Key = accesskey.Value
 	accessToken.ClientConfig.Key = accesskey.Value
 	accessToken.ClientConfig.LocalRange = privAddr
 	accessToken.ClientConfig.LocalRange = privAddr
 
 
-        tokenjson, err := json.Marshal(accessToken)
-        if err != nil {
-                return accesskey, err
-        }
+	tokenjson, err := json.Marshal(accessToken)
+	if err != nil {
+		return accesskey, err
+	}
 
 
-        accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
+	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
 
 
 	//validate accesskey
 	//validate accesskey
 	v := validator.New()
 	v := validator.New()
@@ -752,52 +797,51 @@ func GetSignupToken(netID string) (models.AccessKey, error) {
 
 
 	var accesskey models.AccessKey
 	var accesskey models.AccessKey
 	var accessToken models.AccessToken
 	var accessToken models.AccessToken
-        s := servercfg.GetServerConfig()
-        w := servercfg.GetWGConfig()
-        servervals := models.ServerConfig{
-                        APIConnString: s.APIConnString,
-                        APIHost: s.APIHost,
-                        APIPort: s.APIPort,
-                        GRPCConnString: s.GRPCConnString,
-                        GRPCHost: s.GRPCHost,
-                        GRPCPort: s.GRPCPort,
-                        GRPCSSL: s.GRPCSSL,
-                        }
-        wgvals := models.WG{
-                        GRPCWireGuard: w.GRPCWireGuard,
-                        GRPCWGAddress: w.GRPCWGAddress,
-                        GRPCWGPort: w.GRPCWGPort,
-                        GRPCWGPubKey: w.GRPCWGPubKey,
-                        GRPCWGEndpoint: s.APIHost,
-                }
-
-        accessToken.ServerConfig = servervals
-        accessToken.WG = wgvals
+	s := servercfg.GetServerConfig()
+	w := servercfg.GetWGConfig()
+	servervals := models.ServerConfig{
+		APIConnString:  s.APIConnString,
+		APIHost:        s.APIHost,
+		APIPort:        s.APIPort,
+		GRPCConnString: s.GRPCConnString,
+		GRPCHost:       s.GRPCHost,
+		GRPCPort:       s.GRPCPort,
+		GRPCSSL:        s.GRPCSSL,
+	}
+	wgvals := models.WG{
+		GRPCWireGuard:  w.GRPCWireGuard,
+		GRPCWGAddress:  w.GRPCWGAddress,
+		GRPCWGPort:     w.GRPCWGPort,
+		GRPCWGPubKey:   w.GRPCWGPubKey,
+		GRPCWGEndpoint: s.APIHost,
+	}
+
+	accessToken.ServerConfig = servervals
+	accessToken.WG = wgvals
 
 
 	tokenjson, err := json.Marshal(accessToken)
 	tokenjson, err := json.Marshal(accessToken)
-        if err != nil {
-                return accesskey, err
-        }
+	if err != nil {
+		return accesskey, err
+	}
 
 
-        accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
-        return accesskey, nil
+	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
+	return accesskey, nil
 }
 }
 func getSignupToken(w http.ResponseWriter, r *http.Request) {
 func getSignupToken(w http.ResponseWriter, r *http.Request) {
-        w.Header().Set("Content-Type", "application/json")
-        var params = mux.Vars(r)
-        netID := params["networkname"]
+	w.Header().Set("Content-Type", "application/json")
+	var params = mux.Vars(r)
+	netID := params["networkname"]
 
 
 	token, err := GetSignupToken(netID)
 	token, err := GetSignupToken(netID)
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "internal"))
-                return
-        }
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(token)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	functions.PrintUserLog(r.Header.Get("user"), "got signup token "+netID, 2)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(token)
 }
 }
 
 
-
-
 //pretty simple get
 //pretty simple get
 func getAccessKeys(w http.ResponseWriter, r *http.Request) {
 func getAccessKeys(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
@@ -808,6 +852,7 @@ func getAccessKeys(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "fetched access keys on network "+network, 2)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(keys)
 	json.NewEncoder(w).Encode(keys)
 }
 }
@@ -836,6 +881,7 @@ func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		return
 		return
 	}
 	}
+	functions.PrintUserLog(r.Header.Get("user"), "deleted access key "+keyname+" on network "+netname, 1)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 }
 }
 func DeleteKey(keyname, netname string) error {
 func DeleteKey(keyname, netname string) error {

+ 82 - 90
controllers/userHttpController.go

@@ -30,7 +30,7 @@ func userHandlers(r *mux.Router) {
 	r.HandleFunc("/api/users/{username}", authorizeUserAdm(http.HandlerFunc(createUser))).Methods("POST")
 	r.HandleFunc("/api/users/{username}", authorizeUserAdm(http.HandlerFunc(createUser))).Methods("POST")
 	r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(deleteUser))).Methods("DELETE")
 	r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(deleteUser))).Methods("DELETE")
 	r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(getUser))).Methods("GET")
 	r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(getUser))).Methods("GET")
-        r.HandleFunc("/api/users", authorizeUserAdm(http.HandlerFunc(getUsers))).Methods("GET")
+	r.HandleFunc("/api/users", authorizeUserAdm(http.HandlerFunc(getUsers))).Methods("GET")
 }
 }
 
 
 //Node authenticates using its password and retrieves a JWT for authorization.
 //Node authenticates using its password and retrieves a JWT for authorization.
@@ -112,7 +112,7 @@ func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
 	}
 	}
 
 
 	//Create a new JWT for the node
 	//Create a new JWT for the node
-	tokenString, _ := functions.CreateUserJWT(authRequest.UserName, result.Networks,  result.IsAdmin)
+	tokenString, _ := functions.CreateUserJWT(authRequest.UserName, result.Networks, result.IsAdmin)
 	return tokenString, nil
 	return tokenString, nil
 }
 }
 
 
@@ -126,7 +126,7 @@ func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
 func authorizeUser(next http.Handler) http.HandlerFunc {
 func authorizeUser(next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 	return func(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)
 
 
 		//get the auth token
 		//get the auth token
 		bearerToken := r.Header.Get("Authorization")
 		bearerToken := r.Header.Get("Authorization")
@@ -140,21 +140,20 @@ func authorizeUser(next http.Handler) http.HandlerFunc {
 }
 }
 
 
 func authorizeUserAdm(next http.Handler) http.HandlerFunc {
 func authorizeUserAdm(next http.Handler) http.HandlerFunc {
-        return func(w http.ResponseWriter, r *http.Request) {
-                w.Header().Set("Content-Type", "application/json")
-	        var params = mux.Vars(r)
-
-                //get the auth token
-                bearerToken := r.Header.Get("Authorization")
-                err := ValidateUserToken(bearerToken, params["username"], true)
-                if err != nil {
-                        returnErrorResponse(w, r, formatError(err, "unauthorized"))
-                        return
-                }
-                next.ServeHTTP(w, r)
-        }
-}
+	return func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		var params = mux.Vars(r)
 
 
+		//get the auth token
+		bearerToken := r.Header.Get("Authorization")
+		err := ValidateUserToken(bearerToken, params["username"], true)
+		if err != nil {
+			returnErrorResponse(w, r, formatError(err, "unauthorized"))
+			return
+		}
+		next.ServeHTTP(w, r)
+	}
+}
 
 
 func ValidateUserToken(token string, user string, adminonly bool) error {
 func ValidateUserToken(token string, user string, adminonly bool) error {
 	var tokenSplit = strings.Split(token, " ")
 	var tokenSplit = strings.Split(token, " ")
@@ -241,40 +240,39 @@ func GetUser(username string) (models.User, error) {
 
 
 func GetUsers() ([]models.User, error) {
 func GetUsers() ([]models.User, error) {
 
 
-        var users []models.User
+	var users []models.User
 
 
-        collection := mongoconn.Client.Database("netmaker").Collection("users")
+	collection := mongoconn.Client.Database("netmaker").Collection("users")
 
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
+	cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
 
 
-        if err != nil {
-                return users, err
-        }
+	if err != nil {
+		return users, err
+	}
 
 
-        defer cancel()
+	defer cancel()
 
 
-        for cur.Next(context.TODO()) {
+	for cur.Next(context.TODO()) {
 
 
-                var user models.User
-                err := cur.Decode(&user)
-                if err != nil {
-                        return users, err
-                }
+		var user models.User
+		err := cur.Decode(&user)
+		if err != nil {
+			return users, err
+		}
 
 
-                // add network our array
-                users = append(users, user)
-        }
+		// add network our array
+		users = append(users, user)
+	}
 
 
-        if err := cur.Err(); err != nil {
-                return users, err
-        }
+	if err := cur.Err(); err != nil {
+		return users, err
+	}
 
 
-        return users, err
+	return users, err
 }
 }
 
 
-
 //Get an individual node. Nothin fancy here folks.
 //Get an individual node. Nothin fancy here folks.
 func getUser(w http.ResponseWriter, r *http.Request) {
 func getUser(w http.ResponseWriter, r *http.Request) {
 	// set header.
 	// set header.
@@ -294,26 +292,21 @@ func getUser(w http.ResponseWriter, r *http.Request) {
 
 
 //Get an individual node. Nothin fancy here folks.
 //Get an individual node. Nothin fancy here folks.
 func getUsers(w http.ResponseWriter, r *http.Request) {
 func getUsers(w http.ResponseWriter, r *http.Request) {
-        // set header.
-        w.Header().Set("Content-Type", "application/json")
+	// set header.
+	w.Header().Set("Content-Type", "application/json")
 
 
-        users, err := GetUsers()
+	users, err := GetUsers()
 
 
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "internal"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 
 
-        json.NewEncoder(w).Encode(users)
+	json.NewEncoder(w).Encode(users)
 }
 }
 
 
-
 func CreateUser(user models.User) (models.User, error) {
 func CreateUser(user models.User) (models.User, error) {
-	hasadmin, err := HasAdmin()
-	if hasadmin && user.IsAdmin {
-		return models.User{}, errors.New("Admin already Exists")
-	}
-	err = ValidateUser("create", user)
+	err := ValidateUser("create", user)
 	if err != nil {
 	if err != nil {
 		return models.User{}, err
 		return models.User{}, err
 	}
 	}
@@ -326,7 +319,7 @@ func CreateUser(user models.User) (models.User, error) {
 	//set password to encrypted password
 	//set password to encrypted password
 	user.Password = string(hash)
 	user.Password = string(hash)
 
 
-	tokenString, _ := functions.CreateUserJWT(user.UserName,user.Networks, user.IsAdmin)
+	tokenString, _ := functions.CreateUserJWT(user.UserName, user.Networks, user.IsAdmin)
 
 
 	if tokenString == "" {
 	if tokenString == "" {
 		//returnErrorResponse(w, r, errorResponse)
 		//returnErrorResponse(w, r, errorResponse)
@@ -350,7 +343,7 @@ func createAdmin(w http.ResponseWriter, r *http.Request) {
 	var admin models.User
 	var admin models.User
 	//get node from body of request
 	//get node from body of request
 	_ = json.NewDecoder(r.Body).Decode(&admin)
 	_ = json.NewDecoder(r.Body).Decode(&admin)
-        admin.IsAdmin = true
+	admin.IsAdmin = true
 	admin, err := CreateUser(admin)
 	admin, err := CreateUser(admin)
 
 
 	if err != nil {
 	if err != nil {
@@ -362,23 +355,22 @@ func createAdmin(w http.ResponseWriter, r *http.Request) {
 }
 }
 
 
 func createUser(w http.ResponseWriter, r *http.Request) {
 func createUser(w http.ResponseWriter, r *http.Request) {
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
 
-        var user models.User
-        //get node from body of request
-        _ = json.NewDecoder(r.Body).Decode(&user)
+	var user models.User
+	//get node from body of request
+	_ = json.NewDecoder(r.Body).Decode(&user)
 
 
-        user, err := CreateUser(user)
+	user, err := CreateUser(user)
 
 
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "badrequest"))
-                return
-        }
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "badrequest"))
+		return
+	}
 
 
-        json.NewEncoder(w).Encode(user)
+	json.NewEncoder(w).Encode(user)
 }
 }
 
 
-
 func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 
 
 	err := ValidateUser("update", userchange)
 	err := ValidateUser("update", userchange)
@@ -391,9 +383,9 @@ func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 	if userchange.UserName != "" {
 	if userchange.UserName != "" {
 		user.UserName = userchange.UserName
 		user.UserName = userchange.UserName
 	}
 	}
-        if len(userchange.Networks) > 0  {
-                user.Networks = userchange.Networks
-        }
+	if len(userchange.Networks) > 0 {
+		user.Networks = userchange.Networks
+	}
 	if userchange.Password != "" {
 	if userchange.Password != "" {
 		//encrypt that password so we never see it again
 		//encrypt that password so we never see it again
 		hash, err := bcrypt.GenerateFromPassword([]byte(userchange.Password), 5)
 		hash, err := bcrypt.GenerateFromPassword([]byte(userchange.Password), 5)
@@ -467,28 +459,28 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
 }
 }
 
 
 func updateUserAdm(w http.ResponseWriter, r *http.Request) {
 func updateUserAdm(w http.ResponseWriter, r *http.Request) {
-        w.Header().Set("Content-Type", "application/json")
-        var params = mux.Vars(r)
-        var user models.User
-        //start here
-        user, err := GetUser(params["username"])
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "internal"))
-                return
-        }
-        var userchange models.User
-        // we decode our body request params
-        err = json.NewDecoder(r.Body).Decode(&userchange)
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "internal"))
-                return
-        }
+	w.Header().Set("Content-Type", "application/json")
+	var params = mux.Vars(r)
+	var user models.User
+	//start here
+	user, err := GetUser(params["username"])
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	var userchange models.User
+	// we decode our body request params
+	err = json.NewDecoder(r.Body).Decode(&userchange)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
 	user, err = UpdateUser(userchange, user)
 	user, err = UpdateUser(userchange, user)
-        if err != nil {
-                returnErrorResponse(w, r, formatError(err, "badrequest"))
-                return
-        }
-        json.NewEncoder(w).Encode(user)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "badrequest"))
+		return
+	}
+	json.NewEncoder(w).Encode(user)
 }
 }
 
 
 func DeleteUser(user string) (bool, error) {
 func DeleteUser(user string) (bool, error) {

+ 212 - 205
functions/helpers.go

@@ -14,6 +14,7 @@ import (
 	"net"
 	"net"
 	"strings"
 	"strings"
 	"time"
 	"time"
+
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mongoconn"
 	"github.com/gravitl/netmaker/mongoconn"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
@@ -23,17 +24,24 @@ import (
 	"go.mongodb.org/mongo-driver/mongo/options"
 	"go.mongodb.org/mongo-driver/mongo/options"
 )
 )
 
 
+func PrintUserLog(username string, message string, loglevel int) {
+	log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
+	if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
+		log.Println(username, message)
+	}
+}
+
 //Takes in an arbitrary field and value for field and checks to see if any other
 //Takes in an arbitrary field and value for field and checks to see if any other
 //node has that value for the same field within the network
 //node has that value for the same field within the network
 
 
 func SliceContains(slice []string, item string) bool {
 func SliceContains(slice []string, item string) bool {
-    set := make(map[string]struct{}, len(slice))
-    for _, s := range slice {
-        set[s] = struct{}{}
-    }
+	set := make(map[string]struct{}, len(slice))
+	for _, s := range slice {
+		set[s] = struct{}{}
+	}
 
 
-    _, ok := set[item] 
-    return ok
+	_, ok := set[item]
+	return ok
 }
 }
 
 
 func CreateServerToken(netID string) (string, error) {
 func CreateServerToken(netID string) (string, error) {
@@ -54,7 +62,7 @@ func CreateServerToken(netID string) (string, error) {
 	if *network.IsLocal {
 	if *network.IsLocal {
 		privAddr = network.LocalRange
 		privAddr = network.LocalRange
 	}
 	}
-        accessstringdec := address + "|"+ address + "|" + address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
+	accessstringdec := address + "|" + address + "|" + address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
 
 
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
 
 
@@ -86,85 +94,85 @@ func CreateServerToken(netID string) (string, error) {
 
 
 func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 func GetPeersList(networkName string) ([]models.PeersResponse, error) {
 
 
-        var peers []models.PeersResponse
+	var peers []models.PeersResponse
 
 
-        //Connection mongoDB with mongoconn class
-        collection := mongoconn.Client.Database("netmaker").Collection("nodes")
+	//Connection mongoDB with mongoconn class
+	collection := mongoconn.Client.Database("netmaker").Collection("nodes")
 
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        //Get all nodes in the relevant network which are NOT in pending state
-        filter := bson.M{"network": networkName, "ispending": false}
-        cur, err := collection.Find(ctx, filter)
+	//Get all nodes in the relevant network which are NOT in pending state
+	filter := bson.M{"network": networkName, "ispending": false}
+	cur, err := collection.Find(ctx, filter)
 
 
-        if err != nil {
-                return peers, err
-        }
+	if err != nil {
+		return peers, err
+	}
 
 
-        // Close the cursor once finished and cancel if it takes too long
-        defer cancel()
+	// Close the cursor once finished and cancel if it takes too long
+	defer cancel()
 
 
-        for cur.Next(context.TODO()) {
+	for cur.Next(context.TODO()) {
 
 
-                var peer models.PeersResponse
-                err := cur.Decode(&peer)
-                if err != nil {
-                        log.Fatal(err)
-                }
+		var peer models.PeersResponse
+		err := cur.Decode(&peer)
+		if err != nil {
+			log.Fatal(err)
+		}
 
 
-                // add the node to our node array
-                //maybe better to just return this? But then that's just GetNodes...
-                peers = append(peers, peer)
-        }
+		// add the node to our node array
+		//maybe better to just return this? But then that's just GetNodes...
+		peers = append(peers, peer)
+	}
 
 
-        //Uh oh, fatal error! This needs some better error handling
-        //TODO: needs appropriate error handling so the server doesnt shut down.
-        if err := cur.Err(); err != nil {
-                log.Fatal(err)
-        }
+	//Uh oh, fatal error! This needs some better error handling
+	//TODO: needs appropriate error handling so the server doesnt shut down.
+	if err := cur.Err(); err != nil {
+		log.Fatal(err)
+	}
 
 
-        return peers, err
+	return peers, err
 }
 }
 
 
 func GetIntPeersList() ([]models.PeersResponse, error) {
 func GetIntPeersList() ([]models.PeersResponse, error) {
 
 
-        var peers []models.PeersResponse
+	var peers []models.PeersResponse
 
 
-        collection := mongoconn.Client.Database("netmaker").Collection("intclients")
+	collection := mongoconn.Client.Database("netmaker").Collection("intclients")
 
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        filter := bson.M{"isserver": ""}
+	filter := bson.M{"isserver": ""}
 
 
-        cur, err := collection.Find(ctx, filter)
+	cur, err := collection.Find(ctx, filter)
 
 
-        if err != nil {
-                return peers, err
-        }
+	if err != nil {
+		return peers, err
+	}
 
 
-        // Close the cursor once finished and cancel if it takes too long
-        defer cancel()
+	// Close the cursor once finished and cancel if it takes too long
+	defer cancel()
 
 
-        for cur.Next(context.TODO()) {
+	for cur.Next(context.TODO()) {
 
 
-                var peer models.PeersResponse
-                err := cur.Decode(&peer)
-                if err != nil {
-                        log.Fatal(err)
-                }
+		var peer models.PeersResponse
+		err := cur.Decode(&peer)
+		if err != nil {
+			log.Fatal(err)
+		}
 
 
-                // add the node to our node array
-                //maybe better to just return this? But then that's just GetNodes...
-                peers = append(peers, peer)
-        }
+		// add the node to our node array
+		//maybe better to just return this? But then that's just GetNodes...
+		peers = append(peers, peer)
+	}
 
 
-        //Uh oh, fatal error! This needs some better error handling
-        //TODO: needs appropriate error handling so the server doesnt shut down.
-        if err := cur.Err(); err != nil {
-                log.Fatal(err)
-        }
+	//Uh oh, fatal error! This needs some better error handling
+	//TODO: needs appropriate error handling so the server doesnt shut down.
+	if err := cur.Err(); err != nil {
+		log.Fatal(err)
+	}
 
 
-        return peers, err
+	return peers, err
 }
 }
 
 
 func IsFieldUnique(network string, field string, value string) bool {
 func IsFieldUnique(network string, field string, value string) bool {
@@ -194,23 +202,23 @@ func IsFieldUnique(network string, field string, value string) bool {
 
 
 func ServerIntClientExists() (bool, error) {
 func ServerIntClientExists() (bool, error) {
 
 
-        collection := mongoconn.Client.Database("netmaker").Collection("intclients")
+	collection := mongoconn.Client.Database("netmaker").Collection("intclients")
 
 
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        filter := bson.M{"isserver": "yes"}
+	filter := bson.M{"isserver": "yes"}
 
 
-        var result bson.M
-        err := collection.FindOne(ctx, filter).Decode(&result)
+	var result bson.M
+	err := collection.FindOne(ctx, filter).Decode(&result)
 
 
-        defer cancel()
+	defer cancel()
 
 
-        if err != nil {
-                if err == mongo.ErrNoDocuments {
-                        return false, nil
-                }
-        }
-        return true, err
+	if err != nil {
+		if err == mongo.ErrNoDocuments {
+			return false, nil
+		}
+	}
+	return true, err
 }
 }
 
 
 func NetworkExists(name string) (bool, error) {
 func NetworkExists(name string) (bool, error) {
@@ -453,27 +461,29 @@ func IsKeyValid(networkname string, keyvalue string) bool {
 
 
 func IsKeyValidGlobal(keyvalue string) bool {
 func IsKeyValidGlobal(keyvalue string) bool {
 
 
-        networks, _ := ListNetworks()
-        var key models.AccessKey
-        foundkey := false
-        isvalid := false
+	networks, _ := ListNetworks()
+	var key models.AccessKey
+	foundkey := false
+	isvalid := false
 	for _, network := range networks {
 	for _, network := range networks {
 		for i := len(network.AccessKeys) - 1; i >= 0; i-- {
 		for i := len(network.AccessKeys) - 1; i >= 0; i-- {
-	                currentkey := network.AccessKeys[i]
-	                if currentkey.Value == keyvalue {
-	                        key = currentkey
-	                        foundkey = true
+			currentkey := network.AccessKeys[i]
+			if currentkey.Value == keyvalue {
+				key = currentkey
+				foundkey = true
 				break
 				break
-	                }
-	        }
-		if foundkey { break }
-	}
-        if foundkey {
-                if key.Uses > 0 {
-                        isvalid = true
-                }
-        }
-        return isvalid
+			}
+		}
+		if foundkey {
+			break
+		}
+	}
+	if foundkey {
+		if key.Uses > 0 {
+			isvalid = true
+		}
+	}
+	return isvalid
 }
 }
 
 
 //TODO: Contains a fatal error return. Need to change
 //TODO: Contains a fatal error return. Need to change
@@ -614,71 +624,70 @@ func GetNodeByMacAddress(network string, macaddress string) (models.Node, error)
 }
 }
 
 
 func DeleteAllIntClients() error {
 func DeleteAllIntClients() error {
-        collection := mongoconn.Client.Database("netmaker").Collection("intclients")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-        // Filter out them ID's again
-        err := collection.Drop(ctx)
-        if err != nil {
-                return err
-        }
-        defer cancel()
-        return nil
+	collection := mongoconn.Client.Database("netmaker").Collection("intclients")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	// Filter out them ID's again
+	err := collection.Drop(ctx)
+	if err != nil {
+		return err
+	}
+	defer cancel()
+	return nil
 }
 }
 
 
 func GetAllIntClients() ([]models.IntClient, error) {
 func GetAllIntClients() ([]models.IntClient, error) {
-        var client models.IntClient
-        var clients []models.IntClient
-        collection := mongoconn.Client.Database("netmaker").Collection("intclients")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-        // Filter out them ID's again
-        cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
-        if err != nil {
-                return []models.IntClient{}, err
-        }
-        defer cancel()
-        for cur.Next(context.TODO()) {
-                err := cur.Decode(&client)
-                if err != nil {
-                        return []models.IntClient{}, err
-                }
-                // add node to our array
-                clients = append(clients, client)
-        }
-
-        //TODO: Fatal error
-        if err := cur.Err(); err != nil {
-                return []models.IntClient{}, err
-        }
-        return clients, nil
+	var client models.IntClient
+	var clients []models.IntClient
+	collection := mongoconn.Client.Database("netmaker").Collection("intclients")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	// Filter out them ID's again
+	cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
+	if err != nil {
+		return []models.IntClient{}, err
+	}
+	defer cancel()
+	for cur.Next(context.TODO()) {
+		err := cur.Decode(&client)
+		if err != nil {
+			return []models.IntClient{}, err
+		}
+		// add node to our array
+		clients = append(clients, client)
+	}
+
+	//TODO: Fatal error
+	if err := cur.Err(); err != nil {
+		return []models.IntClient{}, err
+	}
+	return clients, nil
 }
 }
 
 
 func GetAllExtClients() ([]models.ExtClient, error) {
 func GetAllExtClients() ([]models.ExtClient, error) {
-        var extclient models.ExtClient
-        var extclients []models.ExtClient
-        collection := mongoconn.Client.Database("netmaker").Collection("extclients")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-        // Filter out them ID's again
-        cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
-        if err != nil {
-                return []models.ExtClient{}, err
-        }
-        defer cancel()
-        for cur.Next(context.TODO()) {
-                err := cur.Decode(&extclient)
-                if err != nil {
-                        return []models.ExtClient{}, err
-                }
-                // add node to our array
-                extclients = append(extclients, extclient)
-        }
-
-        //TODO: Fatal error
-        if err := cur.Err(); err != nil {
-                return []models.ExtClient{}, err
-        }
-        return extclients, nil
-}
+	var extclient models.ExtClient
+	var extclients []models.ExtClient
+	collection := mongoconn.Client.Database("netmaker").Collection("extclients")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	// Filter out them ID's again
+	cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
+	if err != nil {
+		return []models.ExtClient{}, err
+	}
+	defer cancel()
+	for cur.Next(context.TODO()) {
+		err := cur.Decode(&extclient)
+		if err != nil {
+			return []models.ExtClient{}, err
+		}
+		// add node to our array
+		extclients = append(extclients, extclient)
+	}
 
 
+	//TODO: Fatal error
+	if err := cur.Err(); err != nil {
+		return []models.ExtClient{}, err
+	}
+	return extclients, nil
+}
 
 
 //This returns a unique address for a node to use
 //This returns a unique address for a node to use
 //it iterates through the list of IP's in the subnet
 //it iterates through the list of IP's in the subnet
@@ -705,15 +714,15 @@ func UniqueAddress(networkName string) (string, error) {
 			offset = false
 			offset = false
 			continue
 			continue
 		}
 		}
-                if networkName == "comms" {
-                        if IsIPUniqueClients(networkName, ip.String()) {
-                                return ip.String(), err
-                        }
-                } else {
-                        if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) {
-                                return ip.String(), err
-                        }
-                }
+		if networkName == "comms" {
+			if IsIPUniqueClients(networkName, ip.String()) {
+				return ip.String(), err
+			}
+		} else {
+			if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) {
+				return ip.String(), err
+			}
+		}
 	}
 	}
 
 
 	//TODO
 	//TODO
@@ -747,9 +756,9 @@ func UniqueAddress6(networkName string) (string, error) {
 			continue
 			continue
 		}
 		}
 		if networkName == "comms" {
 		if networkName == "comms" {
-	                if IsIP6UniqueClients(networkName, ip.String()) {
-	                        return ip.String(), err
-	                }
+			if IsIP6UniqueClients(networkName, ip.String()) {
+				return ip.String(), err
+			}
 		} else {
 		} else {
 			if IsIP6Unique(networkName, ip.String()) {
 			if IsIP6Unique(networkName, ip.String()) {
 				return ip.String(), err
 				return ip.String(), err
@@ -798,30 +807,29 @@ func GenKeyName() string {
 
 
 func IsIPUniqueExtClients(network string, ip string) bool {
 func IsIPUniqueExtClients(network string, ip string) bool {
 
 
-        var extclient models.ExtClient
+	var extclient models.ExtClient
 
 
-        isunique := true
+	isunique := true
 
 
-        collection := mongoconn.Client.Database("netmaker").Collection("extclients")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	collection := mongoconn.Client.Database("netmaker").Collection("extclients")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        filter := bson.M{"address": ip, "network": network}
+	filter := bson.M{"address": ip, "network": network}
 
 
-        err := collection.FindOne(ctx, filter).Decode(&extclient)
+	err := collection.FindOne(ctx, filter).Decode(&extclient)
 
 
-        defer cancel()
+	defer cancel()
 
 
-        if err != nil {
-                return isunique
-        }
+	if err != nil {
+		return isunique
+	}
 
 
-        if extclient.Address == ip {
-                isunique = false
-        }
-        return isunique
+	if extclient.Address == ip {
+		isunique = false
+	}
+	return isunique
 }
 }
 
 
-
 //checks if IP is unique in the address range
 //checks if IP is unique in the address range
 //used by UniqueAddress
 //used by UniqueAddress
 func IsIPUnique(network string, ip string) bool {
 func IsIPUnique(network string, ip string) bool {
@@ -880,54 +888,54 @@ func IsIP6Unique(network string, ip string) bool {
 //used by UniqueAddress
 //used by UniqueAddress
 func IsIP6UniqueClients(network string, ip string) bool {
 func IsIP6UniqueClients(network string, ip string) bool {
 
 
-        var client models.IntClient
+	var client models.IntClient
 
 
-        isunique := true
+	isunique := true
 
 
-        collection := mongoconn.Client.Database("netmaker").Collection("intclients")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	collection := mongoconn.Client.Database("netmaker").Collection("intclients")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        filter := bson.M{"address6": ip, "network": network}
+	filter := bson.M{"address6": ip, "network": network}
 
 
-        err := collection.FindOne(ctx, filter).Decode(&client)
+	err := collection.FindOne(ctx, filter).Decode(&client)
 
 
-        defer cancel()
+	defer cancel()
 
 
-        if err != nil {
-                return isunique
-        }
+	if err != nil {
+		return isunique
+	}
 
 
-        if client.Address6 == ip {
-                isunique = false
-        }
-        return isunique
+	if client.Address6 == ip {
+		isunique = false
+	}
+	return isunique
 }
 }
 
 
 //checks if IP is unique in the address range
 //checks if IP is unique in the address range
 //used by UniqueAddress
 //used by UniqueAddress
 func IsIPUniqueClients(network string, ip string) bool {
 func IsIPUniqueClients(network string, ip string) bool {
 
 
-        var client models.IntClient
+	var client models.IntClient
 
 
-        isunique := true
+	isunique := true
 
 
-        collection := mongoconn.Client.Database("netmaker").Collection("intclients")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	collection := mongoconn.Client.Database("netmaker").Collection("intclients")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
-        filter := bson.M{"address": ip, "network": network}
+	filter := bson.M{"address": ip, "network": network}
 
 
-        err := collection.FindOne(ctx, filter).Decode(&client)
+	err := collection.FindOne(ctx, filter).Decode(&client)
 
 
-        defer cancel()
+	defer cancel()
 
 
-        if err != nil {
-                return isunique
-        }
+	if err != nil {
+		return isunique
+	}
 
 
-        if client.Address == ip {
-                isunique = false
-        }
-        return isunique
+	if client.Address == ip {
+		isunique = false
+	}
+	return isunique
 }
 }
 
 
 //called once key has been used by createNode
 //called once key has been used by createNode
@@ -1040,4 +1048,3 @@ func GetAllNodes() ([]models.Node, error) {
 	}
 	}
 	return nodes, nil
 	return nodes, nil
 }
 }
-

+ 4 - 4
go.mod

@@ -6,16 +6,16 @@ require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-playground/validator/v10 v10.5.0
 	github.com/go-playground/validator/v10 v10.5.0
-	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/golang/protobuf v1.5.2
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
 	github.com/gorilla/mux v1.8.0
 	github.com/jinzhu/copier v0.3.2 // indirect
 	github.com/jinzhu/copier v0.3.2 // indirect
-	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
+	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.6.1
 	github.com/stretchr/testify v1.6.1
 	github.com/txn2/txeh v1.3.0
 	github.com/txn2/txeh v1.3.0
 	github.com/urfave/cli v1.22.5 // indirect
 	github.com/urfave/cli v1.22.5 // indirect
-	github.com/urfave/cli/v2 v2.3.0 // indirect
-	github.com/vishvananda/netlink v1.1.0 // indirect
+	github.com/urfave/cli/v2 v2.3.0
+	github.com/vishvananda/netlink v1.1.0
 	go.mongodb.org/mongo-driver v1.4.3
 	go.mongodb.org/mongo-driver v1.4.3
 	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
 	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
 	golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
 	golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect

+ 1 - 1
models/structs.go

@@ -8,7 +8,7 @@ type AuthParams struct {
 }
 }
 
 
 type User struct {
 type User struct {
-	UserName string `json:"username" bson:"username" validate:"alphanum,min=3"`
+	UserName string `json:"username" bson:"username" validate:"min=3,max=40,regexp=^(([a-zA-Z,\-,\.]*)|([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})){3,40}$"`
 	Password string `json:"password" bson:"password" validate:"required,min=5"`
 	Password string `json:"password" bson:"password" validate:"required,min=5"`
 	Networks []string `json:"networks" bson:"networks"`
 	Networks []string `json:"networks" bson:"networks"`
 	IsAdmin  bool   `json:"isadmin" bson:"isadmin"`
 	IsAdmin  bool   `json:"isadmin" bson:"isadmin"`

+ 182 - 170
servercfg/serverconf.go

@@ -1,12 +1,13 @@
 package servercfg
 package servercfg
 
 
 import (
 import (
-        "github.com/gravitl/netmaker/config"
-	"net/http"
+	"errors"
 	"io/ioutil"
 	"io/ioutil"
+	"net/http"
 	"os"
 	"os"
-	"errors"
 	"strconv"
 	"strconv"
+
+	"github.com/gravitl/netmaker/config"
 )
 )
 
 
 func SetHost() error {
 func SetHost() error {
@@ -28,105 +29,106 @@ func GetServerConfig() config.ServerConfig {
 	cfg.MasterKey = "(hidden)"
 	cfg.MasterKey = "(hidden)"
 	cfg.AllowedOrigin = GetAllowedOrigin()
 	cfg.AllowedOrigin = GetAllowedOrigin()
 	cfg.RestBackend = "off"
 	cfg.RestBackend = "off"
+	cfg.Verbosity = GetVerbose()
 	if IsRestBackend() {
 	if IsRestBackend() {
 		cfg.RestBackend = "on"
 		cfg.RestBackend = "on"
 	}
 	}
 	cfg.AgentBackend = "off"
 	cfg.AgentBackend = "off"
-        if IsAgentBackend() {
-                cfg.AgentBackend = "on"
-        }
+	if IsAgentBackend() {
+		cfg.AgentBackend = "on"
+	}
 	cfg.ClientMode = "off"
 	cfg.ClientMode = "off"
 	if IsClientMode() {
 	if IsClientMode() {
 		cfg.ClientMode = "on"
 		cfg.ClientMode = "on"
 	}
 	}
 	cfg.DNSMode = "off"
 	cfg.DNSMode = "off"
 	if IsDNSMode() {
 	if IsDNSMode() {
-	        cfg.DNSMode = "on"
+		cfg.DNSMode = "on"
+	}
+	cfg.GRPCSSL = "off"
+	if IsGRPCSSL() {
+		cfg.GRPCSSL = "on"
 	}
 	}
-        cfg.GRPCSSL = "off"
-        if IsGRPCSSL() {
-                cfg.GRPCSSL = "on"
-        }
 	cfg.DisableRemoteIPCheck = "off"
 	cfg.DisableRemoteIPCheck = "off"
 	if DisableRemoteIPCheck() {
 	if DisableRemoteIPCheck() {
 		cfg.DisableRemoteIPCheck = "on"
 		cfg.DisableRemoteIPCheck = "on"
 	}
 	}
-        cfg.DisableDefaultNet = "off"
-        if DisableDefaultNet() {
-                cfg.DisableRemoteIPCheck = "on"
-        }
+	cfg.DisableDefaultNet = "off"
+	if DisableDefaultNet() {
+		cfg.DisableRemoteIPCheck = "on"
+	}
 	return cfg
 	return cfg
 }
 }
 
 
-func GetWGConfig() config.WG{
+func GetWGConfig() config.WG {
 	var cfg config.WG
 	var cfg config.WG
 	if IsGRPCWireGuard() {
 	if IsGRPCWireGuard() {
 		cfg.GRPCWireGuard = "on"
 		cfg.GRPCWireGuard = "on"
 	} else {
 	} else {
-                cfg.GRPCWireGuard = "off"
+		cfg.GRPCWireGuard = "off"
 	}
 	}
 	cfg.GRPCWGInterface = GetGRPCWGInterface()
 	cfg.GRPCWGInterface = GetGRPCWGInterface()
 	cfg.GRPCWGAddress = GetGRPCWGAddress()
 	cfg.GRPCWGAddress = GetGRPCWGAddress()
-        cfg.GRPCWGAddressRange = GetGRPCWGAddressRange()
+	cfg.GRPCWGAddressRange = GetGRPCWGAddressRange()
 	cfg.GRPCWGPort = GetGRPCWGPort()
 	cfg.GRPCWGPort = GetGRPCWGPort()
-	cfg.GRPCWGPubKey =  GetGRPCWGPubKey()
-	cfg.GRPCWGPrivKey =  GetGRPCWGPrivKey()
+	cfg.GRPCWGPubKey = GetGRPCWGPubKey()
+	cfg.GRPCWGPrivKey = GetGRPCWGPrivKey()
 	return cfg
 	return cfg
 }
 }
 func GetAPIConnString() string {
 func GetAPIConnString() string {
-        conn := ""
-        if os.Getenv("SERVER_API_CONN_STRING") != ""  {
-                conn = os.Getenv("SERVER_API_CONN_STRING")
-        } else if config.Config.Server.APIConnString != "" {
-                conn = config.Config.Server.APIConnString
-        }
-        return conn
+	conn := ""
+	if os.Getenv("SERVER_API_CONN_STRING") != "" {
+		conn = os.Getenv("SERVER_API_CONN_STRING")
+	} else if config.Config.Server.APIConnString != "" {
+		conn = config.Config.Server.APIConnString
+	}
+	return conn
 }
 }
 func GetAPIHost() string {
 func GetAPIHost() string {
-        serverhost := "127.0.0.1"
-        if os.Getenv("SERVER_HTTP_HOST") != ""  {
-                serverhost = os.Getenv("SERVER_HTTP_HOST")
-        } else if config.Config.Server.APIHost != "" {
+	serverhost := "127.0.0.1"
+	if os.Getenv("SERVER_HTTP_HOST") != "" {
+		serverhost = os.Getenv("SERVER_HTTP_HOST")
+	} else if config.Config.Server.APIHost != "" {
 		serverhost = config.Config.Server.APIHost
 		serverhost = config.Config.Server.APIHost
-        } else if os.Getenv("SERVER_HOST") != ""  {
-                serverhost = os.Getenv("SERVER_HOST")
-        } else {
-                remoteip, _ := GetPublicIP()
-                if remoteip != "" {
-                        serverhost = remoteip
-                }
-        }
+	} else if os.Getenv("SERVER_HOST") != "" {
+		serverhost = os.Getenv("SERVER_HOST")
+	} else {
+		remoteip, _ := GetPublicIP()
+		if remoteip != "" {
+			serverhost = remoteip
+		}
+	}
 	return serverhost
 	return serverhost
 }
 }
 func GetAPIPort() string {
 func GetAPIPort() string {
 	apiport := "8081"
 	apiport := "8081"
 	if os.Getenv("API_PORT") != "" {
 	if os.Getenv("API_PORT") != "" {
 		apiport = os.Getenv("API_PORT")
 		apiport = os.Getenv("API_PORT")
-	} else if  config.Config.Server.APIPort != "" {
+	} else if config.Config.Server.APIPort != "" {
 		apiport = config.Config.Server.APIPort
 		apiport = config.Config.Server.APIPort
 	}
 	}
 	return apiport
 	return apiport
 }
 }
 
 
 func GetDefaultNodeLimit() int32 {
 func GetDefaultNodeLimit() int32 {
-        var limit int32
+	var limit int32
 	limit = 999999999
 	limit = 999999999
 	envlimit, err := strconv.Atoi(os.Getenv("DEFAULT_NODE_LIMIT"))
 	envlimit, err := strconv.Atoi(os.Getenv("DEFAULT_NODE_LIMIT"))
 	if err == nil && envlimit != 0 {
 	if err == nil && envlimit != 0 {
-                limit = int32(envlimit)
-        } else if  config.Config.Server.DefaultNodeLimit != 0 {
-                limit = config.Config.Server.DefaultNodeLimit
-        }
-        return limit
+		limit = int32(envlimit)
+	} else if config.Config.Server.DefaultNodeLimit != 0 {
+		limit = config.Config.Server.DefaultNodeLimit
+	}
+	return limit
 }
 }
 func GetGRPCConnString() string {
 func GetGRPCConnString() string {
-        conn := ""
-        if os.Getenv("SERVER_GRPC_CONN_STRING") != ""  {
-                conn = os.Getenv("SERVER_GRPC_CONN_STRING")
-        } else if config.Config.Server.GRPCConnString != "" {
-                conn = config.Config.Server.GRPCConnString
-        }
-        return conn
+	conn := ""
+	if os.Getenv("SERVER_GRPC_CONN_STRING") != "" {
+		conn = os.Getenv("SERVER_GRPC_CONN_STRING")
+	} else if config.Config.Server.GRPCConnString != "" {
+		conn = config.Config.Server.GRPCConnString
+	}
+	return conn
 }
 }
 
 
 func GetGRPCHost() string {
 func GetGRPCHost() string {
@@ -134,51 +136,51 @@ func GetGRPCHost() string {
 	if IsGRPCWireGuard() {
 	if IsGRPCWireGuard() {
 		serverhost = GetGRPCWGAddress()
 		serverhost = GetGRPCWGAddress()
 	} else {
 	} else {
-		if os.Getenv("SERVER_GRPC_HOST") != ""  {
+		if os.Getenv("SERVER_GRPC_HOST") != "" {
 			serverhost = os.Getenv("SERVER_GRPC_HOST")
 			serverhost = os.Getenv("SERVER_GRPC_HOST")
 		} else if config.Config.Server.GRPCHost != "" {
 		} else if config.Config.Server.GRPCHost != "" {
-		       serverhost = config.Config.Server.GRPCHost
-		} else if os.Getenv("SERVER_HOST") != ""  {
-		       serverhost = os.Getenv("SERVER_HOST")
+			serverhost = config.Config.Server.GRPCHost
+		} else if os.Getenv("SERVER_HOST") != "" {
+			serverhost = os.Getenv("SERVER_HOST")
 		} else {
 		} else {
-		        remoteip, _ := GetPublicIP()
+			remoteip, _ := GetPublicIP()
 			if remoteip != "" {
 			if remoteip != "" {
 				serverhost = remoteip
 				serverhost = remoteip
 			}
 			}
 		}
 		}
 	}
 	}
-        return serverhost
+	return serverhost
 }
 }
 func GetGRPCPort() string {
 func GetGRPCPort() string {
-        grpcport := "50051"
+	grpcport := "50051"
 	if os.Getenv("GRPC_PORT") != "" {
 	if os.Getenv("GRPC_PORT") != "" {
-	        grpcport = os.Getenv("GRPC_PORT")
-	} else if  config.Config.Server.GRPCPort != "" {
-	        grpcport = config.Config.Server.GRPCPort
+		grpcport = os.Getenv("GRPC_PORT")
+	} else if config.Config.Server.GRPCPort != "" {
+		grpcport = config.Config.Server.GRPCPort
 	}
 	}
-        return grpcport
+	return grpcport
 }
 }
 func GetMasterKey() string {
 func GetMasterKey() string {
-        key := "secretkey"
-        if os.Getenv("MASTER_KEY") != "" {
-                key = os.Getenv("MASTER_KEY")
-        } else if  config.Config.Server.MasterKey != "" {
-                key = config.Config.Server.MasterKey
-        }
-        return key
+	key := "secretkey"
+	if os.Getenv("MASTER_KEY") != "" {
+		key = os.Getenv("MASTER_KEY")
+	} else if config.Config.Server.MasterKey != "" {
+		key = config.Config.Server.MasterKey
+	}
+	return key
 }
 }
 func GetAllowedOrigin() string {
 func GetAllowedOrigin() string {
-        allowedorigin := "*"
-        if os.Getenv("CORS_ALLOWED_ORIGIN") != "" {
-                allowedorigin = os.Getenv("CORS_ALLOWED_ORIGIN")
-        } else if  config.Config.Server.AllowedOrigin != "" {
-                allowedorigin = config.Config.Server.AllowedOrigin
-        }
-        return allowedorigin
+	allowedorigin := "*"
+	if os.Getenv("CORS_ALLOWED_ORIGIN") != "" {
+		allowedorigin = os.Getenv("CORS_ALLOWED_ORIGIN")
+	} else if config.Config.Server.AllowedOrigin != "" {
+		allowedorigin = config.Config.Server.AllowedOrigin
+	}
+	return allowedorigin
 }
 }
 func IsRestBackend() bool {
 func IsRestBackend() bool {
-        isrest := true
-        if os.Getenv("REST_BACKEND") != "" {
+	isrest := true
+	if os.Getenv("REST_BACKEND") != "" {
 		if os.Getenv("REST_BACKEND") == "off" {
 		if os.Getenv("REST_BACKEND") == "off" {
 			isrest = false
 			isrest = false
 		}
 		}
@@ -186,113 +188,123 @@ func IsRestBackend() bool {
 		if config.Config.Server.RestBackend == "off" {
 		if config.Config.Server.RestBackend == "off" {
 			isrest = false
 			isrest = false
 		}
 		}
-       }
-       return isrest
+	}
+	return isrest
 }
 }
 func IsAgentBackend() bool {
 func IsAgentBackend() bool {
-        isagent := true
-        if os.Getenv("AGENT_BACKEND") != "" {
-                if os.Getenv("AGENT_BACKEND") == "off" {
-                        isagent = false
-                }
-        } else if config.Config.Server.AgentBackend != "" {
-                if config.Config.Server.AgentBackend == "off" {
-                        isagent = false
-                }
-       }
-       return isagent
+	isagent := true
+	if os.Getenv("AGENT_BACKEND") != "" {
+		if os.Getenv("AGENT_BACKEND") == "off" {
+			isagent = false
+		}
+	} else if config.Config.Server.AgentBackend != "" {
+		if config.Config.Server.AgentBackend == "off" {
+			isagent = false
+		}
+	}
+	return isagent
 }
 }
 func IsClientMode() bool {
 func IsClientMode() bool {
-        isclient := true
-        if os.Getenv("CLIENT_MODE") != "" {
-                if os.Getenv("CLIENT_MODE") == "off" {
-                        isclient = false
-                }
-        } else if config.Config.Server.ClientMode != "" {
-                if config.Config.Server.ClientMode == "off" {
-                        isclient = false
-                }
-       }
-       return isclient
+	isclient := true
+	if os.Getenv("CLIENT_MODE") != "" {
+		if os.Getenv("CLIENT_MODE") == "off" {
+			isclient = false
+		}
+	} else if config.Config.Server.ClientMode != "" {
+		if config.Config.Server.ClientMode == "off" {
+			isclient = false
+		}
+	}
+	return isclient
 }
 }
 func IsDNSMode() bool {
 func IsDNSMode() bool {
-        isdns := true
-        if os.Getenv("DNS_MODE") != "" {
-                if os.Getenv("DNS_MODE") == "off" {
-                        isdns = false
-                }
-        } else if config.Config.Server.DNSMode != "" {
-                if config.Config.Server.DNSMode == "off" {
-                        isdns = false
-                }
-       }
-       return isdns
+	isdns := true
+	if os.Getenv("DNS_MODE") != "" {
+		if os.Getenv("DNS_MODE") == "off" {
+			isdns = false
+		}
+	} else if config.Config.Server.DNSMode != "" {
+		if config.Config.Server.DNSMode == "off" {
+			isdns = false
+		}
+	}
+	return isdns
 }
 }
 
 
 func IsGRPCSSL() bool {
 func IsGRPCSSL() bool {
-        isssl := false
-        if os.Getenv("GRPC_SSL") != "" {
-                if os.Getenv("GRPC_SSL") == "on" {
-                        isssl = true
-                }
-        } else if config.Config.Server.DNSMode != "" {
-                if config.Config.Server.DNSMode == "on" {
-                        isssl = true
-                }
-       }
-       return isssl
+	isssl := false
+	if os.Getenv("GRPC_SSL") != "" {
+		if os.Getenv("GRPC_SSL") == "on" {
+			isssl = true
+		}
+	} else if config.Config.Server.DNSMode != "" {
+		if config.Config.Server.DNSMode == "on" {
+			isssl = true
+		}
+	}
+	return isssl
 }
 }
 
 
 func DisableRemoteIPCheck() bool {
 func DisableRemoteIPCheck() bool {
-        disabled := false
-        if os.Getenv("DISABLE_REMOTE_IP_CHECK") != "" {
-                if os.Getenv("DISABLE_REMOTE_IP_CHECK") == "on" {
-                        disabled = true
-                }
-        } else if config.Config.Server.DisableRemoteIPCheck != "" {
-                if config.Config.Server.DisableRemoteIPCheck == "on" {
-                        disabled= true
-                }
-       }
-       return disabled
+	disabled := false
+	if os.Getenv("DISABLE_REMOTE_IP_CHECK") != "" {
+		if os.Getenv("DISABLE_REMOTE_IP_CHECK") == "on" {
+			disabled = true
+		}
+	} else if config.Config.Server.DisableRemoteIPCheck != "" {
+		if config.Config.Server.DisableRemoteIPCheck == "on" {
+			disabled = true
+		}
+	}
+	return disabled
 }
 }
 func DisableDefaultNet() bool {
 func DisableDefaultNet() bool {
-        disabled := false
-        if os.Getenv("DISABLE_DEFAULT_NET") != "" {
-                if os.Getenv("DISABLE_DEFAULT_NET") == "on" {
-                        disabled = true
-                }
-        } else if config.Config.Server.DisableDefaultNet != "" {
-                if config.Config.Server.DisableDefaultNet == "on" {
-                        disabled= true
-                }
-       }
-       return disabled
+	disabled := false
+	if os.Getenv("DISABLE_DEFAULT_NET") != "" {
+		if os.Getenv("DISABLE_DEFAULT_NET") == "on" {
+			disabled = true
+		}
+	} else if config.Config.Server.DisableDefaultNet != "" {
+		if config.Config.Server.DisableDefaultNet == "on" {
+			disabled = true
+		}
+	}
+	return disabled
 }
 }
 func GetPublicIP() (string, error) {
 func GetPublicIP() (string, error) {
 
 
-        endpoint := ""
-        var err error
+	endpoint := ""
+	var err error
 
 
-        iplist := []string{"http://ip.server.gravitl.com", "https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
-        for _, ipserver := range iplist {
-                resp, err := http.Get(ipserver)
-                if err != nil {
-                        continue
-                }
-                defer resp.Body.Close()
-                if resp.StatusCode == http.StatusOK {
-                        bodyBytes, err := ioutil.ReadAll(resp.Body)
-                        if err != nil {
-                                continue
-                        }
-                        endpoint = string(bodyBytes)
-                        break
-                }
+	iplist := []string{"http://ip.server.gravitl.com", "https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
+	for _, ipserver := range iplist {
+		resp, err := http.Get(ipserver)
+		if err != nil {
+			continue
+		}
+		defer resp.Body.Close()
+		if resp.StatusCode == http.StatusOK {
+			bodyBytes, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				continue
+			}
+			endpoint = string(bodyBytes)
+			break
+		}
 
 
-        }
-        if err == nil && endpoint == "" {
-                err =  errors.New("Public Address Not Found.")
-        }
-        return endpoint, err
+	}
+	if err == nil && endpoint == "" {
+		err = errors.New("Public Address Not Found.")
+	}
+	return endpoint, err
+}
+func GetVerbose() int32 {
+	level, err := strconv.Atoi(os.Getenv("VERBOSITY"))
+	if err != nil || level < 0 {
+		level = 0
+	}
+	if level > 3 {
+		level = 3
+	}
+	return int32(level)
 }
 }

+ 2 - 2
test/nodecreate.sh

@@ -3,7 +3,7 @@
 PUBKEY="DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34="
 PUBKEY="DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34="
 IPADDR="69.173.21.202"
 IPADDR="69.173.21.202"
 MACADDRESS="59:2a:9c:d4:e2:49"
 MACADDRESS="59:2a:9c:d4:e2:49"
-ACCESSKEY="F5LjPlgHHgi1zpir"
+ACCESSKEY="9ktiHcUWay2MSKsY"
 PASSWORD="ppppppp"
 PASSWORD="ppppppp"
 
 
 generate_post_json ()
 generate_post_json ()
@@ -22,5 +22,5 @@ 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 mastertoken" localhost:8081/api/nodes/skynet
+curl --max-time 5.0 -d "$POST_JSON" -H 'Content-Type: application/json' -H "authorization: Bearer secretkey" localhost:8081/api/nodes/default