Browse Source

Fix Access Key tests

Matthew R Kasun 4 years ago
parent
commit
699619a371

+ 96 - 122
controllers/networkHttpController.go

@@ -186,52 +186,54 @@ func ValidateNetworkCreate(network models.Network) error {
 
 
 //Simple get network function
 //Simple get network function
 func getNetwork(w http.ResponseWriter, r *http.Request) {
 func getNetwork(w http.ResponseWriter, r *http.Request) {
-
 	// set header.
 	// 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)
+	netname := params["networkname"]
+	network, err := GetNetwork(netname)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(network)
+}
 
 
+func GetNetwork(name string) (models.Network, error) {
 	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"]}
+	filter := bson.M{"netid": name}
 	err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
 	err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
-
 	defer cancel()
 	defer cancel()
-
 	if err != nil {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
+		return models.Network{}, err
 	}
 	}
-	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(network)
+	return network, nil
 }
 }
 
 
 func keyUpdate(w http.ResponseWriter, r *http.Request) {
 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
-
-	network, err := functions.GetParentNetwork(params["networkname"])
+	netname := params["networkname"]
+	network, err := KeyUpdate(netname)
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
 	}
 	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(network)
+}
 
 
+func KeyUpdate(netname string) (models.Network, error) {
+	network, err := functions.GetParentNetwork(netname)
+	if err != nil {
+		return models.Network{}, err
+	}
 	network.KeyUpdateTimeStamp = time.Now().Unix()
 	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"]}
+	filter := bson.M{"netid": netname}
 	// prepare update model.
 	// prepare update model.
 	update := bson.D{
 	update := bson.D{
 		{"$set", bson.D{
 		{"$set", bson.D{
@@ -251,18 +253,12 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
 			{"checkininterval", network.DefaultCheckInInterval},
 			{"checkininterval", 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 {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
+		return models.Network{}, err
 	}
 	}
-
-	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(network)
+	return network, nil
 }
 }
 
 
 //Update a network
 //Update a network
@@ -562,8 +558,7 @@ func CreateNetwork(network models.Network) error {
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 
 
 	// insert our network into the network table
 	// insert our network into the network table
-	result, err := collection.InsertOne(ctx, network)
-	fmt.Printf("=========%T, %v\n", result, result)
+	_, err = collection.InsertOne(ctx, network)
 	defer cancel()
 	defer cancel()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -576,188 +571,167 @@ func CreateNetwork(network models.Network) error {
 //TODO: Very little error handling
 //TODO: Very little error handling
 //accesskey is created as a json string inside the Network collection item in mongo
 //accesskey is created as a json string inside the Network collection item in mongo
 func createAccessKey(w http.ResponseWriter, r *http.Request) {
 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 accesskey models.AccessKey
-
 	//start here
 	//start here
 	network, err := functions.GetParentNetwork(params["networkname"])
 	network, err := functions.GetParentNetwork(params["networkname"])
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
 	}
 	}
-
 	err = json.NewDecoder(r.Body).Decode(&accesskey)
 	err = json.NewDecoder(r.Body).Decode(&accesskey)
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 		return
 	}
 	}
+	key, err := CreateAccessKey(accesskey, network)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "badrequest"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(key)
+	//w.Write([]byte(accesskey.AccessString))
+}
 
 
+func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models.AccessKey, error) {
 	if accesskey.Name == "" {
 	if accesskey.Name == "" {
 		accesskey.Name = functions.GenKeyName()
 		accesskey.Name = functions.GenKeyName()
 	}
 	}
 	if accesskey.Value == "" {
 	if accesskey.Value == "" {
 		accesskey.Value = functions.GenKey()
 		accesskey.Value = functions.GenKey()
 	}
 	}
-
 	if accesskey.Uses == 0 {
 	if accesskey.Uses == 0 {
 		accesskey.Uses = 1
 		accesskey.Uses = 1
 	}
 	}
+	for _, key := range network.AccessKeys {
+		if key.Name == accesskey.Name {
+			return models.AccessKey{}, errors.New("Duplicate AccessKey Name")
+		}
+	}
+
 	_, gconf, err := functions.GetGlobalConfig()
 	_, gconf, err := functions.GetGlobalConfig()
 	if err != nil {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
+		//returnErrorResponse(w, r, formatError(err, "internal"))
+		return models.AccessKey{}, err
 	}
 	}
-
 	privAddr := ""
 	privAddr := ""
-	if *network.IsLocal {
-		privAddr = network.LocalRange
+	if network.IsLocal != nil {
+		if *network.IsLocal {
+			privAddr = network.LocalRange
+		}
 	}
 	}
 
 
-	netID := params["networkname"]
+	//netID := params["networkname"]
 	address := gconf.ServerGRPC + gconf.PortGRPC
 	address := gconf.ServerGRPC + gconf.PortGRPC
-
-	accessstringdec := address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
+	accessstringdec := address + "|" + network.NetID + "|" + accesskey.Value + "|" + privAddr
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
-
+	//validate accesskey
+	v := validator.New()
+	err = v.Struct(accesskey)
+	if err != nil {
+		for _, e := range err.(validator.ValidationErrors) {
+			fmt.Println(e)
+		}
+		return models.AccessKey{}, err
+	}
 	network.AccessKeys = append(network.AccessKeys, accesskey)
 	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
 	// Create filter
-	filter := bson.M{"netid": params["networkname"]}
-
+	filter := bson.M{"netid": network.NetID}
 	// Read update model from body request
 	// Read update model from body request
 	fmt.Println("Adding key to " + network.NetID)
 	fmt.Println("Adding key to " + network.NetID)
-
 	// prepare update model.
 	// prepare update model.
 	update := bson.D{
 	update := bson.D{
 		{"$set", bson.D{
 		{"$set", bson.D{
 			{"accesskeys", network.AccessKeys},
 			{"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 {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
+		//returnErrorResponse(w, r, formatError(err, "internal"))
+		return models.AccessKey{}, err
 	}
 	}
-	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(accesskey)
-	//w.Write([]byte(accesskey.AccessString))
+	return accesskey, nil
 }
 }
 
 
 //pretty simple get
 //pretty simple get
 func getAccessKeys(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)
+	network := params["networkname"]
+	keys, err := GetKeys(network)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(keys)
+}
+func GetKeys(net string) ([]models.AccessKey, error) {
 
 
 	var network models.Network
 	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"]}
+	filter := bson.M{"netid": net}
 	err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
 	err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&network)
-
 	defer cancel()
 	defer cancel()
-
 	if err != nil {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
+		return []models.AccessKey{}, err
 	}
 	}
-	keydata, err := json.Marshal(network.AccessKeys)
-
-	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
-	}
-
-	json.Unmarshal(keydata, &keys)
-
-	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(keys)
+	return network.AccessKeys, nil
 }
 }
 
 
 //delete key. Has to do a little funky logic since it's not a collection item
 //delete key. Has to do a little funky logic since it's not a collection item
 func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
 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
 	keyname := params["name"]
 	keyname := params["name"]
-
-	//start here
-	network, err := functions.GetParentNetwork(params["networkname"])
+	netname := params["networkname"]
+	err := DeleteKey(keyname, netname)
 	if err != nil {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
+		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		return
 		return
 	}
 	}
+	w.WriteHeader(http.StatusOK)
+}
+func DeleteKey(keyname, netname string) error {
+	network, err := functions.GetParentNetwork(netname)
+	if err != nil {
+		return err
+	}
 	//basically, turn the list of access keys into the list of access keys before and after the item
 	//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.
 	//have not done any error handling for if there's like...1 item. I think it works? need to test.
 	found := false
 	found := false
-	for i := len(network.AccessKeys) - 1; i >= 0; i-- {
-
-		currentkey := network.AccessKeys[i]
+	var updatedKeys []models.AccessKey
+	for _, currentkey := range network.AccessKeys {
 		if currentkey.Name == keyname {
 		if currentkey.Name == keyname {
-			network.AccessKeys = append(network.AccessKeys[:i],
-				network.AccessKeys[i+1:]...)
 			found = true
 			found = true
+		} else {
+			updatedKeys = append(updatedKeys, currentkey)
 		}
 		}
 	}
 	}
 	if !found {
 	if !found {
-		err = errors.New("key " + keyname + " does not exist")
-		returnErrorResponse(w, r, formatError(err, "badrequest"))
-		return
+		return errors.New("key " + keyname + " does not exist")
 	}
 	}
 
 
 	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
 	// Create filter
-	filter := bson.M{"netid": params["networkname"]}
-
+	filter := bson.M{"netid": netname}
 	// prepare update model.
 	// prepare update model.
 	update := bson.D{
 	update := bson.D{
 		{"$set", bson.D{
 		{"$set", bson.D{
-			{"accesskeys", network.AccessKeys},
+			{"accesskeys", updatedKeys},
 		}},
 		}},
 	}
 	}
-
 	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
-	keydata, err := json.Marshal(network.AccessKeys)
 	if err != nil {
 	if err != nil {
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
+		return err
 	}
 	}
-
-	json.Unmarshal(keydata, &keys)
-
-	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(keys)
+	return nil
 }
 }

+ 179 - 6
controllers/networkHttpController_test.go

@@ -2,6 +2,7 @@ package controller
 
 
 import (
 import (
 	"testing"
 	"testing"
+	"time"
 
 
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
@@ -13,24 +14,195 @@ type NetworkValidationTestCase struct {
 	errMessage string
 	errMessage string
 }
 }
 
 
+func deleteNet() {
+	_, err := GetNetwork("skynet")
+	if err == nil {
+		_, _ = DeleteNetwork("skynet")
+	}
+}
+
+func createNet() {
+	var network models.Network
+	network.NetID = "skynet"
+	network.AddressRange = "10.0.0.1/24"
+	network.DisplayName = "mynetwork"
+	_, err := GetNetwork("skynet")
+	if err != nil {
+		CreateNetwork(network)
+	}
+}
+
 func TestGetNetworks(t *testing.T) {
 func TestGetNetworks(t *testing.T) {
-	//calls functions.ListNetworks --- nothing to be don
+	//calls functions.ListNetworks --- nothing to be done
 }
 }
 func TestCreateNetwork(t *testing.T) {
 func TestCreateNetwork(t *testing.T) {
+	deleteNet()
+	var network models.Network
+	network.NetID = "skynet"
+	network.AddressRange = "10.0.0.1/24"
+	network.DisplayName = "mynetwork"
+	err := CreateNetwork(network)
+	assert.Nil(t, err)
+}
+func TestGetDeleteNetwork(t *testing.T) {
+	createNet()
+	//create nodes
+	t.Run("NetworkwithNodes", func(t *testing.T) {
+	})
+	t.Run("GetExistingNetwork", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, "skynet", network.NetID)
+	})
+	t.Run("DeleteExistingNetwork", func(t *testing.T) {
+		result, err := DeleteNetwork("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, int64(1), result.DeletedCount)
+		t.Log(result.DeletedCount)
+	})
+	t.Run("GetNonExistantNetwork", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.NotNil(t, err)
+		assert.Equal(t, "mongo: no documents in result", err.Error())
+		assert.Equal(t, "", network.NetID)
+	})
+	t.Run("NonExistantNetwork", func(t *testing.T) {
+		result, err := DeleteNetwork("skynet")
+		assert.Nil(t, err)
+		assert.Equal(t, int64(0), result.DeletedCount)
+		t.Log(result.DeletedCount)
+	})
 }
 }
 func TestGetNetwork(t *testing.T) {
 func TestGetNetwork(t *testing.T) {
 }
 }
 func TestUpdateNetwork(t *testing.T) {
 func TestUpdateNetwork(t *testing.T) {
 }
 }
-func TestDeleteNetwork(t *testing.T) {
-}
+
 func TestKeyUpdate(t *testing.T) {
 func TestKeyUpdate(t *testing.T) {
+	createNet()
+	existing, err := GetNetwork("skynet")
+	assert.Nil(t, err)
+	time.Sleep(time.Second * 1)
+	network, err := KeyUpdate("skynet")
+	assert.Nil(t, err)
+	network, err = GetNetwork("skynet")
+	assert.Nil(t, err)
+	assert.Greater(t, network.KeyUpdateTimeStamp, existing.KeyUpdateTimeStamp)
 }
 }
+
 func TestCreateKey(t *testing.T) {
 func TestCreateKey(t *testing.T) {
+	createNet()
+	var accesskey models.AccessKey
+	var network models.Network
+	network.NetID = "skynet"
+	t.Run("InvalidName", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Name = "bad-name"
+		_, err = CreateAccessKey(accesskey, network)
+		assert.NotNil(t, err)
+		assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'alphanum' tag")
+	})
+	t.Run("NameTooLong", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Name = "Thisisareallylongkeynamethatwillfail"
+		_, err = CreateAccessKey(accesskey, network)
+		assert.NotNil(t, err)
+		assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'max' tag")
+	})
+	t.Run("BlankName", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Name = ""
+		key, err := CreateAccessKey(accesskey, network)
+		assert.Nil(t, err)
+		assert.NotEqual(t, "", key.Name)
+	})
+	t.Run("InvalidValue", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Value = "bad-value"
+		_, err = CreateAccessKey(accesskey, network)
+		assert.NotNil(t, err)
+		assert.Contains(t, err.Error(), "Field validation for 'Value' failed on the 'alphanum' tag")
+	})
+	t.Run("BlankValue", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Name = "mykey"
+		accesskey.Value = ""
+		key, err := CreateAccessKey(accesskey, network)
+		assert.Nil(t, err)
+		assert.NotEqual(t, "", key.Value)
+		assert.Equal(t, accesskey.Name, key.Name)
+	})
+	t.Run("ValueTooLong", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Name = "keyname"
+		accesskey.Value = "AccessKeyValuethatistoolong"
+		_, err = CreateAccessKey(accesskey, network)
+		assert.NotNil(t, err)
+		assert.Contains(t, err.Error(), "Field validation for 'Value' failed on the 'max' tag")
+	})
+	t.Run("BlankUses", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Uses = 0
+		accesskey.Value = ""
+		key, err := CreateAccessKey(accesskey, network)
+		assert.Nil(t, err)
+		assert.Equal(t, 1, key.Uses)
+	})
+	t.Run("DuplicateKey", func(t *testing.T) {
+		network, err := GetNetwork("skynet")
+		assert.Nil(t, err)
+		accesskey.Name = "mykey"
+		_, err = CreateAccessKey(accesskey, network)
+		assert.NotNil(t, err)
+		assert.Equal(t, "Duplicate AccessKey Name", err.Error())
+	})
 }
 }
-func TestGetKey(t *testing.T) {
+func TestGetKeys(t *testing.T) {
+	deleteNet()
+	createNet()
+	network, err := GetNetwork("skynet")
+	assert.Nil(t, err)
+	var key models.AccessKey
+	key.Name = "mykey"
+	_, err = CreateAccessKey(key, network)
+	assert.Nil(t, err)
+	t.Run("KeyExists", func(t *testing.T) {
+		keys, err := GetKeys(network.NetID)
+		assert.Nil(t, err)
+		assert.NotEqual(t, models.AccessKey{}, keys)
+	})
+	t.Run("NonExistantKey", func(t *testing.T) {
+		err := DeleteKey("mykey", "skynet")
+		assert.Nil(t, err)
+		keys, err := GetKeys(network.NetID)
+		assert.Nil(t, err)
+		assert.Equal(t, []models.AccessKey(nil), keys)
+	})
 }
 }
 func TestDeleteKey(t *testing.T) {
 func TestDeleteKey(t *testing.T) {
+	createNet()
+	network, err := GetNetwork("skynet")
+	assert.Nil(t, err)
+	var key models.AccessKey
+	key.Name = "mykey"
+	_, err = CreateAccessKey(key, network)
+	assert.Nil(t, err)
+	t.Run("ExistingKey", func(t *testing.T) {
+		err := DeleteKey("mykey", "skynet")
+		assert.Nil(t, err)
+	})
+	t.Run("NonExistantKey", func(t *testing.T) {
+		err := DeleteKey("mykey", "skynet")
+		assert.NotNil(t, err)
+		assert.Equal(t, "key mykey does not exist", err.Error())
+	})
 }
 }
 func TestSecurityCheck(t *testing.T) {
 func TestSecurityCheck(t *testing.T) {
 }
 }
@@ -39,6 +211,7 @@ func TestValidateNetworkUpdate(t *testing.T) {
 func TestValidateNetworkCreate(t *testing.T) {
 func TestValidateNetworkCreate(t *testing.T) {
 	yes := true
 	yes := true
 	no := false
 	no := false
+	deleteNet()
 	//DeleteNetworks
 	//DeleteNetworks
 	cases := []NetworkValidationTestCase{
 	cases := []NetworkValidationTestCase{
 		NetworkValidationTestCase{
 		NetworkValidationTestCase{
@@ -194,10 +367,10 @@ func TestValidateNetworkCreate(t *testing.T) {
 	}
 	}
 	t.Run("DuplicateNetID", func(t *testing.T) {
 	t.Run("DuplicateNetID", func(t *testing.T) {
 		var net1, net2 models.Network
 		var net1, net2 models.Network
-		net1.NetID = "skylink"
+		net1.NetID = "skynet"
 		net1.AddressRange = "10.0.0.1/24"
 		net1.AddressRange = "10.0.0.1/24"
 		net1.DisplayName = "mynetwork"
 		net1.DisplayName = "mynetwork"
-		net2.NetID = "skylink"
+		net2.NetID = "skynet"
 		net2.AddressRange = "10.0.1.1/24"
 		net2.AddressRange = "10.0.1.1/24"
 		net2.IsDualStack = &no
 		net2.IsDualStack = &no
 
 

+ 33 - 34
functions/helpers.go

@@ -445,16 +445,15 @@ func NameInNetworkCharSet(name string) bool {
 
 
 func NameInDNSCharSet(name string) bool {
 func NameInDNSCharSet(name string) bool {
 
 
-        charset := "abcdefghijklmnopqrstuvwxyz1234567890-."
-
-        for _, char := range name {
-                if !strings.Contains(charset, strings.ToLower(string(char))) {
-                        return false
-                }
-        }
-        return true
-}
+	charset := "abcdefghijklmnopqrstuvwxyz1234567890-."
 
 
+	for _, char := range name {
+		if !strings.Contains(charset, strings.ToLower(string(char))) {
+			return false
+		}
+	}
+	return true
+}
 
 
 func NameInNodeCharSet(name string) bool {
 func NameInNodeCharSet(name string) bool {
 
 
@@ -528,35 +527,35 @@ func UniqueAddress(networkName string) (string, error) {
 
 
 func UniqueAddress6(networkName string) (string, error) {
 func UniqueAddress6(networkName string) (string, error) {
 
 
-        var network models.Network
-        network, err := GetParentNetwork(networkName)
+	var network models.Network
+	network, err := GetParentNetwork(networkName)
 	if !*network.IsDualStack {
 	if !*network.IsDualStack {
 		return "", nil
 		return "", nil
 	}
 	}
 
 
 	if err != nil {
 	if err != nil {
-                fmt.Println("UniqueAddress6 encountered  an error")
-                return "666", err
-        }
-
-        offset := true
-        ip, ipnet, err := net.ParseCIDR(network.AddressRange6)
-        if err != nil {
-                fmt.Println("UniqueAddress6 encountered  an error")
-                return "666", err
-        }
-        for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
-                if offset {
-                        offset = false
-                        continue
-                }
-                if IsIPUnique(networkName, ip.String()) {
-                        return ip.String(), err
-                }
-        }
-        //TODO
-        err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
-        return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
+		fmt.Println("UniqueAddress6 encountered  an error")
+		return "666", err
+	}
+
+	offset := true
+	ip, ipnet, err := net.ParseCIDR(network.AddressRange6)
+	if err != nil {
+		fmt.Println("UniqueAddress6 encountered  an error")
+		return "666", err
+	}
+	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); Inc(ip) {
+		if offset {
+			offset = false
+			continue
+		}
+		if IsIPUnique(networkName, ip.String()) {
+			return ip.String(), err
+		}
+	}
+	//TODO
+	err1 := errors.New("ERROR: No unique addresses available. Check network subnet.")
+	return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
 }
 }
 
 
 //pretty simple get
 //pretty simple get
@@ -620,7 +619,7 @@ func GenKeyName() string {
 	for i := range b {
 	for i := range b {
 		b[i] = charset[seededRand.Intn(len(charset))]
 		b[i] = charset[seededRand.Intn(len(charset))]
 	}
 	}
-	return "key-" + string(b)
+	return "key" + string(b)
 }
 }
 
 
 //checks if IP is unique in the address range
 //checks if IP is unique in the address range

+ 20 - 18
models/network.go

@@ -14,24 +14,26 @@ type Network struct {
 	AddressRange string             `json:"addressrange" bson:"addressrange" validate:"required,cidr"`
 	AddressRange string             `json:"addressrange" bson:"addressrange" validate:"required,cidr"`
 	// bug in validator --- required_with does not work with bools  issue#683
 	// bug in validator --- required_with does not work with bools  issue#683
 	//	AddressRange6          string             `json:"addressrange6" bson:"addressrange6" validate:"required_with=isdualstack true,cidrv6"`
 	//	AddressRange6          string             `json:"addressrange6" bson:"addressrange6" validate:"required_with=isdualstack true,cidrv6"`
-	AddressRange6          string      `json:"addressrange6" bson:"addressrange6" validate:"addressrange6_valid"`
-	DisplayName            string      `json:"displayname,omitempty" bson:"displayname,omitempty" validate:"omitempty,alphanum,min=2,max=20,displayname_unique"`
-	NetID                  string      `json:"netid" bson:"netid" validate:"required,alphanum,min=1,max=12,netid_valid"`
-	NodesLastModified      int64       `json:"nodeslastmodified" bson:"nodeslastmodified"`
-	NetworkLastModified    int64       `json:"networklastmodified" bson:"networklastmodified"`
-	DefaultInterface       string      `json:"defaultinterface" bson:"defaultinterface"`
-	DefaultListenPort      int32       `json:"defaultlistenport,omitempty" bson:"defaultlistenport,omitempty" validate:"omitempty,min=1024,max=65535"`
-	DefaultPostUp          string      `json:"defaultpostup" bson:"defaultpostup"`
-	DefaultPostDown        string      `json:"defaultpostdown" bson:"defaultpostdown"`
-	KeyUpdateTimeStamp     int64       `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
-	DefaultKeepalive       int32       `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"`
-	DefaultSaveConfig      *bool       `json:"defaultsaveconfig" bson:"defaultsaveconfig"`
-	AccessKeys             []AccessKey `json:"accesskeys" bson:"accesskeys"`
-	AllowManualSignUp      *bool       `json:"allowmanualsignup" bson:"allowmanualsignup"`
-	IsLocal                *bool       `json:"islocal" bson:"islocal"`
-	IsDualStack            *bool       `json:"isdualstack" bson:"isdualstack"`
-	LocalRange             string      `json:"localrange" bson:"localrange" validate:"omitempty,cidr"`
-	DefaultCheckInInterval int32       `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"`
+	AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"addressrange6_valid"`
+	//can't have min=1 with omitempty
+	DisplayName         string      `json:"displayname,omitempty" bson:"displayname,omitempty" validate:"omitempty,alphanum,min=2,max=20,displayname_unique"`
+	NetID               string      `json:"netid" bson:"netid" validate:"required,alphanum,min=1,max=12,netid_valid"`
+	NodesLastModified   int64       `json:"nodeslastmodified" bson:"nodeslastmodified"`
+	NetworkLastModified int64       `json:"networklastmodified" bson:"networklastmodified"`
+	DefaultInterface    string      `json:"defaultinterface" bson:"defaultinterface"`
+	DefaultListenPort   int32       `json:"defaultlistenport,omitempty" bson:"defaultlistenport,omitempty" validate:"omitempty,min=1024,max=65535"`
+	DefaultPostUp       string      `json:"defaultpostup" bson:"defaultpostup"`
+	DefaultPostDown     string      `json:"defaultpostdown" bson:"defaultpostdown"`
+	KeyUpdateTimeStamp  int64       `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
+	DefaultKeepalive    int32       `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"`
+	DefaultSaveConfig   *bool       `json:"defaultsaveconfig" bson:"defaultsaveconfig"`
+	AccessKeys          []AccessKey `json:"accesskeys" bson:"accesskeys"`
+	AllowManualSignUp   *bool       `json:"allowmanualsignup" bson:"allowmanualsignup"`
+	IsLocal             *bool       `json:"islocal" bson:"islocal"`
+	IsDualStack         *bool       `json:"isdualstack" bson:"isdualstack"`
+	LocalRange          string      `json:"localrange" bson:"localrange" validate:"omitempty,cidr"`
+	//can't have min=1 with omitempty
+	DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"`
 }
 }
 
 
 //TODO:
 //TODO:

+ 2 - 2
models/structs.go

@@ -62,8 +62,8 @@ type SuccessResponse struct {
 }
 }
 
 
 type AccessKey struct {
 type AccessKey struct {
-	Name         string `json:"name" bson:"name"`
-	Value        string `json:"value" bson:"value"`
+	Name         string `json:"name" bson:"name" validate:"omitempty,alphanum,max=20"`
+	Value        string `json:"value" bson:"value" validate:"omitempty,alphanum,max=16"`
 	AccessString string `json:"accessstring" bson:"accessstring"`
 	AccessString string `json:"accessstring" bson:"accessstring"`
 	Uses         int    `json:"uses" bson:"uses"`
 	Uses         int    `json:"uses" bson:"uses"`
 }
 }

+ 0 - 1
test/api_test.go

@@ -236,7 +236,6 @@ func createNode(t *testing.T) {
 	node.Name = "myNode"
 	node.Name = "myNode"
 	node.PublicKey = "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34="
 	node.PublicKey = "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34="
 	node.Password = "tobedetermined"
 	node.Password = "tobedetermined"
-	node.LocalAddress = "192.168.0.1"
 	node.Endpoint = "10.100.100.4"
 	node.Endpoint = "10.100.100.4"
 	response, err := api(t, node, http.MethodPost, "http://localhost:8081:/api/nodes/skynet", "secretkey")
 	response, err := api(t, node, http.MethodPost, "http://localhost:8081:/api/nodes/skynet", "secretkey")
 	assert.Nil(t, err, err)
 	assert.Nil(t, err, err)

+ 11 - 16
test/network_test.go

@@ -141,13 +141,13 @@ func TestDeleteNetwork(t *testing.T) {
 		setup(t)
 		setup(t)
 		response, err := api(t, "", http.MethodDelete, baseURL+"/api/networks/skynet", "secretkey")
 		response, err := api(t, "", http.MethodDelete, baseURL+"/api/networks/skynet", "secretkey")
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
-		assert.Equal(t, http.StatusForbidden, response.StatusCode)
+		assert.Equal(t, http.StatusBadRequest, response.StatusCode)
 		defer response.Body.Close()
 		defer response.Body.Close()
 		var message models.ErrorResponse
 		var message models.ErrorResponse
 		err = json.NewDecoder(response.Body).Decode(&message)
 		err = json.NewDecoder(response.Body).Decode(&message)
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
 		assert.Contains(t, message.Message, "Node check failed")
 		assert.Contains(t, message.Message, "Node check failed")
-		assert.Equal(t, http.StatusForbidden, message.Code)
+		assert.Equal(t, http.StatusBadRequest, message.Code)
 	})
 	})
 	t.Run("ValidKey", func(t *testing.T) {
 	t.Run("ValidKey", func(t *testing.T) {
 		type Message struct {
 		type Message struct {
@@ -202,11 +202,15 @@ func TestCreateKey(t *testing.T) {
 		assert.Equal(t, 1, returnedkey.Uses)
 		assert.Equal(t, 1, returnedkey.Uses)
 	})
 	})
 	t.Run("DuplicateAccessKey", func(t *testing.T) {
 	t.Run("DuplicateAccessKey", func(t *testing.T) {
-		//this is allowed I think it should fail fail
 		response, err := api(t, key, http.MethodPost, baseURL+"/api/networks/skynet/keys", "secretkey")
 		response, err := api(t, key, http.MethodPost, baseURL+"/api/networks/skynet/keys", "secretkey")
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
-		assert.Equal(t, http.StatusOK, response.StatusCode)
-		deleteKey(t, key.Name, "skynet")
+		assert.Equal(t, http.StatusBadRequest, response.StatusCode)
+		defer response.Body.Close()
+		var message models.ErrorResponse
+		err = json.NewDecoder(response.Body).Decode(&message)
+		assert.Nil(t, err)
+		assert.Equal(t, http.StatusBadRequest, message.Code)
+		assert.Equal(t, "Duplicate AccessKey Name", message.Message)
 	})
 	})
 
 
 	t.Run("InvalidToken", func(t *testing.T) {
 	t.Run("InvalidToken", func(t *testing.T) {
@@ -239,18 +243,9 @@ func TestDeleteKey(t *testing.T) {
 	//ensure key exists
 	//ensure key exists
 	createKey(t)
 	createKey(t)
 	t.Run("KeyValid", func(t *testing.T) {
 	t.Run("KeyValid", func(t *testing.T) {
-		//fails -- deletecount not returned
 		response, err := api(t, "", http.MethodDelete, baseURL+"/api/networks/skynet/keys/skynet", "secretkey")
 		response, err := api(t, "", http.MethodDelete, baseURL+"/api/networks/skynet/keys/skynet", "secretkey")
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
-		defer response.Body.Close()
-		//var message mongo.DeleteResult
-		var messages []models.AccessKey
-		err = json.NewDecoder(response.Body).Decode(&messages)
-		assert.Nil(t, err, err)
 		assert.Equal(t, http.StatusOK, response.StatusCode)
 		assert.Equal(t, http.StatusOK, response.StatusCode)
-		for _, message := range messages {
-			assert.Equal(t, "skynet", message.Name)
-		}
 	})
 	})
 	t.Run("InValidKey", func(t *testing.T) {
 	t.Run("InValidKey", func(t *testing.T) {
 		response, err := api(t, "", http.MethodDelete, baseURL+"/api/networks/skynet/keys/badkey", "secretkey")
 		response, err := api(t, "", http.MethodDelete, baseURL+"/api/networks/skynet/keys/badkey", "secretkey")
@@ -515,7 +510,7 @@ func TestUpdateNetwork(t *testing.T) {
 	t.Run("UpdateKeepAliveTooBig", func(t *testing.T) {
 	t.Run("UpdateKeepAliveTooBig", func(t *testing.T) {
 		//does not fails ----- value gets updated.
 		//does not fails ----- value gets updated.
 		// ----- needs fixing -----
 		// ----- needs fixing -----
-		t.Skip()
+		//t.Skip()
 		type Network struct {
 		type Network struct {
 			DefaultKeepAlive int32
 			DefaultKeepAlive int32
 		}
 		}
@@ -527,7 +522,7 @@ func TestUpdateNetwork(t *testing.T) {
 		err = json.NewDecoder(response.Body).Decode(&message)
 		err = json.NewDecoder(response.Body).Decode(&message)
 		assert.Nil(t, err, err)
 		assert.Nil(t, err, err)
 		assert.Equal(t, http.StatusBadRequest, message.Code)
 		assert.Equal(t, http.StatusBadRequest, message.Code)
-		assert.Contains(t, message.Message, "Field validation for 'DefaultKeepAlive' failed")
+		assert.Contains(t, message.Message, "Field validation for 'DefaultKeepalive' failed on the 'max' tag")
 		assert.Equal(t, http.StatusBadRequest, response.StatusCode)
 		assert.Equal(t, http.StatusBadRequest, response.StatusCode)
 	})
 	})
 	t.Run("UpdateSaveConfig", func(t *testing.T) {
 	t.Run("UpdateSaveConfig", func(t *testing.T) {